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/ca_obj_triop.c
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
op1), src2 == scratch2, src3 == scratch3.
|
|
21
21
|
|
|
22
22
|
Mask handling: none of the currently-defined triops (fma / fms /
|
|
23
|
-
clip) trap on integer zero divisor, so m=NULL always at the
|
|
24
|
-
kernel walk (SIMD fast path). Output mask is
|
|
25
|
-
|
|
23
|
+
clip / select) trap on integer zero divisor, so m=NULL always at the
|
|
24
|
+
kernel walk (SIMD fast path). Output mask is the OR of the operand
|
|
25
|
+
masks, except for select (create_mask time).
|
|
26
26
|
|
|
27
27
|
Cross-ndim promotion: intentional design rejection, mirroring
|
|
28
28
|
CABinOp. Callers must reshape explicitly.
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
#include "carray_internal.h" /* ca_lazy_arena_* */
|
|
34
34
|
#include "ca_triop_dispatch.h"
|
|
35
35
|
#include "ca_monop_dispatch.h" /* CA_MONOP_CAST_BASE */
|
|
36
|
+
#include "carray_math_kernel.h" /* ca_triop_not_implement */
|
|
36
37
|
|
|
37
38
|
extern VALUE ca_broadcast_view (VALUE src, int8_t ndim,
|
|
38
39
|
ca_size_t *target_dim);
|
|
@@ -41,7 +42,6 @@ int8_t CA_OBJ_TRIOP;
|
|
|
41
42
|
VALUE rb_cCATriOp;
|
|
42
43
|
|
|
43
44
|
extern int8_t CA_OBJ_LAZY_MARKER;
|
|
44
|
-
extern VALUE ca_lazy_wrap_scalar (VALUE other, CArray *self_ca);
|
|
45
45
|
|
|
46
46
|
/* ------------------------------------------------------------------- */
|
|
47
47
|
/* CATriOp struct */
|
|
@@ -222,25 +222,6 @@ ca_triop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
222
222
|
ca_triop_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
static void
|
|
226
|
-
ca_triop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
227
|
-
void *data, int dir)
|
|
228
|
-
{
|
|
229
|
-
CATriOp *ca = (CATriOp *) ap;
|
|
230
|
-
ca_size_t i;
|
|
231
|
-
char *out = (char *) data;
|
|
232
|
-
|
|
233
|
-
if ( dir != CA_XFER_GET ) {
|
|
234
|
-
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_addrs PUT)");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
for ( i = 0; i < n; i++ ) {
|
|
238
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
239
|
-
ca_addr2index((CArray *)ca, addrs[i], idx);
|
|
240
|
-
ca_triop_func_xfer_index(ca, idx, out + i * ca->bytes, CA_XFER_GET);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
225
|
/* Test / observability counters (mirror CABinOp's counters). */
|
|
245
226
|
ca_size_t ca_triop_scratch_acquire_count = 0;
|
|
246
227
|
ca_size_t ca_triop_materialise_call_count = 0;
|
|
@@ -249,8 +230,7 @@ ca_size_t ca_triop_materialise_call_count = 0;
|
|
|
249
230
|
be broadcast at step=0). Returns the scratch pointer; updates
|
|
250
231
|
*step_out to 0 (scalar) or 1 (same-shape). */
|
|
251
232
|
static void *
|
|
252
|
-
pull_operand (CArray *op, int is_scalar,
|
|
253
|
-
ca_size_t *counts, ca_size_t slab_n, int8_t ndim,
|
|
233
|
+
pull_operand (CArray *op, int is_scalar, const ca_lazy_req_t *req,
|
|
254
234
|
ca_size_t *step_out)
|
|
255
235
|
{
|
|
256
236
|
void *scratch;
|
|
@@ -274,54 +254,40 @@ pull_operand (CArray *op, int is_scalar, ca_size_t *starts,
|
|
|
274
254
|
*step_out = 0;
|
|
275
255
|
}
|
|
276
256
|
else {
|
|
277
|
-
ca_size_t op_strides[CA_RANK_MAX];
|
|
278
|
-
ca_size_t s = bytes;
|
|
279
|
-
for ( k = ndim - 1; k >= 0; k-- ) {
|
|
280
|
-
op_strides[k] = s;
|
|
281
|
-
s *= counts[k];
|
|
282
|
-
}
|
|
283
257
|
scratch = ( op->data_type == CA_OBJECT )
|
|
284
|
-
? ca_lazy_arena_acquire_object(
|
|
285
|
-
: ca_lazy_arena_acquire(
|
|
258
|
+
? ca_lazy_arena_acquire_object(req->n)
|
|
259
|
+
: ca_lazy_arena_acquire(req->n * bytes);
|
|
286
260
|
ca_triop_scratch_acquire_count++;
|
|
287
|
-
|
|
261
|
+
ca_lazy_req_pull(op, req, scratch, CA_XFER_GET);
|
|
288
262
|
*step_out = 1;
|
|
289
263
|
}
|
|
290
264
|
return scratch;
|
|
291
265
|
}
|
|
292
266
|
|
|
267
|
+
/* Evaluate the cells a request names into `data` (packed, n cells). */
|
|
293
268
|
static void
|
|
294
|
-
|
|
295
|
-
ca_size_t *strides, void *data, int dir)
|
|
269
|
+
ca_triop_eval (CATriOp *to, const ca_lazy_req_t *req, void *data)
|
|
296
270
|
{
|
|
297
|
-
|
|
298
|
-
ca_size_t slab_n;
|
|
299
|
-
int8_t k;
|
|
271
|
+
ca_size_t slab_n = req->n;
|
|
300
272
|
void *scratch2, *scratch3;
|
|
301
273
|
ca_size_t op2_step, op3_step;
|
|
302
274
|
|
|
303
|
-
if ( dir != CA_XFER_GET ) {
|
|
304
|
-
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_stride PUT)");
|
|
305
|
-
}
|
|
306
275
|
ca_triop_materialise_call_count++;
|
|
307
276
|
|
|
308
|
-
slab_n = 1;
|
|
309
|
-
for ( k = 0; k < to->ndim; k++ ) slab_n *= counts[k];
|
|
310
|
-
|
|
311
277
|
/* Step 1: pull op1 into the output buffer. */
|
|
312
|
-
|
|
278
|
+
ca_lazy_req_pull(to->parent, req, data, CA_XFER_GET);
|
|
313
279
|
|
|
314
280
|
/* Step 2: pull op2 into an arena scratch. */
|
|
315
|
-
scratch2 = pull_operand(to->op2, to->op2_is_scalar,
|
|
316
|
-
slab_n, to->ndim, &op2_step);
|
|
281
|
+
scratch2 = pull_operand(to->op2, to->op2_is_scalar, req, &op2_step);
|
|
317
282
|
|
|
318
283
|
/* Step 3: pull op3 into another arena scratch. */
|
|
319
|
-
scratch3 = pull_operand(to->op3, to->op3_is_scalar,
|
|
320
|
-
slab_n, to->ndim, &op3_step);
|
|
284
|
+
scratch3 = pull_operand(to->op3, to->op3_is_scalar, req, &op3_step);
|
|
321
285
|
|
|
322
|
-
/* Step 4: apply the kernel. ptr1 == ptr4 (in-place op1)
|
|
323
|
-
|
|
286
|
+
/* Step 4: apply the kernel. ptr1 == ptr4 (in-place op1). No numeric
|
|
287
|
+
triop traps, so m=NULL; object cells call Ruby, and skip the masked
|
|
288
|
+
cells as the eager triop does. */
|
|
324
289
|
{
|
|
290
|
+
boolean8_t *slab_mask = NULL;
|
|
325
291
|
ca_triop_func_t fn = ca_triop_kernel_lookup_vvv(to->op_id, to->data_type);
|
|
326
292
|
if ( fn == NULL ) {
|
|
327
293
|
ca_lazy_arena_release(scratch3);
|
|
@@ -330,17 +296,51 @@ ca_triop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
330
296
|
"CATriOp: kernel not implemented (op_id=%u data_type=%d)",
|
|
331
297
|
(unsigned) to->op_id, (int) to->data_type);
|
|
332
298
|
}
|
|
333
|
-
|
|
299
|
+
if ( to->data_type == CA_OBJECT ) {
|
|
300
|
+
CArray *ops[3];
|
|
301
|
+
ops[0] = to->parent;
|
|
302
|
+
ops[1] = to->op2;
|
|
303
|
+
ops[2] = to->op3;
|
|
304
|
+
slab_mask = ca_lazy_req_mask(req, 3, ops);
|
|
305
|
+
}
|
|
306
|
+
fn(slab_n, slab_mask,
|
|
334
307
|
(char *)data, 1, /* src1 == dst (op1, in-place) */
|
|
335
308
|
(char *)scratch2, op2_step, /* src2 (op2) */
|
|
336
309
|
(char *)scratch3, op3_step, /* src3 (op3) */
|
|
337
310
|
(char *)data, 1); /* dst */
|
|
311
|
+
if ( slab_mask ) ca_lazy_arena_release(slab_mask);
|
|
338
312
|
}
|
|
339
313
|
|
|
340
314
|
ca_lazy_arena_release(scratch3);
|
|
341
315
|
ca_lazy_arena_release(scratch2);
|
|
342
316
|
}
|
|
343
317
|
|
|
318
|
+
static void
|
|
319
|
+
ca_triop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
320
|
+
ca_size_t *strides, void *data, int dir)
|
|
321
|
+
{
|
|
322
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
323
|
+
ca_lazy_req_t req;
|
|
324
|
+
if ( dir != CA_XFER_GET ) {
|
|
325
|
+
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_stride PUT)");
|
|
326
|
+
}
|
|
327
|
+
ca_lazy_req_region(&req, ap, starts, counts, strides);
|
|
328
|
+
ca_triop_eval((CATriOp *) ap, &req, data);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* An address list is evaluated in one pass, as a region is. */
|
|
332
|
+
static void
|
|
333
|
+
ca_triop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
334
|
+
void *data, int dir)
|
|
335
|
+
{
|
|
336
|
+
ca_lazy_req_t req;
|
|
337
|
+
if ( dir != CA_XFER_GET ) {
|
|
338
|
+
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_addrs PUT)");
|
|
339
|
+
}
|
|
340
|
+
ca_lazy_req_addrs(&req, n, addrs);
|
|
341
|
+
ca_triop_eval((CATriOp *) ap, &req, data);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
344
|
static void
|
|
345
345
|
ca_triop_func_xfer_all (void *ap, void *data, int dir)
|
|
346
346
|
{
|
|
@@ -419,61 +419,16 @@ ca_triop_func_fill_data (void *ap, void *ptr)
|
|
|
419
419
|
rb_raise(rb_eRuntimeError, "CATriOp is read-only (fill_data)");
|
|
420
420
|
}
|
|
421
421
|
|
|
422
|
-
/* Build out.mask
|
|
423
|
-
|
|
422
|
+
/* Build out.mask on each read (CAMaskOfOperands): the three operands'
|
|
423
|
+
masks ORed, except for select, which is masked where the condition is
|
|
424
|
+
or where the branch it chooses is. */
|
|
424
425
|
static void
|
|
425
426
|
ca_triop_func_create_mask (void *ap)
|
|
426
427
|
{
|
|
427
428
|
CATriOp *to = (CATriOp *) ap;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
CArray *
|
|
431
|
-
boolean8_t *dst, *m1, *m2, *m3;
|
|
432
|
-
ca_size_t i, n;
|
|
433
|
-
int has1, has2, has3;
|
|
434
|
-
|
|
435
|
-
has1 = ca_has_mask(op1);
|
|
436
|
-
has2 = ca_has_mask(op2);
|
|
437
|
-
has3 = ca_has_mask(op3);
|
|
438
|
-
if ( ! has1 && ! has2 && ! has3 ) return;
|
|
439
|
-
|
|
440
|
-
/* Exactly one masked operand: the answer is that operand's mask, cell
|
|
441
|
-
for cell. Share it rather than allocating a copy per node. */
|
|
442
|
-
if ( has1 + has2 + has3 == 1 ) {
|
|
443
|
-
CArray *src = has1 ? op1 : ( has2 ? op2 : op3 );
|
|
444
|
-
if ( src->elements == to->elements ) {
|
|
445
|
-
to->mask = (CArray *) ca_refer_new(src->mask, CA_BOOLEAN,
|
|
446
|
-
to->ndim, to->dim, 0, 0);
|
|
447
|
-
return;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
to->mask = (CArray *) carray_new(CA_BOOLEAN, to->ndim, to->dim, 0, NULL);
|
|
452
|
-
dst = (boolean8_t *) to->mask->ptr;
|
|
453
|
-
n = to->elements;
|
|
454
|
-
|
|
455
|
-
/* The masks are what is read here; attaching the operand instead
|
|
456
|
-
materialises the whole subexpression under it. */
|
|
457
|
-
if ( has1 ) ca_attach(op1->mask);
|
|
458
|
-
if ( has2 ) ca_attach(op2->mask);
|
|
459
|
-
if ( has3 ) ca_attach(op3->mask);
|
|
460
|
-
|
|
461
|
-
m1 = has1 ? (boolean8_t *) op1->mask->ptr : NULL;
|
|
462
|
-
m2 = has2 ? (boolean8_t *) op2->mask->ptr : NULL;
|
|
463
|
-
m3 = has3 ? (boolean8_t *) op3->mask->ptr : NULL;
|
|
464
|
-
|
|
465
|
-
for ( i = 0; i < n; i++ ) {
|
|
466
|
-
ca_size_t i2 = to->op2_is_scalar ? 0 : i;
|
|
467
|
-
ca_size_t i3 = to->op3_is_scalar ? 0 : i;
|
|
468
|
-
boolean8_t a = m1 ? m1[i] : 0;
|
|
469
|
-
boolean8_t b = m2 ? m2[i2] : 0;
|
|
470
|
-
boolean8_t c = m3 ? m3[i3] : 0;
|
|
471
|
-
dst[i] = (boolean8_t) ( a | b | c );
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if ( has3 ) ca_detach(op3->mask);
|
|
475
|
-
if ( has2 ) ca_detach(op2->mask);
|
|
476
|
-
if ( has1 ) ca_detach(op1->mask);
|
|
429
|
+
int mode = ( to->op_id == CA_TRIOP_SELECT ) ? CA_LAZY_MASK_SELECT
|
|
430
|
+
: CA_LAZY_MASK_OR;
|
|
431
|
+
to->mask = ca_lazy_operation_mask((CArray *) to, mode);
|
|
477
432
|
}
|
|
478
433
|
|
|
479
434
|
ca_operation_function_t ca_triop_func = {
|
|
@@ -574,21 +529,32 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
574
529
|
r2 = collapse_marker(cary2);
|
|
575
530
|
r3 = collapse_marker(cary3);
|
|
576
531
|
|
|
577
|
-
/*
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
532
|
+
/* select takes its branches already typed (CArray#then_else makes a
|
|
533
|
+
scalar branch a CScalar of the result type); the condition is boolean
|
|
534
|
+
and takes no part in the promotion. */
|
|
535
|
+
if ( op_id == CA_TRIOP_SELECT ) {
|
|
536
|
+
if ( ! rb_obj_is_carray(r1) || ! rb_obj_is_carray(r2) || ! rb_obj_is_carray(r3) ) {
|
|
537
|
+
rb_raise(rb_eArgError, "CATriOp: select takes three CArrays");
|
|
538
|
+
}
|
|
539
|
+
r2 = ca_lazy_settle_scalar(r2, RTEST(rb_obj_is_cscalar(r2)));
|
|
540
|
+
r3 = ca_lazy_settle_scalar(r3, RTEST(rb_obj_is_cscalar(r3)));
|
|
541
|
+
}
|
|
542
|
+
/* Scalar operands (clip's Numeric bounds, a CScalar) are wrapped and
|
|
543
|
+
promoted pairwise in the order the eager triop uses. */
|
|
544
|
+
else if ( ! rb_obj_is_carray(r1) || ! rb_obj_is_carray(r2) || ! rb_obj_is_carray(r3) ||
|
|
545
|
+
rb_obj_is_cscalar(r2) || rb_obj_is_cscalar(r3) ) {
|
|
546
|
+
if ( ! rb_obj_is_carray(r1) ) {
|
|
586
547
|
rb_raise(rb_eArgError,
|
|
587
|
-
"CATriOp:
|
|
548
|
+
"CATriOp: the first operand must be a CArray");
|
|
588
549
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
550
|
+
int r2_scalar = ! rb_obj_is_carray(r2) || rb_obj_is_cscalar(r2);
|
|
551
|
+
int r3_scalar = ! rb_obj_is_carray(r3) || rb_obj_is_cscalar(r3);
|
|
552
|
+
rb_ca_cast_self_or_other(&r1, &r2);
|
|
553
|
+
rb_ca_cast_self_or_other(&r1, &r3);
|
|
554
|
+
rb_ca_cast_self_or_other(&r2, &r3);
|
|
555
|
+
rb_ca_cast_self_or_other(&r1, &r2);
|
|
556
|
+
r2 = ca_lazy_settle_scalar(r2, r2_scalar);
|
|
557
|
+
r3 = ca_lazy_settle_scalar(r3, r3_scalar);
|
|
592
558
|
}
|
|
593
559
|
|
|
594
560
|
TypedData_Get_Struct(r1, CArray, &carray_data_type, op1);
|
|
@@ -599,6 +565,19 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
599
565
|
ca_triop_kernel_input_data_types(op_id,
|
|
600
566
|
op1->data_type, op2->data_type, op3->data_type,
|
|
601
567
|
&dt1, &dt2, &dt3);
|
|
568
|
+
|
|
569
|
+
/* All boolean, and no boolean kernel (fma / fms): read the operands as
|
|
570
|
+
their 0/1 storage in int64, as rb_ca_call_triop does. */
|
|
571
|
+
if ( dt1 == CA_BOOLEAN &&
|
|
572
|
+
ca_triop_kernel_lookup_vvv(op_id, CA_BOOLEAN) == ca_triop_not_implement ) {
|
|
573
|
+
dt1 = dt2 = dt3 = CA_INT64;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/* No kernel for that data_type: raise as the eager triop does. */
|
|
577
|
+
if ( ca_triop_kernel_lookup_vvv(op_id, dt1) == ca_triop_not_implement ) {
|
|
578
|
+
rb_raise(rb_eCADataTypeError,
|
|
579
|
+
"invalid data_type for triop (not implemented)");
|
|
580
|
+
}
|
|
602
581
|
r1 = insert_cast(r1, dt1, &op1);
|
|
603
582
|
r2 = insert_cast(r2, dt2, &op2);
|
|
604
583
|
r3 = insert_cast(r3, dt3, &op3);
|
|
@@ -668,6 +647,17 @@ rb_ca_triop_s_build (VALUE klass, VALUE cary1, VALUE cary2, VALUE cary3,
|
|
|
668
647
|
return rb_ca_triop_build(cary1, cary2, cary3, op_id);
|
|
669
648
|
}
|
|
670
649
|
|
|
650
|
+
/* Whether this node's kernel skips the cells its operands mask, rather
|
|
651
|
+
than computing them: a kernel that can raise on a cell or calls Ruby
|
|
652
|
+
for it. CArray::Fusion reads it so a plan carries the same rule. */
|
|
653
|
+
static VALUE
|
|
654
|
+
rb_ca_triop_trapping (VALUE self)
|
|
655
|
+
{
|
|
656
|
+
CArray *ca;
|
|
657
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
658
|
+
return ( ca->data_type == CA_OBJECT ) ? Qtrue : Qfalse;
|
|
659
|
+
}
|
|
660
|
+
|
|
671
661
|
static VALUE
|
|
672
662
|
rb_ca_triop_op_id (VALUE self)
|
|
673
663
|
{
|
|
@@ -731,6 +721,7 @@ rb_ca_triop_initialize_copy (VALUE self, VALUE other)
|
|
|
731
721
|
{
|
|
732
722
|
CATriOp *ca, *cs;
|
|
733
723
|
TypedData_Get_Struct(self, CATriOp, &catriop_data_type, ca);
|
|
724
|
+
ca_check_uninitialized(ca);
|
|
734
725
|
TypedData_Get_Struct(other, CATriOp, &catriop_data_type, cs);
|
|
735
726
|
if ( ca_func[CA_OBJ_TRIOP].pool_init ) {
|
|
736
727
|
ca_array_pool_alloc(ca, CA_OBJ_TRIOP, cs->parent->ndim);
|
|
@@ -758,6 +749,7 @@ Init_ca_obj_triop (void)
|
|
|
758
749
|
rb_define_const(rb_cCATriOp, "OP_FMA", INT2NUM(CA_TRIOP_FMA));
|
|
759
750
|
rb_define_const(rb_cCATriOp, "OP_FMS", INT2NUM(CA_TRIOP_FMS));
|
|
760
751
|
rb_define_const(rb_cCATriOp, "OP_CLIP", INT2NUM(CA_TRIOP_CLIP));
|
|
752
|
+
rb_define_const(rb_cCATriOp, "OP_SELECT", INT2NUM(CA_TRIOP_SELECT));
|
|
761
753
|
|
|
762
754
|
rb_define_alloc_func(rb_cCATriOp, rb_ca_triop_s_allocate);
|
|
763
755
|
rb_define_method(rb_cCATriOp, "initialize_copy",
|
|
@@ -768,6 +760,7 @@ Init_ca_obj_triop (void)
|
|
|
768
760
|
|
|
769
761
|
rb_define_method(rb_cCATriOp, "__op_id__",
|
|
770
762
|
rb_ca_triop_op_id, 0);
|
|
763
|
+
rb_define_method(rb_cCATriOp, "__trapping__", rb_ca_triop_trapping, 0);
|
|
771
764
|
rb_define_method(rb_cCATriOp, "__triop_op2__",
|
|
772
765
|
rb_ca_triop_op2, 0);
|
|
773
766
|
rb_define_method(rb_cCATriOp, "__triop_op3__",
|