carray 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +104 -81
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_obj_window.c
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
#include "carray.h"
|
|
31
31
|
#include "ca_composite_dispatch.h"
|
|
32
32
|
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE, used by rb_ca_window */
|
|
33
|
+
#include "carray_internal.h" /* ca_axis_view_attach_owned */
|
|
33
34
|
|
|
34
35
|
/* should not be static variable as used by CAIteratorWindow */
|
|
35
36
|
|
|
@@ -82,11 +83,23 @@ ca_window_pool_init (void *ap, int8_t ndim)
|
|
|
82
83
|
ca->dim = ca->count; /* alias; ca_window_setup re-sets */
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/* A window over an object array keeps its fill value, a VALUE, in a
|
|
87
|
+
buffer of its own, so it marks it; ca_mark covers only ca->ptr. */
|
|
88
|
+
void
|
|
89
|
+
ca_window_mark (void *ap)
|
|
90
|
+
{
|
|
91
|
+
CAWindow *ca = (CAWindow *) ap;
|
|
92
|
+
ca_mark(ca);
|
|
93
|
+
if ( ca->fill != NULL && ca_is_object_type(ca) ) {
|
|
94
|
+
rb_gc_mark(*(VALUE *) ca->fill);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
85
98
|
const rb_data_type_t cawindow_data_type = {
|
|
86
99
|
.parent = &caview_data_type,
|
|
87
100
|
.wrap_struct_name = "CAWindow",
|
|
88
101
|
.function = {
|
|
89
|
-
.dmark =
|
|
102
|
+
.dmark = ca_window_mark,
|
|
90
103
|
.dfree = ca_free,
|
|
91
104
|
.dsize = ca_window_dsize,
|
|
92
105
|
.dcompact = NULL
|
|
@@ -255,10 +268,19 @@ ca_window_compose_fold (void *win_ap,
|
|
|
255
268
|
for the window-over-parent mapping (ca_window_compose_fold) and composes
|
|
256
269
|
f through it (ca_stride_compose_through). Declines (returns 0) when the
|
|
257
270
|
window is not interior-only, making the window the fold boundary. */
|
|
271
|
+
static void ca_window_mask_current (CAWindow *ca);
|
|
272
|
+
static int ca_window_mask_reads_standin (CAWindow *ca);
|
|
273
|
+
|
|
258
274
|
static int
|
|
259
275
|
ca_window_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
260
276
|
{
|
|
261
277
|
CAWindow *w = (CAWindow *) ap;
|
|
278
|
+
ca_window_mask_current(w);
|
|
279
|
+
/* A write folded through to a stand-in would bypass the settle in this
|
|
280
|
+
window's write slots. */
|
|
281
|
+
if ( ca_window_mask_reads_standin(w) ) {
|
|
282
|
+
return 0;
|
|
283
|
+
}
|
|
262
284
|
ca_size_t synth_strides[CA_RANK_MAX];
|
|
263
285
|
ca_size_t synth_base;
|
|
264
286
|
ca_size_t *synth_dim;
|
|
@@ -314,7 +336,9 @@ static void
|
|
|
314
336
|
ca_window_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
315
337
|
ca_size_t *strides, void *data, int dir)
|
|
316
338
|
{
|
|
339
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
317
340
|
CAWindow *w = (CAWindow *) ap;
|
|
341
|
+
ca_window_mask_current(w);
|
|
318
342
|
CArray *parent = w->parent;
|
|
319
343
|
int8_t ndim = w->ndim;
|
|
320
344
|
int8_t inner = ndim - 1;
|
|
@@ -355,6 +379,7 @@ ca_window_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
355
379
|
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
356
380
|
for (k = 0; k < ndim; k++) base += starts[k] * wnative[k];
|
|
357
381
|
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
382
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
358
383
|
while (1) {
|
|
359
384
|
ca_size_t woff = base, widx[CA_RANK_MAX];
|
|
360
385
|
for (k = 0; k < ndim; k++) woff += idx[k] * strides[k];
|
|
@@ -658,7 +683,6 @@ ca_window_setup (CAWindow *ca, CArray *parent,
|
|
|
658
683
|
ca_size_t *dim;
|
|
659
684
|
ca_size_t bytes, elements;
|
|
660
685
|
int i;
|
|
661
|
-
int any_mask;
|
|
662
686
|
|
|
663
687
|
data_type = parent->data_type;
|
|
664
688
|
ndim = parent->ndim;
|
|
@@ -667,11 +691,38 @@ ca_window_setup (CAWindow *ca, CArray *parent,
|
|
|
667
691
|
|
|
668
692
|
elements = 1;
|
|
669
693
|
for (i=0; i<ndim; i++) {
|
|
670
|
-
if ( count[i]
|
|
694
|
+
if ( count[i] < 0 ) { /* zero is an empty window */
|
|
671
695
|
rb_raise(rb_eIndexError,
|
|
672
|
-
"invalid size for %i-th dimension (negative
|
|
696
|
+
"invalid size for %i-th dimension (negative)", i);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
elements = ca_shape_elements(ndim, count, bytes);
|
|
700
|
+
|
|
701
|
+
/* Under "ruby" or "strict" an index outside the parent raises. The
|
|
702
|
+
parent's shape is fixed, so a window that reaches outside it would raise
|
|
703
|
+
on every whole read or write, and a write would have changed the cells
|
|
704
|
+
before the one that raised. It is refused here instead. */
|
|
705
|
+
for (i=0; i<ndim; i++) {
|
|
706
|
+
ca_size_t lo, hi, size = dim[i];
|
|
707
|
+
if ( count[i] == 0 ) {
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
lo = start[i];
|
|
711
|
+
hi = start[i] + count[i] - 1;
|
|
712
|
+
if ( bounds[i] == CA_BOUNDS_STRICT ) {
|
|
713
|
+
if ( lo < 0 ) ca_index_out_of_range(lo, size, "index");
|
|
714
|
+
if ( hi >= size ) ca_index_out_of_range(hi, size, "index");
|
|
673
715
|
}
|
|
674
|
-
|
|
716
|
+
else if ( bounds[i] == CA_BOUNDS_RUBY ) {
|
|
717
|
+
if ( lo < -size ) ca_index_out_of_range(lo, size, "index");
|
|
718
|
+
if ( hi >= size ) ca_index_out_of_range(hi, size, "index");
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
723
|
+
run them before it allocates. */
|
|
724
|
+
if ( ca == NULL ) {
|
|
725
|
+
return 0;
|
|
675
726
|
}
|
|
676
727
|
|
|
677
728
|
ca->obj_type = CA_OBJ_WINDOW;
|
|
@@ -687,6 +738,8 @@ ca_window_setup (CAWindow *ca, CArray *parent,
|
|
|
687
738
|
ca->parent = parent;
|
|
688
739
|
ca->attach = 0;
|
|
689
740
|
ca->nosync = 0;
|
|
741
|
+
ca->mask_standin = NULL;
|
|
742
|
+
ca->mask_owner = NULL;
|
|
690
743
|
/* Pool path: bounds/start/count/size0/embed_* are already wired into
|
|
691
744
|
ca->_pool by ca_window_pool_init. Legacy path: ALLOC_N each. `fill`
|
|
692
745
|
is bytes-sized (not ndim) so it stays on its own ALLOC_N in both
|
|
@@ -727,27 +780,36 @@ ca_window_setup (CAWindow *ca, CArray *parent,
|
|
|
727
780
|
}
|
|
728
781
|
}
|
|
729
782
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
783
|
+
return 0;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/* A window with an axis of MASK bounds has a mask of its own. Making it
|
|
787
|
+
asks the parent for its mask, which can raise (a CAObject answers in
|
|
788
|
+
Ruby), so the constructor makes it after the setup under
|
|
789
|
+
ca_fill_or_free; see ca_view_inherit_mask. */
|
|
790
|
+
VALUE
|
|
791
|
+
ca_window_create_bounds_mask (VALUE view)
|
|
792
|
+
{
|
|
793
|
+
CAWindow *ca = (CAWindow *) view;
|
|
794
|
+
int8_t i;
|
|
795
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
733
796
|
if ( ca->bounds[i] == CA_BOUNDS_MASK ) {
|
|
734
|
-
|
|
797
|
+
ca_create_mask((CArray *) ca);
|
|
735
798
|
break;
|
|
736
799
|
}
|
|
737
800
|
}
|
|
738
|
-
|
|
739
|
-
ca_create_mask(ca);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
return 0;
|
|
801
|
+
return Qnil;
|
|
743
802
|
}
|
|
744
803
|
|
|
745
804
|
CAWindow *
|
|
746
805
|
ca_window_new (CArray *parent,
|
|
747
806
|
ca_size_t *start, ca_size_t *count, uint8_t *bounds, char *fill)
|
|
748
807
|
{
|
|
749
|
-
CAWindow *ca
|
|
808
|
+
CAWindow *ca;
|
|
809
|
+
ca_window_setup(NULL, parent, start, count, bounds, fill);
|
|
810
|
+
ca = (CAWindow *) ca_array_alloc(CA_OBJ_WINDOW, parent->ndim);
|
|
750
811
|
ca_window_setup(ca, parent, start, count, bounds, fill);
|
|
812
|
+
ca_fill_or_free((CArray *) ca, ca_window_create_bounds_mask, (VALUE) ca);
|
|
751
813
|
return ca;
|
|
752
814
|
}
|
|
753
815
|
|
|
@@ -757,6 +819,7 @@ free_ca_window (void *ap)
|
|
|
757
819
|
CAWindow *ca = (CAWindow *) ap;
|
|
758
820
|
if ( ca != NULL ) {
|
|
759
821
|
ca_free(ca->mask);
|
|
822
|
+
ca_free(ca->mask_standin);
|
|
760
823
|
xfree(ca->fill); /* always separate (bytes-sized) */
|
|
761
824
|
if ( ca->_pool ) {
|
|
762
825
|
/* bounds/start/count/size0/embed_* all live in ca->_pool. */
|
|
@@ -796,7 +859,39 @@ static void *
|
|
|
796
859
|
ca_window_func_clone (void *ap)
|
|
797
860
|
{
|
|
798
861
|
CAWindow *ca = (CAWindow *) ap;
|
|
799
|
-
|
|
862
|
+
CAWindow *cp = ca_window_new(ca->parent, ca->start, ca->count, ca->bounds,
|
|
863
|
+
ca->fill);
|
|
864
|
+
cp->mask_owner = ca->mask_owner;
|
|
865
|
+
return cp;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* A mask window over its owner's stand-in (ca_mask_standin_current): what
|
|
869
|
+
it reads from now on. */
|
|
870
|
+
static void
|
|
871
|
+
ca_window_mask_current (CAWindow *ca)
|
|
872
|
+
{
|
|
873
|
+
CAWindow *o = (CAWindow *) ca->mask_owner;
|
|
874
|
+
if ( o != NULL ) {
|
|
875
|
+
ca->parent = ca_mask_standin_current((CArray *) ca, ca->parent, o->parent,
|
|
876
|
+
o->mask_standin);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
static int
|
|
881
|
+
ca_window_mask_reads_standin (CAWindow *ca)
|
|
882
|
+
{
|
|
883
|
+
CAWindow *o = (CAWindow *) ca->mask_owner;
|
|
884
|
+
return o != NULL && o->mask_standin != NULL && ca->parent == o->mask_standin;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/* After a write that may have put a true into the stand-in: it goes on to
|
|
888
|
+
the parent's mask. */
|
|
889
|
+
static void
|
|
890
|
+
ca_window_mask_settle (CAWindow *ca)
|
|
891
|
+
{
|
|
892
|
+
if ( ca_window_mask_reads_standin(ca) ) {
|
|
893
|
+
ca_mask_standin_settle(((CAWindow *) ca->mask_owner)->parent, ca->parent);
|
|
894
|
+
}
|
|
800
895
|
}
|
|
801
896
|
|
|
802
897
|
/* Per-cell access. GET and PUT share the bound-normalised index walk; an OOB
|
|
@@ -806,6 +901,7 @@ static void
|
|
|
806
901
|
ca_window_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
807
902
|
{
|
|
808
903
|
CAWindow *ca = (CAWindow *) ap;
|
|
904
|
+
ca_window_mask_current(ca);
|
|
809
905
|
ca_size_t *start = ca->start;
|
|
810
906
|
ca_size_t *size0 = ca->size0;
|
|
811
907
|
ca_size_t idx0[CA_RANK_MAX];
|
|
@@ -834,6 +930,7 @@ ca_window_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
834
930
|
void *data, int dir)
|
|
835
931
|
{
|
|
836
932
|
CAWindow *ca = (CAWindow *) ap;
|
|
933
|
+
ca_window_mask_current(ca);
|
|
837
934
|
ca_size_t *start = ca->start;
|
|
838
935
|
ca_size_t *size0 = ca->size0;
|
|
839
936
|
char *d = (char *) data;
|
|
@@ -952,13 +1049,53 @@ ca_window_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
952
1049
|
ALLOCV_END(h1);
|
|
953
1050
|
}
|
|
954
1051
|
|
|
1052
|
+
/* Whether this window over a parent with no memory to lend owns its buffer
|
|
1053
|
+
rather than attaching the parent. Only FILL / MASK bounds qualify: their
|
|
1054
|
+
xfer_stride hands the parent one region per row, where the other bounds
|
|
1055
|
+
go cell by cell -- for a Ruby-backed parent, a call per cell, which costs
|
|
1056
|
+
more than producing the parent once. Both inputs are fixed for the
|
|
1057
|
+
life of the view, so attach, sync and detach take the same branch. */
|
|
1058
|
+
static int
|
|
1059
|
+
ca_window_owns_buffer (CAWindow *ca)
|
|
1060
|
+
{
|
|
1061
|
+
int8_t k;
|
|
1062
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
1063
|
+
if ( ca->bounds[k] != CA_BOUNDS_FILL && ca->bounds[k] != CA_BOUNDS_MASK ) {
|
|
1064
|
+
return 0;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return ca_parent_lends_no_memory(ca->parent);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
/* The parent's storage the alias path points into: inner axes full and
|
|
1071
|
+
interior, so the window is one contiguous run of the attached parent. */
|
|
1072
|
+
static char *
|
|
1073
|
+
ca_window_alias_ptr (CAWindow *ca)
|
|
1074
|
+
{
|
|
1075
|
+
ca_size_t parent_row_stride = ca->bytes;
|
|
1076
|
+
int8_t k;
|
|
1077
|
+
for (k = ca->ndim - 1; k >= 1; k--) parent_row_stride *= ca->parent->dim[k];
|
|
1078
|
+
return ca->parent->ptr + ca->start[0] * parent_row_stride;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/* Agrees with attach on the alias path: sync has nothing to write back
|
|
1082
|
+
and detach frees nothing there, so a buffer of our own would take the
|
|
1083
|
+
writes and be dropped. */
|
|
955
1084
|
static void
|
|
956
1085
|
ca_window_func_allocate (void *ap)
|
|
957
1086
|
{
|
|
958
1087
|
CAWindow *ca = (CAWindow *) ap;
|
|
1088
|
+
ca_window_mask_current(ca);
|
|
1089
|
+
if ( ca_window_owns_buffer(ca) ) {
|
|
1090
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
959
1093
|
ca_attach(ca->parent);
|
|
960
|
-
|
|
961
|
-
|
|
1094
|
+
if ( ca->embed_alias_eligible ) {
|
|
1095
|
+
ca->ptr = ca_window_alias_ptr(ca);
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
962
1099
|
}
|
|
963
1100
|
|
|
964
1101
|
/* The engine paths below emit a per-axis descriptor (ca_window_describe_axes)
|
|
@@ -973,6 +1110,11 @@ static void
|
|
|
973
1110
|
ca_window_func_attach (void *ap)
|
|
974
1111
|
{
|
|
975
1112
|
CAWindow *ca = (CAWindow *) ap;
|
|
1113
|
+
ca_window_mask_current(ca);
|
|
1114
|
+
if ( ca_window_owns_buffer(ca) ) {
|
|
1115
|
+
ca_axis_view_attach_owned(ca);
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
976
1118
|
ca_attach(ca->parent);
|
|
977
1119
|
if ( ca->embed_alias_eligible ) {
|
|
978
1120
|
/* Alias path: inner axes full + interior, so the embedded region is a
|
|
@@ -981,14 +1123,10 @@ ca_window_func_attach (void *ap)
|
|
|
981
1123
|
CAREFUL: sync and detach must agree with this — sync has nothing to
|
|
982
1124
|
scatter back (the writes already landed in the parent) and detach must
|
|
983
1125
|
not xfree a pointer it does not own. */
|
|
984
|
-
|
|
985
|
-
int8_t k;
|
|
986
|
-
for (k = ca->ndim - 1; k >= 1; k--) parent_row_stride *= ca->parent->dim[k];
|
|
987
|
-
ca->ptr = ca->parent->ptr + ca->start[0] * parent_row_stride;
|
|
1126
|
+
ca->ptr = ca_window_alias_ptr(ca);
|
|
988
1127
|
} else if ( ca->embed_eligible ) {
|
|
989
1128
|
/* Embed path: allocate, then 1 fill + 1 strided memcpy. */
|
|
990
|
-
|
|
991
|
-
ca->ptr = xmalloc(out_len > 0 ? out_len : 1);
|
|
1129
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
992
1130
|
ca_window_attach_embed(ca, ca->ptr);
|
|
993
1131
|
} else {
|
|
994
1132
|
/* Fallback: PERIODIC / REFLECT / NEAREST / RUBY / STRICT go through
|
|
@@ -1005,6 +1143,10 @@ static void
|
|
|
1005
1143
|
ca_window_func_sync (void *ap)
|
|
1006
1144
|
{
|
|
1007
1145
|
CAWindow *ca = (CAWindow *) ap;
|
|
1146
|
+
if ( ca_window_owns_buffer(ca) ) {
|
|
1147
|
+
ca_axis_view_sync_owned(ca);
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1008
1150
|
if ( ca->embed_alias_eligible ) {
|
|
1009
1151
|
/* Alias path: ca->ptr aliases the parent, so the writes already landed
|
|
1010
1152
|
in parent storage. Nothing to scatter back. */
|
|
@@ -1019,12 +1161,18 @@ ca_window_func_sync (void *ap)
|
|
|
1019
1161
|
ca->elements, ca->ptr);
|
|
1020
1162
|
}
|
|
1021
1163
|
ca_sync(ca->parent);
|
|
1164
|
+
ca_window_mask_settle(ca);
|
|
1022
1165
|
}
|
|
1023
1166
|
|
|
1024
1167
|
static void
|
|
1025
1168
|
ca_window_func_detach (void *ap)
|
|
1026
1169
|
{
|
|
1027
1170
|
CAWindow *ca = (CAWindow *) ap;
|
|
1171
|
+
if ( ca_window_owns_buffer(ca) ) {
|
|
1172
|
+
xfree(ca->ptr);
|
|
1173
|
+
ca->ptr = NULL;
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1028
1176
|
/* Alias path: ca->ptr aliases parent storage; it is not ours to xfree. */
|
|
1029
1177
|
if ( ! ca->embed_alias_eligible ) {
|
|
1030
1178
|
xfree(ca->ptr);
|
|
@@ -1078,6 +1226,7 @@ static void
|
|
|
1078
1226
|
ca_window_func_xfer_all (void *ap, void *data, int dir)
|
|
1079
1227
|
{
|
|
1080
1228
|
CAWindow *ca = (CAWindow *) ap;
|
|
1229
|
+
ca_window_mask_current(ca);
|
|
1081
1230
|
if ( ca->parent->ptr ) {
|
|
1082
1231
|
ca_window_func_run_fast_path(ca, (char *) data, dir);
|
|
1083
1232
|
return;
|
|
@@ -1117,9 +1266,25 @@ ca_window_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1117
1266
|
}
|
|
1118
1267
|
}
|
|
1119
1268
|
|
|
1120
|
-
/*
|
|
1121
|
-
|
|
1122
|
-
|
|
1269
|
+
/* A parent with no memory to lend is asked for the cells of the window
|
|
1270
|
+
only, through xfer_stride over the whole view, when the bounds let that
|
|
1271
|
+
go row by row (see ca_window_owns_buffer). */
|
|
1272
|
+
if ( ca_window_owns_buffer(ca) ) {
|
|
1273
|
+
ca_size_t starts[CA_RANK_MAX], strides[CA_RANK_MAX], s;
|
|
1274
|
+
int8_t k;
|
|
1275
|
+
s = ca->bytes;
|
|
1276
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) {
|
|
1277
|
+
starts[k] = 0;
|
|
1278
|
+
strides[k] = s;
|
|
1279
|
+
s *= ca->dim[k];
|
|
1280
|
+
}
|
|
1281
|
+
ca_window_func_xfer_stride(ca, starts, ca->dim, strides, data, dir);
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
/* Any other cold parent: materialise it into a scratch buffer via
|
|
1286
|
+
ca_xfer_all, then run the normal fast path with the scratch standing in
|
|
1287
|
+
for parent->ptr. */
|
|
1123
1288
|
{
|
|
1124
1289
|
volatile VALUE holder;
|
|
1125
1290
|
CArray *parent = ca->parent;
|
|
@@ -1137,12 +1302,14 @@ ca_window_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1137
1302
|
|
|
1138
1303
|
ca_window_func_run_fast_path(ca, (char *) data, dir);
|
|
1139
1304
|
|
|
1305
|
+
/* Put parent->ptr back before the PUT: the PUT can raise (a lazy
|
|
1306
|
+
backing's sync failing), and the scratch is gone once this
|
|
1307
|
+
frame is. */
|
|
1308
|
+
parent->ptr = parent_ptr_saved;
|
|
1140
1309
|
if ( dir == CA_XFER_PUT ) {
|
|
1141
1310
|
/* Push back scratch (modified by scatter) to parent. */
|
|
1142
1311
|
ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
|
|
1143
1312
|
}
|
|
1144
|
-
|
|
1145
|
-
parent->ptr = parent_ptr_saved;
|
|
1146
1313
|
ALLOCV_END(holder);
|
|
1147
1314
|
}
|
|
1148
1315
|
}
|
|
@@ -1161,6 +1328,7 @@ static void
|
|
|
1161
1328
|
ca_window_func_fill_data (void *ap, void *ptr)
|
|
1162
1329
|
{
|
|
1163
1330
|
CAWindow *ca = (CAWindow *) ap;
|
|
1331
|
+
ca_window_mask_current(ca);
|
|
1164
1332
|
|
|
1165
1333
|
/* embed_eligible (= no PERIODIC/REFLECT) covers both interior-only
|
|
1166
1334
|
windows (embed_covers_all == 1) and OOB-bearing ones such as a CAShift
|
|
@@ -1238,22 +1406,32 @@ ca_window_func_fill_data (void *ap, void *ptr)
|
|
|
1238
1406
|
ca_attach(ca->parent);
|
|
1239
1407
|
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1240
1408
|
ca->elements, ptr);
|
|
1241
|
-
|
|
1242
|
-
ca_detach(ca->parent);
|
|
1409
|
+
ca_sync_detach(ca->parent);
|
|
1243
1410
|
}
|
|
1244
1411
|
|
|
1245
1412
|
static void
|
|
1246
1413
|
ca_window_func_create_mask (void *ap)
|
|
1247
1414
|
{
|
|
1248
1415
|
CAWindow *ca = (CAWindow *) ap;
|
|
1416
|
+
CArray *pmask;
|
|
1249
1417
|
boolean8_t fill;
|
|
1250
1418
|
uint8_t mbounds[CA_RANK_MAX];
|
|
1251
1419
|
int8_t i;
|
|
1252
1420
|
int any_mask;
|
|
1253
1421
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1422
|
+
/* The mask lies over the parent's mask, or, while the parent has none,
|
|
1423
|
+
over an all-false stand-in this window holds: masking the
|
|
1424
|
+
out-of-bounds cells gives the parent no mask
|
|
1425
|
+
(ca_mask_standin_new). */
|
|
1426
|
+
if ( ca_has_mask(ca->parent) ) {
|
|
1256
1427
|
ca_create_mask(ca->parent);
|
|
1428
|
+
pmask = ca->parent->mask;
|
|
1429
|
+
}
|
|
1430
|
+
else {
|
|
1431
|
+
if ( ca->mask_standin == NULL ) {
|
|
1432
|
+
ca->mask_standin = ca_mask_standin_new(ca->parent);
|
|
1433
|
+
}
|
|
1434
|
+
pmask = ca->mask_standin;
|
|
1257
1435
|
}
|
|
1258
1436
|
|
|
1259
1437
|
/* Any MASK axis of the view becomes FILL in the mask sub-view, with the
|
|
@@ -1270,8 +1448,77 @@ ca_window_func_create_mask (void *ap)
|
|
|
1270
1448
|
}
|
|
1271
1449
|
fill = any_mask ? 1 : 0;
|
|
1272
1450
|
|
|
1273
|
-
|
|
1274
|
-
|
|
1451
|
+
/* The mask has the view's own type, so CAShift (which shares this table)
|
|
1452
|
+
gets a CAShiftMask. */
|
|
1453
|
+
{
|
|
1454
|
+
/* check: the mask window copies its own window's checked ranges */
|
|
1455
|
+
CAWindow *m = (CAWindow *) ca_array_alloc(ca->obj_type, ca->ndim);
|
|
1456
|
+
ca_window_setup(m, pmask, ca->start, ca->count, mbounds, (char*)&fill);
|
|
1457
|
+
m->obj_type = ca->obj_type;
|
|
1458
|
+
m->mask_owner = (CArray *) ca;
|
|
1459
|
+
if ( pmask == ca->mask_standin ) {
|
|
1460
|
+
/* writes inside an attach window reach the stand-in through the
|
|
1461
|
+
sync, where they can give way to the parent's mask */
|
|
1462
|
+
m->embed_alias_eligible = 0;
|
|
1463
|
+
}
|
|
1464
|
+
ca->mask = (CArray *) m;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
/* The table's write slots: on the mask of a window still reading a
|
|
1469
|
+
stand-in, a write that may have put a true into it ends with the settle
|
|
1470
|
+
(ca_mask_standin_settle). */
|
|
1471
|
+
static void
|
|
1472
|
+
ca_window_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
1473
|
+
{
|
|
1474
|
+
ca_window_func_xfer_index(ap, idx, data, dir);
|
|
1475
|
+
if ( dir == CA_XFER_PUT && ca_window_mask_reads_standin((CAWindow *) ap)
|
|
1476
|
+
&& ca_mask_any_true(data, 1) ) {
|
|
1477
|
+
ca_window_mask_settle((CAWindow *) ap);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
static void
|
|
1482
|
+
ca_window_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
1483
|
+
int dir)
|
|
1484
|
+
{
|
|
1485
|
+
ca_window_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
1486
|
+
if ( dir == CA_XFER_PUT && ca_window_mask_reads_standin((CAWindow *) ap)
|
|
1487
|
+
&& ca_mask_any_true(data, n) ) {
|
|
1488
|
+
ca_window_mask_settle((CAWindow *) ap);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
static void
|
|
1493
|
+
ca_window_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
1494
|
+
ca_size_t *strides, void *data, int dir)
|
|
1495
|
+
{
|
|
1496
|
+
ca_window_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
1497
|
+
if ( dir == CA_XFER_PUT && ca_window_mask_reads_standin((CAWindow *) ap)
|
|
1498
|
+
&& ca_mask_any_true(data,
|
|
1499
|
+
ca_shape_elements(((CArray *) ap)->ndim, counts, 1)) ) {
|
|
1500
|
+
ca_window_mask_settle((CAWindow *) ap);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
static void
|
|
1505
|
+
ca_window_put_xfer_all (void *ap, void *data, int dir)
|
|
1506
|
+
{
|
|
1507
|
+
ca_window_func_xfer_all(ap, data, dir);
|
|
1508
|
+
if ( dir == CA_XFER_PUT && ca_window_mask_reads_standin((CAWindow *) ap)
|
|
1509
|
+
&& ca_mask_any_true(data, ((CArray *) ap)->elements) ) {
|
|
1510
|
+
ca_window_mask_settle((CAWindow *) ap);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
static void
|
|
1515
|
+
ca_window_put_fill_data (void *ap, void *ptr)
|
|
1516
|
+
{
|
|
1517
|
+
ca_window_func_fill_data(ap, ptr);
|
|
1518
|
+
if ( ca_window_mask_reads_standin((CAWindow *) ap)
|
|
1519
|
+
&& ca_mask_any_true(ptr, 1) ) {
|
|
1520
|
+
ca_window_mask_settle((CAWindow *) ap);
|
|
1521
|
+
}
|
|
1275
1522
|
}
|
|
1276
1523
|
|
|
1277
1524
|
ca_operation_function_t ca_window_func = {
|
|
@@ -1283,13 +1530,13 @@ ca_operation_function_t ca_window_func = {
|
|
|
1283
1530
|
ca_window_func_attach,
|
|
1284
1531
|
ca_window_func_sync,
|
|
1285
1532
|
ca_window_func_detach,
|
|
1286
|
-
|
|
1533
|
+
ca_window_put_fill_data,
|
|
1287
1534
|
ca_window_func_create_mask,
|
|
1288
|
-
|
|
1289
|
-
|
|
1535
|
+
ca_window_put_xfer_index,
|
|
1536
|
+
ca_window_put_xfer_addrs,
|
|
1290
1537
|
ca_window_func_fold_stride,
|
|
1291
|
-
|
|
1292
|
-
|
|
1538
|
+
ca_window_put_xfer_stride,
|
|
1539
|
+
ca_window_put_xfer_all,
|
|
1293
1540
|
};
|
|
1294
1541
|
|
|
1295
1542
|
/* ------------------------------------------------------------------- */
|
|
@@ -1309,6 +1556,7 @@ ca_window_describe_axes (void *ap, ca_axis_desc_t *out,
|
|
|
1309
1556
|
ca_size_t *out_parent_dims)
|
|
1310
1557
|
{
|
|
1311
1558
|
CAWindow *ca = (CAWindow *) ap;
|
|
1559
|
+
ca_window_mask_current(ca);
|
|
1312
1560
|
int8_t k;
|
|
1313
1561
|
for ( k = 0; k < ca->ndim; k++ ) {
|
|
1314
1562
|
out_parent_dims[k] = ca->parent->dim[k];
|
|
@@ -1410,9 +1658,13 @@ rb_ca_window (int argc, VALUE *argv, VALUE self)
|
|
|
1410
1658
|
bounds = CA_BOUNDS_MASK;
|
|
1411
1659
|
}
|
|
1412
1660
|
else {
|
|
1413
|
-
|
|
1661
|
+
/* The fill is a value of the array (a String for a CAString, an
|
|
1662
|
+
instant for a time array): rb_ca_obj2ptr writes it as one cell of
|
|
1663
|
+
the storage, through the Face. */
|
|
1664
|
+
rcs = rb_cscalar_new(ca_strip_face(ca)->data_type, ca->bytes, NULL);
|
|
1414
1665
|
TypedData_Get_Struct(rcs, CScalar, &cscalar_data_type, cs);
|
|
1415
1666
|
fill = cs->ptr;
|
|
1667
|
+
rb_ca_obj2ptr(self, rfval, fill);
|
|
1416
1668
|
}
|
|
1417
1669
|
|
|
1418
1670
|
if ( ! NIL_P(rbounds) ) {
|
|
@@ -1427,7 +1679,7 @@ rb_ca_window (int argc, VALUE *argv, VALUE self)
|
|
|
1427
1679
|
cbounds = StringValuePtr(rbounds);
|
|
1428
1680
|
if ( rfval == CA_UNDEF && strncmp(cbounds, "fill", 4)
|
|
1429
1681
|
&& strncmp(cbounds, "mask", 4) ) {
|
|
1430
|
-
rb_raise(
|
|
1682
|
+
rb_raise(rb_eArgError, "conflicted bounds and fill_value");
|
|
1431
1683
|
}
|
|
1432
1684
|
if ( ! strncmp(cbounds, "ruby", 4) ) {
|
|
1433
1685
|
bounds = CA_BOUNDS_RUBY;
|
|
@@ -1458,7 +1710,7 @@ rb_ca_window (int argc, VALUE *argv, VALUE self)
|
|
|
1458
1710
|
bounds = CA_BOUNDS_FILL;
|
|
1459
1711
|
}
|
|
1460
1712
|
else {
|
|
1461
|
-
rb_raise(
|
|
1713
|
+
rb_raise(rb_eArgError,
|
|
1462
1714
|
"unknown option value '%s' for :bounds", cbounds);
|
|
1463
1715
|
}
|
|
1464
1716
|
break;
|
|
@@ -1466,7 +1718,7 @@ rb_ca_window (int argc, VALUE *argv, VALUE self)
|
|
|
1466
1718
|
bounds = NUM2INT(rbounds);
|
|
1467
1719
|
break;
|
|
1468
1720
|
default:
|
|
1469
|
-
rb_raise(
|
|
1721
|
+
rb_raise(rb_eArgError, "invalid option value for :bounds");
|
|
1470
1722
|
}
|
|
1471
1723
|
}
|
|
1472
1724
|
|
|
@@ -1491,6 +1743,7 @@ rb_ca_window_initialize_copy (VALUE self, VALUE other)
|
|
|
1491
1743
|
CAWindow *ca, *cs;
|
|
1492
1744
|
|
|
1493
1745
|
TypedData_Get_Struct(self, CAWindow, &cawindow_data_type, ca);
|
|
1746
|
+
ca_check_uninitialized(ca);
|
|
1494
1747
|
TypedData_Get_Struct(other, CAWindow, &cawindow_data_type, cs);
|
|
1495
1748
|
|
|
1496
1749
|
/* `self` came from rb_ca_window_s_allocate (TypedData_Make_Struct,
|
|
@@ -1500,6 +1753,10 @@ rb_ca_window_initialize_copy (VALUE self, VALUE other)
|
|
|
1500
1753
|
ca_array_pool_alloc(ca, CA_OBJ_WINDOW, cs->ndim);
|
|
1501
1754
|
}
|
|
1502
1755
|
ca_window_setup(ca, cs->parent, cs->start, cs->count, cs->bounds, cs->fill);
|
|
1756
|
+
ca_window_create_bounds_mask((VALUE) ca);
|
|
1757
|
+
/* a copy of a mask over a stand-in gives way to the parent's mask as
|
|
1758
|
+
the original does */
|
|
1759
|
+
ca->mask_owner = cs->mask_owner;
|
|
1503
1760
|
|
|
1504
1761
|
return self;
|
|
1505
1762
|
}
|
|
@@ -1588,6 +1845,34 @@ rb_ca_window_get_bounds (VALUE self)
|
|
|
1588
1845
|
return SIZE2NUM(cw->bounds[0]);
|
|
1589
1846
|
}
|
|
1590
1847
|
|
|
1848
|
+
/* The boundary rule on each axis, one Symbol per axis. `bounds` answers
|
|
1849
|
+
for axis 0 only, which is all CArray#window sets; a shift with `roll:`
|
|
1850
|
+
on some axes sets them one by one. */
|
|
1851
|
+
static VALUE
|
|
1852
|
+
rb_ca_window_axis_bounds (VALUE self)
|
|
1853
|
+
{
|
|
1854
|
+
volatile VALUE ary;
|
|
1855
|
+
CAWindow *cw;
|
|
1856
|
+
const char *name;
|
|
1857
|
+
int8_t i;
|
|
1858
|
+
TypedData_Get_Struct(self, CAWindow, &cawindow_data_type, cw);
|
|
1859
|
+
ary = rb_ary_new2(cw->ndim);
|
|
1860
|
+
for (i=0; i<cw->ndim; i++) {
|
|
1861
|
+
switch ( cw->bounds[i] ) {
|
|
1862
|
+
case CA_BOUNDS_RUBY: name = "ruby"; break;
|
|
1863
|
+
case CA_BOUNDS_STRICT: name = "strict"; break;
|
|
1864
|
+
case CA_BOUNDS_NEAREST: name = "nearest"; break;
|
|
1865
|
+
case CA_BOUNDS_PERIODIC: name = "periodic"; break;
|
|
1866
|
+
case CA_BOUNDS_REFLECT: name = "reflect"; break;
|
|
1867
|
+
case CA_BOUNDS_FILL: name = "fill"; break;
|
|
1868
|
+
case CA_BOUNDS_MASK: name = "mask"; break;
|
|
1869
|
+
default: name = "unknown"; break;
|
|
1870
|
+
}
|
|
1871
|
+
rb_ary_store(ary, i, ID2SYM(rb_intern(name)));
|
|
1872
|
+
}
|
|
1873
|
+
return ary;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1591
1876
|
#define rb_cw_get_attr_ary(name) \
|
|
1592
1877
|
rb_cw_## name (VALUE self) \
|
|
1593
1878
|
{ \
|
|
@@ -1688,6 +1973,7 @@ Init_ca_obj_window (void)
|
|
|
1688
1973
|
/* No `count` accessor: the per-axis window widths are what `shape`
|
|
1689
1974
|
already answers, and the name belongs to CArray#count. */
|
|
1690
1975
|
rb_define_method(rb_cCAWindow, "start", rb_cw_start, 0);
|
|
1976
|
+
rb_define_method(rb_cCAWindow, "__boundary_rule_of_each_axis__", rb_ca_window_axis_bounds, 0);
|
|
1691
1977
|
rb_define_method(rb_cCAWindow, "size0", rb_cw_size0, 0);
|
|
1692
1978
|
|
|
1693
1979
|
#ifdef CARRAY_DEV_BUILD
|