carray 3.0.1 → 3.0.3
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 +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -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_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/carray_mask.c
CHANGED
|
@@ -185,16 +185,67 @@ ca_mask_word_count (const boolean8_t *m, ca_size_t n)
|
|
|
185
185
|
|
|
186
186
|
enum { CA_MASK_SCAN_ANY, CA_MASK_SCAN_ALL, CA_MASK_SCAN_COUNT };
|
|
187
187
|
|
|
188
|
+
/* The block walk runs under ca_lazy_arena_protect: the transfer from a
|
|
189
|
+
virtual mask can raise, and the arena must be left however it ends. */
|
|
190
|
+
typedef struct {
|
|
191
|
+
boolean8_t *scratch; /* first: released by ca_lazy_arena_release_held */
|
|
192
|
+
CArray *mask;
|
|
193
|
+
int op;
|
|
194
|
+
ca_size_t rows;
|
|
195
|
+
ca_size_t inner;
|
|
196
|
+
ca_size_t *native;
|
|
197
|
+
ca_size_t result;
|
|
198
|
+
} ca_mask_scan_t;
|
|
199
|
+
|
|
200
|
+
static VALUE
|
|
201
|
+
ca_mask_scan_virtual_body (VALUE arg)
|
|
202
|
+
{
|
|
203
|
+
ca_mask_scan_t *sc = (ca_mask_scan_t *) arg;
|
|
204
|
+
CArray *mask = sc->mask;
|
|
205
|
+
int8_t ndim = mask->ndim;
|
|
206
|
+
ca_size_t outer = mask->dim[0];
|
|
207
|
+
ca_size_t off;
|
|
208
|
+
int8_t k;
|
|
209
|
+
|
|
210
|
+
sc->scratch = (boolean8_t *) ca_lazy_arena_acquire(sc->rows * sc->inner);
|
|
211
|
+
|
|
212
|
+
for (off = 0; off < outer; off += sc->rows) {
|
|
213
|
+
ca_size_t nrow = (outer - off < sc->rows) ? (outer - off) : sc->rows;
|
|
214
|
+
ca_size_t n = nrow * sc->inner;
|
|
215
|
+
ca_size_t starts[CA_RANK_MAX] = {0};
|
|
216
|
+
ca_size_t counts[CA_RANK_MAX];
|
|
217
|
+
|
|
218
|
+
starts[0] = off;
|
|
219
|
+
counts[0] = nrow;
|
|
220
|
+
for (k = 1; k < ndim; k++) {
|
|
221
|
+
counts[k] = mask->dim[k];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
ca_xfer_stride(mask, starts, counts, sc->native, sc->scratch, CA_XFER_GET);
|
|
225
|
+
|
|
226
|
+
if ( sc->op == CA_MASK_SCAN_ANY ) {
|
|
227
|
+
if ( ca_mask_word_any(sc->scratch, n) ) { sc->result = 1; break; }
|
|
228
|
+
}
|
|
229
|
+
else if ( sc->op == CA_MASK_SCAN_ALL ) {
|
|
230
|
+
if ( ! ca_mask_word_all_set(sc->scratch, n) ) { sc->result = 0; break; }
|
|
231
|
+
}
|
|
232
|
+
else { /* CA_MASK_SCAN_COUNT — no early exit */
|
|
233
|
+
sc->result += ca_mask_word_count(sc->scratch, n);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return Qnil;
|
|
237
|
+
}
|
|
238
|
+
|
|
188
239
|
static ca_size_t
|
|
189
240
|
ca_mask_scan_virtual (CArray *mask, int op)
|
|
190
241
|
{
|
|
191
|
-
int8_t
|
|
192
|
-
ca_size_t
|
|
193
|
-
ca_size_t
|
|
194
|
-
ca_size_t
|
|
195
|
-
ca_size_t
|
|
196
|
-
|
|
197
|
-
int8_t
|
|
242
|
+
int8_t ndim = mask->ndim;
|
|
243
|
+
ca_size_t outer = mask->dim[0];
|
|
244
|
+
ca_size_t inner = 1;
|
|
245
|
+
ca_size_t native[CA_RANK_MAX];
|
|
246
|
+
ca_size_t rows;
|
|
247
|
+
ca_mask_scan_t sc;
|
|
248
|
+
int8_t k;
|
|
198
249
|
|
|
199
250
|
for (k = 1; k < ndim; k++) {
|
|
200
251
|
inner *= mask->dim[k];
|
|
@@ -212,41 +263,18 @@ ca_mask_scan_virtual (CArray *mask, int op)
|
|
|
212
263
|
if ( rows < 1 ) rows = 1;
|
|
213
264
|
if ( rows > outer ) rows = outer;
|
|
214
265
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
ca_size_t nrow = (outer - off < rows) ? (outer - off) : rows;
|
|
224
|
-
ca_size_t n = nrow * inner;
|
|
225
|
-
ca_size_t starts[CA_RANK_MAX] = {0};
|
|
226
|
-
ca_size_t counts[CA_RANK_MAX];
|
|
227
|
-
|
|
228
|
-
starts[0] = off;
|
|
229
|
-
counts[0] = nrow;
|
|
230
|
-
for (k = 1; k < ndim; k++) {
|
|
231
|
-
counts[k] = mask->dim[k];
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
ca_xfer_stride(mask, starts, counts, native, scratch, CA_XFER_GET);
|
|
235
|
-
|
|
236
|
-
if ( op == CA_MASK_SCAN_ANY ) {
|
|
237
|
-
if ( ca_mask_word_any(scratch, n) ) { result = 1; break; }
|
|
238
|
-
}
|
|
239
|
-
else if ( op == CA_MASK_SCAN_ALL ) {
|
|
240
|
-
if ( ! ca_mask_word_all_set(scratch, n) ) { result = 0; break; }
|
|
241
|
-
}
|
|
242
|
-
else { /* CA_MASK_SCAN_COUNT — no early exit */
|
|
243
|
-
result += ca_mask_word_count(scratch, n);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
266
|
+
sc.scratch = NULL;
|
|
267
|
+
sc.mask = mask;
|
|
268
|
+
sc.op = op;
|
|
269
|
+
sc.rows = rows;
|
|
270
|
+
sc.inner = inner;
|
|
271
|
+
sc.native = native;
|
|
272
|
+
/* ALL is vacuously all-set until a non-set cell is found */
|
|
273
|
+
sc.result = ( op == CA_MASK_SCAN_ALL ) ? 1 : 0;
|
|
246
274
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
return result;
|
|
275
|
+
ca_lazy_arena_protect(ca_mask_scan_virtual_body, ca_lazy_arena_release_held,
|
|
276
|
+
(VALUE) &sc);
|
|
277
|
+
return sc.result;
|
|
250
278
|
}
|
|
251
279
|
|
|
252
280
|
boolean8_t *
|
|
@@ -323,7 +351,7 @@ ca_is_any_masked (void *ap)
|
|
|
323
351
|
non-zero word (the typical "all zero, no mask actually set" hot
|
|
324
352
|
pattern). An O(n) scan cache is not viable here: the mask is
|
|
325
353
|
dynamic and a view chain can introduce a mask mid-chain. */
|
|
326
|
-
ca_attach(ca->mask);
|
|
354
|
+
ca_attach(ca->mask); /* window: nothing raises inside */
|
|
327
355
|
flag = ca_mask_word_any((boolean8_t *) ca->mask->ptr, ca->elements);
|
|
328
356
|
ca_detach(ca->mask);
|
|
329
357
|
}
|
|
@@ -350,7 +378,7 @@ ca_is_all_masked (void *ap)
|
|
|
350
378
|
/* cheap mask: O(1) alias attach + word-level all_set with early exit.
|
|
351
379
|
The word check uses (w == 0x0101...01ULL) under the {0,1}
|
|
352
380
|
invariant; returns on the first non-fully-set word. */
|
|
353
|
-
ca_attach(ca->mask);
|
|
381
|
+
ca_attach(ca->mask); /* window: nothing raises inside */
|
|
354
382
|
flag = ca_mask_word_all_set((boolean8_t *) ca->mask->ptr, ca->elements);
|
|
355
383
|
ca_detach(ca->mask);
|
|
356
384
|
}
|
|
@@ -363,6 +391,19 @@ ca_is_all_masked (void *ap)
|
|
|
363
391
|
return flag;
|
|
364
392
|
}
|
|
365
393
|
|
|
394
|
+
/* The create_mask slot of a view whose cells map one-to-one onto its
|
|
395
|
+
parent's in address order (a cast, a byte swap, a Face over its storage):
|
|
396
|
+
the mask is the parent's mask seen in the view's shape. */
|
|
397
|
+
|
|
398
|
+
void
|
|
399
|
+
ca_view_func_create_mask (void *ap)
|
|
400
|
+
{
|
|
401
|
+
CAView *ca = (CAView *) ap;
|
|
402
|
+
ca_create_mask(ca->parent);
|
|
403
|
+
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
404
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
405
|
+
}
|
|
406
|
+
|
|
366
407
|
/* create mask array if array has mask but has not mask array */
|
|
367
408
|
|
|
368
409
|
void
|
|
@@ -374,30 +415,161 @@ ca_update_mask (void *ap)
|
|
|
374
415
|
}
|
|
375
416
|
}
|
|
376
417
|
|
|
418
|
+
static VALUE
|
|
419
|
+
ca_create_mask_attach (VALUE arg)
|
|
420
|
+
{
|
|
421
|
+
ca_attach((CArray *) arg); /* window: released by the view's detach */
|
|
422
|
+
return Qnil;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
CArray *
|
|
426
|
+
ca_multi_parent_mask (CArray *p, CArray **standin)
|
|
427
|
+
{
|
|
428
|
+
*standin = NULL;
|
|
429
|
+
if ( ! ca_has_mask(p) ) {
|
|
430
|
+
CArray *z = carray_new(CA_BOOLEAN, p->ndim, p->dim, 0, NULL);
|
|
431
|
+
MEMZERO(z->ptr, boolean8_t, z->elements);
|
|
432
|
+
if ( ca_is_readonly(p) ) {
|
|
433
|
+
ca_set_flag(z, CA_FLAG_READ_ONLY);
|
|
434
|
+
}
|
|
435
|
+
*standin = z;
|
|
436
|
+
return z;
|
|
437
|
+
}
|
|
438
|
+
ca_create_mask(p);
|
|
439
|
+
return p->mask;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* A value array or a mask array: a parent that can never be given a mask,
|
|
443
|
+
whose stand-in therefore stays in place for good. */
|
|
444
|
+
static int
|
|
445
|
+
ca_multi_parent_mask_unmaskable (CArray *p)
|
|
446
|
+
{
|
|
447
|
+
return ca_is_value_array(p) || ca_is_mask_array(p);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
void
|
|
451
|
+
ca_multi_parent_mask_refresh (CArray *mask, CArray **parents,
|
|
452
|
+
CArray **standins, int32_t n, int for_write)
|
|
453
|
+
{
|
|
454
|
+
CAMultiParent *mp = (CAMultiParent *) mask;
|
|
455
|
+
int32_t k;
|
|
456
|
+
/* Not inside an attach window: its buffer and its detach are those of
|
|
457
|
+
the parents it was opened with. The attach and allocate slots run
|
|
458
|
+
before the buffer is published, and replace the stand-ins then. */
|
|
459
|
+
if ( standins == NULL || ( CAVIEW(mask)->attach > 0 && mask->ptr != NULL ) ) {
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
/* A replaced stand-in stays allocated until the view is freed: a copy
|
|
463
|
+
of the mask (dup) may still point at it. */
|
|
464
|
+
for ( k = 0; k < n; k++ ) {
|
|
465
|
+
CArray *z = standins[k];
|
|
466
|
+
if ( z == NULL || mp->parents[k] != z
|
|
467
|
+
|| ca_test_flag(z, CA_FLAG_READ_ONLY)
|
|
468
|
+
|| ca_multi_parent_mask_unmaskable(parents[k]) ) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
if ( ! ( for_write || ca_has_mask(parents[k]) ) ) {
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
ca_create_mask(parents[k]);
|
|
475
|
+
mp->parents[k] = parents[k]->mask;
|
|
476
|
+
if ( k == 0 ) {
|
|
477
|
+
CAVIEW(mask)->parent = parents[k]->mask;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
void
|
|
483
|
+
ca_multi_parent_mask_check (CArray *mask, CArray **parents,
|
|
484
|
+
CArray **standins, int32_t n)
|
|
485
|
+
{
|
|
486
|
+
CAMultiParent *mp = (CAMultiParent *) mask;
|
|
487
|
+
int32_t k;
|
|
488
|
+
if ( standins == NULL ) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
for ( k = 0; k < n; k++ ) {
|
|
492
|
+
CArray *z = standins[k];
|
|
493
|
+
ca_size_t i;
|
|
494
|
+
if ( z == NULL || mp->parents[k] != z
|
|
495
|
+
|| ! ca_multi_parent_mask_unmaskable(parents[k]) ) {
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
for ( i = 0; i < z->elements && ! ((boolean8_t *) z->ptr)[i]; i++ ) ;
|
|
499
|
+
if ( i == z->elements ) {
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
MEMZERO(z->ptr, boolean8_t, z->elements);
|
|
503
|
+
rb_raise(rb_eTypeError, "can not create mask array for the %s array",
|
|
504
|
+
ca_is_value_array(parents[k]) ? "value" : "mask");
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
void
|
|
509
|
+
ca_multi_parent_mask_settle (CArray *mask, CArray **parents,
|
|
510
|
+
CArray **standins, int32_t n)
|
|
511
|
+
{
|
|
512
|
+
CAMultiParent *mp = (CAMultiParent *) mask;
|
|
513
|
+
int32_t k;
|
|
514
|
+
if ( standins == NULL ) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
ca_multi_parent_mask_check(mask, parents, standins, n);
|
|
518
|
+
for ( k = 0; k < n; k++ ) {
|
|
519
|
+
CArray *z = standins[k];
|
|
520
|
+
ca_size_t i;
|
|
521
|
+
if ( z == NULL || mp->parents[k] != z
|
|
522
|
+
|| ca_test_flag(z, CA_FLAG_READ_ONLY)
|
|
523
|
+
|| ca_multi_parent_mask_unmaskable(parents[k]) ) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
for ( i = 0; i < z->elements && ! ((boolean8_t *) z->ptr)[i]; i++ ) ;
|
|
527
|
+
if ( i == z->elements ) {
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
ca_create_mask(parents[k]);
|
|
531
|
+
ca_xfer_all(parents[k]->mask, z->ptr, CA_XFER_PUT);
|
|
532
|
+
MEMZERO(z->ptr, boolean8_t, z->elements);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
377
536
|
void
|
|
378
537
|
ca_create_mask (void *ap)
|
|
379
538
|
{
|
|
380
539
|
CArray *ca = (CArray *) ap;
|
|
381
540
|
|
|
541
|
+
if ( ca->mask ) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
|
|
382
545
|
if ( ca_is_value_array(ca) ) {
|
|
383
|
-
rb_raise(
|
|
546
|
+
rb_raise(rb_eTypeError,
|
|
384
547
|
"can not create mask array for the value array");
|
|
385
548
|
}
|
|
386
549
|
|
|
387
550
|
if ( ca_is_mask_array(ca) ) {
|
|
388
|
-
rb_raise(
|
|
551
|
+
rb_raise(rb_eTypeError,
|
|
389
552
|
"can not create mask array for the mask array");
|
|
390
553
|
}
|
|
391
554
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
if (
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
555
|
+
ca_func[ca->obj_type].create_mask(ca);
|
|
556
|
+
ca_set_flag(ca->mask, CA_FLAG_MASK_ARRAY); /* set array as mask array */
|
|
557
|
+
if ( ca_is_view(ca) ) {
|
|
558
|
+
if ( CAVIEW(ca)->attach ) {
|
|
559
|
+
/* The new mask joins its view's level. Its attach reads the
|
|
560
|
+
parent's mask, which can raise (a Ruby-backed parent); the mask
|
|
561
|
+
then comes off again, since the view's sync and detach would
|
|
562
|
+
find it attached to nothing. */
|
|
563
|
+
int tag = 0;
|
|
564
|
+
rb_protect(ca_create_mask_attach, (VALUE) ca->mask, &tag);
|
|
565
|
+
if ( tag ) {
|
|
566
|
+
CArray *mask = ca->mask;
|
|
567
|
+
ca->mask = NULL;
|
|
568
|
+
ca_free(mask);
|
|
569
|
+
rb_jump_tag(tag);
|
|
570
|
+
}
|
|
571
|
+
if ( ca_is_view(ca->mask) ) {
|
|
572
|
+
CAVIEW(ca->mask)->attach = CAVIEW(ca)->attach;
|
|
401
573
|
}
|
|
402
574
|
}
|
|
403
575
|
}
|
|
@@ -415,6 +587,20 @@ ca_clear_mask (void *ap)
|
|
|
415
587
|
}
|
|
416
588
|
}
|
|
417
589
|
|
|
590
|
+
typedef struct {
|
|
591
|
+
CArray *ca;
|
|
592
|
+
CArray *mask;
|
|
593
|
+
} ca_setup_mask_t;
|
|
594
|
+
|
|
595
|
+
/* Pushing the cells into ca's mask can raise (a CAObject's mask hooks). */
|
|
596
|
+
static VALUE
|
|
597
|
+
ca_setup_mask_body (VALUE arg)
|
|
598
|
+
{
|
|
599
|
+
ca_setup_mask_t *c = (ca_setup_mask_t *) arg;
|
|
600
|
+
ca_sync_data(c->ca->mask, c->mask->ptr);
|
|
601
|
+
return Qnil;
|
|
602
|
+
}
|
|
603
|
+
|
|
418
604
|
void
|
|
419
605
|
ca_setup_mask (void *ap, CArray *mask)
|
|
420
606
|
{
|
|
@@ -423,12 +609,13 @@ ca_setup_mask (void *ap, CArray *mask)
|
|
|
423
609
|
ca_update_mask(ca);
|
|
424
610
|
|
|
425
611
|
if ( mask ) {
|
|
612
|
+
ca_setup_mask_t c;
|
|
426
613
|
if ( ! ca->mask ) {
|
|
427
614
|
ca_create_mask(ca);
|
|
428
615
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
616
|
+
c.ca = ca;
|
|
617
|
+
c.mask = mask;
|
|
618
|
+
ca_attach_window(1, &c.mask, "r", ca_setup_mask_body, (VALUE) &c);
|
|
432
619
|
}
|
|
433
620
|
else if ( ca->mask ) {
|
|
434
621
|
boolean8_t zero = 0;
|
|
@@ -443,12 +630,59 @@ ca_setup_mask (void *ap, CArray *mask)
|
|
|
443
630
|
|
|
444
631
|
*/
|
|
445
632
|
|
|
446
|
-
|
|
447
|
-
|
|
633
|
+
/* The overlay reads each source's mask into the destination's. A
|
|
634
|
+
source's mask can be made or read by calling Ruby (a CAObject's mask
|
|
635
|
+
hooks) and raise, so every mask is made first and the lot are read
|
|
636
|
+
inside one attach window.
|
|
637
|
+
|
|
638
|
+
A source whose cells live in the destination's root has its mask read
|
|
639
|
+
into a snapshot before the destination's mask is made, cleared or
|
|
640
|
+
written: the destination's mask may be that same memory, and the word
|
|
641
|
+
OR would otherwise read bytes it has already set. */
|
|
642
|
+
typedef struct {
|
|
643
|
+
CArray **list; /* [0] the destination mask, then the attached sources' */
|
|
644
|
+
boolean8_t **snap; /* per source: its mask read in advance, or NULL */
|
|
645
|
+
CArray **att; /* per source: its attached mask when not snapped */
|
|
646
|
+
char *scalar; /* per source: the source is a scalar */
|
|
647
|
+
int k; /* entries in list */
|
|
648
|
+
int ns; /* sources */
|
|
649
|
+
ca_size_t elements;
|
|
650
|
+
} ca_mask_overlay_t;
|
|
651
|
+
|
|
652
|
+
static VALUE
|
|
653
|
+
ca_mask_overlay_body (VALUE arg)
|
|
654
|
+
{
|
|
655
|
+
ca_mask_overlay_t *o = (ca_mask_overlay_t *) arg;
|
|
656
|
+
boolean8_t *ma = (boolean8_t *) o->list[0]->ptr;
|
|
657
|
+
int i;
|
|
658
|
+
for (i=0; i<o->ns; i++) {
|
|
659
|
+
boolean8_t *ms = o->snap[i] ? o->snap[i] : (boolean8_t *) o->att[i]->ptr;
|
|
660
|
+
/* scalar masked source -> broadcast to all (memset); array source
|
|
661
|
+
-> pure word OR (ca_mask_word_or). A defensive `if (*ms)` is
|
|
662
|
+
unnecessary: under the {0,1} invariant, `*ma |= *ms` equals
|
|
663
|
+
`if (*ms) *ma = 1`. Post-condition: the mask byte stays in {0,1}. */
|
|
664
|
+
if ( o->scalar[i] ) {
|
|
665
|
+
if ( *ms ) {
|
|
666
|
+
memset(ma, 1, o->elements);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
else {
|
|
670
|
+
ca_mask_word_or(ma, ms, o->elements);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return Qnil;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/* overwrite: the destination's mask is cleared before the sources are
|
|
677
|
+
OR'd in (and left alone when it has none and no source has a mask). */
|
|
678
|
+
static void
|
|
679
|
+
ca_copy_mask_overlay_core (CArray *ca, ca_size_t elements, int n,
|
|
680
|
+
CArray **slist, int overwrite)
|
|
448
681
|
{
|
|
449
|
-
CArray *ca = (CArray *) ap;
|
|
450
682
|
CArray *cs;
|
|
451
|
-
|
|
683
|
+
ca_mask_overlay_t o;
|
|
684
|
+
volatile VALUE *holders;
|
|
685
|
+
char *modes;
|
|
452
686
|
int i, some_has_mask = 0;
|
|
453
687
|
|
|
454
688
|
for (i=0; i<n; i++) {
|
|
@@ -458,81 +692,115 @@ ca_copy_mask_overlay_n (void *ap, ca_size_t elements, int n, CArray **slist)
|
|
|
458
692
|
}
|
|
459
693
|
}
|
|
460
694
|
|
|
461
|
-
if ( some_has_mask ) {
|
|
695
|
+
if ( ! some_has_mask ) {
|
|
696
|
+
if ( overwrite ) {
|
|
697
|
+
ca_update_mask(ca);
|
|
698
|
+
if ( ca->mask ) {
|
|
699
|
+
boolean8_t zero = 0;
|
|
700
|
+
ca_fill(ca->mask, &zero);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
462
705
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
706
|
+
if ( elements > ca->elements ) {
|
|
707
|
+
elements = ca->elements;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
o.list = ALLOCA_N(CArray *, n + 1);
|
|
711
|
+
o.snap = ALLOCA_N(boolean8_t *, n);
|
|
712
|
+
o.att = ALLOCA_N(CArray *, n);
|
|
713
|
+
o.scalar = ALLOCA_N(char, n);
|
|
714
|
+
holders = ALLOCA_N(VALUE, n);
|
|
715
|
+
modes = ALLOCA_N(char, n + 2);
|
|
716
|
+
o.elements = elements;
|
|
717
|
+
o.ns = 0;
|
|
718
|
+
for (i=0; i<n; i++) {
|
|
719
|
+
holders[i] = 0;
|
|
720
|
+
}
|
|
721
|
+
ca_update_mask(ca);
|
|
722
|
+
|
|
723
|
+
/* Every source mask is made, and those in the destination's root are
|
|
724
|
+
read, before the destination's mask is touched. */
|
|
725
|
+
for (i=0; i<n; i++) {
|
|
726
|
+
cs = slist[i];
|
|
727
|
+
if ( ! cs ) {
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
ca_update_mask(cs);
|
|
731
|
+
if ( ! cs->mask ) {
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
o.scalar[o.ns] = (char) ca_is_scalar(cs);
|
|
735
|
+
o.att[o.ns] = NULL;
|
|
736
|
+
o.snap[o.ns] = NULL;
|
|
737
|
+
if ( ca_shares_root(cs, ca) || ca_shares_root(cs->mask, ca) ||
|
|
738
|
+
( ca->mask && ca_shares_root(cs->mask, ca->mask) ) ) {
|
|
739
|
+
o.snap[o.ns] = ALLOCV_N(boolean8_t, holders[o.ns], cs->mask->elements);
|
|
740
|
+
ca_xfer_all(cs->mask, (char *) o.snap[o.ns], CA_XFER_GET);
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
o.att[o.ns] = cs->mask;
|
|
466
744
|
}
|
|
745
|
+
o.ns++;
|
|
746
|
+
}
|
|
467
747
|
|
|
468
|
-
|
|
469
|
-
|
|
748
|
+
ca_create_mask(ca);
|
|
749
|
+
if ( overwrite ) {
|
|
750
|
+
boolean8_t zero = 0;
|
|
751
|
+
ca_fill(ca->mask, &zero);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
o.k = 0;
|
|
755
|
+
o.list[o.k] = ca->mask;
|
|
756
|
+
modes[o.k++] = 'w';
|
|
757
|
+
for (i=0; i<o.ns; i++) {
|
|
758
|
+
if ( o.att[i] ) {
|
|
759
|
+
o.list[o.k] = o.att[i];
|
|
760
|
+
modes[o.k++] = 'r';
|
|
470
761
|
}
|
|
762
|
+
}
|
|
763
|
+
modes[o.k] = '\0';
|
|
764
|
+
ca_attach_window(o.k, o.list, modes, ca_mask_overlay_body, (VALUE) &o);
|
|
471
765
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if ( ! cs ) {
|
|
476
|
-
continue;
|
|
477
|
-
}
|
|
478
|
-
ca_update_mask(cs);
|
|
479
|
-
if ( ! cs->mask ) {
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
ca_attach(cs->mask);
|
|
483
|
-
ma = (boolean8_t *) ca->mask->ptr;
|
|
484
|
-
ms = (boolean8_t *) cs->mask->ptr;
|
|
485
|
-
/* scalar masked source -> broadcast to all (memset); array source
|
|
486
|
-
-> pure word OR (ca_mask_word_or). A defensive `if (*ms)` is
|
|
487
|
-
unnecessary: under the {0,1} invariant, `*ma |= *ms` equals
|
|
488
|
-
`if (*ms) *ma = 1`. Post-condition: the mask byte stays in {0,1}. */
|
|
489
|
-
if ( ca_is_scalar(cs) ) {
|
|
490
|
-
if ( *ms ) {
|
|
491
|
-
memset(ma, 1, elements);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
else {
|
|
495
|
-
ca_mask_word_or(ma, ms, elements);
|
|
496
|
-
}
|
|
497
|
-
ca_detach(cs->mask);
|
|
766
|
+
for (i=0; i<n; i++) {
|
|
767
|
+
if ( holders[i] ) {
|
|
768
|
+
ALLOCV_END(holders[i]);
|
|
498
769
|
}
|
|
499
|
-
ca_sync(ca->mask);
|
|
500
|
-
ca_detach(ca->mask);
|
|
501
770
|
}
|
|
502
771
|
}
|
|
503
772
|
|
|
773
|
+
void
|
|
774
|
+
ca_copy_mask_overlay_n (void *ap, ca_size_t elements, int n, CArray **slist)
|
|
775
|
+
{
|
|
776
|
+
ca_copy_mask_overlay_core((CArray *) ap, elements, n, slist, 0);
|
|
777
|
+
}
|
|
778
|
+
|
|
504
779
|
void
|
|
505
780
|
ca_copy_mask_overlay (void *ap, ca_size_t elements, int n, ...)
|
|
506
781
|
{
|
|
507
782
|
CArray *ca = (CArray *) ap;
|
|
508
783
|
CArray **slist;
|
|
784
|
+
volatile VALUE holder;
|
|
509
785
|
va_list args;
|
|
510
786
|
int i;
|
|
511
787
|
|
|
512
|
-
slist =
|
|
788
|
+
slist = ALLOCV_N(CArray *, holder, n);
|
|
513
789
|
va_start(args, n);
|
|
514
790
|
for (i=0; i<n; i++) {
|
|
515
791
|
slist[i] = va_arg(args, CArray *);
|
|
516
792
|
}
|
|
517
793
|
va_end(args);
|
|
518
794
|
|
|
519
|
-
|
|
795
|
+
ca_copy_mask_overlay_core(ca, elements, n, slist, 0);
|
|
520
796
|
|
|
521
|
-
|
|
797
|
+
ALLOCV_END(holder);
|
|
522
798
|
}
|
|
523
799
|
|
|
524
800
|
void
|
|
525
801
|
ca_copy_mask_overwrite_n (void *ap, ca_size_t elements, int n, CArray **slist)
|
|
526
802
|
{
|
|
527
|
-
CArray *
|
|
528
|
-
|
|
529
|
-
ca_update_mask(ca);
|
|
530
|
-
if ( ca->mask ) {
|
|
531
|
-
boolean8_t zero = 0;
|
|
532
|
-
ca_fill(ca->mask, &zero);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
ca_copy_mask_overlay_n(ca, elements, n, slist);
|
|
803
|
+
ca_copy_mask_overlay_core((CArray *) ap, elements, n, slist, 1);
|
|
536
804
|
}
|
|
537
805
|
|
|
538
806
|
void
|
|
@@ -540,25 +808,20 @@ ca_copy_mask_overwrite (void *ap, ca_size_t elements, int n, ...)
|
|
|
540
808
|
{
|
|
541
809
|
CArray *ca = (CArray *) ap;
|
|
542
810
|
CArray **slist;
|
|
811
|
+
volatile VALUE holder;
|
|
543
812
|
va_list args;
|
|
544
813
|
int i;
|
|
545
814
|
|
|
546
|
-
slist =
|
|
815
|
+
slist = ALLOCV_N(CArray *, holder, n);
|
|
547
816
|
va_start(args, n);
|
|
548
817
|
for (i=0; i<n; i++) {
|
|
549
818
|
slist[i] = va_arg(args, CArray*);
|
|
550
819
|
}
|
|
551
820
|
va_end(args);
|
|
552
821
|
|
|
553
|
-
|
|
554
|
-
if ( ca->mask ) {
|
|
555
|
-
boolean8_t zero = 0;
|
|
556
|
-
ca_fill(ca->mask, &zero);
|
|
557
|
-
}
|
|
822
|
+
ca_copy_mask_overlay_core(ca, elements, n, slist, 1);
|
|
558
823
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
xfree(slist);
|
|
824
|
+
ALLOCV_END(holder);
|
|
562
825
|
}
|
|
563
826
|
|
|
564
827
|
void
|
|
@@ -582,7 +845,7 @@ ca_count_masked (void *ap)
|
|
|
582
845
|
if ( ca->mask ) {
|
|
583
846
|
if ( ca_attach_is_alias(ca->mask) ) {
|
|
584
847
|
/* cheap mask: O(1) alias attach + word-bulk count. */
|
|
585
|
-
ca_attach(ca->mask);
|
|
848
|
+
ca_attach(ca->mask); /* window: nothing raises inside */
|
|
586
849
|
m = (boolean8_t *) ca->mask->ptr;
|
|
587
850
|
count = ca_mask_word_count(m, ca->elements);
|
|
588
851
|
ca_detach(ca->mask);
|
|
@@ -644,7 +907,7 @@ ca_unmask (void *ap, char *fill_value)
|
|
|
644
907
|
ca_fill(ca->mask, &zero);
|
|
645
908
|
}
|
|
646
909
|
else {
|
|
647
|
-
ca_attach(ca);
|
|
910
|
+
ca_attach(ca); /* window: nothing raises inside */
|
|
648
911
|
|
|
649
912
|
switch ( ca->bytes ) {
|
|
650
913
|
case 1: proc_fill_bang_width(uint8_t); break;
|
|
@@ -654,38 +917,56 @@ ca_unmask (void *ap, char *fill_value)
|
|
|
654
917
|
default: proc_fill_bang_bytes(); break; /* cmplx128 (16) + fixlen */
|
|
655
918
|
}
|
|
656
919
|
|
|
657
|
-
|
|
658
|
-
ca_detach(ca);
|
|
920
|
+
ca_sync_detach(ca);
|
|
659
921
|
}
|
|
660
922
|
}
|
|
661
923
|
}
|
|
662
924
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
{
|
|
666
|
-
CArray *ca = (CArray *) ap;
|
|
925
|
+
typedef struct {
|
|
926
|
+
CArray *ca;
|
|
667
927
|
CArray *co;
|
|
928
|
+
char *fill_value;
|
|
929
|
+
} ca_unmask_copy_args_t;
|
|
930
|
+
|
|
931
|
+
static VALUE
|
|
932
|
+
ca_unmask_copy_fill (VALUE arg)
|
|
933
|
+
{
|
|
934
|
+
ca_unmask_copy_args_t *a = (ca_unmask_copy_args_t *) arg;
|
|
935
|
+
CArray *ca = a->ca, *co = a->co;
|
|
668
936
|
char *q;
|
|
669
937
|
boolean8_t *m;
|
|
670
938
|
ca_size_t i;
|
|
671
939
|
|
|
672
|
-
co = ca_template(ca);
|
|
673
940
|
ca_copy_data(ca, co->ptr);
|
|
674
941
|
|
|
675
|
-
|
|
676
|
-
|
|
942
|
+
/* Only the mask is needed now that the values are in co, so read the
|
|
943
|
+
mask alone rather than producing the view's cells a second time. */
|
|
944
|
+
if ( a->fill_value && ca_has_mask(ca) ) {
|
|
945
|
+
volatile VALUE holder = 0;
|
|
946
|
+
ca_update_mask(ca);
|
|
947
|
+
m = ALLOCV_N(boolean8_t, holder, ca->elements);
|
|
948
|
+
ca_copy_data(ca->mask, (char *) m);
|
|
677
949
|
q = co->ptr;
|
|
678
|
-
m = (boolean8_t *) ca->mask->ptr;
|
|
679
950
|
for (i=0; i<ca->elements; i++) {
|
|
680
|
-
if (
|
|
681
|
-
memcpy(q, fill_value, ca->bytes);
|
|
951
|
+
if ( m[i] ) {
|
|
952
|
+
memcpy(q, a->fill_value, ca->bytes);
|
|
682
953
|
}
|
|
683
|
-
|
|
954
|
+
q+=co->bytes;
|
|
684
955
|
}
|
|
685
|
-
|
|
956
|
+
ALLOCV_END(holder);
|
|
686
957
|
}
|
|
958
|
+
return Qnil;
|
|
959
|
+
}
|
|
687
960
|
|
|
688
|
-
|
|
961
|
+
CArray *
|
|
962
|
+
ca_unmask_copy (void *ap, char *fill_value)
|
|
963
|
+
{
|
|
964
|
+
ca_unmask_copy_args_t a;
|
|
965
|
+
a.ca = (CArray *) ap;
|
|
966
|
+
a.co = ca_template(a.ca);
|
|
967
|
+
a.fill_value = fill_value;
|
|
968
|
+
ca_fill_or_free(a.co, ca_unmask_copy_fill, (VALUE) &a);
|
|
969
|
+
return a.co;
|
|
689
970
|
}
|
|
690
971
|
|
|
691
972
|
void
|
|
@@ -694,16 +975,12 @@ ca_invert_mask (void *ap)
|
|
|
694
975
|
CArray *ca = (CArray *) ap;
|
|
695
976
|
boolean8_t *m;
|
|
696
977
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if ( ! ca->mask ) {
|
|
700
|
-
ca_create_mask(ca);
|
|
701
|
-
}
|
|
978
|
+
ca_create_mask(ca);
|
|
702
979
|
|
|
703
|
-
ca_attach(ca->mask);
|
|
980
|
+
ca_attach(ca->mask); /* window: nothing raises inside */
|
|
704
981
|
m = (boolean8_t *) ca->mask->ptr;
|
|
705
982
|
ca_mask_word_not(m, m, ca->elements); /* in-place 1 - m, LSB-XOR word loop */
|
|
706
|
-
|
|
983
|
+
ca_sync_detach(ca->mask);
|
|
707
984
|
|
|
708
985
|
return;
|
|
709
986
|
}
|
|
@@ -712,9 +989,10 @@ boolean8_t *
|
|
|
712
989
|
ca_allocate_mask_iterator_n (int n, CArray **slist)
|
|
713
990
|
{
|
|
714
991
|
boolean8_t *m, *mp, *ms;
|
|
715
|
-
CArray *cs;
|
|
992
|
+
CArray *cs, **masks;
|
|
993
|
+
char *scalar;
|
|
716
994
|
ca_size_t j, elements = -1;
|
|
717
|
-
int i, some_has_mask = 0;
|
|
995
|
+
int i, k = 0, some_has_mask = 0;
|
|
718
996
|
|
|
719
997
|
for (i=0; i<n; i++) {
|
|
720
998
|
if ( slist[i] ) {
|
|
@@ -728,7 +1006,7 @@ ca_allocate_mask_iterator_n (int n, CArray **slist)
|
|
|
728
1006
|
elements = slist[i]->elements;
|
|
729
1007
|
}
|
|
730
1008
|
else if ( ! ca_is_scalar(slist[i]) ) {
|
|
731
|
-
rb_raise(
|
|
1009
|
+
rb_raise(rb_eArgError,
|
|
732
1010
|
"# of elements is different among the given arrays");
|
|
733
1011
|
}
|
|
734
1012
|
}
|
|
@@ -743,13 +1021,18 @@ ca_allocate_mask_iterator_n (int n, CArray **slist)
|
|
|
743
1021
|
(degenerate call); guard so the alloc/memset never see a negative size
|
|
744
1022
|
(which would wrap to a huge bound). Also silences GCC's VRP warnings. */
|
|
745
1023
|
if ( elements < 0 ) elements = 0;
|
|
746
|
-
m = xmalloc(sizeof(boolean8_t)*elements);
|
|
747
|
-
memset(m, 0, elements);
|
|
748
1024
|
|
|
749
1025
|
if ( ! some_has_mask ) {
|
|
1026
|
+
m = xmalloc(sizeof(boolean8_t)*elements);
|
|
1027
|
+
memset(m, 0, elements);
|
|
750
1028
|
return m;
|
|
751
1029
|
}
|
|
752
1030
|
|
|
1031
|
+
/* The sources' masks, made and attached before the result is allocated:
|
|
1032
|
+
making or reading one can call Ruby (a CAObject's mask hooks) and
|
|
1033
|
+
raise, and then nothing is left attached or allocated. */
|
|
1034
|
+
masks = ALLOCA_N(CArray *, n);
|
|
1035
|
+
scalar = ALLOCA_N(char, n);
|
|
753
1036
|
for (i=0; i<n; i++) {
|
|
754
1037
|
cs = slist[i];
|
|
755
1038
|
if ( ! cs ) {
|
|
@@ -759,10 +1042,17 @@ ca_allocate_mask_iterator_n (int n, CArray **slist)
|
|
|
759
1042
|
if ( ! cs->mask ) {
|
|
760
1043
|
continue;
|
|
761
1044
|
}
|
|
762
|
-
|
|
763
|
-
|
|
1045
|
+
masks[k] = cs->mask;
|
|
1046
|
+
scalar[k++] = (char) ca_is_scalar(cs);
|
|
1047
|
+
}
|
|
1048
|
+
ca_attach_all(masks, k); /* window: nothing raises inside */
|
|
1049
|
+
|
|
1050
|
+
m = xmalloc(sizeof(boolean8_t)*elements);
|
|
1051
|
+
memset(m, 0, elements);
|
|
1052
|
+
for (i=0; i<k; i++) {
|
|
1053
|
+
ms = (boolean8_t *) masks[i]->ptr;
|
|
764
1054
|
mp = m;
|
|
765
|
-
if (
|
|
1055
|
+
if ( scalar[i] ) {
|
|
766
1056
|
if ( *ms ) {
|
|
767
1057
|
for (j=0; j<elements; j++) {
|
|
768
1058
|
*mp = 1;
|
|
@@ -773,7 +1063,9 @@ ca_allocate_mask_iterator_n (int n, CArray **slist)
|
|
|
773
1063
|
else {
|
|
774
1064
|
ca_mask_word_or(mp, ms, elements); /* m[j] |= ms[j], word-bulk OR */
|
|
775
1065
|
}
|
|
776
|
-
|
|
1066
|
+
}
|
|
1067
|
+
while ( k > 0 ) {
|
|
1068
|
+
ca_detach(masks[--k]);
|
|
777
1069
|
}
|
|
778
1070
|
return m;
|
|
779
1071
|
}
|
|
@@ -783,10 +1075,11 @@ ca_allocate_mask_iterator (int n, ...)
|
|
|
783
1075
|
{
|
|
784
1076
|
boolean8_t *m;
|
|
785
1077
|
CArray **slist;
|
|
1078
|
+
volatile VALUE holder;
|
|
786
1079
|
va_list args;
|
|
787
1080
|
int i;
|
|
788
1081
|
|
|
789
|
-
slist =
|
|
1082
|
+
slist = ALLOCV_N(CArray *, holder, n);
|
|
790
1083
|
va_start(args, n);
|
|
791
1084
|
for (i=0; i<n; i++) {
|
|
792
1085
|
slist[i] = va_arg(args, CArray *);
|
|
@@ -795,7 +1088,7 @@ ca_allocate_mask_iterator (int n, ...)
|
|
|
795
1088
|
|
|
796
1089
|
m = ca_allocate_mask_iterator_n(n, slist);
|
|
797
1090
|
|
|
798
|
-
|
|
1091
|
+
ALLOCV_END(holder);
|
|
799
1092
|
|
|
800
1093
|
return m;
|
|
801
1094
|
}
|
|
@@ -949,12 +1242,15 @@ rb_ca_mask_array (VALUE self)
|
|
|
949
1242
|
|
|
950
1243
|
ca_update_mask(ca);
|
|
951
1244
|
if ( ca->mask ) {
|
|
1245
|
+
/* The mask is reached from its array, not through a parent link, so
|
|
1246
|
+
ca_is_readonly on the mask never sees the array's read-only state.
|
|
1247
|
+
Pass it on here, where the mask is handed out. */
|
|
1248
|
+
if ( ca_is_readonly(ca) ) {
|
|
1249
|
+
ca_set_flag(ca->mask, CA_FLAG_READ_ONLY);
|
|
1250
|
+
}
|
|
952
1251
|
obj = TypedData_Wrap_Struct(ca_mask_class[ca->obj_type],
|
|
953
|
-
ca_mask_typeddata[ca->obj_type], ca->mask);
|
|
1252
|
+
ca_mask_typeddata[ca->obj_type], ca->mask);
|
|
954
1253
|
rb_ivar_set(obj, rb_intern("masked_array"), self);
|
|
955
|
-
if ( OBJ_FROZEN(self) ) {
|
|
956
|
-
rb_ca_freeze(obj);
|
|
957
|
-
}
|
|
958
1254
|
return obj;
|
|
959
1255
|
}
|
|
960
1256
|
else {
|
|
@@ -981,30 +1277,54 @@ rb_ca_set_mask (VALUE self, VALUE rval)
|
|
|
981
1277
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
982
1278
|
|
|
983
1279
|
if ( ca_is_value_array(ca) ) {
|
|
984
|
-
rb_raise(
|
|
1280
|
+
rb_raise(rb_eTypeError,
|
|
985
1281
|
"can not create mask for the value array");
|
|
986
1282
|
}
|
|
987
1283
|
|
|
988
1284
|
if ( ca_is_mask_array(ca) ) {
|
|
989
|
-
rb_raise(
|
|
1285
|
+
rb_raise(rb_eTypeError,
|
|
990
1286
|
"can not create mask for the mask array");
|
|
991
1287
|
}
|
|
992
1288
|
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1289
|
+
if ( TYPE(rmask) == T_ARRAY ) {
|
|
1290
|
+
/* Flattened as a store into a boolean array of this shape flattens
|
|
1291
|
+
it, and then taken as a 1-D boolean array (UNDEF becomes a masked
|
|
1292
|
+
cell, as in any boolean array made from it). */
|
|
1293
|
+
CArray shape = *ca;
|
|
1294
|
+
shape.data_type = CA_BOOLEAN;
|
|
1295
|
+
shape.bytes = ca_sizeof[CA_BOOLEAN];
|
|
1296
|
+
rmask = rb_ary_flatten_for_elements(rmask, ca->elements, &shape);
|
|
1297
|
+
if ( NIL_P(rmask) ) {
|
|
1298
|
+
rb_raise(rb_eArgError, "failed to guess data size of given array");
|
|
1299
|
+
}
|
|
1300
|
+
rmask = rb_ca_wrap_readonly(rmask, INT2NUM(CA_BOOLEAN));
|
|
996
1301
|
}
|
|
997
1302
|
|
|
998
1303
|
if ( rb_obj_is_carray(rmask) ) {
|
|
1304
|
+
/* The array owns the shape, as in a store: the new mask agrees with
|
|
1305
|
+
it, is 1-D or squeezes to it, or broadcasts along size-1 axes.
|
|
1306
|
+
Checked before the mask exists, so a refused one leaves none. */
|
|
1307
|
+
ca_broadcast_to_destination(self, &rmask);
|
|
999
1308
|
TypedData_Get_Struct(rmask, CArray, &carray_data_type, cv);
|
|
1309
|
+
/* A new mask taken from self's own root, or from self's mask, is
|
|
1310
|
+
read from a copy: making and writing self's mask would change it
|
|
1311
|
+
before it is read. */
|
|
1312
|
+
ca_update_mask(ca);
|
|
1313
|
+
if ( ca_shares_root(cv, ca) ||
|
|
1314
|
+
( ca->mask && ca_shares_root(cv, ca->mask) ) ) {
|
|
1315
|
+
rmask = rb_ca_copy(rmask);
|
|
1316
|
+
TypedData_Get_Struct(rmask, CArray, &carray_data_type, cv);
|
|
1317
|
+
}
|
|
1000
1318
|
if ( ! ca_is_boolean_type(cv) ) {
|
|
1001
|
-
cv = ca_wrap_readonly(
|
|
1319
|
+
cv = ca_wrap_readonly(rmask, CA_BOOLEAN);
|
|
1002
1320
|
}
|
|
1321
|
+
ca_create_mask(ca);
|
|
1003
1322
|
ca_setup_mask(ca, cv);
|
|
1004
1323
|
ca_copy_mask_overlay(ca, ca->elements, 1, cv);
|
|
1005
1324
|
return rval;
|
|
1006
1325
|
}
|
|
1007
1326
|
else {
|
|
1327
|
+
ca_create_mask(ca);
|
|
1008
1328
|
return rb_ca_store_all(rb_ca_mask_array(self), rmask);
|
|
1009
1329
|
}
|
|
1010
1330
|
}
|
|
@@ -1020,39 +1340,36 @@ with <code>self</code>. The returned array has 1 for the masked elements and
|
|
|
1020
1340
|
VALUE
|
|
1021
1341
|
rb_ca_is_masked (VALUE self)
|
|
1022
1342
|
{
|
|
1023
|
-
volatile VALUE
|
|
1024
|
-
CArray *ca, *
|
|
1343
|
+
volatile VALUE out;
|
|
1344
|
+
CArray *ca, *co;
|
|
1025
1345
|
boolean8_t zero = 0;
|
|
1026
|
-
boolean8_t *
|
|
1346
|
+
boolean8_t *p;
|
|
1027
1347
|
ca_size_t i;
|
|
1028
1348
|
|
|
1029
1349
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1030
1350
|
|
|
1031
1351
|
if ( ca_is_scalar(ca) ) {
|
|
1032
|
-
co = (CArray *)cscalar_new(CA_BOOLEAN, ca->bytes, NULL);
|
|
1352
|
+
co = (CArray *)cscalar_new(CA_BOOLEAN, ca->bytes, NULL);
|
|
1033
1353
|
}
|
|
1034
1354
|
else {
|
|
1035
|
-
co = carray_new(CA_BOOLEAN, ca->ndim, ca->dim, ca->bytes, NULL);
|
|
1355
|
+
co = carray_new(CA_BOOLEAN, ca->ndim, ca->dim, ca->bytes, NULL);
|
|
1036
1356
|
}
|
|
1357
|
+
out = ca_wrap_struct(co); /* owned by Ruby before anything can raise */
|
|
1037
1358
|
|
|
1038
1359
|
ca_update_mask(ca);
|
|
1039
1360
|
if ( ! ca->mask ) {
|
|
1040
1361
|
ca_fill(co, &zero);
|
|
1041
1362
|
}
|
|
1042
1363
|
else {
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
ca_attach(cm);
|
|
1046
|
-
m = (boolean8_t *) cm->ptr;
|
|
1364
|
+
/* Copied straight into the result, then normalised in place. */
|
|
1365
|
+
ca_copy_data(ca->mask, co->ptr);
|
|
1047
1366
|
p = (boolean8_t *) co->ptr;
|
|
1048
1367
|
for (i=0; i<ca->elements; i++) {
|
|
1049
|
-
|
|
1050
|
-
m++; p++;
|
|
1368
|
+
p[i] = ( p[i] ) ? 1 : 0;
|
|
1051
1369
|
}
|
|
1052
|
-
ca_detach(cm);
|
|
1053
1370
|
}
|
|
1054
1371
|
|
|
1055
|
-
return
|
|
1372
|
+
return out;
|
|
1056
1373
|
}
|
|
1057
1374
|
|
|
1058
1375
|
/* @overload is_not_masked
|
|
@@ -1066,39 +1383,52 @@ The returned array has 0 for the masked elements and
|
|
|
1066
1383
|
VALUE
|
|
1067
1384
|
rb_ca_is_not_masked (VALUE self)
|
|
1068
1385
|
{
|
|
1069
|
-
volatile VALUE
|
|
1070
|
-
CArray *ca, *
|
|
1386
|
+
volatile VALUE out;
|
|
1387
|
+
CArray *ca, *co;
|
|
1071
1388
|
boolean8_t one = 1;
|
|
1072
|
-
boolean8_t *
|
|
1389
|
+
boolean8_t *p;
|
|
1073
1390
|
ca_size_t i;
|
|
1074
1391
|
|
|
1075
1392
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1076
1393
|
|
|
1077
1394
|
if ( ca_is_scalar(ca) ) {
|
|
1078
|
-
co = (CArray *)
|
|
1395
|
+
co = (CArray *)cscalar_new(CA_BOOLEAN, ca->bytes, NULL);
|
|
1079
1396
|
}
|
|
1080
1397
|
else {
|
|
1081
|
-
co = carray_new(CA_BOOLEAN, ca->ndim, ca->dim, ca->bytes, NULL);
|
|
1398
|
+
co = carray_new(CA_BOOLEAN, ca->ndim, ca->dim, ca->bytes, NULL);
|
|
1082
1399
|
}
|
|
1400
|
+
out = ca_wrap_struct(co); /* owned by Ruby before anything can raise */
|
|
1083
1401
|
|
|
1084
1402
|
ca_update_mask(ca);
|
|
1085
1403
|
if ( ! ca->mask ) {
|
|
1086
1404
|
ca_fill(co, &one);
|
|
1087
1405
|
}
|
|
1088
1406
|
else {
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
ca_attach(cm);
|
|
1092
|
-
m = (boolean8_t *) cm->ptr;
|
|
1407
|
+
/* Copied straight into the result, then normalised in place. */
|
|
1408
|
+
ca_copy_data(ca->mask, co->ptr);
|
|
1093
1409
|
p = (boolean8_t *) co->ptr;
|
|
1094
1410
|
for (i=0; i<ca->elements; i++) {
|
|
1095
|
-
|
|
1096
|
-
m++; p++;
|
|
1411
|
+
p[i] = ( p[i] ) ? 0 : 1;
|
|
1097
1412
|
}
|
|
1098
|
-
ca_detach(cm);
|
|
1099
1413
|
}
|
|
1100
1414
|
|
|
1101
|
-
return
|
|
1415
|
+
return out;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
VALUE
|
|
1419
|
+
rb_ca_scan_mask_count (VALUE self, VALUE axis)
|
|
1420
|
+
{
|
|
1421
|
+
VALUE present = rb_funcall(self, rb_intern("is_not_masked"), 0);
|
|
1422
|
+
VALUE count;
|
|
1423
|
+
if ( NIL_P(axis) ) {
|
|
1424
|
+
count = rb_funcall(present, rb_intern("cumsum"), 0);
|
|
1425
|
+
}
|
|
1426
|
+
else {
|
|
1427
|
+
VALUE kw = rb_hash_new();
|
|
1428
|
+
rb_hash_aset(kw, ID2SYM(rb_intern("axis")), axis);
|
|
1429
|
+
count = rb_funcallv_kw(present, rb_intern("cumsum"), 1, &kw, RB_PASS_KEYWORDS);
|
|
1430
|
+
}
|
|
1431
|
+
return rb_funcall(count, rb_intern("to_type"), 1, INT2NUM(CA_INT64));
|
|
1102
1432
|
}
|
|
1103
1433
|
|
|
1104
1434
|
/* @overload unmask (fill_value = nil)
|
|
@@ -1124,19 +1454,20 @@ rb_ca_unmask_method (int argc, VALUE *argv, VALUE self)
|
|
|
1124
1454
|
rfval = argv[0];
|
|
1125
1455
|
}
|
|
1126
1456
|
|
|
1457
|
+
/* Filling with UNDEF leaves the cells undefined, as storing UNDEF does. */
|
|
1458
|
+
if ( rfval == CA_UNDEF ) {
|
|
1459
|
+
return self;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1127
1462
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1128
1463
|
|
|
1129
1464
|
if ( rfval != CA_UNSPECIFIED ) {
|
|
1130
|
-
/*
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
CArray *root = ca;
|
|
1134
|
-
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
1135
|
-
if (root) conv_type = root->data_type;
|
|
1136
|
-
}
|
|
1137
|
-
rcs = rb_cscalar_new_with_value(conv_type, ca->bytes, rfval);
|
|
1465
|
+
/* The fill is a value of the array (a struct, an instant for a Face):
|
|
1466
|
+
rb_ca_obj2ptr writes it as one cell of the storage. */
|
|
1467
|
+
rcs = rb_cscalar_new(ca_strip_face(ca)->data_type, ca->bytes, NULL);
|
|
1138
1468
|
TypedData_Get_Struct(rcs, CScalar, &cscalar_data_type, cv);
|
|
1139
1469
|
fval = cv->ptr;
|
|
1470
|
+
rb_ca_obj2ptr(self, rfval, fval);
|
|
1140
1471
|
}
|
|
1141
1472
|
|
|
1142
1473
|
ca_unmask(ca, fval);
|
|
@@ -1181,19 +1512,21 @@ rb_ca_unmask_copy_method (int argc, VALUE *argv, VALUE self)
|
|
|
1181
1512
|
rfval = argv[0];
|
|
1182
1513
|
}
|
|
1183
1514
|
|
|
1515
|
+
/* Filling with UNDEF leaves the cells undefined, as storing UNDEF does:
|
|
1516
|
+
the copy keeps the mask. */
|
|
1517
|
+
if ( rfval == CA_UNDEF ) {
|
|
1518
|
+
return rb_ca_copy(self);
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1184
1521
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1185
1522
|
|
|
1186
1523
|
if ( rfval != CA_UNSPECIFIED ) {
|
|
1187
|
-
/*
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
CArray *root = ca;
|
|
1191
|
-
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
1192
|
-
if (root) conv_type = root->data_type;
|
|
1193
|
-
}
|
|
1194
|
-
rcs = rb_cscalar_new_with_value(conv_type, ca->bytes, rfval);
|
|
1524
|
+
/* The fill is a value of the array (a struct, an instant for a Face):
|
|
1525
|
+
rb_ca_obj2ptr writes it as one cell of the storage. */
|
|
1526
|
+
rcs = rb_cscalar_new(ca_strip_face(ca)->data_type, ca->bytes, NULL);
|
|
1195
1527
|
TypedData_Get_Struct(rcs, CScalar, &cscalar_data_type, cv);
|
|
1196
1528
|
fval = cv->ptr;
|
|
1529
|
+
rb_ca_obj2ptr(self, rfval, fval);
|
|
1197
1530
|
}
|
|
1198
1531
|
|
|
1199
1532
|
co = ca_unmask_copy(ca, fval);
|
|
@@ -1228,6 +1561,7 @@ VALUE
|
|
|
1228
1561
|
rb_ca_invert_mask (VALUE self)
|
|
1229
1562
|
{
|
|
1230
1563
|
CArray *ca;
|
|
1564
|
+
rb_ca_modify(self);
|
|
1231
1565
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1232
1566
|
ca_invert_mask(ca);
|
|
1233
1567
|
return self;
|
|
@@ -1259,24 +1593,53 @@ rb_ca_s_guard_undef(int argc, VALUE *argv, VALUE klass)
|
|
|
1259
1593
|
|
|
1260
1594
|
/* mask_eq(v) — return form of "mask cells equal to v".
|
|
1261
1595
|
Equivalent to: obj = copy; obj[:eq, v] = UNDEF; obj */
|
|
1596
|
+
/* Masks a copy of self at the cells the store key `argv` selects. A
|
|
1597
|
+
read-only Face (CAConstString, CACategorical) copies read-only, so the
|
|
1598
|
+
mask goes on a copy of its storage and the Face is put back; a predicate
|
|
1599
|
+
key (`:eq, v`) is evaluated on the Face, where it compares values rather
|
|
1600
|
+
than storage. */
|
|
1262
1601
|
static VALUE
|
|
1263
|
-
|
|
1602
|
+
ca_mask_copy_where (VALUE self, int argc, VALUE *argv)
|
|
1264
1603
|
{
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1604
|
+
CArray *ca;
|
|
1605
|
+
volatile VALUE obj;
|
|
1606
|
+
VALUE *all_args = ALLOCA_N(VALUE, argc + 1);
|
|
1607
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1608
|
+
if ( ca_is_face(ca) && ca_is_readonly(ca) ) {
|
|
1609
|
+
obj = rb_ca_copy(rb_ca_strip_face_value(self));
|
|
1610
|
+
if ( argc >= 1 && SYMBOL_P(argv[0]) ) {
|
|
1611
|
+
all_args[0] = rb_funcallv(self, SYM2ID(argv[0]), argc - 1, argv + 1);
|
|
1612
|
+
all_args[1] = CA_UNDEF;
|
|
1613
|
+
rb_funcallv(obj, rb_intern("[]="), 2, all_args);
|
|
1614
|
+
}
|
|
1615
|
+
else {
|
|
1616
|
+
memcpy(all_args, argv, argc * sizeof(VALUE));
|
|
1617
|
+
all_args[argc] = CA_UNDEF;
|
|
1618
|
+
rb_funcallv(obj, rb_intern("[]="), argc + 1, all_args);
|
|
1619
|
+
}
|
|
1620
|
+
return rb_funcall(obj, rb_intern("face_lift"), 1, self);
|
|
1621
|
+
}
|
|
1622
|
+
obj = rb_ca_copy(self);
|
|
1623
|
+
memcpy(all_args, argv, argc * sizeof(VALUE));
|
|
1624
|
+
all_args[argc] = CA_UNDEF;
|
|
1625
|
+
rb_funcallv(obj, rb_intern("[]="), argc + 1, all_args);
|
|
1268
1626
|
return obj;
|
|
1269
1627
|
}
|
|
1270
1628
|
|
|
1629
|
+
static VALUE
|
|
1630
|
+
rb_ca_mask_eq (VALUE self, VALUE v)
|
|
1631
|
+
{
|
|
1632
|
+
VALUE args[2] = { ID2SYM(rb_intern("eq")), v };
|
|
1633
|
+
return ca_mask_copy_where(self, 2, args);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1271
1636
|
/* mask_invalid — return form of "mask NaN/Inf cells".
|
|
1272
1637
|
Equivalent to: obj = copy; obj[:is_invalid] = UNDEF; obj */
|
|
1273
1638
|
static VALUE
|
|
1274
1639
|
rb_ca_mask_invalid (VALUE self)
|
|
1275
1640
|
{
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
ID2SYM(rb_intern("is_invalid")), CA_UNDEF);
|
|
1279
|
-
return obj;
|
|
1641
|
+
VALUE args[1] = { ID2SYM(rb_intern("is_invalid")) };
|
|
1642
|
+
return ca_mask_copy_where(self, 1, args);
|
|
1280
1643
|
}
|
|
1281
1644
|
|
|
1282
1645
|
/* mask_where(*args) — generic return form predicate masking.
|
|
@@ -1285,17 +1648,10 @@ rb_ca_mask_invalid (VALUE self)
|
|
|
1285
1648
|
static VALUE
|
|
1286
1649
|
rb_ca_mask_where (int argc, VALUE *argv, VALUE self)
|
|
1287
1650
|
{
|
|
1288
|
-
volatile VALUE obj;
|
|
1289
|
-
VALUE *all_args;
|
|
1290
1651
|
if (argc == 0) {
|
|
1291
1652
|
rb_raise(rb_eArgError, "mask_where requires at least 1 argument");
|
|
1292
1653
|
}
|
|
1293
|
-
|
|
1294
|
-
all_args = ALLOCA_N(VALUE, argc + 1);
|
|
1295
|
-
memcpy(all_args, argv, argc * sizeof(VALUE));
|
|
1296
|
-
all_args[argc] = CA_UNDEF;
|
|
1297
|
-
rb_funcallv(obj, rb_intern("[]="), argc + 1, all_args);
|
|
1298
|
-
return obj;
|
|
1654
|
+
return ca_mask_copy_where(self, argc, argv);
|
|
1299
1655
|
}
|
|
1300
1656
|
|
|
1301
1657
|
/* @overload inherit_mask (*others):
|
|
@@ -1309,6 +1665,7 @@ static VALUE
|
|
|
1309
1665
|
rb_ca_inherit_mask_method (int argc, VALUE *argv, VALUE self)
|
|
1310
1666
|
{
|
|
1311
1667
|
CArray **slist;
|
|
1668
|
+
volatile VALUE holder;
|
|
1312
1669
|
CArray *ca, *cs;
|
|
1313
1670
|
int i;
|
|
1314
1671
|
|
|
@@ -1316,7 +1673,7 @@ rb_ca_inherit_mask_method (int argc, VALUE *argv, VALUE self)
|
|
|
1316
1673
|
|
|
1317
1674
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1318
1675
|
|
|
1319
|
-
slist =
|
|
1676
|
+
slist = ALLOCV_N(CArray *, holder, argc);
|
|
1320
1677
|
for (i=0; i<argc; i++) {
|
|
1321
1678
|
if ( rb_obj_is_carray(argv[i]) ) {
|
|
1322
1679
|
TypedData_Get_Struct(argv[i], CArray, &carray_data_type, cs);
|
|
@@ -1328,7 +1685,7 @@ rb_ca_inherit_mask_method (int argc, VALUE *argv, VALUE self)
|
|
|
1328
1685
|
}
|
|
1329
1686
|
ca_copy_mask_overlay_n(ca, ca->elements, argc, slist);
|
|
1330
1687
|
|
|
1331
|
-
|
|
1688
|
+
ALLOCV_END(holder);
|
|
1332
1689
|
|
|
1333
1690
|
return self;
|
|
1334
1691
|
}
|
|
@@ -1348,6 +1705,7 @@ rb_ca_inherit_mask (VALUE self, int n, ...)
|
|
|
1348
1705
|
{
|
|
1349
1706
|
VALUE other;
|
|
1350
1707
|
CArray **slist;
|
|
1708
|
+
volatile VALUE holder;
|
|
1351
1709
|
CArray *ca, *cs;
|
|
1352
1710
|
int i;
|
|
1353
1711
|
va_list rothers;
|
|
@@ -1357,7 +1715,7 @@ rb_ca_inherit_mask (VALUE self, int n, ...)
|
|
|
1357
1715
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1358
1716
|
|
|
1359
1717
|
va_start(rothers, n);
|
|
1360
|
-
slist =
|
|
1718
|
+
slist = ALLOCV_N(CArray *, holder, n);
|
|
1361
1719
|
for (i=0; i<n; i++) {
|
|
1362
1720
|
other = va_arg(rothers, VALUE);
|
|
1363
1721
|
if ( rb_obj_is_carray(other) ) {
|
|
@@ -1372,7 +1730,7 @@ rb_ca_inherit_mask (VALUE self, int n, ...)
|
|
|
1372
1730
|
|
|
1373
1731
|
ca_copy_mask_overlay_n(ca, ca->elements, n, slist);
|
|
1374
1732
|
|
|
1375
|
-
|
|
1733
|
+
ALLOCV_END(holder);
|
|
1376
1734
|
|
|
1377
1735
|
return self;
|
|
1378
1736
|
}
|
|
@@ -1388,6 +1746,7 @@ static VALUE
|
|
|
1388
1746
|
rb_ca_inherit_mask_replace_method (int argc, VALUE *argv, VALUE self)
|
|
1389
1747
|
{
|
|
1390
1748
|
CArray **slist;
|
|
1749
|
+
volatile VALUE holder;
|
|
1391
1750
|
CArray *ca, *cs;
|
|
1392
1751
|
int i;
|
|
1393
1752
|
|
|
@@ -1395,7 +1754,7 @@ rb_ca_inherit_mask_replace_method (int argc, VALUE *argv, VALUE self)
|
|
|
1395
1754
|
|
|
1396
1755
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1397
1756
|
|
|
1398
|
-
slist =
|
|
1757
|
+
slist = ALLOCV_N(CArray *, holder, argc);
|
|
1399
1758
|
for (i=0; i<argc; i++) {
|
|
1400
1759
|
if ( rb_obj_is_carray(argv[i]) ) {
|
|
1401
1760
|
TypedData_Get_Struct(argv[i], CArray, &carray_data_type, cs);
|
|
@@ -1407,7 +1766,7 @@ rb_ca_inherit_mask_replace_method (int argc, VALUE *argv, VALUE self)
|
|
|
1407
1766
|
}
|
|
1408
1767
|
ca_copy_mask_overwrite_n(ca, ca->elements, argc, slist);
|
|
1409
1768
|
|
|
1410
|
-
|
|
1769
|
+
ALLOCV_END(holder);
|
|
1411
1770
|
|
|
1412
1771
|
return self;
|
|
1413
1772
|
}
|
|
@@ -1427,6 +1786,7 @@ rb_ca_inherit_mask_replace (VALUE self, int n, ...)
|
|
|
1427
1786
|
{
|
|
1428
1787
|
VALUE other;
|
|
1429
1788
|
CArray **slist;
|
|
1789
|
+
volatile VALUE holder;
|
|
1430
1790
|
CArray *ca, *cs;
|
|
1431
1791
|
int i;
|
|
1432
1792
|
va_list rothers;
|
|
@@ -1436,7 +1796,7 @@ rb_ca_inherit_mask_replace (VALUE self, int n, ...)
|
|
|
1436
1796
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1437
1797
|
|
|
1438
1798
|
va_start(rothers, n);
|
|
1439
|
-
slist =
|
|
1799
|
+
slist = ALLOCV_N(CArray *, holder, n);
|
|
1440
1800
|
for (i=0; i<n; i++) {
|
|
1441
1801
|
other = va_arg(rothers, VALUE);
|
|
1442
1802
|
if ( rb_obj_is_carray(other) ) {
|
|
@@ -1451,34 +1811,34 @@ rb_ca_inherit_mask_replace (VALUE self, int n, ...)
|
|
|
1451
1811
|
|
|
1452
1812
|
ca_copy_mask_overwrite_n(ca, ca->elements, n, slist);
|
|
1453
1813
|
|
|
1454
|
-
|
|
1814
|
+
ALLOCV_END(holder);
|
|
1455
1815
|
|
|
1456
1816
|
return self;
|
|
1457
1817
|
}
|
|
1458
1818
|
|
|
1459
|
-
/*
|
|
1460
|
-
|
|
1461
|
-
|
|
1819
|
+
/* The no-mask answer of count_masked / count_not_masked along `axes`:
|
|
1820
|
+
every reduced cell holds `fill`. A reduction over every axis is the
|
|
1821
|
+
number itself. */
|
|
1462
1822
|
static VALUE
|
|
1463
|
-
|
|
1823
|
+
ca_count_uniform (CArray *ca, const int8_t *axes, int8_t naxes, ca_size_t fill)
|
|
1464
1824
|
{
|
|
1465
1825
|
ca_size_t dim[CA_RANK_MAX];
|
|
1466
1826
|
int8_t ndim = 0;
|
|
1467
1827
|
int i, j;
|
|
1468
|
-
int64_t v = (int64_t)
|
|
1828
|
+
int64_t v = (int64_t) fill;
|
|
1469
1829
|
VALUE result;
|
|
1470
1830
|
CArray *co;
|
|
1471
1831
|
|
|
1832
|
+
if ( naxes == ca->ndim ) {
|
|
1833
|
+
return SIZE2NUM(fill);
|
|
1834
|
+
}
|
|
1472
1835
|
for (i = 0; i < ca->ndim; i++) {
|
|
1473
1836
|
int is_axis = 0;
|
|
1474
|
-
for (j = 0; j <
|
|
1475
|
-
|
|
1476
|
-
if (ax < 0) ax += ca->ndim;
|
|
1477
|
-
if (ax == i) { is_axis = 1; break; }
|
|
1837
|
+
for (j = 0; j < naxes; j++) {
|
|
1838
|
+
if ( axes[j] == i ) { is_axis = 1; break; }
|
|
1478
1839
|
}
|
|
1479
1840
|
if (!is_axis) dim[ndim++] = ca->dim[i];
|
|
1480
1841
|
}
|
|
1481
|
-
|
|
1482
1842
|
result = rb_carray_new(CA_INT64, ndim, dim, 0, NULL);
|
|
1483
1843
|
TypedData_Get_Struct(result, CArray, &carray_data_type, co);
|
|
1484
1844
|
ca_fill(co, &v);
|
|
@@ -1492,111 +1852,95 @@ ca_make_reduced_int64 (CArray *ca, int argc, VALUE *argv, ca_size_t fill_val)
|
|
|
1492
1852
|
extern VALUE rb_ca_count_true_ki (int argc, VALUE *argv, VALUE self);
|
|
1493
1853
|
extern VALUE rb_ca_count_false_ki (int argc, VALUE *argv, VALUE self);
|
|
1494
1854
|
|
|
1495
|
-
/* count_masked
|
|
1496
|
-
|
|
1497
|
-
|
|
1855
|
+
/* count_masked / count_not_masked -- the number of masked (present)
|
|
1856
|
+
cells, over every axis (an Integer) or along `axis:` (an int64 CArray).
|
|
1857
|
+
The keywords are those of the count kernels (axis:, keep_axis:,
|
|
1858
|
+
min_count:, fill_value:), checked by them: the mask is counted with
|
|
1859
|
+
count_true_ki / count_false_ki. Without a mask the answer is known
|
|
1860
|
+
from the shape; an axis: alone takes that short cut after the same
|
|
1861
|
+
axis check the kernels make, and any other keyword runs the kernel on
|
|
1862
|
+
an all-false view that occupies one cell.
|
|
1498
1863
|
|
|
1499
1864
|
Public (non-static) linkage so rb_ca_count in carray_count.c can forward
|
|
1500
1865
|
count(UNDEF) here directly without going through Ruby method dispatch. */
|
|
1501
|
-
VALUE
|
|
1502
|
-
|
|
1866
|
+
static VALUE
|
|
1867
|
+
ca_count_by_mask (int argc, VALUE *argv, VALUE self, int masked)
|
|
1503
1868
|
{
|
|
1504
1869
|
CArray *ca;
|
|
1870
|
+
VALUE kw_hash = Qnil, mask_obj;
|
|
1505
1871
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1506
|
-
|
|
1507
|
-
/* Accepts the axis: kwarg only (positional axis is not accepted),
|
|
1508
|
-
matching the aggregate _ki family. */
|
|
1509
|
-
VALUE kw_hash, axis_val = Qnil;
|
|
1510
1872
|
rb_scan_args(argc, argv, "0:", &kw_hash);
|
|
1511
|
-
rb_scan_options(kw_hash, "axis", &axis_val);
|
|
1512
1873
|
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
if (NIL_P(
|
|
1517
|
-
|
|
1874
|
+
if ( ! ca_has_mask(ca) ) {
|
|
1875
|
+
VALUE axis_val = Qnil;
|
|
1876
|
+
int only_axis = 1;
|
|
1877
|
+
if ( ! NIL_P(kw_hash) ) {
|
|
1878
|
+
VALUE given = rb_hash_lookup2(kw_hash, ID2SYM(rb_intern("axis")), Qundef);
|
|
1879
|
+
axis_val = ( given == Qundef ) ? Qnil : given;
|
|
1880
|
+
only_axis = ( RHASH_SIZE(kw_hash) == ( given == Qundef ? 0u : 1u ) );
|
|
1881
|
+
}
|
|
1882
|
+
if ( only_axis ) {
|
|
1883
|
+
int8_t axes[CA_RANK_MAX];
|
|
1884
|
+
int8_t naxes = rb_ca_parse_reduce_axes_kw(axis_val, ca, axes);
|
|
1885
|
+
ca_size_t vol = 1;
|
|
1886
|
+
int i;
|
|
1887
|
+
for ( i = 0; i < naxes; i++ ) vol *= ca->dim[axes[i]];
|
|
1888
|
+
return ca_count_uniform(ca, axes, naxes, masked ? 0 : vol);
|
|
1889
|
+
}
|
|
1890
|
+
{
|
|
1891
|
+
ca_size_t one[CA_RANK_MAX];
|
|
1892
|
+
VALUE shape = rb_ary_new_capa(ca->ndim), cell;
|
|
1893
|
+
boolean8_t zero = 0;
|
|
1894
|
+
CArray *cc;
|
|
1895
|
+
int i;
|
|
1896
|
+
for ( i = 0; i < ca->ndim; i++ ) {
|
|
1897
|
+
one[i] = 1;
|
|
1898
|
+
rb_ary_push(shape, SIZE2NUM(ca->dim[i]));
|
|
1899
|
+
}
|
|
1900
|
+
cell = rb_carray_new(CA_BOOLEAN, ca->ndim, one, 0, NULL);
|
|
1901
|
+
TypedData_Get_Struct(cell, CArray, &carray_data_type, cc);
|
|
1902
|
+
ca_fill(cc, &zero);
|
|
1903
|
+
mask_obj = rb_funcallv(cell, rb_intern("broadcast_to"),
|
|
1904
|
+
(int) RARRAY_LEN(shape), RARRAY_CONST_PTR(shape));
|
|
1518
1905
|
}
|
|
1519
|
-
VALUE axis_ary = (TYPE(axis_val) == T_ARRAY) ? axis_val : rb_ary_new3(1, axis_val);
|
|
1520
|
-
return ca_make_reduced_int64(ca, (int) RARRAY_LEN(axis_ary),
|
|
1521
|
-
(VALUE *) RARRAY_CONST_PTR(axis_ary), 0);
|
|
1522
1906
|
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1907
|
+
else {
|
|
1908
|
+
mask_obj = rb_ca_mask_array(self);
|
|
1909
|
+
}
|
|
1910
|
+
if ( NIL_P(kw_hash) ) {
|
|
1911
|
+
return masked ? rb_ca_count_true_ki(0, NULL, mask_obj)
|
|
1912
|
+
: rb_ca_count_false_ki(0, NULL, mask_obj);
|
|
1913
|
+
}
|
|
1914
|
+
{
|
|
1915
|
+
VALUE kargv[1] = { kw_hash };
|
|
1916
|
+
return masked ? rb_ca_count_true_ki(1, kargv, mask_obj)
|
|
1917
|
+
: rb_ca_count_false_ki(1, kargv, mask_obj);
|
|
1532
1918
|
}
|
|
1533
|
-
VALUE kw = rb_hash_new();
|
|
1534
|
-
rb_hash_aset(kw, ID2SYM(rb_intern("axis")), axis_val);
|
|
1535
|
-
VALUE kargv[1] = { kw };
|
|
1536
|
-
return rb_ca_count_true_ki(1, kargv, mask_obj);
|
|
1537
1919
|
}
|
|
1538
1920
|
|
|
1539
|
-
/* @overload count_not_masked(*axis)
|
|
1540
|
-
|
|
1541
|
-
(Masking, Statistics)
|
|
1542
|
-
Returns the number of not-masked elements, optionally reduced along axes.
|
|
1543
|
-
With no arguments returns an Integer. With axis arguments returns a
|
|
1544
|
-
CArray of int64 with the specified axes collapsed.
|
|
1545
|
-
*/
|
|
1546
|
-
/* C-callable entry: skip rb_scan_args (call-frame state dependency).
|
|
1547
|
-
* axis_val = Qnil -> scalar Integer count over whole array
|
|
1548
|
-
* axis_val = Integer/Array -> reduced CArray int64
|
|
1549
|
-
* For ext authors who need to call count_not_masked from C. */
|
|
1550
1921
|
VALUE
|
|
1551
|
-
|
|
1922
|
+
rb_ca_count_masked (int argc, VALUE *argv, VALUE self)
|
|
1552
1923
|
{
|
|
1553
|
-
|
|
1554
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1555
|
-
|
|
1556
|
-
/* No mask -> every element is not-masked. Short-circuit without
|
|
1557
|
-
materialising a mask (no axis -> elements; axis form -> reduced int64
|
|
1558
|
-
filled with the product of the reduced-axis extents). */
|
|
1559
|
-
if (!ca_has_mask(ca)) {
|
|
1560
|
-
if (NIL_P(axis_val)) {
|
|
1561
|
-
return SIZE2NUM(ca->elements);
|
|
1562
|
-
}
|
|
1563
|
-
VALUE axis_ary = (TYPE(axis_val) == T_ARRAY) ? axis_val : rb_ary_new3(1, axis_val);
|
|
1564
|
-
int n_axes = (int) RARRAY_LEN(axis_ary);
|
|
1565
|
-
VALUE *axes_argv = (VALUE *) RARRAY_CONST_PTR(axis_ary);
|
|
1566
|
-
ca_size_t axis_vol = 1;
|
|
1567
|
-
int j;
|
|
1568
|
-
for (j = 0; j < n_axes; j++) {
|
|
1569
|
-
int ax = NUM2INT(axes_argv[j]);
|
|
1570
|
-
if (ax < 0) ax += ca->ndim;
|
|
1571
|
-
axis_vol *= ca->dim[ax];
|
|
1572
|
-
}
|
|
1573
|
-
return ca_make_reduced_int64(ca, n_axes, axes_argv, axis_vol);
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
/* Not-masked count = count of `false` in the mask, routed through the
|
|
1577
|
-
count_false_ki kernel for both the flat (no axis -> scalar Integer) and
|
|
1578
|
-
per-axis (-> reduced CArray) forms. The scalar C primitive
|
|
1579
|
-
ca_count_not_masked (= elements - ca_count_masked) stays separately for
|
|
1580
|
-
internal C callers (median / order) that need a raw ca_size_t. */
|
|
1581
|
-
VALUE mask_obj = rb_ca_mask_array(self);
|
|
1582
|
-
if (NIL_P(axis_val)) {
|
|
1583
|
-
return rb_ca_count_false_ki(0, NULL, mask_obj);
|
|
1584
|
-
}
|
|
1585
|
-
VALUE kw = rb_hash_new();
|
|
1586
|
-
rb_hash_aset(kw, ID2SYM(rb_intern("axis")), axis_val);
|
|
1587
|
-
VALUE kargv[1] = { kw };
|
|
1588
|
-
return rb_ca_count_false_ki(1, kargv, mask_obj);
|
|
1924
|
+
return ca_count_by_mask(argc, argv, self, 1);
|
|
1589
1925
|
}
|
|
1590
1926
|
|
|
1591
|
-
/* Ruby binding entry: parses (axis: kwarg) -> forwards to _c. */
|
|
1592
1927
|
VALUE
|
|
1593
1928
|
rb_ca_count_not_masked (int argc, VALUE *argv, VALUE self)
|
|
1594
1929
|
{
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1930
|
+
return ca_count_by_mask(argc, argv, self, 0);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
/* count_not_masked(axis: axis_val) for C callers. */
|
|
1934
|
+
VALUE
|
|
1935
|
+
rb_ca_count_not_masked_c (VALUE self, VALUE axis_val)
|
|
1936
|
+
{
|
|
1937
|
+
VALUE kw;
|
|
1938
|
+
if ( NIL_P(axis_val) ) {
|
|
1939
|
+
return ca_count_by_mask(0, NULL, self, 0);
|
|
1940
|
+
}
|
|
1941
|
+
kw = rb_hash_new();
|
|
1942
|
+
rb_hash_aset(kw, ID2SYM(rb_intern("axis")), axis_val);
|
|
1943
|
+
return rb_funcall_with_block_kw(self, rb_intern("count_not_masked"), 1, &kw, Qnil, RB_PASS_KEYWORDS);
|
|
1600
1944
|
}
|
|
1601
1945
|
|
|
1602
1946
|
/* ============================================================================
|
|
@@ -1818,6 +2162,43 @@ Init_carray_mask_fast_paths (void)
|
|
|
1818
2162
|
}
|
|
1819
2163
|
|
|
1820
2164
|
|
|
2165
|
+
/* The Ruby forms of inherit_mask take CArray arguments only: refuse a
|
|
2166
|
+
keyword and any argument that is not a CArray, which the C API would
|
|
2167
|
+
pass over as maskless. Returns the arguments without the keyword Hash. */
|
|
2168
|
+
static VALUE
|
|
2169
|
+
ca_inherit_mask_check_args (int argc, VALUE *argv, const char *name)
|
|
2170
|
+
{
|
|
2171
|
+
VALUE rest, ropt;
|
|
2172
|
+
long i;
|
|
2173
|
+
rb_scan_args(argc, argv, "*:", &rest, &ropt);
|
|
2174
|
+
rb_reject_options(ropt);
|
|
2175
|
+
for (i=0; i<RARRAY_LEN(rest); i++) {
|
|
2176
|
+
VALUE v = RARRAY_AREF(rest, i);
|
|
2177
|
+
if ( ! rb_obj_is_carray(v) ) {
|
|
2178
|
+
rb_raise(rb_eTypeError, "%s: argument %ld must be a CArray (got %s)",
|
|
2179
|
+
name, i, rb_obj_classname(v));
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
return rest;
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
static VALUE
|
|
2186
|
+
rb_ca_inherit_mask_ruby (int argc, VALUE *argv, VALUE self)
|
|
2187
|
+
{
|
|
2188
|
+
volatile VALUE rest = ca_inherit_mask_check_args(argc, argv, "inherit_mask");
|
|
2189
|
+
return rb_ca_inherit_mask_method((int) RARRAY_LEN(rest),
|
|
2190
|
+
(VALUE *) RARRAY_CONST_PTR(rest), self);
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
static VALUE
|
|
2194
|
+
rb_ca_inherit_mask_replace_ruby (int argc, VALUE *argv, VALUE self)
|
|
2195
|
+
{
|
|
2196
|
+
volatile VALUE rest = ca_inherit_mask_check_args(argc, argv,
|
|
2197
|
+
"inherit_mask_replace");
|
|
2198
|
+
return rb_ca_inherit_mask_replace_method((int) RARRAY_LEN(rest),
|
|
2199
|
+
(VALUE *) RARRAY_CONST_PTR(rest), self);
|
|
2200
|
+
}
|
|
2201
|
+
|
|
1821
2202
|
void
|
|
1822
2203
|
Init_carray_mask (void)
|
|
1823
2204
|
{
|
|
@@ -1854,9 +2235,9 @@ Init_carray_mask (void)
|
|
|
1854
2235
|
rb_define_method(rb_cCArray, "mask_invalid", rb_ca_mask_invalid, 0);
|
|
1855
2236
|
rb_define_method(rb_cCArray, "mask_where", rb_ca_mask_where, -1);
|
|
1856
2237
|
|
|
1857
|
-
rb_define_method(rb_cCArray, "inherit_mask",
|
|
2238
|
+
rb_define_method(rb_cCArray, "inherit_mask", rb_ca_inherit_mask_ruby, -1);
|
|
1858
2239
|
rb_define_method(rb_cCArray, "inherit_mask_replace",
|
|
1859
|
-
|
|
2240
|
+
rb_ca_inherit_mask_replace_ruby, -1);
|
|
1860
2241
|
|
|
1861
2242
|
rb_define_method(rb_cCArray, "count_masked", rb_ca_count_masked, -1);
|
|
1862
2243
|
rb_define_method(rb_cCArray, "count_not_masked", rb_ca_count_not_masked, -1);
|