carray 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +104 -81
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_obj_stack.c
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
partial cost)
|
|
13
13
|
- conditional fold_stride: counts[0] == 1 → fold to that parent;
|
|
14
14
|
multi-parent → fold boundary (decline)
|
|
15
|
-
- create_mask:
|
|
16
|
-
|
|
15
|
+
- create_mask: a mask CAStack over the parents' masks, with an all-false
|
|
16
|
+
stand-in for a parent that has none (ca_multi_parent_mask)
|
|
17
17
|
|
|
18
18
|
---------------------------------------------------------------------------- */
|
|
19
19
|
|
|
20
20
|
#include "carray.h"
|
|
21
|
-
#include "carray_internal.h" /* ca_attach_all */
|
|
21
|
+
#include "carray_internal.h" /* ca_attach_all / ca_sync_all */
|
|
22
22
|
#include "ca_composite_dispatch.h"
|
|
23
23
|
#include "ca_obj_face.h"
|
|
24
24
|
|
|
@@ -87,9 +87,9 @@ ca_stack_check_uniform (int32_t n_parents, CArray **parents)
|
|
|
87
87
|
CArray *p = parents[i];
|
|
88
88
|
if ( p->data_type != ref->data_type ) {
|
|
89
89
|
rb_raise(rb_eArgError,
|
|
90
|
-
"
|
|
91
|
-
"(
|
|
92
|
-
ref->data_type, i, p->data_type);
|
|
90
|
+
"stack: the arrays must have the same data type "
|
|
91
|
+
"(array 0 is %s, array %d is %s)",
|
|
92
|
+
ca_type_name[ref->data_type], i, ca_type_name[p->data_type]);
|
|
93
93
|
}
|
|
94
94
|
if ( p->ndim != ref->ndim ) {
|
|
95
95
|
rb_raise(rb_eArgError,
|
|
@@ -117,17 +117,6 @@ ca_stack_check_uniform (int32_t n_parents, CArray **parents)
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
/* One-level strip of a Face VALUE to its storage-side parent (non-Face as-is).
|
|
121
|
-
Used to keep the @parent GC/`.parent` ivar in step with the pre-stripped C
|
|
122
|
-
parents so the Ruby-visible chain of a stacked Face is single-Face too. */
|
|
123
|
-
static VALUE
|
|
124
|
-
ca_stack_face_parent1 (VALUE v)
|
|
125
|
-
{
|
|
126
|
-
CArray *c;
|
|
127
|
-
TypedData_Get_Struct(v, CArray, &carray_data_type, c);
|
|
128
|
-
return ca_is_face(c) ? rb_ca_parent(v) : v;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
120
|
int
|
|
132
121
|
ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
133
122
|
int8_t k_axis)
|
|
@@ -136,6 +125,26 @@ ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
|
136
125
|
int32_t i;
|
|
137
126
|
int8_t a;
|
|
138
127
|
|
|
128
|
+
/* ca == NULL asks for the checks only, so that a constructor can run
|
|
129
|
+
them before it allocates. They see the parents as the setup will,
|
|
130
|
+
one Face level down, without changing the caller's list. */
|
|
131
|
+
if ( ca == NULL ) {
|
|
132
|
+
volatile VALUE holder = 0;
|
|
133
|
+
CArray **seen = ALLOCV_N(CArray *, holder, n_parents > 0 ? n_parents : 1);
|
|
134
|
+
for ( i = 0; i < n_parents; i++ ) {
|
|
135
|
+
seen[i] = ca_is_face(parents[i]) ? CAVIEW(parents[i])->parent : parents[i];
|
|
136
|
+
}
|
|
137
|
+
ca_stack_check_uniform(n_parents, seen);
|
|
138
|
+
ca_check_rank_fits(seen[0]->ndim + 1, NULL);
|
|
139
|
+
if ( k_axis < 0 || k_axis > seen[0]->ndim ) {
|
|
140
|
+
rb_raise(rb_eArgError,
|
|
141
|
+
"CAStack k_axis %d out of range [0, %d]",
|
|
142
|
+
(int) k_axis, (int) seen[0]->ndim);
|
|
143
|
+
}
|
|
144
|
+
ALLOCV_END(holder);
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
139
148
|
/* §8.3 / MEMO_FACE_DOUBLE_LIFT §15.3: pre-strip Face parents one level to
|
|
140
149
|
storage so a stacked Face lifts to a single-Face chain
|
|
141
150
|
(CATime[CAStack[entity, ...]]) instead of a Face on top of Face parents.
|
|
@@ -152,6 +161,7 @@ ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
|
152
161
|
ca_stack_check_uniform(n_parents, parents);
|
|
153
162
|
ref = parents[0];
|
|
154
163
|
|
|
164
|
+
ca_check_rank_fits(ref->ndim + 1, NULL);
|
|
155
165
|
if ( k_axis < 0 || k_axis > ref->ndim ) {
|
|
156
166
|
rb_raise(rb_eArgError,
|
|
157
167
|
"CAStack k_axis %d out of range [0, %d]",
|
|
@@ -171,6 +181,8 @@ ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
|
171
181
|
ca->attach = 0;
|
|
172
182
|
ca->nosync = 0;
|
|
173
183
|
|
|
184
|
+
ca->mask_standins = NULL;
|
|
185
|
+
ca->mask_owner = NULL;
|
|
174
186
|
ca->n_parents = n_parents;
|
|
175
187
|
ca->parents = ALLOC_N(CArray *, n_parents);
|
|
176
188
|
for ( i = 0; i < n_parents; i++ ) {
|
|
@@ -186,7 +198,7 @@ ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
|
186
198
|
ca->dim[k_axis] = n_parents;
|
|
187
199
|
for ( a = k_axis + 1; a < ca->ndim; a++ ) ca->dim[a] = ref->dim[a - 1];
|
|
188
200
|
|
|
189
|
-
/* mask: lazy
|
|
201
|
+
/* mask: lazy, built on first mask access. */
|
|
190
202
|
return 0;
|
|
191
203
|
}
|
|
192
204
|
|
|
@@ -199,7 +211,9 @@ ca_stack_setup (CAStack *ca, int32_t n_parents, CArray **parents)
|
|
|
199
211
|
CAStack *
|
|
200
212
|
ca_stack_new_with_axis (int32_t n_parents, CArray **parents, int8_t k_axis)
|
|
201
213
|
{
|
|
202
|
-
CAStack *ca
|
|
214
|
+
CAStack *ca;
|
|
215
|
+
ca_stack_setup_with_axis(NULL, n_parents, parents, k_axis);
|
|
216
|
+
ca = ALLOC(CAStack);
|
|
203
217
|
ca_stack_setup_with_axis(ca, n_parents, parents, k_axis);
|
|
204
218
|
return ca;
|
|
205
219
|
}
|
|
@@ -216,6 +230,13 @@ free_ca_stack (void *ap)
|
|
|
216
230
|
CAStack *ca = (CAStack *) ap;
|
|
217
231
|
if ( ca != NULL ) {
|
|
218
232
|
ca_free(ca->mask);
|
|
233
|
+
if ( ca->mask_standins ) {
|
|
234
|
+
int32_t k;
|
|
235
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
236
|
+
if ( ca->mask_standins[k] ) ca_free(ca->mask_standins[k]);
|
|
237
|
+
}
|
|
238
|
+
xfree(ca->mask_standins);
|
|
239
|
+
}
|
|
219
240
|
xfree(ca->parents);
|
|
220
241
|
xfree(ca->dim);
|
|
221
242
|
xfree(ca);
|
|
@@ -235,17 +256,40 @@ ca_stack_func_clone (void *ap)
|
|
|
235
256
|
|
|
236
257
|
/* view[..., k at k_axis, ...] = parents[k][parent_idx]
|
|
237
258
|
where parent_idx = idx[] with the k_axis slot removed. */
|
|
259
|
+
/* On the mask of a CAStack: let its stand-ins give way to the parents' own
|
|
260
|
+
masks (see ca_multi_parent_mask_refresh). */
|
|
261
|
+
static void
|
|
262
|
+
ca_stack_mask_refresh (CAStack *ca)
|
|
263
|
+
{
|
|
264
|
+
CAStack *o = (CAStack *) ca->mask_owner;
|
|
265
|
+
if ( o != NULL ) {
|
|
266
|
+
ca_multi_parent_mask_refresh((CArray *) ca, o->parents, o->mask_standins,
|
|
267
|
+
o->n_parents);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
static void
|
|
272
|
+
ca_stack_mask_settle (CAStack *ca)
|
|
273
|
+
{
|
|
274
|
+
CAStack *o = (CAStack *) ca->mask_owner;
|
|
275
|
+
if ( o != NULL ) {
|
|
276
|
+
ca_multi_parent_mask_settle((CArray *) ca, o->parents, o->mask_standins,
|
|
277
|
+
o->n_parents);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
238
281
|
static void
|
|
239
282
|
ca_stack_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
240
283
|
{
|
|
241
284
|
CAStack *ca = (CAStack *) ap;
|
|
285
|
+
ca_stack_mask_refresh(ca);
|
|
242
286
|
int8_t k_axis = ca->k_axis;
|
|
243
287
|
ca_size_t k = idx[k_axis];
|
|
244
288
|
if ( k < 0 || k >= ca->n_parents ) {
|
|
245
289
|
rb_raise(rb_eIndexError, "CAStack k-axis (axis %d) index %lld out of range [0, %d)",
|
|
246
290
|
(int) k_axis, (long long) k, (int) ca->n_parents);
|
|
247
291
|
}
|
|
248
|
-
if ( k_axis == 0 ) {
|
|
292
|
+
if ( k_axis == 0 && ca_fast_paths_enabled() ) {
|
|
249
293
|
/* Fast path: parent_idx = idx[1..ndim-1]; pass idx+1 directly. */
|
|
250
294
|
ca_xfer_index(ca->parents[k], idx + 1, data, dir);
|
|
251
295
|
return;
|
|
@@ -274,6 +318,7 @@ ca_stack_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
274
318
|
void *data, int dir)
|
|
275
319
|
{
|
|
276
320
|
CAStack *ca = (CAStack *) ap;
|
|
321
|
+
ca_stack_mask_refresh(ca);
|
|
277
322
|
int8_t k_axis = ca->k_axis;
|
|
278
323
|
ca_size_t parent_elements = ca->parents[0]->elements;
|
|
279
324
|
ca_size_t bytes = ca->bytes;
|
|
@@ -286,7 +331,7 @@ ca_stack_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
286
331
|
paddrs = ALLOCV_N(ca_size_t, holder1, n);
|
|
287
332
|
pdata = ALLOCV_N(char, holder2, n * bytes);
|
|
288
333
|
|
|
289
|
-
if ( k_axis == 0 ) {
|
|
334
|
+
if ( k_axis == 0 && ca_fast_paths_enabled() ) {
|
|
290
335
|
/* Fast path: addr = k * parent_elements + parent_addr (row-major over
|
|
291
336
|
view shape with K at axis 0). */
|
|
292
337
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
@@ -398,7 +443,9 @@ static void
|
|
|
398
443
|
ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
399
444
|
ca_size_t *strides, void *data, int dir)
|
|
400
445
|
{
|
|
446
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
401
447
|
CAStack *ca = (CAStack *) ap;
|
|
448
|
+
ca_stack_mask_refresh(ca);
|
|
402
449
|
int8_t k_axis = ca->k_axis;
|
|
403
450
|
int8_t pndim = ca->ndim - 1;
|
|
404
451
|
ca_size_t native[CA_RANK_MAX], dstride[CA_RANK_MAX];
|
|
@@ -419,19 +466,24 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
419
466
|
s *= ca->parents[0]->dim[i];
|
|
420
467
|
}
|
|
421
468
|
|
|
422
|
-
/* Structural iff strides[k] == native[k] for all k
|
|
469
|
+
/* Structural iff strides[k] == native[k] for all k and the request is a
|
|
470
|
+
box over the view's own axes. Equal strides alone are not enough: a
|
|
471
|
+
size-1 axis gives two axes the same native stride, and a flat window
|
|
472
|
+
reshaped back to ndim has native strides yet wraps across an axis. The
|
|
473
|
+
request is over the view's addresses; see
|
|
474
|
+
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
423
475
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
424
476
|
if ( strides[i] != native[i] ) { structural = 0; break; }
|
|
425
477
|
}
|
|
478
|
+
if ( structural &&
|
|
479
|
+
! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
480
|
+
structural = 0;
|
|
481
|
+
}
|
|
482
|
+
if ( ! ca_fast_paths_enabled() ) structural = 0;
|
|
426
483
|
|
|
427
484
|
if ( structural ) {
|
|
428
485
|
ca_size_t k_lo = starts[k_axis];
|
|
429
486
|
ca_size_t k_hi = starts[k_axis] + counts[k_axis];
|
|
430
|
-
if ( k_lo < 0 || k_hi > ca->n_parents ) {
|
|
431
|
-
rb_raise(rb_eIndexError,
|
|
432
|
-
"CAStack xfer_stride k-axis (axis %d) [%lld, %lld) out of range [0, %d)",
|
|
433
|
-
(int) k_axis, (long long) k_lo, (long long) k_hi, (int) ca->n_parents);
|
|
434
|
-
}
|
|
435
487
|
|
|
436
488
|
/* dst row-major byte strides over output counts[]. */
|
|
437
489
|
s = ca->bytes;
|
|
@@ -486,6 +538,7 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
486
538
|
ca_size_t pidx[CA_RANK_MAX];
|
|
487
539
|
ca_size_t paddr = 0;
|
|
488
540
|
for ( a = 0; a < pndim; a++ ) pidx[a] = 0;
|
|
541
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
489
542
|
while ( 1 ) {
|
|
490
543
|
ca_size_t voff = k_off;
|
|
491
544
|
for ( a = 0; a < k_axis; a++ ) voff += pidx[a] * dstride[a];
|
|
@@ -518,7 +571,7 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
518
571
|
with native[k_axis] removed, in order. */
|
|
519
572
|
{
|
|
520
573
|
int8_t p = -1;
|
|
521
|
-
int reloc =
|
|
574
|
+
int reloc = ca_fast_paths_enabled();
|
|
522
575
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
523
576
|
if ( strides[i] == native[k_axis] ) { p = i; break; }
|
|
524
577
|
}
|
|
@@ -538,21 +591,33 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
538
591
|
if ( strides[i] != native[v] ) { reloc = 0; break; }
|
|
539
592
|
}
|
|
540
593
|
}
|
|
594
|
+
/* Each output axis must stay inside the view axis it was matched to;
|
|
595
|
+
otherwise the request wraps (or the match was one of two axes sharing
|
|
596
|
+
a native stride because the other has size 1), and only the per-cell
|
|
597
|
+
walk reads it correctly. */
|
|
598
|
+
if ( reloc ) {
|
|
599
|
+
for ( i = 0; i < ca->ndim; i++ ) {
|
|
600
|
+
int8_t j, v;
|
|
601
|
+
if ( counts[i] <= 1 ) continue;
|
|
602
|
+
if ( i == p ) {
|
|
603
|
+
v = k_axis;
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
j = (i < p) ? i : (i - 1);
|
|
607
|
+
v = (j < k_axis) ? j : (j + 1);
|
|
608
|
+
}
|
|
609
|
+
if ( starts[v] + counts[i] > ca->dim[v] ) { reloc = 0; break; }
|
|
610
|
+
}
|
|
611
|
+
}
|
|
541
612
|
if ( reloc ) {
|
|
542
|
-
ca_size_t kk_lo = starts[k_axis];
|
|
543
|
-
ca_size_t kk_hi = starts[k_axis] + counts[p];
|
|
544
613
|
ca_size_t odo[CA_RANK_MAX];
|
|
545
614
|
int8_t a;
|
|
546
|
-
if ( kk_lo < 0 || kk_hi > ca->n_parents ) {
|
|
547
|
-
rb_raise(rb_eIndexError,
|
|
548
|
-
"CAStack xfer_stride k-axis [%lld, %lld) out of range [0, %d)",
|
|
549
|
-
(long long) kk_lo, (long long) kk_hi, (int) ca->n_parents);
|
|
550
|
-
}
|
|
551
615
|
if ( p == ca->ndim - 1 ) {
|
|
552
616
|
/* K innermost: per-cell via the parent's xfer_index directly, escaping
|
|
553
617
|
the CAStack-level addr2index dispatch hop in the per-cell fallback. */
|
|
554
618
|
ca_size_t pidx[CA_RANK_MAX], doff = 0;
|
|
555
619
|
for ( i = 0; i < ca->ndim; i++ ) odo[i] = 0;
|
|
620
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
556
621
|
while ( 1 ) {
|
|
557
622
|
ca_size_t k2 = starts[k_axis] + odo[p];
|
|
558
623
|
for ( a = 0; a < pndim; a++ ) {
|
|
@@ -571,6 +636,7 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
571
636
|
s = ca->bytes;
|
|
572
637
|
for ( i = ca->ndim - 1; i >= 0; i-- ) { dstride[i] = s; s *= counts[i]; }
|
|
573
638
|
for ( i = 0; i <= p; i++ ) odo[i] = 0;
|
|
639
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
574
640
|
while ( 1 ) {
|
|
575
641
|
ca_size_t k2 = starts[k_axis] + odo[p];
|
|
576
642
|
ca_size_t doff = 0;
|
|
@@ -600,6 +666,7 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
600
666
|
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
601
667
|
for ( i = 0; i < ca->ndim; i++ ) base += starts[i] * native[i];
|
|
602
668
|
for ( i = 0; i < ca->ndim; i++ ) idx[i] = 0;
|
|
669
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
603
670
|
while ( 1 ) {
|
|
604
671
|
ca_size_t toff = base, vidx[CA_RANK_MAX];
|
|
605
672
|
for ( i = 0; i < ca->ndim; i++ ) toff += idx[i] * strides[i];
|
|
@@ -624,20 +691,34 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
624
691
|
- k_axis != 0: per-parent contiguous read into a temp buffer, then
|
|
625
692
|
scattered-write to dst at view row-major positions. This is the
|
|
626
693
|
correctness path (per-parent contig-read / scattered-write), not a
|
|
627
|
-
perf-optimised one.
|
|
694
|
+
perf-optimised one.
|
|
695
|
+
|
|
696
|
+
into_buffers (PUT only) writes each parent's cells into the buffer its
|
|
697
|
+
attach handed out, rather than through the parent to what is behind it:
|
|
698
|
+
the sync of an attached stack, which then syncs each parent. Writing
|
|
699
|
+
past the buffer would leave it stale, and the parent's own sync would
|
|
700
|
+
push the stale buffer back over the cells just written. */
|
|
628
701
|
static void
|
|
629
|
-
|
|
702
|
+
ca_stack_xfer_parents (CAStack *ca, char *d, int dir, int into_buffers)
|
|
630
703
|
{
|
|
631
|
-
CAStack *ca = (CAStack *) ap;
|
|
632
704
|
int8_t k_axis = ca->k_axis;
|
|
633
705
|
ca_size_t bytes = ca->bytes;
|
|
634
|
-
char *d = (char *) data;
|
|
635
706
|
int32_t k;
|
|
636
707
|
|
|
637
|
-
|
|
708
|
+
/* The walk below visits a parent's first cell before it tests the
|
|
709
|
+
counts. */
|
|
710
|
+
if ( ca->elements == 0 ) return;
|
|
711
|
+
|
|
712
|
+
if ( k_axis == 0 && ca_fast_paths_enabled() ) {
|
|
638
713
|
ca_size_t parent_bytes_total = ca->parents[0]->elements * bytes;
|
|
639
714
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
640
|
-
|
|
715
|
+
if ( into_buffers ) {
|
|
716
|
+
memcpy(ca->parents[k]->ptr, d + k * parent_bytes_total,
|
|
717
|
+
(size_t) parent_bytes_total);
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
ca_xfer_all(ca->parents[k], d + k * parent_bytes_total, dir);
|
|
721
|
+
}
|
|
641
722
|
}
|
|
642
723
|
return;
|
|
643
724
|
}
|
|
@@ -695,6 +776,7 @@ ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
|
695
776
|
}
|
|
696
777
|
else if ( dir == CA_XFER_GET ) {
|
|
697
778
|
/* dir-hoisted GET inner loop, incremental voff. */
|
|
779
|
+
/* empty: the function returns on an empty view at its entry */
|
|
698
780
|
while ( 1 ) {
|
|
699
781
|
memcpy(d + voff, buf + paddr_bytes, bytes);
|
|
700
782
|
paddr_bytes += bytes;
|
|
@@ -710,6 +792,7 @@ ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
|
710
792
|
}
|
|
711
793
|
else {
|
|
712
794
|
/* dir-hoisted PUT inner loop, incremental voff. */
|
|
795
|
+
/* empty: the function returns on an empty view at its entry */
|
|
713
796
|
while ( 1 ) {
|
|
714
797
|
memcpy(buf + paddr_bytes, d + voff, bytes);
|
|
715
798
|
paddr_bytes += bytes;
|
|
@@ -725,7 +808,12 @@ ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
|
725
808
|
}
|
|
726
809
|
|
|
727
810
|
if ( dir == CA_XFER_PUT ) {
|
|
728
|
-
|
|
811
|
+
if ( into_buffers ) {
|
|
812
|
+
memcpy(ca->parents[k]->ptr, buf, (size_t) (parent_elements * bytes));
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
ca_xfer_all(ca->parents[k], buf, CA_XFER_PUT);
|
|
816
|
+
}
|
|
729
817
|
}
|
|
730
818
|
}
|
|
731
819
|
}
|
|
@@ -733,6 +821,13 @@ ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
|
733
821
|
}
|
|
734
822
|
}
|
|
735
823
|
|
|
824
|
+
static void
|
|
825
|
+
ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
826
|
+
{
|
|
827
|
+
ca_stack_mask_refresh((CAStack *) ap);
|
|
828
|
+
ca_stack_xfer_parents((CAStack *) ap, (char *) data, dir, 0);
|
|
829
|
+
}
|
|
830
|
+
|
|
736
831
|
/* ------------------------------------------------------------------- */
|
|
737
832
|
/* attach / sync / detach (materialise via xfer_all) */
|
|
738
833
|
/* ------------------------------------------------------------------- */
|
|
@@ -741,28 +836,37 @@ static void
|
|
|
741
836
|
ca_stack_func_allocate (void *ap)
|
|
742
837
|
{
|
|
743
838
|
CAStack *ca = (CAStack *) ap;
|
|
839
|
+
ca_stack_mask_refresh(ca);
|
|
744
840
|
ca_attach_all(ca->parents, ca->n_parents);
|
|
745
|
-
ca->ptr =
|
|
841
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
static VALUE
|
|
845
|
+
ca_stack_attach_owned (VALUE arg)
|
|
846
|
+
{
|
|
847
|
+
ca_axis_view_attach_owned((void *) arg);
|
|
848
|
+
return Qnil;
|
|
746
849
|
}
|
|
747
850
|
|
|
748
851
|
static void
|
|
749
852
|
ca_stack_func_attach (void *ap)
|
|
750
853
|
{
|
|
751
854
|
CAStack *ca = (CAStack *) ap;
|
|
855
|
+
ca_stack_mask_refresh(ca);
|
|
752
856
|
ca_attach_all(ca->parents, ca->n_parents);
|
|
753
|
-
ca->
|
|
754
|
-
ca_stack_func_xfer_all(ca, ca->ptr, CA_XFER_GET);
|
|
857
|
+
ca_fill_or_detach(ca->n_parents, ca->parents, ca_stack_attach_owned, (VALUE) ca);
|
|
755
858
|
}
|
|
756
859
|
|
|
860
|
+
static void ca_stack_mask_refuse_sync (CAStack *ca);
|
|
861
|
+
|
|
757
862
|
static void
|
|
758
863
|
ca_stack_func_sync (void *ap)
|
|
759
864
|
{
|
|
760
865
|
CAStack *ca = (CAStack *) ap;
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
}
|
|
866
|
+
ca_stack_mask_refuse_sync(ca);
|
|
867
|
+
ca_stack_xfer_parents(ca, ca->ptr, CA_XFER_PUT, 1);
|
|
868
|
+
ca_sync_all(ca->parents, ca->n_parents);
|
|
869
|
+
ca_stack_mask_settle(ca);
|
|
766
870
|
}
|
|
767
871
|
|
|
768
872
|
static void
|
|
@@ -785,6 +889,7 @@ static void
|
|
|
785
889
|
ca_stack_func_fill_data (void *ap, void *ptr)
|
|
786
890
|
{
|
|
787
891
|
CAStack *ca = (CAStack *) ap;
|
|
892
|
+
ca_stack_mask_refresh(ca);
|
|
788
893
|
int32_t k;
|
|
789
894
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
790
895
|
ca_fill(ca->parents[k], ptr);
|
|
@@ -792,12 +897,13 @@ ca_stack_func_fill_data (void *ap, void *ptr)
|
|
|
792
897
|
}
|
|
793
898
|
|
|
794
899
|
/* ------------------------------------------------------------------- */
|
|
795
|
-
/* create_mask
|
|
900
|
+
/* create_mask */
|
|
796
901
|
/* ------------------------------------------------------------------- */
|
|
797
902
|
|
|
798
|
-
/*
|
|
799
|
-
|
|
800
|
-
re-used as its own mask
|
|
903
|
+
/* The mask is a CAStack over the K parents' masks, a stand-in standing
|
|
904
|
+
for a parent that has none (ca_multi_parent_mask), so building it gives
|
|
905
|
+
no parent a mask. Self-similar (= CAStack re-used as its own mask
|
|
906
|
+
class). */
|
|
801
907
|
static void
|
|
802
908
|
ca_stack_func_create_mask (void *ap)
|
|
803
909
|
{
|
|
@@ -807,12 +913,13 @@ ca_stack_func_create_mask (void *ap)
|
|
|
807
913
|
int32_t k;
|
|
808
914
|
|
|
809
915
|
mask_parents = ALLOCV_N(CArray *, holder, ca->n_parents);
|
|
916
|
+
if ( ! ca->mask_standins ) {
|
|
917
|
+
ca->mask_standins = ALLOC_N(CArray *, ca->n_parents);
|
|
918
|
+
MEMZERO(ca->mask_standins, CArray *, ca->n_parents);
|
|
919
|
+
}
|
|
810
920
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
ca_create_mask(ca->parents[k]);
|
|
814
|
-
}
|
|
815
|
-
mask_parents[k] = ca->parents[k]->mask;
|
|
921
|
+
mask_parents[k] = ca_multi_parent_mask(ca->parents[k],
|
|
922
|
+
&ca->mask_standins[k]);
|
|
816
923
|
}
|
|
817
924
|
/* Build the mask stack with the parent's k_axis from the start so its
|
|
818
925
|
dim[] is laid out for that axis. (Patching ->k_axis after a default
|
|
@@ -821,6 +928,7 @@ ca_stack_func_create_mask (void *ap)
|
|
|
821
928
|
xfer_stride k-range check when k_axis != 0.) */
|
|
822
929
|
ca->mask = (CArray *) ca_stack_new_with_axis(ca->n_parents, mask_parents,
|
|
823
930
|
ca->k_axis);
|
|
931
|
+
((CAStack *) ca->mask)->mask_owner = (CArray *) ca;
|
|
824
932
|
ALLOCV_END(holder);
|
|
825
933
|
}
|
|
826
934
|
|
|
@@ -846,6 +954,13 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
846
954
|
ca_size_t k;
|
|
847
955
|
int8_t i;
|
|
848
956
|
|
|
957
|
+
/* The mask of a stack while it still reads stand-ins: a write must
|
|
958
|
+
reach the stack's transfer, which replaces them first. */
|
|
959
|
+
if ( ca->mask_owner != NULL
|
|
960
|
+
&& ((CAStack *) ca->mask_owner)->mask_standins != NULL ) {
|
|
961
|
+
return 0;
|
|
962
|
+
}
|
|
963
|
+
|
|
849
964
|
/* k_axis != 0: parent byte blocks are interleaved (not contig in view
|
|
850
965
|
buffer), so the byte-box containment check and the size-1 K-axis
|
|
851
966
|
degeneration below would require detecting the K-axis contribution
|
|
@@ -854,6 +969,7 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
854
969
|
through to CAStack.xfer_stride (k_axis-aware), which still delivers
|
|
855
970
|
correct (if non-folded) per-parent dispatch. */
|
|
856
971
|
if ( ca->k_axis != 0 ) return 0;
|
|
972
|
+
if ( ! ca_fast_paths_enabled() ) return 0;
|
|
857
973
|
|
|
858
974
|
for ( i = 0; i < f->ndim; i++ ) {
|
|
859
975
|
ca_size_t span = (f->counts[i] - 1) * f->strides[i];
|
|
@@ -876,6 +992,174 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
876
992
|
/* operation table */
|
|
877
993
|
/* ------------------------------------------------------------------- */
|
|
878
994
|
|
|
995
|
+
/* The table's write slots: after a write that may have put a true into a
|
|
996
|
+
stand-in, the true goes on to the parent's mask, or is refused for a
|
|
997
|
+
value array or a mask array (ca_mask_standin_settle). Only the mask of
|
|
998
|
+
a CAStack has stand-ins. */
|
|
999
|
+
/* A write to the mask of a CAStack, run once against blank masks first
|
|
1000
|
+
(ca_multi_parent_mask_refuse_first), so that a write refused for a value
|
|
1001
|
+
array or mask array part changes no other part. */
|
|
1002
|
+
enum { CA_STACK_PUT_INDEX, CA_STACK_PUT_ADDRS, CA_STACK_PUT_STRIDE, CA_STACK_PUT_ALL,
|
|
1003
|
+
CA_STACK_PUT_FILL, CA_STACK_PUT_SYNC, CA_STACK_PUT_FILL_ADDRS,
|
|
1004
|
+
CA_STACK_PUT_FILL_STRIDE };
|
|
1005
|
+
|
|
1006
|
+
typedef struct {
|
|
1007
|
+
int slot;
|
|
1008
|
+
void *ap;
|
|
1009
|
+
ca_size_t *idx;
|
|
1010
|
+
ca_size_t n;
|
|
1011
|
+
ca_size_t *addrs;
|
|
1012
|
+
ca_size_t *starts;
|
|
1013
|
+
ca_size_t *counts;
|
|
1014
|
+
ca_size_t *strides;
|
|
1015
|
+
void *data;
|
|
1016
|
+
ca_size_t base;
|
|
1017
|
+
int8_t ndim;
|
|
1018
|
+
ca_size_t *steps;
|
|
1019
|
+
} ca_stack_put_t;
|
|
1020
|
+
|
|
1021
|
+
static VALUE
|
|
1022
|
+
ca_stack_put_body (VALUE arg)
|
|
1023
|
+
{
|
|
1024
|
+
ca_stack_put_t *a = (ca_stack_put_t *) arg;
|
|
1025
|
+
switch ( a->slot ) {
|
|
1026
|
+
case CA_STACK_PUT_INDEX:
|
|
1027
|
+
ca_stack_func_xfer_index(a->ap, a->idx, a->data, CA_XFER_PUT); break;
|
|
1028
|
+
case CA_STACK_PUT_ADDRS:
|
|
1029
|
+
ca_stack_func_xfer_addrs(a->ap, a->n, a->addrs, a->data, CA_XFER_PUT); break;
|
|
1030
|
+
case CA_STACK_PUT_STRIDE:
|
|
1031
|
+
ca_stack_func_xfer_stride(a->ap, a->starts, a->counts, a->strides, a->data,
|
|
1032
|
+
CA_XFER_PUT); break;
|
|
1033
|
+
case CA_STACK_PUT_ALL:
|
|
1034
|
+
ca_stack_func_xfer_all(a->ap, a->data, CA_XFER_PUT); break;
|
|
1035
|
+
case CA_STACK_PUT_FILL:
|
|
1036
|
+
ca_stack_func_fill_data(a->ap, a->data); break;
|
|
1037
|
+
case CA_STACK_PUT_FILL_ADDRS:
|
|
1038
|
+
ca_fill_addrs_default(a->ap, a->n, a->addrs, a->data); break;
|
|
1039
|
+
case CA_STACK_PUT_FILL_STRIDE:
|
|
1040
|
+
ca_fill_stride_default(a->ap, a->base, a->ndim, a->counts, a->steps,
|
|
1041
|
+
a->data); break;
|
|
1042
|
+
case CA_STACK_PUT_SYNC:
|
|
1043
|
+
ca_stack_xfer_parents((CAStack *) a->ap, ((CArray *) a->ap)->ptr, CA_XFER_PUT, 1);
|
|
1044
|
+
break;
|
|
1045
|
+
}
|
|
1046
|
+
return Qnil;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
static void
|
|
1050
|
+
ca_stack_mask_refuse_first (ca_stack_put_t *a)
|
|
1051
|
+
{
|
|
1052
|
+
CAStack *o = (CAStack *) ((CAStack *) a->ap)->mask_owner;
|
|
1053
|
+
if ( o != NULL ) {
|
|
1054
|
+
ca_multi_parent_mask_refuse_first((CArray *) a->ap, o->parents,
|
|
1055
|
+
o->mask_standins, o->n_parents,
|
|
1056
|
+
ca_stack_put_body, (VALUE) a);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
static void
|
|
1061
|
+
ca_stack_mask_refuse_sync (CAStack *ca)
|
|
1062
|
+
{
|
|
1063
|
+
ca_stack_put_t a = { CA_STACK_PUT_SYNC, ca, NULL, 0, NULL, NULL, NULL, NULL, NULL };
|
|
1064
|
+
ca_stack_mask_refuse_first(&a);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
/* After a write of n cells of `data` to the mask of a CAStack: a true
|
|
1068
|
+
that went into a stand-in goes on to its parent's mask. */
|
|
1069
|
+
static void
|
|
1070
|
+
ca_stack_mask_settle_after (CAStack *ca, const void *data, ca_size_t n)
|
|
1071
|
+
{
|
|
1072
|
+
if ( ca->mask_owner != NULL && ca_mask_any_true(data, n) ) {
|
|
1073
|
+
ca_stack_mask_settle(ca);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
static void
|
|
1078
|
+
ca_stack_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
1079
|
+
{
|
|
1080
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1081
|
+
ca_stack_put_t a = { CA_STACK_PUT_INDEX, ap, idx, 0, NULL, NULL, NULL, NULL, data };
|
|
1082
|
+
ca_stack_mask_refuse_first(&a);
|
|
1083
|
+
}
|
|
1084
|
+
ca_stack_func_xfer_index(ap, idx, data, dir);
|
|
1085
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_settle_after((CAStack *) ap, data, 1);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
static void
|
|
1089
|
+
ca_stack_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
1090
|
+
int dir)
|
|
1091
|
+
{
|
|
1092
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1093
|
+
ca_stack_put_t a = { CA_STACK_PUT_ADDRS, ap, NULL, n, addrs, NULL, NULL, NULL, data };
|
|
1094
|
+
ca_stack_mask_refuse_first(&a);
|
|
1095
|
+
}
|
|
1096
|
+
ca_stack_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
1097
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_settle_after((CAStack *) ap, data, n);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
static void
|
|
1101
|
+
ca_stack_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
1102
|
+
ca_size_t *strides, void *data, int dir)
|
|
1103
|
+
{
|
|
1104
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1105
|
+
ca_stack_put_t a = { CA_STACK_PUT_STRIDE, ap, NULL, 0, NULL, starts, counts, strides, data };
|
|
1106
|
+
ca_stack_mask_refuse_first(&a);
|
|
1107
|
+
}
|
|
1108
|
+
ca_stack_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
1109
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1110
|
+
ca_stack_mask_settle_after((CAStack *) ap, data,
|
|
1111
|
+
ca_shape_elements(((CArray *) ap)->ndim, counts, 1));
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
static void
|
|
1116
|
+
ca_stack_put_xfer_all (void *ap, void *data, int dir)
|
|
1117
|
+
{
|
|
1118
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1119
|
+
ca_stack_put_t a = { CA_STACK_PUT_ALL, ap, NULL, 0, NULL, NULL, NULL, NULL, data };
|
|
1120
|
+
ca_stack_mask_refuse_first(&a);
|
|
1121
|
+
}
|
|
1122
|
+
ca_stack_func_xfer_all(ap, data, dir);
|
|
1123
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1124
|
+
ca_stack_mask_settle_after((CAStack *) ap, data, ((CArray *) ap)->elements);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
static void
|
|
1129
|
+
ca_stack_put_fill_data (void *ap, void *ptr)
|
|
1130
|
+
{
|
|
1131
|
+
{
|
|
1132
|
+
ca_stack_put_t a = { CA_STACK_PUT_FILL, ap, NULL, 0, NULL, NULL, NULL, NULL, ptr };
|
|
1133
|
+
ca_stack_mask_refuse_first(&a);
|
|
1134
|
+
}
|
|
1135
|
+
ca_stack_func_fill_data(ap, ptr);
|
|
1136
|
+
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/* A fill of part of the mask goes cell by cell through xfer_index; run
|
|
1140
|
+
the whole of it against blank masks first, so that a cell refused late
|
|
1141
|
+
does not leave the cells before it written. */
|
|
1142
|
+
static void
|
|
1143
|
+
ca_stack_put_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
|
|
1144
|
+
{
|
|
1145
|
+
ca_stack_put_t a = { CA_STACK_PUT_FILL_ADDRS, ap, NULL, n, addrs, NULL, NULL,
|
|
1146
|
+
NULL, ptr };
|
|
1147
|
+
ca_stack_mask_refuse_first(&a);
|
|
1148
|
+
ca_fill_addrs_default(ap, n, addrs, ptr);
|
|
1149
|
+
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
static void
|
|
1153
|
+
ca_stack_put_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
1154
|
+
ca_size_t *counts, ca_size_t *steps, void *ptr)
|
|
1155
|
+
{
|
|
1156
|
+
ca_stack_put_t a = { CA_STACK_PUT_FILL_STRIDE, ap, NULL, 0, NULL, NULL, counts,
|
|
1157
|
+
NULL, ptr, base, ndim, steps };
|
|
1158
|
+
ca_stack_mask_refuse_first(&a);
|
|
1159
|
+
ca_fill_stride_default(ap, base, ndim, counts, steps, ptr);
|
|
1160
|
+
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
879
1163
|
ca_operation_function_t ca_stack_func = {
|
|
880
1164
|
-1, /* CA_OBJ_STACK */
|
|
881
1165
|
CA_VIEW_ARRAY,
|
|
@@ -885,13 +1169,13 @@ ca_operation_function_t ca_stack_func = {
|
|
|
885
1169
|
ca_stack_func_attach,
|
|
886
1170
|
ca_stack_func_sync,
|
|
887
1171
|
ca_stack_func_detach,
|
|
888
|
-
|
|
1172
|
+
ca_stack_put_fill_data,
|
|
889
1173
|
ca_stack_func_create_mask,
|
|
890
|
-
|
|
891
|
-
|
|
1174
|
+
ca_stack_put_xfer_index,
|
|
1175
|
+
ca_stack_put_xfer_addrs,
|
|
892
1176
|
ca_stack_func_fold_stride,
|
|
893
|
-
|
|
894
|
-
|
|
1177
|
+
ca_stack_put_xfer_stride,
|
|
1178
|
+
ca_stack_put_xfer_all,
|
|
895
1179
|
};
|
|
896
1180
|
|
|
897
1181
|
/* ------------------------------------------------------------------- */
|
|
@@ -935,7 +1219,7 @@ rb_ca_stack_new_with_axis (VALUE parents_ary, int8_t k_axis)
|
|
|
935
1219
|
ca = ca_stack_new_with_axis((int32_t) n, parents, k_axis);
|
|
936
1220
|
obj = ca_wrap_struct(ca);
|
|
937
1221
|
rb_ivar_set(obj, id_parents, rb_ary_dup(parents_ary)); /* GC anchor */
|
|
938
|
-
rb_ca_set_parent(obj,
|
|
1222
|
+
rb_ca_set_parent(obj, ca_face_strip_one(rb_ary_entry(parents_ary, 0))); /* CAView base (Face-stripped, matches C ->parent) */
|
|
939
1223
|
ALLOCV_END(holder);
|
|
940
1224
|
return obj;
|
|
941
1225
|
}
|
|
@@ -963,8 +1247,14 @@ rb_ca_stack_initialize_copy (VALUE self, VALUE other)
|
|
|
963
1247
|
{
|
|
964
1248
|
CAStack *ca, *cs;
|
|
965
1249
|
TypedData_Get_Struct(self, CAStack, &castack_data_type, ca);
|
|
1250
|
+
ca_check_uninitialized(ca);
|
|
966
1251
|
TypedData_Get_Struct(other, CAStack, &castack_data_type, cs);
|
|
967
1252
|
ca_stack_setup_with_axis(ca, cs->n_parents, cs->parents, cs->k_axis);
|
|
1253
|
+
/* A copy of a stack's mask reads and writes the same stand-ins, so it
|
|
1254
|
+
answers to the same owner: its writes reach the parents' masks. The
|
|
1255
|
+
copy holds the owner alive through the masked_array ivar that dup
|
|
1256
|
+
carries over (see rb_ca_mask_array). */
|
|
1257
|
+
ca->mask_owner = cs->mask_owner;
|
|
968
1258
|
return self;
|
|
969
1259
|
}
|
|
970
1260
|
|
|
@@ -1001,10 +1291,11 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1001
1291
|
VALUE first = rb_ary_entry(list, 0);
|
|
1002
1292
|
rb_check_carray_object(first);
|
|
1003
1293
|
TypedData_Get_Struct(first, CArray, &carray_data_type, ref);
|
|
1004
|
-
k_axis = (int8_t)
|
|
1005
|
-
|
|
1294
|
+
k_axis = (int8_t) ca_normalize_axis_arg(
|
|
1295
|
+
axis_val, (int) ref->ndim + 1, "CAStack.new");
|
|
1006
1296
|
}
|
|
1007
1297
|
TypedData_Get_Struct(self, CAStack, &castack_data_type, ca);
|
|
1298
|
+
ca_check_uninitialized(ca);
|
|
1008
1299
|
parents = ALLOCV_N(CArray *, holder, n);
|
|
1009
1300
|
for ( i = 0; i < n; i++ ) {
|
|
1010
1301
|
VALUE p = rb_ary_entry(list, i);
|
|
@@ -1013,7 +1304,7 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1013
1304
|
}
|
|
1014
1305
|
ca_stack_setup_with_axis(ca, (int32_t) n, parents, k_axis);
|
|
1015
1306
|
rb_ivar_set(self, id_parents, rb_ary_dup(list)); /* GC anchor */
|
|
1016
|
-
rb_ca_set_parent(self,
|
|
1307
|
+
rb_ca_set_parent(self, ca_face_strip_one(rb_ary_entry(list, 0))); /* CAView base (Face-stripped, matches C ->parent) */
|
|
1017
1308
|
ALLOCV_END(holder);
|
|
1018
1309
|
return self;
|
|
1019
1310
|
}
|
|
@@ -1029,8 +1320,9 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1029
1320
|
this method)
|
|
1030
1321
|
- then ca_face_lift re-wraps the result as the same Face class,
|
|
1031
1322
|
carrying state from list[0]
|
|
1032
|
-
|
|
1033
|
-
|
|
1323
|
+
A single Face parent is lifted too. A list mixing Face and non-Face
|
|
1324
|
+
parents, or two Face classes, is refused; a non-Face list returns the
|
|
1325
|
+
raw CAStack (= same result as the inherited Class#new chain).
|
|
1034
1326
|
|
|
1035
1327
|
Replaces the Ruby-level CAStack.new override in lib/carray/compose.rb
|
|
1036
1328
|
(= used alias_method :__new_raw__, :new + class << self def new).
|
|
@@ -1039,68 +1331,23 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1039
1331
|
static VALUE
|
|
1040
1332
|
rb_ca_stack_s_new (int argc, VALUE *argv, VALUE klass)
|
|
1041
1333
|
{
|
|
1042
|
-
VALUE list, kwargs;
|
|
1043
|
-
long n, i;
|
|
1044
|
-
int all_face = 1;
|
|
1045
|
-
VALUE face_class = Qnil;
|
|
1046
|
-
CArray *ref_face = NULL;
|
|
1334
|
+
VALUE list, kwargs, face_class;
|
|
1047
1335
|
VALUE obj;
|
|
1048
1336
|
|
|
1049
1337
|
rb_scan_args(argc, argv, "1:", &list, &kwargs);
|
|
1050
1338
|
Check_Type(list, T_ARRAY);
|
|
1051
|
-
|
|
1052
|
-
if ( n <= 0 ) {
|
|
1339
|
+
if ( RARRAY_LEN(list) <= 0 ) {
|
|
1053
1340
|
rb_raise(rb_eArgError, "CAStack.new requires at least one parent");
|
|
1054
1341
|
}
|
|
1342
|
+
face_class = ca_face_list_class(list, "CAStack.new");
|
|
1055
1343
|
|
|
1056
|
-
/*
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1060
|
-
CArray *ca;
|
|
1061
|
-
rb_check_carray_object(p);
|
|
1062
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1063
|
-
if ( !ca_is_face(ca) ) { all_face = 0; break; }
|
|
1064
|
-
if ( i == 0 ) {
|
|
1065
|
-
face_class = rb_obj_class(p);
|
|
1066
|
-
ref_face = ca;
|
|
1067
|
-
} else if ( rb_obj_class(p) != face_class ) {
|
|
1068
|
-
all_face = 0; break;
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
/* Allocate + initialize raw CAStack. rb_obj_alloc calls the
|
|
1073
|
-
TypedData allocator directly (= bypasses the overridden Class#new,
|
|
1074
|
-
avoiding infinite recursion); rb_obj_call_init_kw dispatches to
|
|
1075
|
-
#initialize forwarding the kwargs hash (= Ruby 3.x strict kwarg
|
|
1076
|
-
separation requires the _kw variant when passing through). */
|
|
1344
|
+
/* rb_obj_alloc calls the TypedData allocator directly (= bypasses the
|
|
1345
|
+
overridden Class#new, avoiding infinite recursion); rb_obj_call_init_kw
|
|
1346
|
+
forwards the kwargs hash. */
|
|
1077
1347
|
obj = rb_obj_alloc(klass);
|
|
1078
1348
|
rb_obj_call_init_kw(obj, argc, argv, RB_PASS_CALLED_KEYWORDS);
|
|
1079
1349
|
|
|
1080
|
-
|
|
1081
|
-
if ( !all_face || n < 2 ) return obj;
|
|
1082
|
-
|
|
1083
|
-
/* Homogeneous Face: portable + pairwise state-compatible checks,
|
|
1084
|
-
then ca_face_lift to re-wrap as the same Face class. */
|
|
1085
|
-
if ( !ca_face_state_portable(ref_face->obj_type, face_class) ) {
|
|
1086
|
-
rb_raise(rb_eArgError,
|
|
1087
|
-
"CAStack.new: %s state is not portable across multiple "
|
|
1088
|
-
"parents (= per-parent storage like CAConstString's buffer); "
|
|
1089
|
-
"strip Face with .parent if a storage-level CAStack is intended",
|
|
1090
|
-
rb_class2name(face_class));
|
|
1091
|
-
}
|
|
1092
|
-
for ( i = 1; i < n; i++ ) {
|
|
1093
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1094
|
-
CArray *ca;
|
|
1095
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1096
|
-
if ( !ca_face_state_compatible(rb_ary_entry(list, 0), ref_face,
|
|
1097
|
-
p, ca) ) {
|
|
1098
|
-
rb_raise(rb_eArgError,
|
|
1099
|
-
"CAStack.new: Face state mismatch across parents "
|
|
1100
|
-
"(= %s instance at index %ld differs in state from index 0)",
|
|
1101
|
-
rb_class2name(face_class), i);
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1350
|
+
if ( NIL_P(face_class) ) return obj;
|
|
1104
1351
|
return ca_face_lift(obj, rb_ary_entry(list, 0));
|
|
1105
1352
|
}
|
|
1106
1353
|
|
|
@@ -1142,6 +1389,9 @@ Init_ca_obj_stack (void)
|
|
|
1142
1389
|
rb_cCAStack = rb_define_class("CAStack", rb_cCAView);
|
|
1143
1390
|
rb_cCAStackMask = rb_define_class("CAStackMask", rb_cCAStack);
|
|
1144
1391
|
|
|
1392
|
+
ca_stack_func.fill_addrs = ca_stack_put_fill_addrs;
|
|
1393
|
+
ca_stack_func.fill_stride = ca_stack_put_fill_stride;
|
|
1394
|
+
|
|
1145
1395
|
CA_OBJ_STACK = ca_install_obj_type(rb_cCAStack,
|
|
1146
1396
|
&castack_data_type,
|
|
1147
1397
|
rb_cCAStackMask,
|