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/carray_slab.c
CHANGED
|
@@ -28,7 +28,20 @@
|
|
|
28
28
|
--------------------------------------------------------------------------- */
|
|
29
29
|
|
|
30
30
|
#include "carray.h"
|
|
31
|
+
#include "carray_internal.h" /* ca_attach_window, ca_calling_method_name, ca_normalize_axis_arg */
|
|
31
32
|
#include "carray_slab.h"
|
|
33
|
+
#include "ca_obj_face.h"
|
|
34
|
+
|
|
35
|
+
/* Promise 8 of the kernel iterator: a slab may be lent to Ruby as a view
|
|
36
|
+
onto the source's own memory only when the source is an entity and the
|
|
37
|
+
walk reads that memory in place (alias_ptr is src->ptr, not a scratch or
|
|
38
|
+
a root it gathered from). Any other slab is a copy, and a view built on
|
|
39
|
+
it would read memory the walk frees or reuses. */
|
|
40
|
+
static int
|
|
41
|
+
ca_slab_walk_reads_src_in_place (const ca_iter_state *it, CArray *src)
|
|
42
|
+
{
|
|
43
|
+
return ca_is_entity(src) && it->alias_ptr == src->ptr;
|
|
44
|
+
}
|
|
32
45
|
|
|
33
46
|
/* Forward declarations: per-form loop bodies are defined later in this
|
|
34
47
|
file and take a state pointer directly. */
|
|
@@ -65,24 +78,18 @@ ca_slab_parse_axes (ca_slab_iter_state_t *st, VALUE axis_arg, int8_t src_ndim)
|
|
|
65
78
|
}
|
|
66
79
|
|
|
67
80
|
n = (int) RARRAY_LEN(arr);
|
|
68
|
-
if ( n < 1 || n > CA_RANK_MAX ) {
|
|
81
|
+
if ( n < 1 || n > CA_RANK_MAX ) { /* rank-check: a list of axes, no longer than the rank */
|
|
69
82
|
rb_raise(rb_eArgError,
|
|
70
|
-
"
|
|
71
|
-
n, CA_RANK_MAX);
|
|
83
|
+
"%s: axis count %d out of range [1..%d]",
|
|
84
|
+
ca_calling_method_name(), n, CA_RANK_MAX);
|
|
72
85
|
}
|
|
73
86
|
|
|
74
87
|
for ( i = 0; i < n; i++ ) {
|
|
75
|
-
int k =
|
|
76
|
-
if ( k < 0 ) k += src_ndim;
|
|
77
|
-
if ( k < 0 || k >= src_ndim ) {
|
|
78
|
-
rb_raise(rb_eArgError,
|
|
79
|
-
"CArray::SlabIterator: axis %d out of range for ndim %d",
|
|
80
|
-
NUM2INT(rb_ary_entry(arr, i)), src_ndim);
|
|
81
|
-
}
|
|
88
|
+
int k = ca_normalize_axis_arg(rb_ary_entry(arr, i), src_ndim, NULL);
|
|
82
89
|
for ( j = 0; j < i; j++ ) {
|
|
83
90
|
if ( st->slab_axes[j] == (int8_t) k ) {
|
|
84
91
|
rb_raise(rb_eArgError,
|
|
85
|
-
"
|
|
92
|
+
"%s: duplicate axis %d", ca_calling_method_name(), k);
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
95
|
st->slab_axes[i] = (int8_t) k;
|
|
@@ -368,23 +375,17 @@ ca_slab_setup_input_slab_view (ca_slab_iter_state_t *st, CArray *src,
|
|
|
368
375
|
p_in via slab_strides into the scratch, present slab_view as
|
|
369
376
|
a CAStride over the carrier with contig strides.
|
|
370
377
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
"(alias_mode = %d)", (int) am);
|
|
383
|
-
}
|
|
384
|
-
contig = ca_slab_strides_are_row_major_contig(slab_ndim,
|
|
385
|
-
st->t1->slab_dims,
|
|
386
|
-
st->t1->slab_strides,
|
|
387
|
-
src->bytes);
|
|
378
|
+
Path (a) needs p_in to lie in src's own buffer: src is an entity
|
|
379
|
+
and the iterator walks that buffer (alias_ptr is src->ptr, not a
|
|
380
|
+
scratch it gathered into). Any other source -- a view, whose cells
|
|
381
|
+
the iterator hands out from the root, a parent or its own scratch --
|
|
382
|
+
takes path (b): the iterator describes every slab by p_in and
|
|
383
|
+
slab_strides, whatever its mode. */
|
|
384
|
+
int contig = ca_slab_walk_reads_src_in_place(st->t1, src)
|
|
385
|
+
&& ca_slab_strides_are_row_major_contig(slab_ndim,
|
|
386
|
+
st->t1->slab_dims,
|
|
387
|
+
st->t1->slab_strides,
|
|
388
|
+
src->bytes);
|
|
388
389
|
if ( contig ) {
|
|
389
390
|
/* (a) contig multi-axis ALIAS: parent=src, K-D strides match src. */
|
|
390
391
|
st->slab_view = ca_slab_build_slab_view(st->self, src->data_type,
|
|
@@ -440,7 +441,11 @@ ca_slab_setup_input_slab_view (ca_slab_iter_state_t *st, CArray *src,
|
|
|
440
441
|
ca_size_t strides[1];
|
|
441
442
|
dim[0] = fiber_len;
|
|
442
443
|
strides[0] = src->bytes;
|
|
443
|
-
|
|
444
|
+
/* A window onto src only when the fiber lies in src's own buffer:
|
|
445
|
+
an entity the iterator walks in place, whose fiber is contiguous.
|
|
446
|
+
A view's fiber comes from the root or the iterator's scratch, so it
|
|
447
|
+
goes through a carrier. */
|
|
448
|
+
in_alias = ca_slab_walk_reads_src_in_place(st->t1, src) && (in_stride == src->bytes);
|
|
444
449
|
|
|
445
450
|
if ( in_alias ) {
|
|
446
451
|
/* ALIAS: parent = src. ca_stride_setup auto-creates slab_view->mask
|
|
@@ -496,8 +501,18 @@ ca_slab_advance_slab_view (ca_slab_iter_state_t *st,
|
|
|
496
501
|
slab_cs->base_offset = (ca_size_t) (p_in - src->ptr);
|
|
497
502
|
if ( slab_cs->mask != NULL ) {
|
|
498
503
|
CAStride *mask_cs = (CAStride *) slab_cs->mask;
|
|
499
|
-
|
|
500
|
-
|
|
504
|
+
if ( m_in != NULL ) {
|
|
505
|
+
mask_cs->ptr = (char *) m_in;
|
|
506
|
+
mask_cs->base_offset = (ca_size_t) ((char *) m_in - src->mask->ptr);
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
/* The walk was opened on a source without a mask and the block
|
|
510
|
+
has given it one since: there is no mask cursor, so the slab's
|
|
511
|
+
mask reads the source's mask at the cell the data starts on. */
|
|
512
|
+
mask_cs->ptr = NULL;
|
|
513
|
+
mask_cs->base_offset = (ca_size_t) ((p_in - src->ptr) / src->bytes)
|
|
514
|
+
* src->mask->bytes;
|
|
515
|
+
}
|
|
501
516
|
}
|
|
502
517
|
} else if ( st->own_data_scratch != NULL ) {
|
|
503
518
|
/* Non-contig multi-axis: K-D gather from src memory (via
|
|
@@ -517,7 +532,7 @@ ca_slab_advance_slab_view (ca_slab_iter_state_t *st,
|
|
|
517
532
|
both slab_view and carrier at the iter's delivered addr. */
|
|
518
533
|
slab_cs->ptr = p_in;
|
|
519
534
|
carrier_cw->ptr = p_in;
|
|
520
|
-
if ( slab_cs->mask != NULL ) {
|
|
535
|
+
if ( slab_cs->mask != NULL && m_in != NULL ) {
|
|
521
536
|
CAStride *mask_cs = (CAStride *) slab_cs->mask;
|
|
522
537
|
mask_cs->ptr = (char *) m_in;
|
|
523
538
|
carrier_cw->mask->ptr = (char *) m_in;
|
|
@@ -525,6 +540,44 @@ ca_slab_advance_slab_view (ca_slab_iter_state_t *st,
|
|
|
525
540
|
}
|
|
526
541
|
}
|
|
527
542
|
|
|
543
|
+
/* map_slab: mark in the output the cells the block's result has masked.
|
|
544
|
+
The output is an entity walked in place, so the slab starts at
|
|
545
|
+
last_data_off in its buffer and steps by slab_strides; the output gets
|
|
546
|
+
a mask only when some result has a masked cell. */
|
|
547
|
+
static void
|
|
548
|
+
ca_map_slab_carry_mask (ca_slab_iter_state_t *st, CArray *out, CArray *res,
|
|
549
|
+
ca_size_t slab_elements)
|
|
550
|
+
{
|
|
551
|
+
ca_iter_state *t = st->t1_out;
|
|
552
|
+
volatile VALUE h = 0;
|
|
553
|
+
boolean8_t *m;
|
|
554
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
555
|
+
ca_size_t i;
|
|
556
|
+
int8_t k;
|
|
557
|
+
|
|
558
|
+
if ( ! ca_has_mask(res) ) return;
|
|
559
|
+
ca_update_mask(res);
|
|
560
|
+
m = (boolean8_t *) ALLOCV(h, slab_elements);
|
|
561
|
+
ca_xfer_all(res->mask, m, CA_XFER_GET);
|
|
562
|
+
for ( i = 0; i < slab_elements && ! m[i]; i++ ) ;
|
|
563
|
+
if ( i < slab_elements ) {
|
|
564
|
+
ca_create_mask(out);
|
|
565
|
+
for ( k = 0; k < t->slab_ndim; k++ ) idx[k] = 0;
|
|
566
|
+
for ( i = 0; i < slab_elements; i++ ) {
|
|
567
|
+
if ( m[i] ) {
|
|
568
|
+
ca_size_t off = t->last_data_off;
|
|
569
|
+
for ( k = 0; k < t->slab_ndim; k++ ) off += idx[k] * t->slab_strides[k];
|
|
570
|
+
((boolean8_t *) out->mask->ptr)[off / out->bytes] = 1;
|
|
571
|
+
}
|
|
572
|
+
for ( k = t->slab_ndim - 1; k >= 0; k-- ) {
|
|
573
|
+
if ( ++idx[k] < t->slab_dims[k] ) break;
|
|
574
|
+
idx[k] = 0;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
ALLOCV_END(h);
|
|
579
|
+
}
|
|
580
|
+
|
|
528
581
|
/* Convert a Ruby Numeric scalar into bytes of slab_view's data_type and
|
|
529
582
|
fill the entire slab buffer at out_ptr. Used when the user block
|
|
530
583
|
returns a scalar instead of a CArray (= broadcast over the slab).
|
|
@@ -533,9 +586,6 @@ static void
|
|
|
533
586
|
ca_slab_fill_scalar (VALUE source, char *out_ptr, ca_size_t slab_elements,
|
|
534
587
|
int8_t out_data_type, ca_size_t out_bytes, VALUE val)
|
|
535
588
|
{
|
|
536
|
-
char buf[64];
|
|
537
|
-
char *scratch = (out_bytes <= (ca_size_t) sizeof(buf)) ? buf
|
|
538
|
-
: xmalloc(out_bytes);
|
|
539
589
|
ca_size_t i;
|
|
540
590
|
/* Use source's data_type-aware conversion (rb_ca_obj2ptr looks at the
|
|
541
591
|
receiver's data_type). Build a stand-in scalar buffer via the
|
|
@@ -546,24 +596,73 @@ ca_slab_fill_scalar (VALUE source, char *out_ptr, ca_size_t slab_elements,
|
|
|
546
596
|
conversion through the actual output entity (= we already have
|
|
547
597
|
`source`-keyed obj2ptr in carray_cast.c). Here we construct an
|
|
548
598
|
ephemeral CScalar of the output data_type to anchor the cast. */
|
|
549
|
-
VALUE cs_anchor =
|
|
599
|
+
volatile VALUE cs_anchor =
|
|
550
600
|
rb_cscalar_new_with_value((int) out_data_type, (int) out_bytes, val);
|
|
551
601
|
CScalar *anchor_ca;
|
|
552
602
|
(void) source;
|
|
553
603
|
TypedData_Get_Struct(cs_anchor, CScalar, &cscalar_data_type, anchor_ca);
|
|
554
|
-
ca_attach(anchor_ca);
|
|
555
|
-
memcpy(scratch, anchor_ca->ptr, out_bytes);
|
|
556
|
-
ca_detach(anchor_ca);
|
|
557
604
|
for ( i = 0; i < slab_elements; i++ ) {
|
|
558
|
-
memcpy(out_ptr + i * out_bytes,
|
|
605
|
+
memcpy(out_ptr + i * out_bytes, anchor_ca->ptr, out_bytes);
|
|
606
|
+
}
|
|
607
|
+
RB_GC_GUARD(cs_anchor);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/* map_slab's cast-on-scatter: each cell of the block's result converted
|
|
611
|
+
into the output data type, with the result attached for the fetches. */
|
|
612
|
+
|
|
613
|
+
typedef struct {
|
|
614
|
+
VALUE result;
|
|
615
|
+
CArray *res;
|
|
616
|
+
VALUE output_view;
|
|
617
|
+
char *write_target;
|
|
618
|
+
ca_size_t out_bytes;
|
|
619
|
+
ca_size_t slab_elements;
|
|
620
|
+
} ca_map_slab_cast_ctx_t;
|
|
621
|
+
|
|
622
|
+
static VALUE
|
|
623
|
+
ca_map_slab_cast_body (VALUE arg)
|
|
624
|
+
{
|
|
625
|
+
ca_map_slab_cast_ctx_t *c = (ca_map_slab_cast_ctx_t *) arg;
|
|
626
|
+
volatile VALUE holder;
|
|
627
|
+
char *scratch = ALLOCV_N(char, holder, c->out_bytes);
|
|
628
|
+
ca_size_t i;
|
|
629
|
+
for ( i = 0; i < c->slab_elements; i++ ) {
|
|
630
|
+
VALUE elem;
|
|
631
|
+
ca_size_t idx[CA_RANK_MAX] = { 0 };
|
|
632
|
+
ca_size_t flat = i;
|
|
633
|
+
int8_t k;
|
|
634
|
+
for ( k = c->res->ndim - 1; k >= 0; k-- ) {
|
|
635
|
+
idx[k] = flat % c->res->dim[k];
|
|
636
|
+
flat /= c->res->dim[k];
|
|
637
|
+
}
|
|
638
|
+
elem = rb_ca_fetch_index(c->result, idx);
|
|
639
|
+
rb_ca_obj2ptr(c->output_view, elem, scratch);
|
|
640
|
+
memcpy(c->write_target + i * c->out_bytes, scratch, c->out_bytes);
|
|
641
|
+
}
|
|
642
|
+
ALLOCV_END(holder);
|
|
643
|
+
return Qnil;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/* What the block sees of the slab: the slab view itself, or, over a Face,
|
|
647
|
+
the slab view under that Face, as `a[...]` would give it. The slab
|
|
648
|
+
view is moved per slab in place, and the Face reads through it, so one
|
|
649
|
+
is built per walk. */
|
|
650
|
+
static VALUE
|
|
651
|
+
ca_slab_piece (ca_slab_iter_state_t *st)
|
|
652
|
+
{
|
|
653
|
+
CArray *src;
|
|
654
|
+
TypedData_Get_Struct(st->self, CArray, &carray_data_type, src);
|
|
655
|
+
if ( ! ca_is_face(src) ) {
|
|
656
|
+
return st->slab_view;
|
|
559
657
|
}
|
|
560
|
-
|
|
658
|
+
return ca_face_lift(st->slab_view, st->self);
|
|
561
659
|
}
|
|
562
660
|
|
|
563
661
|
static VALUE
|
|
564
662
|
ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
565
663
|
{
|
|
566
664
|
CArray *src;
|
|
665
|
+
volatile VALUE piece;
|
|
567
666
|
CArray *out;
|
|
568
667
|
uint32_t flags_in;
|
|
569
668
|
uint32_t flags_out;
|
|
@@ -573,16 +672,13 @@ ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
|
573
672
|
|
|
574
673
|
TypedData_Get_Struct(st->self, CArray, &carray_data_type, src);
|
|
575
674
|
|
|
576
|
-
/*
|
|
577
|
-
|
|
578
|
-
is intentionally NOT scattered — block return CArray mask info is
|
|
579
|
-
dropped (= simplest contract). */
|
|
675
|
+
/* The input slab carries the source's mask; a CArray the block
|
|
676
|
+
returns carries its mask into the output (ca_map_slab_carry_mask). */
|
|
580
677
|
|
|
581
678
|
/* Step 1: allocate output entity (same shape as src, data_type from opts). */
|
|
582
679
|
st->output = rb_carray_new(st->out_data_type, src->ndim, src->dim,
|
|
583
680
|
st->out_bytes, NULL);
|
|
584
681
|
TypedData_Get_Struct(st->output, CArray, &carray_data_type, out);
|
|
585
|
-
ca_allocate(out); /* entity ptr usable as both read + write target */
|
|
586
682
|
|
|
587
683
|
/* Step 2: T1 init on both sides. FIBER_CONTIG is naxes==1 only;
|
|
588
684
|
multi-axis omits it. Output side gets CA_KERNEL_WRITE. */
|
|
@@ -652,6 +748,7 @@ ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
|
652
748
|
TypedData_Get_Struct(st->output_slab_view, CAWrap,
|
|
653
749
|
&cawrap_data_type, out_slab_cw);
|
|
654
750
|
|
|
751
|
+
piece = ca_slab_piece(st);
|
|
655
752
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) &&
|
|
656
753
|
ca_iter_state_next_slab_axes(st->t1_out, &p_out, &m_out) ) {
|
|
657
754
|
VALUE result;
|
|
@@ -669,7 +766,7 @@ ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
|
669
766
|
? st->own_out_scratch : p_out;
|
|
670
767
|
out_slab_cw->ptr = write_target;
|
|
671
768
|
|
|
672
|
-
result = rb_yield(
|
|
769
|
+
result = rb_yield(piece);
|
|
673
770
|
|
|
674
771
|
/* Strict shape check. */
|
|
675
772
|
if ( rb_obj_is_kind_of(result, rb_cCArray) ) {
|
|
@@ -698,34 +795,22 @@ ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
|
698
795
|
(long long) slab_elements, (int) slab_cs->ndim);
|
|
699
796
|
}
|
|
700
797
|
if ( res->data_type == st->out_data_type && res->bytes == st->out_bytes ) {
|
|
701
|
-
ca_attach(res);
|
|
702
798
|
ca_xfer_all(res, write_target, CA_XFER_GET);
|
|
703
|
-
ca_detach(res);
|
|
704
799
|
}
|
|
705
800
|
else {
|
|
706
801
|
/* Cast-on-scatter via per-cell obj2ptr. Writes to write_target
|
|
707
|
-
(= either p_out direct or own_out_scratch).
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
int8_t k;
|
|
718
|
-
for ( k = res->ndim - 1; k >= 0; k-- ) {
|
|
719
|
-
idx[k] = flat % res->dim[k];
|
|
720
|
-
flat /= res->dim[k];
|
|
721
|
-
}
|
|
722
|
-
elem = rb_ca_fetch_index(result, idx);
|
|
723
|
-
rb_ca_obj2ptr(st->output_slab_view, elem, scratch);
|
|
724
|
-
memcpy(write_target + i * st->out_bytes, scratch, st->out_bytes);
|
|
725
|
-
}
|
|
726
|
-
ca_detach(res);
|
|
727
|
-
if ( scratch != buf ) xfree(scratch);
|
|
802
|
+
(= either p_out direct or own_out_scratch). The conversion
|
|
803
|
+
can raise, so the result is read in a window. */
|
|
804
|
+
ca_map_slab_cast_ctx_t c;
|
|
805
|
+
c.result = result;
|
|
806
|
+
c.res = res;
|
|
807
|
+
c.output_view = st->output_slab_view;
|
|
808
|
+
c.write_target = write_target;
|
|
809
|
+
c.out_bytes = st->out_bytes;
|
|
810
|
+
c.slab_elements = slab_elements;
|
|
811
|
+
ca_attach_window(1, &res, "r", ca_map_slab_cast_body, (VALUE) &c);
|
|
728
812
|
}
|
|
813
|
+
ca_map_slab_carry_mask(st, out, res, slab_elements);
|
|
729
814
|
}
|
|
730
815
|
else if ( rb_obj_is_kind_of(result, rb_cNumeric) ||
|
|
731
816
|
result == Qtrue || result == Qfalse ||
|
|
@@ -820,7 +905,6 @@ ca_slab_reduce_setup (ca_slab_iter_state_t *st, CArray **out_src,
|
|
|
820
905
|
st->output = rb_carray_new(st->out_data_type, out_ndim, out_dim,
|
|
821
906
|
st->out_bytes, NULL);
|
|
822
907
|
TypedData_Get_Struct(st->output, CArray, &carray_data_type, out);
|
|
823
|
-
ca_allocate(out);
|
|
824
908
|
|
|
825
909
|
/* FIBER_CONTIG is naxes==1 only (T1 substrate contract). Multi-axis
|
|
826
910
|
omits the flag and uses bare CA_SLAB_AXES; T1 picks an in-src
|
|
@@ -848,10 +932,36 @@ ca_slab_reduce_setup (ca_slab_iter_state_t *st, CArray **out_src,
|
|
|
848
932
|
/* Per-slab block form: block receives the slab CArray, returns a
|
|
849
933
|
scalar; each scalar is cast into the corresponding output cell.
|
|
850
934
|
(`init:` absent ⇒ this path) */
|
|
935
|
+
/* Write one reduced value into the reduction output. UNDEF from the
|
|
936
|
+
block masks the cell, as storing UNDEF into an array does; obj2ptr
|
|
937
|
+
would read it as 0. */
|
|
938
|
+
static void
|
|
939
|
+
ca_slab_store_reduced (ca_slab_iter_state_t *st, CArray *out,
|
|
940
|
+
ca_size_t out_idx, VALUE value, char *scratch)
|
|
941
|
+
{
|
|
942
|
+
char *dst = out->ptr + out_idx * st->out_bytes;
|
|
943
|
+
if ( value == CA_UNDEF ) {
|
|
944
|
+
if ( out->mask == NULL ) {
|
|
945
|
+
ca_create_mask(out);
|
|
946
|
+
}
|
|
947
|
+
((boolean8_t *) out->mask->ptr)[out_idx] = 1;
|
|
948
|
+
if ( out->data_type == CA_OBJECT ) {
|
|
949
|
+
*(VALUE *) dst = INT2FIX(0);
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
memset(dst, 0, st->out_bytes);
|
|
953
|
+
}
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
rb_ca_obj2ptr(st->output, value, scratch);
|
|
957
|
+
memcpy(dst, scratch, st->out_bytes);
|
|
958
|
+
}
|
|
959
|
+
|
|
851
960
|
static VALUE
|
|
852
961
|
ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
853
962
|
{
|
|
854
963
|
CArray *src;
|
|
964
|
+
volatile VALUE piece;
|
|
855
965
|
CArray *out;
|
|
856
966
|
ca_size_t fiber_len;
|
|
857
967
|
char *p_in;
|
|
@@ -862,6 +972,7 @@ ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
|
862
972
|
ca_size_t out_idx = 0;
|
|
863
973
|
char buf[64];
|
|
864
974
|
char *scratch;
|
|
975
|
+
volatile VALUE scratch_holder = 0; /* 0, not Qnil: ALLOCV_END reads a non-zero holder */
|
|
865
976
|
|
|
866
977
|
ca_slab_reduce_setup(st, &src, &fiber_len);
|
|
867
978
|
TypedData_Get_Struct(st->output, CArray, &carray_data_type, out);
|
|
@@ -871,16 +982,19 @@ ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
|
871
982
|
TypedData_Get_Struct(st->carrier, CAWrap, &cawrap_data_type, carrier_cw);
|
|
872
983
|
}
|
|
873
984
|
|
|
874
|
-
|
|
875
|
-
|
|
985
|
+
/* The block and the conversion of its value can raise, so a scratch
|
|
986
|
+
too wide for buf is Ruby's temporary. */
|
|
987
|
+
scratch = (st->out_bytes <= (ca_size_t) sizeof(buf))
|
|
988
|
+
? buf : ALLOCV_N(char, scratch_holder, st->out_bytes);
|
|
876
989
|
|
|
990
|
+
piece = ca_slab_piece(st);
|
|
877
991
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) ) {
|
|
878
992
|
VALUE result;
|
|
879
993
|
|
|
880
994
|
ca_slab_advance_slab_view(st, slab_cs, carrier_cw,
|
|
881
995
|
src, p_in, m_in, in_alias);
|
|
882
996
|
|
|
883
|
-
result = rb_yield(
|
|
997
|
+
result = rb_yield(piece);
|
|
884
998
|
|
|
885
999
|
/* Strict scalar contract: block must return a scalar Ruby value
|
|
886
1000
|
(Numeric / Object / etc.). A CArray is a
|
|
@@ -891,7 +1005,6 @@ ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
|
891
1005
|
if ( rb_obj_is_kind_of(result, rb_cCArray) ) {
|
|
892
1006
|
CArray *res;
|
|
893
1007
|
TypedData_Get_Struct(result, CArray, &carray_data_type, res);
|
|
894
|
-
if ( scratch != buf ) xfree(scratch);
|
|
895
1008
|
rb_raise(rb_eArgError,
|
|
896
1009
|
"CArray#reduce_slab: per-slab block must return a scalar "
|
|
897
1010
|
"(got CArray with %lld element%s; use `slab[0]` or "
|
|
@@ -900,12 +1013,11 @@ ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
|
900
1013
|
res->elements == 1 ? "" : "s");
|
|
901
1014
|
}
|
|
902
1015
|
|
|
903
|
-
|
|
904
|
-
memcpy(out->ptr + out_idx * st->out_bytes, scratch, st->out_bytes);
|
|
1016
|
+
ca_slab_store_reduced(st, out, out_idx, result, scratch);
|
|
905
1017
|
out_idx++;
|
|
906
1018
|
}
|
|
907
1019
|
|
|
908
|
-
|
|
1020
|
+
ALLOCV_END(scratch_holder);
|
|
909
1021
|
return st->output;
|
|
910
1022
|
}
|
|
911
1023
|
|
|
@@ -916,6 +1028,7 @@ static VALUE
|
|
|
916
1028
|
ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
917
1029
|
{
|
|
918
1030
|
CArray *src;
|
|
1031
|
+
volatile VALUE piece;
|
|
919
1032
|
CArray *out;
|
|
920
1033
|
ca_size_t fiber_len;
|
|
921
1034
|
char *p_in;
|
|
@@ -926,6 +1039,7 @@ ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
|
926
1039
|
ca_size_t out_idx = 0;
|
|
927
1040
|
char buf[64];
|
|
928
1041
|
char *scratch;
|
|
1042
|
+
volatile VALUE scratch_holder = 0; /* 0, not Qnil: ALLOCV_END reads a non-zero holder */
|
|
929
1043
|
|
|
930
1044
|
ca_slab_reduce_setup(st, &src, &fiber_len);
|
|
931
1045
|
TypedData_Get_Struct(st->output, CArray, &carray_data_type, out);
|
|
@@ -935,9 +1049,12 @@ ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
|
935
1049
|
TypedData_Get_Struct(st->carrier, CAWrap, &cawrap_data_type, carrier_cw);
|
|
936
1050
|
}
|
|
937
1051
|
|
|
938
|
-
|
|
939
|
-
|
|
1052
|
+
/* The block and the conversion of its value can raise, so a scratch
|
|
1053
|
+
too wide for buf is Ruby's temporary. */
|
|
1054
|
+
scratch = (st->out_bytes <= (ca_size_t) sizeof(buf))
|
|
1055
|
+
? buf : ALLOCV_N(char, scratch_holder, st->out_bytes);
|
|
940
1056
|
|
|
1057
|
+
piece = ca_slab_piece(st);
|
|
941
1058
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) ) {
|
|
942
1059
|
VALUE acc;
|
|
943
1060
|
ca_size_t i;
|
|
@@ -955,7 +1072,7 @@ ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
|
955
1072
|
ca_size_t total = st->t1->slab_elements;
|
|
956
1073
|
for ( i = 0; i < total; i++ ) {
|
|
957
1074
|
VALUE x;
|
|
958
|
-
x = rb_ca_fetch_index(
|
|
1075
|
+
x = rb_ca_fetch_index(piece, kidx);
|
|
959
1076
|
acc = rb_yield_values(2, acc, x);
|
|
960
1077
|
/* Increment kidx[] row-major. */
|
|
961
1078
|
for ( k = slab_cs->ndim - 1; k >= 0; k-- ) {
|
|
@@ -966,12 +1083,11 @@ ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
|
966
1083
|
(void) fiber_len;
|
|
967
1084
|
}
|
|
968
1085
|
|
|
969
|
-
|
|
970
|
-
memcpy(out->ptr + out_idx * st->out_bytes, scratch, st->out_bytes);
|
|
1086
|
+
ca_slab_store_reduced(st, out, out_idx, acc, scratch);
|
|
971
1087
|
out_idx++;
|
|
972
1088
|
}
|
|
973
1089
|
|
|
974
|
-
|
|
1090
|
+
ALLOCV_END(scratch_holder);
|
|
975
1091
|
return st->output;
|
|
976
1092
|
}
|
|
977
1093
|
|
|
@@ -994,6 +1110,7 @@ static VALUE
|
|
|
994
1110
|
ca_slab_run_each (ca_slab_iter_state_t *st)
|
|
995
1111
|
{
|
|
996
1112
|
CArray *src;
|
|
1113
|
+
volatile VALUE piece;
|
|
997
1114
|
char *p_in;
|
|
998
1115
|
boolean8_t *m_in;
|
|
999
1116
|
CAStride *slab_cs;
|
|
@@ -1027,10 +1144,11 @@ ca_slab_run_each (ca_slab_iter_state_t *st)
|
|
|
1027
1144
|
TypedData_Get_Struct(st->carrier, CAWrap, &cawrap_data_type, carrier_cw);
|
|
1028
1145
|
}
|
|
1029
1146
|
|
|
1147
|
+
piece = ca_slab_piece(st);
|
|
1030
1148
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) ) {
|
|
1031
1149
|
ca_slab_advance_slab_view(st, slab_cs, carrier_cw,
|
|
1032
1150
|
src, p_in, m_in, in_alias);
|
|
1033
|
-
rb_yield(
|
|
1151
|
+
rb_yield(piece); /* return value discarded */
|
|
1034
1152
|
}
|
|
1035
1153
|
|
|
1036
1154
|
return st->self;
|
|
@@ -1055,11 +1173,56 @@ slab_state_run_body (VALUE arg)
|
|
|
1055
1173
|
return Qnil;
|
|
1056
1174
|
}
|
|
1057
1175
|
|
|
1176
|
+
/* The slab views outlive the walk: the block may keep the slab or a view
|
|
1177
|
+
of it (`row.dup`), and the GC marks an object array's cells for as long
|
|
1178
|
+
as it has a ptr. Before the scratch they point into is freed, the
|
|
1179
|
+
input slab and its carrier are moved onto a copy of the last slab,
|
|
1180
|
+
held by the carrier, and the internal output view lets go of its
|
|
1181
|
+
buffer. A slab that is a window onto the source itself points into
|
|
1182
|
+
the source and needs nothing. */
|
|
1183
|
+
static void
|
|
1184
|
+
slab_state_release_views (ca_slab_iter_state_t *st)
|
|
1185
|
+
{
|
|
1186
|
+
if ( st->output_slab_view != Qnil ) {
|
|
1187
|
+
CArray *ov;
|
|
1188
|
+
TypedData_Get_Struct(st->output_slab_view, CArray, &carray_data_type, ov);
|
|
1189
|
+
ov->ptr = NULL;
|
|
1190
|
+
}
|
|
1191
|
+
if ( st->carrier != Qnil && st->slab_view != Qnil ) {
|
|
1192
|
+
CArray *cw, *cs, *backing;
|
|
1193
|
+
volatile VALUE bv;
|
|
1194
|
+
TypedData_Get_Struct(st->carrier, CArray, &carray_data_type, cw);
|
|
1195
|
+
TypedData_Get_Struct(st->slab_view, CArray, &carray_data_type, cs);
|
|
1196
|
+
if ( cw->ptr == NULL ) {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
backing = ca_copy(cw);
|
|
1200
|
+
bv = ca_wrap_struct(backing);
|
|
1201
|
+
if ( cw->mask && ! backing->mask ) {
|
|
1202
|
+
ca_create_mask(backing);
|
|
1203
|
+
}
|
|
1204
|
+
rb_ivar_set(st->carrier, rb_intern("__slab_backing__"), bv);
|
|
1205
|
+
if ( cs->ptr ) {
|
|
1206
|
+
cs->ptr = backing->ptr;
|
|
1207
|
+
}
|
|
1208
|
+
if ( cs->mask && cs->mask->ptr ) {
|
|
1209
|
+
cs->mask->ptr = backing->mask->ptr;
|
|
1210
|
+
}
|
|
1211
|
+
cw->ptr = backing->ptr;
|
|
1212
|
+
if ( cw->mask ) {
|
|
1213
|
+
cw->mask->ptr = backing->mask->ptr;
|
|
1214
|
+
}
|
|
1215
|
+
RB_GC_GUARD(bv);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1058
1219
|
static VALUE
|
|
1059
1220
|
slab_state_finish (VALUE arg)
|
|
1060
1221
|
{
|
|
1061
1222
|
ca_slab_iter_state_t *st = (ca_slab_iter_state_t *)(uintptr_t) arg;
|
|
1062
1223
|
|
|
1224
|
+
slab_state_release_views(st);
|
|
1225
|
+
|
|
1063
1226
|
/* T1 substrate teardown.
|
|
1064
1227
|
CAREFUL: ca_detach(slab_view) is NEVER called — T1 owns the buffer;
|
|
1065
1228
|
dropping the VALUE handles lets GC reclaim the CAStride wrappers
|
|
@@ -1124,7 +1287,7 @@ static VALUE
|
|
|
1124
1287
|
slab_extract_kwargs (int argc, VALUE *argv, const char *method_name)
|
|
1125
1288
|
{
|
|
1126
1289
|
VALUE kw = Qnil;
|
|
1127
|
-
if ( argc == 1 && RB_TYPE_P(argv[0], T_HASH) ) {
|
|
1290
|
+
if ( argc == 1 && rb_keyword_given_p() && RB_TYPE_P(argv[0], T_HASH) ) {
|
|
1128
1291
|
kw = argv[0];
|
|
1129
1292
|
}
|
|
1130
1293
|
else if ( argc != 0 ) {
|