carray 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_obj_stack.c
CHANGED
|
@@ -12,12 +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 / ca_sync_all */
|
|
21
22
|
#include "ca_composite_dispatch.h"
|
|
22
23
|
#include "ca_obj_face.h"
|
|
23
24
|
|
|
@@ -86,9 +87,9 @@ ca_stack_check_uniform (int32_t n_parents, CArray **parents)
|
|
|
86
87
|
CArray *p = parents[i];
|
|
87
88
|
if ( p->data_type != ref->data_type ) {
|
|
88
89
|
rb_raise(rb_eArgError,
|
|
89
|
-
"
|
|
90
|
-
"(
|
|
91
|
-
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]);
|
|
92
93
|
}
|
|
93
94
|
if ( p->ndim != ref->ndim ) {
|
|
94
95
|
rb_raise(rb_eArgError,
|
|
@@ -116,17 +117,6 @@ ca_stack_check_uniform (int32_t n_parents, CArray **parents)
|
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
/* One-level strip of a Face VALUE to its storage-side parent (non-Face as-is).
|
|
120
|
-
Used to keep the @parent GC/`.parent` ivar in step with the pre-stripped C
|
|
121
|
-
parents so the Ruby-visible chain of a stacked Face is single-Face too. */
|
|
122
|
-
static VALUE
|
|
123
|
-
ca_stack_face_parent1 (VALUE v)
|
|
124
|
-
{
|
|
125
|
-
CArray *c;
|
|
126
|
-
TypedData_Get_Struct(v, CArray, &carray_data_type, c);
|
|
127
|
-
return ca_is_face(c) ? rb_ca_parent(v) : v;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
120
|
int
|
|
131
121
|
ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
132
122
|
int8_t k_axis)
|
|
@@ -170,6 +160,8 @@ ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
|
170
160
|
ca->attach = 0;
|
|
171
161
|
ca->nosync = 0;
|
|
172
162
|
|
|
163
|
+
ca->mask_standins = NULL;
|
|
164
|
+
ca->mask_owner = NULL;
|
|
173
165
|
ca->n_parents = n_parents;
|
|
174
166
|
ca->parents = ALLOC_N(CArray *, n_parents);
|
|
175
167
|
for ( i = 0; i < n_parents; i++ ) {
|
|
@@ -185,7 +177,7 @@ ca_stack_setup_with_axis (CAStack *ca, int32_t n_parents, CArray **parents,
|
|
|
185
177
|
ca->dim[k_axis] = n_parents;
|
|
186
178
|
for ( a = k_axis + 1; a < ca->ndim; a++ ) ca->dim[a] = ref->dim[a - 1];
|
|
187
179
|
|
|
188
|
-
/* mask: lazy
|
|
180
|
+
/* mask: lazy, built on first mask access. */
|
|
189
181
|
return 0;
|
|
190
182
|
}
|
|
191
183
|
|
|
@@ -215,6 +207,13 @@ free_ca_stack (void *ap)
|
|
|
215
207
|
CAStack *ca = (CAStack *) ap;
|
|
216
208
|
if ( ca != NULL ) {
|
|
217
209
|
ca_free(ca->mask);
|
|
210
|
+
if ( ca->mask_standins ) {
|
|
211
|
+
int32_t k;
|
|
212
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
213
|
+
if ( ca->mask_standins[k] ) ca_free(ca->mask_standins[k]);
|
|
214
|
+
}
|
|
215
|
+
xfree(ca->mask_standins);
|
|
216
|
+
}
|
|
218
217
|
xfree(ca->parents);
|
|
219
218
|
xfree(ca->dim);
|
|
220
219
|
xfree(ca);
|
|
@@ -234,17 +233,40 @@ ca_stack_func_clone (void *ap)
|
|
|
234
233
|
|
|
235
234
|
/* view[..., k at k_axis, ...] = parents[k][parent_idx]
|
|
236
235
|
where parent_idx = idx[] with the k_axis slot removed. */
|
|
236
|
+
/* On the mask of a CAStack: let its stand-ins give way to the parents' own
|
|
237
|
+
masks (see ca_multi_parent_mask_refresh). */
|
|
238
|
+
static void
|
|
239
|
+
ca_stack_mask_refresh (CAStack *ca, int for_write)
|
|
240
|
+
{
|
|
241
|
+
CAStack *o = (CAStack *) ca->mask_owner;
|
|
242
|
+
if ( o != NULL ) {
|
|
243
|
+
ca_multi_parent_mask_refresh((CArray *) ca, o->parents, o->mask_standins,
|
|
244
|
+
o->n_parents, for_write);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static void
|
|
249
|
+
ca_stack_mask_settle (CAStack *ca)
|
|
250
|
+
{
|
|
251
|
+
CAStack *o = (CAStack *) ca->mask_owner;
|
|
252
|
+
if ( o != NULL ) {
|
|
253
|
+
ca_multi_parent_mask_settle((CArray *) ca, o->parents, o->mask_standins,
|
|
254
|
+
o->n_parents);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
237
258
|
static void
|
|
238
259
|
ca_stack_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
239
260
|
{
|
|
240
261
|
CAStack *ca = (CAStack *) ap;
|
|
262
|
+
ca_stack_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
241
263
|
int8_t k_axis = ca->k_axis;
|
|
242
264
|
ca_size_t k = idx[k_axis];
|
|
243
265
|
if ( k < 0 || k >= ca->n_parents ) {
|
|
244
266
|
rb_raise(rb_eIndexError, "CAStack k-axis (axis %d) index %lld out of range [0, %d)",
|
|
245
267
|
(int) k_axis, (long long) k, (int) ca->n_parents);
|
|
246
268
|
}
|
|
247
|
-
if ( k_axis == 0 ) {
|
|
269
|
+
if ( k_axis == 0 && ca_fast_paths_enabled() ) {
|
|
248
270
|
/* Fast path: parent_idx = idx[1..ndim-1]; pass idx+1 directly. */
|
|
249
271
|
ca_xfer_index(ca->parents[k], idx + 1, data, dir);
|
|
250
272
|
return;
|
|
@@ -273,6 +295,7 @@ ca_stack_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
273
295
|
void *data, int dir)
|
|
274
296
|
{
|
|
275
297
|
CAStack *ca = (CAStack *) ap;
|
|
298
|
+
ca_stack_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
276
299
|
int8_t k_axis = ca->k_axis;
|
|
277
300
|
ca_size_t parent_elements = ca->parents[0]->elements;
|
|
278
301
|
ca_size_t bytes = ca->bytes;
|
|
@@ -285,7 +308,7 @@ ca_stack_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
285
308
|
paddrs = ALLOCV_N(ca_size_t, holder1, n);
|
|
286
309
|
pdata = ALLOCV_N(char, holder2, n * bytes);
|
|
287
310
|
|
|
288
|
-
if ( k_axis == 0 ) {
|
|
311
|
+
if ( k_axis == 0 && ca_fast_paths_enabled() ) {
|
|
289
312
|
/* Fast path: addr = k * parent_elements + parent_addr (row-major over
|
|
290
313
|
view shape with K at axis 0). */
|
|
291
314
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
@@ -397,7 +420,9 @@ static void
|
|
|
397
420
|
ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
398
421
|
ca_size_t *strides, void *data, int dir)
|
|
399
422
|
{
|
|
423
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
400
424
|
CAStack *ca = (CAStack *) ap;
|
|
425
|
+
ca_stack_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
401
426
|
int8_t k_axis = ca->k_axis;
|
|
402
427
|
int8_t pndim = ca->ndim - 1;
|
|
403
428
|
ca_size_t native[CA_RANK_MAX], dstride[CA_RANK_MAX];
|
|
@@ -418,19 +443,24 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
418
443
|
s *= ca->parents[0]->dim[i];
|
|
419
444
|
}
|
|
420
445
|
|
|
421
|
-
/* Structural iff strides[k] == native[k] for all k
|
|
446
|
+
/* Structural iff strides[k] == native[k] for all k and the request is a
|
|
447
|
+
box over the view's own axes. Equal strides alone are not enough: a
|
|
448
|
+
size-1 axis gives two axes the same native stride, and a flat window
|
|
449
|
+
reshaped back to ndim has native strides yet wraps across an axis. The
|
|
450
|
+
request is over the view's addresses; see
|
|
451
|
+
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
422
452
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
423
453
|
if ( strides[i] != native[i] ) { structural = 0; break; }
|
|
424
454
|
}
|
|
455
|
+
if ( structural &&
|
|
456
|
+
! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
457
|
+
structural = 0;
|
|
458
|
+
}
|
|
459
|
+
if ( ! ca_fast_paths_enabled() ) structural = 0;
|
|
425
460
|
|
|
426
461
|
if ( structural ) {
|
|
427
462
|
ca_size_t k_lo = starts[k_axis];
|
|
428
463
|
ca_size_t k_hi = starts[k_axis] + counts[k_axis];
|
|
429
|
-
if ( k_lo < 0 || k_hi > ca->n_parents ) {
|
|
430
|
-
rb_raise(rb_eIndexError,
|
|
431
|
-
"CAStack xfer_stride k-axis (axis %d) [%lld, %lld) out of range [0, %d)",
|
|
432
|
-
(int) k_axis, (long long) k_lo, (long long) k_hi, (int) ca->n_parents);
|
|
433
|
-
}
|
|
434
464
|
|
|
435
465
|
/* dst row-major byte strides over output counts[]. */
|
|
436
466
|
s = ca->bytes;
|
|
@@ -517,7 +547,7 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
517
547
|
with native[k_axis] removed, in order. */
|
|
518
548
|
{
|
|
519
549
|
int8_t p = -1;
|
|
520
|
-
int reloc =
|
|
550
|
+
int reloc = ca_fast_paths_enabled();
|
|
521
551
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
522
552
|
if ( strides[i] == native[k_axis] ) { p = i; break; }
|
|
523
553
|
}
|
|
@@ -537,16 +567,27 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
537
567
|
if ( strides[i] != native[v] ) { reloc = 0; break; }
|
|
538
568
|
}
|
|
539
569
|
}
|
|
570
|
+
/* Each output axis must stay inside the view axis it was matched to;
|
|
571
|
+
otherwise the request wraps (or the match was one of two axes sharing
|
|
572
|
+
a native stride because the other has size 1), and only the per-cell
|
|
573
|
+
walk reads it correctly. */
|
|
574
|
+
if ( reloc ) {
|
|
575
|
+
for ( i = 0; i < ca->ndim; i++ ) {
|
|
576
|
+
int8_t j, v;
|
|
577
|
+
if ( counts[i] <= 1 ) continue;
|
|
578
|
+
if ( i == p ) {
|
|
579
|
+
v = k_axis;
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
j = (i < p) ? i : (i - 1);
|
|
583
|
+
v = (j < k_axis) ? j : (j + 1);
|
|
584
|
+
}
|
|
585
|
+
if ( starts[v] + counts[i] > ca->dim[v] ) { reloc = 0; break; }
|
|
586
|
+
}
|
|
587
|
+
}
|
|
540
588
|
if ( reloc ) {
|
|
541
|
-
ca_size_t kk_lo = starts[k_axis];
|
|
542
|
-
ca_size_t kk_hi = starts[k_axis] + counts[p];
|
|
543
589
|
ca_size_t odo[CA_RANK_MAX];
|
|
544
590
|
int8_t a;
|
|
545
|
-
if ( kk_lo < 0 || kk_hi > ca->n_parents ) {
|
|
546
|
-
rb_raise(rb_eIndexError,
|
|
547
|
-
"CAStack xfer_stride k-axis [%lld, %lld) out of range [0, %d)",
|
|
548
|
-
(long long) kk_lo, (long long) kk_hi, (int) ca->n_parents);
|
|
549
|
-
}
|
|
550
591
|
if ( p == ca->ndim - 1 ) {
|
|
551
592
|
/* K innermost: per-cell via the parent's xfer_index directly, escaping
|
|
552
593
|
the CAStack-level addr2index dispatch hop in the per-cell fallback. */
|
|
@@ -623,20 +664,34 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
623
664
|
- k_axis != 0: per-parent contiguous read into a temp buffer, then
|
|
624
665
|
scattered-write to dst at view row-major positions. This is the
|
|
625
666
|
correctness path (per-parent contig-read / scattered-write), not a
|
|
626
|
-
perf-optimised one.
|
|
667
|
+
perf-optimised one.
|
|
668
|
+
|
|
669
|
+
into_buffers (PUT only) writes each parent's cells into the buffer its
|
|
670
|
+
attach handed out, rather than through the parent to what is behind it:
|
|
671
|
+
the sync of an attached stack, which then syncs each parent. Writing
|
|
672
|
+
past the buffer would leave it stale, and the parent's own sync would
|
|
673
|
+
push the stale buffer back over the cells just written. */
|
|
627
674
|
static void
|
|
628
|
-
|
|
675
|
+
ca_stack_xfer_parents (CAStack *ca, char *d, int dir, int into_buffers)
|
|
629
676
|
{
|
|
630
|
-
CAStack *ca = (CAStack *) ap;
|
|
631
677
|
int8_t k_axis = ca->k_axis;
|
|
632
678
|
ca_size_t bytes = ca->bytes;
|
|
633
|
-
char *d = (char *) data;
|
|
634
679
|
int32_t k;
|
|
635
680
|
|
|
636
|
-
|
|
681
|
+
/* The walk below visits a parent's first cell before it tests the
|
|
682
|
+
counts. */
|
|
683
|
+
if ( ca->elements == 0 ) return;
|
|
684
|
+
|
|
685
|
+
if ( k_axis == 0 && ca_fast_paths_enabled() ) {
|
|
637
686
|
ca_size_t parent_bytes_total = ca->parents[0]->elements * bytes;
|
|
638
687
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
639
|
-
|
|
688
|
+
if ( into_buffers ) {
|
|
689
|
+
memcpy(ca->parents[k]->ptr, d + k * parent_bytes_total,
|
|
690
|
+
(size_t) parent_bytes_total);
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
ca_xfer_all(ca->parents[k], d + k * parent_bytes_total, dir);
|
|
694
|
+
}
|
|
640
695
|
}
|
|
641
696
|
return;
|
|
642
697
|
}
|
|
@@ -724,7 +779,12 @@ ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
|
724
779
|
}
|
|
725
780
|
|
|
726
781
|
if ( dir == CA_XFER_PUT ) {
|
|
727
|
-
|
|
782
|
+
if ( into_buffers ) {
|
|
783
|
+
memcpy(ca->parents[k]->ptr, buf, (size_t) (parent_elements * bytes));
|
|
784
|
+
}
|
|
785
|
+
else {
|
|
786
|
+
ca_xfer_all(ca->parents[k], buf, CA_XFER_PUT);
|
|
787
|
+
}
|
|
728
788
|
}
|
|
729
789
|
}
|
|
730
790
|
}
|
|
@@ -732,6 +792,13 @@ ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
|
732
792
|
}
|
|
733
793
|
}
|
|
734
794
|
|
|
795
|
+
static void
|
|
796
|
+
ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
797
|
+
{
|
|
798
|
+
ca_stack_mask_refresh((CAStack *) ap, dir == CA_XFER_PUT);
|
|
799
|
+
ca_stack_xfer_parents((CAStack *) ap, (char *) data, dir, 0);
|
|
800
|
+
}
|
|
801
|
+
|
|
735
802
|
/* ------------------------------------------------------------------- */
|
|
736
803
|
/* attach / sync / detach (materialise via xfer_all) */
|
|
737
804
|
/* ------------------------------------------------------------------- */
|
|
@@ -740,34 +807,42 @@ static void
|
|
|
740
807
|
ca_stack_func_allocate (void *ap)
|
|
741
808
|
{
|
|
742
809
|
CAStack *ca = (CAStack *) ap;
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
ca_attach(ca->parents[k]);
|
|
746
|
-
}
|
|
810
|
+
ca_stack_mask_refresh(ca, 0);
|
|
811
|
+
ca_attach_all(ca->parents, ca->n_parents);
|
|
747
812
|
ca->ptr = xmalloc(ca_length(ca));
|
|
748
813
|
}
|
|
749
814
|
|
|
815
|
+
static VALUE
|
|
816
|
+
ca_stack_attach_owned (VALUE arg)
|
|
817
|
+
{
|
|
818
|
+
ca_axis_view_attach_owned((void *) arg);
|
|
819
|
+
return Qnil;
|
|
820
|
+
}
|
|
821
|
+
|
|
750
822
|
static void
|
|
751
823
|
ca_stack_func_attach (void *ap)
|
|
752
824
|
{
|
|
753
825
|
CAStack *ca = (CAStack *) ap;
|
|
826
|
+
ca_stack_mask_refresh(ca, 0);
|
|
754
827
|
int32_t k;
|
|
755
|
-
|
|
756
|
-
|
|
828
|
+
int tag = 0;
|
|
829
|
+
ca_attach_all(ca->parents, ca->n_parents);
|
|
830
|
+
rb_protect(ca_stack_attach_owned, (VALUE) ca, &tag);
|
|
831
|
+
if ( tag ) {
|
|
832
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
833
|
+
ca_detach(ca->parents[k]);
|
|
834
|
+
}
|
|
835
|
+
rb_jump_tag(tag);
|
|
757
836
|
}
|
|
758
|
-
ca->ptr = xmalloc(ca_length(ca));
|
|
759
|
-
ca_stack_func_xfer_all(ca, ca->ptr, CA_XFER_GET);
|
|
760
837
|
}
|
|
761
838
|
|
|
762
839
|
static void
|
|
763
840
|
ca_stack_func_sync (void *ap)
|
|
764
841
|
{
|
|
765
842
|
CAStack *ca = (CAStack *) ap;
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
ca_sync(ca->parents[k]);
|
|
770
|
-
}
|
|
843
|
+
ca_stack_xfer_parents(ca, ca->ptr, CA_XFER_PUT, 1);
|
|
844
|
+
ca_sync_all(ca->parents, ca->n_parents);
|
|
845
|
+
ca_stack_mask_settle(ca);
|
|
771
846
|
}
|
|
772
847
|
|
|
773
848
|
static void
|
|
@@ -790,6 +865,7 @@ static void
|
|
|
790
865
|
ca_stack_func_fill_data (void *ap, void *ptr)
|
|
791
866
|
{
|
|
792
867
|
CAStack *ca = (CAStack *) ap;
|
|
868
|
+
ca_stack_mask_refresh(ca, 1);
|
|
793
869
|
int32_t k;
|
|
794
870
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
795
871
|
ca_fill(ca->parents[k], ptr);
|
|
@@ -797,12 +873,13 @@ ca_stack_func_fill_data (void *ap, void *ptr)
|
|
|
797
873
|
}
|
|
798
874
|
|
|
799
875
|
/* ------------------------------------------------------------------- */
|
|
800
|
-
/* create_mask
|
|
876
|
+
/* create_mask */
|
|
801
877
|
/* ------------------------------------------------------------------- */
|
|
802
878
|
|
|
803
|
-
/*
|
|
804
|
-
|
|
805
|
-
re-used as its own mask
|
|
879
|
+
/* The mask is a CAStack over the K parents' masks, a stand-in standing
|
|
880
|
+
for a parent that has none (ca_multi_parent_mask), so building it gives
|
|
881
|
+
no parent a mask. Self-similar (= CAStack re-used as its own mask
|
|
882
|
+
class). */
|
|
806
883
|
static void
|
|
807
884
|
ca_stack_func_create_mask (void *ap)
|
|
808
885
|
{
|
|
@@ -812,12 +889,13 @@ ca_stack_func_create_mask (void *ap)
|
|
|
812
889
|
int32_t k;
|
|
813
890
|
|
|
814
891
|
mask_parents = ALLOCV_N(CArray *, holder, ca->n_parents);
|
|
892
|
+
if ( ! ca->mask_standins ) {
|
|
893
|
+
ca->mask_standins = ALLOC_N(CArray *, ca->n_parents);
|
|
894
|
+
MEMZERO(ca->mask_standins, CArray *, ca->n_parents);
|
|
895
|
+
}
|
|
815
896
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
ca_create_mask(ca->parents[k]);
|
|
819
|
-
}
|
|
820
|
-
mask_parents[k] = ca->parents[k]->mask;
|
|
897
|
+
mask_parents[k] = ca_multi_parent_mask(ca->parents[k],
|
|
898
|
+
&ca->mask_standins[k]);
|
|
821
899
|
}
|
|
822
900
|
/* Build the mask stack with the parent's k_axis from the start so its
|
|
823
901
|
dim[] is laid out for that axis. (Patching ->k_axis after a default
|
|
@@ -826,6 +904,7 @@ ca_stack_func_create_mask (void *ap)
|
|
|
826
904
|
xfer_stride k-range check when k_axis != 0.) */
|
|
827
905
|
ca->mask = (CArray *) ca_stack_new_with_axis(ca->n_parents, mask_parents,
|
|
828
906
|
ca->k_axis);
|
|
907
|
+
((CAStack *) ca->mask)->mask_owner = (CArray *) ca;
|
|
829
908
|
ALLOCV_END(holder);
|
|
830
909
|
}
|
|
831
910
|
|
|
@@ -851,6 +930,13 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
851
930
|
ca_size_t k;
|
|
852
931
|
int8_t i;
|
|
853
932
|
|
|
933
|
+
/* The mask of a stack while it still reads stand-ins: a write must
|
|
934
|
+
reach the stack's transfer, which replaces them first. */
|
|
935
|
+
if ( ca->mask_owner != NULL
|
|
936
|
+
&& ((CAStack *) ca->mask_owner)->mask_standins != NULL ) {
|
|
937
|
+
return 0;
|
|
938
|
+
}
|
|
939
|
+
|
|
854
940
|
/* k_axis != 0: parent byte blocks are interleaved (not contig in view
|
|
855
941
|
buffer), so the byte-box containment check and the size-1 K-axis
|
|
856
942
|
degeneration below would require detecting the K-axis contribution
|
|
@@ -859,6 +945,7 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
859
945
|
through to CAStack.xfer_stride (k_axis-aware), which still delivers
|
|
860
946
|
correct (if non-folded) per-parent dispatch. */
|
|
861
947
|
if ( ca->k_axis != 0 ) return 0;
|
|
948
|
+
if ( ! ca_fast_paths_enabled() ) return 0;
|
|
862
949
|
|
|
863
950
|
for ( i = 0; i < f->ndim; i++ ) {
|
|
864
951
|
ca_size_t span = (f->counts[i] - 1) * f->strides[i];
|
|
@@ -881,6 +968,56 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
881
968
|
/* operation table */
|
|
882
969
|
/* ------------------------------------------------------------------- */
|
|
883
970
|
|
|
971
|
+
/* The table's write slots: after a write, refuse a true that reached the
|
|
972
|
+
stand-in of a value array or a mask array (ca_multi_parent_mask_check).
|
|
973
|
+
Only the mask of a CAStack has stand-ins to check. */
|
|
974
|
+
static void
|
|
975
|
+
ca_stack_mask_check (CAStack *ca)
|
|
976
|
+
{
|
|
977
|
+
CAStack *o = (CAStack *) ca->mask_owner;
|
|
978
|
+
if ( o != NULL ) {
|
|
979
|
+
ca_multi_parent_mask_check((CArray *) ca, o->parents, o->mask_standins,
|
|
980
|
+
o->n_parents);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
static void
|
|
985
|
+
ca_stack_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
986
|
+
{
|
|
987
|
+
ca_stack_func_xfer_index(ap, idx, data, dir);
|
|
988
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_check((CAStack *) ap);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
static void
|
|
992
|
+
ca_stack_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
993
|
+
int dir)
|
|
994
|
+
{
|
|
995
|
+
ca_stack_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
996
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_check((CAStack *) ap);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
static void
|
|
1000
|
+
ca_stack_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
1001
|
+
ca_size_t *strides, void *data, int dir)
|
|
1002
|
+
{
|
|
1003
|
+
ca_stack_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
1004
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_check((CAStack *) ap);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
static void
|
|
1008
|
+
ca_stack_put_xfer_all (void *ap, void *data, int dir)
|
|
1009
|
+
{
|
|
1010
|
+
ca_stack_func_xfer_all(ap, data, dir);
|
|
1011
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_check((CAStack *) ap);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
static void
|
|
1015
|
+
ca_stack_put_fill_data (void *ap, void *ptr)
|
|
1016
|
+
{
|
|
1017
|
+
ca_stack_func_fill_data(ap, ptr);
|
|
1018
|
+
ca_stack_mask_check((CAStack *) ap);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
884
1021
|
ca_operation_function_t ca_stack_func = {
|
|
885
1022
|
-1, /* CA_OBJ_STACK */
|
|
886
1023
|
CA_VIEW_ARRAY,
|
|
@@ -890,13 +1027,13 @@ ca_operation_function_t ca_stack_func = {
|
|
|
890
1027
|
ca_stack_func_attach,
|
|
891
1028
|
ca_stack_func_sync,
|
|
892
1029
|
ca_stack_func_detach,
|
|
893
|
-
|
|
1030
|
+
ca_stack_put_fill_data,
|
|
894
1031
|
ca_stack_func_create_mask,
|
|
895
|
-
|
|
896
|
-
|
|
1032
|
+
ca_stack_put_xfer_index,
|
|
1033
|
+
ca_stack_put_xfer_addrs,
|
|
897
1034
|
ca_stack_func_fold_stride,
|
|
898
|
-
|
|
899
|
-
|
|
1035
|
+
ca_stack_put_xfer_stride,
|
|
1036
|
+
ca_stack_put_xfer_all,
|
|
900
1037
|
};
|
|
901
1038
|
|
|
902
1039
|
/* ------------------------------------------------------------------- */
|
|
@@ -940,7 +1077,7 @@ rb_ca_stack_new_with_axis (VALUE parents_ary, int8_t k_axis)
|
|
|
940
1077
|
ca = ca_stack_new_with_axis((int32_t) n, parents, k_axis);
|
|
941
1078
|
obj = ca_wrap_struct(ca);
|
|
942
1079
|
rb_ivar_set(obj, id_parents, rb_ary_dup(parents_ary)); /* GC anchor */
|
|
943
|
-
rb_ca_set_parent(obj,
|
|
1080
|
+
rb_ca_set_parent(obj, ca_face_strip_one(rb_ary_entry(parents_ary, 0))); /* CAView base (Face-stripped, matches C ->parent) */
|
|
944
1081
|
ALLOCV_END(holder);
|
|
945
1082
|
return obj;
|
|
946
1083
|
}
|
|
@@ -968,8 +1105,14 @@ rb_ca_stack_initialize_copy (VALUE self, VALUE other)
|
|
|
968
1105
|
{
|
|
969
1106
|
CAStack *ca, *cs;
|
|
970
1107
|
TypedData_Get_Struct(self, CAStack, &castack_data_type, ca);
|
|
1108
|
+
ca_check_uninitialized(ca);
|
|
971
1109
|
TypedData_Get_Struct(other, CAStack, &castack_data_type, cs);
|
|
972
1110
|
ca_stack_setup_with_axis(ca, cs->n_parents, cs->parents, cs->k_axis);
|
|
1111
|
+
/* A copy of a stack's mask reads and writes the same stand-ins, so it
|
|
1112
|
+
answers to the same owner: its writes reach the parents' masks. The
|
|
1113
|
+
copy holds the owner alive through the masked_array ivar that dup
|
|
1114
|
+
carries over (see rb_ca_mask_array). */
|
|
1115
|
+
ca->mask_owner = cs->mask_owner;
|
|
973
1116
|
return self;
|
|
974
1117
|
}
|
|
975
1118
|
|
|
@@ -1010,6 +1153,7 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1010
1153
|
NUM2LONG(axis_val), (int) ref->ndim + 1, "CAStack.new");
|
|
1011
1154
|
}
|
|
1012
1155
|
TypedData_Get_Struct(self, CAStack, &castack_data_type, ca);
|
|
1156
|
+
ca_check_uninitialized(ca);
|
|
1013
1157
|
parents = ALLOCV_N(CArray *, holder, n);
|
|
1014
1158
|
for ( i = 0; i < n; i++ ) {
|
|
1015
1159
|
VALUE p = rb_ary_entry(list, i);
|
|
@@ -1018,7 +1162,7 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1018
1162
|
}
|
|
1019
1163
|
ca_stack_setup_with_axis(ca, (int32_t) n, parents, k_axis);
|
|
1020
1164
|
rb_ivar_set(self, id_parents, rb_ary_dup(list)); /* GC anchor */
|
|
1021
|
-
rb_ca_set_parent(self,
|
|
1165
|
+
rb_ca_set_parent(self, ca_face_strip_one(rb_ary_entry(list, 0))); /* CAView base (Face-stripped, matches C ->parent) */
|
|
1022
1166
|
ALLOCV_END(holder);
|
|
1023
1167
|
return self;
|
|
1024
1168
|
}
|
|
@@ -1034,8 +1178,9 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1034
1178
|
this method)
|
|
1035
1179
|
- then ca_face_lift re-wraps the result as the same Face class,
|
|
1036
1180
|
carrying state from list[0]
|
|
1037
|
-
|
|
1038
|
-
|
|
1181
|
+
A single Face parent is lifted too. A list mixing Face and non-Face
|
|
1182
|
+
parents, or two Face classes, is refused; a non-Face list returns the
|
|
1183
|
+
raw CAStack (= same result as the inherited Class#new chain).
|
|
1039
1184
|
|
|
1040
1185
|
Replaces the Ruby-level CAStack.new override in lib/carray/compose.rb
|
|
1041
1186
|
(= used alias_method :__new_raw__, :new + class << self def new).
|
|
@@ -1044,68 +1189,23 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1044
1189
|
static VALUE
|
|
1045
1190
|
rb_ca_stack_s_new (int argc, VALUE *argv, VALUE klass)
|
|
1046
1191
|
{
|
|
1047
|
-
VALUE list, kwargs;
|
|
1048
|
-
long n, i;
|
|
1049
|
-
int all_face = 1;
|
|
1050
|
-
VALUE face_class = Qnil;
|
|
1051
|
-
CArray *ref_face = NULL;
|
|
1192
|
+
VALUE list, kwargs, face_class;
|
|
1052
1193
|
VALUE obj;
|
|
1053
1194
|
|
|
1054
1195
|
rb_scan_args(argc, argv, "1:", &list, &kwargs);
|
|
1055
1196
|
Check_Type(list, T_ARRAY);
|
|
1056
|
-
|
|
1057
|
-
if ( n <= 0 ) {
|
|
1197
|
+
if ( RARRAY_LEN(list) <= 0 ) {
|
|
1058
1198
|
rb_raise(rb_eArgError, "CAStack.new requires at least one parent");
|
|
1059
1199
|
}
|
|
1200
|
+
face_class = ca_face_list_class(list, "CAStack.new");
|
|
1060
1201
|
|
|
1061
|
-
/*
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1065
|
-
CArray *ca;
|
|
1066
|
-
rb_check_carray_object(p);
|
|
1067
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1068
|
-
if ( !ca_is_face(ca) ) { all_face = 0; break; }
|
|
1069
|
-
if ( i == 0 ) {
|
|
1070
|
-
face_class = rb_obj_class(p);
|
|
1071
|
-
ref_face = ca;
|
|
1072
|
-
} else if ( rb_obj_class(p) != face_class ) {
|
|
1073
|
-
all_face = 0; break;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
/* Allocate + initialize raw CAStack. rb_obj_alloc calls the
|
|
1078
|
-
TypedData allocator directly (= bypasses the overridden Class#new,
|
|
1079
|
-
avoiding infinite recursion); rb_obj_call_init_kw dispatches to
|
|
1080
|
-
#initialize forwarding the kwargs hash (= Ruby 3.x strict kwarg
|
|
1081
|
-
separation requires the _kw variant when passing through). */
|
|
1202
|
+
/* rb_obj_alloc calls the TypedData allocator directly (= bypasses the
|
|
1203
|
+
overridden Class#new, avoiding infinite recursion); rb_obj_call_init_kw
|
|
1204
|
+
forwards the kwargs hash. */
|
|
1082
1205
|
obj = rb_obj_alloc(klass);
|
|
1083
1206
|
rb_obj_call_init_kw(obj, argc, argv, RB_PASS_CALLED_KEYWORDS);
|
|
1084
1207
|
|
|
1085
|
-
|
|
1086
|
-
if ( !all_face || n < 2 ) return obj;
|
|
1087
|
-
|
|
1088
|
-
/* Homogeneous Face: portable + pairwise state-compatible checks,
|
|
1089
|
-
then ca_face_lift to re-wrap as the same Face class. */
|
|
1090
|
-
if ( !ca_face_state_portable(ref_face->obj_type, face_class) ) {
|
|
1091
|
-
rb_raise(rb_eArgError,
|
|
1092
|
-
"CAStack.new: %s state is not portable across multiple "
|
|
1093
|
-
"parents (= per-parent storage like CAConstString's buffer); "
|
|
1094
|
-
"strip Face with .parent if a storage-level CAStack is intended",
|
|
1095
|
-
rb_class2name(face_class));
|
|
1096
|
-
}
|
|
1097
|
-
for ( i = 1; i < n; i++ ) {
|
|
1098
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1099
|
-
CArray *ca;
|
|
1100
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1101
|
-
if ( !ca_face_state_compatible(rb_ary_entry(list, 0), ref_face,
|
|
1102
|
-
p, ca) ) {
|
|
1103
|
-
rb_raise(rb_eArgError,
|
|
1104
|
-
"CAStack.new: Face state mismatch across parents "
|
|
1105
|
-
"(= %s instance at index %ld differs in state from index 0)",
|
|
1106
|
-
rb_class2name(face_class), i);
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1208
|
+
if ( NIL_P(face_class) ) return obj;
|
|
1109
1209
|
return ca_face_lift(obj, rb_ary_entry(list, 0));
|
|
1110
1210
|
}
|
|
1111
1211
|
|