carray 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +104 -81
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_obj_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 */
|
|
@@ -163,6 +163,7 @@ ca_triop_setup (CATriOp *ca, CArray *op1, CArray *op2, CArray *op3,
|
|
|
163
163
|
CATriOp *
|
|
164
164
|
ca_triop_new (CArray *op1, CArray *op2, CArray *op3, uint16_t op_id)
|
|
165
165
|
{
|
|
166
|
+
/* check: the setup checks nothing */
|
|
166
167
|
CATriOp *ca = (CATriOp *) ca_array_alloc(CA_OBJ_TRIOP, op1->ndim);
|
|
167
168
|
ca_triop_setup(ca, op1, op2, op3, op_id);
|
|
168
169
|
return ca;
|
|
@@ -210,7 +211,7 @@ ca_triop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
210
211
|
ca_size_t s;
|
|
211
212
|
|
|
212
213
|
if ( dir != CA_XFER_GET ) {
|
|
213
|
-
|
|
214
|
+
ca_refuse_read_only();
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
s = ca->bytes;
|
|
@@ -222,25 +223,6 @@ ca_triop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
222
223
|
ca_triop_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
223
224
|
}
|
|
224
225
|
|
|
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
226
|
/* Test / observability counters (mirror CABinOp's counters). */
|
|
245
227
|
ca_size_t ca_triop_scratch_acquire_count = 0;
|
|
246
228
|
ca_size_t ca_triop_materialise_call_count = 0;
|
|
@@ -249,8 +231,7 @@ ca_size_t ca_triop_materialise_call_count = 0;
|
|
|
249
231
|
be broadcast at step=0). Returns the scratch pointer; updates
|
|
250
232
|
*step_out to 0 (scalar) or 1 (same-shape). */
|
|
251
233
|
static void *
|
|
252
|
-
pull_operand (CArray *op, int is_scalar,
|
|
253
|
-
ca_size_t *counts, ca_size_t slab_n, int8_t ndim,
|
|
234
|
+
pull_operand (CArray *op, int is_scalar, const ca_lazy_req_t *req,
|
|
254
235
|
ca_size_t *step_out)
|
|
255
236
|
{
|
|
256
237
|
void *scratch;
|
|
@@ -274,54 +255,40 @@ pull_operand (CArray *op, int is_scalar, ca_size_t *starts,
|
|
|
274
255
|
*step_out = 0;
|
|
275
256
|
}
|
|
276
257
|
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
258
|
scratch = ( op->data_type == CA_OBJECT )
|
|
284
|
-
? ca_lazy_arena_acquire_object(
|
|
285
|
-
: ca_lazy_arena_acquire(
|
|
259
|
+
? ca_lazy_arena_acquire_object(req->n)
|
|
260
|
+
: ca_lazy_arena_acquire(req->n * bytes);
|
|
286
261
|
ca_triop_scratch_acquire_count++;
|
|
287
|
-
|
|
262
|
+
ca_lazy_req_pull(op, req, scratch, CA_XFER_GET);
|
|
288
263
|
*step_out = 1;
|
|
289
264
|
}
|
|
290
265
|
return scratch;
|
|
291
266
|
}
|
|
292
267
|
|
|
268
|
+
/* Evaluate the cells a request names into `data` (packed, n cells). */
|
|
293
269
|
static void
|
|
294
|
-
|
|
295
|
-
ca_size_t *strides, void *data, int dir)
|
|
270
|
+
ca_triop_eval (CATriOp *to, const ca_lazy_req_t *req, void *data)
|
|
296
271
|
{
|
|
297
|
-
|
|
298
|
-
ca_size_t slab_n;
|
|
299
|
-
int8_t k;
|
|
272
|
+
ca_size_t slab_n = req->n;
|
|
300
273
|
void *scratch2, *scratch3;
|
|
301
274
|
ca_size_t op2_step, op3_step;
|
|
302
275
|
|
|
303
|
-
if ( dir != CA_XFER_GET ) {
|
|
304
|
-
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_stride PUT)");
|
|
305
|
-
}
|
|
306
276
|
ca_triop_materialise_call_count++;
|
|
307
277
|
|
|
308
|
-
slab_n = 1;
|
|
309
|
-
for ( k = 0; k < to->ndim; k++ ) slab_n *= counts[k];
|
|
310
|
-
|
|
311
278
|
/* Step 1: pull op1 into the output buffer. */
|
|
312
|
-
|
|
279
|
+
ca_lazy_req_pull(to->parent, req, data, CA_XFER_GET);
|
|
313
280
|
|
|
314
281
|
/* 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);
|
|
282
|
+
scratch2 = pull_operand(to->op2, to->op2_is_scalar, req, &op2_step);
|
|
317
283
|
|
|
318
284
|
/* 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);
|
|
285
|
+
scratch3 = pull_operand(to->op3, to->op3_is_scalar, req, &op3_step);
|
|
321
286
|
|
|
322
|
-
/* Step 4: apply the kernel. ptr1 == ptr4 (in-place op1)
|
|
323
|
-
|
|
287
|
+
/* Step 4: apply the kernel. ptr1 == ptr4 (in-place op1). No numeric
|
|
288
|
+
triop traps, so m=NULL; object cells call Ruby, and skip the masked
|
|
289
|
+
cells as the eager triop does. */
|
|
324
290
|
{
|
|
291
|
+
boolean8_t *slab_mask = NULL;
|
|
325
292
|
ca_triop_func_t fn = ca_triop_kernel_lookup_vvv(to->op_id, to->data_type);
|
|
326
293
|
if ( fn == NULL ) {
|
|
327
294
|
ca_lazy_arena_release(scratch3);
|
|
@@ -330,17 +297,51 @@ ca_triop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
330
297
|
"CATriOp: kernel not implemented (op_id=%u data_type=%d)",
|
|
331
298
|
(unsigned) to->op_id, (int) to->data_type);
|
|
332
299
|
}
|
|
333
|
-
|
|
300
|
+
if ( ca_op_raises_on_cell(CA_OP_KIND_TRIOP, to->op_id, to->data_type) ) {
|
|
301
|
+
CArray *ops[3];
|
|
302
|
+
ops[0] = to->parent;
|
|
303
|
+
ops[1] = to->op2;
|
|
304
|
+
ops[2] = to->op3;
|
|
305
|
+
slab_mask = ca_lazy_req_mask(req, 3, ops);
|
|
306
|
+
}
|
|
307
|
+
fn(slab_n, slab_mask,
|
|
334
308
|
(char *)data, 1, /* src1 == dst (op1, in-place) */
|
|
335
309
|
(char *)scratch2, op2_step, /* src2 (op2) */
|
|
336
310
|
(char *)scratch3, op3_step, /* src3 (op3) */
|
|
337
311
|
(char *)data, 1); /* dst */
|
|
312
|
+
if ( slab_mask ) ca_lazy_arena_release(slab_mask);
|
|
338
313
|
}
|
|
339
314
|
|
|
340
315
|
ca_lazy_arena_release(scratch3);
|
|
341
316
|
ca_lazy_arena_release(scratch2);
|
|
342
317
|
}
|
|
343
318
|
|
|
319
|
+
static void
|
|
320
|
+
ca_triop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
321
|
+
ca_size_t *strides, void *data, int dir)
|
|
322
|
+
{
|
|
323
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
324
|
+
ca_lazy_req_t req;
|
|
325
|
+
if ( dir != CA_XFER_GET ) {
|
|
326
|
+
ca_refuse_read_only();
|
|
327
|
+
}
|
|
328
|
+
ca_lazy_req_region(&req, ap, starts, counts, strides);
|
|
329
|
+
ca_triop_eval((CATriOp *) ap, &req, data);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/* An address list is evaluated in one pass, as a region is. */
|
|
333
|
+
static void
|
|
334
|
+
ca_triop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
335
|
+
void *data, int dir)
|
|
336
|
+
{
|
|
337
|
+
ca_lazy_req_t req;
|
|
338
|
+
if ( dir != CA_XFER_GET ) {
|
|
339
|
+
ca_refuse_read_only();
|
|
340
|
+
}
|
|
341
|
+
ca_lazy_req_addrs(&req, n, addrs);
|
|
342
|
+
ca_triop_eval((CATriOp *) ap, &req, data);
|
|
343
|
+
}
|
|
344
|
+
|
|
344
345
|
static void
|
|
345
346
|
ca_triop_func_xfer_all (void *ap, void *data, int dir)
|
|
346
347
|
{
|
|
@@ -358,15 +359,7 @@ static void
|
|
|
358
359
|
ca_triop_func_allocate (void *ap)
|
|
359
360
|
{
|
|
360
361
|
CATriOp *ca = (CATriOp *) ap;
|
|
361
|
-
ca->ptr =
|
|
362
|
-
/* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
|
|
363
|
-
soon as the view is, so it must not be handed to the GC as raw
|
|
364
|
-
xmalloc garbage. */
|
|
365
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
366
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
367
|
-
ca_size_t i;
|
|
368
|
-
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
369
|
-
}
|
|
362
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
370
363
|
}
|
|
371
364
|
|
|
372
365
|
static void
|
|
@@ -381,19 +374,11 @@ ca_triop_func_attach (void *ap)
|
|
|
381
374
|
int8_t k;
|
|
382
375
|
ca_size_t s;
|
|
383
376
|
|
|
384
|
-
ca->ptr =
|
|
377
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
385
378
|
|
|
386
379
|
s = ca->bytes;
|
|
387
380
|
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
388
381
|
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
389
|
-
/* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
|
|
390
|
-
soon as the view is, so it must not be handed to the GC as raw
|
|
391
|
-
xmalloc garbage. */
|
|
392
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
393
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
394
|
-
ca_size_t i;
|
|
395
|
-
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
396
|
-
}
|
|
397
382
|
ca_triop_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
|
|
398
383
|
}
|
|
399
384
|
|
|
@@ -416,64 +401,19 @@ static void
|
|
|
416
401
|
ca_triop_func_fill_data (void *ap, void *ptr)
|
|
417
402
|
{
|
|
418
403
|
(void) ap; (void) ptr;
|
|
419
|
-
|
|
404
|
+
ca_refuse_read_only();
|
|
420
405
|
}
|
|
421
406
|
|
|
422
|
-
/* Build out.mask
|
|
423
|
-
|
|
407
|
+
/* Build out.mask on each read (CAMaskOfOperands): the three operands'
|
|
408
|
+
masks ORed, except for select, which is masked where the condition is
|
|
409
|
+
or where the branch it chooses is. */
|
|
424
410
|
static void
|
|
425
411
|
ca_triop_func_create_mask (void *ap)
|
|
426
412
|
{
|
|
427
413
|
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);
|
|
414
|
+
int mode = ( to->op_id == CA_TRIOP_SELECT ) ? CA_LAZY_MASK_SELECT
|
|
415
|
+
: CA_LAZY_MASK_OR;
|
|
416
|
+
to->mask = ca_lazy_operation_mask((CArray *) to, mode);
|
|
477
417
|
}
|
|
478
418
|
|
|
479
419
|
ca_operation_function_t ca_triop_func = {
|
|
@@ -574,21 +514,32 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
574
514
|
r2 = collapse_marker(cary2);
|
|
575
515
|
r3 = collapse_marker(cary3);
|
|
576
516
|
|
|
577
|
-
/*
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
517
|
+
/* select takes its branches already typed (CArray#then_else makes a
|
|
518
|
+
scalar branch a CScalar of the result type); the condition is boolean
|
|
519
|
+
and takes no part in the promotion. */
|
|
520
|
+
if ( op_id == CA_TRIOP_SELECT ) {
|
|
521
|
+
if ( ! rb_obj_is_carray(r1) || ! rb_obj_is_carray(r2) || ! rb_obj_is_carray(r3) ) {
|
|
522
|
+
rb_raise(rb_eArgError, "CATriOp: select takes three CArrays");
|
|
523
|
+
}
|
|
524
|
+
r2 = ca_lazy_settle_scalar(r2, RTEST(rb_obj_is_cscalar(r2)));
|
|
525
|
+
r3 = ca_lazy_settle_scalar(r3, RTEST(rb_obj_is_cscalar(r3)));
|
|
526
|
+
}
|
|
527
|
+
/* Scalar operands (clip's Numeric bounds, a CScalar) are wrapped and
|
|
528
|
+
promoted pairwise in the order the eager triop uses. */
|
|
529
|
+
else if ( ! rb_obj_is_carray(r1) || ! rb_obj_is_carray(r2) || ! rb_obj_is_carray(r3) ||
|
|
530
|
+
rb_obj_is_cscalar(r2) || rb_obj_is_cscalar(r3) ) {
|
|
531
|
+
if ( ! rb_obj_is_carray(r1) ) {
|
|
586
532
|
rb_raise(rb_eArgError,
|
|
587
|
-
"CATriOp:
|
|
533
|
+
"CATriOp: the first operand must be a CArray");
|
|
588
534
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
535
|
+
int r2_scalar = ! rb_obj_is_carray(r2) || rb_obj_is_cscalar(r2);
|
|
536
|
+
int r3_scalar = ! rb_obj_is_carray(r3) || rb_obj_is_cscalar(r3);
|
|
537
|
+
rb_ca_cast_self_or_other(&r1, &r2);
|
|
538
|
+
rb_ca_cast_self_or_other(&r1, &r3);
|
|
539
|
+
rb_ca_cast_self_or_other(&r2, &r3);
|
|
540
|
+
rb_ca_cast_self_or_other(&r1, &r2);
|
|
541
|
+
r2 = ca_lazy_settle_scalar(r2, r2_scalar);
|
|
542
|
+
r3 = ca_lazy_settle_scalar(r3, r3_scalar);
|
|
592
543
|
}
|
|
593
544
|
|
|
594
545
|
TypedData_Get_Struct(r1, CArray, &carray_data_type, op1);
|
|
@@ -599,6 +550,18 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
599
550
|
ca_triop_kernel_input_data_types(op_id,
|
|
600
551
|
op1->data_type, op2->data_type, op3->data_type,
|
|
601
552
|
&dt1, &dt2, &dt3);
|
|
553
|
+
|
|
554
|
+
/* All boolean, and no boolean kernel (fma / fms): read the operands as
|
|
555
|
+
their 0/1 storage in int64, as rb_ca_call_triop does. */
|
|
556
|
+
if ( dt1 == CA_BOOLEAN &&
|
|
557
|
+
ca_triop_kernel_lookup_vvv(op_id, CA_BOOLEAN) == ca_triop_not_implement ) {
|
|
558
|
+
dt1 = dt2 = dt3 = CA_INT64;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/* No kernel for that data_type: raise as the eager triop does. */
|
|
562
|
+
if ( ca_triop_kernel_lookup_vvv(op_id, dt1) == ca_triop_not_implement ) {
|
|
563
|
+
ca_op_refuse_unimplemented(cary1, dt1, rb_eCADataTypeError);
|
|
564
|
+
}
|
|
602
565
|
r1 = insert_cast(r1, dt1, &op1);
|
|
603
566
|
r2 = insert_cast(r2, dt2, &op2);
|
|
604
567
|
r3 = insert_cast(r3, dt3, &op3);
|
|
@@ -610,10 +573,11 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
610
573
|
CArray *anchor = NULL;
|
|
611
574
|
volatile VALUE r_anchor = Qnil;
|
|
612
575
|
int8_t anchor_ndim;
|
|
613
|
-
/*
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
else if (
|
|
576
|
+
/* The first operand that is not a scalar is the anchor. An array of
|
|
577
|
+
no cells is one (its shape is the walk's), not a scalar. */
|
|
578
|
+
if ( ! ca_is_scalar(op1) ) { anchor = op1; r_anchor = r1; }
|
|
579
|
+
else if ( ! ca_is_scalar(op2) ) { anchor = op2; r_anchor = r2; }
|
|
580
|
+
else if ( ! ca_is_scalar(op3) ) { anchor = op3; r_anchor = r3; }
|
|
617
581
|
if ( anchor && anchor != op1 ) {
|
|
618
582
|
/* op1 is a CScalar but the walk shape is determined by another
|
|
619
583
|
operand. Lift op1 up to anchor's shape via
|
|
@@ -663,11 +627,24 @@ static VALUE
|
|
|
663
627
|
rb_ca_triop_s_build (VALUE klass, VALUE cary1, VALUE cary2, VALUE cary3,
|
|
664
628
|
VALUE op_id_val)
|
|
665
629
|
{
|
|
630
|
+
/* fits: an operation number from the library's own table */
|
|
666
631
|
uint16_t op_id = (uint16_t) NUM2UINT(op_id_val);
|
|
667
632
|
(void) klass;
|
|
668
633
|
return rb_ca_triop_build(cary1, cary2, cary3, op_id);
|
|
669
634
|
}
|
|
670
635
|
|
|
636
|
+
/* Whether this node's kernel skips the cells its operands mask, rather
|
|
637
|
+
than computing them: a kernel that can raise on a cell or calls Ruby
|
|
638
|
+
for it. CArray::Fusion reads it so a plan carries the same rule. */
|
|
639
|
+
static VALUE
|
|
640
|
+
rb_ca_triop_trapping (VALUE self)
|
|
641
|
+
{
|
|
642
|
+
CATriOp *to;
|
|
643
|
+
TypedData_Get_Struct(self, CATriOp, &catriop_data_type, to);
|
|
644
|
+
return ca_op_raises_on_cell(CA_OP_KIND_TRIOP, to->op_id, to->data_type)
|
|
645
|
+
? Qtrue : Qfalse;
|
|
646
|
+
}
|
|
647
|
+
|
|
671
648
|
static VALUE
|
|
672
649
|
rb_ca_triop_op_id (VALUE self)
|
|
673
650
|
{
|
|
@@ -689,6 +666,7 @@ rb_ca_triop_op3 (VALUE self)
|
|
|
689
666
|
}
|
|
690
667
|
|
|
691
668
|
/* Test instrumentation. */
|
|
669
|
+
#ifdef CARRAY_DEV_BUILD
|
|
692
670
|
static VALUE
|
|
693
671
|
rb_ca_triop_s_reset_scratch_counter (VALUE klass)
|
|
694
672
|
{
|
|
@@ -718,6 +696,7 @@ rb_ca_triop_s_materialise_count (VALUE klass)
|
|
|
718
696
|
(void) klass;
|
|
719
697
|
return SIZE2NUM(ca_triop_materialise_call_count);
|
|
720
698
|
}
|
|
699
|
+
#endif /* CARRAY_DEV_BUILD */
|
|
721
700
|
|
|
722
701
|
static VALUE
|
|
723
702
|
rb_ca_triop_s_allocate (VALUE klass)
|
|
@@ -731,6 +710,7 @@ rb_ca_triop_initialize_copy (VALUE self, VALUE other)
|
|
|
731
710
|
{
|
|
732
711
|
CATriOp *ca, *cs;
|
|
733
712
|
TypedData_Get_Struct(self, CATriOp, &catriop_data_type, ca);
|
|
713
|
+
ca_check_uninitialized(ca);
|
|
734
714
|
TypedData_Get_Struct(other, CATriOp, &catriop_data_type, cs);
|
|
735
715
|
if ( ca_func[CA_OBJ_TRIOP].pool_init ) {
|
|
736
716
|
ca_array_pool_alloc(ca, CA_OBJ_TRIOP, cs->parent->ndim);
|
|
@@ -758,6 +738,7 @@ Init_ca_obj_triop (void)
|
|
|
758
738
|
rb_define_const(rb_cCATriOp, "OP_FMA", INT2NUM(CA_TRIOP_FMA));
|
|
759
739
|
rb_define_const(rb_cCATriOp, "OP_FMS", INT2NUM(CA_TRIOP_FMS));
|
|
760
740
|
rb_define_const(rb_cCATriOp, "OP_CLIP", INT2NUM(CA_TRIOP_CLIP));
|
|
741
|
+
rb_define_const(rb_cCATriOp, "OP_SELECT", INT2NUM(CA_TRIOP_SELECT));
|
|
761
742
|
|
|
762
743
|
rb_define_alloc_func(rb_cCATriOp, rb_ca_triop_s_allocate);
|
|
763
744
|
rb_define_method(rb_cCATriOp, "initialize_copy",
|
|
@@ -768,12 +749,14 @@ Init_ca_obj_triop (void)
|
|
|
768
749
|
|
|
769
750
|
rb_define_method(rb_cCATriOp, "__op_id__",
|
|
770
751
|
rb_ca_triop_op_id, 0);
|
|
752
|
+
rb_define_method(rb_cCATriOp, "__trapping__", rb_ca_triop_trapping, 0);
|
|
771
753
|
rb_define_method(rb_cCATriOp, "__triop_op2__",
|
|
772
754
|
rb_ca_triop_op2, 0);
|
|
773
755
|
rb_define_method(rb_cCATriOp, "__triop_op3__",
|
|
774
756
|
rb_ca_triop_op3, 0);
|
|
775
757
|
|
|
776
758
|
/* Test instrumentation. */
|
|
759
|
+
#ifdef CARRAY_DEV_BUILD
|
|
777
760
|
rb_define_singleton_method(rb_cCATriOp, "__reset_scratch_counter__",
|
|
778
761
|
rb_ca_triop_s_reset_scratch_counter, 0);
|
|
779
762
|
rb_define_singleton_method(rb_cCATriOp, "__scratch_count__",
|
|
@@ -782,4 +765,5 @@ Init_ca_obj_triop (void)
|
|
|
782
765
|
rb_ca_triop_s_reset_materialise_counter, 0);
|
|
783
766
|
rb_define_singleton_method(rb_cCATriOp, "__materialise_count__",
|
|
784
767
|
rb_ca_triop_s_materialise_count, 0);
|
|
768
|
+
#endif
|
|
785
769
|
}
|