carray 3.0.3 → 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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- 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 +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- 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 +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -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 +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -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 +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -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 +78 -10
- 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 +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- 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/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 +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -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 +11 -4
- 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 +182 -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 +53 -36
- 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 +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- 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_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- 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
|
|
|
@@ -225,42 +250,104 @@ ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
|
225
250
|
ca->axes[k].start = protos[k].start;
|
|
226
251
|
ca->axes[k].step = protos[k].step;
|
|
227
252
|
ca->axes[k].indices = NULL;
|
|
253
|
+
ca->axes[k].holes = NULL;
|
|
228
254
|
} else {
|
|
229
255
|
ca->axes[k].start = 0;
|
|
230
256
|
ca->axes[k].step = 0;
|
|
231
257
|
ca->axes[k].indices = ALLOC_N(ca_size_t,
|
|
232
258
|
protos[k].count > 0 ? protos[k].count : 1);
|
|
259
|
+
ca->axes[k].holes = NULL;
|
|
233
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
|
+
}
|
|
234
268
|
for (j = 0; j < protos[k].count; j++) {
|
|
235
269
|
ca_size_t v = protos[k].indices[j];
|
|
270
|
+
if ( ca->axes[k].holes && ca->axes[k].holes[j] ) {
|
|
271
|
+
ca->axes[k].indices[j] = 0;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
236
274
|
ca->axes[k].indices[j] = ( v < 0 ) ? v + parent->dim[k] : v;
|
|
237
275
|
}
|
|
238
276
|
}
|
|
239
277
|
}
|
|
240
278
|
}
|
|
241
279
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
280
|
+
return 0;
|
|
281
|
+
}
|
|
245
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
|
+
}
|
|
246
293
|
return 0;
|
|
247
294
|
}
|
|
248
295
|
|
|
249
|
-
|
|
250
|
-
|
|
296
|
+
int
|
|
297
|
+
ca_grid_has_holes (void *ap)
|
|
298
|
+
{
|
|
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)
|
|
251
326
|
{
|
|
252
327
|
CAGrid *ca;
|
|
253
328
|
ca_grid_check_protos(parent, ndim, protos);
|
|
329
|
+
/* check: ca_grid_check_protos above */
|
|
254
330
|
ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
255
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);
|
|
256
335
|
return ca;
|
|
257
336
|
}
|
|
258
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
|
+
|
|
259
344
|
CAGrid *
|
|
260
345
|
ca_grid_new_share (CArray *parent, int8_t ndim, cag_axis_t *protos)
|
|
261
346
|
{
|
|
347
|
+
/* check: the mask grid copies its own grid's checked axes */
|
|
262
348
|
CAGrid *ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
263
349
|
ca_grid_setup(ca, parent, ndim, protos, 1);
|
|
350
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
264
351
|
return ca;
|
|
265
352
|
}
|
|
266
353
|
|
|
@@ -270,12 +357,16 @@ free_ca_grid (void *ap)
|
|
|
270
357
|
CAGrid *ca = (CAGrid *) ap;
|
|
271
358
|
if ( ca != NULL ) {
|
|
272
359
|
ca_free(ca->mask);
|
|
360
|
+
ca_free(ca->mask_standin);
|
|
273
361
|
if ( ! (ca->flags & CA_FLAG_SHARE_INDEX) ) {
|
|
274
362
|
int8_t k;
|
|
275
363
|
for (k = 0; k < ca->ndim; k++) {
|
|
276
364
|
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices ) {
|
|
277
365
|
xfree(ca->axes[k].indices);
|
|
278
366
|
}
|
|
367
|
+
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].holes ) {
|
|
368
|
+
xfree(ca->axes[k].holes);
|
|
369
|
+
}
|
|
279
370
|
}
|
|
280
371
|
xfree(ca->axes);
|
|
281
372
|
}
|
|
@@ -301,7 +392,8 @@ static void *
|
|
|
301
392
|
ca_grid_func_clone (void *ap)
|
|
302
393
|
{
|
|
303
394
|
CAGrid *ca = (CAGrid *) ap;
|
|
304
|
-
return
|
|
395
|
+
return ca_grid_new_as(ca->parent, ca->ndim, ca->axes, ca->holes_read_masked,
|
|
396
|
+
ca->mask_owner);
|
|
305
397
|
}
|
|
306
398
|
|
|
307
399
|
/* Per-axis parent-index lookup. STRIDE = one multiply, INDEX = one
|
|
@@ -315,6 +407,124 @@ cag_parent_index_for (const cag_axis_t *ax, ca_size_t i)
|
|
|
315
407
|
return ax->indices[i];
|
|
316
408
|
}
|
|
317
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
|
+
|
|
318
528
|
/* per-cell logic lives in ca_grid_func_xfer_index; forward-declared for
|
|
319
529
|
the region-delivery paths below. */
|
|
320
530
|
static void ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir);
|
|
@@ -327,10 +537,28 @@ ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
327
537
|
CAGrid *ca = (CAGrid *) ap;
|
|
328
538
|
ca_size_t idx0[CA_RANK_MAX];
|
|
329
539
|
int8_t i;
|
|
540
|
+
int hole = 0;
|
|
330
541
|
for (i = 0; i < ca->ndim; i++) {
|
|
331
|
-
|
|
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
|
+
}
|
|
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
|
+
}
|
|
332
556
|
}
|
|
557
|
+
cag_mask_current(ca);
|
|
333
558
|
ca_xfer_index(ca->parent, idx0, data, dir);
|
|
559
|
+
if ( dir == CA_XFER_PUT ) {
|
|
560
|
+
cag_mask_settle_after(ca, data, 1);
|
|
561
|
+
}
|
|
334
562
|
}
|
|
335
563
|
|
|
336
564
|
/* Batched address gather/scatter. Per-axis index remap
|
|
@@ -354,6 +582,11 @@ ca_grid_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
354
582
|
int8_t k;
|
|
355
583
|
volatile VALUE holder;
|
|
356
584
|
|
|
585
|
+
if ( cag_has_holes(ca) ) {
|
|
586
|
+
ca_grid_holed_xfer(ca, n, addrs, (char *) data, dir);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
|
|
357
590
|
/* Opportunistic fast path. ca_resolve_attached_root_via_identity lifts
|
|
358
591
|
parent->ptr through an identity CAStride compose-fold (handles a
|
|
359
592
|
flatten[idx].reshape(*) chain etc.). */
|
|
@@ -409,8 +642,9 @@ ca_grid_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
409
642
|
int8_t k;
|
|
410
643
|
|
|
411
644
|
for (k = 0; k < g->ndim; k++) {
|
|
412
|
-
if (g->axes[k].kind == CAG_AXIS_INDEX
|
|
413
|
-
|
|
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 */
|
|
414
648
|
}
|
|
415
649
|
}
|
|
416
650
|
|
|
@@ -505,8 +739,9 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
505
739
|
/* The request is over the view's addresses, so a transposed / flat request
|
|
506
740
|
is legal and must not be composed axis-by-axis; see
|
|
507
741
|
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
508
|
-
if (
|
|
509
|
-
|
|
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) */
|
|
510
745
|
}
|
|
511
746
|
else {
|
|
512
747
|
for (k = 0; k < ndim; k++) {
|
|
@@ -519,6 +754,7 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
519
754
|
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
520
755
|
for (k = 0; k < ndim; k++) base += starts[k] * gnative[k];
|
|
521
756
|
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
757
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
522
758
|
while (1) {
|
|
523
759
|
ca_size_t goff = base, gidx[CA_RANK_MAX];
|
|
524
760
|
for (k = 0; k < ndim; k++) goff += idx[k] * strides[k];
|
|
@@ -607,6 +843,7 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
607
843
|
ca_xfer_stride/ca_xfer_addrs. */
|
|
608
844
|
for (k = 0; k < ndim; k++) o[k] = 0;
|
|
609
845
|
|
|
846
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
610
847
|
while (1) {
|
|
611
848
|
ca_size_t pbase = 0, doff = 0;
|
|
612
849
|
for (k = 0; k < inner; k++) {
|
|
@@ -659,14 +896,22 @@ ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
659
896
|
The predicate asks what the parent is, not whether it is attached now,
|
|
660
897
|
so attach, sync and detach all take the same branch. */
|
|
661
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
|
+
|
|
662
907
|
static void
|
|
663
908
|
ca_grid_func_allocate (void *ap)
|
|
664
909
|
{
|
|
665
910
|
CAGrid *ca = (CAGrid *) ap;
|
|
666
|
-
if ( !
|
|
911
|
+
if ( ! cag_owns_buffer(ca) ) {
|
|
667
912
|
ca_attach(ca->parent);
|
|
668
913
|
}
|
|
669
|
-
ca->ptr =
|
|
914
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
670
915
|
}
|
|
671
916
|
|
|
672
917
|
static void
|
|
@@ -676,7 +921,7 @@ ca_grid_func_attach (void *ap)
|
|
|
676
921
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
677
922
|
ca_size_t pdims[CA_RANK_MAX];
|
|
678
923
|
|
|
679
|
-
if (
|
|
924
|
+
if ( cag_owns_buffer(ca) ) {
|
|
680
925
|
ca_axis_view_attach_owned(ca);
|
|
681
926
|
return;
|
|
682
927
|
}
|
|
@@ -694,7 +939,7 @@ ca_grid_func_sync (void *ap)
|
|
|
694
939
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
695
940
|
ca_size_t pdims[CA_RANK_MAX];
|
|
696
941
|
|
|
697
|
-
if (
|
|
942
|
+
if ( cag_owns_buffer(ca) ) {
|
|
698
943
|
ca_axis_view_sync_owned(ca);
|
|
699
944
|
return;
|
|
700
945
|
}
|
|
@@ -711,7 +956,7 @@ ca_grid_func_detach (void *ap)
|
|
|
711
956
|
CAGrid *ca = (CAGrid *) ap;
|
|
712
957
|
xfree(ca->ptr);
|
|
713
958
|
ca->ptr = NULL;
|
|
714
|
-
if ( !
|
|
959
|
+
if ( ! cag_owns_buffer(ca) ) {
|
|
715
960
|
ca_detach(ca->parent);
|
|
716
961
|
}
|
|
717
962
|
}
|
|
@@ -736,9 +981,41 @@ ca_grid_func_run_fast_path (void *ap, char *data, int dir)
|
|
|
736
981
|
static void
|
|
737
982
|
ca_grid_func_xfer_all (void *ap, void *data, int dir)
|
|
738
983
|
{
|
|
984
|
+
CAGrid *ca = (CAGrid *) ap;
|
|
985
|
+
if ( cag_has_holes(ca) ) {
|
|
986
|
+
ca_grid_holed_xfer(ca, ca->elements, NULL, (char *) data, dir);
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
739
989
|
ca_axis_view_xfer_all(ap, ca_grid_func_run_fast_path, 1, data, dir);
|
|
740
990
|
}
|
|
741
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;
|
|
1010
|
+
}
|
|
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);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
742
1019
|
static void
|
|
743
1020
|
ca_grid_func_fill_data (void *ap, void *ptr)
|
|
744
1021
|
{
|
|
@@ -746,6 +1023,11 @@ ca_grid_func_fill_data (void *ap, void *ptr)
|
|
|
746
1023
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
747
1024
|
ca_size_t pdims[CA_RANK_MAX];
|
|
748
1025
|
|
|
1026
|
+
if ( cag_has_holes(ca) ) {
|
|
1027
|
+
ca_grid_holed_fill(ca, ptr);
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
749
1031
|
ca_grid_describe_axes(ca, desc, pdims);
|
|
750
1032
|
|
|
751
1033
|
/* Writing the selected cells used to go through a whole-parent attach and
|
|
@@ -765,15 +1047,32 @@ ca_grid_func_fill_data (void *ap, void *ptr)
|
|
|
765
1047
|
ca_sync_detach(ca->parent);
|
|
766
1048
|
}
|
|
767
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. */
|
|
768
1052
|
static void
|
|
769
1053
|
ca_grid_func_create_mask (void *ap)
|
|
770
1054
|
{
|
|
771
1055
|
CAGrid *ca = (CAGrid *) ap;
|
|
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 {
|
|
1069
|
+
ca_create_mask(ca->parent);
|
|
1070
|
+
mparent = ca->parent->mask;
|
|
1071
|
+
}
|
|
772
1072
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
ca->mask =
|
|
776
|
-
ca->ndim, ca->axes);
|
|
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;
|
|
777
1076
|
}
|
|
778
1077
|
|
|
779
1078
|
ca_operation_function_t ca_grid_func = {
|
|
@@ -810,41 +1109,6 @@ rb_ca_grid_new (VALUE cary, int8_t ndim, cag_axis_t *protos)
|
|
|
810
1109
|
return obj;
|
|
811
1110
|
}
|
|
812
1111
|
|
|
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
1112
|
/* The INDEX axes of rb_ca_grid, read with their index arrays attached,
|
|
849
1113
|
and the view built from them. */
|
|
850
1114
|
|
|
@@ -859,90 +1123,96 @@ static VALUE
|
|
|
859
1123
|
ca_grid_build_body (VALUE arg)
|
|
860
1124
|
{
|
|
861
1125
|
ca_grid_build_ctx_t *c = (ca_grid_build_ctx_t *) arg;
|
|
862
|
-
volatile VALUE holders[CA_RANK_MAX];
|
|
863
|
-
volatile VALUE obj;
|
|
864
1126
|
int8_t i;
|
|
865
1127
|
|
|
866
1128
|
for (i = 0; i < c->ca->ndim; i++) {
|
|
867
1129
|
CArray *ci = c->ci[i];
|
|
868
|
-
holders[i] = Qfalse;
|
|
869
1130
|
if ( ! ci ) {
|
|
870
1131
|
continue;
|
|
871
1132
|
}
|
|
872
|
-
c->protos[i].kind
|
|
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;
|
|
873
1137
|
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;
|
|
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;
|
|
890
1142
|
}
|
|
891
1143
|
c->protos[i].start = 0;
|
|
892
1144
|
c->protos[i].step = 0;
|
|
893
1145
|
}
|
|
894
1146
|
|
|
895
|
-
|
|
1147
|
+
return rb_ca_grid_new(c->self, c->ca->ndim, c->protos);
|
|
1148
|
+
}
|
|
896
1149
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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;
|
|
900
1165
|
}
|
|
901
1166
|
}
|
|
902
|
-
|
|
1167
|
+
if ( ! any ) {
|
|
1168
|
+
return obj;
|
|
1169
|
+
}
|
|
1170
|
+
return rb_ca_fetch2(obj, argc, idx);
|
|
903
1171
|
}
|
|
904
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. */
|
|
905
1178
|
VALUE
|
|
906
1179
|
rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
907
1180
|
{
|
|
908
|
-
volatile VALUE obj,
|
|
1181
|
+
volatile VALUE obj, rval;
|
|
909
1182
|
volatile VALUE list = rb_ary_new();
|
|
910
1183
|
CArray *ca;
|
|
911
1184
|
CArray *ci[CA_RANK_MAX]; /* CAWrap holders for INDEX axes; NULL for STRIDE */
|
|
912
1185
|
cag_axis_t protos[CA_RANK_MAX];
|
|
1186
|
+
VALUE expanded[CA_RANK_MAX];
|
|
1187
|
+
long n;
|
|
913
1188
|
ca_size_t i;
|
|
914
1189
|
|
|
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
1190
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
928
1191
|
|
|
929
|
-
|
|
1192
|
+
n = ca_index_expand_rubber(ca->ndim, argc, argv, expanded);
|
|
1193
|
+
if ( n >= 0 ) {
|
|
1194
|
+
argc = (int) n;
|
|
1195
|
+
argv = expanded;
|
|
1196
|
+
}
|
|
930
1197
|
|
|
931
|
-
if (
|
|
1198
|
+
if ( argc > ca->ndim ) {
|
|
932
1199
|
rb_raise(rb_eArgError, "# of arguments doesn't equal to the ndim");
|
|
933
1200
|
}
|
|
934
|
-
else if (
|
|
1201
|
+
else if ( argc < ca->ndim ) {
|
|
935
1202
|
volatile VALUE ref;
|
|
936
1203
|
CArray *cv;
|
|
937
1204
|
ca_size_t rdim[CA_RANK_MAX];
|
|
938
|
-
ca_size_t rndim =
|
|
1205
|
+
ca_size_t rndim = argc;
|
|
939
1206
|
ca_size_t j = 0, k;
|
|
940
1207
|
for (i=0; i<rndim; i++) {
|
|
941
|
-
rval =
|
|
1208
|
+
rval = argv[i];
|
|
942
1209
|
if ( rb_obj_is_carray(rval) ) {
|
|
943
1210
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
944
1211
|
rdim[i] = 1;
|
|
945
1212
|
for (k=0; k<cv->ndim; k++) {
|
|
1213
|
+
if ( j >= ca->ndim ) {
|
|
1214
|
+
rb_raise(rb_eArgError, "invalid total ndim of args");
|
|
1215
|
+
}
|
|
946
1216
|
rdim[i] *= ca->dim[j];
|
|
947
1217
|
j += 1;
|
|
948
1218
|
}
|
|
@@ -959,42 +1229,43 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
959
1229
|
return rb_ca_grid(argc, argv, ref);
|
|
960
1230
|
}
|
|
961
1231
|
|
|
962
|
-
/*
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
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
|
+
|
|
966
1244
|
for (i = 0; i < ca->ndim; i++) {
|
|
967
1245
|
ca_size_t dim_size = ca->dim[i];
|
|
968
|
-
rval =
|
|
1246
|
+
rval = argv[i];
|
|
969
1247
|
ci[i] = NULL;
|
|
970
|
-
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);
|
|
971
1251
|
protos[i].kind = CAG_AXIS_STRIDE;
|
|
972
|
-
protos[i].count =
|
|
973
|
-
protos[i].start =
|
|
974
|
-
protos[i].step =
|
|
1252
|
+
protos[i].count = count;
|
|
1253
|
+
protos[i].start = start;
|
|
1254
|
+
protos[i].step = step;
|
|
975
1255
|
protos[i].indices = NULL;
|
|
1256
|
+
protos[i].holes = NULL;
|
|
976
1257
|
continue;
|
|
977
1258
|
}
|
|
978
|
-
if (
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
continue;
|
|
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);
|
|
987
1267
|
}
|
|
988
|
-
|
|
989
|
-
rval = rb_funcall(rb_mKernel, rb_intern("CA_SIZE"), 1, rval);
|
|
990
|
-
}
|
|
991
|
-
else if ( rb_obj_is_carray(rval) ) {
|
|
992
|
-
if ( rb_ca_is_boolean_type(rval) ) {
|
|
993
|
-
rval = rb_ca_where(rval);
|
|
994
|
-
}
|
|
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)");
|
|
1268
|
+
rval = rb_ca_where(rval);
|
|
998
1269
|
}
|
|
999
1270
|
|
|
1000
1271
|
/* INDEX axis: converted here, read once the window below opens */
|
|
@@ -1020,7 +1291,7 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
1020
1291
|
(VALUE) &c);
|
|
1021
1292
|
}
|
|
1022
1293
|
|
|
1023
|
-
return obj;
|
|
1294
|
+
return ca_grid_drop_scalar_axes(obj, argc, argv);
|
|
1024
1295
|
}
|
|
1025
1296
|
|
|
1026
1297
|
static VALUE
|
|
@@ -1044,6 +1315,9 @@ rb_ca_grid_initialize_copy (VALUE self, VALUE other)
|
|
|
1044
1315
|
}
|
|
1045
1316
|
/* Copy the axes: the source may be collected before the copy. */
|
|
1046
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);
|
|
1047
1321
|
|
|
1048
1322
|
return self;
|
|
1049
1323
|
}
|