carray 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/carray_count.c
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
#include "ruby.h"
|
|
14
14
|
#include "carray.h"
|
|
15
|
+
#include "carray_internal.h" /* ca_attach_window */
|
|
15
16
|
#include "ca_obj_face.h"
|
|
16
17
|
#include <math.h>
|
|
17
18
|
#include <float.h>
|
|
@@ -39,11 +40,89 @@ VALUE rb_ca_count_not_masked (int argc, VALUE *argv, VALUE self);
|
|
|
39
40
|
- v is a CArray -> broadcast: count each v[k] and stack
|
|
40
41
|
(rejected for boolean self; see below)
|
|
41
42
|
- self is boolean, v scalar -> v must be true/false literal
|
|
42
|
-
- self is numeric, v scalar -> count_equal_ki (numeric
|
|
43
|
+
- self is numeric or object, v scalar -> count_equal_ki (numeric ==
|
|
44
|
+
for a number, Ruby == for an object)
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
- self is fixlen, v scalar -> count_equal_ki (memcmp over the whole
|
|
47
|
+
cell; a short String query is padded
|
|
48
|
+
out to the cell width) */
|
|
49
|
+
|
|
50
|
+
static VALUE rb_ca_count (int argc, VALUE *argv, VALUE self);
|
|
51
|
+
|
|
52
|
+
/* count(v: CArray): the per-cell counts, run with v attached. */
|
|
53
|
+
|
|
54
|
+
typedef struct {
|
|
55
|
+
VALUE self;
|
|
56
|
+
VALUE rval;
|
|
57
|
+
CArray *cv;
|
|
58
|
+
CArray *cout;
|
|
59
|
+
ca_size_t base_elements;
|
|
60
|
+
int inner_argc;
|
|
61
|
+
VALUE *inner_axes;
|
|
62
|
+
volatile VALUE opt_hash;
|
|
63
|
+
} ca_count_each_ctx_t;
|
|
64
|
+
|
|
65
|
+
static VALUE
|
|
66
|
+
ca_count_each_body (VALUE arg)
|
|
67
|
+
{
|
|
68
|
+
ca_count_each_ctx_t *c = (ca_count_each_ctx_t *) arg;
|
|
69
|
+
CArray *cout = c->cout;
|
|
70
|
+
int64_t *out_ptr = (int64_t *) cout->ptr;
|
|
71
|
+
boolean8_t *out_mask = NULL;
|
|
72
|
+
ca_size_t v_elements = c->cv->elements;
|
|
73
|
+
ca_size_t base_elements = c->base_elements;
|
|
74
|
+
/* inner_argv layout: [vk_scalar, axis..., axis..., [opt_hash]]
|
|
75
|
+
inner_call_argc = 1 (vk) + inner_argc (axes) + (opt_hash ? 1 : 0). */
|
|
76
|
+
int inner_call_argc = 1 + c->inner_argc + (NIL_P(c->opt_hash) ? 0 : 1);
|
|
77
|
+
VALUE inner_argv[CA_RANK_MAX + 2];
|
|
78
|
+
for (int j = 0; j < c->inner_argc; j++) inner_argv[1 + j] = c->inner_axes[j];
|
|
79
|
+
if ( ! NIL_P(c->opt_hash) ) inner_argv[1 + c->inner_argc] = c->opt_hash;
|
|
80
|
+
|
|
81
|
+
for (ca_size_t k = 0; k < v_elements; k++) {
|
|
82
|
+
/* Extract vk as a scalar VALUE via flat addr. rb_ca_fetch_addr
|
|
83
|
+
takes a ca_size_t addr (not a Ruby VALUE). */
|
|
84
|
+
VALUE vk = rb_ca_fetch_addr(c->rval, k);
|
|
85
|
+
inner_argv[0] = vk;
|
|
86
|
+
VALUE sub = rb_ca_count(inner_call_argc, inner_argv, c->self);
|
|
87
|
+
|
|
88
|
+
/* Place sub into output[..., k] slot.
|
|
89
|
+
Output stride for v-axis = 1, base stride = v_elements. */
|
|
90
|
+
if ( sub == CA_UNDEF ) {
|
|
91
|
+
if ( ! out_mask ) {
|
|
92
|
+
ca_create_mask(cout);
|
|
93
|
+
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
94
|
+
}
|
|
95
|
+
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
96
|
+
out_ptr[i * v_elements + k] = 0;
|
|
97
|
+
out_mask[i * v_elements + k] = 1;
|
|
98
|
+
}
|
|
99
|
+
} else if ( rb_obj_is_kind_of(sub, rb_cInteger) ) {
|
|
100
|
+
/* Full reduction: sub is a single integer. */
|
|
101
|
+
out_ptr[k] = NUM2LL(sub);
|
|
102
|
+
} else if ( rb_obj_is_kind_of(sub, rb_cCArray) ) {
|
|
103
|
+
CArray *csub;
|
|
104
|
+
GetCArray(sub, csub);
|
|
105
|
+
ca_attach(csub); /* window: the inner count answered an entity; nothing raises inside */
|
|
106
|
+
int64_t *sub_ptr = (int64_t *) csub->ptr;
|
|
107
|
+
boolean8_t *sub_mask = (csub->mask) ? (boolean8_t *) csub->mask->ptr : NULL;
|
|
108
|
+
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
109
|
+
out_ptr[i * v_elements + k] = sub_ptr[i];
|
|
110
|
+
if ( sub_mask && sub_mask[i] ) {
|
|
111
|
+
if ( ! out_mask ) {
|
|
112
|
+
ca_create_mask(cout);
|
|
113
|
+
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
114
|
+
}
|
|
115
|
+
out_mask[i * v_elements + k] = 1;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
ca_detach(csub);
|
|
119
|
+
} else {
|
|
120
|
+
rb_raise(rb_eRuntimeError,
|
|
121
|
+
"count(v: CArray): unexpected sub-result type");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return Qnil;
|
|
125
|
+
}
|
|
47
126
|
|
|
48
127
|
static VALUE
|
|
49
128
|
rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
@@ -56,10 +135,11 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
56
135
|
ladder. kwargs reach a -1 C method as a trailing options hash, so a
|
|
57
136
|
bare `count(axis: k)` arrives as argc==1 with argv[0] a Hash; discount
|
|
58
137
|
that trailing hash (same convention as the CArray-broadcast branch
|
|
59
|
-
below) before deciding there is no positional value.
|
|
60
|
-
|
|
138
|
+
below) before deciding there is no positional value. A Hash passed
|
|
139
|
+
positionally is the value to count. argv is forwarded verbatim so the
|
|
140
|
+
axis: kwarg passes through. */
|
|
61
141
|
{
|
|
62
|
-
int has_opts = ( argc >= 1 &&
|
|
142
|
+
int has_opts = ( argc >= 1 && rb_keyword_given_p() &&
|
|
63
143
|
rb_obj_is_kind_of(argv[argc - 1], rb_cHash) );
|
|
64
144
|
if ( argc - (has_opts ? 1 : 0) < 1 ) {
|
|
65
145
|
return rb_ca_count_not_masked(argc, argv, self);
|
|
@@ -77,48 +157,30 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
77
157
|
/* Face gate, mirroring the search / linear family (ext/carray_order.c):
|
|
78
158
|
descend an ORDERABLE Face to its storage so the equality runs on the
|
|
79
159
|
numeric storage, and let the reference reconcile the query into its own
|
|
80
|
-
space
|
|
81
|
-
plain one as-is), a unit-bearing one calls its own to_comparable for any
|
|
82
|
-
query type (Face CArray, Element, Time, DateTime). A Face that counts
|
|
160
|
+
space (ca_face_reconcile_operand). A Face that counts
|
|
83
161
|
by other means never arrives here: CACategorical / CAConstString define
|
|
84
162
|
their own #count in Ruby. Placed after the mask-state branches above,
|
|
85
163
|
which read the mask the Face already shares with its storage, and before
|
|
86
164
|
the broadcast branch, so a reconciled query array recurses as storage. */
|
|
87
165
|
if ( ca_is_face(src) ) {
|
|
88
|
-
volatile VALUE self_ref = self;
|
|
89
166
|
int query_was_scalar = ! rb_obj_is_carray(rval);
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"use ca.parent to count the raw storage",
|
|
94
|
-
rb_obj_classname(self));
|
|
167
|
+
if ( src->obj_type == CA_OBJ_RECORD && query_was_scalar ) {
|
|
168
|
+
/* A record is its bytes: a struct element counts as its encoding. */
|
|
169
|
+
rval = ca_face_element_to_storage(self, src, rval);
|
|
95
170
|
}
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if ( ca_is_face(cv) ) {
|
|
101
|
-
rval = rb_ca_strip_face_value(rval);
|
|
102
|
-
}
|
|
171
|
+
else {
|
|
172
|
+
if ( src->obj_type != CA_OBJ_RECORD
|
|
173
|
+
&& ! ca_test_flag(src, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
|
|
174
|
+
ca_face_refuse_order("count(v)", self, "count");
|
|
103
175
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
1, rval));
|
|
109
|
-
/* to_comparable lifts a scalar query to a length-1 array; unwrap it so a
|
|
110
|
-
scalar query still answers with a count rather than a length-1 array
|
|
111
|
-
from the broadcast branch below. */
|
|
176
|
+
rval = ca_face_reconcile_operand(self, rval, "count(v)");
|
|
177
|
+
/* to_comparable lifts a scalar query to a length-1 array; unwrap it so
|
|
178
|
+
a scalar query still answers with a count rather than a length-1
|
|
179
|
+
array from the broadcast branch below. */
|
|
112
180
|
if ( query_was_scalar && rb_obj_is_carray(rval) ) {
|
|
113
181
|
rval = rb_ca_fetch_addr(rval, 0);
|
|
114
182
|
}
|
|
115
183
|
}
|
|
116
|
-
else {
|
|
117
|
-
rb_raise(rb_eArgError,
|
|
118
|
-
"count(v): non-comparable Face (%s) has no to_comparable to "
|
|
119
|
-
"reconcile the query; use ca.parent to count the raw storage",
|
|
120
|
-
rb_obj_classname(self));
|
|
121
|
-
}
|
|
122
184
|
self = rb_ca_strip_face_value(self);
|
|
123
185
|
GetCArray(self, src);
|
|
124
186
|
/* Hand the reconciled query down in argv (count_equal_ki pops argv[0],
|
|
@@ -148,14 +210,26 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
148
210
|
CArray *cv;
|
|
149
211
|
GetCArray(rval, cv);
|
|
150
212
|
|
|
213
|
+
/* A query of a wider type than an integer array is counted in the type
|
|
214
|
+
the two share, as `eq` compares: each v[k] below is then a value of
|
|
215
|
+
that type, not one truncated to the array's. */
|
|
216
|
+
if ( ca_is_integer_type(src) &&
|
|
217
|
+
( ca_is_integer_type(cv) || ca_is_float_type(cv) ) ) {
|
|
218
|
+
int8_t qt = ca_promote_type(src->data_type, cv->data_type);
|
|
219
|
+
if ( qt != src->data_type ) {
|
|
220
|
+
self = rb_ca_wrap_readonly(self, INT2NUM(qt));
|
|
221
|
+
GetCArray(self, src);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
151
225
|
/* Pop trailing options hash (min_count / fill_value) before axes
|
|
152
226
|
parsing so parse_reduce_axes only sees Integer axes. The opts
|
|
153
227
|
are forwarded verbatim via inner_argv to the recursive count(). */
|
|
154
228
|
int inner_argc = argc - 1;
|
|
155
229
|
VALUE *inner_axes = argv + 1;
|
|
156
230
|
volatile VALUE opt_hash = Qnil;
|
|
157
|
-
if ( inner_argc > 0 &&
|
|
158
|
-
|
|
231
|
+
if ( inner_argc > 0 && rb_keyword_given_p() &&
|
|
232
|
+
rb_obj_is_kind_of(inner_axes[inner_argc - 1], rb_cHash) ) {
|
|
159
233
|
opt_hash = inner_axes[inner_argc - 1];
|
|
160
234
|
inner_argc--;
|
|
161
235
|
}
|
|
@@ -202,64 +276,34 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
202
276
|
CArray *cout;
|
|
203
277
|
GetCArray(vout, cout);
|
|
204
278
|
|
|
279
|
+
/* The options are checked by the recursive count() below, which an
|
|
280
|
+
empty v never reaches: check them once with a stand-in query, so a
|
|
281
|
+
misspelt keyword raises whatever v holds. */
|
|
282
|
+
if ( cv->elements == 0 && ! NIL_P(opt_hash) &&
|
|
283
|
+
src->data_type != CA_FIXLEN ) {
|
|
284
|
+
VALUE probe_argv[CA_RANK_MAX + 2];
|
|
285
|
+
int j;
|
|
286
|
+
probe_argv[0] = INT2FIX(0);
|
|
287
|
+
for (j = 0; j < inner_argc; j++) probe_argv[1 + j] = inner_axes[j];
|
|
288
|
+
probe_argv[1 + inner_argc] = opt_hash;
|
|
289
|
+
rb_ca_count(inner_argc + 2, probe_argv, self);
|
|
290
|
+
}
|
|
291
|
+
|
|
205
292
|
/* Iterate v in flat order, call self.count(vk, *axes, **opts)
|
|
206
|
-
recursively, place result at output[..., k].
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
/* Extract vk as a scalar VALUE via flat addr. rb_ca_fetch_addr
|
|
220
|
-
takes a ca_size_t addr (not a Ruby VALUE). */
|
|
221
|
-
VALUE vk = rb_ca_fetch_addr(rval, k);
|
|
222
|
-
inner_argv[0] = vk;
|
|
223
|
-
VALUE sub = rb_ca_count(inner_call_argc, inner_argv, self);
|
|
224
|
-
|
|
225
|
-
/* Place sub into output[..., k] slot.
|
|
226
|
-
Output stride for v-axis = 1, base stride = v_elements. */
|
|
227
|
-
if ( sub == CA_UNDEF ) {
|
|
228
|
-
if ( ! out_mask ) {
|
|
229
|
-
ca_create_mask(cout);
|
|
230
|
-
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
231
|
-
}
|
|
232
|
-
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
233
|
-
out_ptr[i * v_elements + k] = 0;
|
|
234
|
-
out_mask[i * v_elements + k] = 1;
|
|
235
|
-
}
|
|
236
|
-
} else if ( rb_obj_is_kind_of(sub, rb_cInteger) ) {
|
|
237
|
-
/* Full reduction: sub is a single integer. */
|
|
238
|
-
out_ptr[k] = NUM2LL(sub);
|
|
239
|
-
} else if ( rb_obj_is_kind_of(sub, rb_cCArray) ) {
|
|
240
|
-
CArray *csub;
|
|
241
|
-
GetCArray(sub, csub);
|
|
242
|
-
ca_attach(csub);
|
|
243
|
-
int64_t *sub_ptr = (int64_t *) csub->ptr;
|
|
244
|
-
boolean8_t *sub_mask = (csub->mask) ? (boolean8_t *) csub->mask->ptr : NULL;
|
|
245
|
-
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
246
|
-
out_ptr[i * v_elements + k] = sub_ptr[i];
|
|
247
|
-
if ( sub_mask && sub_mask[i] ) {
|
|
248
|
-
if ( ! out_mask ) {
|
|
249
|
-
ca_create_mask(cout);
|
|
250
|
-
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
251
|
-
}
|
|
252
|
-
out_mask[i * v_elements + k] = 1;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
ca_detach(csub);
|
|
256
|
-
} else {
|
|
257
|
-
ca_detach(cv);
|
|
258
|
-
rb_raise(rb_eRuntimeError,
|
|
259
|
-
"count(v: CArray): unexpected sub-result type");
|
|
260
|
-
}
|
|
293
|
+
recursively, place result at output[..., k]. v is held attached
|
|
294
|
+
for the fetches while Ruby runs, so the loop is a window body. */
|
|
295
|
+
{
|
|
296
|
+
ca_count_each_ctx_t c;
|
|
297
|
+
c.self = self;
|
|
298
|
+
c.rval = rval;
|
|
299
|
+
c.cv = cv;
|
|
300
|
+
c.cout = cout;
|
|
301
|
+
c.base_elements = base_elements;
|
|
302
|
+
c.inner_argc = inner_argc;
|
|
303
|
+
c.inner_axes = inner_axes;
|
|
304
|
+
c.opt_hash = opt_hash;
|
|
305
|
+
ca_attach_window(1, &cv, "r", ca_count_each_body, (VALUE) &c);
|
|
261
306
|
}
|
|
262
|
-
ca_detach(cv);
|
|
263
307
|
return vout;
|
|
264
308
|
}
|
|
265
309
|
|
|
@@ -290,11 +334,19 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
290
334
|
rb_obj_classname(rval));
|
|
291
335
|
}
|
|
292
336
|
} else {
|
|
293
|
-
|
|
337
|
+
/* true / false are the boolean array's own domain, not a number --
|
|
338
|
+
except in an object array, where they are ordinary stored values. */
|
|
339
|
+
if ( ( rval == Qtrue || rval == Qfalse ) && src->data_type != CA_OBJECT ) {
|
|
294
340
|
rb_raise(rb_eTypeError,
|
|
295
341
|
"count(v) on numeric array: v must be numeric, got %s",
|
|
296
342
|
rb_obj_classname(rval));
|
|
297
343
|
}
|
|
344
|
+
/* A Float query on an integer array is compared as a float, as `eq`
|
|
345
|
+
compares and `search` searches: 1.5 must not match 1. An Integer
|
|
346
|
+
query keeps the array's type and is refused when it does not fit. */
|
|
347
|
+
if ( ca_is_integer_type(src) && RB_FLOAT_TYPE_P(rval) ) {
|
|
348
|
+
self = rb_ca_wrap_readonly(self, INT2NUM(CA_FLOAT64));
|
|
349
|
+
}
|
|
298
350
|
/* Pass full argv; count_equal_ki pops argv[0] as value_arg. */
|
|
299
351
|
return rb_ca_count_equal_ki(argc, argv, self);
|
|
300
352
|
}
|
data/ext/carray_element.c
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
#include "ruby.h"
|
|
19
19
|
#include "carray.h"
|
|
20
20
|
#include "ca_obj_face.h"
|
|
21
|
+
#include "carray_internal.h" /* ca_obj_extremum_replaces */
|
|
21
22
|
|
|
22
23
|
/* T_ARRAY index parser. ridx is assumed already known to be T_ARRAY.
|
|
23
24
|
Direct VALUE * access + FIXNUM_P fast path eliminates rb_ary_entry
|
|
@@ -85,8 +86,8 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
85
86
|
ca_size_t idx1[CA_RANK_MAX], idx2[CA_RANK_MAX];
|
|
86
87
|
ca_size_t addr1 = 0, addr2 = 0;
|
|
87
88
|
int has_mask, has_index1, has_index2;
|
|
88
|
-
|
|
89
|
-
char *val1
|
|
89
|
+
volatile VALUE holder1, holder2;
|
|
90
|
+
char *val1, *val2;
|
|
90
91
|
boolean8_t m1 = 0, m2 = 0;
|
|
91
92
|
|
|
92
93
|
rb_ca_modify(self);
|
|
@@ -95,10 +96,8 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
95
96
|
|
|
96
97
|
has_mask = elem_probe_mask(ca);
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
val2 = xmalloc(ca->bytes);
|
|
101
|
-
}
|
|
99
|
+
val1 = ALLOCV_N(char, holder1, ca->bytes);
|
|
100
|
+
val2 = ALLOCV_N(char, holder2, ca->bytes);
|
|
102
101
|
|
|
103
102
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
104
103
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -160,10 +159,8 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
160
159
|
}
|
|
161
160
|
}
|
|
162
161
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
xfree(val2);
|
|
166
|
-
}
|
|
162
|
+
ALLOCV_END(holder2);
|
|
163
|
+
ALLOCV_END(holder1);
|
|
167
164
|
|
|
168
165
|
return self;
|
|
169
166
|
}
|
|
@@ -178,8 +175,8 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
178
175
|
ca_size_t idx1[CA_RANK_MAX], idx2[CA_RANK_MAX];
|
|
179
176
|
ca_size_t addr1 = 0, addr2 = 0;
|
|
180
177
|
int has_mask;
|
|
181
|
-
|
|
182
|
-
char *val
|
|
178
|
+
volatile VALUE holder;
|
|
179
|
+
char *val;
|
|
183
180
|
boolean8_t m = 0;
|
|
184
181
|
|
|
185
182
|
rb_ca_modify(self);
|
|
@@ -188,9 +185,7 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
188
185
|
|
|
189
186
|
has_mask = elem_probe_mask(ca);
|
|
190
187
|
|
|
191
|
-
|
|
192
|
-
val = xmalloc(ca->bytes);
|
|
193
|
-
}
|
|
188
|
+
val = ALLOCV_N(char, holder, ca->bytes);
|
|
194
189
|
|
|
195
190
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
196
191
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -222,9 +217,7 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
222
217
|
}
|
|
223
218
|
}
|
|
224
219
|
|
|
225
|
-
|
|
226
|
-
xfree(val);
|
|
227
|
-
}
|
|
220
|
+
ALLOCV_END(holder);
|
|
228
221
|
|
|
229
222
|
return self;
|
|
230
223
|
}
|
|
@@ -380,10 +373,11 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
380
373
|
out = rb_ca_ptr2obj(self, v);
|
|
381
374
|
}
|
|
382
375
|
else {
|
|
383
|
-
|
|
376
|
+
volatile VALUE holder;
|
|
377
|
+
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
384
378
|
ca_fetch_index(ca, idx, v);
|
|
385
379
|
out = rb_ca_ptr2obj(self, v);
|
|
386
|
-
|
|
380
|
+
ALLOCV_END(holder);
|
|
387
381
|
}
|
|
388
382
|
|
|
389
383
|
/* Mask check with inline skip for the entity+no-mask common case. */
|
|
@@ -401,7 +395,7 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
401
395
|
}
|
|
402
396
|
}
|
|
403
397
|
|
|
404
|
-
|
|
398
|
+
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(out, self, ca);
|
|
405
399
|
return out;
|
|
406
400
|
}
|
|
407
401
|
else {
|
|
@@ -690,10 +684,7 @@ rb_ca_elem_mask (VALUE self, VALUE ridx)
|
|
|
690
684
|
/* General path: view array. Walk parent chain + dispatch. */
|
|
691
685
|
{
|
|
692
686
|
boolean8_t one = 1;
|
|
693
|
-
|
|
694
|
-
if ( ! ca->mask ) {
|
|
695
|
-
ca_create_mask(ca);
|
|
696
|
-
}
|
|
687
|
+
ca_create_mask(ca);
|
|
697
688
|
if ( TYPE(ridx) == T_ARRAY ) {
|
|
698
689
|
elem_parse_idx_array(ca, ridx, idx);
|
|
699
690
|
ca_store_index(ca->mask, idx, &one);
|
|
@@ -846,7 +837,7 @@ rb_ca_elem_min (VALUE self, VALUE ridx, VALUE rval)
|
|
|
846
837
|
|
|
847
838
|
cur = from_array ? rb_ca_fetch_index(self, idx) : rb_ca_fetch_addr(self, addr);
|
|
848
839
|
if ( cur == CA_UNDEF ) return self;
|
|
849
|
-
if (
|
|
840
|
+
if ( ca_obj_extremum_replaces(rval, cur, rb_intern("<")) ) {
|
|
850
841
|
if ( from_array ) rb_ca_store_index(self, idx, rval);
|
|
851
842
|
else rb_ca_store_addr(self, addr, rval);
|
|
852
843
|
}
|
|
@@ -899,7 +890,7 @@ rb_ca_elem_max (VALUE self, VALUE ridx, VALUE rval)
|
|
|
899
890
|
|
|
900
891
|
cur = from_array ? rb_ca_fetch_index(self, idx) : rb_ca_fetch_addr(self, addr);
|
|
901
892
|
if ( cur == CA_UNDEF ) return self;
|
|
902
|
-
if (
|
|
893
|
+
if ( ca_obj_extremum_replaces(rval, cur, rb_intern(">")) ) {
|
|
903
894
|
if ( from_array ) rb_ca_store_index(self, idx, rval);
|
|
904
895
|
else rb_ca_store_addr(self, addr, rval);
|
|
905
896
|
}
|