carray 3.0.3 → 3.0.5
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 +469 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +14 -26
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +231 -153
- data/ext/ca_compare.c +9 -20
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1240 -2000
- data/ext/ca_kernel_iterator.h +502 -519
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +152 -45
- data/ext/ca_obj_bincmp.c +25 -21
- data/ext/ca_obj_binop.c +16 -26
- data/ext/ca_obj_bitarray.c +8 -3
- data/ext/ca_obj_bitfield.c +63 -49
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +7 -7
- data/ext/ca_obj_const_string.c +188 -22
- data/ext/ca_obj_face.c +280 -58
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +30 -8
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +455 -134
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +113 -67
- data/ext/ca_obj_object.c +210 -52
- data/ext/ca_obj_record.c +15 -7
- data/ext/ca_obj_reduce.c +17 -8
- data/ext/ca_obj_refer.c +42 -35
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +31 -10
- data/ext/ca_obj_select.c +48 -14
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +41 -7
- data/ext/ca_obj_stack.c +180 -34
- data/ext/ca_obj_stride.c +190 -134
- data/ext/ca_obj_string.c +80 -4
- data/ext/ca_obj_tile.c +32 -11
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +13 -7
- data/ext/ca_obj_triop.c +26 -32
- data/ext/ca_obj_window.c +267 -74
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +214 -75
- data/ext/carray_access.c +200 -99
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +113 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +375 -96
- data/ext/carray_cast_func.rb +90 -20
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +18 -9
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +150 -55
- data/ext/carray_count.c +56 -20
- data/ext/carray_element.c +81 -33
- data/ext/carray_factorize.c +138 -84
- data/ext/carray_generate.c +199 -52
- data/ext/carray_histogram.c +63 -18
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +348 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10897 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +220 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +337 -94
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +129 -52
- data/ext/carray_order.c +604 -77
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +85 -31
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +87 -45
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +123 -37
- data/ext/carray_sort.c +259 -51
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +54 -61
- data/ext/carray_test.c +26 -5
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +309 -66
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +403 -350
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +139 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +105 -17
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +195 -59
- data/lib/carray/categorical_iterator.rb +132 -29
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +24 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +9 -1
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +48 -3
- data/lib/carray/frame/column_verbs.rb +71 -0
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +252 -28
- data/lib/carray/frame/group.rb +603 -101
- data/lib/carray/frame/io.rb +117 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +42 -6
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +217 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +61 -37
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +323 -88
- data/lib/carray/serialize.rb +45 -14
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +113 -5
- data/lib/carray/string_operation_extension.rb +21 -6
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +24 -11
- data/lib/carray/time.rb +819 -158
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +3 -6
- data/yard-stubs/carray_cast.rb +12 -0
- data/yard-stubs/carray_conversion.rb +7 -2
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +17 -10
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +32 -3
- data/yard-stubs/carray_math.rb +41 -5
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +129 -22
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +17 -10
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_obj_grid.c
CHANGED
|
@@ -35,9 +35,14 @@ typedef struct {
|
|
|
35
35
|
/* INDEX-only. Owned in the non-share case (xfree'd by free_ca_grid),
|
|
36
36
|
aliased in the share case (parent owns; CA_FLAG_SHARE_INDEX). */
|
|
37
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;
|
|
38
43
|
} cag_axis_t;
|
|
39
44
|
|
|
40
|
-
typedef struct {
|
|
45
|
+
typedef struct _CAGrid {
|
|
41
46
|
int16_t obj_type;
|
|
42
47
|
int8_t data_type;
|
|
43
48
|
int8_t ndim;
|
|
@@ -53,6 +58,18 @@ typedef struct {
|
|
|
53
58
|
uint8_t nosync;
|
|
54
59
|
/* -------------*/
|
|
55
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;
|
|
56
73
|
} CAGrid;
|
|
57
74
|
|
|
58
75
|
static size_t
|
|
@@ -70,6 +87,9 @@ ca_grid_dsize (const void *ap)
|
|
|
70
87
|
if (ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices) {
|
|
71
88
|
total += ca->axes[k].count * sizeof(ca_size_t);
|
|
72
89
|
}
|
|
90
|
+
if (ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].holes) {
|
|
91
|
+
total += ca->axes[k].count;
|
|
92
|
+
}
|
|
73
93
|
}
|
|
74
94
|
return total;
|
|
75
95
|
}
|
|
@@ -160,13 +180,15 @@ ca_grid_check_protos (CArray *parent, int8_t ndim, const cag_axis_t *protos)
|
|
|
160
180
|
if (protos[k].kind == CAG_AXIS_STRIDE) {
|
|
161
181
|
ca_size_t first = protos[k].start;
|
|
162
182
|
ca_size_t last = first + (protos[k].count - 1) * protos[k].step;
|
|
163
|
-
|
|
164
|
-
if (protos[k].count > 1)
|
|
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);
|
|
165
185
|
}
|
|
166
186
|
else {
|
|
167
187
|
for (j = 0; j < protos[k].count; j++) {
|
|
168
|
-
|
|
169
|
-
|
|
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);
|
|
170
192
|
}
|
|
171
193
|
}
|
|
172
194
|
}
|
|
@@ -207,6 +229,9 @@ ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
|
207
229
|
ca->parent = parent;
|
|
208
230
|
ca->attach = 0;
|
|
209
231
|
ca->nosync = 0;
|
|
232
|
+
ca->holes_read_masked = 0;
|
|
233
|
+
ca->mask_standin = NULL;
|
|
234
|
+
ca->mask_owner = NULL;
|
|
210
235
|
|
|
211
236
|
for (k = 0; k < ndim; k++) ca->dim[k] = protos[k].count;
|
|
212
237
|
|
|
@@ -217,7 +242,9 @@ ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
|
217
242
|
ca_set_flag(ca, CA_FLAG_SHARE_INDEX);
|
|
218
243
|
ca->axes = protos;
|
|
219
244
|
} else {
|
|
220
|
-
|
|
245
|
+
/* Zeroed: an axis's indices or holes that cannot be allocated raises
|
|
246
|
+
with the later axes not yet copied, and free_ca_grid reads them. */
|
|
247
|
+
ca->axes = ZALLOC_N(cag_axis_t, ndim);
|
|
221
248
|
for (k = 0; k < ndim; k++) {
|
|
222
249
|
ca->axes[k].kind = protos[k].kind;
|
|
223
250
|
ca->axes[k].count = protos[k].count;
|
|
@@ -225,42 +252,126 @@ ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
|
225
252
|
ca->axes[k].start = protos[k].start;
|
|
226
253
|
ca->axes[k].step = protos[k].step;
|
|
227
254
|
ca->axes[k].indices = NULL;
|
|
255
|
+
ca->axes[k].holes = NULL;
|
|
228
256
|
} else {
|
|
229
257
|
ca->axes[k].start = 0;
|
|
230
258
|
ca->axes[k].step = 0;
|
|
231
259
|
ca->axes[k].indices = ALLOC_N(ca_size_t,
|
|
232
260
|
protos[k].count > 0 ? protos[k].count : 1);
|
|
261
|
+
ca->axes[k].holes = NULL;
|
|
233
262
|
ca_size_t j;
|
|
263
|
+
if ( protos[k].holes ) {
|
|
264
|
+
for (j = 0; j < protos[k].count && ! protos[k].holes[j]; j++) ;
|
|
265
|
+
if ( j < protos[k].count ) {
|
|
266
|
+
ca->axes[k].holes = ALLOC_N(uint8_t, protos[k].count);
|
|
267
|
+
memcpy(ca->axes[k].holes, protos[k].holes, protos[k].count);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
234
270
|
for (j = 0; j < protos[k].count; j++) {
|
|
235
271
|
ca_size_t v = protos[k].indices[j];
|
|
272
|
+
if ( ca->axes[k].holes && ca->axes[k].holes[j] ) {
|
|
273
|
+
ca->axes[k].indices[j] = 0;
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
236
276
|
ca->axes[k].indices[j] = ( v < 0 ) ? v + parent->dim[k] : v;
|
|
237
277
|
}
|
|
238
278
|
}
|
|
239
279
|
}
|
|
240
280
|
}
|
|
241
281
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
282
|
+
return 0;
|
|
283
|
+
}
|
|
245
284
|
|
|
285
|
+
/* Whether any position of the grid is a hole (cag_axis_t.holes). */
|
|
286
|
+
static int
|
|
287
|
+
cag_has_holes (const CAGrid *ca)
|
|
288
|
+
{
|
|
289
|
+
int8_t k;
|
|
290
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
291
|
+
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].holes ) {
|
|
292
|
+
return 1;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
246
295
|
return 0;
|
|
247
296
|
}
|
|
248
297
|
|
|
249
|
-
|
|
250
|
-
|
|
298
|
+
int
|
|
299
|
+
ca_grid_has_holes (void *ap)
|
|
300
|
+
{
|
|
301
|
+
return cag_has_holes((const CAGrid *) ap);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* A grid with holes has a mask from the start: its holes read as masked
|
|
305
|
+
whatever the parent holds. A mask grid (holes_read_masked) takes none.
|
|
306
|
+
A view of a value array or a mask array can never carry a mask, so it
|
|
307
|
+
can not show a hole. */
|
|
308
|
+
static VALUE
|
|
309
|
+
ca_grid_inherit_mask (VALUE view)
|
|
310
|
+
{
|
|
311
|
+
CAGrid *ca = (CAGrid *) view;
|
|
312
|
+
if ( cag_has_holes(ca) && ! ca->holes_read_masked ) {
|
|
313
|
+
if ( ca_is_value_array(ca) || ca_is_mask_array(ca) ) {
|
|
314
|
+
rb_raise(rb_eArgError,
|
|
315
|
+
"a masked index cell reads as masked, which a view of the %s "
|
|
316
|
+
"array can not hold", ca_is_value_array(ca) ? "value" : "mask");
|
|
317
|
+
}
|
|
318
|
+
ca_create_mask((CArray *) ca);
|
|
319
|
+
return Qnil;
|
|
320
|
+
}
|
|
321
|
+
return ca_view_inherit_mask(view);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
typedef struct {
|
|
325
|
+
CAGrid *ca;
|
|
326
|
+
CArray *parent;
|
|
327
|
+
int8_t ndim;
|
|
328
|
+
cag_axis_t *protos;
|
|
329
|
+
} ca_grid_new_arg;
|
|
330
|
+
|
|
331
|
+
static VALUE
|
|
332
|
+
ca_grid_new_setup (VALUE varg)
|
|
333
|
+
{
|
|
334
|
+
ca_grid_new_arg *a = (ca_grid_new_arg *) varg;
|
|
335
|
+
ca_grid_setup(a->ca, a->parent, a->ndim, a->protos, 0);
|
|
336
|
+
return Qnil;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* holes_read_masked is the copied grid's: a copy of a mask grid is one.
|
|
340
|
+
The setup allocates the axes after the struct and its pool: when that
|
|
341
|
+
fails, the struct goes too. */
|
|
342
|
+
static CAGrid *
|
|
343
|
+
ca_grid_new_as (CArray *parent, int8_t ndim, cag_axis_t *protos,
|
|
344
|
+
int8_t holes_read_masked, CAGrid *mask_owner)
|
|
251
345
|
{
|
|
252
346
|
CAGrid *ca;
|
|
347
|
+
ca_grid_new_arg a;
|
|
253
348
|
ca_grid_check_protos(parent, ndim, protos);
|
|
349
|
+
/* check: ca_grid_check_protos above */
|
|
254
350
|
ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
255
|
-
|
|
351
|
+
a.ca = ca;
|
|
352
|
+
a.parent = parent;
|
|
353
|
+
a.ndim = ndim;
|
|
354
|
+
a.protos = protos;
|
|
355
|
+
ca_fill_or_free((CArray *) ca, ca_grid_new_setup, (VALUE) &a);
|
|
356
|
+
ca->holes_read_masked = holes_read_masked;
|
|
357
|
+
ca->mask_owner = mask_owner;
|
|
358
|
+
ca_fill_or_free((CArray *) ca, ca_grid_inherit_mask, (VALUE) ca);
|
|
256
359
|
return ca;
|
|
257
360
|
}
|
|
258
361
|
|
|
362
|
+
CAGrid *
|
|
363
|
+
ca_grid_new (CArray *parent, int8_t ndim, cag_axis_t *protos)
|
|
364
|
+
{
|
|
365
|
+
return ca_grid_new_as(parent, ndim, protos, 0, NULL);
|
|
366
|
+
}
|
|
367
|
+
|
|
259
368
|
CAGrid *
|
|
260
369
|
ca_grid_new_share (CArray *parent, int8_t ndim, cag_axis_t *protos)
|
|
261
370
|
{
|
|
371
|
+
/* check: the mask grid copies its own grid's checked axes */
|
|
262
372
|
CAGrid *ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
263
373
|
ca_grid_setup(ca, parent, ndim, protos, 1);
|
|
374
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
264
375
|
return ca;
|
|
265
376
|
}
|
|
266
377
|
|
|
@@ -270,12 +381,16 @@ free_ca_grid (void *ap)
|
|
|
270
381
|
CAGrid *ca = (CAGrid *) ap;
|
|
271
382
|
if ( ca != NULL ) {
|
|
272
383
|
ca_free(ca->mask);
|
|
273
|
-
|
|
384
|
+
ca_free(ca->mask_standin);
|
|
385
|
+
if ( ! (ca->flags & CA_FLAG_SHARE_INDEX) && ca->axes ) {
|
|
274
386
|
int8_t k;
|
|
275
387
|
for (k = 0; k < ca->ndim; k++) {
|
|
276
388
|
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices ) {
|
|
277
389
|
xfree(ca->axes[k].indices);
|
|
278
390
|
}
|
|
391
|
+
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].holes ) {
|
|
392
|
+
xfree(ca->axes[k].holes);
|
|
393
|
+
}
|
|
279
394
|
}
|
|
280
395
|
xfree(ca->axes);
|
|
281
396
|
}
|
|
@@ -301,7 +416,8 @@ static void *
|
|
|
301
416
|
ca_grid_func_clone (void *ap)
|
|
302
417
|
{
|
|
303
418
|
CAGrid *ca = (CAGrid *) ap;
|
|
304
|
-
return
|
|
419
|
+
return ca_grid_new_as(ca->parent, ca->ndim, ca->axes, ca->holes_read_masked,
|
|
420
|
+
ca->mask_owner);
|
|
305
421
|
}
|
|
306
422
|
|
|
307
423
|
/* Per-axis parent-index lookup. STRIDE = one multiply, INDEX = one
|
|
@@ -315,6 +431,124 @@ cag_parent_index_for (const cag_axis_t *ax, ca_size_t i)
|
|
|
315
431
|
return ax->indices[i];
|
|
316
432
|
}
|
|
317
433
|
|
|
434
|
+
/* A mask grid over its owner's stand-in (ca_mask_standin_current): what
|
|
435
|
+
it reads from now on. */
|
|
436
|
+
static void
|
|
437
|
+
cag_mask_current (CAGrid *m)
|
|
438
|
+
{
|
|
439
|
+
CAGrid *o = m->mask_owner;
|
|
440
|
+
if ( o != NULL ) {
|
|
441
|
+
m->parent = ca_mask_standin_current((CArray *) m, m->parent, o->parent,
|
|
442
|
+
o->mask_standin);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/* After a write of n cells of `data` to a mask grid: a true that went
|
|
447
|
+
into the stand-in goes on to the parent's mask. */
|
|
448
|
+
static void
|
|
449
|
+
cag_mask_settle_after (CAGrid *m, const void *data, ca_size_t n)
|
|
450
|
+
{
|
|
451
|
+
CAGrid *o = m->mask_owner;
|
|
452
|
+
if ( o != NULL && m->parent == o->mask_standin && ca_mask_any_true(data, n) ) {
|
|
453
|
+
ca_mask_standin_settle(o->parent, o->mask_standin);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/* What the GET of a hole writes when it reads no parent cell: true in a
|
|
458
|
+
mask grid, an empty cell otherwise (a parent with no cell to read). */
|
|
459
|
+
static void
|
|
460
|
+
cag_hole_cells (const CAGrid *ca, char *data, ca_size_t n)
|
|
461
|
+
{
|
|
462
|
+
ca_size_t i;
|
|
463
|
+
if ( ca->holes_read_masked ) {
|
|
464
|
+
memset(data, 1, (size_t) n);
|
|
465
|
+
}
|
|
466
|
+
else if ( ca->data_type == CA_OBJECT ) {
|
|
467
|
+
for (i = 0; i < n; i++) ((VALUE *) data)[i] = INT2FIX(0);
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
memset(data, 0, (size_t) (n * ca->bytes));
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/* The parent address of the view cell at idx. A hole takes index 0 on its
|
|
475
|
+
holed axes; the return says whether the cell is one. */
|
|
476
|
+
static int
|
|
477
|
+
cag_parent_addr (const CAGrid *ca, const ca_size_t *idx, ca_size_t *paddr)
|
|
478
|
+
{
|
|
479
|
+
ca_size_t pa = 0;
|
|
480
|
+
int hole = 0;
|
|
481
|
+
int8_t k;
|
|
482
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
483
|
+
const cag_axis_t *ax = &ca->axes[k];
|
|
484
|
+
if ( ax->kind == CAG_AXIS_INDEX && ax->holes && ax->holes[idx[k]] ) {
|
|
485
|
+
hole = 1;
|
|
486
|
+
}
|
|
487
|
+
pa = pa * ca->parent->dim[k] + cag_parent_index_for(ax, idx[k]);
|
|
488
|
+
}
|
|
489
|
+
*paddr = pa;
|
|
490
|
+
return hole;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/* The transfer of a grid with holes, for the view cells at addrs (NULL:
|
|
494
|
+
the whole view in order). The parent is asked for one batch of
|
|
495
|
+
addresses. A GET reads every cell, a hole reading the cell at index 0
|
|
496
|
+
of its holed axes (in a mask grid it is then set true); a PUT leaves
|
|
497
|
+
the holes out. */
|
|
498
|
+
static void
|
|
499
|
+
ca_grid_holed_xfer (CAGrid *ca, ca_size_t n, const ca_size_t *addrs,
|
|
500
|
+
char *data, int dir)
|
|
501
|
+
{
|
|
502
|
+
CArray *parent;
|
|
503
|
+
ca_size_t bytes = ca->bytes;
|
|
504
|
+
volatile VALUE h_addr = 0, h_hole = 0, h_data = 0;
|
|
505
|
+
ca_size_t *paddrs;
|
|
506
|
+
uint8_t *hole;
|
|
507
|
+
ca_size_t i, m, idx[CA_RANK_MAX];
|
|
508
|
+
|
|
509
|
+
if ( n <= 0 ) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
cag_mask_current(ca);
|
|
513
|
+
parent = ca->parent;
|
|
514
|
+
paddrs = ALLOCV_N(ca_size_t, h_addr, n);
|
|
515
|
+
hole = ALLOCV_N(uint8_t, h_hole, n);
|
|
516
|
+
for (i = 0; i < n; i++) {
|
|
517
|
+
ca_addr2index((CArray *) ca, addrs ? addrs[i] : i, idx);
|
|
518
|
+
hole[i] = (uint8_t) cag_parent_addr(ca, idx, &paddrs[i]);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if ( dir == CA_XFER_GET ) {
|
|
522
|
+
if ( parent->elements == 0 ) {
|
|
523
|
+
cag_hole_cells(ca, data, n); /* every cell is a hole */
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
ca_xfer_addrs(parent, n, paddrs, data, CA_XFER_GET);
|
|
527
|
+
if ( ca->holes_read_masked ) {
|
|
528
|
+
for (i = 0; i < n; i++) {
|
|
529
|
+
if ( hole[i] ) cag_hole_cells(ca, data + i * bytes, 1);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
char *pdata = ALLOCV_N(char, h_data, n * bytes);
|
|
536
|
+
for (i = 0, m = 0; i < n; i++) {
|
|
537
|
+
if ( hole[i] ) continue;
|
|
538
|
+
paddrs[m] = paddrs[i];
|
|
539
|
+
memcpy(pdata + m * bytes, data + i * bytes, (size_t) bytes);
|
|
540
|
+
m++;
|
|
541
|
+
}
|
|
542
|
+
if ( m > 0 ) {
|
|
543
|
+
ca_xfer_addrs(parent, m, paddrs, pdata, CA_XFER_PUT);
|
|
544
|
+
cag_mask_settle_after(ca, pdata, m);
|
|
545
|
+
}
|
|
546
|
+
ALLOCV_END(h_data);
|
|
547
|
+
}
|
|
548
|
+
ALLOCV_END(h_hole);
|
|
549
|
+
ALLOCV_END(h_addr);
|
|
550
|
+
}
|
|
551
|
+
|
|
318
552
|
/* per-cell logic lives in ca_grid_func_xfer_index; forward-declared for
|
|
319
553
|
the region-delivery paths below. */
|
|
320
554
|
static void ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir);
|
|
@@ -327,10 +561,28 @@ ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
327
561
|
CAGrid *ca = (CAGrid *) ap;
|
|
328
562
|
ca_size_t idx0[CA_RANK_MAX];
|
|
329
563
|
int8_t i;
|
|
564
|
+
int hole = 0;
|
|
330
565
|
for (i = 0; i < ca->ndim; i++) {
|
|
331
|
-
|
|
566
|
+
const cag_axis_t *ax = &ca->axes[i];
|
|
567
|
+
idx0[i] = cag_parent_index_for(ax, idx[i]);
|
|
568
|
+
if ( ax->kind == CAG_AXIS_INDEX && ax->holes && ax->holes[idx[i]] ) {
|
|
569
|
+
hole = 1;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if ( hole ) {
|
|
573
|
+
if ( dir == CA_XFER_PUT ) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
if ( ca->holes_read_masked || ca->parent->elements == 0 ) {
|
|
577
|
+
cag_hole_cells(ca, (char *) data, 1);
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
332
580
|
}
|
|
581
|
+
cag_mask_current(ca);
|
|
333
582
|
ca_xfer_index(ca->parent, idx0, data, dir);
|
|
583
|
+
if ( dir == CA_XFER_PUT ) {
|
|
584
|
+
cag_mask_settle_after(ca, data, 1);
|
|
585
|
+
}
|
|
334
586
|
}
|
|
335
587
|
|
|
336
588
|
/* Batched address gather/scatter. Per-axis index remap
|
|
@@ -354,6 +606,11 @@ ca_grid_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
354
606
|
int8_t k;
|
|
355
607
|
volatile VALUE holder;
|
|
356
608
|
|
|
609
|
+
if ( cag_has_holes(ca) ) {
|
|
610
|
+
ca_grid_holed_xfer(ca, n, addrs, (char *) data, dir);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
|
|
357
614
|
/* Opportunistic fast path. ca_resolve_attached_root_via_identity lifts
|
|
358
615
|
parent->ptr through an identity CAStride compose-fold (handles a
|
|
359
616
|
flatten[idx].reshape(*) chain etc.). */
|
|
@@ -409,8 +666,9 @@ ca_grid_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
409
666
|
int8_t k;
|
|
410
667
|
|
|
411
668
|
for (k = 0; k < g->ndim; k++) {
|
|
412
|
-
if (g->axes[k].kind == CAG_AXIS_INDEX
|
|
413
|
-
|
|
669
|
+
if (g->axes[k].kind == CAG_AXIS_INDEX
|
|
670
|
+
&& (g->axes[k].count != 1 || g->axes[k].holes)) {
|
|
671
|
+
return 0; /* multi-INDEX axis -> true gather, decline; a hole is no stride */
|
|
414
672
|
}
|
|
415
673
|
}
|
|
416
674
|
|
|
@@ -505,8 +763,9 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
505
763
|
/* The request is over the view's addresses, so a transposed / flat request
|
|
506
764
|
is legal and must not be composed axis-by-axis; see
|
|
507
765
|
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
508
|
-
if (
|
|
509
|
-
|
|
766
|
+
if ( cag_has_holes(g)
|
|
767
|
+
|| ! ca_xfer_stride_request_is_axis_box(g, starts, counts, strides) ) {
|
|
768
|
+
aligned = 0; /* a grid with holes goes cell by cell (xfer_index) */
|
|
510
769
|
}
|
|
511
770
|
else {
|
|
512
771
|
for (k = 0; k < ndim; k++) {
|
|
@@ -519,6 +778,7 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
519
778
|
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
520
779
|
for (k = 0; k < ndim; k++) base += starts[k] * gnative[k];
|
|
521
780
|
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
781
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
522
782
|
while (1) {
|
|
523
783
|
ca_size_t goff = base, gidx[CA_RANK_MAX];
|
|
524
784
|
for (k = 0; k < ndim; k++) goff += idx[k] * strides[k];
|
|
@@ -607,6 +867,7 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
607
867
|
ca_xfer_stride/ca_xfer_addrs. */
|
|
608
868
|
for (k = 0; k < ndim; k++) o[k] = 0;
|
|
609
869
|
|
|
870
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
610
871
|
while (1) {
|
|
611
872
|
ca_size_t pbase = 0, doff = 0;
|
|
612
873
|
for (k = 0; k < inner; k++) {
|
|
@@ -659,14 +920,22 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
659
920
|
The predicate asks what the parent is, not whether it is attached now,
|
|
660
921
|
so attach, sync and detach all take the same branch. */
|
|
661
922
|
|
|
923
|
+
/* A grid with holes fills and writes back its buffer through its own
|
|
924
|
+
transfers too: the descriptor engine has no hole. */
|
|
925
|
+
static int
|
|
926
|
+
cag_owns_buffer (CAGrid *ca)
|
|
927
|
+
{
|
|
928
|
+
return cag_has_holes(ca) || ca_parent_lends_no_memory(ca->parent);
|
|
929
|
+
}
|
|
930
|
+
|
|
662
931
|
static void
|
|
663
932
|
ca_grid_func_allocate (void *ap)
|
|
664
933
|
{
|
|
665
934
|
CAGrid *ca = (CAGrid *) ap;
|
|
666
|
-
if ( !
|
|
935
|
+
if ( ! cag_owns_buffer(ca) ) {
|
|
667
936
|
ca_attach(ca->parent);
|
|
668
937
|
}
|
|
669
|
-
ca->ptr =
|
|
938
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
670
939
|
}
|
|
671
940
|
|
|
672
941
|
static void
|
|
@@ -676,7 +945,7 @@ ca_grid_func_attach (void *ap)
|
|
|
676
945
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
677
946
|
ca_size_t pdims[CA_RANK_MAX];
|
|
678
947
|
|
|
679
|
-
if (
|
|
948
|
+
if ( cag_owns_buffer(ca) ) {
|
|
680
949
|
ca_axis_view_attach_owned(ca);
|
|
681
950
|
return;
|
|
682
951
|
}
|
|
@@ -694,7 +963,7 @@ ca_grid_func_sync (void *ap)
|
|
|
694
963
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
695
964
|
ca_size_t pdims[CA_RANK_MAX];
|
|
696
965
|
|
|
697
|
-
if (
|
|
966
|
+
if ( cag_owns_buffer(ca) ) {
|
|
698
967
|
ca_axis_view_sync_owned(ca);
|
|
699
968
|
return;
|
|
700
969
|
}
|
|
@@ -711,7 +980,7 @@ ca_grid_func_detach (void *ap)
|
|
|
711
980
|
CAGrid *ca = (CAGrid *) ap;
|
|
712
981
|
xfree(ca->ptr);
|
|
713
982
|
ca->ptr = NULL;
|
|
714
|
-
if ( !
|
|
983
|
+
if ( ! cag_owns_buffer(ca) ) {
|
|
715
984
|
ca_detach(ca->parent);
|
|
716
985
|
}
|
|
717
986
|
}
|
|
@@ -736,9 +1005,41 @@ ca_grid_func_run_fast_path (void *ap, char *data, int dir)
|
|
|
736
1005
|
static void
|
|
737
1006
|
ca_grid_func_xfer_all (void *ap, void *data, int dir)
|
|
738
1007
|
{
|
|
1008
|
+
CAGrid *ca = (CAGrid *) ap;
|
|
1009
|
+
if ( cag_has_holes(ca) ) {
|
|
1010
|
+
ca_grid_holed_xfer(ca, ca->elements, NULL, (char *) data, dir);
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
739
1013
|
ca_axis_view_xfer_all(ap, ca_grid_func_run_fast_path, 1, data, dir);
|
|
740
1014
|
}
|
|
741
1015
|
|
|
1016
|
+
/* The fill of a grid with holes: the parent cells of the positions that
|
|
1017
|
+
are not holes, as one address batch. */
|
|
1018
|
+
static void
|
|
1019
|
+
ca_grid_holed_fill (CAGrid *ca, void *ptr)
|
|
1020
|
+
{
|
|
1021
|
+
volatile VALUE holder = 0;
|
|
1022
|
+
ca_size_t *paddrs;
|
|
1023
|
+
ca_size_t i, m = 0, pa, idx[CA_RANK_MAX];
|
|
1024
|
+
|
|
1025
|
+
if ( ca->elements <= 0 ) {
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
cag_mask_current(ca);
|
|
1029
|
+
paddrs = ALLOCV_N(ca_size_t, holder, ca->elements);
|
|
1030
|
+
for (i = 0; i < ca->elements; i++) {
|
|
1031
|
+
ca_addr2index((CArray *) ca, i, idx);
|
|
1032
|
+
if ( ! cag_parent_addr(ca, idx, &pa) ) {
|
|
1033
|
+
paddrs[m++] = pa;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
if ( m > 0 ) {
|
|
1037
|
+
ca_fill_addrs(ca->parent, m, paddrs, ptr);
|
|
1038
|
+
cag_mask_settle_after(ca, ptr, 1);
|
|
1039
|
+
}
|
|
1040
|
+
ALLOCV_END(holder);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
742
1043
|
static void
|
|
743
1044
|
ca_grid_func_fill_data (void *ap, void *ptr)
|
|
744
1045
|
{
|
|
@@ -746,6 +1047,11 @@ ca_grid_func_fill_data (void *ap, void *ptr)
|
|
|
746
1047
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
747
1048
|
ca_size_t pdims[CA_RANK_MAX];
|
|
748
1049
|
|
|
1050
|
+
if ( cag_has_holes(ca) ) {
|
|
1051
|
+
ca_grid_holed_fill(ca, ptr);
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
749
1055
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
750
1056
|
|
|
751
1057
|
/* Writing the selected cells used to go through a whole-parent attach and
|
|
@@ -765,15 +1071,32 @@ ca_grid_func_fill_data (void *ap, void *ptr)
|
|
|
765
1071
|
ca_sync_detach(ca->parent);
|
|
766
1072
|
}
|
|
767
1073
|
|
|
1074
|
+
/* The mask is a grid over the parent's mask with the same axes, holes
|
|
1075
|
+
included; there the holes read as masked. */
|
|
768
1076
|
static void
|
|
769
1077
|
ca_grid_func_create_mask (void *ap)
|
|
770
1078
|
{
|
|
771
1079
|
CAGrid *ca = (CAGrid *) ap;
|
|
1080
|
+
CArray *mparent;
|
|
1081
|
+
int holed = cag_has_holes(ca);
|
|
1082
|
+
|
|
1083
|
+
/* A grid with holes shows them without giving a parent that has no mask
|
|
1084
|
+
one: its mask grid reads an all-false stand-in until a true is written
|
|
1085
|
+
outside the holes (ca_mask_standin_new). */
|
|
1086
|
+
if ( holed && ! ca_has_mask(ca->parent) ) {
|
|
1087
|
+
if ( ! ca->mask_standin ) {
|
|
1088
|
+
ca->mask_standin = ca_mask_standin_new(ca->parent);
|
|
1089
|
+
}
|
|
1090
|
+
mparent = ca->mask_standin;
|
|
1091
|
+
}
|
|
1092
|
+
else {
|
|
1093
|
+
ca_create_mask(ca->parent);
|
|
1094
|
+
mparent = ca->parent->mask;
|
|
1095
|
+
}
|
|
772
1096
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
ca->mask =
|
|
776
|
-
ca->ndim, ca->axes);
|
|
1097
|
+
ca->mask = (CArray *) ca_grid_new_share(mparent, ca->ndim, ca->axes);
|
|
1098
|
+
((CAGrid *) ca->mask)->holes_read_masked = (int8_t) holed;
|
|
1099
|
+
((CAGrid *) ca->mask)->mask_owner = holed ? ca : NULL;
|
|
777
1100
|
}
|
|
778
1101
|
|
|
779
1102
|
ca_operation_function_t ca_grid_func = {
|
|
@@ -810,41 +1133,6 @@ rb_ca_grid_new (VALUE cary, int8_t ndim, cag_axis_t *protos)
|
|
|
810
1133
|
return obj;
|
|
811
1134
|
}
|
|
812
1135
|
|
|
813
|
-
/* Detect a plain Ruby Range (Integer first/last, exclude_end?, step=1
|
|
814
|
-
implicit) and convert it to STRIDE (start, count, step=1).
|
|
815
|
-
Returns 1 on success (fills *out_start, *out_count), 0 on fallback
|
|
816
|
-
(caller should materialise to INDEX). Negative endpoints are
|
|
817
|
-
normalised against dim_size like everywhere else in CArray. */
|
|
818
|
-
static int
|
|
819
|
-
cag_range_to_stride (VALUE range, ca_size_t dim_size,
|
|
820
|
-
ca_size_t *out_start, ca_size_t *out_count)
|
|
821
|
-
{
|
|
822
|
-
VALUE rb_first, rb_last;
|
|
823
|
-
ca_size_t first, last, count;
|
|
824
|
-
int exclude_end;
|
|
825
|
-
|
|
826
|
-
if ( ! rb_obj_is_kind_of(range, rb_cRange) ) return 0;
|
|
827
|
-
rb_first = rb_funcall(range, rb_intern("first"), 0);
|
|
828
|
-
rb_last = rb_funcall(range, rb_intern("last"), 0);
|
|
829
|
-
if ( ! FIXNUM_P(rb_first) || ! FIXNUM_P(rb_last) ) return 0;
|
|
830
|
-
exclude_end = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
|
|
831
|
-
|
|
832
|
-
first = NUM2SIZE(rb_first);
|
|
833
|
-
last = NUM2SIZE(rb_last);
|
|
834
|
-
if (first < 0) first += dim_size;
|
|
835
|
-
if (last < 0) last += dim_size;
|
|
836
|
-
if (exclude_end) last -= 1;
|
|
837
|
-
|
|
838
|
-
if (first < 0 || first >= dim_size) return 0;
|
|
839
|
-
if (last < first - 1) return 0; /* empty range */
|
|
840
|
-
if (last >= dim_size) return 0;
|
|
841
|
-
count = last - first + 1;
|
|
842
|
-
|
|
843
|
-
*out_start = first;
|
|
844
|
-
*out_count = count;
|
|
845
|
-
return 1;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
1136
|
/* The INDEX axes of rb_ca_grid, read with their index arrays attached,
|
|
849
1137
|
and the view built from them. */
|
|
850
1138
|
|
|
@@ -859,90 +1147,96 @@ static VALUE
|
|
|
859
1147
|
ca_grid_build_body (VALUE arg)
|
|
860
1148
|
{
|
|
861
1149
|
ca_grid_build_ctx_t *c = (ca_grid_build_ctx_t *) arg;
|
|
862
|
-
volatile VALUE holders[CA_RANK_MAX];
|
|
863
|
-
volatile VALUE obj;
|
|
864
1150
|
int8_t i;
|
|
865
1151
|
|
|
866
1152
|
for (i = 0; i < c->ca->ndim; i++) {
|
|
867
1153
|
CArray *ci = c->ci[i];
|
|
868
|
-
holders[i] = Qfalse;
|
|
869
1154
|
if ( ! ci ) {
|
|
870
1155
|
continue;
|
|
871
1156
|
}
|
|
872
|
-
c->protos[i].kind
|
|
1157
|
+
c->protos[i].kind = CAG_AXIS_INDEX;
|
|
1158
|
+
c->protos[i].count = ci->elements;
|
|
1159
|
+
c->protos[i].indices = (ca_size_t *) ci->ptr;
|
|
1160
|
+
c->protos[i].holes = NULL;
|
|
873
1161
|
if ( ca_is_any_masked(ci) ) {
|
|
874
|
-
/*
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
ca_size_t *src = (ca_size_t *) ci->ptr;
|
|
879
|
-
boolean8_t *m = (boolean8_t *) ci->mask->ptr;
|
|
880
|
-
ca_size_t *tmp = ALLOCV_N(ca_size_t, holders[i], gsize > 0 ? gsize : 1);
|
|
881
|
-
ca_size_t j, n = 0;
|
|
882
|
-
for (j = 0; j < ci->elements; j++) {
|
|
883
|
-
if ( ! m[j] ) tmp[n++] = src[j];
|
|
884
|
-
}
|
|
885
|
-
c->protos[i].count = gsize;
|
|
886
|
-
c->protos[i].indices = tmp;
|
|
887
|
-
} else {
|
|
888
|
-
c->protos[i].count = ci->elements;
|
|
889
|
-
c->protos[i].indices = (ca_size_t *) ci->ptr;
|
|
1162
|
+
/* A masked index cell selects nothing: its position stays, as a hole
|
|
1163
|
+
(masked on read, skipped on write). setup copies the mask into
|
|
1164
|
+
its own buffer. */
|
|
1165
|
+
c->protos[i].holes = (uint8_t *) ci->mask->ptr;
|
|
890
1166
|
}
|
|
891
1167
|
c->protos[i].start = 0;
|
|
892
1168
|
c->protos[i].step = 0;
|
|
893
1169
|
}
|
|
894
1170
|
|
|
895
|
-
|
|
1171
|
+
return rb_ca_grid_new(c->self, c->ca->ndim, c->protos);
|
|
1172
|
+
}
|
|
896
1173
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1174
|
+
/* A scalar key (an Integer or a Float) picks one cell along its axis, and that axis is
|
|
1175
|
+
not in the result -- as it is not in a block reference. The view is
|
|
1176
|
+
built with the axis at length 1 and the axis then dropped. */
|
|
1177
|
+
static VALUE
|
|
1178
|
+
ca_grid_drop_scalar_axes (VALUE obj, int argc, VALUE *argv)
|
|
1179
|
+
{
|
|
1180
|
+
VALUE idx[CA_RANK_MAX];
|
|
1181
|
+
int i, any = 0;
|
|
1182
|
+
for (i = 0; i < argc; i++) {
|
|
1183
|
+
if ( ca_index_key_is_scalar(argv[i]) ) {
|
|
1184
|
+
idx[i] = INT2FIX(0);
|
|
1185
|
+
any = 1;
|
|
1186
|
+
}
|
|
1187
|
+
else {
|
|
1188
|
+
idx[i] = Qnil;
|
|
900
1189
|
}
|
|
901
1190
|
}
|
|
902
|
-
|
|
1191
|
+
if ( ! any ) {
|
|
1192
|
+
return obj;
|
|
1193
|
+
}
|
|
1194
|
+
return rb_ca_fetch2(obj, argc, idx);
|
|
903
1195
|
}
|
|
904
1196
|
|
|
1197
|
+
/* ca[k0, k1, ...] with a CArray among the keys. An integer CArray picks
|
|
1198
|
+
the cells it lists along its axis, a boolean one the cells it marks (it
|
|
1199
|
+
must be as long as the axis). Every other key is read as the indexer
|
|
1200
|
+
reads it (ca_index_axis_key): an Integer picks one cell and drops the
|
|
1201
|
+
axis, a Range / ArithmeticSequence / Array form a run, nil the axis. */
|
|
905
1202
|
VALUE
|
|
906
1203
|
rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
907
1204
|
{
|
|
908
|
-
volatile VALUE obj,
|
|
1205
|
+
volatile VALUE obj, rval;
|
|
909
1206
|
volatile VALUE list = rb_ary_new();
|
|
910
1207
|
CArray *ca;
|
|
911
1208
|
CArray *ci[CA_RANK_MAX]; /* CAWrap holders for INDEX axes; NULL for STRIDE */
|
|
912
1209
|
cag_axis_t protos[CA_RANK_MAX];
|
|
1210
|
+
VALUE expanded[CA_RANK_MAX];
|
|
1211
|
+
long n;
|
|
913
1212
|
ca_size_t i;
|
|
914
1213
|
|
|
915
|
-
/* Dispatch hook: route mixed AP + single boolean to CASelectAxis
|
|
916
|
-
(slab-copy optimised path). Falls through to per-cell CAGrid gather
|
|
917
|
-
when not eligible (integer index, multiple INDIRECT axes, indirect
|
|
918
|
-
not on axis 0). Inline argv[0] type check avoids the function call
|
|
919
|
-
when axis 0 is nil/Integer (most patterns with INDIRECT on inner axes). */
|
|
920
|
-
extern int ca_csa_dispatch_bypass;
|
|
921
|
-
if ( ! ca_csa_dispatch_bypass && argc > 0 && TYPE(argv[0]) == T_DATA ) {
|
|
922
|
-
if ( rb_ca_select_axis_eligible_p(argc, argv, self) ) {
|
|
923
|
-
return rb_ca_select_axis(argc, argv, self);
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
|
|
927
1214
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
928
1215
|
|
|
929
|
-
|
|
1216
|
+
n = ca_index_expand_rubber(ca->ndim, argc, argv, expanded);
|
|
1217
|
+
if ( n >= 0 ) {
|
|
1218
|
+
argc = (int) n;
|
|
1219
|
+
argv = expanded;
|
|
1220
|
+
}
|
|
930
1221
|
|
|
931
|
-
if (
|
|
1222
|
+
if ( argc > ca->ndim ) {
|
|
932
1223
|
rb_raise(rb_eArgError, "# of arguments doesn't equal to the ndim");
|
|
933
1224
|
}
|
|
934
|
-
else if (
|
|
1225
|
+
else if ( argc < ca->ndim ) {
|
|
935
1226
|
volatile VALUE ref;
|
|
936
1227
|
CArray *cv;
|
|
937
1228
|
ca_size_t rdim[CA_RANK_MAX];
|
|
938
|
-
ca_size_t rndim =
|
|
1229
|
+
ca_size_t rndim = argc;
|
|
939
1230
|
ca_size_t j = 0, k;
|
|
940
1231
|
for (i=0; i<rndim; i++) {
|
|
941
|
-
rval =
|
|
1232
|
+
rval = argv[i];
|
|
942
1233
|
if ( rb_obj_is_carray(rval) ) {
|
|
943
1234
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
944
1235
|
rdim[i] = 1;
|
|
945
1236
|
for (k=0; k<cv->ndim; k++) {
|
|
1237
|
+
if ( j >= ca->ndim ) {
|
|
1238
|
+
rb_raise(rb_eArgError, "invalid total ndim of args");
|
|
1239
|
+
}
|
|
946
1240
|
rdim[i] *= ca->dim[j];
|
|
947
1241
|
j += 1;
|
|
948
1242
|
}
|
|
@@ -956,45 +1250,69 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
956
1250
|
rb_raise(rb_eArgError, "invalid total ndim of args");
|
|
957
1251
|
}
|
|
958
1252
|
ref = rb_ca_refer_new(self, ca->data_type, rndim, rdim, ca->bytes, 0);
|
|
959
|
-
|
|
1253
|
+
/* An index array that spans several axes picks along the one axis
|
|
1254
|
+
they are joined into, so it is read flat there. */
|
|
1255
|
+
{
|
|
1256
|
+
VALUE flat[CA_RANK_MAX];
|
|
1257
|
+
for (i=0; i<rndim; i++) {
|
|
1258
|
+
flat[i] = rb_obj_is_carray(argv[i]) ? rb_ca_flatten(argv[i]) : argv[i];
|
|
1259
|
+
}
|
|
1260
|
+
return rb_ca_grid(argc, flat, ref);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/* Dispatch hook: route a boolean on axis 0 with plain keys elsewhere to
|
|
1265
|
+
CASelectAxis (slab-copy optimised path). Falls through to CAGrid when
|
|
1266
|
+
not eligible. The inline argv[0] type check avoids the call when axis
|
|
1267
|
+
0 is nil / Integer (most patterns with the CArray on an inner axis). */
|
|
1268
|
+
extern int ca_csa_dispatch_bypass;
|
|
1269
|
+
if ( ! ca_csa_dispatch_bypass && argc > 0 && TYPE(argv[0]) == T_DATA ) {
|
|
1270
|
+
if ( rb_ca_select_axis_eligible_p(argc, argv, self) ) {
|
|
1271
|
+
return ca_grid_drop_scalar_axes(rb_ca_select_axis(argc, argv, self),
|
|
1272
|
+
argc, argv);
|
|
1273
|
+
}
|
|
960
1274
|
}
|
|
961
1275
|
|
|
962
|
-
/* Build per-axis protos:
|
|
963
|
-
nil -> STRIDE(0, parent.dim, 1), no CArray
|
|
964
|
-
Range -> STRIDE if plain integer Range, else fall through to INDEX
|
|
965
|
-
CArray -> INDEX with indices = (ca_size_t*)ca_wrap_readonly(...)->ptr */
|
|
966
1276
|
for (i = 0; i < ca->ndim; i++) {
|
|
967
1277
|
ca_size_t dim_size = ca->dim[i];
|
|
968
|
-
rval =
|
|
1278
|
+
rval = argv[i];
|
|
969
1279
|
ci[i] = NULL;
|
|
970
|
-
if (
|
|
1280
|
+
if ( ! rb_obj_is_carray(rval) ) {
|
|
1281
|
+
ca_size_t start, count, step;
|
|
1282
|
+
ca_index_axis_key(rval, dim_size, (int) i, &start, &count, &step);
|
|
971
1283
|
protos[i].kind = CAG_AXIS_STRIDE;
|
|
972
|
-
protos[i].count =
|
|
973
|
-
protos[i].start =
|
|
974
|
-
protos[i].step =
|
|
1284
|
+
protos[i].count = count;
|
|
1285
|
+
protos[i].start = start;
|
|
1286
|
+
protos[i].step = step;
|
|
975
1287
|
protos[i].indices = NULL;
|
|
1288
|
+
protos[i].holes = NULL;
|
|
976
1289
|
continue;
|
|
977
1290
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1291
|
+
{
|
|
1292
|
+
/* An index array picks cells along its one axis. One of more axes
|
|
1293
|
+
states a shape the axis does not have. */
|
|
1294
|
+
CArray *cs;
|
|
1295
|
+
TypedData_Get_Struct(rval, CArray, &carray_data_type, cs);
|
|
1296
|
+
if ( cs->ndim > 1 ) {
|
|
1297
|
+
volatile VALUE sshape = rb_ary_new();
|
|
1298
|
+
int k;
|
|
1299
|
+
for (k = 0; k < cs->ndim; k++) rb_ary_push(sshape, SIZE2NUM(cs->dim[k]));
|
|
1300
|
+
rb_raise(rb_eArgError,
|
|
1301
|
+
"%s: index array of shape %"PRIsVALUE" on axis %d (an index "
|
|
1302
|
+
"array picks along one axis; use .flatten)",
|
|
1303
|
+
ca_calling_method_name(), sshape, (int) i);
|
|
987
1304
|
}
|
|
988
|
-
/* fallback: materialise to integer array */
|
|
989
|
-
rval = rb_funcall(rb_mKernel, rb_intern("CA_SIZE"), 1, rval);
|
|
990
1305
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1306
|
+
if ( rb_ca_is_boolean_type(rval) ) {
|
|
1307
|
+
CArray *cb;
|
|
1308
|
+
TypedData_Get_Struct(rval, CArray, &carray_data_type, cb);
|
|
1309
|
+
if ( cb->elements != dim_size ) {
|
|
1310
|
+
rb_raise(rb_eArgError,
|
|
1311
|
+
"mismatch of # of elements ( %lld <=> %lld ) in reference "
|
|
1312
|
+
"by selection on axis %d",
|
|
1313
|
+
(long long) cb->elements, (long long) dim_size, (int) i);
|
|
994
1314
|
}
|
|
995
|
-
|
|
996
|
-
else if ( TYPE(rval) == T_ARRAY ) {
|
|
997
|
-
rb_raise(rb_eTypeError, "grid: an axis is an Integer, a Range, nil or a CArray of indices (got Array)");
|
|
1315
|
+
rval = rb_ca_where(rval);
|
|
998
1316
|
}
|
|
999
1317
|
|
|
1000
1318
|
/* INDEX axis: converted here, read once the window below opens */
|
|
@@ -1020,7 +1338,7 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
1020
1338
|
(VALUE) &c);
|
|
1021
1339
|
}
|
|
1022
1340
|
|
|
1023
|
-
return obj;
|
|
1341
|
+
return ca_grid_drop_scalar_axes(obj, argc, argv);
|
|
1024
1342
|
}
|
|
1025
1343
|
|
|
1026
1344
|
static VALUE
|
|
@@ -1044,6 +1362,9 @@ rb_ca_grid_initialize_copy (VALUE self, VALUE other)
|
|
|
1044
1362
|
}
|
|
1045
1363
|
/* Copy the axes: the source may be collected before the copy. */
|
|
1046
1364
|
ca_grid_setup(ca, cs->parent, cs->ndim, cs->axes, 0);
|
|
1365
|
+
ca->holes_read_masked = cs->holes_read_masked;
|
|
1366
|
+
ca->mask_owner = cs->mask_owner;
|
|
1367
|
+
ca_grid_inherit_mask((VALUE) ca);
|
|
1047
1368
|
|
|
1048
1369
|
return self;
|
|
1049
1370
|
}
|