carray 3.0.2 → 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 +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- 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 +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- 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 +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -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 +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -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 +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- 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 +149 -27
- 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 +102 -79
- 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 +463 -0
- data/ext/carray.h +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- 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 +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- 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 +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- 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 +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- 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 +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- 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/factorize.rb +2 -2
- 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 +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- 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/record_order.rb +208 -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 +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- 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 +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -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 +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 +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- 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 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -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 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
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
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
|
}
|
|
@@ -1358,7 +1529,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1358
1529
|
break;
|
|
1359
1530
|
case CA_REG_METHOD_CALL: {
|
|
1360
1531
|
volatile VALUE idx;
|
|
1361
|
-
idx =
|
|
1532
|
+
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1362
1533
|
obj = rb_ca_fetch(self, idx);
|
|
1363
1534
|
break;
|
|
1364
1535
|
}
|
|
@@ -1403,7 +1574,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1403
1574
|
of letting the storage cast truncate it, and the bulk path must not be
|
|
1404
1575
|
the looser door.
|
|
1405
1576
|
- an Array is mapped structure-preserving (leaves converted),
|
|
1406
|
-
- a scalar goes through the write hook (
|
|
1577
|
+
- a scalar goes through the write hook (ca_face_element_to_storage), which
|
|
1407
1578
|
leaves a bare Integer / String unchanged.
|
|
1408
1579
|
|
|
1409
1580
|
Idempotent: an already-converted Integer passes through, so re-running on
|
|
@@ -1414,15 +1585,26 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1414
1585
|
if ( rb_obj_is_carray(val) ) {
|
|
1415
1586
|
CArray *cval;
|
|
1416
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
|
+
}
|
|
1417
1595
|
/* Face RHS: reconcile to self's unit and descend to storage. Mirror of
|
|
1418
|
-
the scalar path (
|
|
1596
|
+
the scalar path (ca_face_element_to_storage) for a bulk CArray source.
|
|
1419
1597
|
Guarded on self having to_comparable so a Face without a reconcile
|
|
1420
1598
|
algebra (e.g. a fixlen-storage Face, whose same-storage store already
|
|
1421
1599
|
takes the storage xfer branch) is left to the existing store path. */
|
|
1422
1600
|
if ( ca_is_face(cval) && rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
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);
|
|
1426
1608
|
}
|
|
1427
1609
|
/* Bare storage escape, integer storage: integer cells only (see above). */
|
|
1428
1610
|
{
|
|
@@ -1445,15 +1627,16 @@ ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
|
1445
1627
|
}
|
|
1446
1628
|
return out;
|
|
1447
1629
|
}
|
|
1448
|
-
return
|
|
1630
|
+
return ca_face_element_to_storage(self, ca, val);
|
|
1449
1631
|
}
|
|
1450
1632
|
|
|
1451
1633
|
static VALUE
|
|
1452
1634
|
rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
1453
1635
|
{
|
|
1454
|
-
volatile VALUE obj = Qnil, rval;
|
|
1636
|
+
volatile VALUE obj = Qnil, rval, dest;
|
|
1455
1637
|
CArray *ca;
|
|
1456
1638
|
CAIndexInfo info;
|
|
1639
|
+
int converted = 0; /* rval has been through the Face's write hook */
|
|
1457
1640
|
|
|
1458
1641
|
rb_ca_modify(self);
|
|
1459
1642
|
|
|
@@ -1463,12 +1646,31 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1463
1646
|
retry:
|
|
1464
1647
|
|
|
1465
1648
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1649
|
+
rval = ca_face_source_for_store(self, ca, rval);
|
|
1466
1650
|
|
|
1467
1651
|
/* Face store: bring a surface value object (Scalar / Time / DateTime) into
|
|
1468
1652
|
the storage domain while self is still the Face. Store-side views strip
|
|
1469
1653
|
the Face to storage, so this is the only point that sees it. */
|
|
1470
1654
|
if ( ca_is_face(ca) ) {
|
|
1471
|
-
|
|
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
|
+
}
|
|
1472
1674
|
}
|
|
1473
1675
|
|
|
1474
1676
|
/* newaxis (:_) interception on store. Build the newaxis view (a
|
|
@@ -1492,31 +1694,40 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1492
1694
|
info.range_check = 1;
|
|
1493
1695
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1494
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
|
+
|
|
1495
1707
|
switch ( info.type ) {
|
|
1496
1708
|
case CA_REG_ADDRESS_COMPLEX:
|
|
1497
1709
|
self = rb_ca_refer_new_flatten(self);
|
|
1498
1710
|
goto retry;
|
|
1499
1711
|
case CA_REG_ADDRESS:
|
|
1500
|
-
obj = rb_ca_store_address(
|
|
1712
|
+
obj = rb_ca_store_address(dest, &info, rval);
|
|
1501
1713
|
break;
|
|
1502
1714
|
case CA_REG_FLATTEN:
|
|
1503
|
-
|
|
1504
|
-
obj = rb_ca_store_all(self, rval);
|
|
1715
|
+
obj = rb_ca_store_all(rb_ca_refer_new_flatten(dest), rval);
|
|
1505
1716
|
break;
|
|
1506
1717
|
case CA_REG_POINT:
|
|
1507
|
-
obj = rb_ca_store_point(
|
|
1718
|
+
obj = rb_ca_store_point(dest, &info, rval);
|
|
1508
1719
|
break;
|
|
1509
1720
|
case CA_REG_ALL:
|
|
1510
|
-
obj = rb_ca_store_all(
|
|
1721
|
+
obj = rb_ca_store_all(dest, rval);
|
|
1511
1722
|
break;
|
|
1512
1723
|
case CA_REG_BLOCK: {
|
|
1513
1724
|
volatile VALUE block;
|
|
1514
|
-
block = rb_ca_ref_block(
|
|
1725
|
+
block = rb_ca_ref_block(dest, &info);
|
|
1515
1726
|
obj = rb_ca_store_all(block, rval);
|
|
1516
1727
|
break;
|
|
1517
1728
|
}
|
|
1518
1729
|
case CA_REG_SELECT: {
|
|
1519
|
-
obj = rb_ca_select_new(
|
|
1730
|
+
obj = rb_ca_select_new(dest, argv[0]);
|
|
1520
1731
|
obj = rb_ca_store_all(obj, rval);
|
|
1521
1732
|
break;
|
|
1522
1733
|
}
|
|
@@ -1529,27 +1740,30 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1529
1740
|
break;
|
|
1530
1741
|
}
|
|
1531
1742
|
case CA_REG_REPEAT: {
|
|
1532
|
-
obj = rb_ca_repeat(argc, argv,
|
|
1743
|
+
obj = rb_ca_repeat(argc, argv, dest);
|
|
1533
1744
|
obj = rb_ca_store_all(obj, rval);
|
|
1534
1745
|
break;
|
|
1535
1746
|
}
|
|
1536
1747
|
case CA_REG_MAPPING: {
|
|
1537
|
-
obj = rb_ca_fancy_index_chain(
|
|
1748
|
+
obj = rb_ca_fancy_index_chain(dest, argv[0]);
|
|
1538
1749
|
obj = rb_ca_store_all(obj, rval);
|
|
1539
1750
|
break;
|
|
1540
1751
|
}
|
|
1541
1752
|
case CA_REG_GRID: {
|
|
1542
|
-
obj = rb_ca_grid(argc, argv,
|
|
1753
|
+
obj = rb_ca_grid(argc, argv, dest);
|
|
1543
1754
|
obj = rb_ca_store_all(obj, rval);
|
|
1544
1755
|
break;
|
|
1545
1756
|
}
|
|
1546
1757
|
case CA_REG_METHOD_CALL: {
|
|
1547
|
-
|
|
1758
|
+
ca_store_method_call_ctx_t c;
|
|
1548
1759
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
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);
|
|
1553
1767
|
break;
|
|
1554
1768
|
}
|
|
1555
1769
|
case CA_REG_MEMBER: {
|
|
@@ -1627,15 +1841,13 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1627
1841
|
Check_Type(rdim, T_ARRAY);
|
|
1628
1842
|
Check_Type(ridx, T_ARRAY);
|
|
1629
1843
|
|
|
1630
|
-
elements = 1;
|
|
1631
1844
|
ndim = (int) RARRAY_LEN(rdim);
|
|
1845
|
+
CA_CHECK_RANK(ndim);
|
|
1632
1846
|
for (i=0; i<ndim; i++) {
|
|
1633
1847
|
dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
1634
|
-
elements *= dim[i];
|
|
1635
1848
|
}
|
|
1636
|
-
|
|
1637
|
-
CA_CHECK_RANK(ndim);
|
|
1638
1849
|
CA_CHECK_DIM(ndim, dim);
|
|
1850
|
+
elements = ca_shape_elements(ndim, dim, 1);
|
|
1639
1851
|
|
|
1640
1852
|
info.range_check = 1;
|
|
1641
1853
|
rb_ca_scan_index(ndim, dim, elements,
|
|
@@ -1699,7 +1911,7 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1699
1911
|
info.index[i].symbol.spec));
|
|
1700
1912
|
break;
|
|
1701
1913
|
default:
|
|
1702
|
-
rb_raise(
|
|
1914
|
+
rb_raise(rb_eIndexError, "unknown index spec");
|
|
1703
1915
|
}
|
|
1704
1916
|
}
|
|
1705
1917
|
break;
|
|
@@ -1767,7 +1979,7 @@ rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
|
1767
1979
|
rb_ary_store(rindex, i, ID2SYM(info.index[i].symbol.id));
|
|
1768
1980
|
break;
|
|
1769
1981
|
default:
|
|
1770
|
-
rb_raise(
|
|
1982
|
+
rb_raise(rb_eIndexError, "unknown index spec");
|
|
1771
1983
|
}
|
|
1772
1984
|
}
|
|
1773
1985
|
return rindex;
|
|
@@ -1814,8 +2026,8 @@ parse_shape_kwarg (VALUE rshape, int *out_ndim, ca_size_t *dim,
|
|
|
1814
2026
|
rb_raise(rb_eArgError, "negative dim %" PRId64 " at axis %d",
|
|
1815
2027
|
(ca_size_t) dim[i], i);
|
|
1816
2028
|
}
|
|
1817
|
-
elements *= dim[i];
|
|
1818
2029
|
}
|
|
2030
|
+
elements = ca_shape_elements(ndim, dim, 1);
|
|
1819
2031
|
*out_ndim = ndim;
|
|
1820
2032
|
*out_elements = elements;
|
|
1821
2033
|
}
|
|
@@ -1829,12 +2041,7 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1829
2041
|
/* Scalar path (Integer input): returns Ruby Array of N Integers.
|
|
1830
2042
|
* Preserves legacy shape for callers like `i, j = ca.addr2index(k)`. */
|
|
1831
2043
|
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
|
-
}
|
|
2044
|
+
ca_size_t addr = ca_index_in_range(NUM2SIZE(raddr), elements, "address");
|
|
1838
2045
|
out = rb_ary_new2(ndim);
|
|
1839
2046
|
for (i = ndim - 1; i >= 0; i--) {
|
|
1840
2047
|
rb_ary_store(out, i, SIZE2NUM(addr % dim[i]));
|
|
@@ -1852,8 +2059,9 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1852
2059
|
ca_size_t j, n;
|
|
1853
2060
|
volatile VALUE objs[CA_RANK_MAX];
|
|
1854
2061
|
|
|
2062
|
+
ca_check_index_array(raddr);
|
|
1855
2063
|
cin = ca_wrap_readonly(raddr, CA_SIZE);
|
|
1856
|
-
ca_attach(cin);
|
|
2064
|
+
ca_attach(cin); /* window: detached before its one raise */
|
|
1857
2065
|
|
|
1858
2066
|
out = rb_ary_new2(ndim);
|
|
1859
2067
|
for (i = 0; i < ndim; i++) {
|
|
@@ -1882,12 +2090,11 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1882
2090
|
continue;
|
|
1883
2091
|
}
|
|
1884
2092
|
addr = src[j];
|
|
1885
|
-
if ( addr <
|
|
2093
|
+
if ( addr < -elements || addr >= elements ) {
|
|
1886
2094
|
ca_detach(cin);
|
|
1887
|
-
|
|
1888
|
-
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1889
|
-
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
2095
|
+
ca_index_out_of_range(addr, elements, "address");
|
|
1890
2096
|
}
|
|
2097
|
+
addr = ca_index_in_range(addr, elements, "address");
|
|
1891
2098
|
for (k = ndim - 1; k >= 0; k--) {
|
|
1892
2099
|
p_out[k][j] = addr % dim[k];
|
|
1893
2100
|
addr /= dim[k];
|
|
@@ -1900,14 +2107,87 @@ addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
|
1900
2107
|
}
|
|
1901
2108
|
}
|
|
1902
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
|
+
|
|
1903
2122
|
static VALUE
|
|
1904
|
-
|
|
2123
|
+
ca_index2addr_body (VALUE arg)
|
|
1905
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;
|
|
1906
2130
|
volatile VALUE obj;
|
|
1907
|
-
CArray *co
|
|
2131
|
+
CArray *co;
|
|
1908
2132
|
ca_size_t *q, *p[CA_RANK_MAX], s[CA_RANK_MAX];
|
|
1909
2133
|
ca_size_t addr, k, n;
|
|
1910
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;
|
|
1911
2191
|
int i, all_number = 1;
|
|
1912
2192
|
int out_ndim = 1;
|
|
1913
2193
|
ca_size_t out_dim[CA_RANK_MAX];
|
|
@@ -1941,6 +2221,7 @@ index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
|
1941
2221
|
* the first non-scalar CArray input; other non-scalar inputs must
|
|
1942
2222
|
* match that shape. */
|
|
1943
2223
|
for (i = 0; i < ndim; i++) {
|
|
2224
|
+
ca_check_index_array(argv[i]);
|
|
1944
2225
|
cidx[i] = ca_wrap_readonly(argv[i], CA_SIZE);
|
|
1945
2226
|
if ( ! ca_is_scalar(cidx[i]) ) {
|
|
1946
2227
|
if ( shape_from < 0 ) {
|
|
@@ -1969,56 +2250,19 @@ index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
|
1969
2250
|
}
|
|
1970
2251
|
}
|
|
1971
2252
|
|
|
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
|
-
}
|
|
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);
|
|
2017
2265
|
}
|
|
2018
|
-
|
|
2019
|
-
for (i = 0; i < ndim; i++) { ca_detach(cidx[i]); }
|
|
2020
|
-
|
|
2021
|
-
return obj;
|
|
2022
2266
|
}
|
|
2023
2267
|
|
|
2024
2268
|
VALUE
|