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_meld.c
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
(sortedness-aware O(n+K) merge is a future
|
|
26
26
|
optimisation, memo §7.3)
|
|
27
27
|
fill_data: K-fold ca_fill
|
|
28
|
-
create_mask:
|
|
28
|
+
create_mask: mask CAMeld over the parents' masks (mirrors CAStack)
|
|
29
29
|
fold_stride: decline (return 0)
|
|
30
30
|
|
|
31
31
|
Design ref: devel/MEMO_CAMELD_SEGMENT_MAJOR_ENGINE.md. Meld-axis reduce
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
---------------------------------------------------------------------------- */
|
|
40
40
|
|
|
41
41
|
#include "carray.h"
|
|
42
|
-
#include "carray_internal.h" /* ca_attach_all */
|
|
42
|
+
#include "carray_internal.h" /* ca_attach_all / ca_sync_all */
|
|
43
43
|
#include "ca_obj_face.h" /* ca_face_state_portable */
|
|
44
44
|
|
|
45
45
|
/* ------------------------------------------------------------------- */
|
|
@@ -112,9 +112,9 @@ ca_meld_check_uniform (int32_t n_parents, CArray **parents, int8_t meld_axis)
|
|
|
112
112
|
CArray *p = parents[i];
|
|
113
113
|
if ( p->data_type != ref->data_type ) {
|
|
114
114
|
rb_raise(rb_eArgError,
|
|
115
|
-
"
|
|
116
|
-
"(
|
|
117
|
-
ref->data_type, i, p->data_type);
|
|
115
|
+
"meld: the arrays must have the same data type "
|
|
116
|
+
"(array 0 is %s, array %d is %s)",
|
|
117
|
+
ca_type_name[ref->data_type], i, ca_type_name[p->data_type]);
|
|
118
118
|
}
|
|
119
119
|
if ( p->ndim != ref->ndim ) {
|
|
120
120
|
rb_raise(rb_eArgError,
|
|
@@ -152,6 +152,20 @@ ca_meld_setup (CAMeld *ca, int32_t n_parents, CArray **parents, int8_t meld_axis
|
|
|
152
152
|
int32_t i;
|
|
153
153
|
int8_t a;
|
|
154
154
|
|
|
155
|
+
/* ca == NULL asks for the checks only, so that a constructor can run
|
|
156
|
+
them before it allocates. They see the parents as the setup will,
|
|
157
|
+
one Face level down, without changing the caller's list. */
|
|
158
|
+
if ( ca == NULL ) {
|
|
159
|
+
volatile VALUE holder = 0;
|
|
160
|
+
CArray **seen = ALLOCV_N(CArray *, holder, n_parents > 0 ? n_parents : 1);
|
|
161
|
+
for ( i = 0; i < n_parents; i++ ) {
|
|
162
|
+
seen[i] = ca_is_face(parents[i]) ? CAVIEW(parents[i])->parent : parents[i];
|
|
163
|
+
}
|
|
164
|
+
ca_meld_check_uniform(n_parents, seen, meld_axis);
|
|
165
|
+
ALLOCV_END(holder);
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
155
169
|
/* Pre-strip Face parents one level to storage, as CAStack does, so a
|
|
156
170
|
melded Face lifts to a single-Face chain (CATime[CAMeld[entity, ...]])
|
|
157
171
|
rather than a Face sitting on Face parents. One level, not a full walk,
|
|
@@ -181,6 +195,8 @@ ca_meld_setup (CAMeld *ca, int32_t n_parents, CArray **parents, int8_t meld_axis
|
|
|
181
195
|
ca->attach = 0;
|
|
182
196
|
ca->nosync = 0;
|
|
183
197
|
|
|
198
|
+
ca->mask_standins = NULL;
|
|
199
|
+
ca->mask_owner = NULL;
|
|
184
200
|
ca->n_parents = n_parents;
|
|
185
201
|
ca->parents = ALLOC_N(CArray *, n_parents);
|
|
186
202
|
for ( i = 0; i < n_parents; i++ ) {
|
|
@@ -209,7 +225,9 @@ ca_meld_setup (CAMeld *ca, int32_t n_parents, CArray **parents, int8_t meld_axis
|
|
|
209
225
|
CAMeld *
|
|
210
226
|
ca_meld_new (int32_t n_parents, CArray **parents, int8_t meld_axis)
|
|
211
227
|
{
|
|
212
|
-
CAMeld *ca
|
|
228
|
+
CAMeld *ca;
|
|
229
|
+
ca_meld_setup(NULL, n_parents, parents, meld_axis);
|
|
230
|
+
ca = ALLOC(CAMeld);
|
|
213
231
|
ca_meld_setup(ca, n_parents, parents, meld_axis);
|
|
214
232
|
return ca;
|
|
215
233
|
}
|
|
@@ -224,6 +242,13 @@ free_ca_meld (void *ap)
|
|
|
224
242
|
CAMeld *ca = (CAMeld *) ap;
|
|
225
243
|
if ( ca != NULL ) {
|
|
226
244
|
ca_free(ca->mask);
|
|
245
|
+
if ( ca->mask_standins ) {
|
|
246
|
+
int32_t k;
|
|
247
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
248
|
+
if ( ca->mask_standins[k] ) ca_free(ca->mask_standins[k]);
|
|
249
|
+
}
|
|
250
|
+
xfree(ca->mask_standins);
|
|
251
|
+
}
|
|
227
252
|
xfree(ca->seg_offset);
|
|
228
253
|
xfree(ca->parents);
|
|
229
254
|
xfree(ca->dim);
|
|
@@ -273,10 +298,33 @@ ca_meld_tail_elements (const CAMeld *ca)
|
|
|
273
298
|
|
|
274
299
|
/* view[..., v at meld_axis, ...] = parents[k][..., v - seg_offset[k], ...]
|
|
275
300
|
where k = segment_of(v). */
|
|
301
|
+
/* On the mask of a CAMeld: let its stand-ins give way to the parents' own
|
|
302
|
+
masks (see ca_multi_parent_mask_refresh). */
|
|
303
|
+
static void
|
|
304
|
+
ca_meld_mask_refresh (CAMeld *ca)
|
|
305
|
+
{
|
|
306
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
307
|
+
if ( o != NULL ) {
|
|
308
|
+
ca_multi_parent_mask_refresh((CArray *) ca, o->parents, o->mask_standins,
|
|
309
|
+
o->n_parents);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
static void
|
|
314
|
+
ca_meld_mask_settle (CAMeld *ca)
|
|
315
|
+
{
|
|
316
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
317
|
+
if ( o != NULL ) {
|
|
318
|
+
ca_multi_parent_mask_settle((CArray *) ca, o->parents, o->mask_standins,
|
|
319
|
+
o->n_parents);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
276
323
|
static void
|
|
277
324
|
ca_meld_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
278
325
|
{
|
|
279
326
|
CAMeld *ca = (CAMeld *) ap;
|
|
327
|
+
ca_meld_mask_refresh(ca);
|
|
280
328
|
int8_t ma = ca->meld_axis;
|
|
281
329
|
ca_size_t v = idx[ma];
|
|
282
330
|
int32_t k;
|
|
@@ -311,6 +359,7 @@ ca_meld_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
311
359
|
void *data, int dir)
|
|
312
360
|
{
|
|
313
361
|
CAMeld *ca = (CAMeld *) ap;
|
|
362
|
+
ca_meld_mask_refresh(ca);
|
|
314
363
|
int8_t ma = ca->meld_axis;
|
|
315
364
|
ca_size_t bytes = ca->bytes;
|
|
316
365
|
ca_size_t view_div[CA_RANK_MAX]; /* row-major divisor per view axis */
|
|
@@ -526,6 +575,7 @@ ca_meld_xfer_stride_ma_internal (CAMeld *ca, ca_size_t *starts,
|
|
|
526
575
|
else memcpy(buf, d + voff, chunk_bytes);
|
|
527
576
|
}
|
|
528
577
|
else if ( dir == CA_XFER_GET ) {
|
|
578
|
+
/* empty: the slot (ca_meld_func_xfer_stride) returns on an empty region; a parent the request does not reach returns above */
|
|
529
579
|
while ( 1 ) {
|
|
530
580
|
memcpy(d + voff, buf + paddr, chunk_bytes);
|
|
531
581
|
paddr += chunk_bytes;
|
|
@@ -539,6 +589,7 @@ ca_meld_xfer_stride_ma_internal (CAMeld *ca, ca_size_t *starts,
|
|
|
539
589
|
if ( i < 0 ) break;
|
|
540
590
|
}
|
|
541
591
|
} else {
|
|
592
|
+
/* empty: as above */
|
|
542
593
|
while ( 1 ) {
|
|
543
594
|
memcpy(buf + paddr, d + voff, chunk_bytes);
|
|
544
595
|
paddr += chunk_bytes;
|
|
@@ -586,6 +637,7 @@ ca_meld_xfer_stride_per_cell (CAMeld *ca, ca_size_t *starts, ca_size_t *counts,
|
|
|
586
637
|
for ( i = 0; i < ndim; i++ ) base += starts[i] * native[i];
|
|
587
638
|
for ( i = 0; i < ndim; i++ ) idx[i] = 0;
|
|
588
639
|
|
|
640
|
+
/* empty: the slot (ca_meld_func_xfer_stride) returns on an empty region */
|
|
589
641
|
while ( 1 ) {
|
|
590
642
|
ca_size_t toff = base;
|
|
591
643
|
for ( i = 0; i < ndim; i++ ) toff += idx[i] * strides[i];
|
|
@@ -606,7 +658,9 @@ static void
|
|
|
606
658
|
ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
607
659
|
ca_size_t *strides, void *data, int dir)
|
|
608
660
|
{
|
|
661
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
609
662
|
CAMeld *ca = (CAMeld *) ap;
|
|
663
|
+
ca_meld_mask_refresh(ca);
|
|
610
664
|
int8_t ma = ca->meld_axis;
|
|
611
665
|
ca_size_t native[CA_RANK_MAX];
|
|
612
666
|
ca_size_t s;
|
|
@@ -616,31 +670,27 @@ ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
616
670
|
s = ca->bytes;
|
|
617
671
|
for ( i = ca->ndim - 1; i >= 0; i-- ) { native[i] = s; s *= ca->dim[i]; }
|
|
618
672
|
|
|
673
|
+
/* Structural iff strides == native and the request is a box over the
|
|
674
|
+
view's own axes. Equal strides alone are not enough: a size-1 axis
|
|
675
|
+
gives two axes the same native stride, and a flat window reshaped back
|
|
676
|
+
to ndim has native strides yet wraps across an axis. The request is
|
|
677
|
+
over the view's addresses; see ca_xfer_stride_request_is_axis_box
|
|
678
|
+
(carray.h). Inside the gate the step on every axis is 1 and the region
|
|
679
|
+
stays inside each axis, which ca_meld_xfer_stride_ma_internal (handed
|
|
680
|
+
no strides) depends on. */
|
|
619
681
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
620
682
|
if ( strides[i] != native[i] ) { structural = 0; break; }
|
|
621
683
|
}
|
|
684
|
+
if ( structural &&
|
|
685
|
+
! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
686
|
+
structural = 0;
|
|
687
|
+
}
|
|
622
688
|
|
|
623
|
-
if ( ! structural ) {
|
|
689
|
+
if ( ! structural || ! ca_fast_paths_enabled() ) {
|
|
624
690
|
ca_meld_xfer_stride_per_cell(ca, starts, counts, strides, data, dir);
|
|
625
691
|
return;
|
|
626
692
|
}
|
|
627
693
|
|
|
628
|
-
/* Bound check on meld_axis, after the gate and not before it. Only once
|
|
629
|
-
strides == native is established does request axis ma mean view axis ma;
|
|
630
|
-
asked earlier, strides[ma] / native[ma] is not a step along the meld axis
|
|
631
|
-
and legal requests get rejected. Inside the gate the step is 1, so the
|
|
632
|
-
region is starts[ma] .. starts[ma] + counts[ma]. ca_meld_xfer_stride_ma_
|
|
633
|
-
internal below is handed no strides at all and depends on both facts. */
|
|
634
|
-
{
|
|
635
|
-
ca_size_t req_lo = starts[ma];
|
|
636
|
-
ca_size_t req_hi = starts[ma] + counts[ma];
|
|
637
|
-
if ( counts[ma] > 0 && ( req_lo < 0 || req_hi > ca->dim[ma] ) ) {
|
|
638
|
-
rb_raise(rb_eIndexError,
|
|
639
|
-
"CAMeld xfer_stride meld_axis (axis %d) [%lld, %lld) out of range [0, %lld)",
|
|
640
|
-
(int) ma, (long long) req_lo, (long long) req_hi, (long long) ca->dim[ma]);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
694
|
if ( ma == 0 ) {
|
|
645
695
|
ca_meld_xfer_stride_ma0(ca, starts, counts, strides, data, dir);
|
|
646
696
|
} else {
|
|
@@ -652,15 +702,37 @@ ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
652
702
|
/* xfer_all */
|
|
653
703
|
/* ------------------------------------------------------------------- */
|
|
654
704
|
|
|
705
|
+
/* A parent's cells, delivered (PUT). into_buffers writes them into the
|
|
706
|
+
buffer the parent's attach handed out, rather than through the parent to
|
|
707
|
+
what is behind it: the sync of an attached meld, which then syncs each
|
|
708
|
+
parent. Writing past the buffer would leave it stale, and the parent's
|
|
709
|
+
own sync would push the stale buffer back over the cells just written. */
|
|
710
|
+
static void
|
|
711
|
+
ca_meld_put_parent (CArray *p, char *src, int into_buffers)
|
|
712
|
+
{
|
|
713
|
+
if ( into_buffers ) {
|
|
714
|
+
memcpy(p->ptr, src, (size_t) (p->elements * p->bytes));
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
ca_xfer_all(p, src, CA_XFER_PUT);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
655
721
|
/* meld_axis == 0 best path: K contig xfer_all at prefix-sum offsets. */
|
|
656
722
|
static void
|
|
657
|
-
ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir)
|
|
723
|
+
ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir, int into_buffers)
|
|
658
724
|
{
|
|
659
725
|
ca_size_t tail_bytes = ca_meld_tail_elements(ca) * ca->bytes;
|
|
660
726
|
char *d = (char *) data;
|
|
661
727
|
int32_t k;
|
|
662
728
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
663
|
-
|
|
729
|
+
char *seg = d + ca->seg_offset[k] * tail_bytes;
|
|
730
|
+
if ( dir == CA_XFER_PUT ) {
|
|
731
|
+
ca_meld_put_parent(ca->parents[k], seg, into_buffers);
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
ca_xfer_all(ca->parents[k], seg, dir);
|
|
735
|
+
}
|
|
664
736
|
}
|
|
665
737
|
}
|
|
666
738
|
|
|
@@ -677,7 +749,8 @@ ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir)
|
|
|
677
749
|
The naive per-cell odometer that this replaces cost ~2x eager on M2;
|
|
678
750
|
chunked memcpy approaches memcpy bandwidth (eager parity target). */
|
|
679
751
|
static void
|
|
680
|
-
ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir
|
|
752
|
+
ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir,
|
|
753
|
+
int into_buffers)
|
|
681
754
|
{
|
|
682
755
|
int8_t ma = ca->meld_axis;
|
|
683
756
|
int8_t ndim = ca->ndim;
|
|
@@ -733,6 +806,7 @@ ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir)
|
|
|
733
806
|
else memcpy(buf, d + voff, chunk_bytes);
|
|
734
807
|
}
|
|
735
808
|
else if ( dir == CA_XFER_GET ) {
|
|
809
|
+
/* empty: the slot returns on an empty view; the outer axes are the view's, and a parent empty along the meld axis copies chunks of 0 bytes */
|
|
736
810
|
while ( 1 ) {
|
|
737
811
|
memcpy(d + voff, buf + paddr, chunk_bytes);
|
|
738
812
|
paddr += chunk_bytes;
|
|
@@ -747,6 +821,7 @@ ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir)
|
|
|
747
821
|
}
|
|
748
822
|
}
|
|
749
823
|
else {
|
|
824
|
+
/* empty: as above */
|
|
750
825
|
while ( 1 ) {
|
|
751
826
|
memcpy(buf + paddr, d + voff, chunk_bytes);
|
|
752
827
|
paddr += chunk_bytes;
|
|
@@ -762,23 +837,30 @@ ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir)
|
|
|
762
837
|
}
|
|
763
838
|
|
|
764
839
|
if ( dir == CA_XFER_PUT ) {
|
|
765
|
-
|
|
840
|
+
ca_meld_put_parent(p, buf, into_buffers);
|
|
766
841
|
}
|
|
767
842
|
ALLOCV_END(holder);
|
|
768
843
|
}
|
|
769
844
|
}
|
|
770
845
|
|
|
771
846
|
static void
|
|
772
|
-
|
|
847
|
+
ca_meld_xfer_parents (CAMeld *ca, void *data, int dir, int into_buffers)
|
|
773
848
|
{
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
ca_meld_xfer_all_ma0(ca, data, dir);
|
|
849
|
+
if ( ca->meld_axis == 0 && ca_fast_paths_enabled() ) {
|
|
850
|
+
ca_meld_xfer_all_ma0(ca, data, dir, into_buffers);
|
|
777
851
|
} else {
|
|
778
|
-
ca_meld_xfer_all_ma_internal(ca, data, dir);
|
|
852
|
+
ca_meld_xfer_all_ma_internal(ca, data, dir, into_buffers);
|
|
779
853
|
}
|
|
780
854
|
}
|
|
781
855
|
|
|
856
|
+
static void
|
|
857
|
+
ca_meld_func_xfer_all (void *ap, void *data, int dir)
|
|
858
|
+
{
|
|
859
|
+
if ( ((CArray *) ap)->elements == 0 ) return;
|
|
860
|
+
ca_meld_mask_refresh((CAMeld *) ap);
|
|
861
|
+
ca_meld_xfer_parents((CAMeld *) ap, data, dir, 0);
|
|
862
|
+
}
|
|
863
|
+
|
|
782
864
|
/* ------------------------------------------------------------------- */
|
|
783
865
|
/* attach / sync / detach */
|
|
784
866
|
/* ------------------------------------------------------------------- */
|
|
@@ -787,28 +869,37 @@ static void
|
|
|
787
869
|
ca_meld_func_allocate (void *ap)
|
|
788
870
|
{
|
|
789
871
|
CAMeld *ca = (CAMeld *) ap;
|
|
872
|
+
ca_meld_mask_refresh(ca);
|
|
790
873
|
ca_attach_all(ca->parents, ca->n_parents);
|
|
791
|
-
ca->ptr =
|
|
874
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
static VALUE
|
|
878
|
+
ca_meld_attach_owned (VALUE arg)
|
|
879
|
+
{
|
|
880
|
+
ca_axis_view_attach_owned((void *) arg);
|
|
881
|
+
return Qnil;
|
|
792
882
|
}
|
|
793
883
|
|
|
794
884
|
static void
|
|
795
885
|
ca_meld_func_attach (void *ap)
|
|
796
886
|
{
|
|
797
887
|
CAMeld *ca = (CAMeld *) ap;
|
|
888
|
+
ca_meld_mask_refresh(ca);
|
|
798
889
|
ca_attach_all(ca->parents, ca->n_parents);
|
|
799
|
-
ca->
|
|
800
|
-
ca_meld_func_xfer_all(ca, ca->ptr, CA_XFER_GET);
|
|
890
|
+
ca_fill_or_detach(ca->n_parents, ca->parents, ca_meld_attach_owned, (VALUE) ca);
|
|
801
891
|
}
|
|
802
892
|
|
|
893
|
+
static void ca_meld_mask_refuse_sync (CAMeld *ca);
|
|
894
|
+
|
|
803
895
|
static void
|
|
804
896
|
ca_meld_func_sync (void *ap)
|
|
805
897
|
{
|
|
806
898
|
CAMeld *ca = (CAMeld *) ap;
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
899
|
+
ca_meld_mask_refuse_sync(ca);
|
|
900
|
+
ca_meld_xfer_parents(ca, ca->ptr, CA_XFER_PUT, 1);
|
|
901
|
+
ca_sync_all(ca->parents, ca->n_parents);
|
|
902
|
+
ca_meld_mask_settle(ca);
|
|
812
903
|
}
|
|
813
904
|
|
|
814
905
|
static void
|
|
@@ -831,6 +922,7 @@ static void
|
|
|
831
922
|
ca_meld_func_fill_data (void *ap, void *ptr)
|
|
832
923
|
{
|
|
833
924
|
CAMeld *ca = (CAMeld *) ap;
|
|
925
|
+
ca_meld_mask_refresh(ca);
|
|
834
926
|
int32_t k;
|
|
835
927
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
836
928
|
ca_fill(ca->parents[k], ptr);
|
|
@@ -838,7 +930,7 @@ ca_meld_func_fill_data (void *ap, void *ptr)
|
|
|
838
930
|
}
|
|
839
931
|
|
|
840
932
|
/* ------------------------------------------------------------------- */
|
|
841
|
-
/* create_mask (
|
|
933
|
+
/* create_mask (mirrors CAStack) */
|
|
842
934
|
/* ------------------------------------------------------------------- */
|
|
843
935
|
|
|
844
936
|
static void
|
|
@@ -850,14 +942,16 @@ ca_meld_func_create_mask (void *ap)
|
|
|
850
942
|
int32_t k;
|
|
851
943
|
|
|
852
944
|
mask_parents = ALLOCV_N(CArray *, holder, ca->n_parents);
|
|
945
|
+
if ( ! ca->mask_standins ) {
|
|
946
|
+
ca->mask_standins = ALLOC_N(CArray *, ca->n_parents);
|
|
947
|
+
MEMZERO(ca->mask_standins, CArray *, ca->n_parents);
|
|
948
|
+
}
|
|
853
949
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
ca_create_mask(ca->parents[k]);
|
|
857
|
-
}
|
|
858
|
-
mask_parents[k] = ca->parents[k]->mask;
|
|
950
|
+
mask_parents[k] = ca_multi_parent_mask(ca->parents[k],
|
|
951
|
+
&ca->mask_standins[k]);
|
|
859
952
|
}
|
|
860
953
|
ca->mask = (CArray *) ca_meld_new(ca->n_parents, mask_parents, ca->meld_axis);
|
|
954
|
+
((CAMeld *) ca->mask)->mask_owner = (CArray *) ca;
|
|
861
955
|
ALLOCV_END(holder);
|
|
862
956
|
}
|
|
863
957
|
|
|
@@ -876,6 +970,174 @@ ca_meld_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
876
970
|
/* operation table */
|
|
877
971
|
/* ------------------------------------------------------------------- */
|
|
878
972
|
|
|
973
|
+
/* The table's write slots: after a write that may have put a true into a
|
|
974
|
+
stand-in, the true goes on to the parent's mask, or is refused for a
|
|
975
|
+
value array or a mask array (ca_mask_standin_settle). Only the mask of
|
|
976
|
+
a CAMeld has stand-ins. */
|
|
977
|
+
/* A write to the mask of a CAMeld, run once against blank masks first
|
|
978
|
+
(ca_multi_parent_mask_refuse_first), so that a write refused for a value
|
|
979
|
+
array or mask array part changes no other part. */
|
|
980
|
+
enum { CA_MELD_PUT_INDEX, CA_MELD_PUT_ADDRS, CA_MELD_PUT_STRIDE, CA_MELD_PUT_ALL,
|
|
981
|
+
CA_MELD_PUT_FILL, CA_MELD_PUT_SYNC, CA_MELD_PUT_FILL_ADDRS,
|
|
982
|
+
CA_MELD_PUT_FILL_STRIDE };
|
|
983
|
+
|
|
984
|
+
typedef struct {
|
|
985
|
+
int slot;
|
|
986
|
+
void *ap;
|
|
987
|
+
ca_size_t *idx;
|
|
988
|
+
ca_size_t n;
|
|
989
|
+
ca_size_t *addrs;
|
|
990
|
+
ca_size_t *starts;
|
|
991
|
+
ca_size_t *counts;
|
|
992
|
+
ca_size_t *strides;
|
|
993
|
+
void *data;
|
|
994
|
+
ca_size_t base;
|
|
995
|
+
int8_t ndim;
|
|
996
|
+
ca_size_t *steps;
|
|
997
|
+
} ca_meld_put_t;
|
|
998
|
+
|
|
999
|
+
static VALUE
|
|
1000
|
+
ca_meld_put_body (VALUE arg)
|
|
1001
|
+
{
|
|
1002
|
+
ca_meld_put_t *a = (ca_meld_put_t *) arg;
|
|
1003
|
+
switch ( a->slot ) {
|
|
1004
|
+
case CA_MELD_PUT_INDEX:
|
|
1005
|
+
ca_meld_func_xfer_index(a->ap, a->idx, a->data, CA_XFER_PUT); break;
|
|
1006
|
+
case CA_MELD_PUT_ADDRS:
|
|
1007
|
+
ca_meld_func_xfer_addrs(a->ap, a->n, a->addrs, a->data, CA_XFER_PUT); break;
|
|
1008
|
+
case CA_MELD_PUT_STRIDE:
|
|
1009
|
+
ca_meld_func_xfer_stride(a->ap, a->starts, a->counts, a->strides, a->data,
|
|
1010
|
+
CA_XFER_PUT); break;
|
|
1011
|
+
case CA_MELD_PUT_ALL:
|
|
1012
|
+
ca_meld_func_xfer_all(a->ap, a->data, CA_XFER_PUT); break;
|
|
1013
|
+
case CA_MELD_PUT_FILL:
|
|
1014
|
+
ca_meld_func_fill_data(a->ap, a->data); break;
|
|
1015
|
+
case CA_MELD_PUT_FILL_ADDRS:
|
|
1016
|
+
ca_fill_addrs_default(a->ap, a->n, a->addrs, a->data); break;
|
|
1017
|
+
case CA_MELD_PUT_FILL_STRIDE:
|
|
1018
|
+
ca_fill_stride_default(a->ap, a->base, a->ndim, a->counts, a->steps,
|
|
1019
|
+
a->data); break;
|
|
1020
|
+
case CA_MELD_PUT_SYNC:
|
|
1021
|
+
ca_meld_xfer_parents((CAMeld *) a->ap, ((CArray *) a->ap)->ptr, CA_XFER_PUT, 1);
|
|
1022
|
+
break;
|
|
1023
|
+
}
|
|
1024
|
+
return Qnil;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
static void
|
|
1028
|
+
ca_meld_mask_refuse_first (ca_meld_put_t *a)
|
|
1029
|
+
{
|
|
1030
|
+
CAMeld *o = (CAMeld *) ((CAMeld *) a->ap)->mask_owner;
|
|
1031
|
+
if ( o != NULL ) {
|
|
1032
|
+
ca_multi_parent_mask_refuse_first((CArray *) a->ap, o->parents,
|
|
1033
|
+
o->mask_standins, o->n_parents,
|
|
1034
|
+
ca_meld_put_body, (VALUE) a);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
static void
|
|
1039
|
+
ca_meld_mask_refuse_sync (CAMeld *ca)
|
|
1040
|
+
{
|
|
1041
|
+
ca_meld_put_t a = { CA_MELD_PUT_SYNC, ca, NULL, 0, NULL, NULL, NULL, NULL, NULL };
|
|
1042
|
+
ca_meld_mask_refuse_first(&a);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/* After a write of n cells of `data` to the mask of a CAMeld: a true
|
|
1046
|
+
that went into a stand-in goes on to its parent's mask. */
|
|
1047
|
+
static void
|
|
1048
|
+
ca_meld_mask_settle_after (CAMeld *ca, const void *data, ca_size_t n)
|
|
1049
|
+
{
|
|
1050
|
+
if ( ca->mask_owner != NULL && ca_mask_any_true(data, n) ) {
|
|
1051
|
+
ca_meld_mask_settle(ca);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
static void
|
|
1056
|
+
ca_meld_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
1057
|
+
{
|
|
1058
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1059
|
+
ca_meld_put_t a = { CA_MELD_PUT_INDEX, ap, idx, 0, NULL, NULL, NULL, NULL, data };
|
|
1060
|
+
ca_meld_mask_refuse_first(&a);
|
|
1061
|
+
}
|
|
1062
|
+
ca_meld_func_xfer_index(ap, idx, data, dir);
|
|
1063
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_settle_after((CAMeld *) ap, data, 1);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
static void
|
|
1067
|
+
ca_meld_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
1068
|
+
int dir)
|
|
1069
|
+
{
|
|
1070
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1071
|
+
ca_meld_put_t a = { CA_MELD_PUT_ADDRS, ap, NULL, n, addrs, NULL, NULL, NULL, data };
|
|
1072
|
+
ca_meld_mask_refuse_first(&a);
|
|
1073
|
+
}
|
|
1074
|
+
ca_meld_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
1075
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_settle_after((CAMeld *) ap, data, n);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
static void
|
|
1079
|
+
ca_meld_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
1080
|
+
ca_size_t *strides, void *data, int dir)
|
|
1081
|
+
{
|
|
1082
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1083
|
+
ca_meld_put_t a = { CA_MELD_PUT_STRIDE, ap, NULL, 0, NULL, starts, counts, strides, data };
|
|
1084
|
+
ca_meld_mask_refuse_first(&a);
|
|
1085
|
+
}
|
|
1086
|
+
ca_meld_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
1087
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1088
|
+
ca_meld_mask_settle_after((CAMeld *) ap, data,
|
|
1089
|
+
ca_shape_elements(((CArray *) ap)->ndim, counts, 1));
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
static void
|
|
1094
|
+
ca_meld_put_xfer_all (void *ap, void *data, int dir)
|
|
1095
|
+
{
|
|
1096
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1097
|
+
ca_meld_put_t a = { CA_MELD_PUT_ALL, ap, NULL, 0, NULL, NULL, NULL, NULL, data };
|
|
1098
|
+
ca_meld_mask_refuse_first(&a);
|
|
1099
|
+
}
|
|
1100
|
+
ca_meld_func_xfer_all(ap, data, dir);
|
|
1101
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1102
|
+
ca_meld_mask_settle_after((CAMeld *) ap, data, ((CArray *) ap)->elements);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
static void
|
|
1107
|
+
ca_meld_put_fill_data (void *ap, void *ptr)
|
|
1108
|
+
{
|
|
1109
|
+
{
|
|
1110
|
+
ca_meld_put_t a = { CA_MELD_PUT_FILL, ap, NULL, 0, NULL, NULL, NULL, NULL, ptr };
|
|
1111
|
+
ca_meld_mask_refuse_first(&a);
|
|
1112
|
+
}
|
|
1113
|
+
ca_meld_func_fill_data(ap, ptr);
|
|
1114
|
+
ca_meld_mask_settle_after((CAMeld *) ap, ptr, 1);
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/* A fill of part of the mask goes cell by cell through xfer_index; run
|
|
1118
|
+
the whole of it against blank masks first, so that a cell refused late
|
|
1119
|
+
does not leave the cells before it written. */
|
|
1120
|
+
static void
|
|
1121
|
+
ca_meld_put_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
|
|
1122
|
+
{
|
|
1123
|
+
ca_meld_put_t a = { CA_MELD_PUT_FILL_ADDRS, ap, NULL, n, addrs, NULL, NULL,
|
|
1124
|
+
NULL, ptr };
|
|
1125
|
+
ca_meld_mask_refuse_first(&a);
|
|
1126
|
+
ca_fill_addrs_default(ap, n, addrs, ptr);
|
|
1127
|
+
ca_meld_mask_settle_after((CAMeld *) ap, ptr, 1);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
static void
|
|
1131
|
+
ca_meld_put_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
1132
|
+
ca_size_t *counts, ca_size_t *steps, void *ptr)
|
|
1133
|
+
{
|
|
1134
|
+
ca_meld_put_t a = { CA_MELD_PUT_FILL_STRIDE, ap, NULL, 0, NULL, NULL, counts,
|
|
1135
|
+
NULL, ptr, base, ndim, steps };
|
|
1136
|
+
ca_meld_mask_refuse_first(&a);
|
|
1137
|
+
ca_fill_stride_default(ap, base, ndim, counts, steps, ptr);
|
|
1138
|
+
ca_meld_mask_settle_after((CAMeld *) ap, ptr, 1);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
879
1141
|
ca_operation_function_t ca_meld_func = {
|
|
880
1142
|
-1, /* CA_OBJ_MELD */
|
|
881
1143
|
CA_VIEW_ARRAY,
|
|
@@ -885,30 +1147,19 @@ ca_operation_function_t ca_meld_func = {
|
|
|
885
1147
|
ca_meld_func_attach,
|
|
886
1148
|
ca_meld_func_sync,
|
|
887
1149
|
ca_meld_func_detach,
|
|
888
|
-
|
|
1150
|
+
ca_meld_put_fill_data,
|
|
889
1151
|
ca_meld_func_create_mask,
|
|
890
|
-
|
|
891
|
-
|
|
1152
|
+
ca_meld_put_xfer_index,
|
|
1153
|
+
ca_meld_put_xfer_addrs,
|
|
892
1154
|
ca_meld_func_fold_stride,
|
|
893
|
-
|
|
894
|
-
|
|
1155
|
+
ca_meld_put_xfer_stride,
|
|
1156
|
+
ca_meld_put_xfer_all,
|
|
895
1157
|
};
|
|
896
1158
|
|
|
897
1159
|
/* ------------------------------------------------------------------- */
|
|
898
1160
|
/* Ruby surface */
|
|
899
1161
|
/* ------------------------------------------------------------------- */
|
|
900
1162
|
|
|
901
|
-
/* One-level strip of a Face VALUE to its storage-side parent (non-Face as-is).
|
|
902
|
-
Keeps the @parent ivar in step with the pre-stripped C parents, so the
|
|
903
|
-
Ruby-visible chain of a melded Face is single-Face too. */
|
|
904
|
-
static VALUE
|
|
905
|
-
ca_meld_face_parent1 (VALUE v)
|
|
906
|
-
{
|
|
907
|
-
CArray *c;
|
|
908
|
-
TypedData_Get_Struct(v, CArray, &carray_data_type, c);
|
|
909
|
-
return ca_is_face(c) ? rb_ca_parent(v) : v;
|
|
910
|
-
}
|
|
911
|
-
|
|
912
1163
|
VALUE
|
|
913
1164
|
rb_ca_meld_new (VALUE parents_ary, int8_t meld_axis)
|
|
914
1165
|
{
|
|
@@ -932,7 +1183,7 @@ rb_ca_meld_new (VALUE parents_ary, int8_t meld_axis)
|
|
|
932
1183
|
ca = ca_meld_new((int32_t) n, parents, meld_axis);
|
|
933
1184
|
obj = ca_wrap_struct(ca);
|
|
934
1185
|
rb_ivar_set(obj, id_parents, rb_ary_dup(parents_ary));
|
|
935
|
-
rb_ca_set_parent(obj,
|
|
1186
|
+
rb_ca_set_parent(obj, ca_face_strip_one(rb_ary_entry(parents_ary, 0)));
|
|
936
1187
|
ALLOCV_END(holder);
|
|
937
1188
|
return obj;
|
|
938
1189
|
}
|
|
@@ -949,8 +1200,14 @@ rb_ca_meld_initialize_copy (VALUE self, VALUE other)
|
|
|
949
1200
|
{
|
|
950
1201
|
CAMeld *ca, *cs;
|
|
951
1202
|
TypedData_Get_Struct(self, CAMeld, &cameld_data_type, ca);
|
|
1203
|
+
ca_check_uninitialized(ca);
|
|
952
1204
|
TypedData_Get_Struct(other, CAMeld, &cameld_data_type, cs);
|
|
953
1205
|
ca_meld_setup(ca, cs->n_parents, cs->parents, cs->meld_axis);
|
|
1206
|
+
/* A copy of a meld's mask reads and writes the same stand-ins, so it
|
|
1207
|
+
answers to the same owner: its writes reach the parents' masks. The
|
|
1208
|
+
copy holds the owner alive through the masked_array ivar that dup
|
|
1209
|
+
carries over (see rb_ca_mask_array). */
|
|
1210
|
+
ca->mask_owner = cs->mask_owner;
|
|
954
1211
|
return self;
|
|
955
1212
|
}
|
|
956
1213
|
|
|
@@ -977,10 +1234,11 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
977
1234
|
VALUE first = rb_ary_entry(list, 0);
|
|
978
1235
|
rb_check_carray_object(first);
|
|
979
1236
|
TypedData_Get_Struct(first, CArray, &carray_data_type, ref);
|
|
980
|
-
meld_axis = (int8_t)
|
|
981
|
-
|
|
1237
|
+
meld_axis = (int8_t) ca_normalize_axis_arg(
|
|
1238
|
+
axis_val, (int) ref->ndim, "CAMeld.new");
|
|
982
1239
|
}
|
|
983
1240
|
TypedData_Get_Struct(self, CAMeld, &cameld_data_type, ca);
|
|
1241
|
+
ca_check_uninitialized(ca);
|
|
984
1242
|
parents = ALLOCV_N(CArray *, holder, n);
|
|
985
1243
|
for ( i = 0; i < n; i++ ) {
|
|
986
1244
|
VALUE p = rb_ary_entry(list, i);
|
|
@@ -989,7 +1247,7 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
989
1247
|
}
|
|
990
1248
|
ca_meld_setup(ca, (int32_t) n, parents, meld_axis);
|
|
991
1249
|
rb_ivar_set(self, id_parents, rb_ary_dup(list));
|
|
992
|
-
rb_ca_set_parent(self,
|
|
1250
|
+
rb_ca_set_parent(self, ca_face_strip_one(rb_ary_entry(list, 0)));
|
|
993
1251
|
ALLOCV_END(holder);
|
|
994
1252
|
return self;
|
|
995
1253
|
}
|
|
@@ -1011,61 +1269,20 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1011
1269
|
static VALUE
|
|
1012
1270
|
rb_ca_meld_s_new (int argc, VALUE *argv, VALUE klass)
|
|
1013
1271
|
{
|
|
1014
|
-
VALUE list, kwargs;
|
|
1015
|
-
long n, i;
|
|
1016
|
-
int all_face = 1;
|
|
1017
|
-
VALUE face_class = Qnil;
|
|
1018
|
-
CArray *ref_face = NULL;
|
|
1272
|
+
VALUE list, kwargs, face_class;
|
|
1019
1273
|
VALUE obj;
|
|
1020
1274
|
|
|
1021
1275
|
rb_scan_args(argc, argv, "1:", &list, &kwargs);
|
|
1022
1276
|
Check_Type(list, T_ARRAY);
|
|
1023
|
-
|
|
1024
|
-
if ( n <= 0 ) {
|
|
1277
|
+
if ( RARRAY_LEN(list) <= 0 ) {
|
|
1025
1278
|
rb_raise(rb_eArgError, "CAMeld.new requires at least one parent");
|
|
1026
1279
|
}
|
|
1027
|
-
|
|
1028
|
-
for ( i = 0; i < n; i++ ) {
|
|
1029
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1030
|
-
CArray *ca;
|
|
1031
|
-
rb_check_carray_object(p);
|
|
1032
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1033
|
-
if ( !ca_is_face(ca) ) { all_face = 0; break; }
|
|
1034
|
-
if ( i == 0 ) {
|
|
1035
|
-
face_class = rb_obj_class(p);
|
|
1036
|
-
ref_face = ca;
|
|
1037
|
-
} else if ( rb_obj_class(p) != face_class ) {
|
|
1038
|
-
all_face = 0; break;
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
/* A single parent has nothing to weld against, so its Face rides the
|
|
1043
|
-
chain as it always did; refuse and lift only apply from two up. */
|
|
1044
|
-
if ( all_face && n > 1
|
|
1045
|
-
&& !ca_face_state_portable(ref_face->obj_type, face_class) ) {
|
|
1046
|
-
rb_raise(rb_eArgError,
|
|
1047
|
-
"CAMeld.new: %s state is not portable across multiple "
|
|
1048
|
-
"parents (= per-parent storage like CAConstString's buffer); "
|
|
1049
|
-
"strip Face with .parent if a storage-level CAMeld is intended",
|
|
1050
|
-
rb_class2name(face_class));
|
|
1051
|
-
}
|
|
1280
|
+
face_class = ca_face_list_class(list, "CAMeld.new");
|
|
1052
1281
|
|
|
1053
1282
|
obj = rb_obj_alloc(klass);
|
|
1054
1283
|
rb_obj_call_init_kw(obj, argc, argv, RB_PASS_CALLED_KEYWORDS);
|
|
1055
1284
|
|
|
1056
|
-
if (
|
|
1057
|
-
|
|
1058
|
-
for ( i = 1; i < n; i++ ) {
|
|
1059
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1060
|
-
CArray *ca;
|
|
1061
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1062
|
-
if ( !ca_face_state_compatible(rb_ary_entry(list, 0), ref_face, p, ca) ) {
|
|
1063
|
-
rb_raise(rb_eArgError,
|
|
1064
|
-
"CAMeld.new: Face state mismatch across parents "
|
|
1065
|
-
"(= %s instance at index %ld differs in state from index 0)",
|
|
1066
|
-
rb_class2name(face_class), i);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1285
|
+
if ( NIL_P(face_class) ) return obj;
|
|
1069
1286
|
return ca_face_lift(obj, rb_ary_entry(list, 0));
|
|
1070
1287
|
}
|
|
1071
1288
|
|
|
@@ -1115,6 +1332,9 @@ Init_ca_obj_meld (void)
|
|
|
1115
1332
|
rb_cCAMeld = rb_define_class("CAMeld", rb_cCAView);
|
|
1116
1333
|
rb_cCAMeldMask = rb_define_class("CAMeldMask", rb_cCAMeld);
|
|
1117
1334
|
|
|
1335
|
+
ca_meld_func.fill_addrs = ca_meld_put_fill_addrs;
|
|
1336
|
+
ca_meld_func.fill_stride = ca_meld_put_fill_stride;
|
|
1337
|
+
|
|
1118
1338
|
CA_OBJ_MELD = ca_install_obj_type(rb_cCAMeld,
|
|
1119
1339
|
&cameld_data_type,
|
|
1120
1340
|
rb_cCAMeldMask,
|