carray 3.0.0 → 3.0.2
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/.yardopts +2 -1
- data/CHANGELOG.md +845 -3
- data/{NEWS.md → CHANGELOG.v1.md} +1 -1
- data/README.md +33 -33
- data/carray.gemspec +12 -8
- data/ext/ca_axis_dispatch.c +33 -4
- data/ext/ca_axis_group.c +256 -114
- data/ext/ca_binop_dispatch.c +5 -6
- data/ext/ca_binop_dispatch.h +0 -7
- data/ext/ca_categorical_iterator.c +121 -67
- data/ext/ca_for_each_element.h +6 -8
- data/ext/ca_group_iter.c +1 -1
- data/ext/ca_kernel_iterator.c +386 -74
- data/ext/ca_kernel_iterator.h +145 -45
- data/ext/ca_obj_array.c +62 -20
- data/ext/ca_obj_bincmp.c +57 -27
- data/ext/ca_obj_binop.c +86 -30
- data/ext/ca_obj_block.c +4 -4
- data/ext/ca_obj_const_string.c +88 -27
- data/ext/ca_obj_face.c +104 -0
- data/ext/ca_obj_face.h +48 -1
- data/ext/ca_obj_fake.c +11 -0
- data/ext/ca_obj_fixlen_string.c +21 -6
- data/ext/ca_obj_grid.c +11 -3
- data/ext/ca_obj_meld.c +125 -22
- data/ext/ca_obj_moncmp.c +33 -14
- data/ext/ca_obj_monop.c +19 -7
- data/ext/ca_obj_object.c +107 -4
- data/ext/ca_obj_record.c +3 -1
- data/ext/ca_obj_refer.c +30 -6
- data/ext/ca_obj_roll.c +13 -5
- data/ext/ca_obj_select.c +49 -34
- data/ext/ca_obj_select_axis.c +16 -6
- data/ext/ca_obj_shift.c +3 -3
- data/ext/ca_obj_stack.c +3 -8
- data/ext/ca_obj_stride.c +178 -24
- data/ext/ca_obj_string.c +11 -5
- data/ext/ca_obj_tile.c +13 -5
- data/ext/ca_obj_time.c +3 -1
- data/ext/ca_obj_timedelta.c +3 -1
- data/ext/ca_obj_transpose.c +1 -1
- data/ext/ca_obj_triop.c +62 -23
- data/ext/ca_obj_window.c +94 -19
- data/ext/ca_op_cmplx64.h +123 -0
- data/ext/ca_op_ipower.c +1 -5
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +5 -5
- data/ext/ca_sweep_engine.c +362 -155
- data/ext/ca_sweep_engine.h +39 -9
- data/ext/ca_transform_common.c +7 -0
- data/ext/carray.h +148 -132
- data/ext/carray_access.c +83 -49
- data/ext/carray_address_basis.c +590 -0
- data/ext/carray_bincount.c +8 -8
- data/ext/carray_broadcast.c +102 -9
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +2010 -335
- data/ext/carray_call_cfunc.h +153 -0
- data/ext/carray_cast.c +184 -72
- data/ext/carray_conversion.c +22 -22
- data/ext/carray_copy.c +67 -32
- data/ext/carray_core.c +140 -13
- data/ext/carray_count.c +10 -11
- data/ext/carray_element.c +7 -7
- data/ext/carray_factorize.c +72 -51
- data/ext/carray_hold.c +1 -1
- data/ext/carray_index_classifier.c +7 -21
- data/ext/carray_internal.h +36 -3
- data/ext/carray_kernels_bincmp.c +1 -0
- data/ext/carray_kernels_binop.c +320 -298
- data/ext/carray_kernels_init.c +1095 -0
- data/ext/carray_kernels_map.c +1 -0
- data/ext/carray_kernels_moncmp.c +1 -0
- data/ext/carray_kernels_monop.c +412 -411
- data/ext/carray_kernels_reduce_aggregate.c +256 -87
- data/ext/carray_kernels_reduce_boolean.c +1 -0
- data/ext/carray_kernels_reduce_cumulative.c +324 -54
- data/ext/carray_kernels_reduce_extreme.c +605 -58
- data/ext/carray_kernels_reduce_variance.c +1 -0
- data/ext/carray_kernels_scan.c +5 -4
- data/ext/carray_kernels_search.c +187 -106
- data/ext/carray_kernels_sort.c +1 -0
- data/ext/carray_kernels_triop.c +1 -0
- data/ext/carray_lazy.c +175 -5
- data/ext/carray_loop.c +7 -1
- data/ext/carray_mask.c +29 -13
- data/ext/carray_median_percentile.c +56 -1
- data/ext/carray_memory_view.c +46 -21
- data/ext/carray_operator.c +50 -53
- data/ext/carray_order.c +1 -1
- data/ext/carray_partition.c +4 -4
- data/ext/carray_random.c +391 -47
- data/ext/carray_scatter.c +1 -1
- data/ext/carray_slab.c +13 -0
- data/ext/carray_sort.c +22 -24
- data/ext/carray_sort_kernel.c +10 -10
- data/ext/carray_test.c +1 -1
- data/ext/extconf.rb +18 -0
- data/ext/mk_call_cfunc.rb +323 -145
- data/ext/mkkernel.rb +651 -129
- data/ext/ruby_carray.c +28 -17
- data/ext/version.h +4 -4
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +14 -1
- data/lib/carray/axis_group.rb +84 -7
- data/lib/carray/basics.rb +63 -59
- data/lib/carray/bincount_nd.rb +12 -12
- data/lib/carray/block_iterator.rb +111 -25
- data/lib/carray/categorical.rb +154 -37
- data/lib/carray/categorical_iterator.rb +300 -151
- data/lib/carray/conditional.rb +14 -14
- data/lib/carray/const_string.rb +131 -27
- data/lib/carray/construct.rb +61 -0
- data/lib/carray/core_extensions.rb +62 -5
- data/lib/carray/data_type_extension.rb +21 -1
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +3 -3
- data/lib/carray/frame/convert.rb +1 -1
- data/lib/carray/frame/csv_parser.rb +11 -4
- data/lib/carray/frame/frame.rb +85 -21
- data/lib/carray/frame/group.rb +36 -3
- data/lib/carray/frame/io.rb +224 -15
- data/lib/carray/frame/records.rb +18 -4
- data/lib/carray/frame/sort.rb +1 -1
- data/lib/carray/frame/verbs.rb +32 -12
- data/lib/carray/fuse_source.rb +123 -0
- data/lib/carray/fusion.rb +218 -0
- data/lib/carray/histogram.rb +16 -16
- data/lib/carray/inspect.rb +43 -16
- data/lib/carray/iterator.rb +147 -3
- data/lib/carray/lazy.rb +88 -73
- data/lib/carray/mask_gap_fill.rb +3 -1
- data/lib/carray/meld_reduce.rb +2 -2
- data/lib/carray/methods/align_addr.rb +1 -1
- data/lib/carray/methods/composition.rb +1 -1
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/is_in.rb +25 -14
- data/lib/carray/methods/locate_addr.rb +81 -3
- data/lib/carray/methods/mask_duplicates.rb +36 -2
- data/lib/carray/methods/meshgrid.rb +4 -5
- data/lib/carray/methods/mode.rb +2 -2
- data/lib/carray/methods/nunique.rb +23 -2
- data/lib/carray/methods/repeat.rb +110 -0
- data/lib/carray/methods/snap.rb +7 -2
- data/lib/carray/methods/unique.rb +44 -4
- data/lib/carray/methods/value_counts.rb +2 -2
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +0 -19
- data/lib/carray/slab_iterator.rb +77 -19
- data/lib/carray/string_operation_extension.rb +10 -6
- data/lib/carray/time.rb +906 -491
- data/lib/carray/window_iterator.rb +421 -27
- data/lib/carray.rb +7 -5
- data/yard-stubs/ca_obj_array.rb +385 -0
- data/yard-stubs/ca_obj_bitarray.rb +38 -0
- data/yard-stubs/ca_obj_bitfield.rb +43 -0
- data/yard-stubs/ca_obj_block.rb +68 -0
- data/yard-stubs/ca_obj_byte_swap.rb +56 -0
- data/yard-stubs/ca_obj_fake.rb +31 -0
- data/yard-stubs/ca_obj_farray.rb +32 -0
- data/yard-stubs/ca_obj_field.rb +45 -0
- data/yard-stubs/ca_obj_grid.rb +35 -0
- data/yard-stubs/ca_obj_refer.rb +72 -0
- data/yard-stubs/ca_obj_roll.rb +45 -0
- data/yard-stubs/ca_obj_shift.rb +43 -0
- data/yard-stubs/ca_obj_stride.rb +181 -0
- data/yard-stubs/ca_obj_tile.rb +29 -0
- data/yard-stubs/ca_obj_transpose.rb +40 -0
- data/yard-stubs/ca_obj_window.rb +57 -0
- data/yard-stubs/carray_access.rb +131 -0
- data/yard-stubs/carray_attribute.rb +246 -0
- data/yard-stubs/carray_broadcast.rb +37 -0
- data/yard-stubs/carray_cast.rb +489 -0
- data/yard-stubs/carray_class.rb +65 -0
- data/yard-stubs/carray_conversion.rb +76 -0
- data/yard-stubs/carray_copy.rb +79 -0
- data/yard-stubs/carray_core.rb +34 -0
- data/yard-stubs/carray_count.rb +84 -0
- data/yard-stubs/carray_element.rb +108 -0
- data/yard-stubs/carray_generate.rb +66 -0
- data/yard-stubs/carray_lazy.rb +228 -0
- data/yard-stubs/carray_loop.rb +140 -0
- data/yard-stubs/carray_mask.rb +259 -0
- data/yard-stubs/carray_math.rb +1615 -0
- data/yard-stubs/carray_mathfunc.rb +45 -0
- data/yard-stubs/carray_median_percentile.rb +103 -0
- data/yard-stubs/carray_memory_view.rb +163 -0
- data/yard-stubs/carray_order.rb +252 -0
- data/yard-stubs/carray_random.rb +89 -0
- data/yard-stubs/carray_scatter.rb +106 -0
- data/yard-stubs/carray_slab.rb +59 -0
- data/yard-stubs/carray_sort.rb +165 -0
- data/yard-stubs/carray_test.rb +85 -0
- data/yard-stubs/carray_undef.rb +64 -0
- data/yard-stubs/carray_utils.rb +97 -0
- data/yard-stubs/ruby_carray.rb +193 -0
- metadata +67 -10
- data/ext/ca_obj_unbound_repeat.c +0 -496
data/ext/carray_conversion.c
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
Siblings:
|
|
8
8
|
carray_copy.c — CArray-to-CArray copy / template family
|
|
9
9
|
carray_element.c — element-level fetch/store (rb_ca_ptr2obj / obj2ptr)
|
|
10
|
-
carray_cast_func.c —
|
|
10
|
+
carray_cast_func.c — data type cast table used by rb_ca_ptr2obj
|
|
11
11
|
|
|
12
12
|
---------------------------------------------------------------------------- */
|
|
13
13
|
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
#include "ruby/io.h"
|
|
17
17
|
|
|
18
18
|
/* to_a dispatch:
|
|
19
|
-
numeric / boolean
|
|
20
|
-
(
|
|
19
|
+
numeric / boolean data type + entity or attach-able view -> fast path
|
|
20
|
+
(data type-direct leaf loop over the attached contig buffer)
|
|
21
21
|
CA_OBJECT / CA_FIXLEN -> universal
|
|
22
22
|
(rb_ca_fetch_index per cell; ptr is VALUE or byte string, not
|
|
23
23
|
directly castable through the leaf switch)
|
|
24
24
|
|
|
25
25
|
Masked cells materialise as CA_UNDEF on both paths. */
|
|
26
26
|
|
|
27
|
-
/* Leaf macro:
|
|
27
|
+
/* Leaf macro: data type-specialized inner loop. Produces `n` VALUE objects
|
|
28
28
|
from a contig ptr base + element width, storing into `dst` (Ruby Array). */
|
|
29
29
|
#define TO_A_LEAF_LOOP(T, TO_VALUE) do { \
|
|
30
30
|
const T *src = (const T *) base; \
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
|
|
43
43
|
#define TO_A_DISPATCH_LEAF(LOOP) do { \
|
|
44
44
|
ca_size_t li; \
|
|
45
|
-
switch (
|
|
45
|
+
switch ( data_type ) { \
|
|
46
46
|
case CA_FLOAT64: LOOP(double, rb_float_new); break; \
|
|
47
47
|
case CA_FLOAT32: LOOP(float, rb_float_new); break; \
|
|
48
48
|
case CA_INT64: LOOP(int64_t, LL2NUM); break; \
|
|
@@ -67,13 +67,13 @@
|
|
|
67
67
|
} \
|
|
68
68
|
break; \
|
|
69
69
|
default: \
|
|
70
|
-
rb_bug("to_a fast path: unexpected
|
|
70
|
+
rb_bug("to_a fast path: unexpected data type %d", data_type); \
|
|
71
71
|
} \
|
|
72
72
|
} while (0)
|
|
73
73
|
|
|
74
74
|
#define TO_A_DISPATCH_LEAF_MASKED(LOOP) do { \
|
|
75
75
|
ca_size_t li; \
|
|
76
|
-
switch (
|
|
76
|
+
switch ( data_type ) { \
|
|
77
77
|
case CA_FLOAT64: LOOP(double, rb_float_new); break; \
|
|
78
78
|
case CA_FLOAT32: LOOP(float, rb_float_new); break; \
|
|
79
79
|
case CA_INT64: LOOP(int64_t, LL2NUM); break; \
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
} \
|
|
96
96
|
break; \
|
|
97
97
|
default: \
|
|
98
|
-
rb_bug("to_a fast path masked: unexpected
|
|
98
|
+
rb_bug("to_a fast path masked: unexpected data type %d", data_type); \
|
|
99
99
|
} \
|
|
100
100
|
} while (0)
|
|
101
101
|
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
static void
|
|
106
106
|
to_a_fast_recurse (CArray *ca, int32_t level, const char *base,
|
|
107
107
|
const boolean8_t *mask_base, VALUE dst,
|
|
108
|
-
int
|
|
108
|
+
int data_type, ca_size_t bytes, int has_mask)
|
|
109
109
|
{
|
|
110
110
|
ca_size_t i, n, slab_elements, slab_bytes;
|
|
111
111
|
|
|
@@ -135,7 +135,7 @@ to_a_fast_recurse (CArray *ca, int32_t level, const char *base,
|
|
|
135
135
|
to_a_fast_recurse(ca, level + 1,
|
|
136
136
|
base + i * slab_bytes,
|
|
137
137
|
has_mask ? mask_base + i * slab_elements : NULL,
|
|
138
|
-
child,
|
|
138
|
+
child, data_type, bytes, has_mask);
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -172,8 +172,8 @@ rb_ca_to_a_loop_universal (VALUE self, int32_t level, ca_size_t *idx, VALUE ary)
|
|
|
172
172
|
* ndim-1 nesting: shape [2, 3] -> 2-element Array of 3-element Arrays.
|
|
173
173
|
* Masked cells become CA_UNDEF; the mask itself is not preserved on the
|
|
174
174
|
* result. ca_attach(self) supplies a contig row-major buffer for the
|
|
175
|
-
* fast path, so all view kinds land in the
|
|
176
|
-
* the
|
|
175
|
+
* fast path, so all view kinds land in the data type-direct leaf loop when
|
|
176
|
+
* the data type is numeric or boolean; CA_OBJECT / CA_FIXLEN fall through
|
|
177
177
|
* to the universal fetch_index walk. */
|
|
178
178
|
VALUE
|
|
179
179
|
rb_ca_to_a (VALUE self)
|
|
@@ -181,7 +181,7 @@ rb_ca_to_a (VALUE self)
|
|
|
181
181
|
volatile VALUE ary;
|
|
182
182
|
CArray *ca;
|
|
183
183
|
ca_size_t idx[CA_RANK_MAX];
|
|
184
|
-
int
|
|
184
|
+
int data_type, fast_eligible;
|
|
185
185
|
|
|
186
186
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
187
187
|
ary = rb_ca_is_empty(self) ? rb_ary_new() : rb_ary_new2(ca->dim[0]);
|
|
@@ -199,22 +199,22 @@ rb_ca_to_a (VALUE self)
|
|
|
199
199
|
numeric-storage Face -- CATimedelta serials instead of CATimedelta
|
|
200
200
|
Elements -- while ca[i] / each / to_type(:object) all decode. The
|
|
201
201
|
universal loop goes through rb_ca_fetch_addr, which decodes. */
|
|
202
|
-
|
|
202
|
+
data_type = ca->data_type;
|
|
203
203
|
fast_eligible = (ca->elements > 0)
|
|
204
204
|
&& ( ! ca_is_face(ca) )
|
|
205
|
-
&& (
|
|
206
|
-
||
|
|
207
|
-
||
|
|
208
|
-
||
|
|
209
|
-
||
|
|
210
|
-
||
|
|
205
|
+
&& (data_type == CA_FLOAT64 || data_type == CA_FLOAT32
|
|
206
|
+
|| data_type == CA_INT64 || data_type == CA_INT32
|
|
207
|
+
|| data_type == CA_INT16 || data_type == CA_INT8
|
|
208
|
+
|| data_type == CA_UINT64 || data_type == CA_UINT32
|
|
209
|
+
|| data_type == CA_UINT16 || data_type == CA_UINT8
|
|
210
|
+
|| data_type == CA_BOOLEAN);
|
|
211
211
|
|
|
212
212
|
if ( fast_eligible ) {
|
|
213
213
|
int has_mask = (ca->mask != NULL);
|
|
214
214
|
const boolean8_t *mask_base = has_mask
|
|
215
215
|
? (const boolean8_t *) ca->mask->ptr : NULL;
|
|
216
216
|
to_a_fast_recurse(ca, 0, ca->ptr, mask_base, ary,
|
|
217
|
-
|
|
217
|
+
data_type, ca->bytes, has_mask);
|
|
218
218
|
}
|
|
219
219
|
else if ( ca->elements > 0 ) {
|
|
220
220
|
rb_ca_to_a_loop_universal(self, 0, idx, ary);
|
|
@@ -229,7 +229,7 @@ rb_ca_to_a (VALUE self)
|
|
|
229
229
|
#undef TO_A_DISPATCH_LEAF_MASKED
|
|
230
230
|
|
|
231
231
|
/* CArray#convert(data_type=nil, bytes: nil) { |elem| ... } — map every cell
|
|
232
|
-
* through the block, into a new array whose
|
|
232
|
+
* through the block, into a new array whose data type is chosen by argv via
|
|
233
233
|
* CArray#template (shape is inherited from self).
|
|
234
234
|
*
|
|
235
235
|
* Masked cells skip the block; if the block returns CA_UNDEF, the
|
data/ext/carray_copy.c
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
#include "carray.h"
|
|
12
12
|
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE */
|
|
13
|
+
#include "carray_internal.h" /* ca_gc_hold_push / ca_gc_hold_pop_to */
|
|
14
|
+
#include "ca_sweep_engine.h" /* ca_sweep_same_shape / ca_sweep_refuse_shapes */
|
|
13
15
|
#include <stdarg.h>
|
|
14
16
|
|
|
15
17
|
/* ------------------------------------------------------------------- */
|
|
@@ -18,22 +20,27 @@
|
|
|
18
20
|
* and bytes as `ca`, copies the element payload, and reproduces the
|
|
19
21
|
* mask state. Always copies even when `ca` is an entity; for view
|
|
20
22
|
* sources the data path goes through `ca_copy_data`, otherwise a flat
|
|
21
|
-
* memcpy of `ca_length(ca)` bytes.
|
|
23
|
+
* memcpy of `ca_length(ca)` bytes. If reading the source raises, the
|
|
24
|
+
* copy is freed before the raise propagates.
|
|
22
25
|
*
|
|
23
26
|
* Backs `CArray#copy` and is also reachable as a C-level utility from
|
|
24
27
|
* other ext files that need an owned snapshot. */
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
void
|
|
29
|
+
ca_fill_or_free (CArray *co, VALUE (*fill)(VALUE), VALUE arg)
|
|
27
30
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
co = carray_new(ca->data_type, ca->ndim, ca->dim, ca->bytes, 0);
|
|
31
|
+
int tag = 0;
|
|
32
|
+
rb_protect(fill, arg, &tag);
|
|
33
|
+
if ( tag ) {
|
|
34
|
+
ca_free(co);
|
|
35
|
+
rb_jump_tag(tag);
|
|
36
36
|
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static VALUE
|
|
40
|
+
ca_copy_fill (VALUE arg)
|
|
41
|
+
{
|
|
42
|
+
CArray **pair = (CArray **) arg;
|
|
43
|
+
CArray *ca = pair[0], *co = pair[1];
|
|
37
44
|
|
|
38
45
|
if ( ca_is_attached(ca) ) {
|
|
39
46
|
memcpy(co->ptr, ca->ptr, ca_length(ca));
|
|
@@ -46,6 +53,26 @@ ca_copy (void *ap)
|
|
|
46
53
|
if ( ca->mask ) {
|
|
47
54
|
ca_copy_mask(co, ca);
|
|
48
55
|
}
|
|
56
|
+
return Qnil;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
CArray *
|
|
60
|
+
ca_copy (void *ap)
|
|
61
|
+
{
|
|
62
|
+
CArray *ca = (CArray *) ap;
|
|
63
|
+
CArray *co;
|
|
64
|
+
CArray *pair[2];
|
|
65
|
+
|
|
66
|
+
if ( ca_is_scalar(ca) ) {
|
|
67
|
+
co = (CArray *) cscalar_new(ca->data_type, ca->bytes, 0);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
co = carray_new(ca->data_type, ca->ndim, ca->dim, ca->bytes, 0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
pair[0] = ca;
|
|
74
|
+
pair[1] = co;
|
|
75
|
+
ca_fill_or_free(co, ca_copy_fill, (VALUE) pair);
|
|
49
76
|
|
|
50
77
|
return co;
|
|
51
78
|
}
|
|
@@ -57,9 +84,18 @@ VALUE
|
|
|
57
84
|
rb_ca_copy (VALUE self)
|
|
58
85
|
{
|
|
59
86
|
volatile VALUE obj;
|
|
60
|
-
CArray *ca;
|
|
87
|
+
CArray *ca, *co;
|
|
88
|
+
int guard = -1;
|
|
61
89
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
62
|
-
|
|
90
|
+
co = ca_copy(ca);
|
|
91
|
+
/* The copy holds VALUEs that so far exist only in co->ptr, and
|
|
92
|
+
ca_wrap_struct allocates. Keep them reachable until the wrapper
|
|
93
|
+
that owns them exists. */
|
|
94
|
+
if ( ca_is_object_type(co) ) {
|
|
95
|
+
guard = ca_gc_hold_push(co->ptr, co->elements);
|
|
96
|
+
}
|
|
97
|
+
obj = ca_wrap_struct(co);
|
|
98
|
+
ca_gc_hold_pop_to(guard);
|
|
63
99
|
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
64
100
|
return obj;
|
|
65
101
|
}
|
|
@@ -262,16 +298,16 @@ rb_ca_template_with_type (VALUE self, VALUE rtype, VALUE rbytes)
|
|
|
262
298
|
return rb_ca_template_method(2, args, self);
|
|
263
299
|
}
|
|
264
300
|
|
|
265
|
-
/*
|
|
266
|
-
*
|
|
267
|
-
* size the output of vectorised scalar
|
|
268
|
-
*
|
|
301
|
+
/* Returns `template` of the first non-scalar among `n` variadic CArray
|
|
302
|
+
* arguments (of the first argument when all are scalars). Used by
|
|
303
|
+
* `carray_call_cfunc.c` to size the output of vectorised scalar
|
|
304
|
+
* C-function calls: a scalar pairs with any array, two arrays only when
|
|
305
|
+
* their shapes agree. */
|
|
269
306
|
VALUE
|
|
270
307
|
rb_ca_template_n (int n, ...)
|
|
271
308
|
{
|
|
272
|
-
volatile VALUE varg, obj;
|
|
273
|
-
CArray *ca;
|
|
274
|
-
ca_size_t elements = -1;
|
|
309
|
+
volatile VALUE varg, obj = Qnil;
|
|
310
|
+
CArray *ca, *donor = NULL;
|
|
275
311
|
va_list vargs;
|
|
276
312
|
int i;
|
|
277
313
|
|
|
@@ -279,24 +315,23 @@ rb_ca_template_n (int n, ...)
|
|
|
279
315
|
for (i=0; i<n; i++) {
|
|
280
316
|
varg = va_arg(vargs, VALUE);
|
|
281
317
|
if ( ! rb_obj_is_carray(varg) ) {
|
|
318
|
+
va_end(vargs);
|
|
282
319
|
rb_raise(rb_eRuntimeError, "[BUG] not-carray object given to rb_ca_template_n");
|
|
283
320
|
}
|
|
284
321
|
TypedData_Get_Struct(varg, CArray, &carray_data_type, ca);
|
|
285
322
|
if ( i == 0 ) {
|
|
286
323
|
obj = varg;
|
|
287
|
-
elements = ca->elements;
|
|
288
324
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
325
|
+
if ( ca_is_scalar(ca) ) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if ( ! donor ) {
|
|
329
|
+
donor = ca;
|
|
330
|
+
obj = varg;
|
|
331
|
+
}
|
|
332
|
+
else if ( ! ca_sweep_same_shape(donor, ca) ) {
|
|
333
|
+
va_end(vargs);
|
|
334
|
+
ca_sweep_refuse_shapes(donor, ca);
|
|
300
335
|
}
|
|
301
336
|
}
|
|
302
337
|
va_end(vargs);
|
data/ext/carray_core.c
CHANGED
|
@@ -231,7 +231,6 @@ ca_cast_table2[CA_NTYPE][CA_NTYPE] = {
|
|
|
231
231
|
* CASelect
|
|
232
232
|
* CAObject
|
|
233
233
|
* CARepeat
|
|
234
|
-
* CAUnboundRepeat
|
|
235
234
|
*/
|
|
236
235
|
|
|
237
236
|
void
|
|
@@ -243,7 +242,6 @@ ca_init_obj_type (void)
|
|
|
243
242
|
extern ca_operation_function_t ca_select_func;
|
|
244
243
|
extern ca_operation_function_t ca_object_func;
|
|
245
244
|
extern ca_operation_function_t ca_stride_func;
|
|
246
|
-
extern ca_operation_function_t ca_ubrep_func;
|
|
247
245
|
|
|
248
246
|
/* CArray */
|
|
249
247
|
ca_func[CA_OBJ_ARRAY] = ca_array_func;
|
|
@@ -309,12 +307,6 @@ ca_init_obj_type (void)
|
|
|
309
307
|
ca_mask_class[CA_OBJ_REPEAT] = rb_cCARepeatMask;
|
|
310
308
|
ca_mask_typeddata[CA_OBJ_REPEAT] = &castride_mask_data_type;
|
|
311
309
|
|
|
312
|
-
/* CAUnboundRepeat */
|
|
313
|
-
ca_func[CA_OBJ_UNBOUND_REPEAT] = ca_ubrep_func;
|
|
314
|
-
ca_class[CA_OBJ_UNBOUND_REPEAT] = rb_cCAUnboundRepeat;
|
|
315
|
-
ca_typeddata[CA_OBJ_UNBOUND_REPEAT] = &caunboundrepeat_data_type;
|
|
316
|
-
ca_mask_class[CA_OBJ_UNBOUND_REPEAT] = rb_cCAUnboundRepeatMask;
|
|
317
|
-
ca_mask_typeddata[CA_OBJ_UNBOUND_REPEAT] = &caunboundrepeat_mask_data_type;
|
|
318
310
|
|
|
319
311
|
ca_obj_num = 9;
|
|
320
312
|
}
|
|
@@ -432,11 +424,22 @@ ca_attach_is_alias (void *ap)
|
|
|
432
424
|
{
|
|
433
425
|
CArray *ca = (CArray *) ap;
|
|
434
426
|
extern ca_operation_function_t ca_stride_func;
|
|
427
|
+
extern ca_operation_function_t ca_lazy_marker_func;
|
|
435
428
|
extern int ca_stride_is_contiguous (CAStride *ca);
|
|
436
429
|
extern int ca_stride_attach_aliases_root (CAStride *ca);
|
|
437
430
|
|
|
438
431
|
if ( ca == NULL ) return 0;
|
|
439
432
|
if ( ca_is_entity(ca) ) return 1;
|
|
433
|
+
|
|
434
|
+
/* CALazyMarker's attach is literally `ca->ptr = ca->parent->ptr` after
|
|
435
|
+
attaching the parent — it adds no layout of its own — so it aliases
|
|
436
|
+
exactly when its parent does. Without this a marker looks expensive
|
|
437
|
+
to every caller and views built on it fall onto materialising paths,
|
|
438
|
+
even though there is nothing between the marker and real memory. */
|
|
439
|
+
if ( ca_func[ca->obj_type].attach == ca_lazy_marker_func.attach ) {
|
|
440
|
+
return ca_attach_is_alias(((CAView *) ca)->parent);
|
|
441
|
+
}
|
|
442
|
+
|
|
440
443
|
/* CAStride family share ca_stride_func.attach (= ca_stride_func_attach).
|
|
441
444
|
The alias-attach fast path is taken iff composed strides are
|
|
442
445
|
row-major contiguous. ca_stride_is_contiguous checks the leaf
|
|
@@ -1399,6 +1402,30 @@ ca_xfer_strided_walk (char *src_base,
|
|
|
1399
1402
|
}
|
|
1400
1403
|
}
|
|
1401
1404
|
|
|
1405
|
+
/* See the comment on the prototype in carray.h. */
|
|
1406
|
+
int
|
|
1407
|
+
ca_xfer_stride_request_is_axis_box (void *ap, ca_size_t *starts,
|
|
1408
|
+
ca_size_t *counts, ca_size_t *strides)
|
|
1409
|
+
{
|
|
1410
|
+
CArray *ca = (CArray *) ap;
|
|
1411
|
+
ca_size_t native[CA_RANK_MAX];
|
|
1412
|
+
ca_size_t s = ca->bytes;
|
|
1413
|
+
int8_t ndim = ca->ndim, k;
|
|
1414
|
+
|
|
1415
|
+
for ( k = ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
1416
|
+
|
|
1417
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
1418
|
+
ca_size_t q;
|
|
1419
|
+
if ( counts[k] <= 1 ) continue; /* moves nothing */
|
|
1420
|
+
if ( strides[k] <= 0 ) return 0; /* zero / negative: not an axis walk */
|
|
1421
|
+
if ( strides[k] % native[k] != 0 ) return 0;
|
|
1422
|
+
q = strides[k] / native[k];
|
|
1423
|
+
if ( q < 1 ) return 0;
|
|
1424
|
+
if ( starts[k] + (counts[k] - 1) * q >= ca->dim[k] ) return 0; /* runs off axis k */
|
|
1425
|
+
}
|
|
1426
|
+
return 1;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1402
1429
|
static void
|
|
1403
1430
|
ca_xfer_stride_dispatch (CArray *ca, ca_size_t *starts, ca_size_t *counts,
|
|
1404
1431
|
ca_size_t *strides, void *data, int dir)
|
|
@@ -1532,10 +1559,12 @@ ca_xfer_all_body (VALUE arg)
|
|
|
1532
1559
|
return Qnil;
|
|
1533
1560
|
}
|
|
1534
1561
|
|
|
1562
|
+
/* `arg` carries the hold depth to unwind to, so nested ca_xfer_all calls
|
|
1563
|
+
each drop their own hold rather than the whole stack. */
|
|
1535
1564
|
static VALUE
|
|
1536
1565
|
ca_xfer_all_ensure (VALUE arg)
|
|
1537
1566
|
{
|
|
1538
|
-
(
|
|
1567
|
+
ca_gc_hold_pop_to(NUM2INT(arg));
|
|
1539
1568
|
ca_lazy_arena_exit();
|
|
1540
1569
|
return Qnil;
|
|
1541
1570
|
}
|
|
@@ -1545,6 +1574,7 @@ ca_xfer_all (void *ap, void *data, int dir)
|
|
|
1545
1574
|
{
|
|
1546
1575
|
CArray *ca = (CArray *) ap;
|
|
1547
1576
|
ca_xfer_all_args_t args;
|
|
1577
|
+
int guard = -1;
|
|
1548
1578
|
if ( ! ca_func[ca->obj_type].xfer_all ) {
|
|
1549
1579
|
rb_raise(rb_eRuntimeError,
|
|
1550
1580
|
"[BUG] xfer_all not defined for object type <%i>",
|
|
@@ -1562,8 +1592,25 @@ ca_xfer_all (void *ap, void *data, int dir)
|
|
|
1562
1592
|
next entry. */
|
|
1563
1593
|
ca_lazy_arena_enter();
|
|
1564
1594
|
args.ca = ca; args.data = data; args.dir = dir;
|
|
1595
|
+
|
|
1596
|
+
/* A CA_OBJECT cell is a VALUE, and this buffer belongs to no Ruby
|
|
1597
|
+
object yet -- it is the destination `copy` will hand out, or a
|
|
1598
|
+
view's own freshly allocated one. The object lane calls rb_funcall
|
|
1599
|
+
per cell, so a collection partway through would free what has been
|
|
1600
|
+
written so far. ca_xfer_all is the whole-view entry, so the window
|
|
1601
|
+
is exactly ca->elements contiguous cells: the one place where the
|
|
1602
|
+
extent is known without trusting a caller's strides. Sub-windows
|
|
1603
|
+
written by nested transfers land inside it. */
|
|
1604
|
+
if ( ca->data_type == CA_OBJECT && dir == CA_XFER_GET ) {
|
|
1605
|
+
if ( data != (void *) ca->ptr ) {
|
|
1606
|
+
VALUE *p = (VALUE *) data;
|
|
1607
|
+
ca_size_t i;
|
|
1608
|
+
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
1609
|
+
}
|
|
1610
|
+
guard = ca_gc_hold_push(data, ca->elements);
|
|
1611
|
+
}
|
|
1565
1612
|
rb_ensure(ca_xfer_all_body, (VALUE) &args,
|
|
1566
|
-
ca_xfer_all_ensure,
|
|
1613
|
+
ca_xfer_all_ensure, INT2NUM(guard));
|
|
1567
1614
|
}
|
|
1568
1615
|
|
|
1569
1616
|
/* ------------------------------------------------------------------- */
|
|
@@ -1608,6 +1655,18 @@ ca_allocate (void *ap)
|
|
|
1608
1655
|
ca_allocate(ca->mask);
|
|
1609
1656
|
}
|
|
1610
1657
|
|
|
1658
|
+
/* The first attach of a view: materialise through the type's slot, then
|
|
1659
|
+
its mask. Run under rb_protect by ca_attach. */
|
|
1660
|
+
static VALUE
|
|
1661
|
+
ca_attach_view_first (VALUE arg)
|
|
1662
|
+
{
|
|
1663
|
+
CArray *ca = (CArray *) arg;
|
|
1664
|
+
ca_func[ca->obj_type].attach(ca);
|
|
1665
|
+
ca_update_mask(ca);
|
|
1666
|
+
ca_attach(ca->mask);
|
|
1667
|
+
return Qnil;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1611
1670
|
/* attach parent's data to ca->ptr */
|
|
1612
1671
|
|
|
1613
1672
|
void
|
|
@@ -1621,14 +1680,30 @@ ca_attach (void *ap)
|
|
|
1621
1680
|
|
|
1622
1681
|
if ( ca_is_view(ca) ) { /* view array */
|
|
1623
1682
|
|
|
1624
|
-
CAVIEW(ca)->attach
|
|
1625
|
-
if ( CAVIEW(ca)->attach > CA_ATTACH_MAX ) {
|
|
1683
|
+
if ( CAVIEW(ca)->attach >= CA_ATTACH_MAX ) {
|
|
1626
1684
|
rb_raise(rb_eRuntimeError,
|
|
1627
1685
|
"too large attach count of view array");
|
|
1628
1686
|
}
|
|
1687
|
+
CAVIEW(ca)->attach += 1; /* increments attach level */
|
|
1629
1688
|
|
|
1630
1689
|
if ( ! ca->ptr ) {
|
|
1631
|
-
|
|
1690
|
+
/* A slot can raise part way (a conversion meeting a value it cannot
|
|
1691
|
+
hold). Undo the attach then, or the next attach finds ca->ptr
|
|
1692
|
+
set, skips the slot and reads a half-filled buffer. A slot that
|
|
1693
|
+
got as far as publishing ca->ptr has also attached what its
|
|
1694
|
+
detach slot releases; one that raised earlier has published
|
|
1695
|
+
nothing and released its own parent attach on the way out. */
|
|
1696
|
+
int tag = 0;
|
|
1697
|
+
rb_protect(ca_attach_view_first, (VALUE) ca, &tag);
|
|
1698
|
+
if ( tag ) {
|
|
1699
|
+
if ( ca->ptr ) {
|
|
1700
|
+
ca_func[ca->obj_type].detach(ca);
|
|
1701
|
+
ca->ptr = NULL;
|
|
1702
|
+
}
|
|
1703
|
+
CAVIEW(ca)->attach -= 1;
|
|
1704
|
+
rb_jump_tag(tag);
|
|
1705
|
+
}
|
|
1706
|
+
return;
|
|
1632
1707
|
}
|
|
1633
1708
|
}
|
|
1634
1709
|
else { /* entity array */
|
|
@@ -1639,6 +1714,43 @@ ca_attach (void *ap)
|
|
|
1639
1714
|
ca_attach(ca->mask);
|
|
1640
1715
|
}
|
|
1641
1716
|
|
|
1717
|
+
/* Attach every array in list[0..n-1], or, if one of those attaches
|
|
1718
|
+
raises, none of them: the ones already attached are detached before the
|
|
1719
|
+
raise propagates. For views over several parents. */
|
|
1720
|
+
|
|
1721
|
+
typedef struct {
|
|
1722
|
+
CArray **list;
|
|
1723
|
+
int32_t n;
|
|
1724
|
+
int32_t done;
|
|
1725
|
+
} ca_attach_all_ctx_t;
|
|
1726
|
+
|
|
1727
|
+
static VALUE
|
|
1728
|
+
ca_attach_all_body (VALUE arg)
|
|
1729
|
+
{
|
|
1730
|
+
ca_attach_all_ctx_t *c = (ca_attach_all_ctx_t *) arg;
|
|
1731
|
+
for ( ; c->done < c->n; c->done++ ) {
|
|
1732
|
+
ca_attach(c->list[c->done]);
|
|
1733
|
+
}
|
|
1734
|
+
return Qnil;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
void
|
|
1738
|
+
ca_attach_all (CArray **list, int32_t n)
|
|
1739
|
+
{
|
|
1740
|
+
ca_attach_all_ctx_t c;
|
|
1741
|
+
int tag = 0;
|
|
1742
|
+
c.list = list;
|
|
1743
|
+
c.n = n;
|
|
1744
|
+
c.done = 0;
|
|
1745
|
+
rb_protect(ca_attach_all_body, (VALUE) &c, &tag);
|
|
1746
|
+
if ( tag ) {
|
|
1747
|
+
while ( c.done > 0 ) {
|
|
1748
|
+
ca_detach(list[--c.done]);
|
|
1749
|
+
}
|
|
1750
|
+
rb_jump_tag(tag);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1642
1754
|
/* attach parent's data to ca->ptr */
|
|
1643
1755
|
|
|
1644
1756
|
void
|
|
@@ -2040,6 +2152,17 @@ ca_fill (void *ap, void *aptr)
|
|
|
2040
2152
|
|
|
2041
2153
|
/* ------------------------------------------------------------------- */
|
|
2042
2154
|
|
|
2155
|
+
#ifdef CARRAY_DEV_BUILD
|
|
2156
|
+
|
|
2157
|
+
/* The Ruby attach surface is built into development builds only. Ruby has no
|
|
2158
|
+
raw pointer, so the only thing a block can do inside an attach window is call
|
|
2159
|
+
back into the array API -- and which door that takes is invisible in the
|
|
2160
|
+
syntax: v[0] reads the attached buffer while v[] and v[0..1] compose past it
|
|
2161
|
+
to the root (R5, see the contract beside ca_attach in carray.h). Per-cell and
|
|
2162
|
+
whole-array writes reach the buffer and survive the sync; a write through a
|
|
2163
|
+
derived view is discarded. The in-tree tests drive the healthy spellings, so
|
|
2164
|
+
the surface stays reachable here and out of released builds. */
|
|
2165
|
+
|
|
2043
2166
|
/* subroutines for CArray.attach, CArray.attach!
|
|
2044
2167
|
CArray#attach, CArray#attach! */
|
|
2045
2168
|
|
|
@@ -2260,6 +2383,8 @@ rb_ca__detach__ (VALUE self)
|
|
|
2260
2383
|
return self;
|
|
2261
2384
|
}
|
|
2262
2385
|
|
|
2386
|
+
#endif /* CARRAY_DEV_BUILD */
|
|
2387
|
+
|
|
2263
2388
|
/* ------------------------------------------------------------------- */
|
|
2264
2389
|
|
|
2265
2390
|
static ID id_decode, id_encode;
|
|
@@ -2468,6 +2593,7 @@ Init_carray_core (void)
|
|
|
2468
2593
|
|
|
2469
2594
|
ca_init_obj_type();
|
|
2470
2595
|
|
|
2596
|
+
#ifdef CARRAY_DEV_BUILD
|
|
2471
2597
|
rb_define_singleton_method(rb_cCArray, "attach", rb_ca_s_attach, -1);
|
|
2472
2598
|
rb_define_singleton_method(rb_cCArray, "attach!", rb_ca_s_attach_bang, -1);
|
|
2473
2599
|
|
|
@@ -2477,6 +2603,7 @@ Init_carray_core (void)
|
|
|
2477
2603
|
rb_define_method(rb_cCArray, "__attach__", rb_ca__attach__, 0);
|
|
2478
2604
|
rb_define_method(rb_cCArray, "__sync__", rb_ca__sync__, 0);
|
|
2479
2605
|
rb_define_method(rb_cCArray, "__detach__", rb_ca__detach__, 0);
|
|
2606
|
+
#endif
|
|
2480
2607
|
|
|
2481
2608
|
rb_define_method(rb_cCArray, "members", rb_ca_members, 0);
|
|
2482
2609
|
|
data/ext/carray_count.c
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
CArray#count dispatcher (= value-comparison family entry point).
|
|
4
4
|
Hand-routed because the dispatch decision depends on (self.data_type,
|
|
5
|
-
v's runtime class), which the per-
|
|
5
|
+
v's runtime class), which the per-type mkkernel kernels can't see;
|
|
6
6
|
the actual counting is delegated to the kernel-iterator helpers
|
|
7
7
|
listed below.
|
|
8
8
|
|
|
@@ -39,11 +39,12 @@ VALUE rb_ca_count_not_masked (int argc, VALUE *argv, VALUE self);
|
|
|
39
39
|
- v is a CArray -> broadcast: count each v[k] and stack
|
|
40
40
|
(rejected for boolean self; see below)
|
|
41
41
|
- self is boolean, v scalar -> v must be true/false literal
|
|
42
|
-
- self is numeric, v scalar -> count_equal_ki (numeric
|
|
42
|
+
- self is numeric or object, v scalar -> count_equal_ki (numeric ==
|
|
43
|
+
for a number, Ruby == for an object)
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
- self is fixlen, v scalar -> count_equal_ki (memcmp over the whole
|
|
46
|
+
cell; a short String query is padded
|
|
47
|
+
out to the cell width) */
|
|
47
48
|
|
|
48
49
|
static VALUE
|
|
49
50
|
rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
@@ -95,11 +96,7 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
95
96
|
}
|
|
96
97
|
if ( ca_test_flag(src, CA_FLAG_FACE_COMPARABLE_STORAGE) ) {
|
|
97
98
|
if ( ! query_was_scalar ) {
|
|
98
|
-
|
|
99
|
-
GetCArray(rval, cv);
|
|
100
|
-
if ( ca_is_face(cv) ) {
|
|
101
|
-
rval = rb_ca_strip_face_value(rval);
|
|
102
|
-
}
|
|
99
|
+
rval = ca_face_operand_descend(rval, "count(v)");
|
|
103
100
|
}
|
|
104
101
|
}
|
|
105
102
|
else if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -290,7 +287,9 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
290
287
|
rb_obj_classname(rval));
|
|
291
288
|
}
|
|
292
289
|
} else {
|
|
293
|
-
|
|
290
|
+
/* true / false are the boolean array's own domain, not a number --
|
|
291
|
+
except in an object array, where they are ordinary stored values. */
|
|
292
|
+
if ( ( rval == Qtrue || rval == Qfalse ) && src->data_type != CA_OBJECT ) {
|
|
294
293
|
rb_raise(rb_eTypeError,
|
|
295
294
|
"count(v) on numeric array: v must be numeric, got %s",
|
|
296
295
|
rb_obj_classname(rval));
|
data/ext/carray_element.c
CHANGED
|
@@ -254,10 +254,10 @@ rb_ca_elem_store (VALUE self, VALUE ridx, VALUE obj)
|
|
|
254
254
|
from_array = 0;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
/* Super-hot path: entity + no mask + common numeric
|
|
257
|
+
/* Super-hot path: entity + no mask + common numeric data type + Numeric obj.
|
|
258
258
|
Bypasses rb_ca_store_index/addr -> ca_update_mask + rb_ca_obj2ptr ->
|
|
259
259
|
cast_table dispatch. Falls through to general path for: views,
|
|
260
|
-
existing mask, non-numeric
|
|
260
|
+
existing mask, non-numeric data type, UNDEF, or non-Numeric obj. */
|
|
261
261
|
if ( ca_is_entity(ca) && ! ca->mask && obj != CA_UNDEF ) {
|
|
262
262
|
int8_t dt = ca->data_type;
|
|
263
263
|
if ( dt == CA_FLOAT64 || dt == CA_FLOAT32 ||
|
|
@@ -269,7 +269,7 @@ rb_ca_elem_store (VALUE self, VALUE ridx, VALUE obj)
|
|
|
269
269
|
/* Compute flat addr if T_ARRAY index path. */
|
|
270
270
|
if ( from_array ) addr = elem_entity_addr(ca, idx);
|
|
271
271
|
char *p = ca->ptr + ca->bytes * addr;
|
|
272
|
-
/* Convert obj to
|
|
272
|
+
/* Convert obj to data type + store. Restrict to Fixnum / Float / true
|
|
273
273
|
/ false to avoid Bignum / Rational / Complex coercion that the
|
|
274
274
|
cast_table handles in the general path. */
|
|
275
275
|
switch ( dt ) {
|
|
@@ -311,7 +311,7 @@ rb_ca_elem_store (VALUE self, VALUE ridx, VALUE obj)
|
|
|
311
311
|
if ( FIXNUM_P(obj) ) { *(uint8_t *)p = (FIX2LONG(obj) != 0); return obj; }
|
|
312
312
|
break;
|
|
313
313
|
}
|
|
314
|
-
/* Fall through:
|
|
314
|
+
/* Fall through: data type matches but obj kind needs general coercion. */
|
|
315
315
|
}
|
|
316
316
|
}
|
|
317
317
|
|
|
@@ -344,7 +344,7 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
344
344
|
volatile VALUE out;
|
|
345
345
|
elem_parse_idx_array(ca, ridx, idx);
|
|
346
346
|
|
|
347
|
-
/* Super-hot path: entity + common numeric
|
|
347
|
+
/* Super-hot path: entity + common numeric data type + no mask.
|
|
348
348
|
Bypass ca_fetch_index dispatch AND rb_ca_ptr2obj cast-table dispatch.
|
|
349
349
|
Covers the bench's float64 / int64 / int32 cases. */
|
|
350
350
|
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
@@ -454,7 +454,7 @@ rb_ca_elem_incr (VALUE self, VALUE ridx1)
|
|
|
454
454
|
|
|
455
455
|
has_mask = elem_probe_mask(ca);
|
|
456
456
|
|
|
457
|
-
/* Super-hot path: entity + no mask + integer
|
|
457
|
+
/* Super-hot path: entity + no mask + integer data type.
|
|
458
458
|
Reads p directly, modifies in place — no separate fetch/store dispatch. */
|
|
459
459
|
if ( ca_is_entity(ca) && ! has_mask ) {
|
|
460
460
|
ca_size_t addr;
|
|
@@ -818,7 +818,7 @@ rb_ca_elem_min (VALUE self, VALUE ridx, VALUE rval)
|
|
|
818
818
|
"elem_min requires a numeric array");
|
|
819
819
|
}
|
|
820
820
|
|
|
821
|
-
/* Super-hot path: entity + numeric
|
|
821
|
+
/* Super-hot path: entity + numeric data type + Fixnum/Float rval. */
|
|
822
822
|
ELEM_MINMAX_BODY(<);
|
|
823
823
|
|
|
824
824
|
/* General path: view / Bignum-Rational-Complex rval / fall-through.
|