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_grid.c
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
---------------------------------------------------------------------------- */
|
|
15
15
|
|
|
16
16
|
#include "carray.h"
|
|
17
|
+
#include "carray_internal.h" /* ca_attach_window */
|
|
17
18
|
|
|
18
19
|
/* Per-axis tagged kind. Each axis is either STRIDE (start/step/count,
|
|
19
20
|
no allocation) or INDEX (an owned ca_size_t index snapshot). A Range
|
|
@@ -34,9 +35,14 @@ typedef struct {
|
|
|
34
35
|
/* INDEX-only. Owned in the non-share case (xfree'd by free_ca_grid),
|
|
35
36
|
aliased in the share case (parent owns; CA_FLAG_SHARE_INDEX). */
|
|
36
37
|
ca_size_t *indices;
|
|
38
|
+
/* INDEX-only, NULL when no cell is a hole. holes[i] marks a position
|
|
39
|
+
whose index cell was masked: it selects no parent cell. Its entry in
|
|
40
|
+
indices is 0 and is never range-checked. Owned and aliased as
|
|
41
|
+
indices is. */
|
|
42
|
+
uint8_t *holes;
|
|
37
43
|
} cag_axis_t;
|
|
38
44
|
|
|
39
|
-
typedef struct {
|
|
45
|
+
typedef struct _CAGrid {
|
|
40
46
|
int16_t obj_type;
|
|
41
47
|
int8_t data_type;
|
|
42
48
|
int8_t ndim;
|
|
@@ -52,6 +58,18 @@ typedef struct {
|
|
|
52
58
|
uint8_t nosync;
|
|
53
59
|
/* -------------*/
|
|
54
60
|
cag_axis_t *axes; /* [ndim], owned (non-share) or aliased (share) */
|
|
61
|
+
/* A grid with holes (cag_axis_t.holes): set on its mask grid, whose
|
|
62
|
+
holes read as masked. The data grid's holes read the cell at index 0
|
|
63
|
+
of each holed axis, as project and gather_nd do. */
|
|
64
|
+
int8_t holes_read_masked;
|
|
65
|
+
/* A grid with holes over a parent that has no mask: the all-false mask
|
|
66
|
+
its mask grid reads instead, so that showing the holes gives the
|
|
67
|
+
parent no mask. Owned by this grid; NULL otherwise. */
|
|
68
|
+
CArray *mask_standin;
|
|
69
|
+
/* On a mask grid: the grid whose mask it is, which holds the stand-in
|
|
70
|
+
and the parent whose mask replaces it. A Ruby copy of the mask keeps
|
|
71
|
+
that grid alive (rb_ca_mask_array sets masked_array). */
|
|
72
|
+
struct _CAGrid *mask_owner;
|
|
55
73
|
} CAGrid;
|
|
56
74
|
|
|
57
75
|
static size_t
|
|
@@ -69,6 +87,9 @@ ca_grid_dsize (const void *ap)
|
|
|
69
87
|
if (ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices) {
|
|
70
88
|
total += ca->axes[k].count * sizeof(ca_size_t);
|
|
71
89
|
}
|
|
90
|
+
if (ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].holes) {
|
|
91
|
+
total += ca->axes[k].count;
|
|
92
|
+
}
|
|
72
93
|
}
|
|
73
94
|
return total;
|
|
74
95
|
}
|
|
@@ -122,53 +143,83 @@ static VALUE rb_cCAGridMask;
|
|
|
122
143
|
|
|
123
144
|
static int8_t CA_OBJ_GRID;
|
|
124
145
|
|
|
125
|
-
/*
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
132
|
-
cag_axis_t *protos, int share)
|
|
146
|
+
/* Raises when protos cannot describe a view of parent: an ndim that is
|
|
147
|
+
not parent's, a negative count, a byte length over the limit, or a
|
|
148
|
+
parent index out of range. Nothing is allocated here, so the caller
|
|
149
|
+
runs it before taking memory. */
|
|
150
|
+
static void
|
|
151
|
+
ca_grid_check_protos (CArray *parent, int8_t ndim, const cag_axis_t *protos)
|
|
133
152
|
{
|
|
134
153
|
int8_t k;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
double length;
|
|
138
|
-
ca_size_t *dim0;
|
|
139
|
-
|
|
140
|
-
CA_ASSUME(ndim >= 0 && ndim <= CA_RANK_MAX); /* bound loops/allocs over [CA_RANK_MAX] arrays */
|
|
141
|
-
data_type = parent->data_type;
|
|
142
|
-
bytes = parent->bytes;
|
|
143
|
-
dim0 = parent->dim;
|
|
154
|
+
ca_size_t j;
|
|
155
|
+
double length;
|
|
144
156
|
|
|
145
|
-
/*
|
|
146
|
-
|
|
147
|
-
time we get here ndim == parent->ndim. */
|
|
157
|
+
/* rb_ca_grid pads with nil when fewer args are given, so ndim ==
|
|
158
|
+
parent->ndim for every in-tree caller. */
|
|
148
159
|
if ( ndim != parent->ndim ) {
|
|
149
160
|
rb_raise(rb_eArgError,
|
|
150
161
|
"CAGrid: ndim mismatch (%d args vs parent->ndim %d)",
|
|
151
162
|
(int) ndim, (int) parent->ndim);
|
|
152
163
|
}
|
|
153
164
|
|
|
154
|
-
|
|
155
|
-
length = bytes;
|
|
165
|
+
length = parent->bytes;
|
|
156
166
|
for (k = 0; k < ndim; k++) {
|
|
157
167
|
if (protos[k].count < 0) {
|
|
158
|
-
rb_raise(
|
|
168
|
+
rb_raise(rb_eArgError, "negative size for %d-th dimension", k);
|
|
159
169
|
}
|
|
160
|
-
elements *= protos[k].count;
|
|
161
170
|
length *= protos[k].count;
|
|
162
171
|
}
|
|
163
172
|
if (length > CA_LENGTH_MAX) {
|
|
164
|
-
rb_raise(
|
|
173
|
+
rb_raise(rb_eArgError, "too large byte length");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
for (k = 0; k < ndim; k++) {
|
|
177
|
+
if ( protos[k].count <= 0 ) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (protos[k].kind == CAG_AXIS_STRIDE) {
|
|
181
|
+
ca_size_t first = protos[k].start;
|
|
182
|
+
ca_size_t last = first + (protos[k].count - 1) * protos[k].step;
|
|
183
|
+
ca_index_in_range_at(first, parent->dim[k], k);
|
|
184
|
+
if (protos[k].count > 1) ca_index_in_range_at(last, parent->dim[k], k);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
for (j = 0; j < protos[k].count; j++) {
|
|
188
|
+
if ( protos[k].holes && protos[k].holes[j] ) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
ca_index_in_range_at(protos[k].indices[j], parent->dim[k], k);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* Setup: caller passes ndim + per-axis protos (cag_axis_t) that
|
|
198
|
+
ca_grid_check_protos has accepted. Copies the fields and, for INDEX
|
|
199
|
+
axes, snapshots the indices into an owned buffer. The share path
|
|
200
|
+
(share=1, used only by create_mask) aliases the caller's protos buffer
|
|
201
|
+
instead: the mask grid is owned and freed by the grid whose axes it
|
|
202
|
+
aliases (free_ca_grid skips the xfree under CA_FLAG_SHARE_INDEX). */
|
|
203
|
+
static int
|
|
204
|
+
ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
205
|
+
cag_axis_t *protos, int share)
|
|
206
|
+
{
|
|
207
|
+
int8_t k;
|
|
208
|
+
ca_size_t elements;
|
|
209
|
+
|
|
210
|
+
CA_ASSUME(ndim >= 0 && ndim <= CA_RANK_MAX); /* bound loops/allocs over [CA_RANK_MAX] arrays */
|
|
211
|
+
|
|
212
|
+
{
|
|
213
|
+
ca_size_t counts[CA_RANK_MAX];
|
|
214
|
+
for (k = 0; k < ndim; k++) counts[k] = protos[k].count;
|
|
215
|
+
elements = ca_shape_elements(ndim, counts, parent->bytes);
|
|
165
216
|
}
|
|
166
217
|
|
|
167
218
|
ca->obj_type = CA_OBJ_GRID;
|
|
168
|
-
ca->data_type = data_type;
|
|
219
|
+
ca->data_type = parent->data_type;
|
|
169
220
|
ca->flags = 0;
|
|
170
221
|
ca->ndim = ndim;
|
|
171
|
-
ca->bytes = bytes;
|
|
222
|
+
ca->bytes = parent->bytes;
|
|
172
223
|
ca->elements = elements;
|
|
173
224
|
ca->ptr = NULL;
|
|
174
225
|
ca->mask = NULL;
|
|
@@ -178,6 +229,9 @@ ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
|
178
229
|
ca->parent = parent;
|
|
179
230
|
ca->attach = 0;
|
|
180
231
|
ca->nosync = 0;
|
|
232
|
+
ca->holes_read_masked = 0;
|
|
233
|
+
ca->mask_standin = NULL;
|
|
234
|
+
ca->mask_owner = NULL;
|
|
181
235
|
|
|
182
236
|
for (k = 0; k < ndim; k++) ca->dim[k] = protos[k].count;
|
|
183
237
|
|
|
@@ -196,48 +250,104 @@ ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
|
196
250
|
ca->axes[k].start = protos[k].start;
|
|
197
251
|
ca->axes[k].step = protos[k].step;
|
|
198
252
|
ca->axes[k].indices = NULL;
|
|
199
|
-
|
|
200
|
-
if (protos[k].count > 0) {
|
|
201
|
-
ca_size_t first = protos[k].start;
|
|
202
|
-
ca_size_t last = first + (protos[k].count - 1) * protos[k].step;
|
|
203
|
-
CA_CHECK_INDEX(first, dim0[k]);
|
|
204
|
-
if (protos[k].count > 1) CA_CHECK_INDEX(last, dim0[k]);
|
|
205
|
-
}
|
|
253
|
+
ca->axes[k].holes = NULL;
|
|
206
254
|
} else {
|
|
207
255
|
ca->axes[k].start = 0;
|
|
208
256
|
ca->axes[k].step = 0;
|
|
209
257
|
ca->axes[k].indices = ALLOC_N(ca_size_t,
|
|
210
258
|
protos[k].count > 0 ? protos[k].count : 1);
|
|
259
|
+
ca->axes[k].holes = NULL;
|
|
211
260
|
ca_size_t j;
|
|
261
|
+
if ( protos[k].holes ) {
|
|
262
|
+
for (j = 0; j < protos[k].count && ! protos[k].holes[j]; j++) ;
|
|
263
|
+
if ( j < protos[k].count ) {
|
|
264
|
+
ca->axes[k].holes = ALLOC_N(uint8_t, protos[k].count);
|
|
265
|
+
memcpy(ca->axes[k].holes, protos[k].holes, protos[k].count);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
212
268
|
for (j = 0; j < protos[k].count; j++) {
|
|
213
269
|
ca_size_t v = protos[k].indices[j];
|
|
214
|
-
|
|
215
|
-
|
|
270
|
+
if ( ca->axes[k].holes && ca->axes[k].holes[j] ) {
|
|
271
|
+
ca->axes[k].indices[j] = 0;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
ca->axes[k].indices[j] = ( v < 0 ) ? v + parent->dim[k] : v;
|
|
216
275
|
}
|
|
217
276
|
}
|
|
218
277
|
}
|
|
219
278
|
}
|
|
220
279
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
280
|
+
return 0;
|
|
281
|
+
}
|
|
224
282
|
|
|
283
|
+
/* Whether any position of the grid is a hole (cag_axis_t.holes). */
|
|
284
|
+
static int
|
|
285
|
+
cag_has_holes (const CAGrid *ca)
|
|
286
|
+
{
|
|
287
|
+
int8_t k;
|
|
288
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
289
|
+
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].holes ) {
|
|
290
|
+
return 1;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
225
293
|
return 0;
|
|
226
294
|
}
|
|
227
295
|
|
|
228
|
-
|
|
229
|
-
|
|
296
|
+
int
|
|
297
|
+
ca_grid_has_holes (void *ap)
|
|
230
298
|
{
|
|
231
|
-
|
|
299
|
+
return cag_has_holes((const CAGrid *) ap);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* A grid with holes has a mask from the start: its holes read as masked
|
|
303
|
+
whatever the parent holds. A mask grid (holes_read_masked) takes none.
|
|
304
|
+
A view of a value array or a mask array can never carry a mask, so it
|
|
305
|
+
can not show a hole. */
|
|
306
|
+
static VALUE
|
|
307
|
+
ca_grid_inherit_mask (VALUE view)
|
|
308
|
+
{
|
|
309
|
+
CAGrid *ca = (CAGrid *) view;
|
|
310
|
+
if ( cag_has_holes(ca) && ! ca->holes_read_masked ) {
|
|
311
|
+
if ( ca_is_value_array(ca) || ca_is_mask_array(ca) ) {
|
|
312
|
+
rb_raise(rb_eArgError,
|
|
313
|
+
"a masked index cell reads as masked, which a view of the %s "
|
|
314
|
+
"array can not hold", ca_is_value_array(ca) ? "value" : "mask");
|
|
315
|
+
}
|
|
316
|
+
ca_create_mask((CArray *) ca);
|
|
317
|
+
return Qnil;
|
|
318
|
+
}
|
|
319
|
+
return ca_view_inherit_mask(view);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/* holes_read_masked is the copied grid's: a copy of a mask grid is one. */
|
|
323
|
+
static CAGrid *
|
|
324
|
+
ca_grid_new_as (CArray *parent, int8_t ndim, cag_axis_t *protos,
|
|
325
|
+
int8_t holes_read_masked, CAGrid *mask_owner)
|
|
326
|
+
{
|
|
327
|
+
CAGrid *ca;
|
|
328
|
+
ca_grid_check_protos(parent, ndim, protos);
|
|
329
|
+
/* check: ca_grid_check_protos above */
|
|
330
|
+
ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
232
331
|
ca_grid_setup(ca, parent, ndim, protos, 0);
|
|
332
|
+
ca->holes_read_masked = holes_read_masked;
|
|
333
|
+
ca->mask_owner = mask_owner;
|
|
334
|
+
ca_fill_or_free((CArray *) ca, ca_grid_inherit_mask, (VALUE) ca);
|
|
233
335
|
return ca;
|
|
234
336
|
}
|
|
235
337
|
|
|
338
|
+
CAGrid *
|
|
339
|
+
ca_grid_new (CArray *parent, int8_t ndim, cag_axis_t *protos)
|
|
340
|
+
{
|
|
341
|
+
return ca_grid_new_as(parent, ndim, protos, 0, NULL);
|
|
342
|
+
}
|
|
343
|
+
|
|
236
344
|
CAGrid *
|
|
237
345
|
ca_grid_new_share (CArray *parent, int8_t ndim, cag_axis_t *protos)
|
|
238
346
|
{
|
|
347
|
+
/* check: the mask grid copies its own grid's checked axes */
|
|
239
348
|
CAGrid *ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
240
349
|
ca_grid_setup(ca, parent, ndim, protos, 1);
|
|
350
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
241
351
|
return ca;
|
|
242
352
|
}
|
|
243
353
|
|
|
@@ -247,12 +357,16 @@ free_ca_grid (void *ap)
|
|
|
247
357
|
CAGrid *ca = (CAGrid *) ap;
|
|
248
358
|
if ( ca != NULL ) {
|
|
249
359
|
ca_free(ca->mask);
|
|
360
|
+
ca_free(ca->mask_standin);
|
|
250
361
|
if ( ! (ca->flags & CA_FLAG_SHARE_INDEX) ) {
|
|
251
362
|
int8_t k;
|
|
252
363
|
for (k = 0; k < ca->ndim; k++) {
|
|
253
364
|
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices ) {
|
|
254
365
|
xfree(ca->axes[k].indices);
|
|
255
366
|
}
|
|
367
|
+
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].holes ) {
|
|
368
|
+
xfree(ca->axes[k].holes);
|
|
369
|
+
}
|
|
256
370
|
}
|
|
257
371
|
xfree(ca->axes);
|
|
258
372
|
}
|
|
@@ -278,7 +392,8 @@ static void *
|
|
|
278
392
|
ca_grid_func_clone (void *ap)
|
|
279
393
|
{
|
|
280
394
|
CAGrid *ca = (CAGrid *) ap;
|
|
281
|
-
return
|
|
395
|
+
return ca_grid_new_as(ca->parent, ca->ndim, ca->axes, ca->holes_read_masked,
|
|
396
|
+
ca->mask_owner);
|
|
282
397
|
}
|
|
283
398
|
|
|
284
399
|
/* Per-axis parent-index lookup. STRIDE = one multiply, INDEX = one
|
|
@@ -292,6 +407,124 @@ cag_parent_index_for (const cag_axis_t *ax, ca_size_t i)
|
|
|
292
407
|
return ax->indices[i];
|
|
293
408
|
}
|
|
294
409
|
|
|
410
|
+
/* A mask grid over its owner's stand-in (ca_mask_standin_current): what
|
|
411
|
+
it reads from now on. */
|
|
412
|
+
static void
|
|
413
|
+
cag_mask_current (CAGrid *m)
|
|
414
|
+
{
|
|
415
|
+
CAGrid *o = m->mask_owner;
|
|
416
|
+
if ( o != NULL ) {
|
|
417
|
+
m->parent = ca_mask_standin_current((CArray *) m, m->parent, o->parent,
|
|
418
|
+
o->mask_standin);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/* After a write of n cells of `data` to a mask grid: a true that went
|
|
423
|
+
into the stand-in goes on to the parent's mask. */
|
|
424
|
+
static void
|
|
425
|
+
cag_mask_settle_after (CAGrid *m, const void *data, ca_size_t n)
|
|
426
|
+
{
|
|
427
|
+
CAGrid *o = m->mask_owner;
|
|
428
|
+
if ( o != NULL && m->parent == o->mask_standin && ca_mask_any_true(data, n) ) {
|
|
429
|
+
ca_mask_standin_settle(o->parent, o->mask_standin);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/* What the GET of a hole writes when it reads no parent cell: true in a
|
|
434
|
+
mask grid, an empty cell otherwise (a parent with no cell to read). */
|
|
435
|
+
static void
|
|
436
|
+
cag_hole_cells (const CAGrid *ca, char *data, ca_size_t n)
|
|
437
|
+
{
|
|
438
|
+
ca_size_t i;
|
|
439
|
+
if ( ca->holes_read_masked ) {
|
|
440
|
+
memset(data, 1, (size_t) n);
|
|
441
|
+
}
|
|
442
|
+
else if ( ca->data_type == CA_OBJECT ) {
|
|
443
|
+
for (i = 0; i < n; i++) ((VALUE *) data)[i] = INT2FIX(0);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
memset(data, 0, (size_t) (n * ca->bytes));
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* The parent address of the view cell at idx. A hole takes index 0 on its
|
|
451
|
+
holed axes; the return says whether the cell is one. */
|
|
452
|
+
static int
|
|
453
|
+
cag_parent_addr (const CAGrid *ca, const ca_size_t *idx, ca_size_t *paddr)
|
|
454
|
+
{
|
|
455
|
+
ca_size_t pa = 0;
|
|
456
|
+
int hole = 0;
|
|
457
|
+
int8_t k;
|
|
458
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
459
|
+
const cag_axis_t *ax = &ca->axes[k];
|
|
460
|
+
if ( ax->kind == CAG_AXIS_INDEX && ax->holes && ax->holes[idx[k]] ) {
|
|
461
|
+
hole = 1;
|
|
462
|
+
}
|
|
463
|
+
pa = pa * ca->parent->dim[k] + cag_parent_index_for(ax, idx[k]);
|
|
464
|
+
}
|
|
465
|
+
*paddr = pa;
|
|
466
|
+
return hole;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/* The transfer of a grid with holes, for the view cells at addrs (NULL:
|
|
470
|
+
the whole view in order). The parent is asked for one batch of
|
|
471
|
+
addresses. A GET reads every cell, a hole reading the cell at index 0
|
|
472
|
+
of its holed axes (in a mask grid it is then set true); a PUT leaves
|
|
473
|
+
the holes out. */
|
|
474
|
+
static void
|
|
475
|
+
ca_grid_holed_xfer (CAGrid *ca, ca_size_t n, const ca_size_t *addrs,
|
|
476
|
+
char *data, int dir)
|
|
477
|
+
{
|
|
478
|
+
CArray *parent;
|
|
479
|
+
ca_size_t bytes = ca->bytes;
|
|
480
|
+
volatile VALUE h_addr = 0, h_hole = 0, h_data = 0;
|
|
481
|
+
ca_size_t *paddrs;
|
|
482
|
+
uint8_t *hole;
|
|
483
|
+
ca_size_t i, m, idx[CA_RANK_MAX];
|
|
484
|
+
|
|
485
|
+
if ( n <= 0 ) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
cag_mask_current(ca);
|
|
489
|
+
parent = ca->parent;
|
|
490
|
+
paddrs = ALLOCV_N(ca_size_t, h_addr, n);
|
|
491
|
+
hole = ALLOCV_N(uint8_t, h_hole, n);
|
|
492
|
+
for (i = 0; i < n; i++) {
|
|
493
|
+
ca_addr2index((CArray *) ca, addrs ? addrs[i] : i, idx);
|
|
494
|
+
hole[i] = (uint8_t) cag_parent_addr(ca, idx, &paddrs[i]);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if ( dir == CA_XFER_GET ) {
|
|
498
|
+
if ( parent->elements == 0 ) {
|
|
499
|
+
cag_hole_cells(ca, data, n); /* every cell is a hole */
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
ca_xfer_addrs(parent, n, paddrs, data, CA_XFER_GET);
|
|
503
|
+
if ( ca->holes_read_masked ) {
|
|
504
|
+
for (i = 0; i < n; i++) {
|
|
505
|
+
if ( hole[i] ) cag_hole_cells(ca, data + i * bytes, 1);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
char *pdata = ALLOCV_N(char, h_data, n * bytes);
|
|
512
|
+
for (i = 0, m = 0; i < n; i++) {
|
|
513
|
+
if ( hole[i] ) continue;
|
|
514
|
+
paddrs[m] = paddrs[i];
|
|
515
|
+
memcpy(pdata + m * bytes, data + i * bytes, (size_t) bytes);
|
|
516
|
+
m++;
|
|
517
|
+
}
|
|
518
|
+
if ( m > 0 ) {
|
|
519
|
+
ca_xfer_addrs(parent, m, paddrs, pdata, CA_XFER_PUT);
|
|
520
|
+
cag_mask_settle_after(ca, pdata, m);
|
|
521
|
+
}
|
|
522
|
+
ALLOCV_END(h_data);
|
|
523
|
+
}
|
|
524
|
+
ALLOCV_END(h_hole);
|
|
525
|
+
ALLOCV_END(h_addr);
|
|
526
|
+
}
|
|
527
|
+
|
|
295
528
|
/* per-cell logic lives in ca_grid_func_xfer_index; forward-declared for
|
|
296
529
|
the region-delivery paths below. */
|
|
297
530
|
static void ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir);
|
|
@@ -304,10 +537,28 @@ ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
304
537
|
CAGrid *ca = (CAGrid *) ap;
|
|
305
538
|
ca_size_t idx0[CA_RANK_MAX];
|
|
306
539
|
int8_t i;
|
|
540
|
+
int hole = 0;
|
|
307
541
|
for (i = 0; i < ca->ndim; i++) {
|
|
308
|
-
|
|
542
|
+
const cag_axis_t *ax = &ca->axes[i];
|
|
543
|
+
idx0[i] = cag_parent_index_for(ax, idx[i]);
|
|
544
|
+
if ( ax->kind == CAG_AXIS_INDEX && ax->holes && ax->holes[idx[i]] ) {
|
|
545
|
+
hole = 1;
|
|
546
|
+
}
|
|
309
547
|
}
|
|
548
|
+
if ( hole ) {
|
|
549
|
+
if ( dir == CA_XFER_PUT ) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
if ( ca->holes_read_masked || ca->parent->elements == 0 ) {
|
|
553
|
+
cag_hole_cells(ca, (char *) data, 1);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
cag_mask_current(ca);
|
|
310
558
|
ca_xfer_index(ca->parent, idx0, data, dir);
|
|
559
|
+
if ( dir == CA_XFER_PUT ) {
|
|
560
|
+
cag_mask_settle_after(ca, data, 1);
|
|
561
|
+
}
|
|
311
562
|
}
|
|
312
563
|
|
|
313
564
|
/* Batched address gather/scatter. Per-axis index remap
|
|
@@ -331,6 +582,11 @@ ca_grid_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
331
582
|
int8_t k;
|
|
332
583
|
volatile VALUE holder;
|
|
333
584
|
|
|
585
|
+
if ( cag_has_holes(ca) ) {
|
|
586
|
+
ca_grid_holed_xfer(ca, n, addrs, (char *) data, dir);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
|
|
334
590
|
/* Opportunistic fast path. ca_resolve_attached_root_via_identity lifts
|
|
335
591
|
parent->ptr through an identity CAStride compose-fold (handles a
|
|
336
592
|
flatten[idx].reshape(*) chain etc.). */
|
|
@@ -386,8 +642,9 @@ ca_grid_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
386
642
|
int8_t k;
|
|
387
643
|
|
|
388
644
|
for (k = 0; k < g->ndim; k++) {
|
|
389
|
-
if (g->axes[k].kind == CAG_AXIS_INDEX
|
|
390
|
-
|
|
645
|
+
if (g->axes[k].kind == CAG_AXIS_INDEX
|
|
646
|
+
&& (g->axes[k].count != 1 || g->axes[k].holes)) {
|
|
647
|
+
return 0; /* multi-INDEX axis -> true gather, decline; a hole is no stride */
|
|
391
648
|
}
|
|
392
649
|
}
|
|
393
650
|
|
|
@@ -451,6 +708,7 @@ static void
|
|
|
451
708
|
ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
452
709
|
ca_size_t *strides, void *data, int dir)
|
|
453
710
|
{
|
|
711
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
454
712
|
CAGrid *g = (CAGrid *) ap;
|
|
455
713
|
CArray *parent = g->parent;
|
|
456
714
|
int8_t ndim = g->ndim;
|
|
@@ -481,8 +739,9 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
481
739
|
/* The request is over the view's addresses, so a transposed / flat request
|
|
482
740
|
is legal and must not be composed axis-by-axis; see
|
|
483
741
|
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
484
|
-
if (
|
|
485
|
-
|
|
742
|
+
if ( cag_has_holes(g)
|
|
743
|
+
|| ! ca_xfer_stride_request_is_axis_box(g, starts, counts, strides) ) {
|
|
744
|
+
aligned = 0; /* a grid with holes goes cell by cell (xfer_index) */
|
|
486
745
|
}
|
|
487
746
|
else {
|
|
488
747
|
for (k = 0; k < ndim; k++) {
|
|
@@ -495,6 +754,7 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
495
754
|
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
496
755
|
for (k = 0; k < ndim; k++) base += starts[k] * gnative[k];
|
|
497
756
|
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
757
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
498
758
|
while (1) {
|
|
499
759
|
ca_size_t goff = base, gidx[CA_RANK_MAX];
|
|
500
760
|
for (k = 0; k < ndim; k++) goff += idx[k] * strides[k];
|
|
@@ -583,6 +843,7 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
583
843
|
ca_xfer_stride/ca_xfer_addrs. */
|
|
584
844
|
for (k = 0; k < ndim; k++) o[k] = 0;
|
|
585
845
|
|
|
846
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
586
847
|
while (1) {
|
|
587
848
|
ca_size_t pbase = 0, doff = 0;
|
|
588
849
|
for (k = 0; k < inner; k++) {
|
|
@@ -624,24 +885,47 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
624
885
|
}
|
|
625
886
|
}
|
|
626
887
|
|
|
888
|
+
/* attach / sync / copy_data / sync_data / fill_data all go through the
|
|
889
|
+
descriptor engine (ca_axis_dispatch.c). This file supplies only
|
|
890
|
+
describe_axes; the engine does the rest.
|
|
891
|
+
|
|
892
|
+
A parent with no memory to lend (ca_parent_lends_no_memory) is never
|
|
893
|
+
attached: attaching it would produce all of its cells to serve the few
|
|
894
|
+
this grid selects. The grid then owns its buffer, filled and drained
|
|
895
|
+
through xfer_all, which asks the parent for the selected cells only.
|
|
896
|
+
The predicate asks what the parent is, not whether it is attached now,
|
|
897
|
+
so attach, sync and detach all take the same branch. */
|
|
898
|
+
|
|
899
|
+
/* A grid with holes fills and writes back its buffer through its own
|
|
900
|
+
transfers too: the descriptor engine has no hole. */
|
|
901
|
+
static int
|
|
902
|
+
cag_owns_buffer (CAGrid *ca)
|
|
903
|
+
{
|
|
904
|
+
return cag_has_holes(ca) || ca_parent_lends_no_memory(ca->parent);
|
|
905
|
+
}
|
|
906
|
+
|
|
627
907
|
static void
|
|
628
908
|
ca_grid_func_allocate (void *ap)
|
|
629
909
|
{
|
|
630
910
|
CAGrid *ca = (CAGrid *) ap;
|
|
631
|
-
|
|
632
|
-
|
|
911
|
+
if ( ! cag_owns_buffer(ca) ) {
|
|
912
|
+
ca_attach(ca->parent);
|
|
913
|
+
}
|
|
914
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
633
915
|
}
|
|
634
916
|
|
|
635
|
-
/* attach / sync / copy_data / sync_data / fill_data all go through the
|
|
636
|
-
descriptor engine (ca_axis_dispatch.c). This file supplies only
|
|
637
|
-
describe_axes; the engine does the rest. */
|
|
638
|
-
|
|
639
917
|
static void
|
|
640
918
|
ca_grid_func_attach (void *ap)
|
|
641
919
|
{
|
|
642
920
|
CAGrid *ca = (CAGrid *) ap;
|
|
643
921
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
644
922
|
ca_size_t pdims[CA_RANK_MAX];
|
|
923
|
+
|
|
924
|
+
if ( cag_owns_buffer(ca) ) {
|
|
925
|
+
ca_axis_view_attach_owned(ca);
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
|
|
645
929
|
ca_attach(ca->parent);
|
|
646
930
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
647
931
|
ca->ptr = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim,
|
|
@@ -654,6 +938,12 @@ ca_grid_func_sync (void *ap)
|
|
|
654
938
|
CAGrid *ca = (CAGrid *) ap;
|
|
655
939
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
656
940
|
ca_size_t pdims[CA_RANK_MAX];
|
|
941
|
+
|
|
942
|
+
if ( cag_owns_buffer(ca) ) {
|
|
943
|
+
ca_axis_view_sync_owned(ca);
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
|
|
657
947
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
658
948
|
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
659
949
|
ca->elements, ca->ptr);
|
|
@@ -666,16 +956,16 @@ ca_grid_func_detach (void *ap)
|
|
|
666
956
|
CAGrid *ca = (CAGrid *) ap;
|
|
667
957
|
xfree(ca->ptr);
|
|
668
958
|
ca->ptr = NULL;
|
|
669
|
-
|
|
959
|
+
if ( ! cag_owns_buffer(ca) ) {
|
|
960
|
+
ca_detach(ca->parent);
|
|
961
|
+
}
|
|
670
962
|
}
|
|
671
963
|
|
|
672
|
-
/*
|
|
673
|
-
of the parent. A cold parent uses a proper 2-pass -- materialise the
|
|
674
|
-
parent into scratch via ca_xfer_all, temporarily expose it as
|
|
675
|
-
parent->ptr, run the fast path, then (for PUT) write scratch back. */
|
|
964
|
+
/* The transfer against parent->ptr, for ca_axis_view_xfer_all. */
|
|
676
965
|
static void
|
|
677
|
-
ca_grid_func_run_fast_path (
|
|
966
|
+
ca_grid_func_run_fast_path (void *ap, char *data, int dir)
|
|
678
967
|
{
|
|
968
|
+
CAGrid *ca = (CAGrid *) ap;
|
|
679
969
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
680
970
|
ca_size_t pdims[CA_RANK_MAX];
|
|
681
971
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
@@ -692,26 +982,38 @@ static void
|
|
|
692
982
|
ca_grid_func_xfer_all (void *ap, void *data, int dir)
|
|
693
983
|
{
|
|
694
984
|
CAGrid *ca = (CAGrid *) ap;
|
|
695
|
-
if ( ca
|
|
696
|
-
|
|
985
|
+
if ( cag_has_holes(ca) ) {
|
|
986
|
+
ca_grid_holed_xfer(ca, ca->elements, NULL, (char *) data, dir);
|
|
697
987
|
return;
|
|
698
988
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
989
|
+
ca_axis_view_xfer_all(ap, ca_grid_func_run_fast_path, 1, data, dir);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
/* The fill of a grid with holes: the parent cells of the positions that
|
|
993
|
+
are not holes, as one address batch. */
|
|
994
|
+
static void
|
|
995
|
+
ca_grid_holed_fill (CAGrid *ca, void *ptr)
|
|
996
|
+
{
|
|
997
|
+
volatile VALUE holder = 0;
|
|
998
|
+
ca_size_t *paddrs;
|
|
999
|
+
ca_size_t i, m = 0, pa, idx[CA_RANK_MAX];
|
|
1000
|
+
|
|
1001
|
+
if ( ca->elements <= 0 ) {
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
cag_mask_current(ca);
|
|
1005
|
+
paddrs = ALLOCV_N(ca_size_t, holder, ca->elements);
|
|
1006
|
+
for (i = 0; i < ca->elements; i++) {
|
|
1007
|
+
ca_addr2index((CArray *) ca, i, idx);
|
|
1008
|
+
if ( ! cag_parent_addr(ca, idx, &pa) ) {
|
|
1009
|
+
paddrs[m++] = pa;
|
|
711
1010
|
}
|
|
712
|
-
parent->ptr = parent_ptr_saved;
|
|
713
|
-
ALLOCV_END(holder);
|
|
714
1011
|
}
|
|
1012
|
+
if ( m > 0 ) {
|
|
1013
|
+
ca_fill_addrs(ca->parent, m, paddrs, ptr);
|
|
1014
|
+
cag_mask_settle_after(ca, ptr, 1);
|
|
1015
|
+
}
|
|
1016
|
+
ALLOCV_END(holder);
|
|
715
1017
|
}
|
|
716
1018
|
|
|
717
1019
|
static void
|
|
@@ -721,6 +1023,11 @@ ca_grid_func_fill_data (void *ap, void *ptr)
|
|
|
721
1023
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
722
1024
|
ca_size_t pdims[CA_RANK_MAX];
|
|
723
1025
|
|
|
1026
|
+
if ( cag_has_holes(ca) ) {
|
|
1027
|
+
ca_grid_holed_fill(ca, ptr);
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
724
1031
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
725
1032
|
|
|
726
1033
|
/* Writing the selected cells used to go through a whole-parent attach and
|
|
@@ -734,25 +1041,38 @@ ca_grid_func_fill_data (void *ap, void *ptr)
|
|
|
734
1041
|
return;
|
|
735
1042
|
}
|
|
736
1043
|
|
|
737
|
-
ca_attach(ca->parent);
|
|
1044
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
738
1045
|
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
739
1046
|
ca->elements, ptr);
|
|
740
|
-
|
|
741
|
-
ca_detach(ca->parent);
|
|
1047
|
+
ca_sync_detach(ca->parent);
|
|
742
1048
|
}
|
|
743
1049
|
|
|
1050
|
+
/* The mask is a grid over the parent's mask with the same axes, holes
|
|
1051
|
+
included; there the holes read as masked. */
|
|
744
1052
|
static void
|
|
745
1053
|
ca_grid_func_create_mask (void *ap)
|
|
746
1054
|
{
|
|
747
1055
|
CAGrid *ca = (CAGrid *) ap;
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
1056
|
+
CArray *mparent;
|
|
1057
|
+
int holed = cag_has_holes(ca);
|
|
1058
|
+
|
|
1059
|
+
/* A grid with holes shows them without giving a parent that has no mask
|
|
1060
|
+
one: its mask grid reads an all-false stand-in until a true is written
|
|
1061
|
+
outside the holes (ca_mask_standin_new). */
|
|
1062
|
+
if ( holed && ! ca_has_mask(ca->parent) ) {
|
|
1063
|
+
if ( ! ca->mask_standin ) {
|
|
1064
|
+
ca->mask_standin = ca_mask_standin_new(ca->parent);
|
|
1065
|
+
}
|
|
1066
|
+
mparent = ca->mask_standin;
|
|
1067
|
+
}
|
|
1068
|
+
else {
|
|
751
1069
|
ca_create_mask(ca->parent);
|
|
1070
|
+
mparent = ca->parent->mask;
|
|
752
1071
|
}
|
|
753
1072
|
|
|
754
|
-
ca->mask = (CArray *) ca_grid_new_share(ca->
|
|
755
|
-
|
|
1073
|
+
ca->mask = (CArray *) ca_grid_new_share(mparent, ca->ndim, ca->axes);
|
|
1074
|
+
((CAGrid *) ca->mask)->holes_read_masked = (int8_t) holed;
|
|
1075
|
+
((CAGrid *) ca->mask)->mask_owner = holed ? ca : NULL;
|
|
756
1076
|
}
|
|
757
1077
|
|
|
758
1078
|
ca_operation_function_t ca_grid_func = {
|
|
@@ -789,82 +1109,110 @@ rb_ca_grid_new (VALUE cary, int8_t ndim, cag_axis_t *protos)
|
|
|
789
1109
|
return obj;
|
|
790
1110
|
}
|
|
791
1111
|
|
|
792
|
-
/*
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
1112
|
+
/* The INDEX axes of rb_ca_grid, read with their index arrays attached,
|
|
1113
|
+
and the view built from them. */
|
|
1114
|
+
|
|
1115
|
+
typedef struct {
|
|
1116
|
+
VALUE self;
|
|
1117
|
+
CArray *ca;
|
|
1118
|
+
CArray **ci;
|
|
1119
|
+
cag_axis_t *protos;
|
|
1120
|
+
} ca_grid_build_ctx_t;
|
|
1121
|
+
|
|
1122
|
+
static VALUE
|
|
1123
|
+
ca_grid_build_body (VALUE arg)
|
|
800
1124
|
{
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1125
|
+
ca_grid_build_ctx_t *c = (ca_grid_build_ctx_t *) arg;
|
|
1126
|
+
int8_t i;
|
|
1127
|
+
|
|
1128
|
+
for (i = 0; i < c->ca->ndim; i++) {
|
|
1129
|
+
CArray *ci = c->ci[i];
|
|
1130
|
+
if ( ! ci ) {
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
c->protos[i].kind = CAG_AXIS_INDEX;
|
|
1134
|
+
c->protos[i].count = ci->elements;
|
|
1135
|
+
c->protos[i].indices = (ca_size_t *) ci->ptr;
|
|
1136
|
+
c->protos[i].holes = NULL;
|
|
1137
|
+
if ( ca_is_any_masked(ci) ) {
|
|
1138
|
+
/* A masked index cell selects nothing: its position stays, as a hole
|
|
1139
|
+
(masked on read, skipped on write). setup copies the mask into
|
|
1140
|
+
its own buffer. */
|
|
1141
|
+
c->protos[i].holes = (uint8_t *) ci->mask->ptr;
|
|
1142
|
+
}
|
|
1143
|
+
c->protos[i].start = 0;
|
|
1144
|
+
c->protos[i].step = 0;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
return rb_ca_grid_new(c->self, c->ca->ndim, c->protos);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/* A scalar key (an Integer or a Float) picks one cell along its axis, and that axis is
|
|
1151
|
+
not in the result -- as it is not in a block reference. The view is
|
|
1152
|
+
built with the axis at length 1 and the axis then dropped. */
|
|
1153
|
+
static VALUE
|
|
1154
|
+
ca_grid_drop_scalar_axes (VALUE obj, int argc, VALUE *argv)
|
|
1155
|
+
{
|
|
1156
|
+
VALUE idx[CA_RANK_MAX];
|
|
1157
|
+
int i, any = 0;
|
|
1158
|
+
for (i = 0; i < argc; i++) {
|
|
1159
|
+
if ( ca_index_key_is_scalar(argv[i]) ) {
|
|
1160
|
+
idx[i] = INT2FIX(0);
|
|
1161
|
+
any = 1;
|
|
1162
|
+
}
|
|
1163
|
+
else {
|
|
1164
|
+
idx[i] = Qnil;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if ( ! any ) {
|
|
1168
|
+
return obj;
|
|
1169
|
+
}
|
|
1170
|
+
return rb_ca_fetch2(obj, argc, idx);
|
|
825
1171
|
}
|
|
826
1172
|
|
|
1173
|
+
/* ca[k0, k1, ...] with a CArray among the keys. An integer CArray picks
|
|
1174
|
+
the cells it lists along its axis, a boolean one the cells it marks (it
|
|
1175
|
+
must be as long as the axis). Every other key is read as the indexer
|
|
1176
|
+
reads it (ca_index_axis_key): an Integer picks one cell and drops the
|
|
1177
|
+
axis, a Range / ArithmeticSequence / Array form a run, nil the axis. */
|
|
827
1178
|
VALUE
|
|
828
1179
|
rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
829
1180
|
{
|
|
830
|
-
volatile VALUE obj,
|
|
1181
|
+
volatile VALUE obj, rval;
|
|
831
1182
|
volatile VALUE list = rb_ary_new();
|
|
832
1183
|
CArray *ca;
|
|
833
1184
|
CArray *ci[CA_RANK_MAX]; /* CAWrap holders for INDEX axes; NULL for STRIDE */
|
|
834
1185
|
cag_axis_t protos[CA_RANK_MAX];
|
|
1186
|
+
VALUE expanded[CA_RANK_MAX];
|
|
1187
|
+
long n;
|
|
835
1188
|
ca_size_t i;
|
|
836
1189
|
|
|
837
|
-
/* Dispatch hook: route mixed AP + single boolean to CASelectAxis
|
|
838
|
-
(slab-copy optimised path). Falls through to per-cell CAGrid gather
|
|
839
|
-
when not eligible (integer index, multiple INDIRECT axes, indirect
|
|
840
|
-
not on axis 0). Inline argv[0] type check avoids the function call
|
|
841
|
-
when axis 0 is nil/Integer (most patterns with INDIRECT on inner axes). */
|
|
842
|
-
extern int ca_csa_dispatch_bypass;
|
|
843
|
-
if ( ! ca_csa_dispatch_bypass && argc > 0 && TYPE(argv[0]) == T_DATA ) {
|
|
844
|
-
if ( rb_ca_select_axis_eligible_p(argc, argv, self) ) {
|
|
845
|
-
return rb_ca_select_axis(argc, argv, self);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
|
|
849
1190
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
850
1191
|
|
|
851
|
-
|
|
1192
|
+
n = ca_index_expand_rubber(ca->ndim, argc, argv, expanded);
|
|
1193
|
+
if ( n >= 0 ) {
|
|
1194
|
+
argc = (int) n;
|
|
1195
|
+
argv = expanded;
|
|
1196
|
+
}
|
|
852
1197
|
|
|
853
|
-
if (
|
|
1198
|
+
if ( argc > ca->ndim ) {
|
|
854
1199
|
rb_raise(rb_eArgError, "# of arguments doesn't equal to the ndim");
|
|
855
1200
|
}
|
|
856
|
-
else if (
|
|
1201
|
+
else if ( argc < ca->ndim ) {
|
|
857
1202
|
volatile VALUE ref;
|
|
858
1203
|
CArray *cv;
|
|
859
1204
|
ca_size_t rdim[CA_RANK_MAX];
|
|
860
|
-
ca_size_t rndim =
|
|
1205
|
+
ca_size_t rndim = argc;
|
|
861
1206
|
ca_size_t j = 0, k;
|
|
862
1207
|
for (i=0; i<rndim; i++) {
|
|
863
|
-
rval =
|
|
1208
|
+
rval = argv[i];
|
|
864
1209
|
if ( rb_obj_is_carray(rval) ) {
|
|
865
1210
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
866
1211
|
rdim[i] = 1;
|
|
867
1212
|
for (k=0; k<cv->ndim; k++) {
|
|
1213
|
+
if ( j >= ca->ndim ) {
|
|
1214
|
+
rb_raise(rb_eArgError, "invalid total ndim of args");
|
|
1215
|
+
}
|
|
868
1216
|
rdim[i] *= ca->dim[j];
|
|
869
1217
|
j += 1;
|
|
870
1218
|
}
|
|
@@ -881,87 +1229,69 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
881
1229
|
return rb_ca_grid(argc, argv, ref);
|
|
882
1230
|
}
|
|
883
1231
|
|
|
884
|
-
/*
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1232
|
+
/* Dispatch hook: route a boolean on axis 0 with plain keys elsewhere to
|
|
1233
|
+
CASelectAxis (slab-copy optimised path). Falls through to CAGrid when
|
|
1234
|
+
not eligible. The inline argv[0] type check avoids the call when axis
|
|
1235
|
+
0 is nil / Integer (most patterns with the CArray on an inner axis). */
|
|
1236
|
+
extern int ca_csa_dispatch_bypass;
|
|
1237
|
+
if ( ! ca_csa_dispatch_bypass && argc > 0 && TYPE(argv[0]) == T_DATA ) {
|
|
1238
|
+
if ( rb_ca_select_axis_eligible_p(argc, argv, self) ) {
|
|
1239
|
+
return ca_grid_drop_scalar_axes(rb_ca_select_axis(argc, argv, self),
|
|
1240
|
+
argc, argv);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
888
1244
|
for (i = 0; i < ca->ndim; i++) {
|
|
889
1245
|
ca_size_t dim_size = ca->dim[i];
|
|
890
|
-
rval =
|
|
1246
|
+
rval = argv[i];
|
|
891
1247
|
ci[i] = NULL;
|
|
892
|
-
if (
|
|
1248
|
+
if ( ! rb_obj_is_carray(rval) ) {
|
|
1249
|
+
ca_size_t start, count, step;
|
|
1250
|
+
ca_index_axis_key(rval, dim_size, (int) i, &start, &count, &step);
|
|
893
1251
|
protos[i].kind = CAG_AXIS_STRIDE;
|
|
894
|
-
protos[i].count =
|
|
895
|
-
protos[i].start =
|
|
896
|
-
protos[i].step =
|
|
1252
|
+
protos[i].count = count;
|
|
1253
|
+
protos[i].start = start;
|
|
1254
|
+
protos[i].step = step;
|
|
897
1255
|
protos[i].indices = NULL;
|
|
1256
|
+
protos[i].holes = NULL;
|
|
898
1257
|
continue;
|
|
899
1258
|
}
|
|
900
|
-
if (
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
continue;
|
|
909
|
-
}
|
|
910
|
-
/* fallback: materialise to integer array */
|
|
911
|
-
rval = rb_funcall(rb_mKernel, rb_intern("CA_SIZE"), 1, rval);
|
|
912
|
-
}
|
|
913
|
-
else if ( rb_obj_is_carray(rval) ) {
|
|
914
|
-
if ( rb_ca_is_boolean_type(rval) ) {
|
|
915
|
-
rval = rb_ca_where(rval);
|
|
1259
|
+
if ( rb_ca_is_boolean_type(rval) ) {
|
|
1260
|
+
CArray *cb;
|
|
1261
|
+
TypedData_Get_Struct(rval, CArray, &carray_data_type, cb);
|
|
1262
|
+
if ( cb->elements != dim_size ) {
|
|
1263
|
+
rb_raise(rb_eArgError,
|
|
1264
|
+
"mismatch of # of elements ( %lld <=> %lld ) in reference "
|
|
1265
|
+
"by selection on axis %d",
|
|
1266
|
+
(long long) cb->elements, (long long) dim_size, (int) i);
|
|
916
1267
|
}
|
|
917
|
-
|
|
918
|
-
else if ( TYPE(rval) == T_ARRAY ) {
|
|
919
|
-
rb_raise(rb_eRuntimeError, "not implemented for this index");
|
|
1268
|
+
rval = rb_ca_where(rval);
|
|
920
1269
|
}
|
|
921
1270
|
|
|
922
|
-
/* INDEX axis */
|
|
1271
|
+
/* INDEX axis: converted here, read once the window below opens */
|
|
1272
|
+
ca_check_index_array(rval);
|
|
923
1273
|
ci[i] = ca_wrap_readonly(rval, CA_SIZE);
|
|
924
1274
|
rb_ary_push(list, rval);
|
|
925
|
-
ca_attach(ci[i]);
|
|
926
|
-
|
|
927
|
-
protos[i].kind = CAG_AXIS_INDEX;
|
|
928
|
-
if ( ca_is_any_masked(ci[i]) ) {
|
|
929
|
-
/* mask-filtered snapshot: skip masked cells. We point protos[i]
|
|
930
|
-
.indices at a temp buffer alloc'd here and freed after setup
|
|
931
|
-
copies it (setup snapshots into its own ALLOC). Caller-side
|
|
932
|
-
lifetime: the temp lives until ca_grid_new returns. */
|
|
933
|
-
ca_size_t gsize = ci[i]->elements - ca_count_masked(ci[i]);
|
|
934
|
-
ca_size_t *src = (ca_size_t *) ci[i]->ptr;
|
|
935
|
-
boolean8_t *m = (boolean8_t *) ci[i]->mask->ptr;
|
|
936
|
-
ca_size_t *tmp = ALLOC_N(ca_size_t, gsize > 0 ? gsize : 1);
|
|
937
|
-
ca_size_t j, n = 0;
|
|
938
|
-
for (j = 0; j < ci[i]->elements; j++) {
|
|
939
|
-
if ( ! m[j] ) tmp[n++] = src[j];
|
|
940
|
-
}
|
|
941
|
-
protos[i].count = gsize;
|
|
942
|
-
protos[i].indices = tmp;
|
|
943
|
-
} else {
|
|
944
|
-
protos[i].count = ci[i]->elements;
|
|
945
|
-
protos[i].indices = (ca_size_t *) ci[i]->ptr;
|
|
946
|
-
}
|
|
947
|
-
protos[i].start = 0;
|
|
948
|
-
protos[i].step = 0;
|
|
949
1275
|
}
|
|
950
1276
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1277
|
+
/* The index arrays are read with all of them attached, and building
|
|
1278
|
+
the view checks every index against the parent -- an index out of
|
|
1279
|
+
range raises there. So the reads and the build are a window body,
|
|
1280
|
+
which detaches the caller's index arrays however it ends. */
|
|
1281
|
+
{
|
|
1282
|
+
ca_grid_build_ctx_t c;
|
|
1283
|
+
char modes[CA_RANK_MAX + 1];
|
|
1284
|
+
memset(modes, 'r', (size_t) ca->ndim);
|
|
1285
|
+
modes[ca->ndim] = '\0';
|
|
1286
|
+
c.self = self;
|
|
1287
|
+
c.ca = ca;
|
|
1288
|
+
c.ci = ci;
|
|
1289
|
+
c.protos = protos;
|
|
1290
|
+
obj = ca_attach_window(ca->ndim, ci, modes, ca_grid_build_body,
|
|
1291
|
+
(VALUE) &c);
|
|
962
1292
|
}
|
|
963
1293
|
|
|
964
|
-
return obj;
|
|
1294
|
+
return ca_grid_drop_scalar_axes(obj, argc, argv);
|
|
965
1295
|
}
|
|
966
1296
|
|
|
967
1297
|
static VALUE
|
|
@@ -977,14 +1307,17 @@ rb_ca_grid_initialize_copy (VALUE self, VALUE other)
|
|
|
977
1307
|
CAGrid *ca, *cs;
|
|
978
1308
|
|
|
979
1309
|
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1310
|
+
ca_check_uninitialized(ca);
|
|
980
1311
|
TypedData_Get_Struct(other, CAGrid, &cagrid_data_type, cs);
|
|
981
1312
|
|
|
982
1313
|
if ( ca_func[CA_OBJ_GRID].pool_init ) {
|
|
983
1314
|
ca_array_pool_alloc(ca, CA_OBJ_GRID, cs->ndim);
|
|
984
1315
|
}
|
|
985
|
-
/*
|
|
986
|
-
|
|
987
|
-
|
|
1316
|
+
/* Copy the axes: the source may be collected before the copy. */
|
|
1317
|
+
ca_grid_setup(ca, cs->parent, cs->ndim, cs->axes, 0);
|
|
1318
|
+
ca->holes_read_masked = cs->holes_read_masked;
|
|
1319
|
+
ca->mask_owner = cs->mask_owner;
|
|
1320
|
+
ca_grid_inherit_mask((VALUE) ca);
|
|
988
1321
|
|
|
989
1322
|
return self;
|
|
990
1323
|
}
|
|
@@ -1087,7 +1420,7 @@ rb_ca_grid_dispatch_attach_debug (VALUE self)
|
|
|
1087
1420
|
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1088
1421
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
1089
1422
|
|
|
1090
|
-
ca_attach(ca->parent);
|
|
1423
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
1091
1424
|
buf = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1092
1425
|
ca->elements, NULL);
|
|
1093
1426
|
ca_detach(ca->parent);
|
|
@@ -1118,11 +1451,10 @@ rb_ca_grid_dispatch_scatter_debug (VALUE self, VALUE in_str)
|
|
|
1118
1451
|
ca_size_t pdims[CA_RANK_MAX];
|
|
1119
1452
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
1120
1453
|
|
|
1121
|
-
ca_attach(ca->parent);
|
|
1454
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
1122
1455
|
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1123
1456
|
ca->elements, RSTRING_PTR(in_str));
|
|
1124
|
-
|
|
1125
|
-
ca_detach(ca->parent);
|
|
1457
|
+
ca_sync_detach(ca->parent);
|
|
1126
1458
|
return Qnil;
|
|
1127
1459
|
}
|
|
1128
1460
|
|
|
@@ -1145,11 +1477,10 @@ rb_ca_grid_dispatch_fill_value_debug (VALUE self, VALUE val_str)
|
|
|
1145
1477
|
ca_size_t pdims[CA_RANK_MAX];
|
|
1146
1478
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
1147
1479
|
|
|
1148
|
-
ca_attach(ca->parent);
|
|
1480
|
+
ca_attach(ca->parent); /* window: nothing raises inside */
|
|
1149
1481
|
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1150
1482
|
ca->elements, RSTRING_PTR(val_str));
|
|
1151
|
-
|
|
1152
|
-
ca_detach(ca->parent);
|
|
1483
|
+
ca_sync_detach(ca->parent);
|
|
1153
1484
|
return Qnil;
|
|
1154
1485
|
}
|
|
1155
1486
|
#endif /* CARRAY_DEV_BUILD */
|