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_monop.c
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
#include "carray.h"
|
|
34
34
|
#include "carray_internal.h" /* ca_lazy_arena_*, ca_is_lazy_view */
|
|
35
35
|
#include "ca_monop_dispatch.h"
|
|
36
|
+
#include "carray_math_kernel.h" /* ca_monop_not_implement */
|
|
36
37
|
|
|
37
38
|
/* ca_cast_block (carray_cast.c) */
|
|
38
39
|
extern void ca_cast_block (ca_size_t n, void *ap1, void *ptr1,
|
|
@@ -221,6 +222,7 @@ ca_monop_setup (CAMonOp *ca, CArray *parent, uint16_t op_id)
|
|
|
221
222
|
CAMonOp *
|
|
222
223
|
ca_monop_new (CArray *parent, uint16_t op_id)
|
|
223
224
|
{
|
|
225
|
+
/* check: the setup checks nothing */
|
|
224
226
|
CAMonOp *ca = (CAMonOp *) ca_array_alloc(CA_OBJ_MONOP, parent->ndim);
|
|
225
227
|
ca_monop_setup(ca, parent, op_id);
|
|
226
228
|
return ca;
|
|
@@ -281,14 +283,13 @@ ca_monop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
281
283
|
/* PUT: only writable-view op_ids accept writes (cast, or byte_swap
|
|
282
284
|
involution). */
|
|
283
285
|
if ( ! ca_monop_is_writable_view(ca->op_id) ) {
|
|
284
|
-
|
|
286
|
+
ca_refuse_read_only();
|
|
285
287
|
}
|
|
286
288
|
{
|
|
287
|
-
|
|
289
|
+
volatile VALUE holder;
|
|
288
290
|
ca_size_t bytes_per_cell = (ca_monop_is_cast(ca->op_id))
|
|
289
291
|
? ca->parent->bytes : ca->bytes;
|
|
290
|
-
char *p = (
|
|
291
|
-
: (char *) ALLOC_N(char, bytes_per_cell);
|
|
292
|
+
char *p = ALLOCV_N(char, holder, bytes_per_cell);
|
|
292
293
|
if ( ca_monop_is_cast(ca->op_id) ) {
|
|
293
294
|
/* Reverse-cast view-data_type `data` to parent data_type scratch, then
|
|
294
295
|
store into parent at idx[]. */
|
|
@@ -301,7 +302,7 @@ ca_monop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
301
302
|
ca_byte_swap_buffer(ca->data_type, ca->bytes, 1, p);
|
|
302
303
|
}
|
|
303
304
|
ca_store_index(ca->parent, idx, p);
|
|
304
|
-
|
|
305
|
+
ALLOCV_END(holder);
|
|
305
306
|
}
|
|
306
307
|
return;
|
|
307
308
|
}
|
|
@@ -316,38 +317,6 @@ ca_monop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
316
317
|
ca_monop_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
317
318
|
}
|
|
318
319
|
|
|
319
|
-
static void
|
|
320
|
-
ca_monop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
321
|
-
void *data, int dir)
|
|
322
|
-
{
|
|
323
|
-
CAMonOp *ca = (CAMonOp *) ap;
|
|
324
|
-
ca_size_t i;
|
|
325
|
-
char *out = (char *) data;
|
|
326
|
-
|
|
327
|
-
if ( dir != CA_XFER_GET ) {
|
|
328
|
-
/* PUT: only writable-view op_ids accept writes. */
|
|
329
|
-
if ( ! ca_monop_is_writable_view(ca->op_id) ) {
|
|
330
|
-
rb_raise(rb_eRuntimeError, "CAMonOp is read-only (xfer_addrs PUT)");
|
|
331
|
-
}
|
|
332
|
-
/* Per-cell loop: forward to xfer_index PUT (handles cast/byte_swap
|
|
333
|
-
branch internally). */
|
|
334
|
-
for ( i = 0; i < n; i++ ) {
|
|
335
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
336
|
-
ca_addr2index((CArray *)ca, addrs[i], idx);
|
|
337
|
-
ca_monop_func_xfer_index(ca, idx, out + i * ca->bytes, CA_XFER_PUT);
|
|
338
|
-
}
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/* Naive per-addr loop: convert addr → idx, then xfer_index. This path
|
|
343
|
-
is not optimised. */
|
|
344
|
-
for ( i = 0; i < n; i++ ) {
|
|
345
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
346
|
-
ca_addr2index((CArray *)ca, addrs[i], idx);
|
|
347
|
-
ca_monop_func_xfer_index(ca, idx, out + i * ca->bytes, CA_XFER_GET);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
320
|
/* ------------------------------------------------------------------- */
|
|
352
321
|
/* In-place chain eval (scratch = 0) */
|
|
353
322
|
/* ------------------------------------------------------------------- */
|
|
@@ -369,27 +338,28 @@ ca_size_t ca_monop_materialise_call_count = 0;
|
|
|
369
338
|
#define CA_MAX_LAZY_DEPTH 256
|
|
370
339
|
#endif
|
|
371
340
|
|
|
341
|
+
/* Whether a cast from `from` to `to` raises on a NaN cell: a float or
|
|
342
|
+
complex value has no integer for NaN. */
|
|
343
|
+
static int
|
|
344
|
+
ca_monop_cast_refuses_nan (int8_t from, int8_t to)
|
|
345
|
+
{
|
|
346
|
+
int from_float = ( from == CA_FLOAT32 || from == CA_FLOAT64 ||
|
|
347
|
+
from == CA_CMPLX64 || from == CA_CMPLX128 );
|
|
348
|
+
return from_float && to >= CA_INT8 && to <= CA_UINT64;
|
|
349
|
+
}
|
|
350
|
+
|
|
372
351
|
/* Apply a single op in-place on `data` (src == dst, unit element stride).
|
|
373
352
|
Raises if the kernel is not implemented for the given input data_type.
|
|
374
353
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
the attach lifecycle (ca_monop_func_create_mask + parent.mask
|
|
382
|
-
CARefer), so reads of masked cells return UNDEF regardless of byte
|
|
383
|
-
contents. The mask marks cells as undefined; it does not guard their
|
|
384
|
-
bytes, so writing garbage into a masked cell is licensed.
|
|
385
|
-
|
|
386
|
-
A "partial mask slow path" (= a cell-wise branch to skip masked-cell
|
|
387
|
-
compute) is a possible future micro-optimisation; it is not done
|
|
388
|
-
because masked-cell compute does not affect correctness and the SIMD
|
|
389
|
-
path is faster overall for typical mask densities. */
|
|
354
|
+
`mask` is NULL except for an op that can raise on a cell: the kernel
|
|
355
|
+
then takes the SIMD-friendly "no mask" branch and computes the masked
|
|
356
|
+
cells too. Their bytes are unobservable -- the output mask is the
|
|
357
|
+
parent's (ca_monop_func_create_mask) -- and the mask marks cells as
|
|
358
|
+
undefined rather than guarding their bytes, so writing anything into a
|
|
359
|
+
masked cell is licensed. */
|
|
390
360
|
static void
|
|
391
361
|
apply_monop_in_place (uint16_t op_id, int8_t cur_dt,
|
|
392
|
-
ca_size_t slab_n, void *data)
|
|
362
|
+
ca_size_t slab_n, void *data, boolean8_t *mask)
|
|
393
363
|
{
|
|
394
364
|
ca_monop_func_t fn = ca_monop_kernel_lookup(op_id, cur_dt);
|
|
395
365
|
if ( fn == NULL ) {
|
|
@@ -397,7 +367,7 @@ apply_monop_in_place (uint16_t op_id, int8_t cur_dt,
|
|
|
397
367
|
"CAMonOp: kernel not implemented (op_id=%u data_type=%d)",
|
|
398
368
|
(unsigned) op_id, (int) cur_dt);
|
|
399
369
|
}
|
|
400
|
-
fn(slab_n,
|
|
370
|
+
fn(slab_n, mask, (char *) data, 1, (char *) data, 1);
|
|
401
371
|
}
|
|
402
372
|
|
|
403
373
|
/* Minimal CArray-shaped stub used as ca_cast_block's data_type-only carrier.
|
|
@@ -434,38 +404,25 @@ typedef struct {
|
|
|
434
404
|
static int8_t
|
|
435
405
|
pull_leaf_with_optional_cast (CArray *leaf, uint16_t innermost_op,
|
|
436
406
|
int has_cast_at_leaf, int8_t out_bytes,
|
|
437
|
-
|
|
438
|
-
ca_size_t *starts, ca_size_t *counts,
|
|
439
|
-
ca_size_t *strides, void *data)
|
|
407
|
+
const ca_lazy_req_t *req, void *data)
|
|
440
408
|
{
|
|
441
409
|
ca_size_t leaf_bytes = leaf->bytes;
|
|
410
|
+
ca_size_t slab_n = req->n;
|
|
442
411
|
|
|
443
412
|
/* Path 1: no size mismatch, no cast — direct pull. */
|
|
444
413
|
if ( leaf_bytes == out_bytes && ! has_cast_at_leaf ) {
|
|
445
|
-
|
|
414
|
+
ca_lazy_req_pull(leaf, req, data, CA_XFER_GET);
|
|
446
415
|
return leaf->data_type;
|
|
447
416
|
}
|
|
448
417
|
|
|
449
|
-
/* Paths 2 & 3 both
|
|
450
|
-
for the leaf pull. */
|
|
451
|
-
ca_size_t parent_strides[CA_RANK_MAX];
|
|
418
|
+
/* Paths 2 & 3 both pull the leaf into a leaf-sized scratch. */
|
|
452
419
|
ca_size_t total_bytes = slab_n * leaf_bytes;
|
|
453
420
|
void *scratch;
|
|
454
|
-
volatile VALUE holder;
|
|
455
|
-
int8_t k;
|
|
456
|
-
{
|
|
457
|
-
ca_size_t s = leaf_bytes;
|
|
458
|
-
for ( k = leaf->ndim - 1; k >= 0; k-- ) {
|
|
459
|
-
parent_strides[k] = s;
|
|
460
|
-
s *= counts[k];
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
(void) holder;
|
|
464
421
|
scratch = ( leaf->data_type == CA_OBJECT )
|
|
465
422
|
? ca_lazy_arena_acquire_object(slab_n)
|
|
466
423
|
: ca_lazy_arena_acquire(total_bytes);
|
|
467
424
|
ca_monop_scratch_acquire_count++;
|
|
468
|
-
|
|
425
|
+
ca_lazy_req_pull(leaf, req, scratch, CA_XFER_GET);
|
|
469
426
|
|
|
470
427
|
int8_t result_dt;
|
|
471
428
|
if ( has_cast_at_leaf ) {
|
|
@@ -486,20 +443,21 @@ pull_leaf_with_optional_cast (CArray *leaf, uint16_t innermost_op,
|
|
|
486
443
|
return result_dt;
|
|
487
444
|
}
|
|
488
445
|
|
|
446
|
+
/* Evaluate (GET) or write (PUT, writable views only) the cells a request
|
|
447
|
+
names; `data` holds them packed. */
|
|
489
448
|
static void
|
|
490
|
-
|
|
491
|
-
ca_size_t *strides, void *data, int dir)
|
|
449
|
+
ca_monop_eval (CAMonOp *mo, const ca_lazy_req_t *req, void *data, int dir)
|
|
492
450
|
{
|
|
493
|
-
CAMonOp *mo = (CAMonOp *) ap;
|
|
494
451
|
uint16_t op_chain[CA_MAX_LAZY_DEPTH];
|
|
495
452
|
int chain_len = 0;
|
|
496
453
|
CArray *leaf;
|
|
497
|
-
ca_size_t slab_n;
|
|
498
|
-
int8_t k;
|
|
454
|
+
ca_size_t slab_n = req->n;
|
|
499
455
|
int8_t cur_dt;
|
|
500
456
|
int i;
|
|
501
457
|
int has_cast_at_leaf = 0;
|
|
502
458
|
int chain_apply_count;
|
|
459
|
+
boolean8_t *slab_mask = NULL;
|
|
460
|
+
int mask_taken = 0;
|
|
503
461
|
|
|
504
462
|
/* Writable-view op_ids (cast / byte_swap) use CAFake-style xfer_stride
|
|
505
463
|
for both GET and PUT. This avoids the chain-materialise inline path
|
|
@@ -510,22 +468,34 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
510
468
|
- byte_swap: same data_type → pstrides = strides; involution apply. */
|
|
511
469
|
if ( ca_monop_is_writable_view(mo->op_id) ) {
|
|
512
470
|
int is_cast = ca_monop_is_cast(mo->op_id);
|
|
513
|
-
ca_size_t
|
|
514
|
-
ca_size_t n = 1;
|
|
471
|
+
ca_size_t n = slab_n;
|
|
515
472
|
ca_size_t parent_bytes = is_cast ? mo->parent->bytes : mo->bytes;
|
|
516
|
-
int8_t kk;
|
|
517
473
|
char *v;
|
|
518
474
|
volatile VALUE holder;
|
|
519
|
-
for ( kk = 0; kk < mo->ndim; kk++ ) {
|
|
520
|
-
n *= counts[kk];
|
|
521
|
-
pstrides[kk] = is_cast
|
|
522
|
-
? (strides[kk] / mo->bytes * mo->parent->bytes)
|
|
523
|
-
: strides[kk];
|
|
524
|
-
}
|
|
525
475
|
v = ALLOCV_N(char, holder, n * parent_bytes);
|
|
526
476
|
if ( dir == CA_XFER_GET ) {
|
|
527
|
-
|
|
528
|
-
if ( is_cast
|
|
477
|
+
ca_lazy_req_pull(mo->parent, req, v, CA_XFER_GET);
|
|
478
|
+
if ( is_cast && ca_monop_cast_refuses_nan(mo->parent->data_type,
|
|
479
|
+
mo->data_type) ) {
|
|
480
|
+
/* The cast raises on a NaN cell it is asked to convert; a masked
|
|
481
|
+
cell (mask_invalid keeps the NaN under the mask) is skipped.
|
|
482
|
+
The mask is copied off the arena first so a raise leaves no
|
|
483
|
+
arena slot held. */
|
|
484
|
+
CArray *parent = mo->parent;
|
|
485
|
+
boolean8_t *arena_mask = ca_lazy_req_mask(req, 1, &parent);
|
|
486
|
+
boolean8_t *m = NULL;
|
|
487
|
+
volatile VALUE mholder = 0;
|
|
488
|
+
if ( arena_mask ) {
|
|
489
|
+
m = ALLOCV_N(boolean8_t, mholder, n);
|
|
490
|
+
memcpy(m, arena_mask, n);
|
|
491
|
+
ca_lazy_arena_release(arena_mask);
|
|
492
|
+
}
|
|
493
|
+
ca_cast_block_with_mask(n, mo->parent, v, (CArray *) mo, data, m);
|
|
494
|
+
if ( m ) {
|
|
495
|
+
ALLOCV_END(mholder);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
else if ( is_cast ) {
|
|
529
499
|
ca_cast_block(n, mo->parent, v, (CArray *) mo, data);
|
|
530
500
|
}
|
|
531
501
|
else {
|
|
@@ -543,7 +513,7 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
543
513
|
memcpy(v, data, n * mo->bytes);
|
|
544
514
|
ca_byte_swap_buffer(mo->data_type, mo->bytes, n, v);
|
|
545
515
|
}
|
|
546
|
-
|
|
516
|
+
ca_lazy_req_pull(mo->parent, req, v, CA_XFER_PUT);
|
|
547
517
|
}
|
|
548
518
|
ALLOCV_END(holder);
|
|
549
519
|
return;
|
|
@@ -552,7 +522,7 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
552
522
|
/* Writable-view op_id PUT/GET is handled above. Below: non-writable
|
|
553
523
|
monop/monfunc. PUT is read-only. */
|
|
554
524
|
if ( dir != CA_XFER_GET ) {
|
|
555
|
-
|
|
525
|
+
ca_refuse_read_only();
|
|
556
526
|
}
|
|
557
527
|
ca_monop_materialise_call_count++;
|
|
558
528
|
|
|
@@ -564,8 +534,8 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
564
534
|
while ( leaf->obj_type == CA_OBJ_MONOP ) {
|
|
565
535
|
CAMonOp *node = (CAMonOp *) leaf;
|
|
566
536
|
if ( chain_len >= CA_MAX_LAZY_DEPTH ) {
|
|
567
|
-
rb_raise(
|
|
568
|
-
"
|
|
537
|
+
rb_raise(rb_eArgError,
|
|
538
|
+
"lazy expression too deep: more than %d operations in a chain",
|
|
569
539
|
CA_MAX_LAZY_DEPTH);
|
|
570
540
|
}
|
|
571
541
|
op_chain[chain_len++] = node->op_id;
|
|
@@ -586,16 +556,12 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
586
556
|
}
|
|
587
557
|
|
|
588
558
|
/* === 2. pull leaf into output buffer (with optional cast) === */
|
|
589
|
-
slab_n = 1;
|
|
590
|
-
for ( k = 0; k < mo->ndim; k++ ) {
|
|
591
|
-
slab_n *= counts[k];
|
|
592
|
-
}
|
|
593
559
|
cur_dt = pull_leaf_with_optional_cast(
|
|
594
560
|
leaf,
|
|
595
561
|
has_cast_at_leaf ? op_chain[chain_len - 1] : 0,
|
|
596
562
|
has_cast_at_leaf,
|
|
597
563
|
(int8_t) mo->bytes,
|
|
598
|
-
|
|
564
|
+
req, data
|
|
599
565
|
);
|
|
600
566
|
|
|
601
567
|
/* === 3. apply remaining chain in reverse (leaf side → outermost) ===
|
|
@@ -626,10 +592,38 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
626
592
|
ca_lazy_arena_release(scratch);
|
|
627
593
|
cur_dt = target_dt;
|
|
628
594
|
} else {
|
|
629
|
-
|
|
595
|
+
if ( ! mask_taken && ca_op_raises_on_cell(CA_OP_KIND_MONOP, op_id, cur_dt) ) {
|
|
596
|
+
slab_mask = ca_lazy_req_mask(req, 1, &leaf);
|
|
597
|
+
mask_taken = 1;
|
|
598
|
+
}
|
|
599
|
+
apply_monop_in_place(op_id, cur_dt, slab_n, data,
|
|
600
|
+
ca_op_raises_on_cell(CA_OP_KIND_MONOP, op_id, cur_dt) ? slab_mask : NULL);
|
|
630
601
|
cur_dt = ca_lazy_promote_monop(op_id, cur_dt);
|
|
631
602
|
}
|
|
632
603
|
}
|
|
604
|
+
if ( slab_mask ) {
|
|
605
|
+
ca_lazy_arena_release(slab_mask);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
static void
|
|
610
|
+
ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
611
|
+
ca_size_t *strides, void *data, int dir)
|
|
612
|
+
{
|
|
613
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
614
|
+
ca_lazy_req_t req;
|
|
615
|
+
ca_lazy_req_region(&req, ap, starts, counts, strides);
|
|
616
|
+
ca_monop_eval((CAMonOp *) ap, &req, data, dir);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/* An address list is evaluated in one pass, as a region is. */
|
|
620
|
+
static void
|
|
621
|
+
ca_monop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
622
|
+
void *data, int dir)
|
|
623
|
+
{
|
|
624
|
+
ca_lazy_req_t req;
|
|
625
|
+
ca_lazy_req_addrs(&req, n, addrs);
|
|
626
|
+
ca_monop_eval((CAMonOp *) ap, &req, data, dir);
|
|
633
627
|
}
|
|
634
628
|
|
|
635
629
|
static void
|
|
@@ -663,16 +657,7 @@ ca_monop_func_allocate (void *ap)
|
|
|
663
657
|
if ( ca_monop_is_writable_view(ca->op_id) ) {
|
|
664
658
|
ca_attach(ca->parent);
|
|
665
659
|
}
|
|
666
|
-
ca->ptr =
|
|
667
|
-
/* CA_OBJECT initialisation for GC safety. */
|
|
668
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
669
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
670
|
-
VALUE zero = SIZE2NUM(0);
|
|
671
|
-
ca_size_t i;
|
|
672
|
-
for ( i = 0; i < ca->elements; i++ ) {
|
|
673
|
-
*p++ = zero;
|
|
674
|
-
}
|
|
675
|
-
}
|
|
660
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
676
661
|
}
|
|
677
662
|
|
|
678
663
|
static void
|
|
@@ -701,22 +686,19 @@ ca_monop_func_attach (void *ap)
|
|
|
701
686
|
Mirrors CAFake.attach. */
|
|
702
687
|
if ( ca_monop_is_writable_view(ca->op_id) ) {
|
|
703
688
|
ca_attach(ca->parent);
|
|
704
|
-
ca->ptr =
|
|
705
|
-
/* CA_OBJECT initialisation for GC safety (mirrors CAFake.allocate):
|
|
706
|
-
zero-init the VALUE cells before any potential GC can observe
|
|
707
|
-
them. */
|
|
708
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
709
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
710
|
-
VALUE zero = SIZE2NUM(0);
|
|
711
|
-
ca_size_t i;
|
|
712
|
-
for ( i = 0; i < ca->elements; i++ ) {
|
|
713
|
-
*p++ = zero;
|
|
714
|
-
}
|
|
715
|
-
}
|
|
689
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
716
690
|
if ( ca_monop_is_cast(ca->op_id) ) {
|
|
717
|
-
/* Cast parent.ptr (parent data_type) → ca.ptr (cast target data_type).
|
|
718
|
-
|
|
719
|
-
|
|
691
|
+
/* Cast parent.ptr (parent data_type) → ca.ptr (cast target data_type).
|
|
692
|
+
A cast that raises on NaN skips the masked cells; the parent's
|
|
693
|
+
mask is attached with the parent. A raise here is undone by
|
|
694
|
+
ca_attach, which calls the detach slot once ca->ptr is set. */
|
|
695
|
+
boolean8_t *m = NULL;
|
|
696
|
+
if ( ca_monop_cast_refuses_nan(ca->parent->data_type, ca->data_type)
|
|
697
|
+
&& ca_has_mask(ca->parent) ) {
|
|
698
|
+
m = (boolean8_t *) ca->parent->mask->ptr;
|
|
699
|
+
}
|
|
700
|
+
ca_cast_block_with_mask(ca->elements, ca->parent, ca->parent->ptr,
|
|
701
|
+
(CArray *) ca, ca->ptr, m);
|
|
720
702
|
}
|
|
721
703
|
else {
|
|
722
704
|
/* byte_swap: memcpy parent.ptr → ca.ptr (same data_type same bytes),
|
|
@@ -727,19 +709,11 @@ ca_monop_func_attach (void *ap)
|
|
|
727
709
|
return;
|
|
728
710
|
}
|
|
729
711
|
|
|
730
|
-
ca->ptr =
|
|
712
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
731
713
|
|
|
732
714
|
s = ca->bytes;
|
|
733
715
|
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
734
716
|
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
735
|
-
/* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
|
|
736
|
-
soon as the view is, so it must not be handed to the GC as raw
|
|
737
|
-
xmalloc garbage. */
|
|
738
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
739
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
740
|
-
ca_size_t i;
|
|
741
|
-
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
742
|
-
}
|
|
743
717
|
ca_monop_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
|
|
744
718
|
}
|
|
745
719
|
|
|
@@ -774,10 +748,12 @@ ca_monop_func_sync (void *ap)
|
|
|
774
748
|
}
|
|
775
749
|
}
|
|
776
750
|
else {
|
|
777
|
-
/* byte_swap (involution):
|
|
778
|
-
|
|
779
|
-
|
|
751
|
+
/* byte_swap (involution): swap a copy back to the parent's byte order.
|
|
752
|
+
Not ca.ptr in place -- the window stays open after a sync, and a
|
|
753
|
+
second sync (a stack holding this view twice) would swap it again. */
|
|
780
754
|
memcpy(ca->parent->ptr, ca->ptr, ca_length(ca));
|
|
755
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, ca->elements,
|
|
756
|
+
ca->parent->ptr);
|
|
781
757
|
}
|
|
782
758
|
ca_sync(ca->parent);
|
|
783
759
|
}
|
|
@@ -805,14 +781,13 @@ ca_monop_func_fill_data (void *ap, void *ptr)
|
|
|
805
781
|
data_type (= same bytes for byte_swap, reverse-cast for cast).
|
|
806
782
|
Non-writable monop/monfunc remains read-only. */
|
|
807
783
|
if ( ! ca_monop_is_writable_view(ca->op_id) ) {
|
|
808
|
-
|
|
784
|
+
ca_refuse_read_only();
|
|
809
785
|
}
|
|
810
786
|
{
|
|
811
787
|
int is_cast = ca_monop_is_cast(ca->op_id);
|
|
812
788
|
ca_size_t parent_bytes = is_cast ? ca->parent->bytes : ca->bytes;
|
|
813
|
-
|
|
814
|
-
char *v = (
|
|
815
|
-
: (char *) xmalloc(parent_bytes);
|
|
789
|
+
volatile VALUE holder;
|
|
790
|
+
char *v = ALLOCV_N(char, holder, parent_bytes);
|
|
816
791
|
if ( is_cast ) {
|
|
817
792
|
ca_ptr2ptr((CArray *) ca, ptr, ca->parent, v);
|
|
818
793
|
}
|
|
@@ -821,7 +796,7 @@ ca_monop_func_fill_data (void *ap, void *ptr)
|
|
|
821
796
|
ca_byte_swap_buffer(ca->data_type, ca->bytes, 1, v);
|
|
822
797
|
}
|
|
823
798
|
ca_fill(ca->parent, v);
|
|
824
|
-
|
|
799
|
+
ALLOCV_END(holder);
|
|
825
800
|
}
|
|
826
801
|
}
|
|
827
802
|
|
|
@@ -829,12 +804,12 @@ static void
|
|
|
829
804
|
ca_monop_func_create_mask (void *ap)
|
|
830
805
|
{
|
|
831
806
|
CAMonOp *ca = (CAMonOp *) ap;
|
|
832
|
-
|
|
833
|
-
|
|
807
|
+
ca_view_func_create_mask(ca);
|
|
808
|
+
/* A cast view writes through to its parent, mask included; any other
|
|
809
|
+
operation is read-only and so is its mask. */
|
|
810
|
+
if ( ca_test_flag(ca, CA_FLAG_READ_ONLY) ) {
|
|
811
|
+
ca_set_flag(ca->mask, CA_FLAG_READ_ONLY);
|
|
834
812
|
}
|
|
835
|
-
ca->mask =
|
|
836
|
-
(CArray *) ca_refer_new(ca->parent->mask,
|
|
837
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
838
813
|
}
|
|
839
814
|
|
|
840
815
|
ca_operation_function_t ca_monop_func = {
|
|
@@ -933,8 +908,41 @@ rb_ca_monop_build (VALUE cary, uint16_t op_id)
|
|
|
933
908
|
}
|
|
934
909
|
|
|
935
910
|
parent_dt = parent->data_type;
|
|
911
|
+
|
|
912
|
+
/* A boolean parent, as rb_ca_call_monop and the data_type-changing
|
|
913
|
+
monops treat it: a math function wants an explicit cast, and an op
|
|
914
|
+
with no boolean kernel reads the 0/1 storage in int64. */
|
|
915
|
+
if ( parent_dt == CA_BOOLEAN && ! ca_monop_is_writable_view(op_id) ) {
|
|
916
|
+
if ( ca_monop_is_widening(op_id) ) {
|
|
917
|
+
/* the eager monop reads a boolean with no kernel as int64 (0/1), and
|
|
918
|
+
names that type in its refusal */
|
|
919
|
+
ca_op_refuse_unimplemented(cary, CA_INT64, rb_eCADataTypeError);
|
|
920
|
+
}
|
|
921
|
+
if ( ca_monop_kernel_lookup(op_id, CA_BOOLEAN) == ca_monop_not_implement ) {
|
|
922
|
+
target = rb_ca_monop_new(target, CA_MONOP_CAST_BASE + CA_INT64);
|
|
923
|
+
TypedData_Get_Struct(target, CArray, &carray_data_type, parent);
|
|
924
|
+
parent_dt = CA_INT64;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
936
928
|
kernel_in_dt = ca_monop_kernel_input_data_type(op_id, parent_dt);
|
|
937
929
|
|
|
930
|
+
/* No kernel for the parent, nor one a cast could reach (a fixlen cell
|
|
931
|
+
converts to nothing numeric): raise as the eager monop does, before
|
|
932
|
+
a view is built over it. */
|
|
933
|
+
if ( ! ca_monop_is_writable_view(op_id) &&
|
|
934
|
+
( ca_monop_kernel_lookup(op_id, kernel_in_dt) == ca_monop_not_implement ||
|
|
935
|
+
( parent_dt == CA_FIXLEN &&
|
|
936
|
+
ca_monop_kernel_lookup(op_id, CA_FIXLEN) == ca_monop_not_implement ) ) ) {
|
|
937
|
+
/* the eager monop takes an integer to float64 before it looks for the
|
|
938
|
+
kernel, and names the type it looked in */
|
|
939
|
+
ca_op_refuse_unimplemented(cary,
|
|
940
|
+
parent_dt == CA_FIXLEN ? CA_FIXLEN
|
|
941
|
+
: RTEST(rb_ca_is_integer_type(cary)) ? CA_FLOAT64
|
|
942
|
+
: kernel_in_dt,
|
|
943
|
+
rb_eCADataTypeError);
|
|
944
|
+
}
|
|
945
|
+
|
|
938
946
|
/* Insert cast node if the kernel wants a different input data_type. */
|
|
939
947
|
if ( kernel_in_dt != parent_dt ) {
|
|
940
948
|
uint16_t cast_op_id = CA_MONOP_CAST_BASE + (uint16_t) kernel_in_dt;
|
|
@@ -949,6 +957,7 @@ rb_ca_monop_build (VALUE cary, uint16_t op_id)
|
|
|
949
957
|
static VALUE
|
|
950
958
|
rb_ca_monop_s_build (VALUE klass, VALUE cary, VALUE op_id_val)
|
|
951
959
|
{
|
|
960
|
+
/* fits: an operation number from the library's own table */
|
|
952
961
|
uint16_t op_id = (uint16_t) NUM2UINT(op_id_val);
|
|
953
962
|
(void) klass;
|
|
954
963
|
return rb_ca_monop_build(cary, op_id);
|
|
@@ -964,6 +973,19 @@ rb_ca_is_lazy_view_p (VALUE self)
|
|
|
964
973
|
}
|
|
965
974
|
|
|
966
975
|
/* Read CAMonOp's op_id for inspect/dump_tree consumers in Ruby. */
|
|
976
|
+
/* Whether this node's kernel skips the cells its operands mask, rather
|
|
977
|
+
than computing them: a kernel that can raise on a cell or calls Ruby
|
|
978
|
+
for it. CArray::Fusion reads it so a plan carries the same rule. */
|
|
979
|
+
static VALUE
|
|
980
|
+
rb_ca_monop_trapping (VALUE self)
|
|
981
|
+
{
|
|
982
|
+
CAMonOp *mo;
|
|
983
|
+
TypedData_Get_Struct(self, CAMonOp, &camonop_data_type, mo);
|
|
984
|
+
return ( ! ca_monop_is_cast(mo->op_id)
|
|
985
|
+
&& ca_op_raises_on_cell(CA_OP_KIND_MONOP, mo->op_id, mo->parent->data_type) )
|
|
986
|
+
? Qtrue : Qfalse;
|
|
987
|
+
}
|
|
988
|
+
|
|
967
989
|
static VALUE
|
|
968
990
|
rb_ca_monop_op_id (VALUE self)
|
|
969
991
|
{
|
|
@@ -980,6 +1002,7 @@ rb_ca_monop_op_id (VALUE self)
|
|
|
980
1002
|
because in-place chain eval allocates no scratch; only attach (xfer_all
|
|
981
1003
|
→ output) and the parent's own xfer_stride alloc, neither of which we
|
|
982
1004
|
count here. */
|
|
1005
|
+
#ifdef CARRAY_DEV_BUILD
|
|
983
1006
|
static VALUE
|
|
984
1007
|
rb_ca_monop_s_reset_scratch_counter (VALUE klass)
|
|
985
1008
|
{
|
|
@@ -1005,6 +1028,7 @@ rb_ca_monop_s_materialise_count (VALUE klass)
|
|
|
1005
1028
|
{
|
|
1006
1029
|
return SIZE2NUM(ca_monop_materialise_call_count);
|
|
1007
1030
|
}
|
|
1031
|
+
#endif /* CARRAY_DEV_BUILD */
|
|
1008
1032
|
|
|
1009
1033
|
static VALUE
|
|
1010
1034
|
rb_ca_monop_s_allocate (VALUE klass)
|
|
@@ -1018,6 +1042,7 @@ rb_ca_monop_initialize_copy (VALUE self, VALUE other)
|
|
|
1018
1042
|
{
|
|
1019
1043
|
CAMonOp *ca, *cs;
|
|
1020
1044
|
TypedData_Get_Struct(self, CAMonOp, &camonop_data_type, ca);
|
|
1045
|
+
ca_check_uninitialized(ca);
|
|
1021
1046
|
TypedData_Get_Struct(other, CAMonOp, &camonop_data_type, cs);
|
|
1022
1047
|
if ( ca_func[CA_OBJ_MONOP].pool_init ) {
|
|
1023
1048
|
ca_array_pool_alloc(ca, CA_OBJ_MONOP, cs->parent->ndim);
|
|
@@ -1102,16 +1127,18 @@ Init_ca_obj_monop (void)
|
|
|
1102
1127
|
rb_define_singleton_method(rb_cCAMonOp, "__build__",
|
|
1103
1128
|
rb_ca_monop_s_build, 2);
|
|
1104
1129
|
|
|
1105
|
-
/* Lazy-view predicate
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1130
|
+
/* Lazy-view predicate on CArray (covers CAMonOp and CALazyMarker).
|
|
1131
|
+
Protected: the lazy dispatch asks it of the other operands. */
|
|
1132
|
+
rb_define_protected_method(rb_cCArray, "lazy_view?",
|
|
1133
|
+
rb_ca_is_lazy_view_p, 0);
|
|
1109
1134
|
|
|
1110
1135
|
/* op_id accessor for inspect / dump_tree consumers in Ruby. */
|
|
1111
1136
|
rb_define_method(rb_cCAMonOp, "__op_id__",
|
|
1112
1137
|
rb_ca_monop_op_id, 0);
|
|
1138
|
+
rb_define_method(rb_cCAMonOp, "__trapping__", rb_ca_monop_trapping, 0);
|
|
1113
1139
|
|
|
1114
1140
|
/* Test instrumentation (not user-facing API). */
|
|
1141
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1115
1142
|
rb_define_singleton_method(rb_cCAMonOp, "__reset_scratch_counter__",
|
|
1116
1143
|
rb_ca_monop_s_reset_scratch_counter, 0);
|
|
1117
1144
|
rb_define_singleton_method(rb_cCAMonOp, "__scratch_count__",
|
|
@@ -1120,4 +1147,5 @@ Init_ca_obj_monop (void)
|
|
|
1120
1147
|
rb_ca_monop_s_reset_materialise_counter, 0);
|
|
1121
1148
|
rb_define_singleton_method(rb_cCAMonOp, "__materialise_count__",
|
|
1122
1149
|
rb_ca_monop_s_materialise_count, 0);
|
|
1150
|
+
#endif
|
|
1123
1151
|
}
|