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_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,6 +39,8 @@
|
|
|
39
39
|
---------------------------------------------------------------------------- */
|
|
40
40
|
|
|
41
41
|
#include "carray.h"
|
|
42
|
+
#include "carray_internal.h" /* ca_attach_all / ca_sync_all */
|
|
43
|
+
#include "ca_obj_face.h" /* ca_face_state_portable */
|
|
42
44
|
|
|
43
45
|
/* ------------------------------------------------------------------- */
|
|
44
46
|
/* TypedData */
|
|
@@ -110,9 +112,9 @@ ca_meld_check_uniform (int32_t n_parents, CArray **parents, int8_t meld_axis)
|
|
|
110
112
|
CArray *p = parents[i];
|
|
111
113
|
if ( p->data_type != ref->data_type ) {
|
|
112
114
|
rb_raise(rb_eArgError,
|
|
113
|
-
"
|
|
114
|
-
"(
|
|
115
|
-
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]);
|
|
116
118
|
}
|
|
117
119
|
if ( p->ndim != ref->ndim ) {
|
|
118
120
|
rb_raise(rb_eArgError,
|
|
@@ -150,6 +152,19 @@ ca_meld_setup (CAMeld *ca, int32_t n_parents, CArray **parents, int8_t meld_axis
|
|
|
150
152
|
int32_t i;
|
|
151
153
|
int8_t a;
|
|
152
154
|
|
|
155
|
+
/* Pre-strip Face parents one level to storage, as CAStack does, so a
|
|
156
|
+
melded Face lifts to a single-Face chain (CATime[CAMeld[entity, ...]])
|
|
157
|
+
rather than a Face sitting on Face parents. One level, not a full walk,
|
|
158
|
+
preserves any distinct Face a parent melded underneath. A Face is
|
|
159
|
+
storage-transparent, so welding over storage reads the same bytes; the
|
|
160
|
+
lifted top Face (rb_ca_meld_s_new) carries the identity. The @parents
|
|
161
|
+
accessor keeps the originals, which the callers set. */
|
|
162
|
+
for ( i = 0; i < n_parents; i++ ) {
|
|
163
|
+
if ( ca_is_face(parents[i]) ) {
|
|
164
|
+
parents[i] = CAVIEW(parents[i])->parent;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
153
168
|
ca_meld_check_uniform(n_parents, parents, meld_axis);
|
|
154
169
|
ref = parents[0];
|
|
155
170
|
|
|
@@ -166,6 +181,8 @@ ca_meld_setup (CAMeld *ca, int32_t n_parents, CArray **parents, int8_t meld_axis
|
|
|
166
181
|
ca->attach = 0;
|
|
167
182
|
ca->nosync = 0;
|
|
168
183
|
|
|
184
|
+
ca->mask_standins = NULL;
|
|
185
|
+
ca->mask_owner = NULL;
|
|
169
186
|
ca->n_parents = n_parents;
|
|
170
187
|
ca->parents = ALLOC_N(CArray *, n_parents);
|
|
171
188
|
for ( i = 0; i < n_parents; i++ ) {
|
|
@@ -209,6 +226,13 @@ free_ca_meld (void *ap)
|
|
|
209
226
|
CAMeld *ca = (CAMeld *) ap;
|
|
210
227
|
if ( ca != NULL ) {
|
|
211
228
|
ca_free(ca->mask);
|
|
229
|
+
if ( ca->mask_standins ) {
|
|
230
|
+
int32_t k;
|
|
231
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
232
|
+
if ( ca->mask_standins[k] ) ca_free(ca->mask_standins[k]);
|
|
233
|
+
}
|
|
234
|
+
xfree(ca->mask_standins);
|
|
235
|
+
}
|
|
212
236
|
xfree(ca->seg_offset);
|
|
213
237
|
xfree(ca->parents);
|
|
214
238
|
xfree(ca->dim);
|
|
@@ -258,10 +282,33 @@ ca_meld_tail_elements (const CAMeld *ca)
|
|
|
258
282
|
|
|
259
283
|
/* view[..., v at meld_axis, ...] = parents[k][..., v - seg_offset[k], ...]
|
|
260
284
|
where k = segment_of(v). */
|
|
285
|
+
/* On the mask of a CAMeld: let its stand-ins give way to the parents' own
|
|
286
|
+
masks (see ca_multi_parent_mask_refresh). */
|
|
287
|
+
static void
|
|
288
|
+
ca_meld_mask_refresh (CAMeld *ca, int for_write)
|
|
289
|
+
{
|
|
290
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
291
|
+
if ( o != NULL ) {
|
|
292
|
+
ca_multi_parent_mask_refresh((CArray *) ca, o->parents, o->mask_standins,
|
|
293
|
+
o->n_parents, for_write);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
static void
|
|
298
|
+
ca_meld_mask_settle (CAMeld *ca)
|
|
299
|
+
{
|
|
300
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
301
|
+
if ( o != NULL ) {
|
|
302
|
+
ca_multi_parent_mask_settle((CArray *) ca, o->parents, o->mask_standins,
|
|
303
|
+
o->n_parents);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
261
307
|
static void
|
|
262
308
|
ca_meld_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
263
309
|
{
|
|
264
310
|
CAMeld *ca = (CAMeld *) ap;
|
|
311
|
+
ca_meld_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
265
312
|
int8_t ma = ca->meld_axis;
|
|
266
313
|
ca_size_t v = idx[ma];
|
|
267
314
|
int32_t k;
|
|
@@ -296,6 +343,7 @@ ca_meld_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
296
343
|
void *data, int dir)
|
|
297
344
|
{
|
|
298
345
|
CAMeld *ca = (CAMeld *) ap;
|
|
346
|
+
ca_meld_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
299
347
|
int8_t ma = ca->meld_axis;
|
|
300
348
|
ca_size_t bytes = ca->bytes;
|
|
301
349
|
ca_size_t view_div[CA_RANK_MAX]; /* row-major divisor per view axis */
|
|
@@ -591,7 +639,9 @@ static void
|
|
|
591
639
|
ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
592
640
|
ca_size_t *strides, void *data, int dir)
|
|
593
641
|
{
|
|
642
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
594
643
|
CAMeld *ca = (CAMeld *) ap;
|
|
644
|
+
ca_meld_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
595
645
|
int8_t ma = ca->meld_axis;
|
|
596
646
|
ca_size_t native[CA_RANK_MAX];
|
|
597
647
|
ca_size_t s;
|
|
@@ -601,29 +651,27 @@ ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
601
651
|
s = ca->bytes;
|
|
602
652
|
for ( i = ca->ndim - 1; i >= 0; i-- ) { native[i] = s; s *= ca->dim[i]; }
|
|
603
653
|
|
|
604
|
-
/*
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
ca_size_t req_hi = (( last < starts[ma] ) ? starts[ma] : last) + 1;
|
|
613
|
-
if ( counts[ma] > 0 && ( req_lo < 0 || req_hi > ca->dim[ma] ) ) {
|
|
614
|
-
rb_raise(rb_eIndexError,
|
|
615
|
-
"CAMeld xfer_stride meld_axis (axis %d) [%lld, %lld) out of range [0, %lld)",
|
|
616
|
-
(int) ma, (long long) req_lo, (long long) req_hi, (long long) ca->dim[ma]);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
654
|
+
/* Structural iff strides == native and the request is a box over the
|
|
655
|
+
view's own axes. Equal strides alone are not enough: a size-1 axis
|
|
656
|
+
gives two axes the same native stride, and a flat window reshaped back
|
|
657
|
+
to ndim has native strides yet wraps across an axis. The request is
|
|
658
|
+
over the view's addresses; see ca_xfer_stride_request_is_axis_box
|
|
659
|
+
(carray.h). Inside the gate the step on every axis is 1 and the region
|
|
660
|
+
stays inside each axis, which ca_meld_xfer_stride_ma_internal (handed
|
|
661
|
+
no strides) depends on. */
|
|
619
662
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
620
663
|
if ( strides[i] != native[i] ) { structural = 0; break; }
|
|
621
664
|
}
|
|
665
|
+
if ( structural &&
|
|
666
|
+
! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
667
|
+
structural = 0;
|
|
668
|
+
}
|
|
622
669
|
|
|
623
|
-
if ( ! structural ) {
|
|
670
|
+
if ( ! structural || ! ca_fast_paths_enabled() ) {
|
|
624
671
|
ca_meld_xfer_stride_per_cell(ca, starts, counts, strides, data, dir);
|
|
625
672
|
return;
|
|
626
673
|
}
|
|
674
|
+
|
|
627
675
|
if ( ma == 0 ) {
|
|
628
676
|
ca_meld_xfer_stride_ma0(ca, starts, counts, strides, data, dir);
|
|
629
677
|
} else {
|
|
@@ -635,15 +683,37 @@ ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
635
683
|
/* xfer_all */
|
|
636
684
|
/* ------------------------------------------------------------------- */
|
|
637
685
|
|
|
686
|
+
/* A parent's cells, delivered (PUT). into_buffers writes them into the
|
|
687
|
+
buffer the parent's attach handed out, rather than through the parent to
|
|
688
|
+
what is behind it: the sync of an attached meld, which then syncs each
|
|
689
|
+
parent. Writing past the buffer would leave it stale, and the parent's
|
|
690
|
+
own sync would push the stale buffer back over the cells just written. */
|
|
691
|
+
static void
|
|
692
|
+
ca_meld_put_parent (CArray *p, char *src, int into_buffers)
|
|
693
|
+
{
|
|
694
|
+
if ( into_buffers ) {
|
|
695
|
+
memcpy(p->ptr, src, (size_t) (p->elements * p->bytes));
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
ca_xfer_all(p, src, CA_XFER_PUT);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
638
702
|
/* meld_axis == 0 best path: K contig xfer_all at prefix-sum offsets. */
|
|
639
703
|
static void
|
|
640
|
-
ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir)
|
|
704
|
+
ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir, int into_buffers)
|
|
641
705
|
{
|
|
642
706
|
ca_size_t tail_bytes = ca_meld_tail_elements(ca) * ca->bytes;
|
|
643
707
|
char *d = (char *) data;
|
|
644
708
|
int32_t k;
|
|
645
709
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
646
|
-
|
|
710
|
+
char *seg = d + ca->seg_offset[k] * tail_bytes;
|
|
711
|
+
if ( dir == CA_XFER_PUT ) {
|
|
712
|
+
ca_meld_put_parent(ca->parents[k], seg, into_buffers);
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
ca_xfer_all(ca->parents[k], seg, dir);
|
|
716
|
+
}
|
|
647
717
|
}
|
|
648
718
|
}
|
|
649
719
|
|
|
@@ -660,7 +730,8 @@ ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir)
|
|
|
660
730
|
The naive per-cell odometer that this replaces cost ~2x eager on M2;
|
|
661
731
|
chunked memcpy approaches memcpy bandwidth (eager parity target). */
|
|
662
732
|
static void
|
|
663
|
-
ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir
|
|
733
|
+
ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir,
|
|
734
|
+
int into_buffers)
|
|
664
735
|
{
|
|
665
736
|
int8_t ma = ca->meld_axis;
|
|
666
737
|
int8_t ndim = ca->ndim;
|
|
@@ -745,23 +816,29 @@ ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir)
|
|
|
745
816
|
}
|
|
746
817
|
|
|
747
818
|
if ( dir == CA_XFER_PUT ) {
|
|
748
|
-
|
|
819
|
+
ca_meld_put_parent(p, buf, into_buffers);
|
|
749
820
|
}
|
|
750
821
|
ALLOCV_END(holder);
|
|
751
822
|
}
|
|
752
823
|
}
|
|
753
824
|
|
|
754
825
|
static void
|
|
755
|
-
|
|
826
|
+
ca_meld_xfer_parents (CAMeld *ca, void *data, int dir, int into_buffers)
|
|
756
827
|
{
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
ca_meld_xfer_all_ma0(ca, data, dir);
|
|
828
|
+
if ( ca->meld_axis == 0 && ca_fast_paths_enabled() ) {
|
|
829
|
+
ca_meld_xfer_all_ma0(ca, data, dir, into_buffers);
|
|
760
830
|
} else {
|
|
761
|
-
ca_meld_xfer_all_ma_internal(ca, data, dir);
|
|
831
|
+
ca_meld_xfer_all_ma_internal(ca, data, dir, into_buffers);
|
|
762
832
|
}
|
|
763
833
|
}
|
|
764
834
|
|
|
835
|
+
static void
|
|
836
|
+
ca_meld_func_xfer_all (void *ap, void *data, int dir)
|
|
837
|
+
{
|
|
838
|
+
ca_meld_mask_refresh((CAMeld *) ap, dir == CA_XFER_PUT);
|
|
839
|
+
ca_meld_xfer_parents((CAMeld *) ap, data, dir, 0);
|
|
840
|
+
}
|
|
841
|
+
|
|
765
842
|
/* ------------------------------------------------------------------- */
|
|
766
843
|
/* attach / sync / detach */
|
|
767
844
|
/* ------------------------------------------------------------------- */
|
|
@@ -770,34 +847,42 @@ static void
|
|
|
770
847
|
ca_meld_func_allocate (void *ap)
|
|
771
848
|
{
|
|
772
849
|
CAMeld *ca = (CAMeld *) ap;
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
ca_attach(ca->parents[k]);
|
|
776
|
-
}
|
|
850
|
+
ca_meld_mask_refresh(ca, 0);
|
|
851
|
+
ca_attach_all(ca->parents, ca->n_parents);
|
|
777
852
|
ca->ptr = xmalloc(ca_length(ca));
|
|
778
853
|
}
|
|
779
854
|
|
|
855
|
+
static VALUE
|
|
856
|
+
ca_meld_attach_owned (VALUE arg)
|
|
857
|
+
{
|
|
858
|
+
ca_axis_view_attach_owned((void *) arg);
|
|
859
|
+
return Qnil;
|
|
860
|
+
}
|
|
861
|
+
|
|
780
862
|
static void
|
|
781
863
|
ca_meld_func_attach (void *ap)
|
|
782
864
|
{
|
|
783
865
|
CAMeld *ca = (CAMeld *) ap;
|
|
866
|
+
ca_meld_mask_refresh(ca, 0);
|
|
784
867
|
int32_t k;
|
|
785
|
-
|
|
786
|
-
|
|
868
|
+
int tag = 0;
|
|
869
|
+
ca_attach_all(ca->parents, ca->n_parents);
|
|
870
|
+
rb_protect(ca_meld_attach_owned, (VALUE) ca, &tag);
|
|
871
|
+
if ( tag ) {
|
|
872
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
873
|
+
ca_detach(ca->parents[k]);
|
|
874
|
+
}
|
|
875
|
+
rb_jump_tag(tag);
|
|
787
876
|
}
|
|
788
|
-
ca->ptr = xmalloc(ca_length(ca));
|
|
789
|
-
ca_meld_func_xfer_all(ca, ca->ptr, CA_XFER_GET);
|
|
790
877
|
}
|
|
791
878
|
|
|
792
879
|
static void
|
|
793
880
|
ca_meld_func_sync (void *ap)
|
|
794
881
|
{
|
|
795
882
|
CAMeld *ca = (CAMeld *) ap;
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
ca_sync(ca->parents[k]);
|
|
800
|
-
}
|
|
883
|
+
ca_meld_xfer_parents(ca, ca->ptr, CA_XFER_PUT, 1);
|
|
884
|
+
ca_sync_all(ca->parents, ca->n_parents);
|
|
885
|
+
ca_meld_mask_settle(ca);
|
|
801
886
|
}
|
|
802
887
|
|
|
803
888
|
static void
|
|
@@ -820,6 +905,7 @@ static void
|
|
|
820
905
|
ca_meld_func_fill_data (void *ap, void *ptr)
|
|
821
906
|
{
|
|
822
907
|
CAMeld *ca = (CAMeld *) ap;
|
|
908
|
+
ca_meld_mask_refresh(ca, 1);
|
|
823
909
|
int32_t k;
|
|
824
910
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
825
911
|
ca_fill(ca->parents[k], ptr);
|
|
@@ -827,7 +913,7 @@ ca_meld_func_fill_data (void *ap, void *ptr)
|
|
|
827
913
|
}
|
|
828
914
|
|
|
829
915
|
/* ------------------------------------------------------------------- */
|
|
830
|
-
/* create_mask (
|
|
916
|
+
/* create_mask (mirrors CAStack) */
|
|
831
917
|
/* ------------------------------------------------------------------- */
|
|
832
918
|
|
|
833
919
|
static void
|
|
@@ -839,14 +925,16 @@ ca_meld_func_create_mask (void *ap)
|
|
|
839
925
|
int32_t k;
|
|
840
926
|
|
|
841
927
|
mask_parents = ALLOCV_N(CArray *, holder, ca->n_parents);
|
|
928
|
+
if ( ! ca->mask_standins ) {
|
|
929
|
+
ca->mask_standins = ALLOC_N(CArray *, ca->n_parents);
|
|
930
|
+
MEMZERO(ca->mask_standins, CArray *, ca->n_parents);
|
|
931
|
+
}
|
|
842
932
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
ca_create_mask(ca->parents[k]);
|
|
846
|
-
}
|
|
847
|
-
mask_parents[k] = ca->parents[k]->mask;
|
|
933
|
+
mask_parents[k] = ca_multi_parent_mask(ca->parents[k],
|
|
934
|
+
&ca->mask_standins[k]);
|
|
848
935
|
}
|
|
849
936
|
ca->mask = (CArray *) ca_meld_new(ca->n_parents, mask_parents, ca->meld_axis);
|
|
937
|
+
((CAMeld *) ca->mask)->mask_owner = (CArray *) ca;
|
|
850
938
|
ALLOCV_END(holder);
|
|
851
939
|
}
|
|
852
940
|
|
|
@@ -865,6 +953,56 @@ ca_meld_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
865
953
|
/* operation table */
|
|
866
954
|
/* ------------------------------------------------------------------- */
|
|
867
955
|
|
|
956
|
+
/* The table's write slots: after a write, refuse a true that reached the
|
|
957
|
+
stand-in of a value array or a mask array (ca_multi_parent_mask_check).
|
|
958
|
+
Only the mask of a CAMeld has stand-ins to check. */
|
|
959
|
+
static void
|
|
960
|
+
ca_meld_mask_check (CAMeld *ca)
|
|
961
|
+
{
|
|
962
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
963
|
+
if ( o != NULL ) {
|
|
964
|
+
ca_multi_parent_mask_check((CArray *) ca, o->parents, o->mask_standins,
|
|
965
|
+
o->n_parents);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
static void
|
|
970
|
+
ca_meld_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
971
|
+
{
|
|
972
|
+
ca_meld_func_xfer_index(ap, idx, data, dir);
|
|
973
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
static void
|
|
977
|
+
ca_meld_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
978
|
+
int dir)
|
|
979
|
+
{
|
|
980
|
+
ca_meld_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
981
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
static void
|
|
985
|
+
ca_meld_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
986
|
+
ca_size_t *strides, void *data, int dir)
|
|
987
|
+
{
|
|
988
|
+
ca_meld_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
989
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
static void
|
|
993
|
+
ca_meld_put_xfer_all (void *ap, void *data, int dir)
|
|
994
|
+
{
|
|
995
|
+
ca_meld_func_xfer_all(ap, data, dir);
|
|
996
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
static void
|
|
1000
|
+
ca_meld_put_fill_data (void *ap, void *ptr)
|
|
1001
|
+
{
|
|
1002
|
+
ca_meld_func_fill_data(ap, ptr);
|
|
1003
|
+
ca_meld_mask_check((CAMeld *) ap);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
868
1006
|
ca_operation_function_t ca_meld_func = {
|
|
869
1007
|
-1, /* CA_OBJ_MELD */
|
|
870
1008
|
CA_VIEW_ARRAY,
|
|
@@ -874,13 +1012,13 @@ ca_operation_function_t ca_meld_func = {
|
|
|
874
1012
|
ca_meld_func_attach,
|
|
875
1013
|
ca_meld_func_sync,
|
|
876
1014
|
ca_meld_func_detach,
|
|
877
|
-
|
|
1015
|
+
ca_meld_put_fill_data,
|
|
878
1016
|
ca_meld_func_create_mask,
|
|
879
|
-
|
|
880
|
-
|
|
1017
|
+
ca_meld_put_xfer_index,
|
|
1018
|
+
ca_meld_put_xfer_addrs,
|
|
881
1019
|
ca_meld_func_fold_stride,
|
|
882
|
-
|
|
883
|
-
|
|
1020
|
+
ca_meld_put_xfer_stride,
|
|
1021
|
+
ca_meld_put_xfer_all,
|
|
884
1022
|
};
|
|
885
1023
|
|
|
886
1024
|
/* ------------------------------------------------------------------- */
|
|
@@ -910,7 +1048,7 @@ rb_ca_meld_new (VALUE parents_ary, int8_t meld_axis)
|
|
|
910
1048
|
ca = ca_meld_new((int32_t) n, parents, meld_axis);
|
|
911
1049
|
obj = ca_wrap_struct(ca);
|
|
912
1050
|
rb_ivar_set(obj, id_parents, rb_ary_dup(parents_ary));
|
|
913
|
-
rb_ca_set_parent(obj, rb_ary_entry(parents_ary, 0));
|
|
1051
|
+
rb_ca_set_parent(obj, ca_face_strip_one(rb_ary_entry(parents_ary, 0)));
|
|
914
1052
|
ALLOCV_END(holder);
|
|
915
1053
|
return obj;
|
|
916
1054
|
}
|
|
@@ -927,8 +1065,14 @@ rb_ca_meld_initialize_copy (VALUE self, VALUE other)
|
|
|
927
1065
|
{
|
|
928
1066
|
CAMeld *ca, *cs;
|
|
929
1067
|
TypedData_Get_Struct(self, CAMeld, &cameld_data_type, ca);
|
|
1068
|
+
ca_check_uninitialized(ca);
|
|
930
1069
|
TypedData_Get_Struct(other, CAMeld, &cameld_data_type, cs);
|
|
931
1070
|
ca_meld_setup(ca, cs->n_parents, cs->parents, cs->meld_axis);
|
|
1071
|
+
/* A copy of a meld's mask reads and writes the same stand-ins, so it
|
|
1072
|
+
answers to the same owner: its writes reach the parents' masks. The
|
|
1073
|
+
copy holds the owner alive through the masked_array ivar that dup
|
|
1074
|
+
carries over (see rb_ca_mask_array). */
|
|
1075
|
+
ca->mask_owner = cs->mask_owner;
|
|
932
1076
|
return self;
|
|
933
1077
|
}
|
|
934
1078
|
|
|
@@ -959,6 +1103,7 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
959
1103
|
NUM2LONG(axis_val), (int) ref->ndim, "CAMeld.new");
|
|
960
1104
|
}
|
|
961
1105
|
TypedData_Get_Struct(self, CAMeld, &cameld_data_type, ca);
|
|
1106
|
+
ca_check_uninitialized(ca);
|
|
962
1107
|
parents = ALLOCV_N(CArray *, holder, n);
|
|
963
1108
|
for ( i = 0; i < n; i++ ) {
|
|
964
1109
|
VALUE p = rb_ary_entry(list, i);
|
|
@@ -967,11 +1112,45 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
967
1112
|
}
|
|
968
1113
|
ca_meld_setup(ca, (int32_t) n, parents, meld_axis);
|
|
969
1114
|
rb_ivar_set(self, id_parents, rb_ary_dup(list));
|
|
970
|
-
rb_ca_set_parent(self, rb_ary_entry(list, 0));
|
|
1115
|
+
rb_ca_set_parent(self, ca_face_strip_one(rb_ary_entry(list, 0)));
|
|
971
1116
|
ALLOCV_END(holder);
|
|
972
1117
|
return self;
|
|
973
1118
|
}
|
|
974
1119
|
|
|
1120
|
+
/* CAMeld.new(list, axis: 0) -- Class#new override, the twin of
|
|
1121
|
+
rb_ca_stack_s_new. A melded view has one surface over many parents, so a
|
|
1122
|
+
homogeneous Face list is treated the way CAStack treats it: refuse a Face
|
|
1123
|
+
whose state is per-parent (the cells of parent i are only readable against
|
|
1124
|
+
parent i's own state -- a CAConstString's cells are byte ranges into ITS
|
|
1125
|
+
buffer), and lift the rest so the Face survives the weld.
|
|
1126
|
+
|
|
1127
|
+
Without this meld was the one multi-parent constructor that neither asked
|
|
1128
|
+
nor lifted: it returned the raw storage of whatever it was given, which for
|
|
1129
|
+
CAConstString meant 16-byte (start,end) pairs presented as the string cells,
|
|
1130
|
+
and for CATime meant raw int64 ticks. Both looked like data.
|
|
1131
|
+
|
|
1132
|
+
Doing it here rather than in CArray.meld covers CAFrame.meld and a direct
|
|
1133
|
+
CAMeld.new by the same check. */
|
|
1134
|
+
static VALUE
|
|
1135
|
+
rb_ca_meld_s_new (int argc, VALUE *argv, VALUE klass)
|
|
1136
|
+
{
|
|
1137
|
+
VALUE list, kwargs, face_class;
|
|
1138
|
+
VALUE obj;
|
|
1139
|
+
|
|
1140
|
+
rb_scan_args(argc, argv, "1:", &list, &kwargs);
|
|
1141
|
+
Check_Type(list, T_ARRAY);
|
|
1142
|
+
if ( RARRAY_LEN(list) <= 0 ) {
|
|
1143
|
+
rb_raise(rb_eArgError, "CAMeld.new requires at least one parent");
|
|
1144
|
+
}
|
|
1145
|
+
face_class = ca_face_list_class(list, "CAMeld.new");
|
|
1146
|
+
|
|
1147
|
+
obj = rb_obj_alloc(klass);
|
|
1148
|
+
rb_obj_call_init_kw(obj, argc, argv, RB_PASS_CALLED_KEYWORDS);
|
|
1149
|
+
|
|
1150
|
+
if ( NIL_P(face_class) ) return obj;
|
|
1151
|
+
return ca_face_lift(obj, rb_ary_entry(list, 0));
|
|
1152
|
+
}
|
|
1153
|
+
|
|
975
1154
|
static VALUE
|
|
976
1155
|
rb_ca_meld_n_parents (VALUE self)
|
|
977
1156
|
{
|
|
@@ -1027,6 +1206,7 @@ Init_ca_obj_meld (void)
|
|
|
1027
1206
|
id_parents = rb_intern("parents");
|
|
1028
1207
|
|
|
1029
1208
|
rb_define_alloc_func(rb_cCAMeld, rb_ca_meld_s_allocate);
|
|
1209
|
+
rb_define_singleton_method(rb_cCAMeld, "new", rb_ca_meld_s_new, -1);
|
|
1030
1210
|
rb_define_method(rb_cCAMeld, "initialize",
|
|
1031
1211
|
rb_ca_meld_initialize, -1);
|
|
1032
1212
|
rb_define_method(rb_cCAMeld, "initialize_copy",
|