carray 3.0.4 → 3.0.6
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 +438 -0
- data/README.md +1 -1
- data/carray.gemspec +3 -2
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_dispatch.c +19 -20
- data/ext/ca_axis_group.c +1 -1
- data/ext/ca_categorical_iterator.c +34 -27
- data/ext/ca_compare.c +4 -4
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_kernel_iterator.c +122 -237
- data/ext/ca_kernel_iterator.h +522 -337
- data/ext/ca_obj_array.c +69 -19
- data/ext/ca_obj_bincmp.c +10 -1
- data/ext/ca_obj_binop.c +11 -1
- data/ext/ca_obj_bitarray.c +5 -1
- data/ext/ca_obj_bitfield.c +60 -43
- data/ext/ca_obj_byte_swap.c +4 -1
- data/ext/ca_obj_const_string.c +15 -3
- data/ext/ca_obj_face.c +44 -1
- data/ext/ca_obj_fake.c +3 -1
- data/ext/ca_obj_field.c +13 -3
- data/ext/ca_obj_grid.c +219 -17
- data/ext/ca_obj_meld.c +69 -113
- data/ext/ca_obj_moncmp.c +9 -1
- data/ext/ca_obj_monop.c +86 -12
- data/ext/ca_obj_object.c +118 -32
- data/ext/ca_obj_record.c +3 -0
- data/ext/ca_obj_reduce.c +19 -1
- data/ext/ca_obj_refer.c +80 -26
- data/ext/ca_obj_remap.c +69 -10
- data/ext/ca_obj_roll.c +27 -6
- data/ext/ca_obj_select.c +38 -6
- data/ext/ca_obj_select_axis.c +1 -0
- data/ext/ca_obj_shift.c +32 -7
- data/ext/ca_obj_stack.c +311 -111
- data/ext/ca_obj_stride.c +159 -64
- data/ext/ca_obj_string.c +27 -2
- data/ext/ca_obj_tile.c +28 -7
- data/ext/ca_obj_transpose.c +8 -4
- data/ext/ca_obj_triop.c +12 -1
- data/ext/ca_obj_window.c +80 -50
- data/ext/ca_op_ipower.c +12 -12
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +35 -1
- data/ext/carray_access.c +43 -67
- data/ext/carray_address_basis.c +134 -0
- data/ext/carray_attribute.c +32 -0
- data/ext/carray_broadcast.c +3 -4
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_cast.c +251 -93
- data/ext/carray_cast_func.rb +56 -26
- data/ext/carray_conversion.c +11 -7
- data/ext/carray_core.c +814 -72
- data/ext/carray_count.c +6 -0
- data/ext/carray_element.c +22 -13
- data/ext/carray_factorize.c +20 -20
- data/ext/carray_generate.c +8 -2
- data/ext/carray_histogram.c +26 -4
- data/ext/carray_index_classifier.c +4 -4
- data/ext/carray_internal.h +159 -12
- data/ext/carray_kernels_bincmp.c +2174 -170
- data/ext/carray_kernels_binop.c +25653 -5487
- data/ext/carray_kernels_init.c +8 -8
- data/ext/carray_kernels_moncmp.c +96 -96
- data/ext/carray_kernels_monop.c +12253 -5235
- data/ext/carray_kernels_reduce_aggregate.c +6150 -2423
- data/ext/carray_kernels_reduce_boolean.c +1533 -15
- data/ext/carray_kernels_reduce_cumulative.c +2442 -882
- data/ext/carray_kernels_reduce_extreme.c +5658 -1661
- data/ext/carray_kernels_reduce_variance.c +2534 -402
- data/ext/carray_kernels_scan.c +368 -368
- data/ext/carray_kernels_search.c +4551 -604
- data/ext/carray_kernels_sort.c +659 -751
- data/ext/carray_kernels_triop.c +114 -114
- data/ext/carray_key_windows.c +4 -0
- data/ext/carray_lazy.c +47 -0
- data/ext/carray_loop.c +1 -1
- data/ext/carray_mask.c +175 -161
- data/ext/carray_median_percentile.c +4 -4
- data/ext/carray_memory_view.c +15 -9
- data/ext/carray_operator.c +152 -49
- data/ext/carray_order.c +230 -10
- data/ext/carray_random.c +22 -19
- data/ext/carray_scatter.c +24 -7
- data/ext/carray_slab.c +128 -29
- data/ext/carray_sort.c +224 -16
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +35 -43
- data/ext/carray_test.c +74 -19
- data/ext/carray_time_text.c +6 -4
- data/ext/carray_utils.c +63 -21
- data/ext/extconf.rb +11 -0
- data/ext/mkkernel.rb +546 -199
- data/ext/ruby_carray.c +4 -1
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +42 -5
- data/lib/carray/autoload_carray.rb +3 -3
- data/lib/carray/autoload_method_extension.rb +5 -3
- data/lib/carray/axis_group.rb +13 -7
- data/lib/carray/basics.rb +28 -8
- data/lib/carray/block_iterator.rb +17 -3
- data/lib/carray/categorical.rb +35 -23
- data/lib/carray/categorical_iterator.rb +8 -8
- data/lib/carray/complex.rb +2 -2
- data/lib/carray/conditional.rb +3 -2
- data/lib/carray/const_string.rb +10 -0
- data/lib/carray/data_type_extension.rb +8 -1
- data/lib/carray/fixlen_string.rb +41 -2
- data/lib/carray/frame/column_verbs.rb +48 -16
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +19 -0
- data/lib/carray/frame/csv_parser.rb +32 -32
- data/lib/carray/frame/describe.rb +4 -2
- data/lib/carray/frame/frame.rb +405 -85
- data/lib/carray/frame/group.rb +777 -64
- data/lib/carray/frame/io.rb +212 -72
- data/lib/carray/frame/join.rb +146 -37
- data/lib/carray/frame/records.rb +3 -3
- data/lib/carray/frame/reshape.rb +89 -11
- data/lib/carray/frame/sort.rb +57 -9
- data/lib/carray/frame/verbs.rb +384 -49
- data/lib/carray/frame/windows.rb +44 -6
- data/lib/carray/fuse_source.rb +31 -2
- data/lib/carray/inspect.rb +7 -2
- data/lib/carray/iterator.rb +32 -0
- data/lib/carray/lazy.rb +52 -8
- data/lib/carray/mask_gap_fill.rb +37 -17
- data/lib/carray/meld_reduce.rb +1 -1
- data/lib/carray/methods/choose.rb +3 -2
- data/lib/carray/methods/is_in.rb +8 -1
- data/lib/carray/methods/meshgrid.rb +3 -1
- data/lib/carray/runtime.rb +47 -8
- data/lib/carray/segment_iterator.rb +35 -16
- data/lib/carray/serialize.rb +53 -19
- data/lib/carray/stack.rb +33 -18
- data/lib/carray/string.rb +8 -0
- data/lib/carray/string_operation_extension.rb +13 -5
- data/lib/carray/struct_builder.rb +5 -3
- data/lib/carray/time.rb +112 -68
- data/lib/carray/window_iterator.rb +16 -4
- data/yard-stubs/ca_obj_array.rb +26 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/carray_attribute.rb +3 -1
- data/yard-stubs/carray_cast.rb +10 -5
- data/yard-stubs/carray_conversion.rb +13 -3
- data/yard-stubs/carray_element.rb +7 -6
- data/yard-stubs/carray_mask.rb +28 -4
- data/yard-stubs/carray_math.rb +45 -20
- data/yard-stubs/carray_memory_view.rb +7 -0
- data/yard-stubs/carray_order.rb +100 -4
- data/yard-stubs/carray_scatter.rb +7 -5
- data/yard-stubs/carray_test.rb +7 -4
- metadata +18 -4
data/ext/ca_obj_stack.c
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
#include "carray.h"
|
|
21
21
|
#include "carray_internal.h" /* ca_attach_all / ca_sync_all */
|
|
22
|
+
#include <ruby/ractor.h>
|
|
22
23
|
#include "ca_composite_dispatch.h"
|
|
23
24
|
#include "ca_obj_face.h"
|
|
24
25
|
|
|
@@ -289,12 +290,7 @@ ca_stack_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
289
290
|
rb_raise(rb_eIndexError, "CAStack k-axis (axis %d) index %lld out of range [0, %d)",
|
|
290
291
|
(int) k_axis, (long long) k, (int) ca->n_parents);
|
|
291
292
|
}
|
|
292
|
-
|
|
293
|
-
/* Fast path: parent_idx = idx[1..ndim-1]; pass idx+1 directly. */
|
|
294
|
-
ca_xfer_index(ca->parents[k], idx + 1, data, dir);
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
/* General case: build parent_idx by removing the k_axis slot. */
|
|
293
|
+
/* The parent index is idx without the k_axis slot. */
|
|
298
294
|
{
|
|
299
295
|
ca_size_t pidx[CA_RANK_MAX];
|
|
300
296
|
int8_t a, pndim = ca->ndim - 1;
|
|
@@ -331,7 +327,7 @@ ca_stack_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
331
327
|
paddrs = ALLOCV_N(ca_size_t, holder1, n);
|
|
332
328
|
pdata = ALLOCV_N(char, holder2, n * bytes);
|
|
333
329
|
|
|
334
|
-
if ( k_axis == 0 &&
|
|
330
|
+
if ( k_axis == 0 && ca_fast_path(CA_SC_STACK_ADDRS_K0) ) {
|
|
335
331
|
/* Fast path: addr = k * parent_elements + parent_addr (row-major over
|
|
336
332
|
view shape with K at axis 0). */
|
|
337
333
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
@@ -479,7 +475,13 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
479
475
|
! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
480
476
|
structural = 0;
|
|
481
477
|
}
|
|
482
|
-
|
|
478
|
+
/* With the stack axis between the first and the last, each parent's box
|
|
479
|
+
lands in dst one cell at a time below; the reloc walk further down
|
|
480
|
+
takes the same box a contiguous row at a time, about 5x faster on a
|
|
481
|
+
block of a 500x4x2000 stack. With it last the reloc walk goes cell by
|
|
482
|
+
cell instead, so the box stays here. */
|
|
483
|
+
if ( k_axis != 0 && k_axis != ca->ndim - 1 ) structural = 0;
|
|
484
|
+
if ( ! ca_fast_path(CA_SC_STACK_STRIDE_BOX) ) structural = 0;
|
|
483
485
|
|
|
484
486
|
if ( structural ) {
|
|
485
487
|
ca_size_t k_lo = starts[k_axis];
|
|
@@ -571,7 +573,7 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
571
573
|
with native[k_axis] removed, in order. */
|
|
572
574
|
{
|
|
573
575
|
int8_t p = -1;
|
|
574
|
-
int reloc =
|
|
576
|
+
int reloc = ca_fast_path(CA_SC_STACK_STRIDE_RELOC);
|
|
575
577
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
576
578
|
if ( strides[i] == native[k_axis] ) { p = i; break; }
|
|
577
579
|
}
|
|
@@ -680,6 +682,25 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
680
682
|
}
|
|
681
683
|
}
|
|
682
684
|
|
|
685
|
+
/* A parent's cells, delivered (PUT): into the buffer its attach handed
|
|
686
|
+
out, or through the parent (see ca_stack_xfer_parents). A parent with no
|
|
687
|
+
buffer out (a stand-in the trial of a write puts in place, which is never
|
|
688
|
+
attached) has nothing to go stale: the cells go through it. */
|
|
689
|
+
static void
|
|
690
|
+
ca_stack_put_parent (CArray *p, char *src, volatile VALUE *sync_error)
|
|
691
|
+
{
|
|
692
|
+
if ( sync_error != NULL && p->ptr != NULL ) {
|
|
693
|
+
/* Synced at once, before the next part is written: parts that share
|
|
694
|
+
cells then take the write of the last of them, as a write through
|
|
695
|
+
the parts does. */
|
|
696
|
+
memcpy(p->ptr, src, (size_t) (p->elements * p->bytes));
|
|
697
|
+
ca_sync_carry_on(p, sync_error);
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
ca_xfer_all(p, src, CA_XFER_PUT);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
683
704
|
/* ------------------------------------------------------------------- */
|
|
684
705
|
/* xfer_all: K-fold over all parents */
|
|
685
706
|
/* ------------------------------------------------------------------- */
|
|
@@ -693,13 +714,14 @@ ca_stack_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
693
714
|
correctness path (per-parent contig-read / scattered-write), not a
|
|
694
715
|
perf-optimised one.
|
|
695
716
|
|
|
696
|
-
|
|
697
|
-
attach handed out, rather than through the parent to what is
|
|
698
|
-
the sync of an attached stack
|
|
717
|
+
A non-NULL sync_error (PUT only) writes each parent's cells into the
|
|
718
|
+
buffer its attach handed out, rather than through the parent to what is
|
|
719
|
+
behind it, and syncs the parent: the sync of an attached stack. Writing
|
|
699
720
|
past the buffer would leave it stale, and the parent's own sync would
|
|
700
|
-
push the stale buffer back over the cells just written.
|
|
721
|
+
push the stale buffer back over the cells just written. An exception
|
|
722
|
+
from one parent's sync is kept in *sync_error while the others go on. */
|
|
701
723
|
static void
|
|
702
|
-
ca_stack_xfer_parents (CAStack *ca, char *d, int dir,
|
|
724
|
+
ca_stack_xfer_parents (CAStack *ca, char *d, int dir, volatile VALUE *sync_error)
|
|
703
725
|
{
|
|
704
726
|
int8_t k_axis = ca->k_axis;
|
|
705
727
|
ca_size_t bytes = ca->bytes;
|
|
@@ -709,12 +731,12 @@ ca_stack_xfer_parents (CAStack *ca, char *d, int dir, int into_buffers)
|
|
|
709
731
|
counts. */
|
|
710
732
|
if ( ca->elements == 0 ) return;
|
|
711
733
|
|
|
712
|
-
if ( k_axis == 0 &&
|
|
734
|
+
if ( k_axis == 0 && ca_fast_path(CA_SC_STACK_PARENTS_K0) ) {
|
|
713
735
|
ca_size_t parent_bytes_total = ca->parents[0]->elements * bytes;
|
|
714
736
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
715
|
-
if (
|
|
716
|
-
|
|
717
|
-
|
|
737
|
+
if ( dir == CA_XFER_PUT ) {
|
|
738
|
+
ca_stack_put_parent(ca->parents[k], d + k * parent_bytes_total,
|
|
739
|
+
sync_error);
|
|
718
740
|
}
|
|
719
741
|
else {
|
|
720
742
|
ca_xfer_all(ca->parents[k], d + k * parent_bytes_total, dir);
|
|
@@ -808,12 +830,7 @@ ca_stack_xfer_parents (CAStack *ca, char *d, int dir, int into_buffers)
|
|
|
808
830
|
}
|
|
809
831
|
|
|
810
832
|
if ( dir == CA_XFER_PUT ) {
|
|
811
|
-
|
|
812
|
-
memcpy(ca->parents[k]->ptr, buf, (size_t) (parent_elements * bytes));
|
|
813
|
-
}
|
|
814
|
-
else {
|
|
815
|
-
ca_xfer_all(ca->parents[k], buf, CA_XFER_PUT);
|
|
816
|
-
}
|
|
833
|
+
ca_stack_put_parent(ca->parents[k], buf, sync_error);
|
|
817
834
|
}
|
|
818
835
|
}
|
|
819
836
|
}
|
|
@@ -825,7 +842,7 @@ static void
|
|
|
825
842
|
ca_stack_func_xfer_all (void *ap, void *data, int dir)
|
|
826
843
|
{
|
|
827
844
|
ca_stack_mask_refresh((CAStack *) ap);
|
|
828
|
-
ca_stack_xfer_parents((CAStack *) ap, (char *) data, dir,
|
|
845
|
+
ca_stack_xfer_parents((CAStack *) ap, (char *) data, dir, NULL);
|
|
829
846
|
}
|
|
830
847
|
|
|
831
848
|
/* ------------------------------------------------------------------- */
|
|
@@ -857,15 +874,19 @@ ca_stack_func_attach (void *ap)
|
|
|
857
874
|
ca_fill_or_detach(ca->n_parents, ca->parents, ca_stack_attach_owned, (VALUE) ca);
|
|
858
875
|
}
|
|
859
876
|
|
|
860
|
-
static void ca_stack_mask_refuse_sync (CAStack *ca);
|
|
861
|
-
|
|
862
877
|
static void
|
|
863
878
|
ca_stack_func_sync (void *ap)
|
|
864
879
|
{
|
|
865
880
|
CAStack *ca = (CAStack *) ap;
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
881
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ca, t,
|
|
882
|
+
ca_stack_xfer_parents((CAStack *) t, ca->ptr, CA_XFER_PUT, NULL));
|
|
883
|
+
{
|
|
884
|
+
volatile VALUE error = Qnil;
|
|
885
|
+
ca_stack_xfer_parents(ca, ca->ptr, CA_XFER_PUT, &error);
|
|
886
|
+
if ( ! NIL_P(error) ) {
|
|
887
|
+
rb_exc_raise(error);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
869
890
|
ca_stack_mask_settle(ca);
|
|
870
891
|
}
|
|
871
892
|
|
|
@@ -969,7 +990,8 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
969
990
|
through to CAStack.xfer_stride (k_axis-aware), which still delivers
|
|
970
991
|
correct (if non-folded) per-parent dispatch. */
|
|
971
992
|
if ( ca->k_axis != 0 ) return 0;
|
|
972
|
-
if ( !
|
|
993
|
+
if ( ! ca_fast_path(CA_SC_STACK_FOLD) ) return 0;
|
|
994
|
+
if ( pbt == 0 ) return 0; /* empty parents: no parent holds the box */
|
|
973
995
|
|
|
974
996
|
for ( i = 0; i < f->ndim; i++ ) {
|
|
975
997
|
ca_size_t span = (f->counts[i] - 1) * f->strides[i];
|
|
@@ -980,6 +1002,16 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
980
1002
|
if ( k < 0 || k >= ca->n_parents ) return 0;
|
|
981
1003
|
if ( hi >= (k + 1) * pbt ) return 0; /* box spans >1 parent */
|
|
982
1004
|
|
|
1005
|
+
/* A view folded past this stack is built on the parent's root and asks
|
|
1006
|
+
that root for its mask. Whether the parent is a value array or a mask
|
|
1007
|
+
array is answered along the parent's own chain, which the folded view
|
|
1008
|
+
is not on (ca_keep_chain_flags reads the chain of the view folded,
|
|
1009
|
+
and it stops at a stack): the view would read the root's mask through
|
|
1010
|
+
a value array. Such a parent stays behind the stack's transfer. */
|
|
1011
|
+
if ( ca_is_value_array(ca->parents[k]) || ca_is_mask_array(ca->parents[k]) ) {
|
|
1012
|
+
return 0;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
983
1015
|
f->base -= k * pbt;
|
|
984
1016
|
for ( i = 0; i < f->ndim; i++ ) { /* degenerate the (size-1) K axis */
|
|
985
1017
|
if ( f->strides[i] == pbt ) f->strides[i] = 0;
|
|
@@ -992,80 +1024,250 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
992
1024
|
/* operation table */
|
|
993
1025
|
/* ------------------------------------------------------------------- */
|
|
994
1026
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1027
|
+
extern int8_t CA_OBJ_MELD;
|
|
1028
|
+
CAMeld *ca_meld_new (int32_t n_parents, CArray **parents, int8_t meld_axis);
|
|
1029
|
+
|
|
1030
|
+
/* For a stack or meld holding data (not the mask of one): its parts. */
|
|
1031
|
+
static int
|
|
1032
|
+
ca_value_trial_parts (CArray *ca, CArray ***parts, int32_t *n)
|
|
1033
|
+
{
|
|
1034
|
+
if ( ca->obj_type == CA_OBJ_STACK && ((CAStack *) ca)->mask_owner == NULL ) {
|
|
1035
|
+
*parts = ((CAStack *) ca)->parents;
|
|
1036
|
+
*n = ((CAStack *) ca)->n_parents;
|
|
1037
|
+
return 1;
|
|
1038
|
+
}
|
|
1039
|
+
if ( ca->obj_type == CA_OBJ_MELD && ((CAMeld *) ca)->mask_owner == NULL ) {
|
|
1040
|
+
*parts = ((CAMeld *) ca)->parents;
|
|
1041
|
+
*n = ((CAMeld *) ca)->n_parents;
|
|
1042
|
+
return 1;
|
|
1043
|
+
}
|
|
1044
|
+
return 0;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/* The data type a write through `q` is converted to and can be refused by:
|
|
1048
|
+
the parent type of the first writable cast that changes the type, down
|
|
1049
|
+
the chain of single-parent views. -1 if there is none. */
|
|
1050
|
+
static int
|
|
1051
|
+
ca_value_trial_target (CArray *q)
|
|
1052
|
+
{
|
|
1053
|
+
int8_t t;
|
|
1054
|
+
while ( q != NULL ) {
|
|
1055
|
+
if ( ca_monop_writable_cast_target(q, &t) && t != q->data_type ) {
|
|
1056
|
+
return t;
|
|
1057
|
+
}
|
|
1058
|
+
if ( ! ca_is_view(q) || ca_test_flag(q, CA_FLAG_MULTI_PARENTS) ) {
|
|
1059
|
+
break;
|
|
1060
|
+
}
|
|
1061
|
+
q = CAVIEW(q)->parent;
|
|
1062
|
+
}
|
|
1063
|
+
return -1;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
static int
|
|
1067
|
+
ca_value_trial_needed (CArray *ca, int depth)
|
|
1068
|
+
{
|
|
1069
|
+
CArray **parts;
|
|
1070
|
+
int32_t n, k;
|
|
1071
|
+
if ( depth > 64 || ! ca_value_trial_parts(ca, &parts, &n) ) {
|
|
1072
|
+
return 0;
|
|
1073
|
+
}
|
|
1074
|
+
for ( k = 0; k < n; k++ ) {
|
|
1075
|
+
if ( ca_value_trial_target(parts[k]) >= 0
|
|
1076
|
+
|| ca_value_trial_needed(parts[k], depth + 1) ) {
|
|
1077
|
+
return 1;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
return 0;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
static CArray *
|
|
1084
|
+
ca_value_trial_hold (VALUE keep, CArray *ca)
|
|
1085
|
+
{
|
|
1086
|
+
rb_ary_push(keep, ca_wrap_struct(ca));
|
|
1087
|
+
return ca;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
static CArray *ca_value_trial_like (CArray *ca, VALUE keep, int depth);
|
|
1091
|
+
|
|
1092
|
+
/* A scratch array standing for the part `q`: converting as `q` does when
|
|
1093
|
+
`q` can refuse a value, plain otherwise. */
|
|
1094
|
+
static CArray *
|
|
1095
|
+
ca_value_trial_standin (CArray *q, VALUE keep, int depth)
|
|
1096
|
+
{
|
|
1097
|
+
CArray **parts;
|
|
1098
|
+
int32_t n;
|
|
1099
|
+
int t = ca_value_trial_target(q);
|
|
1100
|
+
if ( t >= 0 ) {
|
|
1101
|
+
VALUE z = rb_carray_new((int8_t) t, q->ndim, q->dim, 0, NULL);
|
|
1102
|
+
/* coerce: the stand-in converts as the part's own cast does */
|
|
1103
|
+
VALUE w = rb_ca_wrap_writable(z, INT2NUM(q->data_type));
|
|
1104
|
+
rb_ary_push(keep, z);
|
|
1105
|
+
rb_ary_push(keep, w);
|
|
1106
|
+
return (CArray *) DATA_PTR(w);
|
|
1107
|
+
}
|
|
1108
|
+
if ( ca_value_trial_parts(q, &parts, &n) && ca_value_trial_needed(q, depth) ) {
|
|
1109
|
+
return ca_value_trial_like(q, keep, depth);
|
|
1110
|
+
}
|
|
1111
|
+
{
|
|
1112
|
+
VALUE z = rb_carray_new(q->data_type, q->ndim, q->dim, q->bytes, NULL);
|
|
1113
|
+
rb_ary_push(keep, z);
|
|
1114
|
+
return (CArray *) DATA_PTR(z);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
static CArray *
|
|
1119
|
+
ca_value_trial_like (CArray *ca, VALUE keep, int depth)
|
|
1120
|
+
{
|
|
1121
|
+
volatile VALUE holder = 0;
|
|
1122
|
+
CArray **parts = NULL, **standins, *like;
|
|
1123
|
+
int32_t n = 0, k;
|
|
1124
|
+
ca_value_trial_parts(ca, &parts, &n);
|
|
1125
|
+
standins = ALLOCV_N(CArray *, holder, n);
|
|
1126
|
+
for ( k = 0; k < n; k++ ) {
|
|
1127
|
+
standins[k] = ca_value_trial_standin(parts[k], keep, depth + 1);
|
|
1128
|
+
}
|
|
1129
|
+
if ( ca->obj_type == CA_OBJ_STACK ) {
|
|
1130
|
+
like = (CArray *) ca_stack_new_with_axis(n, standins, ((CAStack *) ca)->k_axis);
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
like = (CArray *) ca_meld_new(n, standins, ((CAMeld *) ca)->meld_axis);
|
|
1134
|
+
}
|
|
1135
|
+
ALLOCV_END(holder);
|
|
1136
|
+
return ca_value_trial_hold(keep, like);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/* Set while a write runs against stand-ins; a write nested in it is not
|
|
1140
|
+
tried again. */
|
|
1141
|
+
static rb_ractor_local_key_t ca_value_trial_depth_key;
|
|
1142
|
+
|
|
1143
|
+
static long
|
|
1144
|
+
ca_value_trial_depth (void)
|
|
1145
|
+
{
|
|
1146
|
+
VALUE v;
|
|
1147
|
+
if ( ca_value_trial_depth_key
|
|
1148
|
+
&& rb_ractor_local_storage_value_lookup(ca_value_trial_depth_key, &v) ) {
|
|
1149
|
+
return FIX2LONG(v);
|
|
1150
|
+
}
|
|
1151
|
+
return 0;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
static void
|
|
1155
|
+
ca_value_trial_depth_add (long d)
|
|
1156
|
+
{
|
|
1157
|
+
rb_ractor_local_storage_value_set(ca_value_trial_depth_key,
|
|
1158
|
+
LONG2FIX(ca_value_trial_depth() + d));
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
int
|
|
1162
|
+
ca_multi_parent_value_needs_trial (CArray *ca)
|
|
1163
|
+
{
|
|
1164
|
+
return ca_value_trial_depth() == 0 && ca_value_trial_needed(ca, 0);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
CArray *
|
|
1168
|
+
ca_multi_parent_value_trial (CArray *ca, VALUE keep)
|
|
1169
|
+
{
|
|
1170
|
+
return ca_value_trial_like(ca, keep, 0);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
/* A view over a stack or meld can hand a write on to it in several pieces
|
|
1174
|
+
(a CAGrid picking along the stack axis), each a write of its own. The
|
|
1175
|
+
stack or meld below `ca`, reached through views that have no buffer out
|
|
1176
|
+
(a view with one gets its write checked when it is synced), when a write
|
|
1177
|
+
through `ca` needs to be tried first; NULL otherwise. */
|
|
1178
|
+
CArray *
|
|
1179
|
+
ca_multi_parent_value_trial_below (CArray *ca)
|
|
1180
|
+
{
|
|
1181
|
+
CArray *q;
|
|
1182
|
+
if ( ! ca_is_view(ca) || ca_test_flag(ca, CA_FLAG_MULTI_PARENTS)
|
|
1183
|
+
|| ca_value_trial_depth() > 0 ) {
|
|
1184
|
+
return NULL;
|
|
1185
|
+
}
|
|
1186
|
+
q = CAVIEW(ca)->parent;
|
|
1187
|
+
while ( q != NULL && ca_is_view(q) && ! ca_test_flag(q, CA_FLAG_MULTI_PARENTS) ) {
|
|
1188
|
+
if ( q->ptr != NULL ) {
|
|
1189
|
+
return NULL;
|
|
1190
|
+
}
|
|
1191
|
+
q = CAVIEW(q)->parent;
|
|
1192
|
+
}
|
|
1193
|
+
if ( q == NULL || q->ptr != NULL || ! ca_value_trial_needed(q, 0) ) {
|
|
1194
|
+
return NULL;
|
|
1195
|
+
}
|
|
1196
|
+
return q;
|
|
1197
|
+
}
|
|
1005
1198
|
|
|
1006
1199
|
typedef struct {
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
}
|
|
1200
|
+
CAMultiParent *mp;
|
|
1201
|
+
CArray **saved;
|
|
1202
|
+
CArray *saved_parent;
|
|
1203
|
+
VALUE (*body)(VALUE);
|
|
1204
|
+
VALUE arg;
|
|
1205
|
+
} ca_value_trial_swap_t;
|
|
1206
|
+
|
|
1207
|
+
static VALUE
|
|
1208
|
+
ca_value_trial_swap_body (VALUE p)
|
|
1209
|
+
{
|
|
1210
|
+
ca_value_trial_swap_t *t = (ca_value_trial_swap_t *) p;
|
|
1211
|
+
return t->body(t->arg);
|
|
1212
|
+
}
|
|
1020
1213
|
|
|
1021
1214
|
static VALUE
|
|
1022
|
-
|
|
1215
|
+
ca_value_trial_swap_restore (VALUE p)
|
|
1023
1216
|
{
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
case CA_STACK_PUT_ADDRS:
|
|
1029
|
-
ca_stack_func_xfer_addrs(a->ap, a->n, a->addrs, a->data, CA_XFER_PUT); break;
|
|
1030
|
-
case CA_STACK_PUT_STRIDE:
|
|
1031
|
-
ca_stack_func_xfer_stride(a->ap, a->starts, a->counts, a->strides, a->data,
|
|
1032
|
-
CA_XFER_PUT); break;
|
|
1033
|
-
case CA_STACK_PUT_ALL:
|
|
1034
|
-
ca_stack_func_xfer_all(a->ap, a->data, CA_XFER_PUT); break;
|
|
1035
|
-
case CA_STACK_PUT_FILL:
|
|
1036
|
-
ca_stack_func_fill_data(a->ap, a->data); break;
|
|
1037
|
-
case CA_STACK_PUT_FILL_ADDRS:
|
|
1038
|
-
ca_fill_addrs_default(a->ap, a->n, a->addrs, a->data); break;
|
|
1039
|
-
case CA_STACK_PUT_FILL_STRIDE:
|
|
1040
|
-
ca_fill_stride_default(a->ap, a->base, a->ndim, a->counts, a->steps,
|
|
1041
|
-
a->data); break;
|
|
1042
|
-
case CA_STACK_PUT_SYNC:
|
|
1043
|
-
ca_stack_xfer_parents((CAStack *) a->ap, ((CArray *) a->ap)->ptr, CA_XFER_PUT, 1);
|
|
1044
|
-
break;
|
|
1217
|
+
ca_value_trial_swap_t *t = (ca_value_trial_swap_t *) p;
|
|
1218
|
+
int32_t k;
|
|
1219
|
+
for ( k = 0; k < t->mp->n_parents; k++ ) {
|
|
1220
|
+
t->mp->parents[k] = t->saved[k];
|
|
1045
1221
|
}
|
|
1222
|
+
CAVIEW(t->mp)->parent = t->saved_parent;
|
|
1223
|
+
ca_value_trial_depth_add(-1);
|
|
1046
1224
|
return Qnil;
|
|
1047
1225
|
}
|
|
1048
1226
|
|
|
1049
|
-
|
|
1050
|
-
|
|
1227
|
+
/* Run `body(arg)` once with the parts of the stack or meld `m` replaced by
|
|
1228
|
+
stand-ins (ca_multi_parent_value_trial), then put the parts back. */
|
|
1229
|
+
void
|
|
1230
|
+
ca_multi_parent_value_trial_through (CArray *m, VALUE (*body)(VALUE), VALUE arg)
|
|
1051
1231
|
{
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1232
|
+
volatile VALUE keep = rb_ary_new();
|
|
1233
|
+
volatile VALUE holder = 0;
|
|
1234
|
+
CAMultiParent *mp = (CAMultiParent *) m;
|
|
1235
|
+
CAMultiParent *like = (CAMultiParent *) ca_multi_parent_value_trial(m, keep);
|
|
1236
|
+
ca_value_trial_swap_t t;
|
|
1237
|
+
int32_t k;
|
|
1238
|
+
t.mp = mp;
|
|
1239
|
+
t.saved = ALLOCV_N(CArray *, holder, mp->n_parents);
|
|
1240
|
+
t.saved_parent = CAVIEW(m)->parent;
|
|
1241
|
+
t.body = body;
|
|
1242
|
+
t.arg = arg;
|
|
1243
|
+
for ( k = 0; k < mp->n_parents; k++ ) {
|
|
1244
|
+
t.saved[k] = mp->parents[k];
|
|
1245
|
+
mp->parents[k] = like->parents[k];
|
|
1057
1246
|
}
|
|
1247
|
+
CAVIEW(m)->parent = mp->parents[0];
|
|
1248
|
+
ca_value_trial_depth_add(1);
|
|
1249
|
+
rb_ensure(ca_value_trial_swap_body, (VALUE) &t,
|
|
1250
|
+
ca_value_trial_swap_restore, (VALUE) &t);
|
|
1251
|
+
ALLOCV_END(holder);
|
|
1252
|
+
RB_GC_GUARD(keep);
|
|
1058
1253
|
}
|
|
1059
1254
|
|
|
1255
|
+
/* The table's write slots: after a write that may have put a true into a
|
|
1256
|
+
stand-in, the true goes on to the parent's mask (ca_mask_standin_settle).
|
|
1257
|
+
Only the mask of a CAStack has stand-ins. */
|
|
1258
|
+
/* After a write of n cells of `data` to the mask of a CAStack: a true
|
|
1259
|
+
that went into a stand-in goes on to its parent's mask. */
|
|
1060
1260
|
static void
|
|
1061
|
-
|
|
1261
|
+
ca_stack_mask_adopt_before (void *ap, const void *data, ca_size_t n)
|
|
1062
1262
|
{
|
|
1063
|
-
|
|
1064
|
-
|
|
1263
|
+
CAStack *ca = (CAStack *) ap;
|
|
1264
|
+
CAStack *o = (CAStack *) ca->mask_owner;
|
|
1265
|
+
if ( o != NULL && ca_mask_any_true(data, n) ) {
|
|
1266
|
+
ca_multi_parent_mask_adopt((CArray *) ca, o->parents, o->mask_standins,
|
|
1267
|
+
o->n_parents);
|
|
1268
|
+
}
|
|
1065
1269
|
}
|
|
1066
1270
|
|
|
1067
|
-
/* After a write of n cells of `data` to the mask of a CAStack: a true
|
|
1068
|
-
that went into a stand-in goes on to its parent's mask. */
|
|
1069
1271
|
static void
|
|
1070
1272
|
ca_stack_mask_settle_after (CAStack *ca, const void *data, ca_size_t n)
|
|
1071
1273
|
{
|
|
@@ -1077,10 +1279,7 @@ ca_stack_mask_settle_after (CAStack *ca, const void *data, ca_size_t n)
|
|
|
1077
1279
|
static void
|
|
1078
1280
|
ca_stack_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
1079
1281
|
{
|
|
1080
|
-
if ( dir == CA_XFER_PUT )
|
|
1081
|
-
ca_stack_put_t a = { CA_STACK_PUT_INDEX, ap, idx, 0, NULL, NULL, NULL, NULL, data };
|
|
1082
|
-
ca_stack_mask_refuse_first(&a);
|
|
1083
|
-
}
|
|
1282
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_adopt_before(ap, data, 1);
|
|
1084
1283
|
ca_stack_func_xfer_index(ap, idx, data, dir);
|
|
1085
1284
|
if ( dir == CA_XFER_PUT ) ca_stack_mask_settle_after((CAStack *) ap, data, 1);
|
|
1086
1285
|
}
|
|
@@ -1090,8 +1289,9 @@ ca_stack_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
|
1090
1289
|
int dir)
|
|
1091
1290
|
{
|
|
1092
1291
|
if ( dir == CA_XFER_PUT ) {
|
|
1093
|
-
|
|
1094
|
-
|
|
1292
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ap, t,
|
|
1293
|
+
ca_stack_func_xfer_addrs(t, n, addrs, data, dir));
|
|
1294
|
+
ca_stack_mask_adopt_before(ap, data, n);
|
|
1095
1295
|
}
|
|
1096
1296
|
ca_stack_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
1097
1297
|
if ( dir == CA_XFER_PUT ) ca_stack_mask_settle_after((CAStack *) ap, data, n);
|
|
@@ -1102,8 +1302,10 @@ ca_stack_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
1102
1302
|
ca_size_t *strides, void *data, int dir)
|
|
1103
1303
|
{
|
|
1104
1304
|
if ( dir == CA_XFER_PUT ) {
|
|
1105
|
-
|
|
1106
|
-
|
|
1305
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ap, t,
|
|
1306
|
+
ca_stack_func_xfer_stride(t, starts, counts, strides, data, dir));
|
|
1307
|
+
ca_stack_mask_adopt_before(ap, data,
|
|
1308
|
+
ca_shape_elements(((CArray *) ap)->ndim, counts, 1));
|
|
1107
1309
|
}
|
|
1108
1310
|
ca_stack_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
1109
1311
|
if ( dir == CA_XFER_PUT ) {
|
|
@@ -1116,8 +1318,8 @@ static void
|
|
|
1116
1318
|
ca_stack_put_xfer_all (void *ap, void *data, int dir)
|
|
1117
1319
|
{
|
|
1118
1320
|
if ( dir == CA_XFER_PUT ) {
|
|
1119
|
-
|
|
1120
|
-
|
|
1321
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ap, t, ca_stack_func_xfer_all(t, data, dir));
|
|
1322
|
+
ca_stack_mask_adopt_before(ap, data, ((CArray *) ap)->elements);
|
|
1121
1323
|
}
|
|
1122
1324
|
ca_stack_func_xfer_all(ap, data, dir);
|
|
1123
1325
|
if ( dir == CA_XFER_PUT ) {
|
|
@@ -1128,23 +1330,17 @@ ca_stack_put_xfer_all (void *ap, void *data, int dir)
|
|
|
1128
1330
|
static void
|
|
1129
1331
|
ca_stack_put_fill_data (void *ap, void *ptr)
|
|
1130
1332
|
{
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
ca_stack_mask_refuse_first(&a);
|
|
1134
|
-
}
|
|
1333
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ap, t, ca_stack_func_fill_data(t, ptr));
|
|
1334
|
+
ca_stack_mask_adopt_before(ap, ptr, 1);
|
|
1135
1335
|
ca_stack_func_fill_data(ap, ptr);
|
|
1136
1336
|
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1137
1337
|
}
|
|
1138
1338
|
|
|
1139
|
-
/* A fill of part of the mask goes cell by cell through xfer_index; run
|
|
1140
|
-
the whole of it against blank masks first, so that a cell refused late
|
|
1141
|
-
does not leave the cells before it written. */
|
|
1142
1339
|
static void
|
|
1143
1340
|
ca_stack_put_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
|
|
1144
1341
|
{
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
ca_stack_mask_refuse_first(&a);
|
|
1342
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ap, t, ca_fill_addrs_default(t, n, addrs, ptr));
|
|
1343
|
+
ca_stack_mask_adopt_before(ap, ptr, 1);
|
|
1148
1344
|
ca_fill_addrs_default(ap, n, addrs, ptr);
|
|
1149
1345
|
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1150
1346
|
}
|
|
@@ -1153,9 +1349,9 @@ static void
|
|
|
1153
1349
|
ca_stack_put_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
1154
1350
|
ca_size_t *counts, ca_size_t *steps, void *ptr)
|
|
1155
1351
|
{
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1352
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ap, t,
|
|
1353
|
+
ca_fill_stride_default(t, base, ndim, counts, steps, ptr));
|
|
1354
|
+
ca_stack_mask_adopt_before(ap, ptr, 1);
|
|
1159
1355
|
ca_fill_stride_default(ap, base, ndim, counts, steps, ptr);
|
|
1160
1356
|
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1161
1357
|
}
|
|
@@ -1215,6 +1411,7 @@ rb_ca_stack_new_with_axis (VALUE parents_ary, int8_t k_axis)
|
|
|
1215
1411
|
VALUE p = rb_ary_entry(parents_ary, i);
|
|
1216
1412
|
rb_check_carray_object(p);
|
|
1217
1413
|
TypedData_Get_Struct(p, CArray, &carray_data_type, parents[i]);
|
|
1414
|
+
ca_multi_parent_check_part(parents[i], "stack");
|
|
1218
1415
|
}
|
|
1219
1416
|
ca = ca_stack_new_with_axis((int32_t) n, parents, k_axis);
|
|
1220
1417
|
obj = ca_wrap_struct(ca);
|
|
@@ -1301,6 +1498,7 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1301
1498
|
VALUE p = rb_ary_entry(list, i);
|
|
1302
1499
|
rb_check_carray_object(p);
|
|
1303
1500
|
TypedData_Get_Struct(p, CArray, &carray_data_type, parents[i]);
|
|
1501
|
+
ca_multi_parent_check_part(parents[i], "stack");
|
|
1304
1502
|
}
|
|
1305
1503
|
ca_stack_setup_with_axis(ca, (int32_t) n, parents, k_axis);
|
|
1306
1504
|
rb_ivar_set(self, id_parents, rb_ary_dup(list)); /* GC anchor */
|
|
@@ -1378,6 +1576,7 @@ rb_ca_stack_k_axis (VALUE self)
|
|
|
1378
1576
|
void
|
|
1379
1577
|
Init_ca_obj_stack (void)
|
|
1380
1578
|
{
|
|
1579
|
+
ca_value_trial_depth_key = rb_ractor_local_storage_value_newkey();
|
|
1381
1580
|
/* CAStack must match the CAMultiParent layout convention so generic code
|
|
1382
1581
|
can fold over parents[] via the CA_FLAG_MULTI_PARENTS path. */
|
|
1383
1582
|
if ( offsetof(CAStack, n_parents) != offsetof(CAMultiParent, n_parents) ||
|
|
@@ -1396,6 +1595,7 @@ Init_ca_obj_stack (void)
|
|
|
1396
1595
|
&castack_data_type,
|
|
1397
1596
|
rb_cCAStackMask,
|
|
1398
1597
|
&castack_mask_data_type, &ca_stack_func, sizeof(ca_stack_func));
|
|
1598
|
+
ca_register_cell_moving_view(CA_OBJ_STACK);
|
|
1399
1599
|
rb_define_const(rb_cObject, "CA_OBJ_STACK", INT2NUM(CA_OBJ_STACK));
|
|
1400
1600
|
|
|
1401
1601
|
id_parents = rb_intern("parents");
|