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_select_axis.c
CHANGED
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
- single INDIRECT axis (boolean), other axes AP (nil/Integer/Range)
|
|
13
13
|
- parent must be an entity CArray (no CAStride parent)
|
|
14
14
|
- selector copied at construction (fully static, fragility-free)
|
|
15
|
-
-
|
|
15
|
+
- a masked selector cell selects nothing (same rule as CASelect)
|
|
16
16
|
- slab copy uses straightforward nested-loop memcpy (no SIMD fast paths)
|
|
17
17
|
|
|
18
18
|
---------------------------------------------------------------------------- */
|
|
19
19
|
|
|
20
20
|
#include "carray.h"
|
|
21
|
+
#include "carray_internal.h" /* ca_select_snapshot */
|
|
21
22
|
|
|
22
23
|
typedef struct {
|
|
23
24
|
/* CAView prefix (mirrors carray.h ca_virtual layout) */
|
|
@@ -112,9 +113,11 @@ static int8_t CA_OBJ_SELECT_AXIS;
|
|
|
112
113
|
|
|
113
114
|
/* Benchmark-only bypass flag: when non-zero, rb_ca_grid skips the
|
|
114
115
|
CASelectAxis dispatch hook and falls through to the pre-CSA CAGrid path.
|
|
115
|
-
Exposed to Ruby as CArray._csa_bypass
|
|
116
|
+
Exposed to Ruby as CArray._csa_bypass= in development builds.
|
|
117
|
+
Production code never touches it. */
|
|
116
118
|
int ca_csa_dispatch_bypass = 0;
|
|
117
119
|
|
|
120
|
+
#ifdef CARRAY_DEV_BUILD
|
|
118
121
|
static VALUE
|
|
119
122
|
rb_ca_s_csa_bypass_eq (VALUE klass, VALUE val)
|
|
120
123
|
{
|
|
@@ -129,6 +132,7 @@ rb_ca_s_csa_bypass_p (VALUE klass)
|
|
|
129
132
|
(void) klass;
|
|
130
133
|
return ca_csa_dispatch_bypass ? Qtrue : Qfalse;
|
|
131
134
|
}
|
|
135
|
+
#endif
|
|
132
136
|
|
|
133
137
|
static VALUE rb_cCASelectAxis;
|
|
134
138
|
static VALUE rb_cCASelectAxisMask;
|
|
@@ -175,22 +179,18 @@ ca_select_axis_setup (CASelectAxis *ca, CArray *parent, int8_t indirect_axis,
|
|
|
175
179
|
(int) indirect_axis,
|
|
176
180
|
(long long) parent->dim[indirect_axis]);
|
|
177
181
|
}
|
|
178
|
-
if ( ca_has_mask(selector) ) {
|
|
179
|
-
rb_raise(rb_eArgError,
|
|
180
|
-
"CASelectAxis: selector boolean array must not have a mask. "
|
|
181
|
-
"Use `selector.strip_mask(false)` etc. to flatten first.");
|
|
182
|
-
}
|
|
183
|
-
|
|
184
182
|
/* Validate AP axes */
|
|
185
183
|
for ( k = 0; k < ndim; k++ ) {
|
|
186
184
|
if ( k == indirect_axis ) continue;
|
|
187
185
|
if ( ap_step[k] == 0 ) {
|
|
188
186
|
rb_raise(rb_eArgError, "CASelectAxis: ap_step[%d] is 0", (int) k);
|
|
189
187
|
}
|
|
190
|
-
if ( ap_count[k]
|
|
191
|
-
rb_raise(rb_eArgError, "CASelectAxis: ap_count[%d]
|
|
188
|
+
if ( ap_count[k] < 0 ) {
|
|
189
|
+
rb_raise(rb_eArgError, "CASelectAxis: ap_count[%d] is negative", (int) k);
|
|
192
190
|
}
|
|
193
|
-
|
|
191
|
+
/* A zero count (an axis of length zero) selects no cells: the view is
|
|
192
|
+
empty and there is no first or last index to check. */
|
|
193
|
+
if ( ap_count[k] > 0 ) {
|
|
194
194
|
ca_size_t start_v = ap_start[k];
|
|
195
195
|
ca_size_t last_v = ap_start[k] + (ap_count[k] - 1) * ap_step[k];
|
|
196
196
|
if ( start_v < 0 || start_v >= parent->dim[k] ) {
|
|
@@ -222,8 +222,9 @@ ca_select_axis_setup (CASelectAxis *ca, CArray *parent, int8_t indirect_axis,
|
|
|
222
222
|
|
|
223
223
|
/* Copy selector (view owns its own copy; immune to external mutation).
|
|
224
224
|
The selector is small (1 axis length), so the copy cost is acceptable,
|
|
225
|
-
and it avoids the fragility CASelect has from live references.
|
|
226
|
-
|
|
225
|
+
and it avoids the fragility CASelect has from live references. A
|
|
226
|
+
masked selector cell selects nothing, as it does for CASelect. */
|
|
227
|
+
ca->selector = ca_select_snapshot(selector);
|
|
227
228
|
|
|
228
229
|
/* Allocate dim and AP arrays (pool path: already wired by pool_init). */
|
|
229
230
|
if ( ! ca->_pool ) {
|
|
@@ -310,6 +311,7 @@ ca_select_axis_new (CArray *parent, int8_t indirect_axis,
|
|
|
310
311
|
CArray *selector,
|
|
311
312
|
ca_size_t *ap_start, ca_size_t *ap_count, ca_size_t *ap_step)
|
|
312
313
|
{
|
|
314
|
+
/* check: the callers (clone, create_mask) pass an existing view's checked selector */
|
|
313
315
|
CASelectAxis *ca = (CASelectAxis *) ca_array_alloc(CA_OBJ_SELECT_AXIS, parent->ndim);
|
|
314
316
|
ca_select_axis_setup(ca, parent, indirect_axis, selector,
|
|
315
317
|
ap_start, ap_count, ap_step);
|
|
@@ -548,6 +550,7 @@ static void
|
|
|
548
550
|
ca_select_axis_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
549
551
|
ca_size_t *strides, void *data, int dir)
|
|
550
552
|
{
|
|
553
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
551
554
|
CASelectAxis *ca = (CASelectAxis *) ap;
|
|
552
555
|
CArray *parent = ca->parent;
|
|
553
556
|
int8_t ndim = ca->ndim;
|
|
@@ -588,6 +591,7 @@ ca_select_axis_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
588
591
|
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
589
592
|
for (k = 0; k < ndim; k++) base += starts[k] * cnative[k];
|
|
590
593
|
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
594
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
591
595
|
while (1) {
|
|
592
596
|
ca_size_t coff = base, cidx[CA_RANK_MAX];
|
|
593
597
|
for (k = 0; k < ndim; k++) coff += idx[k] * strides[k];
|
|
@@ -671,6 +675,7 @@ ca_select_axis_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
671
675
|
ca_xfer_stride/ca_xfer_addrs. */
|
|
672
676
|
for (k = 0; k < ndim; k++) o[k] = 0;
|
|
673
677
|
|
|
678
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
674
679
|
while (1) {
|
|
675
680
|
ca_size_t pbase = 0, doff = 0;
|
|
676
681
|
for (k = 0; k < inner; k++) {
|
|
@@ -710,25 +715,34 @@ ca_select_axis_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
710
715
|
}
|
|
711
716
|
}
|
|
712
717
|
|
|
718
|
+
/* A parent with no memory to lend (ca_parent_lends_no_memory) is never
|
|
719
|
+
attached: the view owns its buffer, filled and drained through xfer_all,
|
|
720
|
+
which asks the parent for the selected cells only. The predicate asks
|
|
721
|
+
what the parent is, not whether it is attached now, so attach, sync and
|
|
722
|
+
detach all take the same branch. */
|
|
723
|
+
|
|
713
724
|
static void
|
|
714
725
|
ca_select_axis_func_allocate (void *ap)
|
|
715
726
|
{
|
|
716
727
|
CASelectAxis *ca = (CASelectAxis *) ap;
|
|
717
|
-
|
|
718
|
-
|
|
728
|
+
if ( ! ca_parent_lends_no_memory(ca->parent) ) {
|
|
729
|
+
ca_attach(ca->parent);
|
|
730
|
+
}
|
|
731
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
719
732
|
}
|
|
720
733
|
|
|
721
|
-
/* attach / sync / copy_data / sync_data / fill_data all go through the
|
|
722
|
-
common descriptor engine. This file holds only describe_axes for
|
|
723
|
-
translating CSA state into the shared descriptor; the engine in
|
|
724
|
-
ext/ca_axis_dispatch.c does the rest. */
|
|
725
|
-
|
|
726
734
|
static void
|
|
727
735
|
ca_select_axis_func_attach (void *ap)
|
|
728
736
|
{
|
|
729
737
|
CASelectAxis *ca = (CASelectAxis *) ap;
|
|
730
738
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
731
739
|
ca_size_t pdims[CA_RANK_MAX];
|
|
740
|
+
|
|
741
|
+
if ( ca_parent_lends_no_memory(ca->parent) ) {
|
|
742
|
+
ca_axis_view_attach_owned(ca);
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
|
|
732
746
|
ca_attach(ca->parent);
|
|
733
747
|
ca_select_axis_describe_axes(ca, desc, pdims);
|
|
734
748
|
ca->ptr = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim,
|
|
@@ -741,6 +755,12 @@ ca_select_axis_func_sync (void *ap)
|
|
|
741
755
|
CASelectAxis *ca = (CASelectAxis *) ap;
|
|
742
756
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
743
757
|
ca_size_t pdims[CA_RANK_MAX];
|
|
758
|
+
|
|
759
|
+
if ( ca_parent_lends_no_memory(ca->parent) ) {
|
|
760
|
+
ca_axis_view_sync_owned(ca);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
|
|
744
764
|
ca_select_axis_describe_axes(ca, desc, pdims);
|
|
745
765
|
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
746
766
|
ca->elements, ca->ptr);
|
|
@@ -756,16 +776,16 @@ ca_select_axis_func_detach (void *ap)
|
|
|
756
776
|
ca->ptr = NULL;
|
|
757
777
|
}
|
|
758
778
|
/* indices[] lives for the view's lifetime; freed in free_ca_select_axis. */
|
|
759
|
-
|
|
779
|
+
if ( ! ca_parent_lends_no_memory(ca->parent) ) {
|
|
780
|
+
ca_detach(ca->parent);
|
|
781
|
+
}
|
|
760
782
|
}
|
|
761
783
|
|
|
762
|
-
/*
|
|
763
|
-
of the parent. A cold parent uses a proper 2-pass (materialise the
|
|
764
|
-
parent into scratch, expose it as parent->ptr, run the fast path, then
|
|
765
|
-
write scratch back for PUT). */
|
|
784
|
+
/* The transfer against parent->ptr, for ca_axis_view_xfer_all. */
|
|
766
785
|
static void
|
|
767
|
-
ca_select_axis_func_run_fast_path (
|
|
786
|
+
ca_select_axis_func_run_fast_path (void *ap, char *data, int dir)
|
|
768
787
|
{
|
|
788
|
+
CASelectAxis *ca = (CASelectAxis *) ap;
|
|
769
789
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
770
790
|
ca_size_t pdims[CA_RANK_MAX];
|
|
771
791
|
ca_select_axis_describe_axes(ca, desc, pdims);
|
|
@@ -781,27 +801,7 @@ ca_select_axis_func_run_fast_path (CASelectAxis *ca, char *data, int dir)
|
|
|
781
801
|
static void
|
|
782
802
|
ca_select_axis_func_xfer_all (void *ap, void *data, int dir)
|
|
783
803
|
{
|
|
784
|
-
|
|
785
|
-
if ( ca->parent->ptr ) {
|
|
786
|
-
ca_select_axis_func_run_fast_path(ca, (char *) data, dir);
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
/* Proper 2-pass cold fallback. */
|
|
790
|
-
{
|
|
791
|
-
volatile VALUE holder;
|
|
792
|
-
CArray *parent = ca->parent;
|
|
793
|
-
ca_size_t plen = parent->elements * parent->bytes;
|
|
794
|
-
char *parent_scratch = ALLOCV_N(char, holder, plen);
|
|
795
|
-
char *parent_ptr_saved = parent->ptr;
|
|
796
|
-
ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
|
|
797
|
-
parent->ptr = parent_scratch;
|
|
798
|
-
ca_select_axis_func_run_fast_path(ca, (char *) data, dir);
|
|
799
|
-
if ( dir == CA_XFER_PUT ) {
|
|
800
|
-
ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
|
|
801
|
-
}
|
|
802
|
-
parent->ptr = parent_ptr_saved;
|
|
803
|
-
ALLOCV_END(holder);
|
|
804
|
-
}
|
|
804
|
+
ca_axis_view_xfer_all(ap, ca_select_axis_func_run_fast_path, 1, data, dir);
|
|
805
805
|
}
|
|
806
806
|
|
|
807
807
|
static void
|
|
@@ -824,21 +824,17 @@ ca_select_axis_func_fill_data (void *ap, void *val)
|
|
|
824
824
|
return;
|
|
825
825
|
}
|
|
826
826
|
|
|
827
|
-
ca_attach(ca->parent);
|
|
827
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
828
828
|
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
829
829
|
ca->elements, val);
|
|
830
|
-
|
|
831
|
-
ca_detach(ca->parent);
|
|
830
|
+
ca_sync_detach(ca->parent);
|
|
832
831
|
}
|
|
833
832
|
|
|
834
833
|
static void
|
|
835
834
|
ca_select_axis_func_create_mask (void *ap)
|
|
836
835
|
{
|
|
837
836
|
CASelectAxis *ca = (CASelectAxis *) ap;
|
|
838
|
-
|
|
839
|
-
if ( ! ca->parent->mask ) {
|
|
840
|
-
ca_create_mask(ca->parent);
|
|
841
|
-
}
|
|
837
|
+
ca_create_mask(ca->parent);
|
|
842
838
|
ca->mask = ca_select_axis_new(ca->parent->mask, ca->indirect_axis,
|
|
843
839
|
ca->selector,
|
|
844
840
|
ca->ap_start, ca->ap_count, ca->ap_step);
|
|
@@ -878,6 +874,7 @@ rb_ca_select_axis_initialize_copy (VALUE self, VALUE other)
|
|
|
878
874
|
{
|
|
879
875
|
CASelectAxis *ca, *cs;
|
|
880
876
|
TypedData_Get_Struct(self, CASelectAxis, &caselectaxis_data_type, ca);
|
|
877
|
+
ca_check_uninitialized(ca);
|
|
881
878
|
TypedData_Get_Struct(other, CASelectAxis, &caselectaxis_data_type, cs);
|
|
882
879
|
if ( ca_func[CA_OBJ_SELECT_AXIS].pool_init ) {
|
|
883
880
|
ca_array_pool_alloc(ca, CA_OBJ_SELECT_AXIS, cs->parent->ndim);
|
|
@@ -887,6 +884,7 @@ rb_ca_select_axis_initialize_copy (VALUE self, VALUE other)
|
|
|
887
884
|
return self;
|
|
888
885
|
}
|
|
889
886
|
|
|
887
|
+
#ifdef CARRAY_DEV_BUILD
|
|
890
888
|
/* Debug-only Ruby ctor:
|
|
891
889
|
CASelectAxis._new_debug(parent, indirect_axis, selector,
|
|
892
890
|
ap_start_arr, ap_count_arr, ap_step_arr)
|
|
@@ -900,6 +898,7 @@ rb_ca_select_axis_s_new_debug (VALUE klass, VALUE rparent, VALUE rindirect,
|
|
|
900
898
|
VALUE rap_count, VALUE rap_step)
|
|
901
899
|
{
|
|
902
900
|
CArray *parent, *selector;
|
|
901
|
+
/* fits: an axis number from the view that made it */
|
|
903
902
|
int8_t indirect_axis = (int8_t) NUM2INT(rindirect);
|
|
904
903
|
int8_t ndim;
|
|
905
904
|
int8_t k;
|
|
@@ -937,6 +936,7 @@ rb_ca_select_axis_s_new_debug (VALUE klass, VALUE rparent, VALUE rindirect,
|
|
|
937
936
|
rb_ivar_set(obj, rb_intern("_selector"), rselector);
|
|
938
937
|
return obj;
|
|
939
938
|
}
|
|
939
|
+
#endif
|
|
940
940
|
|
|
941
941
|
/* ------------------------------------------------------------------- */
|
|
942
942
|
/* Indexer dispatch hook: called from rb_ca_grid */
|
|
@@ -970,15 +970,15 @@ rb_ca_select_axis_eligible_p (int argc, VALUE *argv, VALUE self)
|
|
|
970
970
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
971
971
|
if ( argc != ca->ndim ) return 0;
|
|
972
972
|
|
|
973
|
-
/* axis 0 is the boolean (indirect).
|
|
973
|
+
/* axis 0 is the boolean (indirect). The rest are read as the indexer
|
|
974
|
+
reads them; a run of more than one step, or of no cells, goes to
|
|
975
|
+
CAGrid. */
|
|
974
976
|
for ( i = 1; i < argc; i++ ) {
|
|
975
977
|
VALUE arg = argv[i];
|
|
976
|
-
|
|
977
|
-
if (
|
|
978
|
-
|
|
979
|
-
if (
|
|
980
|
-
if ( rb_obj_is_kind_of(arg, rb_cInteger) ) continue;
|
|
981
|
-
return 0;
|
|
978
|
+
ca_size_t start, count, step;
|
|
979
|
+
if ( rb_obj_is_carray(arg) ) return 0; /* CArray at axis > 0 → bail */
|
|
980
|
+
ca_index_axis_key(arg, ca->dim[i], i, &start, &count, &step);
|
|
981
|
+
if ( step != 1 || count < 1 ) return 0;
|
|
982
982
|
}
|
|
983
983
|
|
|
984
984
|
return 1;
|
|
@@ -1010,45 +1010,9 @@ rb_ca_select_axis (int argc, VALUE *argv, VALUE self)
|
|
|
1010
1010
|
for ( i = 0; i < argc; i++ ) {
|
|
1011
1011
|
VALUE arg = argv[i];
|
|
1012
1012
|
|
|
1013
|
-
if (
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
ap_step[i] = 1;
|
|
1017
|
-
}
|
|
1018
|
-
else if ( FIXNUM_P(arg) || rb_obj_is_kind_of(arg, rb_cInteger) ) {
|
|
1019
|
-
ca_size_t n = NUM2LL(arg);
|
|
1020
|
-
if ( n < 0 ) n += parent->dim[i];
|
|
1021
|
-
if ( n < 0 || n >= parent->dim[i] ) {
|
|
1022
|
-
rb_raise(rb_eIndexError,
|
|
1023
|
-
"CASelectAxis: index %lld out of range at axis %d",
|
|
1024
|
-
(long long) n, i);
|
|
1025
|
-
}
|
|
1026
|
-
ap_start[i] = n;
|
|
1027
|
-
ap_count[i] = 1;
|
|
1028
|
-
ap_step[i] = 1;
|
|
1029
|
-
}
|
|
1030
|
-
else if ( rb_obj_is_kind_of(arg, rb_cRange) ) {
|
|
1031
|
-
VALUE rfirst = rb_funcall(arg, rb_intern("first"), 0);
|
|
1032
|
-
VALUE rlast = rb_funcall(arg, rb_intern("last"), 0);
|
|
1033
|
-
int exclusive = RTEST(rb_funcall(arg, rb_intern("exclude_end?"), 0));
|
|
1034
|
-
ca_size_t a = NUM2LL(rfirst);
|
|
1035
|
-
ca_size_t b = NUM2LL(rlast);
|
|
1036
|
-
if ( a < 0 ) a += parent->dim[i];
|
|
1037
|
-
if ( b < 0 ) b += parent->dim[i];
|
|
1038
|
-
ca_size_t cnt = exclusive ? (b - a) : (b - a + 1);
|
|
1039
|
-
if ( cnt <= 0 ) {
|
|
1040
|
-
rb_raise(rb_eIndexError,
|
|
1041
|
-
"CASelectAxis: empty range at axis %d", i);
|
|
1042
|
-
}
|
|
1043
|
-
if ( a < 0 || a >= parent->dim[i] ||
|
|
1044
|
-
(a + cnt - 1) < 0 || (a + cnt - 1) >= parent->dim[i] ) {
|
|
1045
|
-
rb_raise(rb_eIndexError,
|
|
1046
|
-
"CASelectAxis: range [%lld..%lld] out of bounds at axis %d",
|
|
1047
|
-
(long long) a, (long long) (a + cnt - 1), i);
|
|
1048
|
-
}
|
|
1049
|
-
ap_start[i] = a;
|
|
1050
|
-
ap_count[i] = cnt;
|
|
1051
|
-
ap_step[i] = 1;
|
|
1013
|
+
if ( ! rb_obj_is_carray(arg) ) {
|
|
1014
|
+
ca_index_axis_key(arg, parent->dim[i], i,
|
|
1015
|
+
&ap_start[i], &ap_count[i], &ap_step[i]);
|
|
1052
1016
|
}
|
|
1053
1017
|
else if ( rb_obj_is_carray(arg) && rb_ca_is_boolean_type(arg) ) {
|
|
1054
1018
|
TypedData_Get_Struct(arg, CArray, &carray_data_type, selector);
|
|
@@ -1188,7 +1152,7 @@ rb_ca_select_axis_dispatch_attach_debug (VALUE self)
|
|
|
1188
1152
|
TypedData_Get_Struct(self, CASelectAxis, &caselectaxis_data_type, ca);
|
|
1189
1153
|
ca_select_axis_describe_axes(ca, desc, pdims);
|
|
1190
1154
|
|
|
1191
|
-
ca_attach(ca->parent);
|
|
1155
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
1192
1156
|
buf = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1193
1157
|
ca->elements, NULL);
|
|
1194
1158
|
ca_detach(ca->parent);
|
|
@@ -1222,11 +1186,10 @@ rb_ca_select_axis_dispatch_scatter_debug (VALUE self, VALUE in_str)
|
|
|
1222
1186
|
ca_size_t pdims[CA_RANK_MAX];
|
|
1223
1187
|
ca_select_axis_describe_axes(ca, desc, pdims);
|
|
1224
1188
|
|
|
1225
|
-
ca_attach(ca->parent);
|
|
1189
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
1226
1190
|
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1227
1191
|
ca->elements, RSTRING_PTR(in_str));
|
|
1228
|
-
|
|
1229
|
-
ca_detach(ca->parent);
|
|
1192
|
+
ca_sync_detach(ca->parent);
|
|
1230
1193
|
return Qnil;
|
|
1231
1194
|
}
|
|
1232
1195
|
|
|
@@ -1250,11 +1213,10 @@ rb_ca_select_axis_dispatch_fill_value_debug (VALUE self, VALUE val_str)
|
|
|
1250
1213
|
ca_size_t pdims[CA_RANK_MAX];
|
|
1251
1214
|
ca_select_axis_describe_axes(ca, desc, pdims);
|
|
1252
1215
|
|
|
1253
|
-
ca_attach(ca->parent);
|
|
1216
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
1254
1217
|
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1255
1218
|
ca->elements, RSTRING_PTR(val_str));
|
|
1256
|
-
|
|
1257
|
-
ca_detach(ca->parent);
|
|
1219
|
+
ca_sync_detach(ca->parent);
|
|
1258
1220
|
return Qnil;
|
|
1259
1221
|
}
|
|
1260
1222
|
#endif /* CARRAY_DEV_BUILD */
|
|
@@ -1281,9 +1243,11 @@ Init_ca_obj_select_axis (void)
|
|
|
1281
1243
|
rb_define_alloc_func(rb_cCASelectAxis, rb_ca_select_axis_s_allocate);
|
|
1282
1244
|
rb_define_method(rb_cCASelectAxis, "initialize_copy",
|
|
1283
1245
|
rb_ca_select_axis_initialize_copy, 1);
|
|
1246
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1284
1247
|
/* Debug-only ctor for testing; not part of the public API. */
|
|
1285
1248
|
rb_define_singleton_method(rb_cCASelectAxis, "_new_debug",
|
|
1286
1249
|
rb_ca_select_axis_s_new_debug, 6);
|
|
1250
|
+
#endif
|
|
1287
1251
|
|
|
1288
1252
|
#ifdef CARRAY_DEV_BUILD
|
|
1289
1253
|
/* debug accessors (dev-only, stripped in release).
|
|
@@ -1300,7 +1264,9 @@ Init_ca_obj_select_axis (void)
|
|
|
1300
1264
|
rb_ca_select_axis_dispatch_fill_value_debug, 1);
|
|
1301
1265
|
#endif
|
|
1302
1266
|
|
|
1267
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1303
1268
|
/* Benchmark-only bypass setter on CArray class. */
|
|
1304
1269
|
rb_define_singleton_method(rb_cCArray, "_csa_bypass=", rb_ca_s_csa_bypass_eq, 1);
|
|
1305
1270
|
rb_define_singleton_method(rb_cCArray, "_csa_bypass?", rb_ca_s_csa_bypass_p, 0);
|
|
1271
|
+
#endif
|
|
1306
1272
|
}
|
data/ext/ca_obj_shift.c
CHANGED
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
sync_data / fill_data / ptr_at_* / fetch_index / store_index) are
|
|
9
9
|
shared with CAWindow's per-axis bounds engine via the `ca_shift_func`
|
|
10
10
|
table, which is built by copying `ca_window_func` and only overriding
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
clone, so that cloning produces a CAShift. create_mask is shared: it
|
|
12
|
+
gives the mask the view's own obj_type.
|
|
13
13
|
|
|
14
14
|
User surface (CArray#shift) is documented in yard-stubs/ca_obj_shift.rb.
|
|
15
15
|
|
|
16
16
|
---------------------------------------------------------------------------- */
|
|
17
17
|
|
|
18
18
|
#include "carray.h"
|
|
19
|
+
#include "carray_internal.h" /* ca_window_create_bounds_mask */
|
|
19
20
|
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE */
|
|
20
21
|
|
|
21
22
|
/* External: CAWindow's operation table + setup are the basis for CAShift. */
|
|
@@ -31,11 +32,13 @@ extern int ca_window_setup (CAWindow *ca, CArray *parent,
|
|
|
31
32
|
(rb_data_type_t *) cast would write into .rodata and SIGBUS on macOS. */
|
|
32
33
|
static size_t ca_shift_dsize (const void *ap);
|
|
33
34
|
|
|
35
|
+
extern void ca_window_mark (void *ap); /* ca_obj_window.c: marks the fill value */
|
|
36
|
+
|
|
34
37
|
const rb_data_type_t cashift_data_type = {
|
|
35
|
-
.parent = &
|
|
38
|
+
.parent = &cawindow_data_type,
|
|
36
39
|
.wrap_struct_name = "CAShift",
|
|
37
40
|
.function = {
|
|
38
|
-
.dmark =
|
|
41
|
+
.dmark = ca_window_mark,
|
|
39
42
|
.dfree = ca_free,
|
|
40
43
|
.dsize = ca_shift_dsize,
|
|
41
44
|
.dcompact = NULL
|
|
@@ -44,7 +47,7 @@ const rb_data_type_t cashift_data_type = {
|
|
|
44
47
|
};
|
|
45
48
|
|
|
46
49
|
/* CAREFUL: mask TypedData uses ca_free_nop. The mask CArray is owned
|
|
47
|
-
by the parent CAShift's `ca->mask` field and freed by
|
|
50
|
+
by the parent CAShift's `ca->mask` field and freed by the shared window free's
|
|
48
51
|
ca_free(ca->mask). If the wrapped Ruby VALUE (from the `ca.mask`
|
|
49
52
|
accessor / rb_ca_mask_array) also freed it, the result is a
|
|
50
53
|
double-free that explodes under GC stress. */
|
|
@@ -105,10 +108,13 @@ ca_shift_setup (CAShift *ca, CArray *parent,
|
|
|
105
108
|
/* Delegate to CAWindow setup. */
|
|
106
109
|
ca_window_setup((CAWindow *) ca, parent, start, count, bounds, fill);
|
|
107
110
|
|
|
111
|
+
if ( ca == NULL ) { /* checks only, see ca_window_setup */
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
108
115
|
/* Override obj_type so dispatch (ca_func[obj_type]) lands on the
|
|
109
116
|
CAShift-specific table (which differs from CAWindow only in
|
|
110
|
-
|
|
111
|
-
result). */
|
|
117
|
+
clone). */
|
|
112
118
|
ca->obj_type = CA_OBJ_SHIFT;
|
|
113
119
|
|
|
114
120
|
return 0;
|
|
@@ -118,37 +124,14 @@ CAShift *
|
|
|
118
124
|
ca_shift_new (CArray *parent, ca_size_t *shift, char *fill, int8_t *roll,
|
|
119
125
|
int fill_mask)
|
|
120
126
|
{
|
|
121
|
-
CAShift *ca
|
|
127
|
+
CAShift *ca;
|
|
128
|
+
ca_shift_setup(NULL, parent, shift, fill, roll, fill_mask);
|
|
129
|
+
ca = (CAShift *) ca_array_alloc(CA_OBJ_SHIFT, parent->ndim);
|
|
122
130
|
ca_shift_setup(ca, parent, shift, fill, roll, fill_mask);
|
|
131
|
+
ca_fill_or_free((CArray *) ca, ca_window_create_bounds_mask, (VALUE) ca);
|
|
123
132
|
return ca;
|
|
124
133
|
}
|
|
125
134
|
|
|
126
|
-
/* Free: same fields as CAWindow (same struct). CAShift goes through
|
|
127
|
-
ca_window_setup, so the same seven ndim-sized fields live in ca->_pool
|
|
128
|
-
(fill stays separate). */
|
|
129
|
-
static void
|
|
130
|
-
free_ca_shift (void *ap)
|
|
131
|
-
{
|
|
132
|
-
CAShift *ca = (CAShift *) ap;
|
|
133
|
-
if ( ca != NULL ) {
|
|
134
|
-
ca_free(ca->mask);
|
|
135
|
-
xfree(ca->fill); /* always separate (bytes-sized) */
|
|
136
|
-
if ( ca->_pool ) {
|
|
137
|
-
ca_array_free(ca);
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
xfree(ca->bounds);
|
|
141
|
-
xfree(ca->start);
|
|
142
|
-
xfree(ca->count);
|
|
143
|
-
xfree(ca->size0);
|
|
144
|
-
xfree(ca->embed_parent_start);
|
|
145
|
-
xfree(ca->embed_count);
|
|
146
|
-
xfree(ca->embed_output_offset);
|
|
147
|
-
xfree(ca);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
135
|
/* Clone: produce a CAShift (not CAWindow) by rebuilding via setup.
|
|
153
136
|
Recover (shift[], roll[], fill_mask) from current (start[], bounds[]). */
|
|
154
137
|
static void *
|
|
@@ -171,73 +154,14 @@ ca_shift_func_clone (void *ap)
|
|
|
171
154
|
}
|
|
172
155
|
}
|
|
173
156
|
|
|
174
|
-
return ca_shift_new(ca->parent, shift, ca->fill, roll, fill_mask);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/* create_mask: produce a CAShift-typed mask (not CAWindow-typed).
|
|
178
|
-
Following the original ca_shift_func_create_mask semantics:
|
|
179
|
-
- Ensure parent has mask
|
|
180
|
-
- Build mask sub-view using same shift/roll, fill = 1 if fill_mask
|
|
181
|
-
else 0 (i.e. range-outside cells get masked when fill_mask was on,
|
|
182
|
-
unmasked otherwise) */
|
|
183
|
-
static void
|
|
184
|
-
ca_shift_func_create_mask (void *ap)
|
|
185
|
-
{
|
|
186
|
-
CAShift *ca = (CAShift *) ap;
|
|
187
|
-
ca_size_t shift[CA_RANK_MAX];
|
|
188
|
-
int8_t roll[CA_RANK_MAX];
|
|
189
|
-
boolean8_t fill_val;
|
|
190
|
-
int fill_mask_was_on = 0;
|
|
191
|
-
int8_t k;
|
|
192
|
-
|
|
193
|
-
ca_update_mask(ca->parent);
|
|
194
|
-
if ( ! ca->parent->mask ) {
|
|
195
|
-
ca_create_mask(ca->parent);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
for (k = 0; k < ca->ndim; k++) {
|
|
199
|
-
shift[k] = -ca->start[k];
|
|
200
|
-
if ( ca->bounds[k] == CA_BOUNDS_PERIODIC ) {
|
|
201
|
-
roll[k] = 1;
|
|
202
|
-
} else {
|
|
203
|
-
roll[k] = 0;
|
|
204
|
-
if ( ca->bounds[k] == CA_BOUNDS_MASK ) fill_mask_was_on = 1;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/* If MASK policy was set, the mask sub-view should mark out-of-range
|
|
209
|
-
cells as "masked" (fill value = 1). Otherwise out-of-range cells
|
|
210
|
-
get the fill value (fill = 0) and aren't masked. */
|
|
211
|
-
fill_val = fill_mask_was_on ? 1 : 0;
|
|
212
|
-
|
|
213
|
-
/* Build the mask as CAShift with same shift/roll but using fill_mask=0
|
|
214
|
-
(the mask itself shouldn't recursively create a mask) and fill = 0/1
|
|
215
|
-
boolean. Bounds for mask: replace MASK→FILL so the mask values are
|
|
216
|
-
written, not the mask's mask. */
|
|
217
157
|
{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
ca_size_t mcount[CA_RANK_MAX];
|
|
222
|
-
CAShift *m;
|
|
223
|
-
CA_ASSUME(ca->ndim >= 0 && ca->ndim <= CA_RANK_MAX); /* bound loop over [CA_RANK_MAX] arrays */
|
|
224
|
-
for (k = 0; k < ca->ndim; k++) {
|
|
225
|
-
mstart[k] = ca->start[k];
|
|
226
|
-
mcount[k] = ca->count[k];
|
|
227
|
-
mbounds[k] = ( ca->bounds[k] == CA_BOUNDS_MASK )
|
|
228
|
-
? CA_BOUNDS_FILL : ca->bounds[k];
|
|
229
|
-
}
|
|
230
|
-
/* CAShift-typed mask: allocate, setup as CAWindow with adjusted
|
|
231
|
-
bounds, bump obj_type. */
|
|
232
|
-
m = (CAShift *) ca_array_alloc(CA_OBJ_SHIFT, ca->ndim);
|
|
233
|
-
ca_window_setup((CAWindow *) m, ca->parent->mask,
|
|
234
|
-
mstart, mcount, mbounds, (char *) &fill_val);
|
|
235
|
-
m->obj_type = CA_OBJ_SHIFT;
|
|
236
|
-
ca->mask = (CArray *) m;
|
|
158
|
+
CAShift *cp = ca_shift_new(ca->parent, shift, ca->fill, roll, fill_mask);
|
|
159
|
+
cp->mask_owner = ca->mask_owner;
|
|
160
|
+
return cp;
|
|
237
161
|
}
|
|
238
|
-
(void) shift; (void) roll; /* recovered above but unused in this block */
|
|
239
162
|
}
|
|
240
163
|
|
|
164
|
+
|
|
241
165
|
/* ------------------------------------------------------------------- */
|
|
242
166
|
|
|
243
167
|
VALUE
|
|
@@ -319,9 +243,12 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
|
|
|
319
243
|
fill_mask = 1;
|
|
320
244
|
}
|
|
321
245
|
else {
|
|
322
|
-
|
|
246
|
+
/* The fill is a value of the array (a struct, an instant for a Face):
|
|
247
|
+
rb_ca_obj2ptr writes it as one cell of the storage. */
|
|
248
|
+
rcs = rb_cscalar_new(ca_strip_face(ca)->data_type, ca->bytes, NULL);
|
|
323
249
|
TypedData_Get_Struct(rcs, CScalar, &cscalar_data_type, cs);
|
|
324
250
|
fill = cs->ptr;
|
|
251
|
+
rb_ca_obj2ptr(self, rfval, fill);
|
|
325
252
|
}
|
|
326
253
|
|
|
327
254
|
if ( NIL_P(rroll) ) {
|
|
@@ -366,6 +293,7 @@ rb_ca_shift_initialize_copy (VALUE self, VALUE other)
|
|
|
366
293
|
int8_t k;
|
|
367
294
|
|
|
368
295
|
TypedData_Get_Struct(self, CAShift, &cashift_data_type, ca);
|
|
296
|
+
ca_check_uninitialized(ca);
|
|
369
297
|
TypedData_Get_Struct(other, CAShift, &cashift_data_type, cs);
|
|
370
298
|
|
|
371
299
|
/* Recover shift/roll/fill_mask from cs (same scheme as clone). */
|
|
@@ -384,6 +312,10 @@ rb_ca_shift_initialize_copy (VALUE self, VALUE other)
|
|
|
384
312
|
ca_array_pool_alloc(ca, CA_OBJ_SHIFT, cs->ndim);
|
|
385
313
|
}
|
|
386
314
|
ca_shift_setup(ca, cs->parent, shift, cs->fill, roll, fill_mask);
|
|
315
|
+
ca_window_create_bounds_mask((VALUE) ca);
|
|
316
|
+
/* a copy of a mask over a stand-in gives way to the parent's mask as
|
|
317
|
+
the original does */
|
|
318
|
+
ca->mask_owner = cs->mask_owner;
|
|
387
319
|
|
|
388
320
|
return self;
|
|
389
321
|
}
|
|
@@ -395,12 +327,10 @@ rb_ca_shift_initialize_copy (VALUE self, VALUE other)
|
|
|
395
327
|
void
|
|
396
328
|
Init_ca_obj_shift (void)
|
|
397
329
|
{
|
|
398
|
-
/* Build the CAShift op table by copying CAWindow's
|
|
399
|
-
|
|
330
|
+
/* Build the CAShift op table by copying CAWindow's; only clone has to
|
|
331
|
+
rebuild a CAShift. */
|
|
400
332
|
ca_shift_func = ca_window_func;
|
|
401
|
-
ca_shift_func.free_object = free_ca_shift;
|
|
402
333
|
ca_shift_func.clone = ca_shift_func_clone;
|
|
403
|
-
ca_shift_func.create_mask = ca_shift_func_create_mask;
|
|
404
334
|
|
|
405
335
|
rb_cCAShift = rb_define_class("CAShift", rb_cCAWindow);
|
|
406
336
|
rb_cCAShiftMask = rb_define_class("CAShiftMask", rb_cCAShift);
|