carray 3.0.5 → 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 +233 -0
- data/README.md +1 -1
- data/carray.gemspec +3 -2
- data/ext/ca_axis_dispatch.c +6 -0
- data/ext/ca_axis_group.c +1 -1
- data/ext/ca_categorical_iterator.c +7 -7
- data/ext/ca_kernel_iterator.c +116 -231
- data/ext/ca_kernel_iterator.h +410 -254
- data/ext/ca_obj_bincmp.c +9 -1
- data/ext/ca_obj_binop.c +10 -1
- data/ext/ca_obj_bitfield.c +2 -0
- data/ext/ca_obj_byte_swap.c +2 -0
- data/ext/ca_obj_face.c +2 -0
- data/ext/ca_obj_fake.c +3 -1
- data/ext/ca_obj_grid.c +167 -12
- data/ext/ca_obj_meld.c +69 -113
- data/ext/ca_obj_moncmp.c +9 -1
- data/ext/ca_obj_monop.c +40 -2
- data/ext/ca_obj_object.c +54 -20
- data/ext/ca_obj_reduce.c +15 -1
- data/ext/ca_obj_refer.c +65 -20
- data/ext/ca_obj_remap.c +69 -10
- data/ext/ca_obj_roll.c +1 -0
- data/ext/ca_obj_select.c +4 -1
- data/ext/ca_obj_select_axis.c +1 -0
- data/ext/ca_obj_shift.c +1 -0
- data/ext/ca_obj_stack.c +310 -111
- data/ext/ca_obj_stride.c +131 -45
- data/ext/ca_obj_string.c +18 -2
- data/ext/ca_obj_tile.c +1 -0
- data/ext/ca_obj_triop.c +9 -1
- data/ext/ca_obj_window.c +1 -0
- data/ext/ca_op_ipower.c +8 -8
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +2 -1
- data/ext/carray_access.c +27 -64
- data/ext/carray_address_basis.c +134 -0
- data/ext/carray_attribute.c +8 -0
- data/ext/carray_broadcast.c +3 -4
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_cast.c +8 -11
- data/ext/carray_conversion.c +9 -5
- data/ext/carray_core.c +811 -72
- data/ext/carray_element.c +13 -9
- data/ext/carray_histogram.c +25 -3
- data/ext/carray_internal.h +147 -12
- data/ext/carray_kernels_bincmp.c +2007 -3
- data/ext/carray_kernels_binop.c +25365 -5199
- data/ext/carray_kernels_init.c +8 -8
- data/ext/carray_kernels_monop.c +10696 -3678
- data/ext/carray_kernels_reduce_aggregate.c +4429 -702
- data/ext/carray_kernels_reduce_boolean.c +1533 -15
- data/ext/carray_kernels_reduce_cumulative.c +1808 -248
- data/ext/carray_kernels_reduce_extreme.c +4508 -511
- data/ext/carray_kernels_reduce_variance.c +2284 -152
- data/ext/carray_kernels_scan.c +240 -240
- data/ext/carray_kernels_search.c +4211 -264
- data/ext/carray_kernels_sort.c +367 -450
- data/ext/carray_lazy.c +47 -0
- data/ext/carray_loop.c +1 -1
- data/ext/carray_mask.c +130 -139
- data/ext/carray_median_percentile.c +4 -4
- data/ext/carray_memory_view.c +13 -7
- data/ext/carray_operator.c +147 -44
- data/ext/carray_order.c +3 -2
- data/ext/carray_random.c +4 -1
- data/ext/carray_slab.c +97 -21
- data/ext/carray_sort.c +1 -1
- data/ext/carray_test.c +74 -19
- data/ext/carray_time_text.c +2 -2
- data/ext/extconf.rb +11 -0
- data/ext/mkkernel.rb +346 -94
- data/ext/ruby_carray.c +4 -1
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +25 -1
- 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 +1 -1
- data/lib/carray/block_iterator.rb +17 -3
- data/lib/carray/categorical.rb +6 -8
- data/lib/carray/categorical_iterator.rb +2 -2
- data/lib/carray/complex.rb +2 -2
- data/lib/carray/conditional.rb +3 -2
- data/lib/carray/frame/column_verbs.rb +45 -14
- 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 +399 -78
- data/lib/carray/frame/group.rb +679 -53
- data/lib/carray/frame/io.rb +209 -71
- 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/inspect.rb +7 -2
- data/lib/carray/iterator.rb +32 -0
- data/lib/carray/lazy.rb +17 -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/meshgrid.rb +3 -1
- data/lib/carray/runtime.rb +47 -8
- data/lib/carray/segment_iterator.rb +23 -8
- data/lib/carray/serialize.rb +34 -17
- data/lib/carray/stack.rb +18 -6
- data/lib/carray/time.rb +5 -0
- data/lib/carray/window_iterator.rb +16 -4
- data/yard-stubs/ca_obj_array.rb +26 -1
- data/yard-stubs/carray_cast.rb +8 -5
- data/yard-stubs/carray_conversion.rb +8 -2
- data/yard-stubs/carray_mask.rb +20 -1
- data/yard-stubs/carray_math.rb +31 -16
- data/yard-stubs/carray_memory_view.rb +7 -0
- 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,7 @@ 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;
|
|
973
994
|
if ( pbt == 0 ) return 0; /* empty parents: no parent holds the box */
|
|
974
995
|
|
|
975
996
|
for ( i = 0; i < f->ndim; i++ ) {
|
|
@@ -981,6 +1002,16 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
981
1002
|
if ( k < 0 || k >= ca->n_parents ) return 0;
|
|
982
1003
|
if ( hi >= (k + 1) * pbt ) return 0; /* box spans >1 parent */
|
|
983
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
|
+
|
|
984
1015
|
f->base -= k * pbt;
|
|
985
1016
|
for ( i = 0; i < f->ndim; i++ ) { /* degenerate the (size-1) K axis */
|
|
986
1017
|
if ( f->strides[i] == pbt ) f->strides[i] = 0;
|
|
@@ -993,80 +1024,250 @@ ca_stack_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
993
1024
|
/* operation table */
|
|
994
1025
|
/* ------------------------------------------------------------------- */
|
|
995
1026
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
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
|
+
}
|
|
1006
1198
|
|
|
1007
1199
|
typedef struct {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
}
|
|
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
|
+
}
|
|
1021
1213
|
|
|
1022
1214
|
static VALUE
|
|
1023
|
-
|
|
1215
|
+
ca_value_trial_swap_restore (VALUE p)
|
|
1024
1216
|
{
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
case CA_STACK_PUT_ADDRS:
|
|
1030
|
-
ca_stack_func_xfer_addrs(a->ap, a->n, a->addrs, a->data, CA_XFER_PUT); break;
|
|
1031
|
-
case CA_STACK_PUT_STRIDE:
|
|
1032
|
-
ca_stack_func_xfer_stride(a->ap, a->starts, a->counts, a->strides, a->data,
|
|
1033
|
-
CA_XFER_PUT); break;
|
|
1034
|
-
case CA_STACK_PUT_ALL:
|
|
1035
|
-
ca_stack_func_xfer_all(a->ap, a->data, CA_XFER_PUT); break;
|
|
1036
|
-
case CA_STACK_PUT_FILL:
|
|
1037
|
-
ca_stack_func_fill_data(a->ap, a->data); break;
|
|
1038
|
-
case CA_STACK_PUT_FILL_ADDRS:
|
|
1039
|
-
ca_fill_addrs_default(a->ap, a->n, a->addrs, a->data); break;
|
|
1040
|
-
case CA_STACK_PUT_FILL_STRIDE:
|
|
1041
|
-
ca_fill_stride_default(a->ap, a->base, a->ndim, a->counts, a->steps,
|
|
1042
|
-
a->data); break;
|
|
1043
|
-
case CA_STACK_PUT_SYNC:
|
|
1044
|
-
ca_stack_xfer_parents((CAStack *) a->ap, ((CArray *) a->ap)->ptr, CA_XFER_PUT, 1);
|
|
1045
|
-
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];
|
|
1046
1221
|
}
|
|
1222
|
+
CAVIEW(t->mp)->parent = t->saved_parent;
|
|
1223
|
+
ca_value_trial_depth_add(-1);
|
|
1047
1224
|
return Qnil;
|
|
1048
1225
|
}
|
|
1049
1226
|
|
|
1050
|
-
|
|
1051
|
-
|
|
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)
|
|
1052
1231
|
{
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
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];
|
|
1058
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);
|
|
1059
1253
|
}
|
|
1060
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. */
|
|
1061
1260
|
static void
|
|
1062
|
-
|
|
1261
|
+
ca_stack_mask_adopt_before (void *ap, const void *data, ca_size_t n)
|
|
1063
1262
|
{
|
|
1064
|
-
|
|
1065
|
-
|
|
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
|
+
}
|
|
1066
1269
|
}
|
|
1067
1270
|
|
|
1068
|
-
/* After a write of n cells of `data` to the mask of a CAStack: a true
|
|
1069
|
-
that went into a stand-in goes on to its parent's mask. */
|
|
1070
1271
|
static void
|
|
1071
1272
|
ca_stack_mask_settle_after (CAStack *ca, const void *data, ca_size_t n)
|
|
1072
1273
|
{
|
|
@@ -1078,10 +1279,7 @@ ca_stack_mask_settle_after (CAStack *ca, const void *data, ca_size_t n)
|
|
|
1078
1279
|
static void
|
|
1079
1280
|
ca_stack_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
1080
1281
|
{
|
|
1081
|
-
if ( dir == CA_XFER_PUT )
|
|
1082
|
-
ca_stack_put_t a = { CA_STACK_PUT_INDEX, ap, idx, 0, NULL, NULL, NULL, NULL, data };
|
|
1083
|
-
ca_stack_mask_refuse_first(&a);
|
|
1084
|
-
}
|
|
1282
|
+
if ( dir == CA_XFER_PUT ) ca_stack_mask_adopt_before(ap, data, 1);
|
|
1085
1283
|
ca_stack_func_xfer_index(ap, idx, data, dir);
|
|
1086
1284
|
if ( dir == CA_XFER_PUT ) ca_stack_mask_settle_after((CAStack *) ap, data, 1);
|
|
1087
1285
|
}
|
|
@@ -1091,8 +1289,9 @@ ca_stack_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
|
1091
1289
|
int dir)
|
|
1092
1290
|
{
|
|
1093
1291
|
if ( dir == CA_XFER_PUT ) {
|
|
1094
|
-
|
|
1095
|
-
|
|
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);
|
|
1096
1295
|
}
|
|
1097
1296
|
ca_stack_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
1098
1297
|
if ( dir == CA_XFER_PUT ) ca_stack_mask_settle_after((CAStack *) ap, data, n);
|
|
@@ -1103,8 +1302,10 @@ ca_stack_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
1103
1302
|
ca_size_t *strides, void *data, int dir)
|
|
1104
1303
|
{
|
|
1105
1304
|
if ( dir == CA_XFER_PUT ) {
|
|
1106
|
-
|
|
1107
|
-
|
|
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));
|
|
1108
1309
|
}
|
|
1109
1310
|
ca_stack_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
1110
1311
|
if ( dir == CA_XFER_PUT ) {
|
|
@@ -1117,8 +1318,8 @@ static void
|
|
|
1117
1318
|
ca_stack_put_xfer_all (void *ap, void *data, int dir)
|
|
1118
1319
|
{
|
|
1119
1320
|
if ( dir == CA_XFER_PUT ) {
|
|
1120
|
-
|
|
1121
|
-
|
|
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);
|
|
1122
1323
|
}
|
|
1123
1324
|
ca_stack_func_xfer_all(ap, data, dir);
|
|
1124
1325
|
if ( dir == CA_XFER_PUT ) {
|
|
@@ -1129,23 +1330,17 @@ ca_stack_put_xfer_all (void *ap, void *data, int dir)
|
|
|
1129
1330
|
static void
|
|
1130
1331
|
ca_stack_put_fill_data (void *ap, void *ptr)
|
|
1131
1332
|
{
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
ca_stack_mask_refuse_first(&a);
|
|
1135
|
-
}
|
|
1333
|
+
CA_MULTI_PARENT_VALUE_TRIAL(ap, t, ca_stack_func_fill_data(t, ptr));
|
|
1334
|
+
ca_stack_mask_adopt_before(ap, ptr, 1);
|
|
1136
1335
|
ca_stack_func_fill_data(ap, ptr);
|
|
1137
1336
|
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1138
1337
|
}
|
|
1139
1338
|
|
|
1140
|
-
/* A fill of part of the mask goes cell by cell through xfer_index; run
|
|
1141
|
-
the whole of it against blank masks first, so that a cell refused late
|
|
1142
|
-
does not leave the cells before it written. */
|
|
1143
1339
|
static void
|
|
1144
1340
|
ca_stack_put_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
|
|
1145
1341
|
{
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
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);
|
|
1149
1344
|
ca_fill_addrs_default(ap, n, addrs, ptr);
|
|
1150
1345
|
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1151
1346
|
}
|
|
@@ -1154,9 +1349,9 @@ static void
|
|
|
1154
1349
|
ca_stack_put_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
1155
1350
|
ca_size_t *counts, ca_size_t *steps, void *ptr)
|
|
1156
1351
|
{
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
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);
|
|
1160
1355
|
ca_fill_stride_default(ap, base, ndim, counts, steps, ptr);
|
|
1161
1356
|
ca_stack_mask_settle_after((CAStack *) ap, ptr, 1);
|
|
1162
1357
|
}
|
|
@@ -1216,6 +1411,7 @@ rb_ca_stack_new_with_axis (VALUE parents_ary, int8_t k_axis)
|
|
|
1216
1411
|
VALUE p = rb_ary_entry(parents_ary, i);
|
|
1217
1412
|
rb_check_carray_object(p);
|
|
1218
1413
|
TypedData_Get_Struct(p, CArray, &carray_data_type, parents[i]);
|
|
1414
|
+
ca_multi_parent_check_part(parents[i], "stack");
|
|
1219
1415
|
}
|
|
1220
1416
|
ca = ca_stack_new_with_axis((int32_t) n, parents, k_axis);
|
|
1221
1417
|
obj = ca_wrap_struct(ca);
|
|
@@ -1302,6 +1498,7 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1302
1498
|
VALUE p = rb_ary_entry(list, i);
|
|
1303
1499
|
rb_check_carray_object(p);
|
|
1304
1500
|
TypedData_Get_Struct(p, CArray, &carray_data_type, parents[i]);
|
|
1501
|
+
ca_multi_parent_check_part(parents[i], "stack");
|
|
1305
1502
|
}
|
|
1306
1503
|
ca_stack_setup_with_axis(ca, (int32_t) n, parents, k_axis);
|
|
1307
1504
|
rb_ivar_set(self, id_parents, rb_ary_dup(list)); /* GC anchor */
|
|
@@ -1379,6 +1576,7 @@ rb_ca_stack_k_axis (VALUE self)
|
|
|
1379
1576
|
void
|
|
1380
1577
|
Init_ca_obj_stack (void)
|
|
1381
1578
|
{
|
|
1579
|
+
ca_value_trial_depth_key = rb_ractor_local_storage_value_newkey();
|
|
1382
1580
|
/* CAStack must match the CAMultiParent layout convention so generic code
|
|
1383
1581
|
can fold over parents[] via the CA_FLAG_MULTI_PARENTS path. */
|
|
1384
1582
|
if ( offsetof(CAStack, n_parents) != offsetof(CAMultiParent, n_parents) ||
|
|
@@ -1397,6 +1595,7 @@ Init_ca_obj_stack (void)
|
|
|
1397
1595
|
&castack_data_type,
|
|
1398
1596
|
rb_cCAStackMask,
|
|
1399
1597
|
&castack_mask_data_type, &ca_stack_func, sizeof(ca_stack_func));
|
|
1598
|
+
ca_register_cell_moving_view(CA_OBJ_STACK);
|
|
1400
1599
|
rb_define_const(rb_cObject, "CA_OBJ_STACK", INT2NUM(CA_OBJ_STACK));
|
|
1401
1600
|
|
|
1402
1601
|
id_parents = rb_intern("parents");
|