carray 3.0.2 → 3.0.4
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 +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +104 -81
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/carray_access.c
CHANGED
|
@@ -36,10 +36,7 @@ rb_ca_store_index (VALUE self, ca_size_t *idx, VALUE rval)
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
if ( rval == CA_UNDEF ) { /* set mask of the element at the index 'idx' */
|
|
39
|
-
|
|
40
|
-
if ( ! ca->mask ) {
|
|
41
|
-
ca_create_mask(ca);
|
|
42
|
-
}
|
|
39
|
+
ca_create_mask(ca);
|
|
43
40
|
ca_store_index(ca->mask, idx, &one);
|
|
44
41
|
}
|
|
45
42
|
else { /* unset mask and set value of the element at the index 'idx' */
|
|
@@ -51,16 +48,12 @@ rb_ca_store_index (VALUE self, ca_size_t *idx, VALUE rval)
|
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
/* store value */
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
ca_store_index(ca, idx, v);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
char *v = xmalloc(ca->bytes);
|
|
51
|
+
{
|
|
52
|
+
volatile VALUE holder;
|
|
53
|
+
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
61
54
|
rb_ca_obj2ptr(self, rval, v);
|
|
62
55
|
ca_store_index(ca, idx, v);
|
|
63
|
-
|
|
56
|
+
ALLOCV_END(holder);
|
|
64
57
|
}
|
|
65
58
|
}
|
|
66
59
|
|
|
@@ -79,16 +72,12 @@ rb_ca_fetch_index (VALUE self, ca_size_t *idx)
|
|
|
79
72
|
}
|
|
80
73
|
|
|
81
74
|
/* fetch value from the element */
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
out = rb_ca_ptr2obj(self, v);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
char *v = xmalloc(ca->bytes);
|
|
75
|
+
{
|
|
76
|
+
volatile VALUE holder;
|
|
77
|
+
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
89
78
|
ca_fetch_index(ca, idx, v);
|
|
90
|
-
out =
|
|
91
|
-
|
|
79
|
+
out = rb_ca_ptr2obj_storage(self, v);
|
|
80
|
+
ALLOCV_END(holder);
|
|
92
81
|
}
|
|
93
82
|
|
|
94
83
|
/* check if the element is masked */
|
|
@@ -101,11 +90,11 @@ rb_ca_fetch_index (VALUE self, ca_size_t *idx)
|
|
|
101
90
|
}
|
|
102
91
|
}
|
|
103
92
|
|
|
104
|
-
/* Face scalar decode (invoked if the subclass defines
|
|
105
|
-
|
|
93
|
+
/* Face scalar decode (invoked if the subclass defines storage_to_element(raw)) */
|
|
94
|
+
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(out, self, ca);
|
|
106
95
|
|
|
107
96
|
/* Boolean scalar access yields true/false, not Integer 0/1. Bulk paths
|
|
108
|
-
(
|
|
97
|
+
(cast / serialize) keep 0/1. Gate on the raw
|
|
109
98
|
INT2FIX(0/1) so a boolean-storage Face that decoded to its own object is
|
|
110
99
|
left untouched; note INT2FIX(0) is truthy in Ruby, so map by value, not
|
|
111
100
|
by RTEST. */
|
|
@@ -131,10 +120,7 @@ rb_ca_store_addr (VALUE self, ca_size_t addr, VALUE rval)
|
|
|
131
120
|
}
|
|
132
121
|
|
|
133
122
|
if ( rval == CA_UNDEF ) { /* set mask at the element */
|
|
134
|
-
|
|
135
|
-
if ( ! ca->mask ) {
|
|
136
|
-
ca_create_mask(ca);
|
|
137
|
-
}
|
|
123
|
+
ca_create_mask(ca);
|
|
138
124
|
ca_store_addr(ca->mask, addr, &one);
|
|
139
125
|
}
|
|
140
126
|
else { /* set value at the element */
|
|
@@ -144,16 +130,12 @@ rb_ca_store_addr (VALUE self, ca_size_t addr, VALUE rval)
|
|
|
144
130
|
}
|
|
145
131
|
|
|
146
132
|
/* store value */
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
ca_store_addr(ca, addr, v);
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
char *v = xmalloc(ca->bytes);
|
|
133
|
+
{
|
|
134
|
+
volatile VALUE holder;
|
|
135
|
+
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
154
136
|
rb_ca_obj2ptr(self, rval, v);
|
|
155
137
|
ca_store_addr(ca, addr, v);
|
|
156
|
-
|
|
138
|
+
ALLOCV_END(holder);
|
|
157
139
|
}
|
|
158
140
|
}
|
|
159
141
|
|
|
@@ -172,16 +154,12 @@ rb_ca_fetch_addr (VALUE self, ca_size_t addr)
|
|
|
172
154
|
}
|
|
173
155
|
|
|
174
156
|
/* fetch value from the element */
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
out = rb_ca_ptr2obj(self, v);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
char *v = xmalloc(ca->bytes);
|
|
157
|
+
{
|
|
158
|
+
volatile VALUE holder;
|
|
159
|
+
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
182
160
|
ca_fetch_addr(ca, addr, v);
|
|
183
|
-
out =
|
|
184
|
-
|
|
161
|
+
out = rb_ca_ptr2obj_storage(self, v);
|
|
162
|
+
ALLOCV_END(holder);
|
|
185
163
|
}
|
|
186
164
|
|
|
187
165
|
/* check if the element is masked */
|
|
@@ -195,7 +173,7 @@ rb_ca_fetch_addr (VALUE self, ca_size_t addr)
|
|
|
195
173
|
}
|
|
196
174
|
|
|
197
175
|
/* Face scalar decode */
|
|
198
|
-
|
|
176
|
+
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(out, self, ca);
|
|
199
177
|
|
|
200
178
|
/* Boolean scalar access yields true/false (see rb_ca_fetch_index). */
|
|
201
179
|
if ( ca->data_type == CA_BOOLEAN &&
|
|
@@ -220,21 +198,19 @@ rb_ca_fill (VALUE self, VALUE rval)
|
|
|
220
198
|
|
|
221
199
|
if ( rval == CA_UNDEF ) {
|
|
222
200
|
boolean8_t one = 1;
|
|
223
|
-
|
|
224
|
-
if ( ! ca->mask ) {
|
|
225
|
-
ca_create_mask(ca);
|
|
226
|
-
}
|
|
201
|
+
ca_create_mask(ca);
|
|
227
202
|
ca_fill(ca->mask, &one);
|
|
228
203
|
}
|
|
229
204
|
else {
|
|
230
|
-
|
|
205
|
+
volatile VALUE holder;
|
|
206
|
+
char *fval = ALLOCV_N(char, holder, ca->bytes);
|
|
231
207
|
boolean8_t zero = 0;
|
|
232
208
|
rb_ca_obj2ptr(self, rval, fval);
|
|
233
209
|
if ( ca_has_mask(ca) ) {
|
|
234
210
|
ca_fill(ca->mask, &zero);
|
|
235
211
|
}
|
|
236
212
|
ca_fill(ca, fval);
|
|
237
|
-
|
|
213
|
+
ALLOCV_END(holder);
|
|
238
214
|
}
|
|
239
215
|
|
|
240
216
|
return self;
|
|
@@ -253,9 +229,7 @@ static void
|
|
|
253
229
|
ary_guess_shape (VALUE ary, int level, int *max_level, ca_size_t *dim)
|
|
254
230
|
{
|
|
255
231
|
volatile VALUE ary0;
|
|
256
|
-
|
|
257
|
-
rb_raise(rb_eRuntimeError, "too deep level array for conversion to carray");
|
|
258
|
-
}
|
|
232
|
+
ca_check_rank_fits(level + 1, NULL);
|
|
259
233
|
|
|
260
234
|
if ( TYPE(ary) == T_ARRAY ) {
|
|
261
235
|
if ( RARRAY_LEN(ary) == 0 && level == 0 ) {
|
|
@@ -304,7 +278,7 @@ ary_flatten_upto_level (VALUE ary, int max_level, int level,
|
|
|
304
278
|
int32_t i;
|
|
305
279
|
|
|
306
280
|
if ( TYPE(ary) != T_ARRAY ) {
|
|
307
|
-
rb_raise(
|
|
281
|
+
rb_raise(rb_eArgError, "invalid shape array for conversion to carray");
|
|
308
282
|
}
|
|
309
283
|
|
|
310
284
|
if ( level == max_level ) {
|
|
@@ -321,7 +295,7 @@ ary_flatten_upto_level (VALUE ary, int max_level, int level,
|
|
|
321
295
|
}
|
|
322
296
|
}
|
|
323
297
|
|
|
324
|
-
|
|
298
|
+
VALUE
|
|
325
299
|
rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
326
300
|
{
|
|
327
301
|
CArray *ca = (CArray *) ap;
|
|
@@ -348,7 +322,7 @@ rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
|
348
322
|
}
|
|
349
323
|
|
|
350
324
|
if ( total != ca->elements ) {
|
|
351
|
-
rb_raise(
|
|
325
|
+
rb_raise(rb_eArgError, "invalid shape array for conversion to carray");
|
|
352
326
|
}
|
|
353
327
|
else {
|
|
354
328
|
volatile VALUE out = rb_ary_new2(0);
|
|
@@ -500,6 +474,200 @@ ca_id_expression_evaluator (void)
|
|
|
500
474
|
return id;
|
|
501
475
|
}
|
|
502
476
|
|
|
477
|
+
/* The casting stores below convert into the destination inside a window,
|
|
478
|
+
and a conversion from Ruby objects can raise part way. Such a window
|
|
479
|
+
attaches rather than allocates: the cells converted before the raise
|
|
480
|
+
are then pushed back with the others left as they were -- what an
|
|
481
|
+
entity destination, which has no separate buffer, shows as well. A
|
|
482
|
+
cast that cannot raise keeps the cheaper allocate. */
|
|
483
|
+
|
|
484
|
+
typedef struct {
|
|
485
|
+
CArray *ca;
|
|
486
|
+
CArray *cv; /* CArray source, delivered into scratch */
|
|
487
|
+
char *scratch;
|
|
488
|
+
boolean8_t *mscratch; /* cv's mask, or NULL when it has none */
|
|
489
|
+
CArray *ico; /* Ruby Array source: an object descriptor */
|
|
490
|
+
volatile VALUE list;
|
|
491
|
+
int has_mask;
|
|
492
|
+
} ca_store_all_ctx_t;
|
|
493
|
+
|
|
494
|
+
static const char *
|
|
495
|
+
ca_store_all_mode (CArray *cv)
|
|
496
|
+
{
|
|
497
|
+
return ( cv->data_type == CA_OBJECT ) ? "w" : "a";
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/* The window has attached ca's mask, and the one created here joins it,
|
|
501
|
+
so the mask is written in its buffer. */
|
|
502
|
+
static VALUE
|
|
503
|
+
ca_store_all_cast_body (VALUE arg)
|
|
504
|
+
{
|
|
505
|
+
ca_store_all_ctx_t *c = (ca_store_all_ctx_t *) arg;
|
|
506
|
+
CArray *ca = c->ca;
|
|
507
|
+
if ( c->mscratch ) {
|
|
508
|
+
if ( ! ca->mask ) {
|
|
509
|
+
ca_create_mask(ca);
|
|
510
|
+
}
|
|
511
|
+
memcpy(ca->mask->ptr, c->mscratch, ca->elements);
|
|
512
|
+
}
|
|
513
|
+
else if ( ca->mask ) {
|
|
514
|
+
memset(ca->mask->ptr, 0, ca->elements);
|
|
515
|
+
}
|
|
516
|
+
if ( ca->mask ) {
|
|
517
|
+
ca_cast_block_with_mask(ca->elements, c->cv, c->scratch, ca, ca->ptr,
|
|
518
|
+
(boolean8_t*)ca->mask->ptr);
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
ca_cast_block(ca->elements, c->cv, c->scratch, ca, ca->ptr);
|
|
522
|
+
}
|
|
523
|
+
return Qnil;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
static VALUE
|
|
527
|
+
ca_store_all_list_body (VALUE arg)
|
|
528
|
+
{
|
|
529
|
+
ca_store_all_ctx_t *c = (ca_store_all_ctx_t *) arg;
|
|
530
|
+
CArray *ca = c->ca;
|
|
531
|
+
VALUE list = c->list;
|
|
532
|
+
ca_size_t i;
|
|
533
|
+
/* Face has surface != storage; the cast runs in the storage
|
|
534
|
+
data_type. Passing ca directly makes the cast table see FIXLEN
|
|
535
|
+
and report non-implemented, so pass a shadow CArray (storage
|
|
536
|
+
data_type, ptr aliased to ca). */
|
|
537
|
+
CArray shadow;
|
|
538
|
+
CArray *cast_target = ca;
|
|
539
|
+
memset(&shadow, 0, sizeof(CArray));
|
|
540
|
+
if ( ca_is_face(ca) ) {
|
|
541
|
+
CArray *root = ca_strip_face(ca);
|
|
542
|
+
if (root) {
|
|
543
|
+
shadow.data_type = root->data_type;
|
|
544
|
+
shadow.bytes = ca->bytes;
|
|
545
|
+
shadow.elements = ca->elements;
|
|
546
|
+
shadow.ptr = ca->ptr;
|
|
547
|
+
cast_target = &shadow;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if ( c->has_mask ) {
|
|
551
|
+
boolean8_t *m;
|
|
552
|
+
m = (boolean8_t *)ca->mask->ptr;
|
|
553
|
+
for (i=0; i<ca->elements; i++) {
|
|
554
|
+
if ( rb_ary_entry(list,i) == CA_UNDEF ) {
|
|
555
|
+
*m = 1;
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
*m = 0;
|
|
559
|
+
}
|
|
560
|
+
m++;
|
|
561
|
+
}
|
|
562
|
+
ca_cast_block_with_mask(ca->elements, c->ico, (VALUE *)RARRAY_CONST_PTR(list),
|
|
563
|
+
cast_target, ca->ptr,
|
|
564
|
+
(boolean8_t*)ca->mask->ptr);
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
/* Every cell gets a value, so none stays masked. */
|
|
568
|
+
if ( ca->mask ) {
|
|
569
|
+
memset(ca->mask->ptr, 0, ca->elements);
|
|
570
|
+
}
|
|
571
|
+
ca_cast_block(ca->elements, c->ico, (VALUE *)RARRAY_CONST_PTR(list), cast_target, ca->ptr);
|
|
572
|
+
}
|
|
573
|
+
return Qnil;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/* A Face source stored into an array that is not the same Face. Its cells
|
|
577
|
+
are surface values, and its storage means nothing to the destination: a
|
|
578
|
+
CATime's ticks are not times to an object array, and a categorical's codes
|
|
579
|
+
are not its labels. So an object destination, or a Face that does not
|
|
580
|
+
reconcile a Face source itself (a fixlen string taking a const string),
|
|
581
|
+
receives the values (to_type(:object)), and any other plain destination
|
|
582
|
+
refuses rather than receive storage bytes. A destination of the same Face
|
|
583
|
+
class, or one that reconciles a Face (to_comparable), is left to
|
|
584
|
+
ca_face_convert_store_rval. */
|
|
585
|
+
static VALUE
|
|
586
|
+
ca_face_source_for_store (VALUE self, CArray *ca, VALUE rval)
|
|
587
|
+
{
|
|
588
|
+
CArray *cr;
|
|
589
|
+
|
|
590
|
+
if ( ! rb_obj_is_carray(rval) ) {
|
|
591
|
+
return rval;
|
|
592
|
+
}
|
|
593
|
+
GetCArray(rval, cr);
|
|
594
|
+
if ( ! ca_is_face(cr) ) {
|
|
595
|
+
return rval;
|
|
596
|
+
}
|
|
597
|
+
if ( ca_is_face(ca) && ca->obj_type == CA_OBJ_RECORD ) {
|
|
598
|
+
/* A record is read at its data_class's member offsets, so records of
|
|
599
|
+
another data_class (of the same size or not) are refused; the class
|
|
600
|
+
of the record array (a subclass or CARecord itself) does not matter. */
|
|
601
|
+
if ( cr->obj_type == CA_OBJ_RECORD
|
|
602
|
+
&& rb_ca_data_class(self) == rb_ca_data_class(rval) ) {
|
|
603
|
+
return rval;
|
|
604
|
+
}
|
|
605
|
+
if ( cr->obj_type == CA_OBJ_RECORD ) {
|
|
606
|
+
rb_raise(rb_eTypeError,
|
|
607
|
+
"can not store a record array of %"PRIsVALUE
|
|
608
|
+
" into a record array of %"PRIsVALUE,
|
|
609
|
+
rb_ca_data_class(rval), rb_ca_data_class(self));
|
|
610
|
+
}
|
|
611
|
+
rb_raise(rb_eTypeError,
|
|
612
|
+
"can not store a %s array into a record array of %"PRIsVALUE,
|
|
613
|
+
rb_obj_classname(rval), rb_ca_data_class(self));
|
|
614
|
+
}
|
|
615
|
+
if ( ca_is_face(ca) ) {
|
|
616
|
+
if ( rb_obj_class(self) == rb_obj_class(rval)
|
|
617
|
+
|| rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
618
|
+
return rval;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
else if ( ca->data_type != CA_OBJECT ) {
|
|
622
|
+
/* A fixlen string or a record is its bytes: storage and surface are
|
|
623
|
+
the same, so a plain array of that type takes them as they are. A
|
|
624
|
+
const string's bytes are ranges into a pool of its own, and it is the
|
|
625
|
+
read-only Face that says so. */
|
|
626
|
+
CArray *storage = ca_strip_face(cr);
|
|
627
|
+
if ( storage->data_type == cr->data_type && storage->bytes == cr->bytes
|
|
628
|
+
&& ! ca_is_readonly(cr) ) {
|
|
629
|
+
return rval;
|
|
630
|
+
}
|
|
631
|
+
rb_raise(rb_eTypeError,
|
|
632
|
+
"can not store a %s array into %s array "
|
|
633
|
+
"(to_type(:object) gives its values)",
|
|
634
|
+
rb_obj_classname(rval), ca_type_name[ca->data_type]);
|
|
635
|
+
}
|
|
636
|
+
return rb_funcall(rval, rb_intern("to_type"), 1, INT2NUM(CA_OBJECT));
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/* A store into no cells writes nothing, but the value is checked as it
|
|
640
|
+
would be for any cells: the same statement does not raise or pass
|
|
641
|
+
depending on how many cells the index picks. */
|
|
642
|
+
static void
|
|
643
|
+
ca_store_all_check_empty (VALUE self, VALUE rval)
|
|
644
|
+
{
|
|
645
|
+
CArray *ca;
|
|
646
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
647
|
+
if ( rb_obj_is_cscalar(rval) ) {
|
|
648
|
+
rval = rb_ca_fetch_addr(rval, 0);
|
|
649
|
+
}
|
|
650
|
+
rval = ca_face_source_for_store(self, ca, rval);
|
|
651
|
+
if ( ! rb_obj_is_carray(rval) && TYPE(rval) != T_ARRAY &&
|
|
652
|
+
rb_respond_to(rval, id_to_ca) ) {
|
|
653
|
+
rval = rb_funcall(rval, id_to_ca, 0);
|
|
654
|
+
}
|
|
655
|
+
if ( rb_obj_is_carray(rval) ) {
|
|
656
|
+
ca_broadcast_to_destination(self, (volatile VALUE *) &rval);
|
|
657
|
+
}
|
|
658
|
+
else if ( TYPE(rval) == T_ARRAY ) {
|
|
659
|
+
if ( NIL_P(rb_ary_flatten_for_elements(rval, ca->elements, ca)) ) {
|
|
660
|
+
rb_raise(rb_eArgError, "failed to guess data size of given array");
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
else if ( rval != CA_UNDEF ) {
|
|
664
|
+
volatile VALUE holder;
|
|
665
|
+
char *fval = ALLOCV_N(char, holder, ca->bytes);
|
|
666
|
+
rb_ca_obj2ptr(self, rval, fval);
|
|
667
|
+
ALLOCV_END(holder);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
503
671
|
VALUE
|
|
504
672
|
rb_ca_store_all (VALUE self, VALUE rval)
|
|
505
673
|
{
|
|
@@ -507,15 +675,20 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
507
675
|
|
|
508
676
|
rb_ca_modify(self);
|
|
509
677
|
|
|
510
|
-
if ( self == rval
|
|
678
|
+
if ( self == rval ) {
|
|
511
679
|
return rval;
|
|
512
680
|
}
|
|
513
|
-
|
|
681
|
+
if ( rb_ca_is_empty(self) ) {
|
|
682
|
+
ca_store_all_check_empty(self, rval);
|
|
683
|
+
return rval;
|
|
684
|
+
}
|
|
685
|
+
|
|
514
686
|
if ( rb_obj_is_cscalar(rval) ) {
|
|
515
687
|
rval = rb_ca_fetch_addr(rval, 0);
|
|
516
688
|
}
|
|
517
689
|
|
|
518
690
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
691
|
+
rval = ca_face_source_for_store(self, ca, rval);
|
|
519
692
|
|
|
520
693
|
retry:
|
|
521
694
|
|
|
@@ -534,6 +707,7 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
534
707
|
&& ca->data_type == cv->data_type
|
|
535
708
|
&& ca->ndim == cv->ndim
|
|
536
709
|
&& ca->elements == cv->elements
|
|
710
|
+
&& ca_in_main_ractor()
|
|
537
711
|
&& RTEST(rb_attr_get(rb_cCArray, ca_id_expression_evaluator())) ) {
|
|
538
712
|
int8_t k;
|
|
539
713
|
int same = 1;
|
|
@@ -552,6 +726,17 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
552
726
|
ca_broadcast_to_destination(self, &rval);
|
|
553
727
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
554
728
|
|
|
729
|
+
/* Fixlen cells of another width are fitted cell by cell, padded with
|
|
730
|
+
NUL or cut to the destination's width, as a String or an Array of
|
|
731
|
+
Strings stored into fixlen cells is. Copied as they are, the bytes
|
|
732
|
+
would be read past the end of a narrower source. */
|
|
733
|
+
if ( ca->data_type == CA_FIXLEN && cv->data_type == CA_FIXLEN
|
|
734
|
+
&& ca->bytes != cv->bytes ) {
|
|
735
|
+
rval = rb_ca_to_type(rb_ca_strip_face_value(rval), INT2NUM(CA_FIXLEN),
|
|
736
|
+
SIZE2NUM(ca->bytes));
|
|
737
|
+
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
738
|
+
}
|
|
739
|
+
|
|
555
740
|
/* Source delivery via ca_xfer_all into a local scratch instead of
|
|
556
741
|
ca_attach(cv). This routes through ca_*_func_xfer_all's per-region
|
|
557
742
|
partial-materialise path, avoiding a ca_attach(root) silent
|
|
@@ -564,29 +749,50 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
564
749
|
scales with the view, not the root. (The dst-side ca_sync_data is
|
|
565
750
|
already an xfer_all PUT.) */
|
|
566
751
|
{
|
|
567
|
-
volatile VALUE scratch_holder;
|
|
752
|
+
volatile VALUE scratch_holder, mscratch_holder = 0;
|
|
568
753
|
ca_size_t cv_bytes = cv->bytes * cv->elements;
|
|
569
754
|
char *scratch = ALLOCV_N(char, scratch_holder, cv_bytes);
|
|
755
|
+
boolean8_t *mscratch = NULL;
|
|
570
756
|
ca_xfer_all(cv, scratch, CA_XFER_GET);
|
|
571
757
|
|
|
758
|
+
/* The source's mask is taken now as well, before anything is
|
|
759
|
+
written: the source may read through to the destination's mask
|
|
760
|
+
(`c[] = c.flip(0)`, or a lazy expression over c whose mask is
|
|
761
|
+
built from c's on demand), and the writes below clear it. */
|
|
762
|
+
if ( ca_has_mask(cv) ) {
|
|
763
|
+
mscratch = ALLOCV_N(boolean8_t, mscratch_holder, cv->elements);
|
|
764
|
+
ca_xfer_all(cv->mask, mscratch, CA_XFER_GET);
|
|
765
|
+
}
|
|
766
|
+
|
|
572
767
|
if ( ca->data_type != cv->data_type ) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
768
|
+
ca_store_all_ctx_t c;
|
|
769
|
+
c.ca = ca;
|
|
770
|
+
c.cv = cv;
|
|
771
|
+
c.scratch = scratch;
|
|
772
|
+
c.mscratch = mscratch;
|
|
773
|
+
ca_attach_window(1, &ca, ca_store_all_mode(cv), ca_store_all_cast_body,
|
|
774
|
+
(VALUE) &c);
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
if ( mscratch ) {
|
|
778
|
+
if ( ! ca->mask ) {
|
|
779
|
+
ca_create_mask(ca);
|
|
780
|
+
}
|
|
781
|
+
ca_sync_data(ca->mask, (char *) mscratch);
|
|
578
782
|
}
|
|
579
783
|
else {
|
|
580
|
-
|
|
784
|
+
ca_update_mask(ca);
|
|
785
|
+
if ( ca->mask ) {
|
|
786
|
+
boolean8_t zero = 0;
|
|
787
|
+
ca_fill(ca->mask, &zero);
|
|
788
|
+
}
|
|
581
789
|
}
|
|
582
|
-
ca_sync(ca);
|
|
583
|
-
ca_detach(ca);
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
587
790
|
ca_sync_data(ca, scratch);
|
|
588
791
|
}
|
|
589
792
|
|
|
793
|
+
if ( mscratch ) {
|
|
794
|
+
ALLOCV_END(mscratch_holder);
|
|
795
|
+
}
|
|
590
796
|
ALLOCV_END(scratch_holder);
|
|
591
797
|
}
|
|
592
798
|
}
|
|
@@ -595,7 +801,7 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
595
801
|
rb_ary_flatten_for_elements(rval, ca->elements, ca);
|
|
596
802
|
ca_size_t i;
|
|
597
803
|
if ( NIL_P(list) ) {
|
|
598
|
-
rb_raise(
|
|
804
|
+
rb_raise(rb_eArgError,
|
|
599
805
|
"failed to guess data size of given array");
|
|
600
806
|
}
|
|
601
807
|
else {
|
|
@@ -612,54 +818,19 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
612
818
|
break;
|
|
613
819
|
}
|
|
614
820
|
}
|
|
615
|
-
/*
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
so ca_allocate()'s simpler path (no parent data copy) is sufficient. */
|
|
621
|
-
ca_allocate(ca);
|
|
821
|
+
/* Every element is replaced, so there would be no need to gather the
|
|
822
|
+
old values -- but converting a Ruby object can raise part way, and
|
|
823
|
+
then the cells already converted are pushed back with the rest
|
|
824
|
+
left as they were, which needs the old values in the buffer. So
|
|
825
|
+
this window attaches (see ca_store_all_mode). */
|
|
622
826
|
{
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
memset(&shadow, 0, sizeof(CArray));
|
|
630
|
-
if ( ca_is_face(ca) ) {
|
|
631
|
-
CArray *root = ca;
|
|
632
|
-
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
633
|
-
if (root) {
|
|
634
|
-
shadow.data_type = root->data_type;
|
|
635
|
-
shadow.bytes = ca->bytes;
|
|
636
|
-
shadow.elements = ca->elements;
|
|
637
|
-
shadow.ptr = ca->ptr;
|
|
638
|
-
cast_target = &shadow;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
if ( has_mask ) {
|
|
642
|
-
boolean8_t *m;
|
|
643
|
-
m = (boolean8_t *)ca->mask->ptr;
|
|
644
|
-
for (i=0; i<ca->elements; i++) {
|
|
645
|
-
if ( rb_ary_entry(list,i) == CA_UNDEF ) {
|
|
646
|
-
*m = 1;
|
|
647
|
-
}
|
|
648
|
-
else {
|
|
649
|
-
*m = 0;
|
|
650
|
-
}
|
|
651
|
-
m++;
|
|
652
|
-
}
|
|
653
|
-
ca_cast_block_with_mask(ca->elements, &ico, (VALUE *)RARRAY_CONST_PTR(list),
|
|
654
|
-
cast_target, ca->ptr,
|
|
655
|
-
(boolean8_t*)ca->mask->ptr);
|
|
656
|
-
}
|
|
657
|
-
else {
|
|
658
|
-
ca_cast_block(ca->elements, &ico, (VALUE *)RARRAY_CONST_PTR(list), cast_target, ca->ptr);
|
|
659
|
-
}
|
|
827
|
+
ca_store_all_ctx_t c;
|
|
828
|
+
c.ca = ca;
|
|
829
|
+
c.ico = &ico;
|
|
830
|
+
c.list = list;
|
|
831
|
+
c.has_mask = has_mask;
|
|
832
|
+
ca_attach_window(1, &ca, "w", ca_store_all_list_body, (VALUE) &c);
|
|
660
833
|
}
|
|
661
|
-
ca_sync(ca);
|
|
662
|
-
ca_detach(ca);
|
|
663
834
|
}
|
|
664
835
|
}
|
|
665
836
|
else if ( rb_respond_to(rval, id_to_ca) ) {
|
|
@@ -835,9 +1006,8 @@ rb_ca_ref_block (VALUE self, CAIndexInfo *info)
|
|
|
835
1006
|
data_type to the storage data_type (chain bottom) so the write path
|
|
836
1007
|
casts in the storage type. */
|
|
837
1008
|
if ( ca_is_face(ca) ) {
|
|
838
|
-
CArray *blk_ca, *root = ca;
|
|
1009
|
+
CArray *blk_ca, *root = ca_strip_face(ca);
|
|
839
1010
|
TypedData_Get_Struct(blk, CArray, &carray_data_type, blk_ca);
|
|
840
|
-
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
841
1011
|
if (root && root->data_type != blk_ca->data_type) {
|
|
842
1012
|
blk_ca->data_type = root->data_type;
|
|
843
1013
|
}
|
|
@@ -871,7 +1041,9 @@ extern VALUE rb_ca_remap_new (VALUE cary, VALUE rmapper);
|
|
|
871
1041
|
(b) Otherwise -> normalize chain (a.flatten[mapper.flatten]
|
|
872
1042
|
.reshape). A 1-D mapper is already routed to CAGrid upstream.
|
|
873
1043
|
|
|
874
|
-
|
|
1044
|
+
A masked mapper cell selects nothing: the cell keeps its position and
|
|
1045
|
+
reads as masked (a CAGrid hole); the same-shape fast path is left to a
|
|
1046
|
+
mapper with no masked cell. */
|
|
875
1047
|
static VALUE
|
|
876
1048
|
rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
877
1049
|
{
|
|
@@ -883,18 +1055,33 @@ rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
|
883
1055
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
884
1056
|
TypedData_Get_Struct(rmapper, CArray, &carray_data_type, cm);
|
|
885
1057
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1058
|
+
/* (a) same-shape fast path: ndim + per-axis dim + CA_SIZE data_type.
|
|
1059
|
+
The view reads the index array it is given, so it is given a copy: the
|
|
1060
|
+
indices are the ones the caller passed at this call, as every other
|
|
1061
|
+
route reads them, and each is checked against self now, so an index out
|
|
1062
|
+
of range raises here and not at the first read. */
|
|
891
1063
|
if ( cm->data_type == CA_SIZE
|
|
1064
|
+
&& ! ca_is_any_masked(cm)
|
|
892
1065
|
&& cm->ndim == ca->ndim
|
|
893
1066
|
&& memcmp(cm->dim, ca->dim, ca->ndim * sizeof(ca_size_t)) == 0 ) {
|
|
894
|
-
|
|
1067
|
+
volatile VALUE snapshot = rb_ca_copy(rmapper);
|
|
1068
|
+
CArray *cs;
|
|
1069
|
+
ca_size_t k, *p;
|
|
1070
|
+
TypedData_Get_Struct(snapshot, CArray, &carray_data_type, cs);
|
|
1071
|
+
p = (ca_size_t *) cs->ptr;
|
|
1072
|
+
for (k = 0; k < cs->elements; k++) {
|
|
1073
|
+
CA_CHECK_INDEX(p[k], ca->elements);
|
|
1074
|
+
}
|
|
1075
|
+
return rb_ca_remap_new(self, snapshot);
|
|
895
1076
|
}
|
|
896
1077
|
|
|
897
|
-
/* (b) Normalize chain fallback.
|
|
1078
|
+
/* (b) Normalize chain fallback. A Face is flattened through its storage
|
|
1079
|
+
and put on top of the result, so no Face is left in the middle of the
|
|
1080
|
+
chain (CAFace.md 8.3). */
|
|
1081
|
+
if ( ca_is_face(ca) ) {
|
|
1082
|
+
result = rb_ca_fancy_index_chain(rb_ca_strip_face_value(self), rmapper);
|
|
1083
|
+
return ca_face_lift(result, self);
|
|
1084
|
+
}
|
|
898
1085
|
flat_self = rb_ca_refer_new_flatten(self);
|
|
899
1086
|
flat_mapper = (cm->ndim == 1) ? rmapper : rb_ca_flatten(rmapper);
|
|
900
1087
|
grid_argv[0] = flat_mapper;
|
|
@@ -913,10 +1100,9 @@ rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
|
913
1100
|
return result;
|
|
914
1101
|
}
|
|
915
1102
|
|
|
916
|
-
/*
|
|
917
|
-
the
|
|
918
|
-
|
|
919
|
-
class of the returned VALUE is CARefer (chain outermost), not CAMapping. */
|
|
1103
|
+
/* rb_ca_mapping_new and rb_ca_mapping index cary by a mapper array through
|
|
1104
|
+
rb_ca_fancy_index_chain: the result is a CAGrid over the flattened array,
|
|
1105
|
+
reshaped (CARefer, the outermost layer) to the mapper's shape. */
|
|
920
1106
|
|
|
921
1107
|
VALUE
|
|
922
1108
|
rb_ca_mapping_new (VALUE cary, CArray *mapper)
|
|
@@ -942,6 +1128,18 @@ rb_ca_mapping (int argc, VALUE *argv, VALUE self)
|
|
|
942
1128
|
the optimal view class (CAStride for stride bases, CARefer for fancy
|
|
943
1129
|
bases). */
|
|
944
1130
|
|
|
1131
|
+
/* a[:name, args] calls a method of the array, and its arguments are the
|
|
1132
|
+
method's, whatever they are: the scans for :_, :> and group indices
|
|
1133
|
+
below look at index keys only. */
|
|
1134
|
+
static int
|
|
1135
|
+
ca_argv_is_method_call (int argc, VALUE *argv)
|
|
1136
|
+
{
|
|
1137
|
+
const char *name;
|
|
1138
|
+
if ( argc < 1 || ! SYMBOL_P(argv[0]) ) return 0;
|
|
1139
|
+
name = rb_id2name(SYM2ID(argv[0]));
|
|
1140
|
+
return ( name != NULL && strlen(name) > 1 );
|
|
1141
|
+
}
|
|
1142
|
+
|
|
945
1143
|
static int
|
|
946
1144
|
ca_argv_has_newaxis (int argc, VALUE *argv)
|
|
947
1145
|
{
|
|
@@ -983,6 +1181,10 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
983
1181
|
|
|
984
1182
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
985
1183
|
|
|
1184
|
+
if ( ca_argv_is_method_call(argc, argv) ) {
|
|
1185
|
+
goto classify;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
986
1188
|
/* newaxis (:_) interception (cheap pointer scan; zero overhead beyond
|
|
987
1189
|
the loop when no :_ is present). */
|
|
988
1190
|
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
@@ -1006,6 +1208,7 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1006
1208
|
return rb_ca_fetch_group(argc, argv, self);
|
|
1007
1209
|
}
|
|
1008
1210
|
|
|
1211
|
+
classify:
|
|
1009
1212
|
info.range_check = 1;
|
|
1010
1213
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1011
1214
|
|
|
@@ -1014,8 +1217,20 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1014
1217
|
/* Re-enter against a flattened view of self. rb_ca_refer_new_flatten
|
|
1015
1218
|
is an internal builder and hands back a bare refer, so a marker
|
|
1016
1219
|
receiver would be dropped here and the result would never be lifted
|
|
1017
|
-
at the tail. Put it back on before the re-entry.
|
|
1018
|
-
|
|
1220
|
+
at the tail. Put it back on before the re-entry.
|
|
1221
|
+
|
|
1222
|
+
A Face is flattened through its storage and put on top once at the
|
|
1223
|
+
end; re-entering against the flattened Face would build the view on
|
|
1224
|
+
it and leave a Face in the middle of the chain (CAFace.md 8.3). */
|
|
1225
|
+
if ( ca_is_face(ca) ) {
|
|
1226
|
+
volatile VALUE flat =
|
|
1227
|
+
rb_ca_refer_new_flatten(rb_ca_strip_face_value(self));
|
|
1228
|
+
obj = rb_ca_fetch_method(argc, argv, flat);
|
|
1229
|
+
if ( rb_obj_is_kind_of(obj, rb_cCArray) ) {
|
|
1230
|
+
obj = ca_face_lift(obj, self);
|
|
1231
|
+
}
|
|
1232
|
+
return obj;
|
|
1233
|
+
}
|
|
1019
1234
|
self = rb_ca_refer_new_flatten(self);
|
|
1020
1235
|
if ( ca_is_lazy_marker(ca) ) {
|
|
1021
1236
|
extern VALUE rb_ca_lazy_marker_new (VALUE cary);
|
|
@@ -1053,8 +1268,10 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1053
1268
|
obj = rb_ca_grid(argc, argv, self);
|
|
1054
1269
|
break;
|
|
1055
1270
|
case CA_REG_METHOD_CALL: {
|
|
1271
|
+
/* a[:eq, 0] is a[a.eq(0)]: a public method of the array, as a call
|
|
1272
|
+
written out would reach (a[:puts] does not run Kernel#puts). */
|
|
1056
1273
|
volatile VALUE idx;
|
|
1057
|
-
idx =
|
|
1274
|
+
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1058
1275
|
obj = rb_ca_fetch(self, idx);
|
|
1059
1276
|
break;
|
|
1060
1277
|
}
|
|
@@ -1073,11 +1290,6 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1073
1290
|
}
|
|
1074
1291
|
break;
|
|
1075
1292
|
}
|
|
1076
|
-
case CA_REG_ATTRIBUTE: {
|
|
1077
|
-
obj = rb_funcall(self, rb_intern("attribute"), 0);
|
|
1078
|
-
obj = rb_hash_aref(obj, info.symbol);
|
|
1079
|
-
break;
|
|
1080
|
-
}
|
|
1081
1293
|
default:
|
|
1082
1294
|
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1083
1295
|
}
|
|
@@ -1121,7 +1333,7 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1121
1333
|
nunder++;
|
|
1122
1334
|
continue;
|
|
1123
1335
|
}
|
|
1124
|
-
if (
|
|
1336
|
+
if ( ca_index_key_is_scalar(a) ) {
|
|
1125
1337
|
nscalar++;
|
|
1126
1338
|
}
|
|
1127
1339
|
if ( a == sym_gt || a == sym_perc
|
|
@@ -1130,7 +1342,7 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1130
1342
|
"newaxis (:_) cannot be combined with :>, :%%, "
|
|
1131
1343
|
"or rubber dim (false / :~)");
|
|
1132
1344
|
}
|
|
1133
|
-
if ( nclean >= CA_RANK_MAX ) {
|
|
1345
|
+
if ( nclean >= CA_RANK_MAX ) { /* rank-check: a count of indices */
|
|
1134
1346
|
rb_raise(rb_eIndexError, "too many indices");
|
|
1135
1347
|
}
|
|
1136
1348
|
clean[nclean++] = a;
|
|
@@ -1168,21 +1380,40 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1168
1380
|
TypedData_Get_Struct(base, CArray, &carray_data_type, cb);
|
|
1169
1381
|
|
|
1170
1382
|
/* Reconstruct final shape: walk original argv. :_ -> size-1, scalar
|
|
1171
|
-
(Integer) -> dropped (skip), else -> base.dim[cursor].
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1383
|
+
(Integer) -> dropped (skip), else -> base.dim[cursor]. A key gives one
|
|
1384
|
+
axis, except an integer CArray read alone (a mapping), which gives as
|
|
1385
|
+
many as it has: the axes the base has beyond one per key are its. */
|
|
1386
|
+
{
|
|
1387
|
+
int nkeys = 0, extra, ncarray = 0;
|
|
1388
|
+
for (i = 0; i < nclean; i++) {
|
|
1389
|
+
if ( ! ca_index_key_is_scalar(clean[i]) ) {
|
|
1390
|
+
nkeys++;
|
|
1391
|
+
if ( rb_obj_is_carray(clean[i]) ) ncarray++;
|
|
1392
|
+
}
|
|
1180
1393
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1394
|
+
extra = cb->ndim - nkeys;
|
|
1395
|
+
base_cursor = ( extra != 0 && ncarray != 1 ) ? -1 : 0;
|
|
1396
|
+
for (i = 0; i < argc && base_cursor >= 0; i++) {
|
|
1397
|
+
VALUE a = argv[i];
|
|
1398
|
+
int take = 1, t;
|
|
1399
|
+
if ( a == sym_under ) {
|
|
1400
|
+
final_dims[nfinal++] = 1;
|
|
1401
|
+
continue;
|
|
1402
|
+
}
|
|
1403
|
+
if ( ca_index_key_is_scalar(a) ) {
|
|
1404
|
+
/* scalar index -> axis dropped in base; contributes no output axis */
|
|
1405
|
+
continue;
|
|
1406
|
+
}
|
|
1407
|
+
if ( rb_obj_is_carray(a) ) {
|
|
1408
|
+
take += extra;
|
|
1409
|
+
}
|
|
1410
|
+
for (t = 0; t < take; t++) {
|
|
1411
|
+
if ( base_cursor >= cb->ndim || nfinal >= CA_RANK_MAX ) { /* rank-check: a count of indices */
|
|
1412
|
+
base_cursor = -1;
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
final_dims[nfinal++] = cb->dim[base_cursor++];
|
|
1184
1416
|
}
|
|
1185
|
-
final_dims[nfinal++] = cb->dim[base_cursor++];
|
|
1186
1417
|
}
|
|
1187
1418
|
}
|
|
1188
1419
|
if ( base_cursor != cb->ndim ) {
|
|
@@ -1226,7 +1457,7 @@ rb_ca_slab_iter_new (VALUE self, CAIndexInfo *info)
|
|
|
1226
1457
|
align with the post-expansion ndim, replace :> with nil (full axis),
|
|
1227
1458
|
promote Integer to length-1 Range so the base view preserves ndim,
|
|
1228
1459
|
recurse through the regular indexer dispatch to build the base
|
|
1229
|
-
reference (CABlock / CASelectAxis / CAGrid /
|
|
1460
|
+
reference (CABlock / CASelectAxis / CAGrid / ...), then
|
|
1230
1461
|
wrap in CASlabIterator with the recorded slab_axes positions. */
|
|
1231
1462
|
static VALUE
|
|
1232
1463
|
rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
@@ -1280,7 +1511,7 @@ rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
|
1280
1511
|
eargv = expanded;
|
|
1281
1512
|
}
|
|
1282
1513
|
|
|
1283
|
-
if ( eargc > CA_RANK_MAX ) {
|
|
1514
|
+
if ( eargc > CA_RANK_MAX ) { /* rank-check: a count of indices */
|
|
1284
1515
|
rb_raise(rb_eIndexError, "too many indices");
|
|
1285
1516
|
}
|
|
1286
1517
|
|
|
@@ -1290,7 +1521,7 @@ rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
|
1290
1521
|
rb_ary_push(slab_axes, INT2NUM(i));
|
|
1291
1522
|
clean[i] = Qnil;
|
|
1292
1523
|
}
|
|
1293
|
-
else if (
|
|
1524
|
+
else if ( ca_index_key_is_scalar(a) ) {
|
|
1294
1525
|
/* Promote Integer to length-1 Range so the recursed view keeps
|
|
1295
1526
|
the axis (matches the existing :> dispatcher semantics where
|
|
1296
1527
|
scalars become length-1 BLOCKs via finalize_reg). */
|
|
@@ -1358,7 +1589,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1358
1589
|
break;
|
|
1359
1590
|
case CA_REG_METHOD_CALL: {
|
|
1360
1591
|
volatile VALUE idx;
|
|
1361
|
-
idx =
|
|
1592
|
+
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1362
1593
|
obj = rb_ca_fetch(self, idx);
|
|
1363
1594
|
break;
|
|
1364
1595
|
}
|
|
@@ -1374,11 +1605,6 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1374
1605
|
}
|
|
1375
1606
|
break;
|
|
1376
1607
|
}
|
|
1377
|
-
case CA_REG_ATTRIBUTE: {
|
|
1378
|
-
obj = rb_funcall(self, rb_intern("attribute"), 0);
|
|
1379
|
-
obj = rb_hash_aref(obj, info.symbol);
|
|
1380
|
-
break;
|
|
1381
|
-
}
|
|
1382
1608
|
default:
|
|
1383
1609
|
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1384
1610
|
}
|
|
@@ -1403,7 +1629,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1403
1629
|
of letting the storage cast truncate it, and the bulk path must not be
|
|
1404
1630
|
the looser door.
|
|
1405
1631
|
- an Array is mapped structure-preserving (leaves converted),
|
|
1406
|
-
- a scalar goes through the write hook (
|
|
1632
|
+
- a scalar goes through the write hook (ca_face_element_to_storage), which
|
|
1407
1633
|
leaves a bare Integer / String unchanged.
|
|
1408
1634
|
|
|
1409
1635
|
Idempotent: an already-converted Integer passes through, so re-running on
|
|
@@ -1414,25 +1640,59 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1414
1640
|
if ( rb_obj_is_carray(val) ) {
|
|
1415
1641
|
CArray *cval;
|
|
1416
1642
|
GetCArray(val, cval);
|
|
1643
|
+
/* An object array holding struct elements (a record array's
|
|
1644
|
+
to_type(:object)) goes in as its values, each through the write
|
|
1645
|
+
hook; masked cells come back as UNDEF and stay masked. */
|
|
1646
|
+
if ( ca->obj_type == CA_OBJ_RECORD && cval->data_type == CA_OBJECT ) {
|
|
1647
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1648
|
+
rb_funcall(val, rb_intern("to_a"), 0));
|
|
1649
|
+
}
|
|
1650
|
+
/* A CAString takes Strings. A text Face goes in as the CAString its
|
|
1651
|
+
to_string gives, and an object array as itself wrapped in a CAString,
|
|
1652
|
+
which checks every cell that is not masked; either keeps its shape,
|
|
1653
|
+
so it meets the shape rule of a store as an object array would. Any
|
|
1654
|
+
other array goes in as its values, each through the write hook. */
|
|
1655
|
+
if ( ca->obj_type == CA_OBJ_STRING && cval->obj_type != CA_OBJ_STRING ) {
|
|
1656
|
+
if ( ca_is_face(cval) && rb_respond_to(val, rb_intern("to_string")) ) {
|
|
1657
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1658
|
+
rb_funcall(val, rb_intern("to_string"), 0));
|
|
1659
|
+
}
|
|
1660
|
+
if ( ! ca_is_face(cval) && cval->data_type == CA_OBJECT ) {
|
|
1661
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1662
|
+
rb_funcall(rb_obj_class(self), rb_intern("wrap"), 1, val));
|
|
1663
|
+
}
|
|
1664
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1665
|
+
rb_funcall(val, rb_intern("to_a"), 0));
|
|
1666
|
+
}
|
|
1417
1667
|
/* Face RHS: reconcile to self's unit and descend to storage. Mirror of
|
|
1418
|
-
the scalar path (
|
|
1668
|
+
the scalar path (ca_face_element_to_storage) for a bulk CArray source.
|
|
1419
1669
|
Guarded on self having to_comparable so a Face without a reconcile
|
|
1420
1670
|
algebra (e.g. a fixlen-storage Face, whose same-storage store already
|
|
1421
1671
|
takes the storage xfer branch) is left to the existing store path. */
|
|
1422
1672
|
if ( ca_is_face(cval) && rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1673
|
+
return ca_face_reconcile_operand(self, val, "[]=");
|
|
1674
|
+
}
|
|
1675
|
+
/* A Face of the same class and a compatible state holds values of the
|
|
1676
|
+
same kind in the same encoding: it goes in as its storage. */
|
|
1677
|
+
if ( ca_is_face(cval) && rb_obj_class(val) == rb_obj_class(self)
|
|
1678
|
+
&& ca_face_state_compatible(self, ca, val, cval) ) {
|
|
1679
|
+
return rb_ca_strip_face_value(val);
|
|
1426
1680
|
}
|
|
1427
1681
|
/* Bare storage escape, integer storage: integer cells only (see above). */
|
|
1428
1682
|
{
|
|
1429
1683
|
CArray *storage = ca_strip_face(ca);
|
|
1430
1684
|
if ( storage && ca_is_integer_type(storage) && ! ca_is_integer_type(cval) ) {
|
|
1685
|
+
const char *method = ca_face_storage_method(self);
|
|
1686
|
+
if ( method ) {
|
|
1687
|
+
rb_raise(rb_eTypeError,
|
|
1688
|
+
"%s cannot store a bare %s array as raw storage "
|
|
1689
|
+
"(write the %s storage, which #%s gives, directly)",
|
|
1690
|
+
rb_obj_classname(self), ca_type_name[cval->data_type],
|
|
1691
|
+
ca_type_name[storage->data_type], method);
|
|
1692
|
+
}
|
|
1431
1693
|
rb_raise(rb_eTypeError,
|
|
1432
|
-
"%s cannot store a bare %s array as raw storage
|
|
1433
|
-
|
|
1434
|
-
rb_obj_classname(self), ca_type_name[cval->data_type],
|
|
1435
|
-
ca_type_name[storage->data_type]);
|
|
1694
|
+
"%s cannot store a bare %s array as raw storage",
|
|
1695
|
+
rb_obj_classname(self), ca_type_name[cval->data_type]);
|
|
1436
1696
|
}
|
|
1437
1697
|
}
|
|
1438
1698
|
return val;
|
|
@@ -1445,15 +1705,16 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1445
1705
|
}
|
|
1446
1706
|
return out;
|
|
1447
1707
|
}
|
|
1448
|
-
return
|
|
1708
|
+
return ca_face_element_to_storage(self, ca, val);
|
|
1449
1709
|
}
|
|
1450
1710
|
|
|
1451
1711
|
static VALUE
|
|
1452
1712
|
rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
1453
1713
|
{
|
|
1454
|
-
volatile VALUE obj = Qnil, rval;
|
|
1714
|
+
volatile VALUE obj = Qnil, rval, dest;
|
|
1455
1715
|
CArray *ca;
|
|
1456
1716
|
CAIndexInfo info;
|
|
1717
|
+
int converted = 0; /* rval has been through the Face's write hook */
|
|
1457
1718
|
|
|
1458
1719
|
rb_ca_modify(self);
|
|
1459
1720
|
|
|
@@ -1463,18 +1724,37 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1463
1724
|
retry:
|
|
1464
1725
|
|
|
1465
1726
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1727
|
+
rval = ca_face_source_for_store(self, ca, rval);
|
|
1466
1728
|
|
|
1467
1729
|
/* Face store: bring a surface value object (Scalar / Time / DateTime) into
|
|
1468
1730
|
the storage domain while self is still the Face. Store-side views strip
|
|
1469
1731
|
the Face to storage, so this is the only point that sees it. */
|
|
1470
1732
|
if ( ca_is_face(ca) ) {
|
|
1471
|
-
|
|
1733
|
+
/* Once: a retry below comes back here with rval already converted. */
|
|
1734
|
+
if ( ! converted ) {
|
|
1735
|
+
rval = ca_face_convert_store_rval(self, ca, rval);
|
|
1736
|
+
converted = 1;
|
|
1737
|
+
}
|
|
1738
|
+
/* A CArray source is storage now, so the destination has to be too.
|
|
1739
|
+
A block store descends on its own (its view is built on the storage);
|
|
1740
|
+
a whole, boolean or address store kept the Face and cast the storage
|
|
1741
|
+
to the Face's surface type, which an int64 tick cannot become. A Face
|
|
1742
|
+
whose surface type is its storage's (a string or record Face) needs
|
|
1743
|
+
no descent, and keeps its own index forms (a record's field name). */
|
|
1744
|
+
if ( rb_obj_is_carray(rval) ) {
|
|
1745
|
+
CArray *cr;
|
|
1746
|
+
GetCArray(rval, cr);
|
|
1747
|
+
if ( ! ca_is_face(cr) && ca_strip_face(ca)->data_type != ca->data_type ) {
|
|
1748
|
+
self = rb_ca_strip_face_value(self);
|
|
1749
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1472
1752
|
}
|
|
1473
1753
|
|
|
1474
1754
|
/* newaxis (:_) interception on store. Build the newaxis view (a
|
|
1475
1755
|
writable reshape aliasing self), then assign rval into the whole view
|
|
1476
1756
|
(writes propagate to self). */
|
|
1477
|
-
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
1757
|
+
if ( ! ca_argv_is_method_call(argc, argv) && ca_argv_has_newaxis(argc, argv) ) {
|
|
1478
1758
|
volatile VALUE view = rb_ca_fetch_newaxis(argc, argv, self, ca);
|
|
1479
1759
|
rb_ca_store_all(view, rval);
|
|
1480
1760
|
return rval;
|
|
@@ -1483,7 +1763,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1483
1763
|
/* slab sigil on store is rejected regardless of outer-slot type. Catch
|
|
1484
1764
|
:> before scan_index so mask/fancy outer slots get the same "not
|
|
1485
1765
|
supported" message instead of a misleading TypeError. */
|
|
1486
|
-
if ( ca_argv_has_slab_sigil(argc, argv) ) {
|
|
1766
|
+
if ( ! ca_argv_is_method_call(argc, argv) && ca_argv_has_slab_sigil(argc, argv) ) {
|
|
1487
1767
|
rb_raise(rb_eIndexError,
|
|
1488
1768
|
"assignment through a slab iterator (:>) is not supported "
|
|
1489
1769
|
"(use a block index, e.g. ca[range, nil] = val, or each_slab)");
|
|
@@ -1492,31 +1772,50 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1492
1772
|
info.range_check = 1;
|
|
1493
1773
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1494
1774
|
|
|
1775
|
+
/* A value or a Ruby Array converted above is in the storage domain now.
|
|
1776
|
+
Stored through the Face it would meet the write hook a second time
|
|
1777
|
+
(rb_ca_obj2ptr converts too), so a positional store goes into the
|
|
1778
|
+
storage, which has the Face's shape. A predicate (:sym) is still
|
|
1779
|
+
asked of the Face; a member store keeps the Face for its data_class. */
|
|
1780
|
+
dest = self;
|
|
1781
|
+
if ( converted && ca_is_face(ca) && ! rb_obj_is_carray(rval) ) {
|
|
1782
|
+
dest = rb_ca_strip_face_value(self);
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
/* One cell of a CAString holds a String. Stored into the object storage,
|
|
1786
|
+
a Ruby Array would become the cell's value, which a plain object array
|
|
1787
|
+
allows. */
|
|
1788
|
+
if ( ca->obj_type == CA_OBJ_STRING && TYPE(rval) == T_ARRAY &&
|
|
1789
|
+
( info.type == CA_REG_ADDRESS || info.type == CA_REG_POINT ) ) {
|
|
1790
|
+
rb_raise(rb_eTypeError,
|
|
1791
|
+
"%s: an Array is not a String (one cell of a CAString holds "
|
|
1792
|
+
"a String; UNDEF masks a cell)", ca_calling_method_name());
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1495
1795
|
switch ( info.type ) {
|
|
1496
1796
|
case CA_REG_ADDRESS_COMPLEX:
|
|
1497
1797
|
self = rb_ca_refer_new_flatten(self);
|
|
1498
1798
|
goto retry;
|
|
1499
1799
|
case CA_REG_ADDRESS:
|
|
1500
|
-
obj = rb_ca_store_address(
|
|
1800
|
+
obj = rb_ca_store_address(dest, &info, rval);
|
|
1501
1801
|
break;
|
|
1502
1802
|
case CA_REG_FLATTEN:
|
|
1503
|
-
|
|
1504
|
-
obj = rb_ca_store_all(self, rval);
|
|
1803
|
+
obj = rb_ca_store_all(rb_ca_refer_new_flatten(dest), rval);
|
|
1505
1804
|
break;
|
|
1506
1805
|
case CA_REG_POINT:
|
|
1507
|
-
obj = rb_ca_store_point(
|
|
1806
|
+
obj = rb_ca_store_point(dest, &info, rval);
|
|
1508
1807
|
break;
|
|
1509
1808
|
case CA_REG_ALL:
|
|
1510
|
-
obj = rb_ca_store_all(
|
|
1809
|
+
obj = rb_ca_store_all(dest, rval);
|
|
1511
1810
|
break;
|
|
1512
1811
|
case CA_REG_BLOCK: {
|
|
1513
1812
|
volatile VALUE block;
|
|
1514
|
-
block = rb_ca_ref_block(
|
|
1813
|
+
block = rb_ca_ref_block(dest, &info);
|
|
1515
1814
|
obj = rb_ca_store_all(block, rval);
|
|
1516
1815
|
break;
|
|
1517
1816
|
}
|
|
1518
1817
|
case CA_REG_SELECT: {
|
|
1519
|
-
obj = rb_ca_select_new(
|
|
1818
|
+
obj = rb_ca_select_new(dest, argv[0]);
|
|
1520
1819
|
obj = rb_ca_store_all(obj, rval);
|
|
1521
1820
|
break;
|
|
1522
1821
|
}
|
|
@@ -1529,27 +1828,27 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1529
1828
|
break;
|
|
1530
1829
|
}
|
|
1531
1830
|
case CA_REG_REPEAT: {
|
|
1532
|
-
obj = rb_ca_repeat(argc, argv,
|
|
1831
|
+
obj = rb_ca_repeat(argc, argv, dest);
|
|
1533
1832
|
obj = rb_ca_store_all(obj, rval);
|
|
1534
1833
|
break;
|
|
1535
1834
|
}
|
|
1536
1835
|
case CA_REG_MAPPING: {
|
|
1537
|
-
obj = rb_ca_fancy_index_chain(
|
|
1836
|
+
obj = rb_ca_fancy_index_chain(dest, argv[0]);
|
|
1538
1837
|
obj = rb_ca_store_all(obj, rval);
|
|
1539
1838
|
break;
|
|
1540
1839
|
}
|
|
1541
1840
|
case CA_REG_GRID: {
|
|
1542
|
-
obj = rb_ca_grid(argc, argv,
|
|
1841
|
+
obj = rb_ca_grid(argc, argv, dest);
|
|
1543
1842
|
obj = rb_ca_store_all(obj, rval);
|
|
1544
1843
|
break;
|
|
1545
1844
|
}
|
|
1546
1845
|
case CA_REG_METHOD_CALL: {
|
|
1846
|
+
/* a[:eq, 0] = v is a[a.eq(0)] = v: the index is computed first and the
|
|
1847
|
+
store then goes through it, as the read does -- only the cells it
|
|
1848
|
+
picks are written. */
|
|
1547
1849
|
volatile VALUE idx;
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
idx = rb_funcall2(self, SYM2ID(info.symbol), (int)(argc-1), argv+1);
|
|
1551
|
-
obj = rb_ca_store(self, idx, rval);
|
|
1552
|
-
ca_detach(ca);
|
|
1850
|
+
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1851
|
+
obj = rb_ca_store(dest, idx, rval);
|
|
1553
1852
|
break;
|
|
1554
1853
|
}
|
|
1555
1854
|
case CA_REG_MEMBER: {
|
|
@@ -1564,11 +1863,6 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1564
1863
|
}
|
|
1565
1864
|
break;
|
|
1566
1865
|
}
|
|
1567
|
-
case CA_REG_ATTRIBUTE: {
|
|
1568
|
-
obj = rb_funcall(self, rb_intern("attribute"), 0);
|
|
1569
|
-
obj = rb_hash_aset(obj, info.symbol, rval);
|
|
1570
|
-
break;
|
|
1571
|
-
}
|
|
1572
1866
|
}
|
|
1573
1867
|
|
|
1574
1868
|
return obj;
|
|
@@ -1598,7 +1892,9 @@ rb_ca_store (VALUE self, VALUE index, VALUE rval)
|
|
|
1598
1892
|
case T_ARRAY:
|
|
1599
1893
|
index = rb_obj_clone(index);
|
|
1600
1894
|
rb_ary_push(index, rval);
|
|
1601
|
-
|
|
1895
|
+
rval = rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1896
|
+
RB_GC_GUARD(index); /* the store reads its arguments out of index */
|
|
1897
|
+
return rval;
|
|
1602
1898
|
default: {
|
|
1603
1899
|
VALUE rindex[2] = { index, rval };
|
|
1604
1900
|
return rb_ca_store_method(2, rindex, self);
|
|
@@ -1611,7 +1907,9 @@ rb_ca_store2 (VALUE self, int n, VALUE *rindex, VALUE rval)
|
|
|
1611
1907
|
{
|
|
1612
1908
|
volatile VALUE index = rb_ary_new4(n, rindex);
|
|
1613
1909
|
rb_ary_push(index, rval);
|
|
1614
|
-
|
|
1910
|
+
rval = rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1911
|
+
RB_GC_GUARD(index); /* the store reads its arguments out of index */
|
|
1912
|
+
return rval;
|
|
1615
1913
|
}
|
|
1616
1914
|
|
|
1617
1915
|
static VALUE
|
|
@@ -1627,15 +1925,13 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1627
1925
|
Check_Type(rdim, T_ARRAY);
|
|
1628
1926
|
Check_Type(ridx, T_ARRAY);
|
|
1629
1927
|
|
|
1630
|
-
elements = 1;
|
|
1631
1928
|
ndim = (int) RARRAY_LEN(rdim);
|
|
1929
|
+
CA_CHECK_RANK_GIVEN(ndim);
|
|
1632
1930
|
for (i=0; i<ndim; i++) {
|
|
1633
1931
|
dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
1634
|
-
elements *= dim[i];
|
|
1635
1932
|
}
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
CA_CHECK_DIM(ndim, dim);
|
|
1933
|
+
CA_CHECK_DIM_GIVEN(ndim, dim);
|
|
1934
|
+
elements = ca_shape_elements(ndim, dim, 1);
|
|
1639
1935
|
|
|
1640
1936
|
info.range_check = 1;
|
|
1641
1937
|
rb_ca_scan_index(ndim, dim, elements,
|
|
@@ -1699,7 +1995,7 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1699
1995
|
info.index[i].symbol.spec));
|
|
1700
1996
|
break;
|
|
1701
1997
|
default:
|
|
1702
|
-
rb_raise(
|
|
1998
|
+
rb_raise(rb_eIndexError, "unknown index spec");
|
|
1703
1999
|
}
|
|
1704
2000
|
}
|
|
1705
2001
|
break;
|
|
@@ -1707,8 +2003,7 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1707
2003
|
case CA_REG_GRID:
|
|
1708
2004
|
case CA_REG_MAPPING:
|
|
1709
2005
|
case CA_REG_METHOD_CALL:
|
|
1710
|
-
case CA_REG_MEMBER:
|
|
1711
|
-
case CA_REG_ATTRIBUTE:
|
|
2006
|
+
case CA_REG_MEMBER:
|
|
1712
2007
|
break;
|
|
1713
2008
|
default:
|
|
1714
2009
|
rb_raise(rb_eArgError, "unknown index specification");
|
|
@@ -1767,7 +2062,7 @@ rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
|
1767
2062
|
rb_ary_store(rindex, i, ID2SYM(info.index[i].symbol.id));
|
|
1768
2063
|
break;
|
|
1769
2064
|
default:
|
|
1770
|
-
rb_raise(
|
|
2065
|
+
rb_raise(rb_eIndexError, "unknown index spec");
|
|
1771
2066
|
}
|
|
1772
2067
|
}
|
|
1773
2068
|
return rindex;
|
|
@@ -1804,18 +2099,19 @@ parse_shape_kwarg (VALUE rshape, int *out_ndim, ca_size_t *dim,
|
|
|
1804
2099
|
|
|
1805
2100
|
Check_Type(rshape, T_ARRAY);
|
|
1806
2101
|
ndim = (int) RARRAY_LEN(rshape);
|
|
1807
|
-
if ( ndim < 1
|
|
2102
|
+
if ( ndim < 1 ) {
|
|
1808
2103
|
rb_raise(rb_eArgError, "invalid shape ndim %d (must be 1..%d)",
|
|
1809
2104
|
ndim, CA_RANK_MAX);
|
|
1810
2105
|
}
|
|
2106
|
+
ca_check_rank_fits(ndim, NULL);
|
|
1811
2107
|
for (i = 0; i < ndim; i++) {
|
|
1812
2108
|
dim[i] = NUM2SIZE(rb_ary_entry(rshape, i));
|
|
1813
2109
|
if ( dim[i] < 0 ) {
|
|
1814
2110
|
rb_raise(rb_eArgError, "negative dim %" PRId64 " at axis %d",
|
|
1815
2111
|
(ca_size_t) dim[i], i);
|
|
1816
2112
|
}
|
|
1817
|
-
elements *= dim[i];
|
|
1818
2113
|
}
|
|
2114
|
+
elements = ca_shape_elements(ndim, dim, 1);
|
|
1819
2115
|
*out_ndim = ndim;
|
|
1820
2116
|
*out_elements = elements;
|
|
1821
2117
|
}
|
|
@@ -1829,12 +2125,7 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1829
2125
|
/* Scalar path (Integer input): returns Ruby Array of N Integers.
|
|
1830
2126
|
* Preserves legacy shape for callers like `i, j = ca.addr2index(k)`. */
|
|
1831
2127
|
if ( rb_obj_is_kind_of(raddr, rb_cInteger) ) {
|
|
1832
|
-
ca_size_t addr = NUM2SIZE(raddr);
|
|
1833
|
-
if ( addr < 0 || addr >= elements ) {
|
|
1834
|
-
rb_raise(rb_eArgError,
|
|
1835
|
-
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1836
|
-
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
1837
|
-
}
|
|
2128
|
+
ca_size_t addr = ca_index_in_range(NUM2SIZE(raddr), elements, "address");
|
|
1838
2129
|
out = rb_ary_new2(ndim);
|
|
1839
2130
|
for (i = ndim - 1; i >= 0; i--) {
|
|
1840
2131
|
rb_ary_store(out, i, SIZE2NUM(addr % dim[i]));
|
|
@@ -1852,8 +2143,9 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1852
2143
|
ca_size_t j, n;
|
|
1853
2144
|
volatile VALUE objs[CA_RANK_MAX];
|
|
1854
2145
|
|
|
2146
|
+
ca_check_index_array(raddr);
|
|
1855
2147
|
cin = ca_wrap_readonly(raddr, CA_SIZE);
|
|
1856
|
-
ca_attach(cin);
|
|
2148
|
+
ca_attach(cin); /* window: detached before its one raise */
|
|
1857
2149
|
|
|
1858
2150
|
out = rb_ary_new2(ndim);
|
|
1859
2151
|
for (i = 0; i < ndim; i++) {
|
|
@@ -1882,12 +2174,11 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1882
2174
|
continue;
|
|
1883
2175
|
}
|
|
1884
2176
|
addr = src[j];
|
|
1885
|
-
if ( addr <
|
|
2177
|
+
if ( addr < -elements || addr >= elements ) {
|
|
1886
2178
|
ca_detach(cin);
|
|
1887
|
-
|
|
1888
|
-
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1889
|
-
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
2179
|
+
ca_index_out_of_range(addr, elements, "address");
|
|
1890
2180
|
}
|
|
2181
|
+
addr = ca_index_in_range(addr, elements, "address");
|
|
1891
2182
|
for (k = ndim - 1; k >= 0; k--) {
|
|
1892
2183
|
p_out[k][j] = addr % dim[k];
|
|
1893
2184
|
addr /= dim[k];
|
|
@@ -1896,18 +2187,92 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1896
2187
|
}
|
|
1897
2188
|
|
|
1898
2189
|
ca_detach(cin);
|
|
2190
|
+
RB_GC_GUARD(raddr); /* the CA_SIZE view is reached only through cin */
|
|
1899
2191
|
return out;
|
|
1900
2192
|
}
|
|
1901
2193
|
}
|
|
1902
2194
|
|
|
2195
|
+
/* The vector path of index2addr reads every index array inside one
|
|
2196
|
+
window: an index out of range raises part way through. */
|
|
2197
|
+
|
|
2198
|
+
typedef struct {
|
|
2199
|
+
int ndim;
|
|
2200
|
+
ca_size_t *dim;
|
|
2201
|
+
CArray **cidx;
|
|
2202
|
+
int out_ndim;
|
|
2203
|
+
ca_size_t *out_dim;
|
|
2204
|
+
ca_size_t out_elements;
|
|
2205
|
+
} ca_index2addr_ctx_t;
|
|
2206
|
+
|
|
1903
2207
|
static VALUE
|
|
1904
|
-
|
|
2208
|
+
ca_index2addr_body (VALUE arg)
|
|
1905
2209
|
{
|
|
2210
|
+
ca_index2addr_ctx_t *c = (ca_index2addr_ctx_t *) arg;
|
|
2211
|
+
int ndim = c->ndim;
|
|
2212
|
+
ca_size_t *dim = c->dim;
|
|
2213
|
+
CArray **cidx = c->cidx;
|
|
2214
|
+
ca_size_t out_elements = c->out_elements;
|
|
1906
2215
|
volatile VALUE obj;
|
|
1907
|
-
CArray *co
|
|
2216
|
+
CArray *co;
|
|
1908
2217
|
ca_size_t *q, *p[CA_RANK_MAX], s[CA_RANK_MAX];
|
|
1909
2218
|
ca_size_t addr, k, n;
|
|
1910
2219
|
boolean8_t *m;
|
|
2220
|
+
int i;
|
|
2221
|
+
|
|
2222
|
+
for (i = 0; i < ndim; i++) {
|
|
2223
|
+
ca_set_iterator(1, cidx[i], &p[i], &s[i]);
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
obj = rb_carray_new(CA_SIZE, c->out_ndim, c->out_dim, 0, NULL);
|
|
2227
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
|
|
2228
|
+
|
|
2229
|
+
q = (ca_size_t *) co->ptr;
|
|
2230
|
+
|
|
2231
|
+
ca_copy_mask_overwrite_n(co, out_elements, ndim, cidx);
|
|
2232
|
+
m = ( co->mask ) ? (boolean8_t *) co->mask->ptr : NULL;
|
|
2233
|
+
|
|
2234
|
+
if ( m ) {
|
|
2235
|
+
n = out_elements;
|
|
2236
|
+
while ( n-- ) {
|
|
2237
|
+
if ( ! *m ) {
|
|
2238
|
+
addr = 0;
|
|
2239
|
+
for (i = 0; i < ndim; i++) {
|
|
2240
|
+
k = *(p[i]);
|
|
2241
|
+
p[i] += s[i];
|
|
2242
|
+
CA_CHECK_INDEX(k, dim[i]);
|
|
2243
|
+
addr = dim[i] * addr + k;
|
|
2244
|
+
}
|
|
2245
|
+
*q = addr;
|
|
2246
|
+
}
|
|
2247
|
+
else {
|
|
2248
|
+
for (i = 0; i < ndim; i++) { p[i] += s[i]; }
|
|
2249
|
+
}
|
|
2250
|
+
m++; q++;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
else {
|
|
2254
|
+
n = out_elements;
|
|
2255
|
+
while ( n-- ) {
|
|
2256
|
+
addr = 0;
|
|
2257
|
+
for (i = 0; i < ndim; i++) {
|
|
2258
|
+
k = *(p[i]);
|
|
2259
|
+
p[i] += s[i];
|
|
2260
|
+
CA_CHECK_INDEX(k, dim[i]);
|
|
2261
|
+
addr = dim[i] * addr + k;
|
|
2262
|
+
}
|
|
2263
|
+
*q = addr;
|
|
2264
|
+
q++;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
return obj;
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
static VALUE
|
|
2272
|
+
index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
2273
|
+
{
|
|
2274
|
+
CArray *cidx[CA_RANK_MAX];
|
|
2275
|
+
ca_size_t addr, k;
|
|
1911
2276
|
int i, all_number = 1;
|
|
1912
2277
|
int out_ndim = 1;
|
|
1913
2278
|
ca_size_t out_dim[CA_RANK_MAX];
|
|
@@ -1941,6 +2306,7 @@ index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
|
1941
2306
|
* the first non-scalar CArray input; other non-scalar inputs must
|
|
1942
2307
|
* match that shape. */
|
|
1943
2308
|
for (i = 0; i < ndim; i++) {
|
|
2309
|
+
ca_check_index_array(argv[i]);
|
|
1944
2310
|
cidx[i] = ca_wrap_readonly(argv[i], CA_SIZE);
|
|
1945
2311
|
if ( ! ca_is_scalar(cidx[i]) ) {
|
|
1946
2312
|
if ( shape_from < 0 ) {
|
|
@@ -1969,56 +2335,19 @@ index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
|
1969
2335
|
}
|
|
1970
2336
|
}
|
|
1971
2337
|
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
if ( m ) {
|
|
1986
|
-
n = out_elements;
|
|
1987
|
-
while ( n-- ) {
|
|
1988
|
-
if ( ! *m ) {
|
|
1989
|
-
addr = 0;
|
|
1990
|
-
for (i = 0; i < ndim; i++) {
|
|
1991
|
-
k = *(p[i]);
|
|
1992
|
-
p[i] += s[i];
|
|
1993
|
-
CA_CHECK_INDEX(k, dim[i]);
|
|
1994
|
-
addr = dim[i] * addr + k;
|
|
1995
|
-
}
|
|
1996
|
-
*q = addr;
|
|
1997
|
-
}
|
|
1998
|
-
else {
|
|
1999
|
-
for (i = 0; i < ndim; i++) { p[i] += s[i]; }
|
|
2000
|
-
}
|
|
2001
|
-
m++; q++;
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
else {
|
|
2005
|
-
n = out_elements;
|
|
2006
|
-
while ( n-- ) {
|
|
2007
|
-
addr = 0;
|
|
2008
|
-
for (i = 0; i < ndim; i++) {
|
|
2009
|
-
k = *(p[i]);
|
|
2010
|
-
p[i] += s[i];
|
|
2011
|
-
CA_CHECK_INDEX(k, dim[i]);
|
|
2012
|
-
addr = dim[i] * addr + k;
|
|
2013
|
-
}
|
|
2014
|
-
*q = addr;
|
|
2015
|
-
q++;
|
|
2016
|
-
}
|
|
2338
|
+
{
|
|
2339
|
+
ca_index2addr_ctx_t c;
|
|
2340
|
+
char modes[CA_RANK_MAX + 1];
|
|
2341
|
+
memset(modes, 'r', (size_t) ndim);
|
|
2342
|
+
modes[ndim] = '\0';
|
|
2343
|
+
c.ndim = ndim;
|
|
2344
|
+
c.dim = dim;
|
|
2345
|
+
c.cidx = cidx;
|
|
2346
|
+
c.out_ndim = out_ndim;
|
|
2347
|
+
c.out_dim = out_dim;
|
|
2348
|
+
c.out_elements = out_elements;
|
|
2349
|
+
return ca_attach_window(ndim, cidx, modes, ca_index2addr_body, (VALUE) &c);
|
|
2017
2350
|
}
|
|
2018
|
-
|
|
2019
|
-
for (i = 0; i < ndim; i++) { ca_detach(cidx[i]); }
|
|
2020
|
-
|
|
2021
|
-
return obj;
|
|
2022
2351
|
}
|
|
2023
2352
|
|
|
2024
2353
|
VALUE
|
|
@@ -2062,7 +2391,7 @@ rb_ca_s_addr2index (int argc, VALUE *argv, VALUE klass)
|
|
|
2062
2391
|
static VALUE
|
|
2063
2392
|
rb_ca_s_index2addr (int argc, VALUE *argv, VALUE klass)
|
|
2064
2393
|
{
|
|
2065
|
-
VALUE rest, opts;
|
|
2394
|
+
VALUE rest, opts, out;
|
|
2066
2395
|
ID kw_ids[1];
|
|
2067
2396
|
VALUE kw_vals[1];
|
|
2068
2397
|
int ndim;
|
|
@@ -2076,7 +2405,10 @@ rb_ca_s_index2addr (int argc, VALUE *argv, VALUE klass)
|
|
|
2076
2405
|
}
|
|
2077
2406
|
rb_get_kwargs(opts, kw_ids, 1, 0, kw_vals);
|
|
2078
2407
|
parse_shape_kwarg(kw_vals[0], &ndim, dim, &elements);
|
|
2079
|
-
|
|
2408
|
+
/* index2addr_do reads, and replaces, its arguments in rest */
|
|
2409
|
+
out = index2addr_do(ndim, dim, (int) RARRAY_LEN(rest), RARRAY_PTR(rest));
|
|
2410
|
+
RB_GC_GUARD(rest);
|
|
2411
|
+
return out;
|
|
2080
2412
|
}
|
|
2081
2413
|
|
|
2082
2414
|
|