carray 3.0.1 → 3.0.3
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 +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -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_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/carray_access.c
CHANGED
|
@@ -19,7 +19,7 @@ static ID id_begin, id_end, id_excl_end;
|
|
|
19
19
|
#define RANGE_EXCL(r) (rb_funcall(r, id_excl_end, 0))
|
|
20
20
|
|
|
21
21
|
static ID id_to_ca;
|
|
22
|
-
static VALUE
|
|
22
|
+
static VALUE sym_perc, sym_under, sym_gt, sym_tilde;
|
|
23
23
|
static VALUE S_CAInfo;
|
|
24
24
|
|
|
25
25
|
VALUE
|
|
@@ -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
79
|
out = rb_ca_ptr2obj(self, v);
|
|
91
|
-
|
|
80
|
+
ALLOCV_END(holder);
|
|
92
81
|
}
|
|
93
82
|
|
|
94
83
|
/* check if the element is masked */
|
|
@@ -101,8 +90,8 @@ 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
|
(to_a / cast / serialize via rb_ca_ptr2obj) keep 0/1. Gate on the raw
|
|
@@ -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
161
|
out = rb_ca_ptr2obj(self, v);
|
|
184
|
-
|
|
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;
|
|
@@ -254,7 +230,7 @@ ary_guess_shape (VALUE ary, int level, int *max_level, ca_size_t *dim)
|
|
|
254
230
|
{
|
|
255
231
|
volatile VALUE ary0;
|
|
256
232
|
if ( level > CA_RANK_MAX ) {
|
|
257
|
-
rb_raise(
|
|
233
|
+
rb_raise(rb_eArgError, "too deep level array for conversion to carray");
|
|
258
234
|
}
|
|
259
235
|
|
|
260
236
|
if ( TYPE(ary) == T_ARRAY ) {
|
|
@@ -304,7 +280,7 @@ ary_flatten_upto_level (VALUE ary, int max_level, int level,
|
|
|
304
280
|
int32_t i;
|
|
305
281
|
|
|
306
282
|
if ( TYPE(ary) != T_ARRAY ) {
|
|
307
|
-
rb_raise(
|
|
283
|
+
rb_raise(rb_eArgError, "invalid shape array for conversion to carray");
|
|
308
284
|
}
|
|
309
285
|
|
|
310
286
|
if ( level == max_level ) {
|
|
@@ -321,7 +297,7 @@ ary_flatten_upto_level (VALUE ary, int max_level, int level,
|
|
|
321
297
|
}
|
|
322
298
|
}
|
|
323
299
|
|
|
324
|
-
|
|
300
|
+
VALUE
|
|
325
301
|
rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
326
302
|
{
|
|
327
303
|
CArray *ca = (CArray *) ap;
|
|
@@ -348,7 +324,7 @@ rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
|
348
324
|
}
|
|
349
325
|
|
|
350
326
|
if ( total != ca->elements ) {
|
|
351
|
-
rb_raise(
|
|
327
|
+
rb_raise(rb_eArgError, "invalid shape array for conversion to carray");
|
|
352
328
|
}
|
|
353
329
|
else {
|
|
354
330
|
volatile VALUE out = rb_ary_new2(0);
|
|
@@ -500,6 +476,184 @@ ca_id_expression_evaluator (void)
|
|
|
500
476
|
return id;
|
|
501
477
|
}
|
|
502
478
|
|
|
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
|
+
/* The casting stores below convert into the destination inside a window,
|
|
500
|
+
and a conversion from Ruby objects can raise part way. Such a window
|
|
501
|
+
attaches rather than allocates: the cells converted before the raise
|
|
502
|
+
are then pushed back with the others left as they were -- what an
|
|
503
|
+
entity destination, which has no separate buffer, shows as well. A
|
|
504
|
+
cast that cannot raise keeps the cheaper allocate. */
|
|
505
|
+
|
|
506
|
+
typedef struct {
|
|
507
|
+
CArray *ca;
|
|
508
|
+
CArray *cv; /* CArray source, delivered into scratch */
|
|
509
|
+
char *scratch;
|
|
510
|
+
boolean8_t *mscratch; /* cv's mask, or NULL when it has none */
|
|
511
|
+
CArray *ico; /* Ruby Array source: an object descriptor */
|
|
512
|
+
volatile VALUE list;
|
|
513
|
+
int has_mask;
|
|
514
|
+
} ca_store_all_ctx_t;
|
|
515
|
+
|
|
516
|
+
static const char *
|
|
517
|
+
ca_store_all_mode (CArray *cv)
|
|
518
|
+
{
|
|
519
|
+
return ( cv->data_type == CA_OBJECT ) ? "w" : "a";
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/* The window has attached ca's mask, and the one created here joins it,
|
|
523
|
+
so the mask is written in its buffer. */
|
|
524
|
+
static VALUE
|
|
525
|
+
ca_store_all_cast_body (VALUE arg)
|
|
526
|
+
{
|
|
527
|
+
ca_store_all_ctx_t *c = (ca_store_all_ctx_t *) arg;
|
|
528
|
+
CArray *ca = c->ca;
|
|
529
|
+
if ( c->mscratch ) {
|
|
530
|
+
if ( ! ca->mask ) {
|
|
531
|
+
ca_create_mask(ca);
|
|
532
|
+
}
|
|
533
|
+
memcpy(ca->mask->ptr, c->mscratch, ca->elements);
|
|
534
|
+
}
|
|
535
|
+
else if ( ca->mask ) {
|
|
536
|
+
memset(ca->mask->ptr, 0, ca->elements);
|
|
537
|
+
}
|
|
538
|
+
if ( ca->mask ) {
|
|
539
|
+
ca_cast_block_with_mask(ca->elements, c->cv, c->scratch, ca, ca->ptr,
|
|
540
|
+
(boolean8_t*)ca->mask->ptr);
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
ca_cast_block(ca->elements, c->cv, c->scratch, ca, ca->ptr);
|
|
544
|
+
}
|
|
545
|
+
return Qnil;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
static VALUE
|
|
549
|
+
ca_store_all_list_body (VALUE arg)
|
|
550
|
+
{
|
|
551
|
+
ca_store_all_ctx_t *c = (ca_store_all_ctx_t *) arg;
|
|
552
|
+
CArray *ca = c->ca;
|
|
553
|
+
VALUE list = c->list;
|
|
554
|
+
ca_size_t i;
|
|
555
|
+
/* Face has surface != storage; the cast runs in the storage
|
|
556
|
+
data_type. Passing ca directly makes the cast table see FIXLEN
|
|
557
|
+
and report non-implemented, so pass a shadow CArray (storage
|
|
558
|
+
data_type, ptr aliased to ca). */
|
|
559
|
+
CArray shadow;
|
|
560
|
+
CArray *cast_target = ca;
|
|
561
|
+
memset(&shadow, 0, sizeof(CArray));
|
|
562
|
+
if ( ca_is_face(ca) ) {
|
|
563
|
+
CArray *root = ca_strip_face(ca);
|
|
564
|
+
if (root) {
|
|
565
|
+
shadow.data_type = root->data_type;
|
|
566
|
+
shadow.bytes = ca->bytes;
|
|
567
|
+
shadow.elements = ca->elements;
|
|
568
|
+
shadow.ptr = ca->ptr;
|
|
569
|
+
cast_target = &shadow;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if ( c->has_mask ) {
|
|
573
|
+
boolean8_t *m;
|
|
574
|
+
m = (boolean8_t *)ca->mask->ptr;
|
|
575
|
+
for (i=0; i<ca->elements; i++) {
|
|
576
|
+
if ( rb_ary_entry(list,i) == CA_UNDEF ) {
|
|
577
|
+
*m = 1;
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
*m = 0;
|
|
581
|
+
}
|
|
582
|
+
m++;
|
|
583
|
+
}
|
|
584
|
+
ca_cast_block_with_mask(ca->elements, c->ico, (VALUE *)RARRAY_CONST_PTR(list),
|
|
585
|
+
cast_target, ca->ptr,
|
|
586
|
+
(boolean8_t*)ca->mask->ptr);
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
ca_cast_block(ca->elements, c->ico, (VALUE *)RARRAY_CONST_PTR(list), cast_target, ca->ptr);
|
|
590
|
+
}
|
|
591
|
+
return Qnil;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/* A Face source stored into an array that is not the same Face. Its cells
|
|
595
|
+
are surface values, and its storage means nothing to the destination: a
|
|
596
|
+
CATime's ticks are not times to an object array, and a categorical's codes
|
|
597
|
+
are not its labels. So an object destination, or a Face that does not
|
|
598
|
+
reconcile a Face source itself (a fixlen string taking a const string),
|
|
599
|
+
receives the values (to_type(:object)), and any other plain destination
|
|
600
|
+
refuses rather than receive storage bytes. A destination of the same Face
|
|
601
|
+
class, or one that reconciles a Face (to_comparable), is left to
|
|
602
|
+
ca_face_convert_store_rval. */
|
|
603
|
+
static VALUE
|
|
604
|
+
ca_face_source_for_store (VALUE self, CArray *ca, VALUE rval)
|
|
605
|
+
{
|
|
606
|
+
CArray *cr;
|
|
607
|
+
|
|
608
|
+
if ( ! rb_obj_is_carray(rval) ) {
|
|
609
|
+
return rval;
|
|
610
|
+
}
|
|
611
|
+
GetCArray(rval, cr);
|
|
612
|
+
if ( ! ca_is_face(cr) ) {
|
|
613
|
+
return rval;
|
|
614
|
+
}
|
|
615
|
+
if ( ca_is_face(ca) && ca->obj_type == CA_OBJ_RECORD ) {
|
|
616
|
+
/* A record is read at its data_class's member offsets, so records of
|
|
617
|
+
another data_class (of the same size or not) are refused; the class
|
|
618
|
+
of the record array (a subclass or CARecord itself) does not matter. */
|
|
619
|
+
if ( cr->obj_type == CA_OBJ_RECORD
|
|
620
|
+
&& rb_ca_data_class(self) == rb_ca_data_class(rval) ) {
|
|
621
|
+
return rval;
|
|
622
|
+
}
|
|
623
|
+
if ( cr->obj_type == CA_OBJ_RECORD ) {
|
|
624
|
+
rb_raise(rb_eTypeError,
|
|
625
|
+
"can not store a record array of %"PRIsVALUE
|
|
626
|
+
" into a record array of %"PRIsVALUE,
|
|
627
|
+
rb_ca_data_class(rval), rb_ca_data_class(self));
|
|
628
|
+
}
|
|
629
|
+
rb_raise(rb_eTypeError,
|
|
630
|
+
"can not store a %s array into a record array of %"PRIsVALUE,
|
|
631
|
+
rb_obj_classname(rval), rb_ca_data_class(self));
|
|
632
|
+
}
|
|
633
|
+
if ( ca_is_face(ca) ) {
|
|
634
|
+
if ( rb_obj_class(self) == rb_obj_class(rval)
|
|
635
|
+
|| rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
636
|
+
return rval;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
else if ( ca->data_type != CA_OBJECT ) {
|
|
640
|
+
/* A fixlen string or a record is its bytes: storage and surface are
|
|
641
|
+
the same, so a plain array of that type takes them as they are. A
|
|
642
|
+
const string's bytes are ranges into a pool of its own, and it is the
|
|
643
|
+
read-only Face that says so. */
|
|
644
|
+
CArray *storage = ca_strip_face(cr);
|
|
645
|
+
if ( storage->data_type == cr->data_type && storage->bytes == cr->bytes
|
|
646
|
+
&& ! ca_is_readonly(cr) ) {
|
|
647
|
+
return rval;
|
|
648
|
+
}
|
|
649
|
+
rb_raise(rb_eTypeError,
|
|
650
|
+
"can not store a %s array into %s array "
|
|
651
|
+
"(to_type(:object) gives its values)",
|
|
652
|
+
rb_obj_classname(rval), ca_type_name[ca->data_type]);
|
|
653
|
+
}
|
|
654
|
+
return rb_funcall(rval, rb_intern("to_type"), 1, INT2NUM(CA_OBJECT));
|
|
655
|
+
}
|
|
656
|
+
|
|
503
657
|
VALUE
|
|
504
658
|
rb_ca_store_all (VALUE self, VALUE rval)
|
|
505
659
|
{
|
|
@@ -516,6 +670,7 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
516
670
|
}
|
|
517
671
|
|
|
518
672
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
673
|
+
rval = ca_face_source_for_store(self, ca, rval);
|
|
519
674
|
|
|
520
675
|
retry:
|
|
521
676
|
|
|
@@ -552,6 +707,17 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
552
707
|
ca_broadcast_to_destination(self, &rval);
|
|
553
708
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
554
709
|
|
|
710
|
+
/* Fixlen cells of another width are fitted cell by cell, padded with
|
|
711
|
+
NUL or cut to the destination's width, as a String or an Array of
|
|
712
|
+
Strings stored into fixlen cells is. Copied as they are, the bytes
|
|
713
|
+
would be read past the end of a narrower source. */
|
|
714
|
+
if ( ca->data_type == CA_FIXLEN && cv->data_type == CA_FIXLEN
|
|
715
|
+
&& ca->bytes != cv->bytes ) {
|
|
716
|
+
rval = rb_ca_to_type(rb_ca_strip_face_value(rval), INT2NUM(CA_FIXLEN),
|
|
717
|
+
SIZE2NUM(ca->bytes));
|
|
718
|
+
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
719
|
+
}
|
|
720
|
+
|
|
555
721
|
/* Source delivery via ca_xfer_all into a local scratch instead of
|
|
556
722
|
ca_attach(cv). This routes through ca_*_func_xfer_all's per-region
|
|
557
723
|
partial-materialise path, avoiding a ca_attach(root) silent
|
|
@@ -564,29 +730,50 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
564
730
|
scales with the view, not the root. (The dst-side ca_sync_data is
|
|
565
731
|
already an xfer_all PUT.) */
|
|
566
732
|
{
|
|
567
|
-
volatile VALUE scratch_holder;
|
|
733
|
+
volatile VALUE scratch_holder, mscratch_holder = 0;
|
|
568
734
|
ca_size_t cv_bytes = cv->bytes * cv->elements;
|
|
569
735
|
char *scratch = ALLOCV_N(char, scratch_holder, cv_bytes);
|
|
736
|
+
boolean8_t *mscratch = NULL;
|
|
570
737
|
ca_xfer_all(cv, scratch, CA_XFER_GET);
|
|
571
738
|
|
|
739
|
+
/* The source's mask is taken now as well, before anything is
|
|
740
|
+
written: the source may read through to the destination's mask
|
|
741
|
+
(`c[] = c.flip(0)`, or a lazy expression over c whose mask is
|
|
742
|
+
built from c's on demand), and the writes below clear it. */
|
|
743
|
+
if ( ca_has_mask(cv) ) {
|
|
744
|
+
mscratch = ALLOCV_N(boolean8_t, mscratch_holder, cv->elements);
|
|
745
|
+
ca_xfer_all(cv->mask, mscratch, CA_XFER_GET);
|
|
746
|
+
}
|
|
747
|
+
|
|
572
748
|
if ( ca->data_type != cv->data_type ) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
749
|
+
ca_store_all_ctx_t c;
|
|
750
|
+
c.ca = ca;
|
|
751
|
+
c.cv = cv;
|
|
752
|
+
c.scratch = scratch;
|
|
753
|
+
c.mscratch = mscratch;
|
|
754
|
+
ca_attach_window(1, &ca, ca_store_all_mode(cv), ca_store_all_cast_body,
|
|
755
|
+
(VALUE) &c);
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
if ( mscratch ) {
|
|
759
|
+
if ( ! ca->mask ) {
|
|
760
|
+
ca_create_mask(ca);
|
|
761
|
+
}
|
|
762
|
+
ca_sync_data(ca->mask, (char *) mscratch);
|
|
578
763
|
}
|
|
579
764
|
else {
|
|
580
|
-
|
|
765
|
+
ca_update_mask(ca);
|
|
766
|
+
if ( ca->mask ) {
|
|
767
|
+
boolean8_t zero = 0;
|
|
768
|
+
ca_fill(ca->mask, &zero);
|
|
769
|
+
}
|
|
581
770
|
}
|
|
582
|
-
ca_sync(ca);
|
|
583
|
-
ca_detach(ca);
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
587
771
|
ca_sync_data(ca, scratch);
|
|
588
772
|
}
|
|
589
773
|
|
|
774
|
+
if ( mscratch ) {
|
|
775
|
+
ALLOCV_END(mscratch_holder);
|
|
776
|
+
}
|
|
590
777
|
ALLOCV_END(scratch_holder);
|
|
591
778
|
}
|
|
592
779
|
}
|
|
@@ -595,7 +782,7 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
595
782
|
rb_ary_flatten_for_elements(rval, ca->elements, ca);
|
|
596
783
|
ca_size_t i;
|
|
597
784
|
if ( NIL_P(list) ) {
|
|
598
|
-
rb_raise(
|
|
785
|
+
rb_raise(rb_eArgError,
|
|
599
786
|
"failed to guess data size of given array");
|
|
600
787
|
}
|
|
601
788
|
else {
|
|
@@ -612,54 +799,19 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
612
799
|
break;
|
|
613
800
|
}
|
|
614
801
|
}
|
|
615
|
-
/*
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
so ca_allocate()'s simpler path (no parent data copy) is sufficient. */
|
|
621
|
-
ca_allocate(ca);
|
|
802
|
+
/* Every element is replaced, so there would be no need to gather the
|
|
803
|
+
old values -- but converting a Ruby object can raise part way, and
|
|
804
|
+
then the cells already converted are pushed back with the rest
|
|
805
|
+
left as they were, which needs the old values in the buffer. So
|
|
806
|
+
this window attaches (see ca_store_all_mode). */
|
|
622
807
|
{
|
|
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
|
-
}
|
|
808
|
+
ca_store_all_ctx_t c;
|
|
809
|
+
c.ca = ca;
|
|
810
|
+
c.ico = &ico;
|
|
811
|
+
c.list = list;
|
|
812
|
+
c.has_mask = has_mask;
|
|
813
|
+
ca_attach_window(1, &ca, "w", ca_store_all_list_body, (VALUE) &c);
|
|
660
814
|
}
|
|
661
|
-
ca_sync(ca);
|
|
662
|
-
ca_detach(ca);
|
|
663
815
|
}
|
|
664
816
|
}
|
|
665
817
|
else if ( rb_respond_to(rval, id_to_ca) ) {
|
|
@@ -835,9 +987,8 @@ rb_ca_ref_block (VALUE self, CAIndexInfo *info)
|
|
|
835
987
|
data_type to the storage data_type (chain bottom) so the write path
|
|
836
988
|
casts in the storage type. */
|
|
837
989
|
if ( ca_is_face(ca) ) {
|
|
838
|
-
CArray *blk_ca, *root = ca;
|
|
990
|
+
CArray *blk_ca, *root = ca_strip_face(ca);
|
|
839
991
|
TypedData_Get_Struct(blk, CArray, &carray_data_type, blk_ca);
|
|
840
|
-
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
841
992
|
if (root && root->data_type != blk_ca->data_type) {
|
|
842
993
|
blk_ca->data_type = root->data_type;
|
|
843
994
|
}
|
|
@@ -894,7 +1045,13 @@ rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
|
894
1045
|
return rb_ca_remap_new(self, rmapper);
|
|
895
1046
|
}
|
|
896
1047
|
|
|
897
|
-
/* (b) Normalize chain fallback.
|
|
1048
|
+
/* (b) Normalize chain fallback. A Face is flattened through its storage
|
|
1049
|
+
and put on top of the result, so no Face is left in the middle of the
|
|
1050
|
+
chain (CAFace.md 8.3). */
|
|
1051
|
+
if ( ca_is_face(ca) ) {
|
|
1052
|
+
result = rb_ca_fancy_index_chain(rb_ca_strip_face_value(self), rmapper);
|
|
1053
|
+
return ca_face_lift(result, self);
|
|
1054
|
+
}
|
|
898
1055
|
flat_self = rb_ca_refer_new_flatten(self);
|
|
899
1056
|
flat_mapper = (cm->ndim == 1) ? rmapper : rb_ca_flatten(rmapper);
|
|
900
1057
|
grid_argv[0] = flat_mapper;
|
|
@@ -1014,8 +1171,20 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1014
1171
|
/* Re-enter against a flattened view of self. rb_ca_refer_new_flatten
|
|
1015
1172
|
is an internal builder and hands back a bare refer, so a marker
|
|
1016
1173
|
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
|
-
|
|
1174
|
+
at the tail. Put it back on before the re-entry.
|
|
1175
|
+
|
|
1176
|
+
A Face is flattened through its storage and put on top once at the
|
|
1177
|
+
end; re-entering against the flattened Face would build the view on
|
|
1178
|
+
it and leave a Face in the middle of the chain (CAFace.md 8.3). */
|
|
1179
|
+
if ( ca_is_face(ca) ) {
|
|
1180
|
+
volatile VALUE flat =
|
|
1181
|
+
rb_ca_refer_new_flatten(rb_ca_strip_face_value(self));
|
|
1182
|
+
obj = rb_ca_fetch_method(argc, argv, flat);
|
|
1183
|
+
if ( rb_obj_is_kind_of(obj, rb_cCArray) ) {
|
|
1184
|
+
obj = ca_face_lift(obj, self);
|
|
1185
|
+
}
|
|
1186
|
+
return obj;
|
|
1187
|
+
}
|
|
1019
1188
|
self = rb_ca_refer_new_flatten(self);
|
|
1020
1189
|
if ( ca_is_lazy_marker(ca) ) {
|
|
1021
1190
|
extern VALUE rb_ca_lazy_marker_new (VALUE cary);
|
|
@@ -1053,8 +1222,10 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1053
1222
|
obj = rb_ca_grid(argc, argv, self);
|
|
1054
1223
|
break;
|
|
1055
1224
|
case CA_REG_METHOD_CALL: {
|
|
1225
|
+
/* a[:eq, 0] is a[a.eq(0)]: a public method of the array, as a call
|
|
1226
|
+
written out would reach (a[:puts] does not run Kernel#puts). */
|
|
1056
1227
|
volatile VALUE idx;
|
|
1057
|
-
idx =
|
|
1228
|
+
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1058
1229
|
obj = rb_ca_fetch(self, idx);
|
|
1059
1230
|
break;
|
|
1060
1231
|
}
|
|
@@ -1089,11 +1260,8 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1089
1260
|
already-a-Face case (some builders lift their own result) is handled
|
|
1090
1261
|
inside ca_wrapper_lift.
|
|
1091
1262
|
|
|
1092
|
-
Every CA_REG_* branch converges here, so this one line covers
|
|
1093
|
-
|
|
1094
|
-
whose shape stays open until an operand binds it, and a marker copies
|
|
1095
|
-
shape at construction. ca_wrapper_lift refuses that one, in one place,
|
|
1096
|
-
because `unbound_repeat` reaches it by a second route. */
|
|
1263
|
+
Every CA_REG_* branch converges here, so this one line covers every
|
|
1264
|
+
index form that returns a CArray. */
|
|
1097
1265
|
CA_WRAPPER_LIFT(obj, self, ca);
|
|
1098
1266
|
|
|
1099
1267
|
return obj;
|
|
@@ -1107,6 +1275,8 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1107
1275
|
{
|
|
1108
1276
|
int i;
|
|
1109
1277
|
int nclean = 0;
|
|
1278
|
+
int nscalar = 0;
|
|
1279
|
+
int nunder = 0;
|
|
1110
1280
|
VALUE clean[CA_RANK_MAX];
|
|
1111
1281
|
volatile VALUE base;
|
|
1112
1282
|
ca_size_t final_dims[CA_RANK_MAX];
|
|
@@ -1118,11 +1288,17 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1118
1288
|
/* Build clean argv (strip :_); reject disjoint sigils + rubber dim. */
|
|
1119
1289
|
for (i = 0; i < argc; i++) {
|
|
1120
1290
|
VALUE a = argv[i];
|
|
1121
|
-
if ( a == sym_under )
|
|
1122
|
-
|
|
1291
|
+
if ( a == sym_under ) {
|
|
1292
|
+
nunder++;
|
|
1293
|
+
continue;
|
|
1294
|
+
}
|
|
1295
|
+
if ( FIXNUM_P(a) || RB_TYPE_P(a, T_BIGNUM) ) {
|
|
1296
|
+
nscalar++;
|
|
1297
|
+
}
|
|
1298
|
+
if ( a == sym_gt || a == sym_perc
|
|
1123
1299
|
|| a == Qfalse || a == sym_tilde ) {
|
|
1124
1300
|
rb_raise(rb_eIndexError,
|
|
1125
|
-
"newaxis (:_) cannot be combined with :>,
|
|
1301
|
+
"newaxis (:_) cannot be combined with :>, :%%, "
|
|
1126
1302
|
"or rubber dim (false / :~)");
|
|
1127
1303
|
}
|
|
1128
1304
|
if ( nclean >= CA_RANK_MAX ) {
|
|
@@ -1140,18 +1316,26 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1140
1316
|
nclean, (int) ca->ndim);
|
|
1141
1317
|
}
|
|
1142
1318
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
if (
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1319
|
+
/* Every real axis indexed by a scalar: fetching `clean` would yield the
|
|
1320
|
+
element itself, and there would be nothing left to reshape. Ask for a
|
|
1321
|
+
length-1 block on each axis instead, so the base stays a CArray and the
|
|
1322
|
+
result is a view into self. The result carries exactly the axes :_ asked
|
|
1323
|
+
for, all of length 1 -- an operand that states rank nunder and one
|
|
1324
|
+
element, which is what the shape rules then hold it to. */
|
|
1325
|
+
if ( nscalar == nclean ) {
|
|
1326
|
+
VALUE blocks[CA_RANK_MAX];
|
|
1327
|
+
for (i = 0; i < nclean; i++) {
|
|
1328
|
+
blocks[i] = rb_assoc_new(clean[i], INT2FIX(1));
|
|
1329
|
+
}
|
|
1330
|
+
base = rb_ca_fetch_method(nclean, blocks, self);
|
|
1331
|
+
for (i = 0; i < nunder; i++) {
|
|
1332
|
+
dim_argv[i] = INT2FIX(1);
|
|
1333
|
+
}
|
|
1334
|
+
return rb_ca_reshape(nunder, dim_argv, base);
|
|
1153
1335
|
}
|
|
1154
1336
|
|
|
1337
|
+
base = rb_ca_fetch_method(nclean, clean, self);
|
|
1338
|
+
|
|
1155
1339
|
TypedData_Get_Struct(base, CArray, &carray_data_type, cb);
|
|
1156
1340
|
|
|
1157
1341
|
/* Reconstruct final shape: walk original argv. :_ -> size-1, scalar
|
|
@@ -1345,7 +1529,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1345
1529
|
break;
|
|
1346
1530
|
case CA_REG_METHOD_CALL: {
|
|
1347
1531
|
volatile VALUE idx;
|
|
1348
|
-
idx =
|
|
1532
|
+
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1349
1533
|
obj = rb_ca_fetch(self, idx);
|
|
1350
1534
|
break;
|
|
1351
1535
|
}
|
|
@@ -1390,7 +1574,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1390
1574
|
of letting the storage cast truncate it, and the bulk path must not be
|
|
1391
1575
|
the looser door.
|
|
1392
1576
|
- an Array is mapped structure-preserving (leaves converted),
|
|
1393
|
-
- a scalar goes through the write hook (
|
|
1577
|
+
- a scalar goes through the write hook (ca_face_element_to_storage), which
|
|
1394
1578
|
leaves a bare Integer / String unchanged.
|
|
1395
1579
|
|
|
1396
1580
|
Idempotent: an already-converted Integer passes through, so re-running on
|
|
@@ -1401,15 +1585,26 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1401
1585
|
if ( rb_obj_is_carray(val) ) {
|
|
1402
1586
|
CArray *cval;
|
|
1403
1587
|
GetCArray(val, cval);
|
|
1588
|
+
/* An object array holding struct elements (a record array's
|
|
1589
|
+
to_type(:object)) goes in as its values, each through the write
|
|
1590
|
+
hook; masked cells come back as UNDEF and stay masked. */
|
|
1591
|
+
if ( ca->obj_type == CA_OBJ_RECORD && cval->data_type == CA_OBJECT ) {
|
|
1592
|
+
return ca_face_convert_store_rval(self, ca,
|
|
1593
|
+
rb_funcall(val, rb_intern("to_a"), 0));
|
|
1594
|
+
}
|
|
1404
1595
|
/* Face RHS: reconcile to self's unit and descend to storage. Mirror of
|
|
1405
|
-
the scalar path (
|
|
1596
|
+
the scalar path (ca_face_element_to_storage) for a bulk CArray source.
|
|
1406
1597
|
Guarded on self having to_comparable so a Face without a reconcile
|
|
1407
1598
|
algebra (e.g. a fixlen-storage Face, whose same-storage store already
|
|
1408
1599
|
takes the storage xfer branch) is left to the existing store path. */
|
|
1409
1600
|
if ( ca_is_face(cval) && rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1601
|
+
return ca_face_reconcile_operand(self, val, "[]=");
|
|
1602
|
+
}
|
|
1603
|
+
/* A Face of the same class and a compatible state holds values of the
|
|
1604
|
+
same kind in the same encoding: it goes in as its storage. */
|
|
1605
|
+
if ( ca_is_face(cval) && rb_obj_class(val) == rb_obj_class(self)
|
|
1606
|
+
&& ca_face_state_compatible(self, ca, val, cval) ) {
|
|
1607
|
+
return rb_ca_strip_face_value(val);
|
|
1413
1608
|
}
|
|
1414
1609
|
/* Bare storage escape, integer storage: integer cells only (see above). */
|
|
1415
1610
|
{
|
|
@@ -1432,15 +1627,16 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1432
1627
|
}
|
|
1433
1628
|
return out;
|
|
1434
1629
|
}
|
|
1435
|
-
return
|
|
1630
|
+
return ca_face_element_to_storage(self, ca, val);
|
|
1436
1631
|
}
|
|
1437
1632
|
|
|
1438
1633
|
static VALUE
|
|
1439
1634
|
rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
1440
1635
|
{
|
|
1441
|
-
volatile VALUE obj = Qnil, rval;
|
|
1636
|
+
volatile VALUE obj = Qnil, rval, dest;
|
|
1442
1637
|
CArray *ca;
|
|
1443
1638
|
CAIndexInfo info;
|
|
1639
|
+
int converted = 0; /* rval has been through the Face's write hook */
|
|
1444
1640
|
|
|
1445
1641
|
rb_ca_modify(self);
|
|
1446
1642
|
|
|
@@ -1450,12 +1646,31 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1450
1646
|
retry:
|
|
1451
1647
|
|
|
1452
1648
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1649
|
+
rval = ca_face_source_for_store(self, ca, rval);
|
|
1453
1650
|
|
|
1454
1651
|
/* Face store: bring a surface value object (Scalar / Time / DateTime) into
|
|
1455
1652
|
the storage domain while self is still the Face. Store-side views strip
|
|
1456
1653
|
the Face to storage, so this is the only point that sees it. */
|
|
1457
1654
|
if ( ca_is_face(ca) ) {
|
|
1458
|
-
|
|
1655
|
+
/* Once: a retry below comes back here with rval already converted. */
|
|
1656
|
+
if ( ! converted ) {
|
|
1657
|
+
rval = ca_face_convert_store_rval(self, ca, rval);
|
|
1658
|
+
converted = 1;
|
|
1659
|
+
}
|
|
1660
|
+
/* A CArray source is storage now, so the destination has to be too.
|
|
1661
|
+
A block store descends on its own (its view is built on the storage);
|
|
1662
|
+
a whole, boolean or address store kept the Face and cast the storage
|
|
1663
|
+
to the Face's surface type, which an int64 tick cannot become. A Face
|
|
1664
|
+
whose surface type is its storage's (a string or record Face) needs
|
|
1665
|
+
no descent, and keeps its own index forms (a record's field name). */
|
|
1666
|
+
if ( rb_obj_is_carray(rval) ) {
|
|
1667
|
+
CArray *cr;
|
|
1668
|
+
GetCArray(rval, cr);
|
|
1669
|
+
if ( ! ca_is_face(cr) && ca_strip_face(ca)->data_type != ca->data_type ) {
|
|
1670
|
+
self = rb_ca_strip_face_value(self);
|
|
1671
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1459
1674
|
}
|
|
1460
1675
|
|
|
1461
1676
|
/* newaxis (:_) interception on store. Build the newaxis view (a
|
|
@@ -1479,31 +1694,40 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1479
1694
|
info.range_check = 1;
|
|
1480
1695
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1481
1696
|
|
|
1697
|
+
/* A value or a Ruby Array converted above is in the storage domain now.
|
|
1698
|
+
Stored through the Face it would meet the write hook a second time
|
|
1699
|
+
(rb_ca_obj2ptr converts too), so a positional store goes into the
|
|
1700
|
+
storage, which has the Face's shape. A predicate (:sym) is still
|
|
1701
|
+
asked of the Face; a member store keeps the Face for its data_class. */
|
|
1702
|
+
dest = self;
|
|
1703
|
+
if ( converted && ca_is_face(ca) && ! rb_obj_is_carray(rval) ) {
|
|
1704
|
+
dest = rb_ca_strip_face_value(self);
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1482
1707
|
switch ( info.type ) {
|
|
1483
1708
|
case CA_REG_ADDRESS_COMPLEX:
|
|
1484
1709
|
self = rb_ca_refer_new_flatten(self);
|
|
1485
1710
|
goto retry;
|
|
1486
1711
|
case CA_REG_ADDRESS:
|
|
1487
|
-
obj = rb_ca_store_address(
|
|
1712
|
+
obj = rb_ca_store_address(dest, &info, rval);
|
|
1488
1713
|
break;
|
|
1489
1714
|
case CA_REG_FLATTEN:
|
|
1490
|
-
|
|
1491
|
-
obj = rb_ca_store_all(self, rval);
|
|
1715
|
+
obj = rb_ca_store_all(rb_ca_refer_new_flatten(dest), rval);
|
|
1492
1716
|
break;
|
|
1493
1717
|
case CA_REG_POINT:
|
|
1494
|
-
obj = rb_ca_store_point(
|
|
1718
|
+
obj = rb_ca_store_point(dest, &info, rval);
|
|
1495
1719
|
break;
|
|
1496
1720
|
case CA_REG_ALL:
|
|
1497
|
-
obj = rb_ca_store_all(
|
|
1721
|
+
obj = rb_ca_store_all(dest, rval);
|
|
1498
1722
|
break;
|
|
1499
1723
|
case CA_REG_BLOCK: {
|
|
1500
1724
|
volatile VALUE block;
|
|
1501
|
-
block = rb_ca_ref_block(
|
|
1725
|
+
block = rb_ca_ref_block(dest, &info);
|
|
1502
1726
|
obj = rb_ca_store_all(block, rval);
|
|
1503
1727
|
break;
|
|
1504
1728
|
}
|
|
1505
1729
|
case CA_REG_SELECT: {
|
|
1506
|
-
obj = rb_ca_select_new(
|
|
1730
|
+
obj = rb_ca_select_new(dest, argv[0]);
|
|
1507
1731
|
obj = rb_ca_store_all(obj, rval);
|
|
1508
1732
|
break;
|
|
1509
1733
|
}
|
|
@@ -1516,27 +1740,30 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1516
1740
|
break;
|
|
1517
1741
|
}
|
|
1518
1742
|
case CA_REG_REPEAT: {
|
|
1519
|
-
obj = rb_ca_repeat(argc, argv,
|
|
1743
|
+
obj = rb_ca_repeat(argc, argv, dest);
|
|
1520
1744
|
obj = rb_ca_store_all(obj, rval);
|
|
1521
1745
|
break;
|
|
1522
1746
|
}
|
|
1523
1747
|
case CA_REG_MAPPING: {
|
|
1524
|
-
obj = rb_ca_fancy_index_chain(
|
|
1748
|
+
obj = rb_ca_fancy_index_chain(dest, argv[0]);
|
|
1525
1749
|
obj = rb_ca_store_all(obj, rval);
|
|
1526
1750
|
break;
|
|
1527
1751
|
}
|
|
1528
1752
|
case CA_REG_GRID: {
|
|
1529
|
-
obj = rb_ca_grid(argc, argv,
|
|
1753
|
+
obj = rb_ca_grid(argc, argv, dest);
|
|
1530
1754
|
obj = rb_ca_store_all(obj, rval);
|
|
1531
1755
|
break;
|
|
1532
1756
|
}
|
|
1533
1757
|
case CA_REG_METHOD_CALL: {
|
|
1534
|
-
|
|
1758
|
+
ca_store_method_call_ctx_t c;
|
|
1535
1759
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1760
|
+
c.self = self;
|
|
1761
|
+
c.dest = dest;
|
|
1762
|
+
c.mid = SYM2ID(info.symbol);
|
|
1763
|
+
c.argc = (int)(argc-1);
|
|
1764
|
+
c.argv = argv+1;
|
|
1765
|
+
c.rval = rval;
|
|
1766
|
+
obj = ca_attach_window(1, &ca, "r", ca_store_method_call_body, (VALUE) &c);
|
|
1540
1767
|
break;
|
|
1541
1768
|
}
|
|
1542
1769
|
case CA_REG_MEMBER: {
|
|
@@ -1614,15 +1841,13 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1614
1841
|
Check_Type(rdim, T_ARRAY);
|
|
1615
1842
|
Check_Type(ridx, T_ARRAY);
|
|
1616
1843
|
|
|
1617
|
-
elements = 1;
|
|
1618
1844
|
ndim = (int) RARRAY_LEN(rdim);
|
|
1845
|
+
CA_CHECK_RANK(ndim);
|
|
1619
1846
|
for (i=0; i<ndim; i++) {
|
|
1620
1847
|
dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
1621
|
-
elements *= dim[i];
|
|
1622
1848
|
}
|
|
1623
|
-
|
|
1624
|
-
CA_CHECK_RANK(ndim);
|
|
1625
1849
|
CA_CHECK_DIM(ndim, dim);
|
|
1850
|
+
elements = ca_shape_elements(ndim, dim, 1);
|
|
1626
1851
|
|
|
1627
1852
|
info.range_check = 1;
|
|
1628
1853
|
rb_ca_scan_index(ndim, dim, elements,
|
|
@@ -1686,7 +1911,7 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1686
1911
|
info.index[i].symbol.spec));
|
|
1687
1912
|
break;
|
|
1688
1913
|
default:
|
|
1689
|
-
rb_raise(
|
|
1914
|
+
rb_raise(rb_eIndexError, "unknown index spec");
|
|
1690
1915
|
}
|
|
1691
1916
|
}
|
|
1692
1917
|
break;
|
|
@@ -1754,7 +1979,7 @@ rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
|
1754
1979
|
rb_ary_store(rindex, i, ID2SYM(info.index[i].symbol.id));
|
|
1755
1980
|
break;
|
|
1756
1981
|
default:
|
|
1757
|
-
rb_raise(
|
|
1982
|
+
rb_raise(rb_eIndexError, "unknown index spec");
|
|
1758
1983
|
}
|
|
1759
1984
|
}
|
|
1760
1985
|
return rindex;
|
|
@@ -1801,8 +2026,8 @@ parse_shape_kwarg (VALUE rshape, int *out_ndim, ca_size_t *dim,
|
|
|
1801
2026
|
rb_raise(rb_eArgError, "negative dim %" PRId64 " at axis %d",
|
|
1802
2027
|
(ca_size_t) dim[i], i);
|
|
1803
2028
|
}
|
|
1804
|
-
elements *= dim[i];
|
|
1805
2029
|
}
|
|
2030
|
+
elements = ca_shape_elements(ndim, dim, 1);
|
|
1806
2031
|
*out_ndim = ndim;
|
|
1807
2032
|
*out_elements = elements;
|
|
1808
2033
|
}
|
|
@@ -1816,12 +2041,7 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1816
2041
|
/* Scalar path (Integer input): returns Ruby Array of N Integers.
|
|
1817
2042
|
* Preserves legacy shape for callers like `i, j = ca.addr2index(k)`. */
|
|
1818
2043
|
if ( rb_obj_is_kind_of(raddr, rb_cInteger) ) {
|
|
1819
|
-
ca_size_t addr = NUM2SIZE(raddr);
|
|
1820
|
-
if ( addr < 0 || addr >= elements ) {
|
|
1821
|
-
rb_raise(rb_eArgError,
|
|
1822
|
-
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1823
|
-
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
1824
|
-
}
|
|
2044
|
+
ca_size_t addr = ca_index_in_range(NUM2SIZE(raddr), elements, "address");
|
|
1825
2045
|
out = rb_ary_new2(ndim);
|
|
1826
2046
|
for (i = ndim - 1; i >= 0; i--) {
|
|
1827
2047
|
rb_ary_store(out, i, SIZE2NUM(addr % dim[i]));
|
|
@@ -1839,8 +2059,9 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1839
2059
|
ca_size_t j, n;
|
|
1840
2060
|
volatile VALUE objs[CA_RANK_MAX];
|
|
1841
2061
|
|
|
2062
|
+
ca_check_index_array(raddr);
|
|
1842
2063
|
cin = ca_wrap_readonly(raddr, CA_SIZE);
|
|
1843
|
-
ca_attach(cin);
|
|
2064
|
+
ca_attach(cin); /* window: detached before its one raise */
|
|
1844
2065
|
|
|
1845
2066
|
out = rb_ary_new2(ndim);
|
|
1846
2067
|
for (i = 0; i < ndim; i++) {
|
|
@@ -1869,12 +2090,11 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1869
2090
|
continue;
|
|
1870
2091
|
}
|
|
1871
2092
|
addr = src[j];
|
|
1872
|
-
if ( addr <
|
|
2093
|
+
if ( addr < -elements || addr >= elements ) {
|
|
1873
2094
|
ca_detach(cin);
|
|
1874
|
-
|
|
1875
|
-
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1876
|
-
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
2095
|
+
ca_index_out_of_range(addr, elements, "address");
|
|
1877
2096
|
}
|
|
2097
|
+
addr = ca_index_in_range(addr, elements, "address");
|
|
1878
2098
|
for (k = ndim - 1; k >= 0; k--) {
|
|
1879
2099
|
p_out[k][j] = addr % dim[k];
|
|
1880
2100
|
addr /= dim[k];
|
|
@@ -1887,14 +2107,87 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1887
2107
|
}
|
|
1888
2108
|
}
|
|
1889
2109
|
|
|
2110
|
+
/* The vector path of index2addr reads every index array inside one
|
|
2111
|
+
window: an index out of range raises part way through. */
|
|
2112
|
+
|
|
2113
|
+
typedef struct {
|
|
2114
|
+
int ndim;
|
|
2115
|
+
ca_size_t *dim;
|
|
2116
|
+
CArray **cidx;
|
|
2117
|
+
int out_ndim;
|
|
2118
|
+
ca_size_t *out_dim;
|
|
2119
|
+
ca_size_t out_elements;
|
|
2120
|
+
} ca_index2addr_ctx_t;
|
|
2121
|
+
|
|
1890
2122
|
static VALUE
|
|
1891
|
-
|
|
2123
|
+
ca_index2addr_body (VALUE arg)
|
|
1892
2124
|
{
|
|
2125
|
+
ca_index2addr_ctx_t *c = (ca_index2addr_ctx_t *) arg;
|
|
2126
|
+
int ndim = c->ndim;
|
|
2127
|
+
ca_size_t *dim = c->dim;
|
|
2128
|
+
CArray **cidx = c->cidx;
|
|
2129
|
+
ca_size_t out_elements = c->out_elements;
|
|
1893
2130
|
volatile VALUE obj;
|
|
1894
|
-
CArray *co
|
|
2131
|
+
CArray *co;
|
|
1895
2132
|
ca_size_t *q, *p[CA_RANK_MAX], s[CA_RANK_MAX];
|
|
1896
2133
|
ca_size_t addr, k, n;
|
|
1897
2134
|
boolean8_t *m;
|
|
2135
|
+
int i;
|
|
2136
|
+
|
|
2137
|
+
for (i = 0; i < ndim; i++) {
|
|
2138
|
+
ca_set_iterator(1, cidx[i], &p[i], &s[i]);
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
obj = rb_carray_new(CA_SIZE, c->out_ndim, c->out_dim, 0, NULL);
|
|
2142
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
|
|
2143
|
+
|
|
2144
|
+
q = (ca_size_t *) co->ptr;
|
|
2145
|
+
|
|
2146
|
+
ca_copy_mask_overwrite_n(co, out_elements, ndim, cidx);
|
|
2147
|
+
m = ( co->mask ) ? (boolean8_t *) co->mask->ptr : NULL;
|
|
2148
|
+
|
|
2149
|
+
if ( m ) {
|
|
2150
|
+
n = out_elements;
|
|
2151
|
+
while ( n-- ) {
|
|
2152
|
+
if ( ! *m ) {
|
|
2153
|
+
addr = 0;
|
|
2154
|
+
for (i = 0; i < ndim; i++) {
|
|
2155
|
+
k = *(p[i]);
|
|
2156
|
+
p[i] += s[i];
|
|
2157
|
+
CA_CHECK_INDEX(k, dim[i]);
|
|
2158
|
+
addr = dim[i] * addr + k;
|
|
2159
|
+
}
|
|
2160
|
+
*q = addr;
|
|
2161
|
+
}
|
|
2162
|
+
else {
|
|
2163
|
+
for (i = 0; i < ndim; i++) { p[i] += s[i]; }
|
|
2164
|
+
}
|
|
2165
|
+
m++; q++;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
else {
|
|
2169
|
+
n = out_elements;
|
|
2170
|
+
while ( n-- ) {
|
|
2171
|
+
addr = 0;
|
|
2172
|
+
for (i = 0; i < ndim; i++) {
|
|
2173
|
+
k = *(p[i]);
|
|
2174
|
+
p[i] += s[i];
|
|
2175
|
+
CA_CHECK_INDEX(k, dim[i]);
|
|
2176
|
+
addr = dim[i] * addr + k;
|
|
2177
|
+
}
|
|
2178
|
+
*q = addr;
|
|
2179
|
+
q++;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
return obj;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
static VALUE
|
|
2187
|
+
index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
2188
|
+
{
|
|
2189
|
+
CArray *cidx[CA_RANK_MAX];
|
|
2190
|
+
ca_size_t addr, k;
|
|
1898
2191
|
int i, all_number = 1;
|
|
1899
2192
|
int out_ndim = 1;
|
|
1900
2193
|
ca_size_t out_dim[CA_RANK_MAX];
|
|
@@ -1928,6 +2221,7 @@ index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
|
1928
2221
|
* the first non-scalar CArray input; other non-scalar inputs must
|
|
1929
2222
|
* match that shape. */
|
|
1930
2223
|
for (i = 0; i < ndim; i++) {
|
|
2224
|
+
ca_check_index_array(argv[i]);
|
|
1931
2225
|
cidx[i] = ca_wrap_readonly(argv[i], CA_SIZE);
|
|
1932
2226
|
if ( ! ca_is_scalar(cidx[i]) ) {
|
|
1933
2227
|
if ( shape_from < 0 ) {
|
|
@@ -1956,56 +2250,19 @@ index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
|
1956
2250
|
}
|
|
1957
2251
|
}
|
|
1958
2252
|
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
if ( m ) {
|
|
1973
|
-
n = out_elements;
|
|
1974
|
-
while ( n-- ) {
|
|
1975
|
-
if ( ! *m ) {
|
|
1976
|
-
addr = 0;
|
|
1977
|
-
for (i = 0; i < ndim; i++) {
|
|
1978
|
-
k = *(p[i]);
|
|
1979
|
-
p[i] += s[i];
|
|
1980
|
-
CA_CHECK_INDEX(k, dim[i]);
|
|
1981
|
-
addr = dim[i] * addr + k;
|
|
1982
|
-
}
|
|
1983
|
-
*q = addr;
|
|
1984
|
-
}
|
|
1985
|
-
else {
|
|
1986
|
-
for (i = 0; i < ndim; i++) { p[i] += s[i]; }
|
|
1987
|
-
}
|
|
1988
|
-
m++; q++;
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
else {
|
|
1992
|
-
n = out_elements;
|
|
1993
|
-
while ( n-- ) {
|
|
1994
|
-
addr = 0;
|
|
1995
|
-
for (i = 0; i < ndim; i++) {
|
|
1996
|
-
k = *(p[i]);
|
|
1997
|
-
p[i] += s[i];
|
|
1998
|
-
CA_CHECK_INDEX(k, dim[i]);
|
|
1999
|
-
addr = dim[i] * addr + k;
|
|
2000
|
-
}
|
|
2001
|
-
*q = addr;
|
|
2002
|
-
q++;
|
|
2003
|
-
}
|
|
2253
|
+
{
|
|
2254
|
+
ca_index2addr_ctx_t c;
|
|
2255
|
+
char modes[CA_RANK_MAX + 1];
|
|
2256
|
+
memset(modes, 'r', (size_t) ndim);
|
|
2257
|
+
modes[ndim] = '\0';
|
|
2258
|
+
c.ndim = ndim;
|
|
2259
|
+
c.dim = dim;
|
|
2260
|
+
c.cidx = cidx;
|
|
2261
|
+
c.out_ndim = out_ndim;
|
|
2262
|
+
c.out_dim = out_dim;
|
|
2263
|
+
c.out_elements = out_elements;
|
|
2264
|
+
return ca_attach_window(ndim, cidx, modes, ca_index2addr_body, (VALUE) &c);
|
|
2004
2265
|
}
|
|
2005
|
-
|
|
2006
|
-
for (i = 0; i < ndim; i++) { ca_detach(cidx[i]); }
|
|
2007
|
-
|
|
2008
|
-
return obj;
|
|
2009
2266
|
}
|
|
2010
2267
|
|
|
2011
2268
|
VALUE
|
|
@@ -2076,7 +2333,6 @@ Init_carray_access (void)
|
|
|
2076
2333
|
id_excl_end = rb_intern("exclude_end?");
|
|
2077
2334
|
|
|
2078
2335
|
id_to_ca = rb_intern("to_ca");
|
|
2079
|
-
sym_star = ID2SYM(rb_intern("*"));
|
|
2080
2336
|
sym_perc = ID2SYM(rb_intern("%"));
|
|
2081
2337
|
sym_under = ID2SYM(rb_intern("_"));
|
|
2082
2338
|
sym_gt = ID2SYM(rb_intern(">"));
|