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_moncmp.c
CHANGED
|
@@ -189,24 +189,6 @@ ca_moncmp_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
189
189
|
ca_moncmp_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
static void
|
|
193
|
-
ca_moncmp_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
194
|
-
void *data, int dir)
|
|
195
|
-
{
|
|
196
|
-
CAMonCmp *ca = (CAMonCmp *) ap;
|
|
197
|
-
ca_size_t i;
|
|
198
|
-
char *out = (char *) data;
|
|
199
|
-
|
|
200
|
-
if ( dir != CA_XFER_GET ) {
|
|
201
|
-
rb_raise(rb_eRuntimeError, "CAMonCmp is read-only (xfer_addrs PUT)");
|
|
202
|
-
}
|
|
203
|
-
for ( i = 0; i < n; i++ ) {
|
|
204
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
205
|
-
ca_addr2index((CArray *)ca, addrs[i], idx);
|
|
206
|
-
ca_moncmp_func_xfer_index(ca, idx, out + i, CA_XFER_GET);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
192
|
ca_size_t ca_moncmp_scratch_acquire_count = 0;
|
|
211
193
|
ca_size_t ca_moncmp_materialise_call_count = 0;
|
|
212
194
|
ca_size_t ca_moncmp_leaf_inplace_count = 0;
|
|
@@ -242,55 +224,30 @@ ca_moncmp_try_leaf_inplace (CArray *p,
|
|
|
242
224
|
return 1;
|
|
243
225
|
}
|
|
244
226
|
|
|
227
|
+
/* Evaluate the cells a request names into `data` (packed, n cells). */
|
|
245
228
|
static void
|
|
246
|
-
|
|
247
|
-
ca_size_t *strides, void *data, int dir)
|
|
229
|
+
ca_moncmp_eval (CAMonCmp *mc, const ca_lazy_req_t *req, void *data)
|
|
248
230
|
{
|
|
249
|
-
|
|
250
|
-
ca_size_t slab_n;
|
|
251
|
-
int8_t k;
|
|
231
|
+
ca_size_t slab_n = req->n;
|
|
252
232
|
void *scratch;
|
|
253
233
|
ca_size_t operand_bytes;
|
|
254
|
-
ca_size_t operand_strides[CA_RANK_MAX];
|
|
255
234
|
int is_contig;
|
|
256
235
|
|
|
257
|
-
if ( dir != CA_XFER_GET ) {
|
|
258
|
-
rb_raise(rb_eRuntimeError, "CAMonCmp is read-only (xfer_stride PUT)");
|
|
259
|
-
}
|
|
260
236
|
ca_moncmp_materialise_call_count++;
|
|
261
237
|
|
|
262
|
-
slab_n = 1;
|
|
263
|
-
for ( k = 0; k < mc->ndim; k++ ) slab_n *= counts[k];
|
|
264
|
-
|
|
265
238
|
operand_bytes = mc->parent->bytes;
|
|
266
239
|
|
|
267
|
-
/* The
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
is_contig says the caller asked for the row-major slab that xfer_all
|
|
273
|
-
and attach send. Only then does the parent's own buffer hold the
|
|
274
|
-
wanted cells in the packed order the kernel reads them in, so it is
|
|
275
|
-
also the only case the leaf in-place path is good for. */
|
|
276
|
-
{
|
|
277
|
-
ca_size_t native = mc->bytes;
|
|
278
|
-
is_contig = 1;
|
|
279
|
-
for ( k = mc->ndim - 1; k >= 0; k-- ) {
|
|
280
|
-
operand_strides[k] = strides[k] / mc->bytes * operand_bytes;
|
|
281
|
-
if ( strides[k] != native ) {
|
|
282
|
-
is_contig = 0;
|
|
283
|
-
}
|
|
284
|
-
native *= mc->dim[k];
|
|
285
|
-
}
|
|
286
|
-
}
|
|
240
|
+
/* The leaf in-place path reads the parent's own buffer, which holds the
|
|
241
|
+
wanted cells in the order the kernel reads them only for the row-major
|
|
242
|
+
slab that xfer_all and attach send. */
|
|
243
|
+
is_contig = ca_lazy_req_is_packed(req, mc);
|
|
287
244
|
|
|
288
245
|
/* === 1. pull parent (leaf-opt or scratch) === */
|
|
289
246
|
int scratch_is_inplace = 0;
|
|
290
247
|
{
|
|
291
248
|
char *inplace = NULL;
|
|
292
249
|
if ( is_contig &&
|
|
293
|
-
ca_moncmp_try_leaf_inplace(mc->parent, starts, counts,
|
|
250
|
+
ca_moncmp_try_leaf_inplace(mc->parent, req->starts, req->counts,
|
|
294
251
|
operand_bytes, &inplace) ) {
|
|
295
252
|
scratch = inplace;
|
|
296
253
|
scratch_is_inplace = 1;
|
|
@@ -301,8 +258,7 @@ ca_moncmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
301
258
|
? ca_lazy_arena_acquire_object(slab_n)
|
|
302
259
|
: ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
303
260
|
ca_moncmp_scratch_acquire_count++;
|
|
304
|
-
|
|
305
|
-
CA_XFER_GET);
|
|
261
|
+
ca_lazy_req_pull(mc->parent, req, scratch, CA_XFER_GET);
|
|
306
262
|
}
|
|
307
263
|
}
|
|
308
264
|
|
|
@@ -312,10 +268,12 @@ ca_moncmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
312
268
|
* fn(n, m, ptr1, i1, ptr2, i2)
|
|
313
269
|
* where ptr2 is boolean8_t*
|
|
314
270
|
*
|
|
315
|
-
*
|
|
316
|
-
*
|
|
271
|
+
* m=NULL (= SIMD fast path) except for an object parent, whose cells
|
|
272
|
+
* call Ruby: those skip the masked cells, as the eager method does.
|
|
273
|
+
* Per-data_type kernel handles integer is_nan etc. internally.
|
|
317
274
|
*/
|
|
318
275
|
{
|
|
276
|
+
boolean8_t *slab_mask = NULL;
|
|
319
277
|
ca_moncmp_func_t fn = ca_moncmp_kernel_lookup(mc->op_id,
|
|
320
278
|
mc->parent->data_type);
|
|
321
279
|
if ( fn == NULL ) {
|
|
@@ -324,14 +282,44 @@ ca_moncmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
324
282
|
"CAMonCmp: kernel not implemented (op_id=%u data_type=%d)",
|
|
325
283
|
(unsigned) mc->op_id, (int) mc->parent->data_type);
|
|
326
284
|
}
|
|
327
|
-
|
|
285
|
+
if ( mc->parent->data_type == CA_OBJECT ) {
|
|
286
|
+
slab_mask = ca_lazy_req_mask(req, 1, &mc->parent);
|
|
287
|
+
}
|
|
288
|
+
fn(slab_n, slab_mask,
|
|
328
289
|
(char *) scratch, 1,
|
|
329
290
|
(boolean8_t *) data, 1);
|
|
291
|
+
if ( slab_mask ) ca_lazy_arena_release(slab_mask);
|
|
330
292
|
}
|
|
331
293
|
|
|
332
294
|
if ( ! scratch_is_inplace ) ca_lazy_arena_release(scratch);
|
|
333
295
|
}
|
|
334
296
|
|
|
297
|
+
static void
|
|
298
|
+
ca_moncmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
299
|
+
ca_size_t *strides, void *data, int dir)
|
|
300
|
+
{
|
|
301
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
302
|
+
ca_lazy_req_t req;
|
|
303
|
+
if ( dir != CA_XFER_GET ) {
|
|
304
|
+
rb_raise(rb_eRuntimeError, "CAMonCmp is read-only (xfer_stride PUT)");
|
|
305
|
+
}
|
|
306
|
+
ca_lazy_req_region(&req, ap, starts, counts, strides);
|
|
307
|
+
ca_moncmp_eval((CAMonCmp *) ap, &req, data);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* An address list is evaluated in one pass, as a region is. */
|
|
311
|
+
static void
|
|
312
|
+
ca_moncmp_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
313
|
+
void *data, int dir)
|
|
314
|
+
{
|
|
315
|
+
ca_lazy_req_t req;
|
|
316
|
+
if ( dir != CA_XFER_GET ) {
|
|
317
|
+
rb_raise(rb_eRuntimeError, "CAMonCmp is read-only (xfer_addrs PUT)");
|
|
318
|
+
}
|
|
319
|
+
ca_lazy_req_addrs(&req, n, addrs);
|
|
320
|
+
ca_moncmp_eval((CAMonCmp *) ap, &req, data);
|
|
321
|
+
}
|
|
322
|
+
|
|
335
323
|
static void
|
|
336
324
|
ca_moncmp_func_xfer_all (void *ap, void *data, int dir)
|
|
337
325
|
{
|
|
@@ -394,17 +382,16 @@ ca_moncmp_func_fill_data (void *ap, void *ptr)
|
|
|
394
382
|
rb_raise(rb_eRuntimeError, "CAMonCmp is read-only (fill_data)");
|
|
395
383
|
}
|
|
396
384
|
|
|
385
|
+
/* The parent's mask cell for cell, read-only as the comparison is. */
|
|
397
386
|
static void
|
|
398
387
|
ca_moncmp_func_create_mask (void *ap)
|
|
399
388
|
{
|
|
400
389
|
CAMonCmp *mc = (CAMonCmp *) ap;
|
|
401
390
|
CArray *p = mc->parent;
|
|
402
391
|
if ( ! ca_has_mask(p) ) return;
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
memcpy(mc->mask->ptr, p->mask->ptr, mc->elements);
|
|
407
|
-
ca_detach(p->mask);
|
|
392
|
+
mc->mask = (CArray *) ca_refer_new(p->mask, CA_BOOLEAN,
|
|
393
|
+
mc->ndim, mc->dim, 0, 0);
|
|
394
|
+
ca_set_flag(mc->mask, CA_FLAG_READ_ONLY);
|
|
408
395
|
}
|
|
409
396
|
|
|
410
397
|
ca_operation_function_t ca_moncmp_func = {
|
|
@@ -470,6 +457,17 @@ rb_ca_moncmp_s_build (VALUE klass, VALUE p_cary, VALUE op_id_val)
|
|
|
470
457
|
return rb_ca_moncmp_build(p_cary, op_id);
|
|
471
458
|
}
|
|
472
459
|
|
|
460
|
+
/* Whether this node's kernel skips the cells its operands mask, rather
|
|
461
|
+
than computing them: object cells, which call Ruby. CArray::Fusion
|
|
462
|
+
reads it so a plan carries the same rule. */
|
|
463
|
+
static VALUE
|
|
464
|
+
rb_ca_moncmp_trapping (VALUE self)
|
|
465
|
+
{
|
|
466
|
+
CAMonCmp *mc;
|
|
467
|
+
TypedData_Get_Struct(self, CAMonCmp, &camoncmp_data_type, mc);
|
|
468
|
+
return ( mc->parent->data_type == CA_OBJECT ) ? Qtrue : Qfalse;
|
|
469
|
+
}
|
|
470
|
+
|
|
473
471
|
static VALUE
|
|
474
472
|
rb_ca_moncmp_op_id (VALUE self)
|
|
475
473
|
{
|
|
@@ -535,6 +533,7 @@ rb_ca_moncmp_initialize_copy (VALUE self, VALUE other)
|
|
|
535
533
|
{
|
|
536
534
|
CAMonCmp *ca, *cs;
|
|
537
535
|
TypedData_Get_Struct(self, CAMonCmp, &camoncmp_data_type, ca);
|
|
536
|
+
ca_check_uninitialized(ca);
|
|
538
537
|
TypedData_Get_Struct(other, CAMonCmp, &camoncmp_data_type, cs);
|
|
539
538
|
if ( ca_func[CA_OBJ_MONCMP].pool_init ) {
|
|
540
539
|
ca_array_pool_alloc(ca, CA_OBJ_MONCMP, cs->parent->ndim);
|
|
@@ -572,6 +571,7 @@ Init_ca_obj_moncmp (void)
|
|
|
572
571
|
rb_ca_moncmp_s_build, 2);
|
|
573
572
|
|
|
574
573
|
rb_define_method(rb_cCAMonCmp, "__op_id__", rb_ca_moncmp_op_id, 0);
|
|
574
|
+
rb_define_method(rb_cCAMonCmp, "__trapping__", rb_ca_moncmp_trapping, 0);
|
|
575
575
|
|
|
576
576
|
rb_define_singleton_method(rb_cCAMonCmp, "__reset_scratch_counter__",
|
|
577
577
|
rb_ca_moncmp_s_reset_scratch_counter, 0);
|
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,
|
|
@@ -284,11 +285,10 @@ ca_monop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
284
285
|
rb_raise(rb_eRuntimeError, "CAMonOp is read-only (xfer_index PUT)");
|
|
285
286
|
}
|
|
286
287
|
{
|
|
287
|
-
|
|
288
|
+
volatile VALUE holder;
|
|
288
289
|
ca_size_t bytes_per_cell = (ca_monop_is_cast(ca->op_id))
|
|
289
290
|
? ca->parent->bytes : ca->bytes;
|
|
290
|
-
char *p = (
|
|
291
|
-
: (char *) ALLOC_N(char, bytes_per_cell);
|
|
291
|
+
char *p = ALLOCV_N(char, holder, bytes_per_cell);
|
|
292
292
|
if ( ca_monop_is_cast(ca->op_id) ) {
|
|
293
293
|
/* Reverse-cast view-data_type `data` to parent data_type scratch, then
|
|
294
294
|
store into parent at idx[]. */
|
|
@@ -301,7 +301,7 @@ ca_monop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
301
301
|
ca_byte_swap_buffer(ca->data_type, ca->bytes, 1, p);
|
|
302
302
|
}
|
|
303
303
|
ca_store_index(ca->parent, idx, p);
|
|
304
|
-
|
|
304
|
+
ALLOCV_END(holder);
|
|
305
305
|
}
|
|
306
306
|
return;
|
|
307
307
|
}
|
|
@@ -316,38 +316,6 @@ ca_monop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
316
316
|
ca_monop_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
317
317
|
}
|
|
318
318
|
|
|
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
319
|
/* ------------------------------------------------------------------- */
|
|
352
320
|
/* In-place chain eval (scratch = 0) */
|
|
353
321
|
/* ------------------------------------------------------------------- */
|
|
@@ -369,27 +337,30 @@ ca_size_t ca_monop_materialise_call_count = 0;
|
|
|
369
337
|
#define CA_MAX_LAZY_DEPTH 256
|
|
370
338
|
#endif
|
|
371
339
|
|
|
340
|
+
/* Whether an op can raise on a cell, so that a masked cell must be
|
|
341
|
+
skipped rather than computed: any op on an object cell (it calls Ruby),
|
|
342
|
+
and an integer reciprocal (zero raises). */
|
|
343
|
+
static int
|
|
344
|
+
ca_monop_is_trapping (uint16_t op_id, int8_t dt)
|
|
345
|
+
{
|
|
346
|
+
if ( dt == CA_OBJECT ) {
|
|
347
|
+
return 1;
|
|
348
|
+
}
|
|
349
|
+
return ( op_id == CA_MONOP_RCP && dt >= CA_INT8 && dt <= CA_UINT64 );
|
|
350
|
+
}
|
|
351
|
+
|
|
372
352
|
/* Apply a single op in-place on `data` (src == dst, unit element stride).
|
|
373
353
|
Raises if the kernel is not implemented for the given input data_type.
|
|
374
354
|
|
|
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. */
|
|
355
|
+
`mask` is NULL except for an op that can raise on a cell: the kernel
|
|
356
|
+
then takes the SIMD-friendly "no mask" branch and computes the masked
|
|
357
|
+
cells too. Their bytes are unobservable -- the output mask is the
|
|
358
|
+
parent's (ca_monop_func_create_mask) -- and the mask marks cells as
|
|
359
|
+
undefined rather than guarding their bytes, so writing anything into a
|
|
360
|
+
masked cell is licensed. */
|
|
390
361
|
static void
|
|
391
362
|
apply_monop_in_place (uint16_t op_id, int8_t cur_dt,
|
|
392
|
-
ca_size_t slab_n, void *data)
|
|
363
|
+
ca_size_t slab_n, void *data, boolean8_t *mask)
|
|
393
364
|
{
|
|
394
365
|
ca_monop_func_t fn = ca_monop_kernel_lookup(op_id, cur_dt);
|
|
395
366
|
if ( fn == NULL ) {
|
|
@@ -397,7 +368,7 @@ apply_monop_in_place (uint16_t op_id, int8_t cur_dt,
|
|
|
397
368
|
"CAMonOp: kernel not implemented (op_id=%u data_type=%d)",
|
|
398
369
|
(unsigned) op_id, (int) cur_dt);
|
|
399
370
|
}
|
|
400
|
-
fn(slab_n,
|
|
371
|
+
fn(slab_n, mask, (char *) data, 1, (char *) data, 1);
|
|
401
372
|
}
|
|
402
373
|
|
|
403
374
|
/* Minimal CArray-shaped stub used as ca_cast_block's data_type-only carrier.
|
|
@@ -434,38 +405,25 @@ typedef struct {
|
|
|
434
405
|
static int8_t
|
|
435
406
|
pull_leaf_with_optional_cast (CArray *leaf, uint16_t innermost_op,
|
|
436
407
|
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)
|
|
408
|
+
const ca_lazy_req_t *req, void *data)
|
|
440
409
|
{
|
|
441
410
|
ca_size_t leaf_bytes = leaf->bytes;
|
|
411
|
+
ca_size_t slab_n = req->n;
|
|
442
412
|
|
|
443
413
|
/* Path 1: no size mismatch, no cast — direct pull. */
|
|
444
414
|
if ( leaf_bytes == out_bytes && ! has_cast_at_leaf ) {
|
|
445
|
-
|
|
415
|
+
ca_lazy_req_pull(leaf, req, data, CA_XFER_GET);
|
|
446
416
|
return leaf->data_type;
|
|
447
417
|
}
|
|
448
418
|
|
|
449
|
-
/* Paths 2 & 3 both
|
|
450
|
-
for the leaf pull. */
|
|
451
|
-
ca_size_t parent_strides[CA_RANK_MAX];
|
|
419
|
+
/* Paths 2 & 3 both pull the leaf into a leaf-sized scratch. */
|
|
452
420
|
ca_size_t total_bytes = slab_n * leaf_bytes;
|
|
453
421
|
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
422
|
scratch = ( leaf->data_type == CA_OBJECT )
|
|
465
423
|
? ca_lazy_arena_acquire_object(slab_n)
|
|
466
424
|
: ca_lazy_arena_acquire(total_bytes);
|
|
467
425
|
ca_monop_scratch_acquire_count++;
|
|
468
|
-
|
|
426
|
+
ca_lazy_req_pull(leaf, req, scratch, CA_XFER_GET);
|
|
469
427
|
|
|
470
428
|
int8_t result_dt;
|
|
471
429
|
if ( has_cast_at_leaf ) {
|
|
@@ -486,20 +444,21 @@ pull_leaf_with_optional_cast (CArray *leaf, uint16_t innermost_op,
|
|
|
486
444
|
return result_dt;
|
|
487
445
|
}
|
|
488
446
|
|
|
447
|
+
/* Evaluate (GET) or write (PUT, writable views only) the cells a request
|
|
448
|
+
names; `data` holds them packed. */
|
|
489
449
|
static void
|
|
490
|
-
|
|
491
|
-
ca_size_t *strides, void *data, int dir)
|
|
450
|
+
ca_monop_eval (CAMonOp *mo, const ca_lazy_req_t *req, void *data, int dir)
|
|
492
451
|
{
|
|
493
|
-
CAMonOp *mo = (CAMonOp *) ap;
|
|
494
452
|
uint16_t op_chain[CA_MAX_LAZY_DEPTH];
|
|
495
453
|
int chain_len = 0;
|
|
496
454
|
CArray *leaf;
|
|
497
|
-
ca_size_t slab_n;
|
|
498
|
-
int8_t k;
|
|
455
|
+
ca_size_t slab_n = req->n;
|
|
499
456
|
int8_t cur_dt;
|
|
500
457
|
int i;
|
|
501
458
|
int has_cast_at_leaf = 0;
|
|
502
459
|
int chain_apply_count;
|
|
460
|
+
boolean8_t *slab_mask = NULL;
|
|
461
|
+
int mask_taken = 0;
|
|
503
462
|
|
|
504
463
|
/* Writable-view op_ids (cast / byte_swap) use CAFake-style xfer_stride
|
|
505
464
|
for both GET and PUT. This avoids the chain-materialise inline path
|
|
@@ -510,21 +469,13 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
510
469
|
- byte_swap: same data_type → pstrides = strides; involution apply. */
|
|
511
470
|
if ( ca_monop_is_writable_view(mo->op_id) ) {
|
|
512
471
|
int is_cast = ca_monop_is_cast(mo->op_id);
|
|
513
|
-
ca_size_t
|
|
514
|
-
ca_size_t n = 1;
|
|
472
|
+
ca_size_t n = slab_n;
|
|
515
473
|
ca_size_t parent_bytes = is_cast ? mo->parent->bytes : mo->bytes;
|
|
516
|
-
int8_t kk;
|
|
517
474
|
char *v;
|
|
518
475
|
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
476
|
v = ALLOCV_N(char, holder, n * parent_bytes);
|
|
526
477
|
if ( dir == CA_XFER_GET ) {
|
|
527
|
-
|
|
478
|
+
ca_lazy_req_pull(mo->parent, req, v, CA_XFER_GET);
|
|
528
479
|
if ( is_cast ) {
|
|
529
480
|
ca_cast_block(n, mo->parent, v, (CArray *) mo, data);
|
|
530
481
|
}
|
|
@@ -543,7 +494,7 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
543
494
|
memcpy(v, data, n * mo->bytes);
|
|
544
495
|
ca_byte_swap_buffer(mo->data_type, mo->bytes, n, v);
|
|
545
496
|
}
|
|
546
|
-
|
|
497
|
+
ca_lazy_req_pull(mo->parent, req, v, CA_XFER_PUT);
|
|
547
498
|
}
|
|
548
499
|
ALLOCV_END(holder);
|
|
549
500
|
return;
|
|
@@ -564,8 +515,8 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
564
515
|
while ( leaf->obj_type == CA_OBJ_MONOP ) {
|
|
565
516
|
CAMonOp *node = (CAMonOp *) leaf;
|
|
566
517
|
if ( chain_len >= CA_MAX_LAZY_DEPTH ) {
|
|
567
|
-
rb_raise(
|
|
568
|
-
"
|
|
518
|
+
rb_raise(rb_eArgError,
|
|
519
|
+
"lazy expression too deep: more than %d operations in a chain",
|
|
569
520
|
CA_MAX_LAZY_DEPTH);
|
|
570
521
|
}
|
|
571
522
|
op_chain[chain_len++] = node->op_id;
|
|
@@ -586,16 +537,12 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
586
537
|
}
|
|
587
538
|
|
|
588
539
|
/* === 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
540
|
cur_dt = pull_leaf_with_optional_cast(
|
|
594
541
|
leaf,
|
|
595
542
|
has_cast_at_leaf ? op_chain[chain_len - 1] : 0,
|
|
596
543
|
has_cast_at_leaf,
|
|
597
544
|
(int8_t) mo->bytes,
|
|
598
|
-
|
|
545
|
+
req, data
|
|
599
546
|
);
|
|
600
547
|
|
|
601
548
|
/* === 3. apply remaining chain in reverse (leaf side → outermost) ===
|
|
@@ -626,10 +573,38 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
626
573
|
ca_lazy_arena_release(scratch);
|
|
627
574
|
cur_dt = target_dt;
|
|
628
575
|
} else {
|
|
629
|
-
|
|
576
|
+
if ( ! mask_taken && ca_monop_is_trapping(op_id, cur_dt) ) {
|
|
577
|
+
slab_mask = ca_lazy_req_mask(req, 1, &leaf);
|
|
578
|
+
mask_taken = 1;
|
|
579
|
+
}
|
|
580
|
+
apply_monop_in_place(op_id, cur_dt, slab_n, data,
|
|
581
|
+
ca_monop_is_trapping(op_id, cur_dt) ? slab_mask : NULL);
|
|
630
582
|
cur_dt = ca_lazy_promote_monop(op_id, cur_dt);
|
|
631
583
|
}
|
|
632
584
|
}
|
|
585
|
+
if ( slab_mask ) {
|
|
586
|
+
ca_lazy_arena_release(slab_mask);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
static void
|
|
591
|
+
ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
592
|
+
ca_size_t *strides, void *data, int dir)
|
|
593
|
+
{
|
|
594
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
595
|
+
ca_lazy_req_t req;
|
|
596
|
+
ca_lazy_req_region(&req, ap, starts, counts, strides);
|
|
597
|
+
ca_monop_eval((CAMonOp *) ap, &req, data, dir);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/* An address list is evaluated in one pass, as a region is. */
|
|
601
|
+
static void
|
|
602
|
+
ca_monop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
603
|
+
void *data, int dir)
|
|
604
|
+
{
|
|
605
|
+
ca_lazy_req_t req;
|
|
606
|
+
ca_lazy_req_addrs(&req, n, addrs);
|
|
607
|
+
ca_monop_eval((CAMonOp *) ap, &req, data, dir);
|
|
633
608
|
}
|
|
634
609
|
|
|
635
610
|
static void
|
|
@@ -774,10 +749,12 @@ ca_monop_func_sync (void *ap)
|
|
|
774
749
|
}
|
|
775
750
|
}
|
|
776
751
|
else {
|
|
777
|
-
/* byte_swap (involution):
|
|
778
|
-
|
|
779
|
-
|
|
752
|
+
/* byte_swap (involution): swap a copy back to the parent's byte order.
|
|
753
|
+
Not ca.ptr in place -- the window stays open after a sync, and a
|
|
754
|
+
second sync (a stack holding this view twice) would swap it again. */
|
|
780
755
|
memcpy(ca->parent->ptr, ca->ptr, ca_length(ca));
|
|
756
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, ca->elements,
|
|
757
|
+
ca->parent->ptr);
|
|
781
758
|
}
|
|
782
759
|
ca_sync(ca->parent);
|
|
783
760
|
}
|
|
@@ -810,9 +787,8 @@ ca_monop_func_fill_data (void *ap, void *ptr)
|
|
|
810
787
|
{
|
|
811
788
|
int is_cast = ca_monop_is_cast(ca->op_id);
|
|
812
789
|
ca_size_t parent_bytes = is_cast ? ca->parent->bytes : ca->bytes;
|
|
813
|
-
|
|
814
|
-
char *v = (
|
|
815
|
-
: (char *) xmalloc(parent_bytes);
|
|
790
|
+
volatile VALUE holder;
|
|
791
|
+
char *v = ALLOCV_N(char, holder, parent_bytes);
|
|
816
792
|
if ( is_cast ) {
|
|
817
793
|
ca_ptr2ptr((CArray *) ca, ptr, ca->parent, v);
|
|
818
794
|
}
|
|
@@ -821,7 +797,7 @@ ca_monop_func_fill_data (void *ap, void *ptr)
|
|
|
821
797
|
ca_byte_swap_buffer(ca->data_type, ca->bytes, 1, v);
|
|
822
798
|
}
|
|
823
799
|
ca_fill(ca->parent, v);
|
|
824
|
-
|
|
800
|
+
ALLOCV_END(holder);
|
|
825
801
|
}
|
|
826
802
|
}
|
|
827
803
|
|
|
@@ -829,12 +805,12 @@ static void
|
|
|
829
805
|
ca_monop_func_create_mask (void *ap)
|
|
830
806
|
{
|
|
831
807
|
CAMonOp *ca = (CAMonOp *) ap;
|
|
832
|
-
|
|
833
|
-
|
|
808
|
+
ca_view_func_create_mask(ca);
|
|
809
|
+
/* A cast view writes through to its parent, mask included; any other
|
|
810
|
+
operation is read-only and so is its mask. */
|
|
811
|
+
if ( ca_test_flag(ca, CA_FLAG_READ_ONLY) ) {
|
|
812
|
+
ca_set_flag(ca->mask, CA_FLAG_READ_ONLY);
|
|
834
813
|
}
|
|
835
|
-
ca->mask =
|
|
836
|
-
(CArray *) ca_refer_new(ca->parent->mask,
|
|
837
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
838
814
|
}
|
|
839
815
|
|
|
840
816
|
ca_operation_function_t ca_monop_func = {
|
|
@@ -933,8 +909,35 @@ rb_ca_monop_build (VALUE cary, uint16_t op_id)
|
|
|
933
909
|
}
|
|
934
910
|
|
|
935
911
|
parent_dt = parent->data_type;
|
|
912
|
+
|
|
913
|
+
/* A boolean parent, as rb_ca_call_monop and the data_type-changing
|
|
914
|
+
monops treat it: a math function wants an explicit cast, and an op
|
|
915
|
+
with no boolean kernel reads the 0/1 storage in int64. */
|
|
916
|
+
if ( parent_dt == CA_BOOLEAN && ! ca_monop_is_writable_view(op_id) ) {
|
|
917
|
+
if ( ca_monop_is_widening(op_id) ) {
|
|
918
|
+
rb_raise(rb_eCADataTypeError,
|
|
919
|
+
"invalid data type for monop (not implemented)");
|
|
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
|
+
rb_raise(rb_eCADataTypeError,
|
|
938
|
+
"invalid data type for monop (not implemented)");
|
|
939
|
+
}
|
|
940
|
+
|
|
938
941
|
/* Insert cast node if the kernel wants a different input data_type. */
|
|
939
942
|
if ( kernel_in_dt != parent_dt ) {
|
|
940
943
|
uint16_t cast_op_id = CA_MONOP_CAST_BASE + (uint16_t) kernel_in_dt;
|
|
@@ -964,6 +967,19 @@ rb_ca_is_lazy_view_p (VALUE self)
|
|
|
964
967
|
}
|
|
965
968
|
|
|
966
969
|
/* Read CAMonOp's op_id for inspect/dump_tree consumers in Ruby. */
|
|
970
|
+
/* Whether this node's kernel skips the cells its operands mask, rather
|
|
971
|
+
than computing them: a kernel that can raise on a cell or calls Ruby
|
|
972
|
+
for it. CArray::Fusion reads it so a plan carries the same rule. */
|
|
973
|
+
static VALUE
|
|
974
|
+
rb_ca_monop_trapping (VALUE self)
|
|
975
|
+
{
|
|
976
|
+
CAMonOp *mo;
|
|
977
|
+
TypedData_Get_Struct(self, CAMonOp, &camonop_data_type, mo);
|
|
978
|
+
return ( ! ca_monop_is_cast(mo->op_id)
|
|
979
|
+
&& ca_monop_is_trapping(mo->op_id, mo->parent->data_type) )
|
|
980
|
+
? Qtrue : Qfalse;
|
|
981
|
+
}
|
|
982
|
+
|
|
967
983
|
static VALUE
|
|
968
984
|
rb_ca_monop_op_id (VALUE self)
|
|
969
985
|
{
|
|
@@ -1018,6 +1034,7 @@ rb_ca_monop_initialize_copy (VALUE self, VALUE other)
|
|
|
1018
1034
|
{
|
|
1019
1035
|
CAMonOp *ca, *cs;
|
|
1020
1036
|
TypedData_Get_Struct(self, CAMonOp, &camonop_data_type, ca);
|
|
1037
|
+
ca_check_uninitialized(ca);
|
|
1021
1038
|
TypedData_Get_Struct(other, CAMonOp, &camonop_data_type, cs);
|
|
1022
1039
|
if ( ca_func[CA_OBJ_MONOP].pool_init ) {
|
|
1023
1040
|
ca_array_pool_alloc(ca, CA_OBJ_MONOP, cs->parent->ndim);
|
|
@@ -1110,6 +1127,7 @@ Init_ca_obj_monop (void)
|
|
|
1110
1127
|
/* op_id accessor for inspect / dump_tree consumers in Ruby. */
|
|
1111
1128
|
rb_define_method(rb_cCAMonOp, "__op_id__",
|
|
1112
1129
|
rb_ca_monop_op_id, 0);
|
|
1130
|
+
rb_define_method(rb_cCAMonOp, "__trapping__", rb_ca_monop_trapping, 0);
|
|
1113
1131
|
|
|
1114
1132
|
/* Test instrumentation (not user-facing API). */
|
|
1115
1133
|
rb_define_singleton_method(rb_cCAMonOp, "__reset_scratch_counter__",
|