carray 3.0.3 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +469 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +14 -26
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +231 -153
- data/ext/ca_compare.c +9 -20
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1240 -2000
- data/ext/ca_kernel_iterator.h +502 -519
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +152 -45
- data/ext/ca_obj_bincmp.c +25 -21
- data/ext/ca_obj_binop.c +16 -26
- data/ext/ca_obj_bitarray.c +8 -3
- data/ext/ca_obj_bitfield.c +63 -49
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +7 -7
- data/ext/ca_obj_const_string.c +188 -22
- data/ext/ca_obj_face.c +280 -58
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +30 -8
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +455 -134
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +113 -67
- data/ext/ca_obj_object.c +210 -52
- data/ext/ca_obj_record.c +15 -7
- data/ext/ca_obj_reduce.c +17 -8
- data/ext/ca_obj_refer.c +42 -35
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +31 -10
- data/ext/ca_obj_select.c +48 -14
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +41 -7
- data/ext/ca_obj_stack.c +180 -34
- data/ext/ca_obj_stride.c +190 -134
- data/ext/ca_obj_string.c +80 -4
- data/ext/ca_obj_tile.c +32 -11
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +13 -7
- data/ext/ca_obj_triop.c +26 -32
- data/ext/ca_obj_window.c +267 -74
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +214 -75
- data/ext/carray_access.c +200 -99
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +113 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +375 -96
- data/ext/carray_cast_func.rb +90 -20
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +18 -9
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +150 -55
- data/ext/carray_count.c +56 -20
- data/ext/carray_element.c +81 -33
- data/ext/carray_factorize.c +138 -84
- data/ext/carray_generate.c +199 -52
- data/ext/carray_histogram.c +63 -18
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +348 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10897 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +220 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +337 -94
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +129 -52
- data/ext/carray_order.c +604 -77
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +85 -31
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +87 -45
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +123 -37
- data/ext/carray_sort.c +259 -51
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +54 -61
- data/ext/carray_test.c +26 -5
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +309 -66
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +403 -350
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +139 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +105 -17
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +195 -59
- data/lib/carray/categorical_iterator.rb +132 -29
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +24 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +9 -1
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +48 -3
- data/lib/carray/frame/column_verbs.rb +71 -0
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +252 -28
- data/lib/carray/frame/group.rb +603 -101
- data/lib/carray/frame/io.rb +117 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +42 -6
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +217 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +61 -37
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +323 -88
- data/lib/carray/serialize.rb +45 -14
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +113 -5
- data/lib/carray/string_operation_extension.rb +21 -6
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +24 -11
- data/lib/carray/time.rb +819 -158
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +3 -6
- data/yard-stubs/carray_cast.rb +12 -0
- data/yard-stubs/carray_conversion.rb +7 -2
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +17 -10
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +32 -3
- data/yard-stubs/carray_math.rb +41 -5
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +129 -22
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +17 -10
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/carray_access.c
CHANGED
|
@@ -76,7 +76,7 @@ rb_ca_fetch_index (VALUE self, ca_size_t *idx)
|
|
|
76
76
|
volatile VALUE holder;
|
|
77
77
|
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
78
78
|
ca_fetch_index(ca, idx, v);
|
|
79
|
-
out =
|
|
79
|
+
out = rb_ca_ptr2obj_storage(self, v);
|
|
80
80
|
ALLOCV_END(holder);
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -94,7 +94,7 @@ rb_ca_fetch_index (VALUE self, ca_size_t *idx)
|
|
|
94
94
|
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(out, self, ca);
|
|
95
95
|
|
|
96
96
|
/* Boolean scalar access yields true/false, not Integer 0/1. Bulk paths
|
|
97
|
-
(
|
|
97
|
+
(cast / serialize) keep 0/1. Gate on the raw
|
|
98
98
|
INT2FIX(0/1) so a boolean-storage Face that decoded to its own object is
|
|
99
99
|
left untouched; note INT2FIX(0) is truthy in Ruby, so map by value, not
|
|
100
100
|
by RTEST. */
|
|
@@ -158,7 +158,7 @@ rb_ca_fetch_addr (VALUE self, ca_size_t addr)
|
|
|
158
158
|
volatile VALUE holder;
|
|
159
159
|
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
160
160
|
ca_fetch_addr(ca, addr, v);
|
|
161
|
-
out =
|
|
161
|
+
out = rb_ca_ptr2obj_storage(self, v);
|
|
162
162
|
ALLOCV_END(holder);
|
|
163
163
|
}
|
|
164
164
|
|
|
@@ -193,6 +193,14 @@ rb_ca_fill (VALUE self, VALUE rval)
|
|
|
193
193
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
194
194
|
|
|
195
195
|
if ( ca_is_empty(ca) ) {
|
|
196
|
+
/* No cell to fill, but a value no cell could hold is refused, as an
|
|
197
|
+
assignment to the empty array refuses it. */
|
|
198
|
+
if ( rval != CA_UNDEF && ca->bytes > 0 ) {
|
|
199
|
+
volatile VALUE holder;
|
|
200
|
+
char *fval = ALLOCV_N(char, holder, ca->bytes);
|
|
201
|
+
rb_ca_obj2ptr(self, rval, fval);
|
|
202
|
+
ALLOCV_END(holder);
|
|
203
|
+
}
|
|
196
204
|
return self; /* empty = no-op fill; return self for chaining */
|
|
197
205
|
}
|
|
198
206
|
|
|
@@ -229,9 +237,7 @@ static void
|
|
|
229
237
|
ary_guess_shape (VALUE ary, int level, int *max_level, ca_size_t *dim)
|
|
230
238
|
{
|
|
231
239
|
volatile VALUE ary0;
|
|
232
|
-
|
|
233
|
-
rb_raise(rb_eArgError, "too deep level array for conversion to carray");
|
|
234
|
-
}
|
|
240
|
+
ca_check_rank_fits(level + 1, NULL);
|
|
235
241
|
|
|
236
242
|
if ( TYPE(ary) == T_ARRAY ) {
|
|
237
243
|
if ( RARRAY_LEN(ary) == 0 && level == 0 ) {
|
|
@@ -476,26 +482,6 @@ ca_id_expression_evaluator (void)
|
|
|
476
482
|
return id;
|
|
477
483
|
}
|
|
478
484
|
|
|
479
|
-
/* `a[:sym, args] = v` computes the index by calling Ruby with self held
|
|
480
|
-
attached for the reads, then stores through it. */
|
|
481
|
-
|
|
482
|
-
typedef struct {
|
|
483
|
-
VALUE self;
|
|
484
|
-
VALUE dest; /* what is stored into: self, or a Face's storage */
|
|
485
|
-
ID mid;
|
|
486
|
-
int argc;
|
|
487
|
-
VALUE *argv;
|
|
488
|
-
VALUE rval;
|
|
489
|
-
} ca_store_method_call_ctx_t;
|
|
490
|
-
|
|
491
|
-
static VALUE
|
|
492
|
-
ca_store_method_call_body (VALUE arg)
|
|
493
|
-
{
|
|
494
|
-
ca_store_method_call_ctx_t *c = (ca_store_method_call_ctx_t *) arg;
|
|
495
|
-
volatile VALUE idx = rb_funcallv_public(c->self, c->mid, c->argc, c->argv);
|
|
496
|
-
return rb_ca_store(c->dest, idx, c->rval);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
485
|
/* The casting stores below convert into the destination inside a window,
|
|
500
486
|
and a conversion from Ruby objects can raise part way. Such a window
|
|
501
487
|
attaches rather than allocates: the cells converted before the raise
|
|
@@ -586,6 +572,10 @@ ca_store_all_list_body (VALUE arg)
|
|
|
586
572
|
(boolean8_t*)ca->mask->ptr);
|
|
587
573
|
}
|
|
588
574
|
else {
|
|
575
|
+
/* Every cell gets a value, so none stays masked. */
|
|
576
|
+
if ( ca->mask ) {
|
|
577
|
+
memset(ca->mask->ptr, 0, ca->elements);
|
|
578
|
+
}
|
|
589
579
|
ca_cast_block(ca->elements, c->ico, (VALUE *)RARRAY_CONST_PTR(list), cast_target, ca->ptr);
|
|
590
580
|
}
|
|
591
581
|
return Qnil;
|
|
@@ -654,6 +644,38 @@ ca_face_source_for_store (VALUE self, CArray *ca, VALUE rval)
|
|
|
654
644
|
return rb_funcall(rval, rb_intern("to_type"), 1, INT2NUM(CA_OBJECT));
|
|
655
645
|
}
|
|
656
646
|
|
|
647
|
+
/* A store into no cells writes nothing, but the value is checked as it
|
|
648
|
+
would be for any cells: the same statement does not raise or pass
|
|
649
|
+
depending on how many cells the index picks. */
|
|
650
|
+
static void
|
|
651
|
+
ca_store_all_check_empty (VALUE self, VALUE rval)
|
|
652
|
+
{
|
|
653
|
+
CArray *ca;
|
|
654
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
655
|
+
if ( rb_obj_is_cscalar(rval) ) {
|
|
656
|
+
rval = rb_ca_fetch_addr(rval, 0);
|
|
657
|
+
}
|
|
658
|
+
rval = ca_face_source_for_store(self, ca, rval);
|
|
659
|
+
if ( ! rb_obj_is_carray(rval) && TYPE(rval) != T_ARRAY &&
|
|
660
|
+
rb_respond_to(rval, id_to_ca) ) {
|
|
661
|
+
rval = rb_funcall(rval, id_to_ca, 0);
|
|
662
|
+
}
|
|
663
|
+
if ( rb_obj_is_carray(rval) ) {
|
|
664
|
+
ca_broadcast_to_destination(self, (volatile VALUE *) &rval);
|
|
665
|
+
}
|
|
666
|
+
else if ( TYPE(rval) == T_ARRAY ) {
|
|
667
|
+
if ( NIL_P(rb_ary_flatten_for_elements(rval, ca->elements, ca)) ) {
|
|
668
|
+
rb_raise(rb_eArgError, "failed to guess data size of given array");
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
else if ( rval != CA_UNDEF ) {
|
|
672
|
+
volatile VALUE holder;
|
|
673
|
+
char *fval = ALLOCV_N(char, holder, ca->bytes);
|
|
674
|
+
rb_ca_obj2ptr(self, rval, fval);
|
|
675
|
+
ALLOCV_END(holder);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
657
679
|
VALUE
|
|
658
680
|
rb_ca_store_all (VALUE self, VALUE rval)
|
|
659
681
|
{
|
|
@@ -661,10 +683,14 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
661
683
|
|
|
662
684
|
rb_ca_modify(self);
|
|
663
685
|
|
|
664
|
-
if ( self == rval
|
|
686
|
+
if ( self == rval ) {
|
|
687
|
+
return rval;
|
|
688
|
+
}
|
|
689
|
+
if ( rb_ca_is_empty(self) ) {
|
|
690
|
+
ca_store_all_check_empty(self, rval);
|
|
665
691
|
return rval;
|
|
666
692
|
}
|
|
667
|
-
|
|
693
|
+
|
|
668
694
|
if ( rb_obj_is_cscalar(rval) ) {
|
|
669
695
|
rval = rb_ca_fetch_addr(rval, 0);
|
|
670
696
|
}
|
|
@@ -689,6 +715,7 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
689
715
|
&& ca->data_type == cv->data_type
|
|
690
716
|
&& ca->ndim == cv->ndim
|
|
691
717
|
&& ca->elements == cv->elements
|
|
718
|
+
&& ca_in_main_ractor()
|
|
692
719
|
&& RTEST(rb_attr_get(rb_cCArray, ca_id_expression_evaluator())) ) {
|
|
693
720
|
int8_t k;
|
|
694
721
|
int same = 1;
|
|
@@ -865,9 +892,9 @@ rb_ca_index_restruct_block (int16_t *ndimp, ca_size_t *shrink, ca_size_t *dim,
|
|
|
865
892
|
|
|
866
893
|
offset = 0;
|
|
867
894
|
|
|
868
|
-
if ( idx[0] == -1 ) {
|
|
869
|
-
j =
|
|
870
|
-
|
|
895
|
+
if ( ndim0 > 0 && idx[0] == -1 ) {
|
|
896
|
+
/* j = the number of leading axes collapsed by a scalar index */
|
|
897
|
+
for (j=1; j<ndim0 && idx[j] == -1; j++) {
|
|
871
898
|
;
|
|
872
899
|
}
|
|
873
900
|
|
|
@@ -1022,7 +1049,9 @@ extern VALUE rb_ca_remap_new (VALUE cary, VALUE rmapper);
|
|
|
1022
1049
|
(b) Otherwise -> normalize chain (a.flatten[mapper.flatten]
|
|
1023
1050
|
.reshape). A 1-D mapper is already routed to CAGrid upstream.
|
|
1024
1051
|
|
|
1025
|
-
|
|
1052
|
+
A masked mapper cell selects nothing: the cell keeps its position and
|
|
1053
|
+
reads as masked (a CAGrid hole); the same-shape fast path is left to a
|
|
1054
|
+
mapper with no masked cell. */
|
|
1026
1055
|
static VALUE
|
|
1027
1056
|
rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
1028
1057
|
{
|
|
@@ -1034,15 +1063,24 @@ rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
|
1034
1063
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1035
1064
|
TypedData_Get_Struct(rmapper, CArray, &carray_data_type, cm);
|
|
1036
1065
|
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1066
|
+
/* (a) same-shape fast path: ndim + per-axis dim + CA_SIZE data_type.
|
|
1067
|
+
The view reads the index array it is given, so it is given a copy: the
|
|
1068
|
+
indices are the ones the caller passed at this call, as every other
|
|
1069
|
+
route reads them, and each is checked against self now, so an index out
|
|
1070
|
+
of range raises here and not at the first read. */
|
|
1042
1071
|
if ( cm->data_type == CA_SIZE
|
|
1072
|
+
&& ! ca_is_any_masked(cm)
|
|
1043
1073
|
&& cm->ndim == ca->ndim
|
|
1044
1074
|
&& memcmp(cm->dim, ca->dim, ca->ndim * sizeof(ca_size_t)) == 0 ) {
|
|
1045
|
-
|
|
1075
|
+
volatile VALUE snapshot = rb_ca_copy(rmapper);
|
|
1076
|
+
CArray *cs;
|
|
1077
|
+
ca_size_t k, *p;
|
|
1078
|
+
TypedData_Get_Struct(snapshot, CArray, &carray_data_type, cs);
|
|
1079
|
+
p = (ca_size_t *) cs->ptr;
|
|
1080
|
+
for (k = 0; k < cs->elements; k++) {
|
|
1081
|
+
CA_CHECK_INDEX(p[k], ca->elements);
|
|
1082
|
+
}
|
|
1083
|
+
return rb_ca_remap_new(self, snapshot);
|
|
1046
1084
|
}
|
|
1047
1085
|
|
|
1048
1086
|
/* (b) Normalize chain fallback. A Face is flattened through its storage
|
|
@@ -1070,10 +1108,9 @@ rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
|
1070
1108
|
return result;
|
|
1071
1109
|
}
|
|
1072
1110
|
|
|
1073
|
-
/*
|
|
1074
|
-
the
|
|
1075
|
-
|
|
1076
|
-
class of the returned VALUE is CARefer (chain outermost), not CAMapping. */
|
|
1111
|
+
/* rb_ca_mapping_new and rb_ca_mapping index cary by a mapper array through
|
|
1112
|
+
rb_ca_fancy_index_chain: the result is a CAGrid over the flattened array,
|
|
1113
|
+
reshaped (CARefer, the outermost layer) to the mapper's shape. */
|
|
1077
1114
|
|
|
1078
1115
|
VALUE
|
|
1079
1116
|
rb_ca_mapping_new (VALUE cary, CArray *mapper)
|
|
@@ -1099,6 +1136,18 @@ rb_ca_mapping (int argc, VALUE *argv, VALUE self)
|
|
|
1099
1136
|
the optimal view class (CAStride for stride bases, CARefer for fancy
|
|
1100
1137
|
bases). */
|
|
1101
1138
|
|
|
1139
|
+
/* a[:name, args] calls a method of the array, and its arguments are the
|
|
1140
|
+
method's, whatever they are: the scans for :_, :> and group indices
|
|
1141
|
+
below look at index keys only. */
|
|
1142
|
+
static int
|
|
1143
|
+
ca_argv_is_method_call (int argc, VALUE *argv)
|
|
1144
|
+
{
|
|
1145
|
+
const char *name;
|
|
1146
|
+
if ( argc < 1 || ! SYMBOL_P(argv[0]) ) return 0;
|
|
1147
|
+
name = rb_id2name(SYM2ID(argv[0]));
|
|
1148
|
+
return ( name != NULL && strlen(name) > 1 );
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1102
1151
|
static int
|
|
1103
1152
|
ca_argv_has_newaxis (int argc, VALUE *argv)
|
|
1104
1153
|
{
|
|
@@ -1140,6 +1189,10 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1140
1189
|
|
|
1141
1190
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1142
1191
|
|
|
1192
|
+
if ( ca_argv_is_method_call(argc, argv) ) {
|
|
1193
|
+
goto classify;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1143
1196
|
/* newaxis (:_) interception (cheap pointer scan; zero overhead beyond
|
|
1144
1197
|
the loop when no :_ is present). */
|
|
1145
1198
|
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
@@ -1163,6 +1216,7 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1163
1216
|
return rb_ca_fetch_group(argc, argv, self);
|
|
1164
1217
|
}
|
|
1165
1218
|
|
|
1219
|
+
classify:
|
|
1166
1220
|
info.range_check = 1;
|
|
1167
1221
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1168
1222
|
|
|
@@ -1244,11 +1298,6 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1244
1298
|
}
|
|
1245
1299
|
break;
|
|
1246
1300
|
}
|
|
1247
|
-
case CA_REG_ATTRIBUTE: {
|
|
1248
|
-
obj = rb_funcall(self, rb_intern("attribute"), 0);
|
|
1249
|
-
obj = rb_hash_aref(obj, info.symbol);
|
|
1250
|
-
break;
|
|
1251
|
-
}
|
|
1252
1301
|
default:
|
|
1253
1302
|
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1254
1303
|
}
|
|
@@ -1292,7 +1341,7 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1292
1341
|
nunder++;
|
|
1293
1342
|
continue;
|
|
1294
1343
|
}
|
|
1295
|
-
if (
|
|
1344
|
+
if ( ca_index_key_is_scalar(a) ) {
|
|
1296
1345
|
nscalar++;
|
|
1297
1346
|
}
|
|
1298
1347
|
if ( a == sym_gt || a == sym_perc
|
|
@@ -1301,7 +1350,7 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1301
1350
|
"newaxis (:_) cannot be combined with :>, :%%, "
|
|
1302
1351
|
"or rubber dim (false / :~)");
|
|
1303
1352
|
}
|
|
1304
|
-
if ( nclean >= CA_RANK_MAX ) {
|
|
1353
|
+
if ( nclean >= CA_RANK_MAX ) { /* rank-check: a count of indices */
|
|
1305
1354
|
rb_raise(rb_eIndexError, "too many indices");
|
|
1306
1355
|
}
|
|
1307
1356
|
clean[nclean++] = a;
|
|
@@ -1324,6 +1373,7 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1324
1373
|
element, which is what the shape rules then hold it to. */
|
|
1325
1374
|
if ( nscalar == nclean ) {
|
|
1326
1375
|
VALUE blocks[CA_RANK_MAX];
|
|
1376
|
+
ca_check_rank_fits(nunder, NULL); /* the result has the :_ axes only */
|
|
1327
1377
|
for (i = 0; i < nclean; i++) {
|
|
1328
1378
|
blocks[i] = rb_assoc_new(clean[i], INT2FIX(1));
|
|
1329
1379
|
}
|
|
@@ -1338,22 +1388,45 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1338
1388
|
|
|
1339
1389
|
TypedData_Get_Struct(base, CArray, &carray_data_type, cb);
|
|
1340
1390
|
|
|
1391
|
+
/* The result has the base's axes and one for each :_, before any is
|
|
1392
|
+
written into final_dims. */
|
|
1393
|
+
ca_check_rank_fits((long) nunder + cb->ndim, NULL);
|
|
1394
|
+
|
|
1341
1395
|
/* Reconstruct final shape: walk original argv. :_ -> size-1, scalar
|
|
1342
|
-
(Integer) -> dropped (skip), else -> base.dim[cursor].
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1396
|
+
(Integer) -> dropped (skip), else -> base.dim[cursor]. A key gives one
|
|
1397
|
+
axis, except an integer CArray read alone (a mapping), which gives as
|
|
1398
|
+
many as it has: the axes the base has beyond one per key are its. */
|
|
1399
|
+
{
|
|
1400
|
+
int nkeys = 0, extra, ncarray = 0;
|
|
1401
|
+
for (i = 0; i < nclean; i++) {
|
|
1402
|
+
if ( ! ca_index_key_is_scalar(clean[i]) ) {
|
|
1403
|
+
nkeys++;
|
|
1404
|
+
if ( rb_obj_is_carray(clean[i]) ) ncarray++;
|
|
1405
|
+
}
|
|
1351
1406
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1407
|
+
extra = cb->ndim - nkeys;
|
|
1408
|
+
base_cursor = ( extra != 0 && ncarray != 1 ) ? -1 : 0;
|
|
1409
|
+
for (i = 0; i < argc && base_cursor >= 0; i++) {
|
|
1410
|
+
VALUE a = argv[i];
|
|
1411
|
+
int take = 1, t;
|
|
1412
|
+
if ( a == sym_under ) {
|
|
1413
|
+
final_dims[nfinal++] = 1;
|
|
1414
|
+
continue;
|
|
1415
|
+
}
|
|
1416
|
+
if ( ca_index_key_is_scalar(a) ) {
|
|
1417
|
+
/* scalar index -> axis dropped in base; contributes no output axis */
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
if ( rb_obj_is_carray(a) ) {
|
|
1421
|
+
take += extra;
|
|
1422
|
+
}
|
|
1423
|
+
for (t = 0; t < take; t++) {
|
|
1424
|
+
if ( base_cursor >= cb->ndim || nfinal >= CA_RANK_MAX ) { /* rank-check: a count of indices */
|
|
1425
|
+
base_cursor = -1;
|
|
1426
|
+
break;
|
|
1427
|
+
}
|
|
1428
|
+
final_dims[nfinal++] = cb->dim[base_cursor++];
|
|
1355
1429
|
}
|
|
1356
|
-
final_dims[nfinal++] = cb->dim[base_cursor++];
|
|
1357
1430
|
}
|
|
1358
1431
|
}
|
|
1359
1432
|
if ( base_cursor != cb->ndim ) {
|
|
@@ -1397,7 +1470,7 @@ rb_ca_slab_iter_new (VALUE self, CAIndexInfo *info)
|
|
|
1397
1470
|
align with the post-expansion ndim, replace :> with nil (full axis),
|
|
1398
1471
|
promote Integer to length-1 Range so the base view preserves ndim,
|
|
1399
1472
|
recurse through the regular indexer dispatch to build the base
|
|
1400
|
-
reference (CABlock / CASelectAxis / CAGrid /
|
|
1473
|
+
reference (CABlock / CASelectAxis / CAGrid / ...), then
|
|
1401
1474
|
wrap in CASlabIterator with the recorded slab_axes positions. */
|
|
1402
1475
|
static VALUE
|
|
1403
1476
|
rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
@@ -1451,7 +1524,7 @@ rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
|
1451
1524
|
eargv = expanded;
|
|
1452
1525
|
}
|
|
1453
1526
|
|
|
1454
|
-
if ( eargc > CA_RANK_MAX ) {
|
|
1527
|
+
if ( eargc > CA_RANK_MAX ) { /* rank-check: a count of indices */
|
|
1455
1528
|
rb_raise(rb_eIndexError, "too many indices");
|
|
1456
1529
|
}
|
|
1457
1530
|
|
|
@@ -1461,7 +1534,7 @@ rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
|
1461
1534
|
rb_ary_push(slab_axes, INT2NUM(i));
|
|
1462
1535
|
clean[i] = Qnil;
|
|
1463
1536
|
}
|
|
1464
|
-
else if (
|
|
1537
|
+
else if ( ca_index_key_is_scalar(a) ) {
|
|
1465
1538
|
/* Promote Integer to length-1 Range so the recursed view keeps
|
|
1466
1539
|
the axis (matches the existing :> dispatcher semantics where
|
|
1467
1540
|
scalars become length-1 BLOCKs via finalize_reg). */
|
|
@@ -1545,11 +1618,6 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1545
1618
|
}
|
|
1546
1619
|
break;
|
|
1547
1620
|
}
|
|
1548
|
-
case CA_REG_ATTRIBUTE: {
|
|
1549
|
-
obj = rb_funcall(self, rb_intern("attribute"), 0);
|
|
1550
|
-
obj = rb_hash_aref(obj, info.symbol);
|
|
1551
|
-
break;
|
|
1552
|
-
}
|
|
1553
1621
|
default:
|
|
1554
1622
|
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1555
1623
|
}
|
|
@@ -1592,6 +1660,23 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1592
1660
|
return ca_face_convert_store_rval(self, ca,
|
|
1593
1661
|
rb_funcall(val, rb_intern("to_a"), 0));
|
|
1594
1662
|
}
|
|
1663
|
+
/* A CAString takes Strings. A text Face goes in as the CAString its
|
|
1664
|
+
to_string gives, and an object array as itself wrapped in a CAString,
|
|
1665
|
+
which checks every cell that is not masked; either keeps its shape,
|
|
1666
|
+
so it meets the shape rule of a store as an object array would. Any
|
|
1667
|
+
other array goes in as its values, each through the write hook. */
|
|
1668
|
+
if ( ca->obj_type == CA_OBJ_STRING && cval->obj_type != CA_OBJ_STRING ) {
|
|
1669
|
+
if ( ca_is_face(cval) && rb_respond_to(val, rb_intern("to_string")) ) {
|
|
1670
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1671
|
+
rb_funcall(val, rb_intern("to_string"), 0));
|
|
1672
|
+
}
|
|
1673
|
+
if ( ! ca_is_face(cval) && cval->data_type == CA_OBJECT ) {
|
|
1674
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1675
|
+
rb_funcall(rb_obj_class(self), rb_intern("wrap"), 1, val));
|
|
1676
|
+
}
|
|
1677
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1678
|
+
rb_funcall(val, rb_intern("to_a"), 0));
|
|
1679
|
+
}
|
|
1595
1680
|
/* Face RHS: reconcile to self's unit and descend to storage. Mirror of
|
|
1596
1681
|
the scalar path (ca_face_element_to_storage) for a bulk CArray source.
|
|
1597
1682
|
Guarded on self having to_comparable so a Face without a reconcile
|
|
@@ -1610,11 +1695,17 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1610
1695
|
{
|
|
1611
1696
|
CArray *storage = ca_strip_face(ca);
|
|
1612
1697
|
if ( storage && ca_is_integer_type(storage) && ! ca_is_integer_type(cval) ) {
|
|
1698
|
+
const char *method = ca_face_storage_method(self);
|
|
1699
|
+
if ( method ) {
|
|
1700
|
+
rb_raise(rb_eTypeError,
|
|
1701
|
+
"%s cannot store a bare %s array as raw storage "
|
|
1702
|
+
"(write the %s storage, which #%s gives, directly)",
|
|
1703
|
+
rb_obj_classname(self), ca_type_name[cval->data_type],
|
|
1704
|
+
ca_type_name[storage->data_type], method);
|
|
1705
|
+
}
|
|
1613
1706
|
rb_raise(rb_eTypeError,
|
|
1614
|
-
"%s cannot store a bare %s array as raw storage
|
|
1615
|
-
|
|
1616
|
-
rb_obj_classname(self), ca_type_name[cval->data_type],
|
|
1617
|
-
ca_type_name[storage->data_type]);
|
|
1707
|
+
"%s cannot store a bare %s array as raw storage",
|
|
1708
|
+
rb_obj_classname(self), ca_type_name[cval->data_type]);
|
|
1618
1709
|
}
|
|
1619
1710
|
}
|
|
1620
1711
|
return val;
|
|
@@ -1676,7 +1767,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1676
1767
|
/* newaxis (:_) interception on store. Build the newaxis view (a
|
|
1677
1768
|
writable reshape aliasing self), then assign rval into the whole view
|
|
1678
1769
|
(writes propagate to self). */
|
|
1679
|
-
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
1770
|
+
if ( ! ca_argv_is_method_call(argc, argv) && ca_argv_has_newaxis(argc, argv) ) {
|
|
1680
1771
|
volatile VALUE view = rb_ca_fetch_newaxis(argc, argv, self, ca);
|
|
1681
1772
|
rb_ca_store_all(view, rval);
|
|
1682
1773
|
return rval;
|
|
@@ -1685,7 +1776,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1685
1776
|
/* slab sigil on store is rejected regardless of outer-slot type. Catch
|
|
1686
1777
|
:> before scan_index so mask/fancy outer slots get the same "not
|
|
1687
1778
|
supported" message instead of a misleading TypeError. */
|
|
1688
|
-
if ( ca_argv_has_slab_sigil(argc, argv) ) {
|
|
1779
|
+
if ( ! ca_argv_is_method_call(argc, argv) && ca_argv_has_slab_sigil(argc, argv) ) {
|
|
1689
1780
|
rb_raise(rb_eIndexError,
|
|
1690
1781
|
"assignment through a slab iterator (:>) is not supported "
|
|
1691
1782
|
"(use a block index, e.g. ca[range, nil] = val, or each_slab)");
|
|
@@ -1704,6 +1795,16 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1704
1795
|
dest = rb_ca_strip_face_value(self);
|
|
1705
1796
|
}
|
|
1706
1797
|
|
|
1798
|
+
/* One cell of a CAString holds a String. Stored into the object storage,
|
|
1799
|
+
a Ruby Array would become the cell's value, which a plain object array
|
|
1800
|
+
allows. */
|
|
1801
|
+
if ( ca->obj_type == CA_OBJ_STRING && TYPE(rval) == T_ARRAY &&
|
|
1802
|
+
( info.type == CA_REG_ADDRESS || info.type == CA_REG_POINT ) ) {
|
|
1803
|
+
rb_raise(rb_eTypeError,
|
|
1804
|
+
"%s: an Array is not a String (one cell of a CAString holds "
|
|
1805
|
+
"a String; UNDEF masks a cell)", ca_calling_method_name());
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1707
1808
|
switch ( info.type ) {
|
|
1708
1809
|
case CA_REG_ADDRESS_COMPLEX:
|
|
1709
1810
|
self = rb_ca_refer_new_flatten(self);
|
|
@@ -1755,15 +1856,12 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1755
1856
|
break;
|
|
1756
1857
|
}
|
|
1757
1858
|
case CA_REG_METHOD_CALL: {
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
c.argv = argv+1;
|
|
1765
|
-
c.rval = rval;
|
|
1766
|
-
obj = ca_attach_window(1, &ca, "r", ca_store_method_call_body, (VALUE) &c);
|
|
1859
|
+
/* a[:eq, 0] = v is a[a.eq(0)] = v: the index is computed first and the
|
|
1860
|
+
store then goes through it, as the read does -- only the cells it
|
|
1861
|
+
picks are written. */
|
|
1862
|
+
volatile VALUE idx;
|
|
1863
|
+
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1864
|
+
obj = rb_ca_store(dest, idx, rval);
|
|
1767
1865
|
break;
|
|
1768
1866
|
}
|
|
1769
1867
|
case CA_REG_MEMBER: {
|
|
@@ -1778,11 +1876,6 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1778
1876
|
}
|
|
1779
1877
|
break;
|
|
1780
1878
|
}
|
|
1781
|
-
case CA_REG_ATTRIBUTE: {
|
|
1782
|
-
obj = rb_funcall(self, rb_intern("attribute"), 0);
|
|
1783
|
-
obj = rb_hash_aset(obj, info.symbol, rval);
|
|
1784
|
-
break;
|
|
1785
|
-
}
|
|
1786
1879
|
}
|
|
1787
1880
|
|
|
1788
1881
|
return obj;
|
|
@@ -1812,7 +1905,9 @@ rb_ca_store (VALUE self, VALUE index, VALUE rval)
|
|
|
1812
1905
|
case T_ARRAY:
|
|
1813
1906
|
index = rb_obj_clone(index);
|
|
1814
1907
|
rb_ary_push(index, rval);
|
|
1815
|
-
|
|
1908
|
+
rval = rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1909
|
+
RB_GC_GUARD(index); /* the store reads its arguments out of index */
|
|
1910
|
+
return rval;
|
|
1816
1911
|
default: {
|
|
1817
1912
|
VALUE rindex[2] = { index, rval };
|
|
1818
1913
|
return rb_ca_store_method(2, rindex, self);
|
|
@@ -1825,7 +1920,9 @@ rb_ca_store2 (VALUE self, int n, VALUE *rindex, VALUE rval)
|
|
|
1825
1920
|
{
|
|
1826
1921
|
volatile VALUE index = rb_ary_new4(n, rindex);
|
|
1827
1922
|
rb_ary_push(index, rval);
|
|
1828
|
-
|
|
1923
|
+
rval = rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1924
|
+
RB_GC_GUARD(index); /* the store reads its arguments out of index */
|
|
1925
|
+
return rval;
|
|
1829
1926
|
}
|
|
1830
1927
|
|
|
1831
1928
|
static VALUE
|
|
@@ -1842,11 +1939,11 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1842
1939
|
Check_Type(ridx, T_ARRAY);
|
|
1843
1940
|
|
|
1844
1941
|
ndim = (int) RARRAY_LEN(rdim);
|
|
1845
|
-
|
|
1942
|
+
CA_CHECK_RANK_GIVEN(ndim);
|
|
1846
1943
|
for (i=0; i<ndim; i++) {
|
|
1847
1944
|
dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
1848
1945
|
}
|
|
1849
|
-
|
|
1946
|
+
CA_CHECK_DIM_GIVEN(ndim, dim);
|
|
1850
1947
|
elements = ca_shape_elements(ndim, dim, 1);
|
|
1851
1948
|
|
|
1852
1949
|
info.range_check = 1;
|
|
@@ -1919,8 +2016,7 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1919
2016
|
case CA_REG_GRID:
|
|
1920
2017
|
case CA_REG_MAPPING:
|
|
1921
2018
|
case CA_REG_METHOD_CALL:
|
|
1922
|
-
case CA_REG_MEMBER:
|
|
1923
|
-
case CA_REG_ATTRIBUTE:
|
|
2019
|
+
case CA_REG_MEMBER:
|
|
1924
2020
|
break;
|
|
1925
2021
|
default:
|
|
1926
2022
|
rb_raise(rb_eArgError, "unknown index specification");
|
|
@@ -2016,10 +2112,11 @@ parse_shape_kwarg (VALUE rshape, int *out_ndim, ca_size_t *dim,
|
|
|
2016
2112
|
|
|
2017
2113
|
Check_Type(rshape, T_ARRAY);
|
|
2018
2114
|
ndim = (int) RARRAY_LEN(rshape);
|
|
2019
|
-
if ( ndim < 1
|
|
2115
|
+
if ( ndim < 1 ) {
|
|
2020
2116
|
rb_raise(rb_eArgError, "invalid shape ndim %d (must be 1..%d)",
|
|
2021
2117
|
ndim, CA_RANK_MAX);
|
|
2022
2118
|
}
|
|
2119
|
+
ca_check_rank_fits(ndim, NULL);
|
|
2023
2120
|
for (i = 0; i < ndim; i++) {
|
|
2024
2121
|
dim[i] = NUM2SIZE(rb_ary_entry(rshape, i));
|
|
2025
2122
|
if ( dim[i] < 0 ) {
|
|
@@ -2103,6 +2200,7 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
2103
2200
|
}
|
|
2104
2201
|
|
|
2105
2202
|
ca_detach(cin);
|
|
2203
|
+
RB_GC_GUARD(raddr); /* the CA_SIZE view is reached only through cin */
|
|
2106
2204
|
return out;
|
|
2107
2205
|
}
|
|
2108
2206
|
}
|
|
@@ -2306,7 +2404,7 @@ rb_ca_s_addr2index (int argc, VALUE *argv, VALUE klass)
|
|
|
2306
2404
|
static VALUE
|
|
2307
2405
|
rb_ca_s_index2addr (int argc, VALUE *argv, VALUE klass)
|
|
2308
2406
|
{
|
|
2309
|
-
VALUE rest, opts;
|
|
2407
|
+
VALUE rest, opts, out;
|
|
2310
2408
|
ID kw_ids[1];
|
|
2311
2409
|
VALUE kw_vals[1];
|
|
2312
2410
|
int ndim;
|
|
@@ -2320,7 +2418,10 @@ rb_ca_s_index2addr (int argc, VALUE *argv, VALUE klass)
|
|
|
2320
2418
|
}
|
|
2321
2419
|
rb_get_kwargs(opts, kw_ids, 1, 0, kw_vals);
|
|
2322
2420
|
parse_shape_kwarg(kw_vals[0], &ndim, dim, &elements);
|
|
2323
|
-
|
|
2421
|
+
/* index2addr_do reads, and replaces, its arguments in rest */
|
|
2422
|
+
out = index2addr_do(ndim, dim, (int) RARRAY_LEN(rest), RARRAY_PTR(rest));
|
|
2423
|
+
RB_GC_GUARD(rest);
|
|
2424
|
+
return out;
|
|
2324
2425
|
}
|
|
2325
2426
|
|
|
2326
2427
|
|