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_binop.c
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
#include "carray_internal.h" /* ca_lazy_arena_* */
|
|
35
35
|
#include "ca_binop_dispatch.h"
|
|
36
36
|
#include "ca_monop_dispatch.h" /* CA_MONOP_CAST_BASE */
|
|
37
|
+
#include "carray_math_kernel.h" /* ca_binop_not_implement */
|
|
37
38
|
|
|
38
39
|
/* carray_broadcast.c */
|
|
39
40
|
extern VALUE ca_broadcast_view (VALUE src, int8_t ndim,
|
|
@@ -48,7 +49,6 @@ extern int8_t CA_OBJ_LAZY_MARKER;
|
|
|
48
49
|
|
|
49
50
|
/* Defined in carray_lazy.c: wrap a non-CArray Ruby value as a
|
|
50
51
|
CScalar carrying the other operand's natural data_type. */
|
|
51
|
-
extern VALUE ca_lazy_wrap_scalar (VALUE other, CArray *self_ca);
|
|
52
52
|
|
|
53
53
|
/* ------------------------------------------------------------------- */
|
|
54
54
|
/* CABinOp struct */
|
|
@@ -177,6 +177,7 @@ ca_binop_setup (CABinOp *ca, CArray *left, CArray *right, uint16_t op_id)
|
|
|
177
177
|
CABinOp *
|
|
178
178
|
ca_binop_new (CArray *left, CArray *right, uint16_t op_id)
|
|
179
179
|
{
|
|
180
|
+
/* check: the setup checks nothing */
|
|
180
181
|
CABinOp *ca = (CABinOp *) ca_array_alloc(CA_OBJ_BINOP, left->ndim);
|
|
181
182
|
ca_binop_setup(ca, left, right, op_id);
|
|
182
183
|
return ca;
|
|
@@ -227,7 +228,7 @@ ca_binop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
227
228
|
ca_size_t s;
|
|
228
229
|
|
|
229
230
|
if ( dir != CA_XFER_GET ) {
|
|
230
|
-
|
|
231
|
+
ca_refuse_read_only();
|
|
231
232
|
}
|
|
232
233
|
|
|
233
234
|
s = ca->bytes;
|
|
@@ -239,58 +240,30 @@ ca_binop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
239
240
|
ca_binop_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
240
241
|
}
|
|
241
242
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
CABinOp *ca = (CABinOp *) ap;
|
|
247
|
-
ca_size_t i;
|
|
248
|
-
char *out = (char *) data;
|
|
249
|
-
|
|
250
|
-
if ( dir != CA_XFER_GET ) {
|
|
251
|
-
rb_raise(rb_eRuntimeError, "CABinOp is read-only (xfer_addrs PUT)");
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
for ( i = 0; i < n; i++ ) {
|
|
255
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
256
|
-
ca_addr2index((CArray *)ca, addrs[i], idx);
|
|
257
|
-
ca_binop_func_xfer_index(ca, idx, out + i * ca->bytes, CA_XFER_GET);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/* Test / observability counters bumped from the xfer_stride hot
|
|
262
|
-
path so specs can assert scratch acquisition (one per node,
|
|
263
|
-
independent of left-chain depth) and materialise vs
|
|
264
|
-
non-materialise behaviour without attaching the view. */
|
|
243
|
+
/* Test / observability counters bumped from the evaluation hot path
|
|
244
|
+
so specs can assert scratch acquisition (one per node, independent
|
|
245
|
+
of left-chain depth) and materialise vs non-materialise behaviour
|
|
246
|
+
without attaching the view. */
|
|
265
247
|
ca_size_t ca_binop_scratch_acquire_count = 0;
|
|
266
248
|
ca_size_t ca_binop_materialise_call_count = 0;
|
|
267
249
|
|
|
250
|
+
/* Evaluate the cells a request names into `data` (packed, n cells). */
|
|
268
251
|
static void
|
|
269
|
-
|
|
270
|
-
ca_size_t *strides, void *data, int dir)
|
|
252
|
+
ca_binop_eval (CABinOp *bo, const ca_lazy_req_t *req, void *data)
|
|
271
253
|
{
|
|
272
|
-
|
|
273
|
-
ca_size_t slab_n;
|
|
254
|
+
ca_size_t slab_n = req->n;
|
|
274
255
|
int8_t k;
|
|
275
256
|
void *scratch;
|
|
276
257
|
volatile VALUE holder;
|
|
277
258
|
ca_size_t right_bytes;
|
|
278
259
|
ca_size_t right_step; /* element-stride for the kernel walk */
|
|
279
260
|
|
|
280
|
-
if ( dir != CA_XFER_GET ) {
|
|
281
|
-
rb_raise(rb_eRuntimeError, "CABinOp is read-only (xfer_stride PUT)");
|
|
282
|
-
}
|
|
283
261
|
ca_binop_materialise_call_count++;
|
|
284
262
|
|
|
285
|
-
slab_n = 1;
|
|
286
|
-
for ( k = 0; k < bo->ndim; k++ ) slab_n *= counts[k];
|
|
287
|
-
|
|
288
263
|
/* === 1. Pull left into the output buffer ===
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
output row. */
|
|
293
|
-
ca_xfer_stride(bo->parent, starts, counts, strides, data, CA_XFER_GET);
|
|
264
|
+
left.data_type == output.data_type by the cast-before invariant,
|
|
265
|
+
so the output buffer holds left's cells as they are. */
|
|
266
|
+
ca_lazy_req_pull(bo->parent, req, data, CA_XFER_GET);
|
|
294
267
|
|
|
295
268
|
/* === 2. Pull right into an arena scratch === */
|
|
296
269
|
right_bytes = bo->right->bytes;
|
|
@@ -315,17 +288,12 @@ ca_binop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
315
288
|
right_step = 0;
|
|
316
289
|
}
|
|
317
290
|
else {
|
|
318
|
-
/* Same-shape right
|
|
319
|
-
same one the left was pulled with -- recomputing a packed one here
|
|
320
|
-
reads the right operand's cells 0, 1, 2 against the left's 0, 2, 4.
|
|
321
|
-
right.bytes matches output.bytes because right.data_type ==
|
|
322
|
-
out.data_type by cast-before, so the same steps serve both. */
|
|
291
|
+
/* Same-shape right, pulled over the same cells as the left. */
|
|
323
292
|
scratch = ( bo->data_type == CA_OBJECT )
|
|
324
293
|
? ca_lazy_arena_acquire_object(slab_n)
|
|
325
294
|
: ca_lazy_arena_acquire(slab_n * right_bytes);
|
|
326
295
|
ca_binop_scratch_acquire_count++;
|
|
327
|
-
|
|
328
|
-
CA_XFER_GET);
|
|
296
|
+
ca_lazy_req_pull(bo->right, req, scratch, CA_XFER_GET);
|
|
329
297
|
right_step = 1;
|
|
330
298
|
}
|
|
331
299
|
|
|
@@ -337,8 +305,9 @@ ca_binop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
337
305
|
* Mask handling:
|
|
338
306
|
* - non-trapping op → m = NULL (SIMD fast path; garbage compute
|
|
339
307
|
* on masked cells is allowed).
|
|
340
|
-
* - trapping op
|
|
341
|
-
* mask
|
|
308
|
+
* - trapping op (one that can raise on a cell, or an object cell)
|
|
309
|
+
* with any operand mask → the cells either operand masks
|
|
310
|
+
* (ca_lazy_req_mask), which the kernel skips.
|
|
342
311
|
*
|
|
343
312
|
* CAREFUL: the trapping-op mask is built from left.mask and
|
|
344
313
|
* right.mask directly, NOT from out->mask. The output's mask
|
|
@@ -353,67 +322,13 @@ ca_binop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
353
322
|
{
|
|
354
323
|
boolean8_t *slab_mask = NULL;
|
|
355
324
|
void *mscratch = NULL;
|
|
356
|
-
volatile VALUE mholder = Qnil;
|
|
357
|
-
int is_trapping = ca_binop_is_trapping(bo->op_id, bo->data_type);
|
|
358
|
-
|
|
359
|
-
if ( is_trapping && ( ca_has_mask(bo->parent) ||
|
|
360
|
-
ca_has_mask(bo->right) ) ) {
|
|
361
|
-
/* Build a slab-shaped mask = left.slab_mask | right.slab_mask.
|
|
362
|
-
Pull each operand's mask (or fill with 0 if absent) into the
|
|
363
|
-
output-shaped layout, then OR them in place. */
|
|
364
|
-
ca_size_t k_;
|
|
365
|
-
ca_size_t right_mask_strides[CA_RANK_MAX];
|
|
366
|
-
(void) mholder; /* Kept for stack-shape compatibility; arena
|
|
367
|
-
replaces the ALLOCV path here. */
|
|
368
|
-
|
|
369
|
-
mscratch = ca_lazy_arena_acquire(slab_n);
|
|
370
|
-
slab_mask = (boolean8_t *) mscratch;
|
|
371
|
-
|
|
372
|
-
if ( ca_has_mask(bo->parent) ) {
|
|
373
|
-
ca_size_t mstrides[CA_RANK_MAX];
|
|
374
|
-
ca_size_t s = 1;
|
|
375
|
-
for ( k_ = bo->ndim - 1; k_ >= 0; k_-- ) {
|
|
376
|
-
mstrides[k_] = s; s *= counts[k_];
|
|
377
|
-
}
|
|
378
|
-
ca_xfer_stride(bo->parent->mask, starts, counts, mstrides,
|
|
379
|
-
slab_mask, CA_XFER_GET);
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
memset(slab_mask, 0, slab_n);
|
|
383
|
-
}
|
|
384
325
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
ca_size_t one_counts[CA_RANK_MAX];
|
|
392
|
-
ca_size_t one_strides[CA_RANK_MAX];
|
|
393
|
-
boolean8_t one_bit = 0;
|
|
394
|
-
for ( k_ = 0; k_ < bo->right->ndim; k_++ ) {
|
|
395
|
-
one_counts[k_] = 1;
|
|
396
|
-
one_strides[k_] = 1;
|
|
397
|
-
}
|
|
398
|
-
ca_xfer_stride(bo->right->mask, one_starts, one_counts,
|
|
399
|
-
one_strides, &one_bit, CA_XFER_GET);
|
|
400
|
-
if ( one_bit ) {
|
|
401
|
-
for ( i_ = 0; i_ < slab_n; i_++ ) slab_mask[i_] = 1;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
ca_size_t s = 1;
|
|
406
|
-
for ( k_ = bo->ndim - 1; k_ >= 0; k_-- ) {
|
|
407
|
-
right_mask_strides[k_] = s; s *= counts[k_];
|
|
408
|
-
}
|
|
409
|
-
/* Small mask-scratch for right; OR into slab_mask in
|
|
410
|
-
place to avoid a persistent second buffer. */
|
|
411
|
-
rm = (boolean8_t *) ALLOCA_N(boolean8_t, slab_n);
|
|
412
|
-
ca_xfer_stride(bo->right->mask, starts, counts,
|
|
413
|
-
right_mask_strides, rm, CA_XFER_GET);
|
|
414
|
-
for ( i_ = 0; i_ < slab_n; i_++ ) slab_mask[i_] |= rm[i_];
|
|
415
|
-
}
|
|
416
|
-
}
|
|
326
|
+
if ( ca_op_raises_on_cell(CA_OP_KIND_BINOP, bo->op_id, bo->data_type) ) {
|
|
327
|
+
CArray *ops[2];
|
|
328
|
+
ops[0] = bo->parent;
|
|
329
|
+
ops[1] = bo->right;
|
|
330
|
+
slab_mask = ca_lazy_req_mask(req, 2, ops);
|
|
331
|
+
mscratch = slab_mask;
|
|
417
332
|
}
|
|
418
333
|
|
|
419
334
|
ca_binop_func_t fn = ca_binop_kernel_lookup_vv(bo->op_id, bo->data_type);
|
|
@@ -435,6 +350,33 @@ ca_binop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
435
350
|
ca_lazy_arena_release(scratch);
|
|
436
351
|
}
|
|
437
352
|
|
|
353
|
+
static void
|
|
354
|
+
ca_binop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
355
|
+
ca_size_t *strides, void *data, int dir)
|
|
356
|
+
{
|
|
357
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
358
|
+
ca_lazy_req_t req;
|
|
359
|
+
if ( dir != CA_XFER_GET ) {
|
|
360
|
+
ca_refuse_read_only();
|
|
361
|
+
}
|
|
362
|
+
ca_lazy_req_region(&req, ap, starts, counts, strides);
|
|
363
|
+
ca_binop_eval((CABinOp *) ap, &req, data);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* An address list is evaluated in one pass: each operand is gathered at
|
|
367
|
+
the same addresses and the kernel runs once over all of them. */
|
|
368
|
+
static void
|
|
369
|
+
ca_binop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
370
|
+
void *data, int dir)
|
|
371
|
+
{
|
|
372
|
+
ca_lazy_req_t req;
|
|
373
|
+
if ( dir != CA_XFER_GET ) {
|
|
374
|
+
ca_refuse_read_only();
|
|
375
|
+
}
|
|
376
|
+
ca_lazy_req_addrs(&req, n, addrs);
|
|
377
|
+
ca_binop_eval((CABinOp *) ap, &req, data);
|
|
378
|
+
}
|
|
379
|
+
|
|
438
380
|
static void
|
|
439
381
|
ca_binop_func_xfer_all (void *ap, void *data, int dir)
|
|
440
382
|
{
|
|
@@ -452,15 +394,7 @@ static void
|
|
|
452
394
|
ca_binop_func_allocate (void *ap)
|
|
453
395
|
{
|
|
454
396
|
CABinOp *ca = (CABinOp *) ap;
|
|
455
|
-
ca->ptr =
|
|
456
|
-
/* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
|
|
457
|
-
soon as the view is, so it must not be handed to the GC as raw
|
|
458
|
-
xmalloc garbage. */
|
|
459
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
460
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
461
|
-
ca_size_t i;
|
|
462
|
-
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
463
|
-
}
|
|
397
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
464
398
|
}
|
|
465
399
|
|
|
466
400
|
static void
|
|
@@ -477,19 +411,11 @@ ca_binop_func_attach (void *ap)
|
|
|
477
411
|
int8_t k;
|
|
478
412
|
ca_size_t s;
|
|
479
413
|
|
|
480
|
-
ca->ptr =
|
|
414
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
481
415
|
|
|
482
416
|
s = ca->bytes;
|
|
483
417
|
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
484
418
|
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
485
|
-
/* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
|
|
486
|
-
soon as the view is, so it must not be handed to the GC as raw
|
|
487
|
-
xmalloc garbage. */
|
|
488
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
489
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
490
|
-
ca_size_t i;
|
|
491
|
-
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
492
|
-
}
|
|
493
419
|
ca_binop_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
|
|
494
420
|
}
|
|
495
421
|
|
|
@@ -511,107 +437,28 @@ NORETURN(static void ca_binop_func_fill_data (void *ap, void *ptr));
|
|
|
511
437
|
static void
|
|
512
438
|
ca_binop_func_fill_data (void *ap, void *ptr)
|
|
513
439
|
{
|
|
514
|
-
|
|
440
|
+
ca_refuse_read_only();
|
|
515
441
|
}
|
|
516
442
|
|
|
517
|
-
/* Build out.mask
|
|
518
|
-
|
|
519
|
-
OR `left.mask | right.mask`.
|
|
443
|
+
/* Build out.mask: the operands' masks ORed on each read (CAMaskOfOperands), so
|
|
444
|
+
that it follows them as the values do.
|
|
520
445
|
|
|
521
446
|
Boolean AND / OR are three-valued (Kleene): a masked cell is resolved by
|
|
522
447
|
the *known* side (`unknown | true = true`, `unknown & false = false`), so
|
|
523
|
-
it is NOT masked in the result.
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
element (true for OR, false for AND) dominates whatever garbage sits on
|
|
527
|
-
the masked side. Nested trees compose: an inner boolean `&`/`|` node's
|
|
528
|
-
mask is already Kleene-resolved by the time an outer node reads it.
|
|
529
|
-
|
|
530
|
-
Not memory-optimal (a CARepeat-like view would share pages), but correct
|
|
531
|
-
and decoupled from xfer_stride ordering. */
|
|
448
|
+
it is NOT masked in the result. The blind value the value kernel writes
|
|
449
|
+
is already correct on a resolved cell because the absorbing element (true
|
|
450
|
+
for OR, false for AND) dominates whatever sits on the masked side. */
|
|
532
451
|
static void
|
|
533
452
|
ca_binop_func_create_mask (void *ap)
|
|
534
453
|
{
|
|
535
454
|
CABinOp *bo = (CABinOp *) ap;
|
|
536
|
-
|
|
537
|
-
CArray *r = bo->right;
|
|
538
|
-
boolean8_t *dst;
|
|
539
|
-
ca_size_t i, n;
|
|
540
|
-
int has_l, has_r, kleene, need_l, need_r, is_or;
|
|
541
|
-
boolean8_t *lm, *rm, *lv, *rv;
|
|
542
|
-
|
|
543
|
-
has_l = ca_has_mask(l);
|
|
544
|
-
has_r = ca_has_mask(r);
|
|
545
|
-
if ( ! has_l && ! has_r ) return;
|
|
546
|
-
|
|
547
|
-
kleene = ( bo->data_type == CA_BOOLEAN &&
|
|
548
|
-
( bo->op_id == CA_BINOP_BIT_AND || bo->op_id == CA_BINOP_BIT_OR ) );
|
|
549
|
-
is_or = ( bo->op_id == CA_BINOP_BIT_OR );
|
|
550
|
-
|
|
551
|
-
/* One masked operand and no Kleene resolution: the answer is that
|
|
552
|
-
operand's mask, cell for cell. Share it the way CAMonOp shares its
|
|
553
|
-
parent's, rather than allocating a copy per node -- a chain of k
|
|
554
|
-
binops over one masked array then holds one boolean array, not k. */
|
|
555
|
-
if ( ! kleene && ( has_l != has_r ) ) {
|
|
556
|
-
CArray *src = has_l ? l : r;
|
|
557
|
-
if ( src->elements == bo->elements ) {
|
|
558
|
-
bo->mask = (CArray *) ca_refer_new(src->mask, CA_BOOLEAN,
|
|
559
|
-
bo->ndim, bo->dim, 0, 0);
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
bo->mask = (CArray *) carray_new(CA_BOOLEAN, bo->ndim, bo->dim, 0, NULL);
|
|
565
|
-
dst = (boolean8_t *) bo->mask->ptr;
|
|
566
|
-
n = bo->elements;
|
|
567
|
-
|
|
568
|
-
/* Kleene needs operand values even where an operand is unmasked. */
|
|
569
|
-
need_l = has_l || kleene;
|
|
570
|
-
need_r = has_r || kleene;
|
|
571
|
-
/* Only Kleene reads operand values. Every other op reads the operand
|
|
572
|
-
masks alone, and attaching the operand to reach its mask materialises
|
|
573
|
-
the whole subexpression under it -- so a chain of k masked binops
|
|
574
|
-
evaluates its own subtree k times over. Attach what is read. */
|
|
575
|
-
if ( kleene ) {
|
|
576
|
-
if ( need_l ) ca_attach(l);
|
|
577
|
-
if ( need_r ) ca_attach(r);
|
|
578
|
-
}
|
|
579
|
-
else {
|
|
580
|
-
if ( has_l ) ca_attach(l->mask);
|
|
581
|
-
if ( has_r ) ca_attach(r->mask);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
lm = has_l ? (boolean8_t *) l->mask->ptr : NULL;
|
|
585
|
-
rm = has_r ? (boolean8_t *) r->mask->ptr : NULL;
|
|
586
|
-
lv = kleene ? (boolean8_t *) l->ptr : NULL;
|
|
587
|
-
rv = kleene ? (boolean8_t *) r->ptr : NULL;
|
|
588
|
-
|
|
589
|
-
for ( i = 0; i < n; i++ ) {
|
|
590
|
-
/* right broadcast: repeat element 0 when right was a scalar. */
|
|
591
|
-
ca_size_t ri = bo->right_is_scalar ? 0 : i;
|
|
592
|
-
boolean8_t am = lm ? lm[i] : 0;
|
|
593
|
-
boolean8_t bm = rm ? rm[ri] : 0;
|
|
594
|
-
boolean8_t m = (boolean8_t)( am | bm );
|
|
595
|
-
if ( kleene && m ) {
|
|
596
|
-
boolean8_t av = lv[i], bv = rv[ri];
|
|
597
|
-
if ( is_or ) {
|
|
598
|
-
if ( ( ! am && av ) || ( ! bm && bv ) ) m = 0; /* known TRUE */
|
|
599
|
-
}
|
|
600
|
-
else {
|
|
601
|
-
if ( ( ! am && ! av ) || ( ! bm && ! bv ) ) m = 0; /* known FALSE */
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
dst[i] = m;
|
|
605
|
-
}
|
|
455
|
+
int mode = CA_LAZY_MASK_OR;
|
|
606
456
|
|
|
607
|
-
if (
|
|
608
|
-
if (
|
|
609
|
-
if (
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
if ( has_r ) ca_detach(r->mask);
|
|
613
|
-
if ( has_l ) ca_detach(l->mask);
|
|
457
|
+
if ( bo->data_type == CA_BOOLEAN ) {
|
|
458
|
+
if ( bo->op_id == CA_BINOP_BIT_OR ) mode = CA_LAZY_MASK_KLEENE_OR;
|
|
459
|
+
if ( bo->op_id == CA_BINOP_BIT_AND ) mode = CA_LAZY_MASK_KLEENE_AND;
|
|
614
460
|
}
|
|
461
|
+
bo->mask = ca_lazy_operation_mask((CArray *) bo, mode);
|
|
615
462
|
}
|
|
616
463
|
|
|
617
464
|
ca_operation_function_t ca_binop_func = {
|
|
@@ -704,17 +551,22 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
|
|
|
704
551
|
l_resolved = collapse_marker(l_cary);
|
|
705
552
|
r_resolved = collapse_marker(r_cary);
|
|
706
553
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
554
|
+
ca_binop_read_boolean_as_truth(
|
|
555
|
+
ca_binop_kernel_lookup_vv(op_id, CA_BOOLEAN) != ca_binop_not_implement,
|
|
556
|
+
&l_resolved, &r_resolved);
|
|
557
|
+
|
|
558
|
+
/* A scalar beside the array (a Ruby value or a CScalar) takes the
|
|
559
|
+
data_type the eager binop gives it, and the pair is promoted as the
|
|
560
|
+
eager binop promotes it. An integer power keeps its int64 exponent
|
|
561
|
+
(ca_binop_kernel_input_data_types). */
|
|
562
|
+
if ( op_id != CA_BINOP_IPOWER &&
|
|
563
|
+
( ! rb_obj_is_carray(l_resolved) || ! rb_obj_is_carray(r_resolved) ||
|
|
564
|
+
rb_obj_is_cscalar(l_resolved) || rb_obj_is_cscalar(r_resolved) ) ) {
|
|
565
|
+
int l_scalar = ! rb_obj_is_carray(l_resolved) || rb_obj_is_cscalar(l_resolved);
|
|
566
|
+
int r_scalar = ! rb_obj_is_carray(r_resolved) || rb_obj_is_cscalar(r_resolved);
|
|
567
|
+
rb_ca_cast_self_or_other(&l_resolved, &r_resolved);
|
|
568
|
+
l_resolved = ca_lazy_settle_scalar(l_resolved, l_scalar);
|
|
569
|
+
r_resolved = ca_lazy_settle_scalar(r_resolved, r_scalar);
|
|
718
570
|
}
|
|
719
571
|
|
|
720
572
|
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
@@ -725,6 +577,22 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
|
|
|
725
577
|
ca_binop_kernel_input_data_types(op_id, l->data_type, r->data_type,
|
|
726
578
|
&l_in_dt, &r_in_dt);
|
|
727
579
|
|
|
580
|
+
/* A boolean operand of an op with no boolean kernel (arithmetic) is
|
|
581
|
+
read as its 0/1 storage in int64, as rb_ca_call_binop does. */
|
|
582
|
+
if ( l_in_dt == CA_BOOLEAN &&
|
|
583
|
+
ca_binop_kernel_lookup_vv(op_id, CA_BOOLEAN) == ca_binop_not_implement ) {
|
|
584
|
+
l_in_dt = CA_INT64;
|
|
585
|
+
if ( r_in_dt == CA_BOOLEAN ) {
|
|
586
|
+
r_in_dt = CA_INT64;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/* No kernel for that data_type (fixlen arithmetic, ...): raise as the
|
|
591
|
+
eager binop does, before a view is built over it. */
|
|
592
|
+
if ( ca_binop_kernel_lookup_vv(op_id, l_in_dt) == ca_binop_not_implement ) {
|
|
593
|
+
ca_op_refuse_unimplemented(l_cary, l_in_dt, rb_eCADataTypeError);
|
|
594
|
+
}
|
|
595
|
+
|
|
728
596
|
if ( l_in_dt != l->data_type ) {
|
|
729
597
|
VALUE cast_op = INT2NUM(CA_MONOP_CAST_BASE + l_in_dt);
|
|
730
598
|
l_resolved = rb_funcall(rb_const_get(rb_cObject, rb_intern("CAMonOp")),
|
|
@@ -757,11 +625,11 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
|
|
|
757
625
|
shape so the kernel sees matched shapes; cost is N
|
|
758
626
|
reads of the scalar cell with stride 0. */
|
|
759
627
|
if ( l->elements != r->elements ) {
|
|
760
|
-
if ( r->elements == 1
|
|
628
|
+
if ( r->elements == 1 ) {
|
|
761
629
|
/* CScalar-vs-array, right. xfer_stride handles this with
|
|
762
630
|
right_step = 0. */
|
|
763
631
|
}
|
|
764
|
-
else if ( l->elements == 1
|
|
632
|
+
else if ( l->elements == 1 ) {
|
|
765
633
|
int commutes = ( op_id == CA_BINOP_ADD ||
|
|
766
634
|
op_id == CA_BINOP_MUL ||
|
|
767
635
|
op_id == CA_BINOP_BIT_AND ||
|
|
@@ -810,12 +678,24 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
|
|
|
810
678
|
static VALUE
|
|
811
679
|
rb_ca_binop_s_build (VALUE klass, VALUE l_cary, VALUE r_cary, VALUE op_id_val)
|
|
812
680
|
{
|
|
681
|
+
/* fits: an operation number from the library's own table */
|
|
813
682
|
uint16_t op_id = (uint16_t) NUM2UINT(op_id_val);
|
|
814
683
|
(void) klass;
|
|
815
684
|
return rb_ca_binop_build(l_cary, r_cary, op_id);
|
|
816
685
|
}
|
|
817
686
|
|
|
818
687
|
/* op_id accessor for inspect / dump_tree consumers in Ruby. */
|
|
688
|
+
/* Whether this node's kernel skips the cells its operands mask, rather
|
|
689
|
+
than computing them: a kernel that can raise on a cell or calls Ruby
|
|
690
|
+
for it. CArray::Fusion reads it so a plan carries the same rule. */
|
|
691
|
+
static VALUE
|
|
692
|
+
rb_ca_binop_trapping (VALUE self)
|
|
693
|
+
{
|
|
694
|
+
CABinOp *bo;
|
|
695
|
+
TypedData_Get_Struct(self, CABinOp, &cabinop_data_type, bo);
|
|
696
|
+
return ca_op_raises_on_cell(CA_OP_KIND_BINOP, bo->op_id, bo->data_type) ? Qtrue : Qfalse;
|
|
697
|
+
}
|
|
698
|
+
|
|
819
699
|
static VALUE
|
|
820
700
|
rb_ca_binop_op_id (VALUE self)
|
|
821
701
|
{
|
|
@@ -834,6 +714,7 @@ rb_ca_binop_right (VALUE self)
|
|
|
834
714
|
}
|
|
835
715
|
|
|
836
716
|
/* Test instrumentation (mirrors CAMonOp counters). */
|
|
717
|
+
#ifdef CARRAY_DEV_BUILD
|
|
837
718
|
static VALUE
|
|
838
719
|
rb_ca_binop_s_reset_scratch_counter (VALUE klass)
|
|
839
720
|
{
|
|
@@ -859,6 +740,7 @@ rb_ca_binop_s_materialise_count (VALUE klass)
|
|
|
859
740
|
{
|
|
860
741
|
return SIZE2NUM(ca_binop_materialise_call_count);
|
|
861
742
|
}
|
|
743
|
+
#endif /* CARRAY_DEV_BUILD */
|
|
862
744
|
|
|
863
745
|
static VALUE
|
|
864
746
|
rb_ca_binop_s_allocate (VALUE klass)
|
|
@@ -872,6 +754,7 @@ rb_ca_binop_initialize_copy (VALUE self, VALUE other)
|
|
|
872
754
|
{
|
|
873
755
|
CABinOp *ca, *cs;
|
|
874
756
|
TypedData_Get_Struct(self, CABinOp, &cabinop_data_type, ca);
|
|
757
|
+
ca_check_uninitialized(ca);
|
|
875
758
|
TypedData_Get_Struct(other, CABinOp, &cabinop_data_type, cs);
|
|
876
759
|
if ( ca_func[CA_OBJ_BINOP].pool_init ) {
|
|
877
760
|
ca_array_pool_alloc(ca, CA_OBJ_BINOP, cs->parent->ndim);
|
|
@@ -933,10 +816,12 @@ Init_ca_obj_binop (void)
|
|
|
933
816
|
|
|
934
817
|
rb_define_method(rb_cCABinOp, "__op_id__",
|
|
935
818
|
rb_ca_binop_op_id, 0);
|
|
819
|
+
rb_define_method(rb_cCABinOp, "__trapping__", rb_ca_binop_trapping, 0);
|
|
936
820
|
rb_define_method(rb_cCABinOp, "__binop_right__",
|
|
937
821
|
rb_ca_binop_right, 0);
|
|
938
822
|
|
|
939
823
|
/* Test instrumentation, not user-facing. */
|
|
824
|
+
#ifdef CARRAY_DEV_BUILD
|
|
940
825
|
rb_define_singleton_method(rb_cCABinOp, "__reset_scratch_counter__",
|
|
941
826
|
rb_ca_binop_s_reset_scratch_counter, 0);
|
|
942
827
|
rb_define_singleton_method(rb_cCABinOp, "__scratch_count__",
|
|
@@ -945,4 +830,5 @@ Init_ca_obj_binop (void)
|
|
|
945
830
|
rb_ca_binop_s_reset_materialise_counter, 0);
|
|
946
831
|
rb_define_singleton_method(rb_cCABinOp, "__materialise_count__",
|
|
947
832
|
rb_ca_binop_s_materialise_count, 0);
|
|
833
|
+
#endif
|
|
948
834
|
}
|
data/ext/ca_obj_bitarray.c
CHANGED
|
@@ -96,6 +96,22 @@ ca_bitarray_setup (CABitarray *ca, CArray *parent)
|
|
|
96
96
|
rb_raise(rb_eCADataTypeError, "invalid data_type for bitarray");
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/* The bits of one byte would share that byte's one mask cell, so a bit
|
|
100
|
+
view takes no masked array and holds no mask of its own. */
|
|
101
|
+
/* mask: the constructor asks first, before it allocates (ca == NULL) */
|
|
102
|
+
if ( ca_has_mask(parent) ) {
|
|
103
|
+
rb_raise(rb_eArgError,
|
|
104
|
+
"bitarray: the array has a mask, which a bit view can not "
|
|
105
|
+
"carry (its bits would share one mask per byte); "
|
|
106
|
+
"use .value.bitarray to read the bits without it");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
110
|
+
run them before it allocates. */
|
|
111
|
+
if ( ca == NULL ) {
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
99
115
|
ndim = parent->ndim + 1;
|
|
100
116
|
bitlen = 8 * parent->bytes;
|
|
101
117
|
elements = bitlen * parent->elements;
|
|
@@ -122,17 +138,15 @@ ca_bitarray_setup (CABitarray *ca, CArray *parent)
|
|
|
122
138
|
memcpy(ca->dim, parent->dim, (ndim-1) * sizeof(ca_size_t));
|
|
123
139
|
ca->dim[ndim-1] = bitlen;
|
|
124
140
|
|
|
125
|
-
if ( ca_has_mask(parent) ) {
|
|
126
|
-
ca_create_mask(ca);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
141
|
return 0;
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
CABitarray *
|
|
133
145
|
ca_bitarray_new (CArray *parent)
|
|
134
146
|
{
|
|
135
|
-
CABitarray *ca
|
|
147
|
+
CABitarray *ca;
|
|
148
|
+
ca_bitarray_setup(NULL, parent);
|
|
149
|
+
ca = (CABitarray *) ca_array_alloc(CA_OBJ_BITARRAY, parent->ndim + 1);
|
|
136
150
|
ca_bitarray_setup(ca, parent);
|
|
137
151
|
return ca;
|
|
138
152
|
}
|
|
@@ -178,7 +192,7 @@ ca_bitarray_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
178
192
|
ca_size_t bytes = ca->parent->bytes;
|
|
179
193
|
ca_size_t offset = idx[ca->ndim-1];
|
|
180
194
|
ca_size_t major, minor;
|
|
181
|
-
|
|
195
|
+
volatile VALUE holder;
|
|
182
196
|
uint8_t *v;
|
|
183
197
|
|
|
184
198
|
if ( ca_endian == CA_BIG_ENDIAN &&
|
|
@@ -191,7 +205,7 @@ ca_bitarray_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
191
205
|
}
|
|
192
206
|
minor = offset % 8;
|
|
193
207
|
|
|
194
|
-
v = (
|
|
208
|
+
v = ALLOCV_N(uint8_t, holder, ca->parent->bytes);
|
|
195
209
|
|
|
196
210
|
if ( dir == CA_XFER_GET ) {
|
|
197
211
|
ca_fetch_index(ca->parent, idx, v);
|
|
@@ -209,7 +223,7 @@ ca_bitarray_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
209
223
|
ca_store_index(ca->parent, idx, v);
|
|
210
224
|
}
|
|
211
225
|
|
|
212
|
-
|
|
226
|
+
ALLOCV_END(holder);
|
|
213
227
|
}
|
|
214
228
|
|
|
215
229
|
/* Batched gather / scatter.
|
|
@@ -315,6 +329,7 @@ static void
|
|
|
315
329
|
ca_bitarray_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
316
330
|
ca_size_t *strides, void *data, int dir)
|
|
317
331
|
{
|
|
332
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
318
333
|
CABitarray *ca = (CABitarray *) ap;
|
|
319
334
|
int8_t ndim = ca->ndim;
|
|
320
335
|
ca_size_t native[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
@@ -381,7 +396,7 @@ ca_bitarray_func_allocate (void *ap)
|
|
|
381
396
|
{
|
|
382
397
|
CABitarray *ca = (CABitarray *) ap;
|
|
383
398
|
ca_attach(ca->parent);
|
|
384
|
-
ca->ptr =
|
|
399
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
385
400
|
}
|
|
386
401
|
|
|
387
402
|
static void
|
|
@@ -389,7 +404,7 @@ ca_bitarray_func_attach (void *ap)
|
|
|
389
404
|
{
|
|
390
405
|
CABitarray *ca = (CABitarray *) ap;
|
|
391
406
|
ca_attach(ca->parent);
|
|
392
|
-
ca->ptr =
|
|
407
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
393
408
|
ca_bitarray_attach(ca);
|
|
394
409
|
}
|
|
395
410
|
|
|
@@ -478,29 +493,27 @@ ca_bitarray_func_fill_data (void *ap, void *ptr)
|
|
|
478
493
|
CABitarray *ca = (CABitarray *) ap;
|
|
479
494
|
ca_attach(ca->parent);
|
|
480
495
|
ca_bitarray_fill(ca, ptr);
|
|
481
|
-
|
|
482
|
-
ca_detach(ca->parent);
|
|
496
|
+
ca_sync_detach(ca->parent);
|
|
483
497
|
}
|
|
484
498
|
|
|
499
|
+
/* Reached when a mask is about to be put on the view (mask=, storing UNDEF
|
|
500
|
+
or a masked array), or when the array it views has gained a mask since
|
|
501
|
+
the view was made. */
|
|
502
|
+
NORETURN(static void ca_bitarray_func_create_mask (void *ap));
|
|
503
|
+
|
|
485
504
|
static void
|
|
486
505
|
ca_bitarray_func_create_mask (void *ap)
|
|
487
506
|
{
|
|
488
507
|
CABitarray *ca = (CABitarray *) ap;
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
count[ca->ndim-1] = ca->bitlen;
|
|
496
|
-
|
|
497
|
-
ca_update_mask(ca->parent);
|
|
498
|
-
if ( ! ca->parent->mask ) {
|
|
499
|
-
ca_create_mask(ca->parent);
|
|
508
|
+
if ( ca_has_mask(ca->parent) ) {
|
|
509
|
+
rb_raise(rb_eArgError,
|
|
510
|
+
"bitarray: the array this view reads has gained a mask, which "
|
|
511
|
+
"a bit view can not carry (its bits would share one mask per "
|
|
512
|
+
"byte); use .value.bitarray to read the bits without it");
|
|
500
513
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
514
|
+
rb_raise(rb_eArgError,
|
|
515
|
+
"a bitarray view can not hold a mask "
|
|
516
|
+
"(its bits would share one mask per byte)");
|
|
504
517
|
}
|
|
505
518
|
|
|
506
519
|
ca_operation_function_t ca_bitarray_func = {
|
|
@@ -703,6 +716,7 @@ rb_ca_bitarray_initialize_copy (VALUE self, VALUE other)
|
|
|
703
716
|
CABitarray *ca, *cs;
|
|
704
717
|
|
|
705
718
|
TypedData_Get_Struct(self, CABitarray, &cabitarray_data_type, ca);
|
|
719
|
+
ca_check_uninitialized(ca);
|
|
706
720
|
TypedData_Get_Struct(other, CABitarray, &cabitarray_data_type, cs);
|
|
707
721
|
|
|
708
722
|
if ( ca_func[CA_OBJ_BITARRAY].pool_init ) {
|