carray 3.0.3 → 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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- 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/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_obj_monop.c
CHANGED
|
@@ -222,6 +222,7 @@ ca_monop_setup (CAMonOp *ca, CArray *parent, uint16_t op_id)
|
|
|
222
222
|
CAMonOp *
|
|
223
223
|
ca_monop_new (CArray *parent, uint16_t op_id)
|
|
224
224
|
{
|
|
225
|
+
/* check: the setup checks nothing */
|
|
225
226
|
CAMonOp *ca = (CAMonOp *) ca_array_alloc(CA_OBJ_MONOP, parent->ndim);
|
|
226
227
|
ca_monop_setup(ca, parent, op_id);
|
|
227
228
|
return ca;
|
|
@@ -282,7 +283,7 @@ ca_monop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
282
283
|
/* PUT: only writable-view op_ids accept writes (cast, or byte_swap
|
|
283
284
|
involution). */
|
|
284
285
|
if ( ! ca_monop_is_writable_view(ca->op_id) ) {
|
|
285
|
-
|
|
286
|
+
ca_refuse_read_only();
|
|
286
287
|
}
|
|
287
288
|
{
|
|
288
289
|
volatile VALUE holder;
|
|
@@ -337,16 +338,14 @@ ca_size_t ca_monop_materialise_call_count = 0;
|
|
|
337
338
|
#define CA_MAX_LAZY_DEPTH 256
|
|
338
339
|
#endif
|
|
339
340
|
|
|
340
|
-
/* Whether
|
|
341
|
-
|
|
342
|
-
and an integer reciprocal (zero raises). */
|
|
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
343
|
static int
|
|
344
|
-
|
|
344
|
+
ca_monop_cast_refuses_nan (int8_t from, int8_t to)
|
|
345
345
|
{
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return ( op_id == CA_MONOP_RCP && dt >= CA_INT8 && dt <= CA_UINT64 );
|
|
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;
|
|
350
349
|
}
|
|
351
350
|
|
|
352
351
|
/* Apply a single op in-place on `data` (src == dst, unit element stride).
|
|
@@ -476,7 +475,27 @@ ca_monop_eval (CAMonOp *mo, const ca_lazy_req_t *req, void *data, int dir)
|
|
|
476
475
|
v = ALLOCV_N(char, holder, n * parent_bytes);
|
|
477
476
|
if ( dir == CA_XFER_GET ) {
|
|
478
477
|
ca_lazy_req_pull(mo->parent, req, v, CA_XFER_GET);
|
|
479
|
-
if ( is_cast
|
|
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 ) {
|
|
480
499
|
ca_cast_block(n, mo->parent, v, (CArray *) mo, data);
|
|
481
500
|
}
|
|
482
501
|
else {
|
|
@@ -503,7 +522,7 @@ ca_monop_eval (CAMonOp *mo, const ca_lazy_req_t *req, void *data, int dir)
|
|
|
503
522
|
/* Writable-view op_id PUT/GET is handled above. Below: non-writable
|
|
504
523
|
monop/monfunc. PUT is read-only. */
|
|
505
524
|
if ( dir != CA_XFER_GET ) {
|
|
506
|
-
|
|
525
|
+
ca_refuse_read_only();
|
|
507
526
|
}
|
|
508
527
|
ca_monop_materialise_call_count++;
|
|
509
528
|
|
|
@@ -573,12 +592,12 @@ ca_monop_eval (CAMonOp *mo, const ca_lazy_req_t *req, void *data, int dir)
|
|
|
573
592
|
ca_lazy_arena_release(scratch);
|
|
574
593
|
cur_dt = target_dt;
|
|
575
594
|
} else {
|
|
576
|
-
if ( ! mask_taken &&
|
|
595
|
+
if ( ! mask_taken && ca_op_raises_on_cell(CA_OP_KIND_MONOP, op_id, cur_dt) ) {
|
|
577
596
|
slab_mask = ca_lazy_req_mask(req, 1, &leaf);
|
|
578
597
|
mask_taken = 1;
|
|
579
598
|
}
|
|
580
599
|
apply_monop_in_place(op_id, cur_dt, slab_n, data,
|
|
581
|
-
|
|
600
|
+
ca_op_raises_on_cell(CA_OP_KIND_MONOP, op_id, cur_dt) ? slab_mask : NULL);
|
|
582
601
|
cur_dt = ca_lazy_promote_monop(op_id, cur_dt);
|
|
583
602
|
}
|
|
584
603
|
}
|
|
@@ -638,16 +657,7 @@ ca_monop_func_allocate (void *ap)
|
|
|
638
657
|
if ( ca_monop_is_writable_view(ca->op_id) ) {
|
|
639
658
|
ca_attach(ca->parent);
|
|
640
659
|
}
|
|
641
|
-
ca->ptr =
|
|
642
|
-
/* CA_OBJECT initialisation for GC safety. */
|
|
643
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
644
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
645
|
-
VALUE zero = SIZE2NUM(0);
|
|
646
|
-
ca_size_t i;
|
|
647
|
-
for ( i = 0; i < ca->elements; i++ ) {
|
|
648
|
-
*p++ = zero;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
660
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
651
661
|
}
|
|
652
662
|
|
|
653
663
|
static void
|
|
@@ -676,22 +686,19 @@ ca_monop_func_attach (void *ap)
|
|
|
676
686
|
Mirrors CAFake.attach. */
|
|
677
687
|
if ( ca_monop_is_writable_view(ca->op_id) ) {
|
|
678
688
|
ca_attach(ca->parent);
|
|
679
|
-
ca->ptr =
|
|
680
|
-
/* CA_OBJECT initialisation for GC safety (mirrors CAFake.allocate):
|
|
681
|
-
zero-init the VALUE cells before any potential GC can observe
|
|
682
|
-
them. */
|
|
683
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
684
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
685
|
-
VALUE zero = SIZE2NUM(0);
|
|
686
|
-
ca_size_t i;
|
|
687
|
-
for ( i = 0; i < ca->elements; i++ ) {
|
|
688
|
-
*p++ = zero;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
689
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
691
690
|
if ( ca_monop_is_cast(ca->op_id) ) {
|
|
692
|
-
/* Cast parent.ptr (parent data_type) → ca.ptr (cast target data_type).
|
|
693
|
-
|
|
694
|
-
|
|
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);
|
|
695
702
|
}
|
|
696
703
|
else {
|
|
697
704
|
/* byte_swap: memcpy parent.ptr → ca.ptr (same data_type same bytes),
|
|
@@ -702,19 +709,11 @@ ca_monop_func_attach (void *ap)
|
|
|
702
709
|
return;
|
|
703
710
|
}
|
|
704
711
|
|
|
705
|
-
ca->ptr =
|
|
712
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
706
713
|
|
|
707
714
|
s = ca->bytes;
|
|
708
715
|
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
709
716
|
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
710
|
-
/* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
|
|
711
|
-
soon as the view is, so it must not be handed to the GC as raw
|
|
712
|
-
xmalloc garbage. */
|
|
713
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
714
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
715
|
-
ca_size_t i;
|
|
716
|
-
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
717
|
-
}
|
|
718
717
|
ca_monop_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
|
|
719
718
|
}
|
|
720
719
|
|
|
@@ -782,7 +781,7 @@ ca_monop_func_fill_data (void *ap, void *ptr)
|
|
|
782
781
|
data_type (= same bytes for byte_swap, reverse-cast for cast).
|
|
783
782
|
Non-writable monop/monfunc remains read-only. */
|
|
784
783
|
if ( ! ca_monop_is_writable_view(ca->op_id) ) {
|
|
785
|
-
|
|
784
|
+
ca_refuse_read_only();
|
|
786
785
|
}
|
|
787
786
|
{
|
|
788
787
|
int is_cast = ca_monop_is_cast(ca->op_id);
|
|
@@ -915,8 +914,9 @@ rb_ca_monop_build (VALUE cary, uint16_t op_id)
|
|
|
915
914
|
with no boolean kernel reads the 0/1 storage in int64. */
|
|
916
915
|
if ( parent_dt == CA_BOOLEAN && ! ca_monop_is_writable_view(op_id) ) {
|
|
917
916
|
if ( ca_monop_is_widening(op_id) ) {
|
|
918
|
-
|
|
919
|
-
|
|
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
920
|
}
|
|
921
921
|
if ( ca_monop_kernel_lookup(op_id, CA_BOOLEAN) == ca_monop_not_implement ) {
|
|
922
922
|
target = rb_ca_monop_new(target, CA_MONOP_CAST_BASE + CA_INT64);
|
|
@@ -934,8 +934,13 @@ rb_ca_monop_build (VALUE cary, uint16_t op_id)
|
|
|
934
934
|
( ca_monop_kernel_lookup(op_id, kernel_in_dt) == ca_monop_not_implement ||
|
|
935
935
|
( parent_dt == CA_FIXLEN &&
|
|
936
936
|
ca_monop_kernel_lookup(op_id, CA_FIXLEN) == ca_monop_not_implement ) ) ) {
|
|
937
|
-
|
|
938
|
-
|
|
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);
|
|
939
944
|
}
|
|
940
945
|
|
|
941
946
|
/* Insert cast node if the kernel wants a different input data_type. */
|
|
@@ -952,6 +957,7 @@ rb_ca_monop_build (VALUE cary, uint16_t op_id)
|
|
|
952
957
|
static VALUE
|
|
953
958
|
rb_ca_monop_s_build (VALUE klass, VALUE cary, VALUE op_id_val)
|
|
954
959
|
{
|
|
960
|
+
/* fits: an operation number from the library's own table */
|
|
955
961
|
uint16_t op_id = (uint16_t) NUM2UINT(op_id_val);
|
|
956
962
|
(void) klass;
|
|
957
963
|
return rb_ca_monop_build(cary, op_id);
|
|
@@ -976,7 +982,7 @@ rb_ca_monop_trapping (VALUE self)
|
|
|
976
982
|
CAMonOp *mo;
|
|
977
983
|
TypedData_Get_Struct(self, CAMonOp, &camonop_data_type, mo);
|
|
978
984
|
return ( ! ca_monop_is_cast(mo->op_id)
|
|
979
|
-
&&
|
|
985
|
+
&& ca_op_raises_on_cell(CA_OP_KIND_MONOP, mo->op_id, mo->parent->data_type) )
|
|
980
986
|
? Qtrue : Qfalse;
|
|
981
987
|
}
|
|
982
988
|
|
|
@@ -996,6 +1002,7 @@ rb_ca_monop_op_id (VALUE self)
|
|
|
996
1002
|
because in-place chain eval allocates no scratch; only attach (xfer_all
|
|
997
1003
|
→ output) and the parent's own xfer_stride alloc, neither of which we
|
|
998
1004
|
count here. */
|
|
1005
|
+
#ifdef CARRAY_DEV_BUILD
|
|
999
1006
|
static VALUE
|
|
1000
1007
|
rb_ca_monop_s_reset_scratch_counter (VALUE klass)
|
|
1001
1008
|
{
|
|
@@ -1021,6 +1028,7 @@ rb_ca_monop_s_materialise_count (VALUE klass)
|
|
|
1021
1028
|
{
|
|
1022
1029
|
return SIZE2NUM(ca_monop_materialise_call_count);
|
|
1023
1030
|
}
|
|
1031
|
+
#endif /* CARRAY_DEV_BUILD */
|
|
1024
1032
|
|
|
1025
1033
|
static VALUE
|
|
1026
1034
|
rb_ca_monop_s_allocate (VALUE klass)
|
|
@@ -1119,10 +1127,10 @@ Init_ca_obj_monop (void)
|
|
|
1119
1127
|
rb_define_singleton_method(rb_cCAMonOp, "__build__",
|
|
1120
1128
|
rb_ca_monop_s_build, 2);
|
|
1121
1129
|
|
|
1122
|
-
/* Lazy-view predicate
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
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);
|
|
1126
1134
|
|
|
1127
1135
|
/* op_id accessor for inspect / dump_tree consumers in Ruby. */
|
|
1128
1136
|
rb_define_method(rb_cCAMonOp, "__op_id__",
|
|
@@ -1130,6 +1138,7 @@ Init_ca_obj_monop (void)
|
|
|
1130
1138
|
rb_define_method(rb_cCAMonOp, "__trapping__", rb_ca_monop_trapping, 0);
|
|
1131
1139
|
|
|
1132
1140
|
/* Test instrumentation (not user-facing API). */
|
|
1141
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1133
1142
|
rb_define_singleton_method(rb_cCAMonOp, "__reset_scratch_counter__",
|
|
1134
1143
|
rb_ca_monop_s_reset_scratch_counter, 0);
|
|
1135
1144
|
rb_define_singleton_method(rb_cCAMonOp, "__scratch_count__",
|
|
@@ -1138,4 +1147,5 @@ Init_ca_obj_monop (void)
|
|
|
1138
1147
|
rb_ca_monop_s_reset_materialise_counter, 0);
|
|
1139
1148
|
rb_define_singleton_method(rb_cCAMonOp, "__materialise_count__",
|
|
1140
1149
|
rb_ca_monop_s_materialise_count, 0);
|
|
1150
|
+
#endif
|
|
1141
1151
|
}
|
data/ext/ca_obj_object.c
CHANGED
|
@@ -60,6 +60,15 @@ ca_object_pool_init (void *ap, int8_t ndim)
|
|
|
60
60
|
ca->dim = (ca_size_t *) ca->_pool;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/* ca->self is the CAObject's own VALUE, which compaction can move; the
|
|
64
|
+
hooks call back through it, so follow the object to its new slot. */
|
|
65
|
+
static void
|
|
66
|
+
ca_object_compact (void *ap)
|
|
67
|
+
{
|
|
68
|
+
CAObject *ca = (CAObject *) ap;
|
|
69
|
+
ca->self = rb_gc_location(ca->self);
|
|
70
|
+
}
|
|
71
|
+
|
|
63
72
|
const rb_data_type_t caobject_data_type = {
|
|
64
73
|
.parent = &caview_data_type,
|
|
65
74
|
.wrap_struct_name = "CAObject",
|
|
@@ -67,7 +76,7 @@ const rb_data_type_t caobject_data_type = {
|
|
|
67
76
|
.dmark = ca_mark,
|
|
68
77
|
.dfree = ca_free,
|
|
69
78
|
.dsize = ca_object_dsize,
|
|
70
|
-
.dcompact =
|
|
79
|
+
.dcompact = ca_object_compact
|
|
71
80
|
},
|
|
72
81
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
73
82
|
};
|
|
@@ -84,15 +93,23 @@ ca_objectmask_dsize (const void *ap)
|
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
/* The mask reads and writes through its CAObject, and its cache is the
|
|
87
|
-
CAObject's; it keeps the CAObject alive
|
|
96
|
+
CAObject's; it keeps the CAObject alive, and follows it when compaction
|
|
97
|
+
moves it. */
|
|
88
98
|
static void
|
|
89
99
|
ca_objmask_mark (void *ap)
|
|
90
100
|
{
|
|
91
101
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
92
|
-
|
|
102
|
+
rb_gc_mark_movable(ca->array);
|
|
93
103
|
ca_mark(ap);
|
|
94
104
|
}
|
|
95
105
|
|
|
106
|
+
static void
|
|
107
|
+
ca_objmask_compact (void *ap)
|
|
108
|
+
{
|
|
109
|
+
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
110
|
+
ca->array = rb_gc_location(ca->array);
|
|
111
|
+
}
|
|
112
|
+
|
|
96
113
|
const rb_data_type_t caobjectmask_data_type = {
|
|
97
114
|
.parent = &carray_data_type,
|
|
98
115
|
.wrap_struct_name = "CAObjectMask",
|
|
@@ -100,7 +117,7 @@ const rb_data_type_t caobjectmask_data_type = {
|
|
|
100
117
|
.dmark = ca_objmask_mark,
|
|
101
118
|
.dfree = ca_free,
|
|
102
119
|
.dsize = ca_objectmask_dsize,
|
|
103
|
-
.dcompact =
|
|
120
|
+
.dcompact = ca_objmask_compact
|
|
104
121
|
},
|
|
105
122
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
106
123
|
};
|
|
@@ -111,6 +128,7 @@ VALUE rb_cCAObjectMask;
|
|
|
111
128
|
static CAObjectMask *
|
|
112
129
|
ca_objmask_new (VALUE array, int8_t ndim, ca_size_t *dim)
|
|
113
130
|
{
|
|
131
|
+
/* check: the mask takes the CAObject's own shape, already checked */
|
|
114
132
|
CAObjectMask *ca = ALLOC(CAObjectMask);
|
|
115
133
|
/* CA_OBJ_OBJECT_MASK registers no pool_init, so it lives on the legacy
|
|
116
134
|
ALLOC_N path (dim allocated separately, freed via free_ca_wrap's else
|
|
@@ -135,50 +153,74 @@ ca_objmask_mask_data (void *ap)
|
|
|
135
153
|
rb_intern("mask"), 0);
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
/*
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
/* A wrap handed to a hook points at a buffer the caller frees once the
|
|
157
|
+
hook returns. Taking it back leaves an array of no cells: a hook that
|
|
158
|
+
kept it holds something that raises when read, not a pointer into freed
|
|
159
|
+
memory. */
|
|
160
|
+
static char ca_object_no_cells[16];
|
|
161
|
+
|
|
162
|
+
static void
|
|
163
|
+
ca_object_empty_wrap (CArray *w)
|
|
164
|
+
{
|
|
165
|
+
int8_t k;
|
|
166
|
+
/* Not NULL: an entity whose pointer is NULL reads as detached. */
|
|
167
|
+
w->ptr = ca_object_no_cells;
|
|
168
|
+
w->elements = 0;
|
|
169
|
+
for ( k = 0; k < w->ndim; k++ ) {
|
|
170
|
+
w->dim[k] = 0;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Calls copy_data / sync_data with a wrap of a caller's buffer, shaped as
|
|
175
|
+
the object, and takes the buffer back however the call leaves. The wrap
|
|
176
|
+
shares the object's mask (the data's), and whatever mask it holds after
|
|
177
|
+
the call becomes the data's: a hook that writes masked values masks the
|
|
178
|
+
object's cells. The data points at the buffer for the duration too, for
|
|
179
|
+
a hook that reads the object back while it runs. */
|
|
143
180
|
|
|
144
181
|
typedef struct {
|
|
145
|
-
|
|
146
|
-
char
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
VALUE (*arg)(void *);
|
|
150
|
-
void *ap;
|
|
182
|
+
CAObject *ca;
|
|
183
|
+
char *saved;
|
|
184
|
+
ID mid;
|
|
185
|
+
VALUE wrap;
|
|
151
186
|
} ca_object_lend_t;
|
|
152
187
|
|
|
153
188
|
static VALUE
|
|
154
189
|
ca_object_lend_body (VALUE varg)
|
|
155
190
|
{
|
|
156
191
|
ca_object_lend_t *l = (ca_object_lend_t *) varg;
|
|
157
|
-
return rb_funcall(l->
|
|
192
|
+
return rb_funcall(l->ca->self, l->mid, 1, l->wrap);
|
|
158
193
|
}
|
|
159
194
|
|
|
160
195
|
static VALUE
|
|
161
196
|
ca_object_lend_restore (VALUE varg)
|
|
162
197
|
{
|
|
163
198
|
ca_object_lend_t *l = (ca_object_lend_t *) varg;
|
|
164
|
-
*
|
|
199
|
+
CArray *w = (CArray *) DATA_PTR(l->wrap);
|
|
200
|
+
l->ca->data->mask = w->mask;
|
|
201
|
+
w->mask = NULL;
|
|
202
|
+
ca_object_empty_wrap(w);
|
|
203
|
+
l->ca->data->ptr = l->saved;
|
|
165
204
|
return Qnil;
|
|
166
205
|
}
|
|
167
206
|
|
|
168
207
|
static void
|
|
169
|
-
ca_object_call_lending (
|
|
170
|
-
VALUE (*arg)(void *), void *ap)
|
|
208
|
+
ca_object_call_lending (CAObject *ca, void *ptr, const char *mid)
|
|
171
209
|
{
|
|
172
210
|
ca_object_lend_t l;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
211
|
+
CArray *data = ca->data;
|
|
212
|
+
CAWrap *w;
|
|
213
|
+
w = ca_wrap_new(data->data_type, data->ndim, data->dim, data->bytes,
|
|
214
|
+
NULL, (char *) ptr);
|
|
215
|
+
l.wrap = ca_wrap_struct(w);
|
|
216
|
+
w->mask = data->mask;
|
|
217
|
+
l.ca = ca;
|
|
218
|
+
l.saved = data->ptr;
|
|
176
219
|
l.mid = rb_intern(mid);
|
|
177
|
-
|
|
178
|
-
l.ap = ap;
|
|
179
|
-
*slot = (char *) ptr;
|
|
220
|
+
data->ptr = (char *) ptr;
|
|
180
221
|
rb_ensure(ca_object_lend_body, (VALUE) &l,
|
|
181
222
|
ca_object_lend_restore, (VALUE) &l);
|
|
223
|
+
RB_GC_GUARD(l.wrap);
|
|
182
224
|
}
|
|
183
225
|
|
|
184
226
|
/* Calls recv.mid(*argv), where some of argv are transient wraps of a
|
|
@@ -187,8 +229,7 @@ ca_object_call_lending (char **slot, void *ptr, VALUE recv, const char *mid,
|
|
|
187
229
|
when it returns, and a wrap outlives the call: the collector scans the
|
|
188
230
|
machine stack conservatively and still finds it there, and an object
|
|
189
231
|
wrap is marked cell by cell -- through a buffer that is gone. A wrap
|
|
190
|
-
taken back
|
|
191
|
-
handle, not a stale one. */
|
|
232
|
+
taken back has no cells (ca_object_empty_wrap). */
|
|
192
233
|
|
|
193
234
|
typedef struct {
|
|
194
235
|
VALUE recv;
|
|
@@ -212,7 +253,7 @@ ca_object_hook_release (VALUE varg)
|
|
|
212
253
|
ca_object_hook_t *h = (ca_object_hook_t *) varg;
|
|
213
254
|
int i;
|
|
214
255
|
for ( i = 0; i < h->ntrans; i++ ) {
|
|
215
|
-
((CArray *) DATA_PTR(h->trans[i]))
|
|
256
|
+
ca_object_empty_wrap((CArray *) DATA_PTR(h->trans[i]));
|
|
216
257
|
}
|
|
217
258
|
return Qnil;
|
|
218
259
|
}
|
|
@@ -233,11 +274,6 @@ ca_object_call_transient (VALUE recv, const char *mid,
|
|
|
233
274
|
ca_object_hook_release, (VALUE) &h);
|
|
234
275
|
}
|
|
235
276
|
|
|
236
|
-
static VALUE
|
|
237
|
-
ca_object_data_of (void *ap)
|
|
238
|
-
{
|
|
239
|
-
return rb_ivar_get(((CAObject *) ap)->self, rb_intern("__data__"));
|
|
240
|
-
}
|
|
241
277
|
|
|
242
278
|
|
|
243
279
|
/* Forward declaration: ca_object_wrap_transient (defined further down,
|
|
@@ -710,10 +746,16 @@ ca_object_setup (CAObject *ca,
|
|
|
710
746
|
|
|
711
747
|
/* check arguments */
|
|
712
748
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
749
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
750
|
+
CA_CHECK_RANK_GIVEN(ndim);
|
|
751
|
+
CA_CHECK_DIM_GIVEN(ndim, dim);
|
|
752
|
+
CA_CHECK_BYTES_GIVEN(data_type, bytes);
|
|
753
|
+
|
|
754
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
755
|
+
run them before it allocates. */
|
|
756
|
+
if ( ca == NULL ) {
|
|
757
|
+
return 0;
|
|
758
|
+
}
|
|
717
759
|
|
|
718
760
|
/* calculate total number of elements */
|
|
719
761
|
|
|
@@ -745,7 +787,9 @@ ca_object_setup (CAObject *ca,
|
|
|
745
787
|
static CAObject *
|
|
746
788
|
ca_object_new (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes)
|
|
747
789
|
{
|
|
748
|
-
CAObject *ca
|
|
790
|
+
CAObject *ca;
|
|
791
|
+
ca_object_setup(NULL, data_type, ndim, dim, bytes);
|
|
792
|
+
ca = (CAObject *) ca_array_alloc(CA_OBJ_OBJECT, ndim);
|
|
749
793
|
ca_object_setup(ca, data_type, ndim, dim, bytes);
|
|
750
794
|
return ca;
|
|
751
795
|
}
|
|
@@ -755,7 +799,12 @@ free_ca_object (void *ap)
|
|
|
755
799
|
{
|
|
756
800
|
CAObject *ca = (CAObject *) ap;
|
|
757
801
|
if ( ca != NULL ) {
|
|
758
|
-
/*
|
|
802
|
+
/* A Face's mask is a view over its parent's mask (made by
|
|
803
|
+
ca_view_func_create_mask) and belongs to this struct. Otherwise
|
|
804
|
+
the mask is a Ruby object held in @mask, and the GC frees it. */
|
|
805
|
+
if ( ca_is_face(ca) ) {
|
|
806
|
+
ca_free(ca->mask);
|
|
807
|
+
}
|
|
759
808
|
if ( ca->_pool ) {
|
|
760
809
|
ca_array_free(ca); /* dim lives in _pool */
|
|
761
810
|
}
|
|
@@ -789,6 +838,19 @@ ca_object_mask_bytes (CAObject *ca)
|
|
|
789
838
|
return (boolean8_t *) ca->mask->ptr;
|
|
790
839
|
}
|
|
791
840
|
|
|
841
|
+
/* Whether the mask of this object comes from its mask_* hooks. Then a
|
|
842
|
+
fetched value says nothing about the mask: a cell the hooks mask stays
|
|
843
|
+
masked when its value is read, and only a fetcher answering UNDEF marks
|
|
844
|
+
one. Without hooks the mask is what the fetches have answered, so a
|
|
845
|
+
value fetched clears the cell. */
|
|
846
|
+
static int
|
|
847
|
+
ca_object_mask_from_hooks (CAObject *ca)
|
|
848
|
+
{
|
|
849
|
+
return rb_obj_respond_to(ca->self, rb_intern("mask_fetch_addr"), Qtrue)
|
|
850
|
+
|| rb_obj_respond_to(ca->self, rb_intern("mask_fetch_index"), Qtrue)
|
|
851
|
+
|| rb_obj_respond_to(ca->self, rb_intern("mask_copy_data"), Qtrue);
|
|
852
|
+
}
|
|
853
|
+
|
|
792
854
|
/* per-cell cores: the addr- and index-primary Ruby-callback bridge logic,
|
|
793
855
|
direction-unified. The fetch_* / store_* slots below are thin
|
|
794
856
|
forwarders onto these. */
|
|
@@ -809,7 +871,7 @@ ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
|
809
871
|
}
|
|
810
872
|
}
|
|
811
873
|
else {
|
|
812
|
-
if ( ca_has_mask(ca) ) {
|
|
874
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
813
875
|
ca_object_mask_bytes(ca)[addr] = 0;
|
|
814
876
|
}
|
|
815
877
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -831,7 +893,7 @@ ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
|
831
893
|
}
|
|
832
894
|
}
|
|
833
895
|
else {
|
|
834
|
-
if ( ca_has_mask(ca) ) {
|
|
896
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
835
897
|
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 0;
|
|
836
898
|
}
|
|
837
899
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -877,7 +939,7 @@ ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
|
877
939
|
}
|
|
878
940
|
}
|
|
879
941
|
else {
|
|
880
|
-
if ( ca_has_mask(ca) ) {
|
|
942
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
881
943
|
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 0;
|
|
882
944
|
}
|
|
883
945
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -895,7 +957,7 @@ ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
|
895
957
|
}
|
|
896
958
|
}
|
|
897
959
|
else {
|
|
898
|
-
if ( ca_has_mask(ca) ) {
|
|
960
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
899
961
|
ca_object_mask_bytes(ca)[addr] = 0;
|
|
900
962
|
}
|
|
901
963
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -924,8 +986,8 @@ static void
|
|
|
924
986
|
ca_object_func_allocate (void *ap)
|
|
925
987
|
{
|
|
926
988
|
CAObject *ca = (CAObject *) ap;
|
|
927
|
-
/*
|
|
928
|
-
ca->data->ptr = xmalloc(ca_length(ca));
|
|
989
|
+
/* cells: seeded with 0, which a copy_data that skips cells leaves visible */
|
|
990
|
+
ca->data->ptr = xmalloc(ca_length(ca));
|
|
929
991
|
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
930
992
|
VALUE *p = (VALUE *) ca->data->ptr;
|
|
931
993
|
VALUE zero = INT2NUM(0);
|
|
@@ -951,12 +1013,51 @@ ca_object_func_allocate (void *ap)
|
|
|
951
1013
|
arithmetic all work via the slow per-element fallback. The fast bulk
|
|
952
1014
|
path is opt-in by defining copy_data / sync_data / fill_data. */
|
|
953
1015
|
|
|
1016
|
+
/* copy_data of an object whose mask comes from its hooks: the array it is
|
|
1017
|
+
handed must not carry the mask's cache, or a store of its values into it
|
|
1018
|
+
(d[] = src) would clear the cells the hooks mask. It is handed without a
|
|
1019
|
+
mask, and a mask the call makes on it is dropped. */
|
|
1020
|
+
typedef struct {
|
|
1021
|
+
CAObject *ca;
|
|
1022
|
+
void *ptr;
|
|
1023
|
+
CArray *mask;
|
|
1024
|
+
} ca_object_copy_bare_t;
|
|
1025
|
+
|
|
1026
|
+
static VALUE
|
|
1027
|
+
ca_object_copy_bare_body (VALUE arg)
|
|
1028
|
+
{
|
|
1029
|
+
ca_object_copy_bare_t *c = (ca_object_copy_bare_t *) arg;
|
|
1030
|
+
ca_object_call_lending(c->ca, c->ptr, "copy_data");
|
|
1031
|
+
return Qnil;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
static VALUE
|
|
1035
|
+
ca_object_copy_bare_restore (VALUE arg)
|
|
1036
|
+
{
|
|
1037
|
+
ca_object_copy_bare_t *c = (ca_object_copy_bare_t *) arg;
|
|
1038
|
+
CArray *made = c->ca->data->mask;
|
|
1039
|
+
if ( made != NULL && made != c->mask ) {
|
|
1040
|
+
ca_free(made);
|
|
1041
|
+
}
|
|
1042
|
+
c->ca->data->mask = c->mask;
|
|
1043
|
+
return Qnil;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
954
1046
|
static void
|
|
955
1047
|
ca_object_dispatch_copy (CAObject *ca, void *ptr)
|
|
956
1048
|
{
|
|
957
1049
|
if ( rb_obj_respond_to(ca->self, rb_intern("copy_data"), Qtrue) ) {
|
|
958
|
-
|
|
959
|
-
|
|
1050
|
+
if ( ca->data->mask != NULL && ca_object_mask_from_hooks(ca) ) {
|
|
1051
|
+
ca_object_copy_bare_t c;
|
|
1052
|
+
c.ca = ca;
|
|
1053
|
+
c.ptr = ptr;
|
|
1054
|
+
c.mask = ca->data->mask;
|
|
1055
|
+
ca->data->mask = NULL;
|
|
1056
|
+
rb_ensure(ca_object_copy_bare_body, (VALUE) &c,
|
|
1057
|
+
ca_object_copy_bare_restore, (VALUE) &c);
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
ca_object_call_lending(ca, ptr, "copy_data");
|
|
960
1061
|
}
|
|
961
1062
|
else {
|
|
962
1063
|
ca_size_t addr;
|
|
@@ -971,8 +1072,7 @@ static void
|
|
|
971
1072
|
ca_object_dispatch_sync (CAObject *ca, void *ptr)
|
|
972
1073
|
{
|
|
973
1074
|
if ( rb_obj_respond_to(ca->self, rb_intern("sync_data"), Qtrue) ) {
|
|
974
|
-
ca_object_call_lending(
|
|
975
|
-
ca_object_data_of, ca);
|
|
1075
|
+
ca_object_call_lending(ca, ptr, "sync_data");
|
|
976
1076
|
}
|
|
977
1077
|
else {
|
|
978
1078
|
ca_size_t addr;
|
|
@@ -1017,7 +1117,7 @@ ca_object_func_attach (void *ap)
|
|
|
1017
1117
|
ca_face_attach(ap);
|
|
1018
1118
|
return;
|
|
1019
1119
|
}
|
|
1020
|
-
/*
|
|
1120
|
+
/* cells: seeded with 0, which a copy_data that skips cells leaves visible */
|
|
1021
1121
|
ca->data->ptr = xmalloc(ca_length(ca));
|
|
1022
1122
|
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
1023
1123
|
VALUE *p = (VALUE *) ca->data->ptr;
|
|
@@ -1468,6 +1568,12 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
1468
1568
|
data = ca_wrap_struct(ca->data);
|
|
1469
1569
|
rb_ivar_set(self, rb_intern("__data__"), data);
|
|
1470
1570
|
|
|
1571
|
+
/* A Face's mask is a C struct owned by the Face, so the copy makes its
|
|
1572
|
+
own from the parent when it is asked for one. */
|
|
1573
|
+
if ( ca_is_face(ca) ) {
|
|
1574
|
+
return self;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1471
1577
|
ca_update_mask(cs);
|
|
1472
1578
|
if ( cs->mask ) {
|
|
1473
1579
|
ca->mask = cs->mask;
|
|
@@ -1567,7 +1673,7 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1567
1673
|
}
|
|
1568
1674
|
|
|
1569
1675
|
Check_Type(rdim, T_ARRAY);
|
|
1570
|
-
|
|
1676
|
+
CA_CHECK_RANK_GIVEN(RARRAY_LEN(rdim)); /* before dim[] is filled */
|
|
1571
1677
|
|
|
1572
1678
|
ndim = RARRAY_LEN(rdim);
|
|
1573
1679
|
for (i=0; i<ndim; i++) {
|