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_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>
|
|
@@ -46,6 +47,91 @@ VALUE rb_ca_count_not_masked (int argc, VALUE *argv, VALUE self);
|
|
|
46
47
|
cell; a short String query is padded
|
|
47
48
|
out to the cell width) */
|
|
48
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
|
+
VALUE sub;
|
|
86
|
+
/* A masked query cell asks nothing: its count is masked. Passing it
|
|
87
|
+
on would ask count(UNDEF), the count of self's masked cells. */
|
|
88
|
+
if ( vk == CA_UNDEF ) {
|
|
89
|
+
sub = CA_UNDEF;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
inner_argv[0] = vk;
|
|
93
|
+
sub = rb_ca_count(inner_call_argc, inner_argv, c->self);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Place sub into output[..., k] slot.
|
|
97
|
+
Output stride for v-axis = 1, base stride = v_elements. */
|
|
98
|
+
if ( sub == CA_UNDEF ) {
|
|
99
|
+
if ( ! out_mask ) {
|
|
100
|
+
ca_create_mask(cout);
|
|
101
|
+
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
102
|
+
}
|
|
103
|
+
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
104
|
+
out_ptr[i * v_elements + k] = 0;
|
|
105
|
+
out_mask[i * v_elements + k] = 1;
|
|
106
|
+
}
|
|
107
|
+
} else if ( rb_obj_is_kind_of(sub, rb_cInteger) ) {
|
|
108
|
+
/* Full reduction: sub is a single integer. */
|
|
109
|
+
out_ptr[k] = NUM2LL(sub);
|
|
110
|
+
} else if ( rb_obj_is_kind_of(sub, rb_cCArray) ) {
|
|
111
|
+
CArray *csub;
|
|
112
|
+
GetCArray(sub, csub);
|
|
113
|
+
ca_attach(csub); /* window: the inner count answered an entity; nothing raises inside */
|
|
114
|
+
int64_t *sub_ptr = (int64_t *) csub->ptr;
|
|
115
|
+
boolean8_t *sub_mask = (csub->mask) ? (boolean8_t *) csub->mask->ptr : NULL;
|
|
116
|
+
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
117
|
+
out_ptr[i * v_elements + k] = sub_ptr[i];
|
|
118
|
+
if ( sub_mask && sub_mask[i] ) {
|
|
119
|
+
if ( ! out_mask ) {
|
|
120
|
+
ca_create_mask(cout);
|
|
121
|
+
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
122
|
+
}
|
|
123
|
+
out_mask[i * v_elements + k] = 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
ca_detach(csub);
|
|
127
|
+
} else {
|
|
128
|
+
rb_raise(rb_eRuntimeError,
|
|
129
|
+
"count(v: CArray): unexpected sub-result type");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return Qnil;
|
|
133
|
+
}
|
|
134
|
+
|
|
49
135
|
static VALUE
|
|
50
136
|
rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
51
137
|
{
|
|
@@ -57,10 +143,11 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
57
143
|
ladder. kwargs reach a -1 C method as a trailing options hash, so a
|
|
58
144
|
bare `count(axis: k)` arrives as argc==1 with argv[0] a Hash; discount
|
|
59
145
|
that trailing hash (same convention as the CArray-broadcast branch
|
|
60
|
-
below) before deciding there is no positional value.
|
|
61
|
-
|
|
146
|
+
below) before deciding there is no positional value. A Hash passed
|
|
147
|
+
positionally is the value to count. argv is forwarded verbatim so the
|
|
148
|
+
axis: kwarg passes through. */
|
|
62
149
|
{
|
|
63
|
-
int has_opts = ( argc >= 1 &&
|
|
150
|
+
int has_opts = ( argc >= 1 && rb_keyword_given_p() &&
|
|
64
151
|
rb_obj_is_kind_of(argv[argc - 1], rb_cHash) );
|
|
65
152
|
if ( argc - (has_opts ? 1 : 0) < 1 ) {
|
|
66
153
|
return rb_ca_count_not_masked(argc, argv, self);
|
|
@@ -78,44 +165,36 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
78
165
|
/* Face gate, mirroring the search / linear family (ext/carray_order.c):
|
|
79
166
|
descend an ORDERABLE Face to its storage so the equality runs on the
|
|
80
167
|
numeric storage, and let the reference reconcile the query into its own
|
|
81
|
-
space
|
|
82
|
-
plain one as-is), a unit-bearing one calls its own to_comparable for any
|
|
83
|
-
query type (Face CArray, Element, Time, DateTime). A Face that counts
|
|
168
|
+
space (ca_face_reconcile_operand). A Face that counts
|
|
84
169
|
by other means never arrives here: CACategorical / CAConstString define
|
|
85
170
|
their own #count in Ruby. Placed after the mask-state branches above,
|
|
86
171
|
which read the mask the Face already shares with its storage, and before
|
|
87
172
|
the broadcast branch, so a reconciled query array recurses as storage. */
|
|
88
173
|
if ( ca_is_face(src) ) {
|
|
89
|
-
volatile VALUE self_ref = self;
|
|
90
174
|
int query_was_scalar = ! rb_obj_is_carray(rval);
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"use ca.parent to count the raw storage",
|
|
95
|
-
rb_obj_classname(self));
|
|
175
|
+
if ( src->obj_type == CA_OBJ_RECORD && query_was_scalar ) {
|
|
176
|
+
/* A record is its bytes: a struct element counts as its encoding. */
|
|
177
|
+
rval = ca_face_element_to_storage(self, src, rval);
|
|
96
178
|
}
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
179
|
+
else {
|
|
180
|
+
if ( src->obj_type != CA_OBJ_RECORD ) {
|
|
181
|
+
ca_face_require_orderable(self, "count(v)", "count");
|
|
100
182
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
183
|
+
{
|
|
184
|
+
volatile VALUE ref = self, query = rval;
|
|
185
|
+
ca_face_reconcile_pair(&ref, &query, "count(v)");
|
|
186
|
+
self = ref;
|
|
187
|
+
rval = query;
|
|
188
|
+
}
|
|
189
|
+
/* The reconcile lifts a scalar query to a length-1 array; unwrap it so
|
|
190
|
+
a scalar query still answers with a count rather than a length-1
|
|
191
|
+
array from the broadcast branch below. A Ruby Array is a list of
|
|
192
|
+
queries and stays one, like a CArray query. */
|
|
193
|
+
if ( query_was_scalar && ! RB_TYPE_P(argv[0], T_ARRAY)
|
|
194
|
+
&& rb_obj_is_carray(rval) ) {
|
|
110
195
|
rval = rb_ca_fetch_addr(rval, 0);
|
|
111
196
|
}
|
|
112
197
|
}
|
|
113
|
-
else {
|
|
114
|
-
rb_raise(rb_eArgError,
|
|
115
|
-
"count(v): non-comparable Face (%s) has no to_comparable to "
|
|
116
|
-
"reconcile the query; use ca.parent to count the raw storage",
|
|
117
|
-
rb_obj_classname(self));
|
|
118
|
-
}
|
|
119
198
|
self = rb_ca_strip_face_value(self);
|
|
120
199
|
GetCArray(self, src);
|
|
121
200
|
/* Hand the reconciled query down in argv (count_equal_ki pops argv[0],
|
|
@@ -145,14 +224,25 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
145
224
|
CArray *cv;
|
|
146
225
|
GetCArray(rval, cv);
|
|
147
226
|
|
|
227
|
+
/* The array is counted in the type it and v match in, as `eq` compares
|
|
228
|
+
(ca_query_match_type): each v[k] below is then a value of that type,
|
|
229
|
+
not one cut to the array's. */
|
|
230
|
+
if ( ca_query_match_applies(src, rval) ) {
|
|
231
|
+
int8_t qt = ca_query_match_type(src->data_type, rval);
|
|
232
|
+
if ( qt != src->data_type ) {
|
|
233
|
+
self = rb_ca_wrap_readonly(self, INT2NUM(qt));
|
|
234
|
+
GetCArray(self, src);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
148
238
|
/* Pop trailing options hash (min_count / fill_value) before axes
|
|
149
239
|
parsing so parse_reduce_axes only sees Integer axes. The opts
|
|
150
240
|
are forwarded verbatim via inner_argv to the recursive count(). */
|
|
151
241
|
int inner_argc = argc - 1;
|
|
152
242
|
VALUE *inner_axes = argv + 1;
|
|
153
243
|
volatile VALUE opt_hash = Qnil;
|
|
154
|
-
if ( inner_argc > 0 &&
|
|
155
|
-
|
|
244
|
+
if ( inner_argc > 0 && rb_keyword_given_p() &&
|
|
245
|
+
rb_obj_is_kind_of(inner_axes[inner_argc - 1], rb_cHash) ) {
|
|
156
246
|
opt_hash = inner_axes[inner_argc - 1];
|
|
157
247
|
inner_argc--;
|
|
158
248
|
}
|
|
@@ -199,64 +289,34 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
199
289
|
CArray *cout;
|
|
200
290
|
GetCArray(vout, cout);
|
|
201
291
|
|
|
292
|
+
/* The options are checked by the recursive count() below, which an
|
|
293
|
+
empty v never reaches: check them once with a stand-in query, so a
|
|
294
|
+
misspelt keyword raises whatever v holds. */
|
|
295
|
+
if ( cv->elements == 0 && ! NIL_P(opt_hash) &&
|
|
296
|
+
src->data_type != CA_FIXLEN ) {
|
|
297
|
+
VALUE probe_argv[CA_RANK_MAX + 2];
|
|
298
|
+
int j;
|
|
299
|
+
probe_argv[0] = INT2FIX(0);
|
|
300
|
+
for (j = 0; j < inner_argc; j++) probe_argv[1 + j] = inner_axes[j];
|
|
301
|
+
probe_argv[1 + inner_argc] = opt_hash;
|
|
302
|
+
rb_ca_count(inner_argc + 2, probe_argv, self);
|
|
303
|
+
}
|
|
304
|
+
|
|
202
305
|
/* Iterate v in flat order, call self.count(vk, *axes, **opts)
|
|
203
|
-
recursively, place result at output[..., k].
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
/* Extract vk as a scalar VALUE via flat addr. rb_ca_fetch_addr
|
|
217
|
-
takes a ca_size_t addr (not a Ruby VALUE). */
|
|
218
|
-
VALUE vk = rb_ca_fetch_addr(rval, k);
|
|
219
|
-
inner_argv[0] = vk;
|
|
220
|
-
VALUE sub = rb_ca_count(inner_call_argc, inner_argv, self);
|
|
221
|
-
|
|
222
|
-
/* Place sub into output[..., k] slot.
|
|
223
|
-
Output stride for v-axis = 1, base stride = v_elements. */
|
|
224
|
-
if ( sub == CA_UNDEF ) {
|
|
225
|
-
if ( ! out_mask ) {
|
|
226
|
-
ca_create_mask(cout);
|
|
227
|
-
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
228
|
-
}
|
|
229
|
-
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
230
|
-
out_ptr[i * v_elements + k] = 0;
|
|
231
|
-
out_mask[i * v_elements + k] = 1;
|
|
232
|
-
}
|
|
233
|
-
} else if ( rb_obj_is_kind_of(sub, rb_cInteger) ) {
|
|
234
|
-
/* Full reduction: sub is a single integer. */
|
|
235
|
-
out_ptr[k] = NUM2LL(sub);
|
|
236
|
-
} else if ( rb_obj_is_kind_of(sub, rb_cCArray) ) {
|
|
237
|
-
CArray *csub;
|
|
238
|
-
GetCArray(sub, csub);
|
|
239
|
-
ca_attach(csub);
|
|
240
|
-
int64_t *sub_ptr = (int64_t *) csub->ptr;
|
|
241
|
-
boolean8_t *sub_mask = (csub->mask) ? (boolean8_t *) csub->mask->ptr : NULL;
|
|
242
|
-
for (ca_size_t i = 0; i < base_elements; i++) {
|
|
243
|
-
out_ptr[i * v_elements + k] = sub_ptr[i];
|
|
244
|
-
if ( sub_mask && sub_mask[i] ) {
|
|
245
|
-
if ( ! out_mask ) {
|
|
246
|
-
ca_create_mask(cout);
|
|
247
|
-
out_mask = (boolean8_t *) cout->mask->ptr;
|
|
248
|
-
}
|
|
249
|
-
out_mask[i * v_elements + k] = 1;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
ca_detach(csub);
|
|
253
|
-
} else {
|
|
254
|
-
ca_detach(cv);
|
|
255
|
-
rb_raise(rb_eRuntimeError,
|
|
256
|
-
"count(v: CArray): unexpected sub-result type");
|
|
257
|
-
}
|
|
306
|
+
recursively, place result at output[..., k]. v is held attached
|
|
307
|
+
for the fetches while Ruby runs, so the loop is a window body. */
|
|
308
|
+
{
|
|
309
|
+
ca_count_each_ctx_t c;
|
|
310
|
+
c.self = self;
|
|
311
|
+
c.rval = rval;
|
|
312
|
+
c.cv = cv;
|
|
313
|
+
c.cout = cout;
|
|
314
|
+
c.base_elements = base_elements;
|
|
315
|
+
c.inner_argc = inner_argc;
|
|
316
|
+
c.inner_axes = inner_axes;
|
|
317
|
+
c.opt_hash = opt_hash;
|
|
318
|
+
ca_attach_window(1, &cv, "r", ca_count_each_body, (VALUE) &c);
|
|
258
319
|
}
|
|
259
|
-
ca_detach(cv);
|
|
260
320
|
return vout;
|
|
261
321
|
}
|
|
262
322
|
|
|
@@ -294,6 +354,29 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
294
354
|
"count(v) on numeric array: v must be numeric, got %s",
|
|
295
355
|
rb_obj_classname(rval));
|
|
296
356
|
}
|
|
357
|
+
/* The query is compared in the type it and the array match in, as `eq`
|
|
358
|
+
compares (ca_query_match_type): 1.5 does not match 1, and an Integer
|
|
359
|
+
the array's type cannot hold matches nothing. */
|
|
360
|
+
if ( ca_is_integer_type(src) && ! RB_INTEGER_TYPE_P(rval)
|
|
361
|
+
&& ! RB_FLOAT_TYPE_P(rval) && ! RB_TYPE_P(rval, T_COMPLEX)
|
|
362
|
+
&& rb_obj_is_kind_of(rval, rb_cNumeric) ) {
|
|
363
|
+
/* A Rational or BigDecimal query: an integral one is the Integer it
|
|
364
|
+
equals; any other is compared as a float, like a Float query,
|
|
365
|
+
rather than cut to the array's type. */
|
|
366
|
+
VALUE ival = rb_funcall(rval, rb_intern("to_i"), 0);
|
|
367
|
+
VALUE *nargv = ALLOCA_N(VALUE, argc);
|
|
368
|
+
MEMCPY(nargv, argv, VALUE, argc);
|
|
369
|
+
nargv[0] = RTEST(rb_funcall(rval, rb_intern("=="), 1, ival))
|
|
370
|
+
? ival : rb_funcall(rval, rb_intern("to_f"), 0);
|
|
371
|
+
argv = nargv;
|
|
372
|
+
rval = nargv[0];
|
|
373
|
+
}
|
|
374
|
+
if ( ca_query_match_applies(src, rval) ) {
|
|
375
|
+
int8_t qt = ca_query_match_type(src->data_type, rval);
|
|
376
|
+
if ( qt != src->data_type ) {
|
|
377
|
+
self = rb_ca_wrap_readonly(self, INT2NUM(qt));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
297
380
|
/* Pass full argv; count_equal_ki pops argv[0] as value_arg. */
|
|
298
381
|
return rb_ca_count_equal_ki(argc, argv, self);
|
|
299
382
|
}
|
data/ext/carray_element.c
CHANGED
|
@@ -18,6 +18,20 @@
|
|
|
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 */
|
|
22
|
+
|
|
23
|
+
/* An element index is an Integer, as it is for `[]`; a Float would be cut
|
|
24
|
+
to an integer by NUM2SIZE. */
|
|
25
|
+
static inline ca_size_t
|
|
26
|
+
elem_index_value (VALUE v)
|
|
27
|
+
{
|
|
28
|
+
if ( FIXNUM_P(v) ) return (ca_size_t) FIX2LONG(v);
|
|
29
|
+
if ( ! RB_INTEGER_TYPE_P(v) ) {
|
|
30
|
+
rb_raise(rb_eIndexError, "object '%"PRIsVALUE"' is invalid for an index",
|
|
31
|
+
rb_inspect(v));
|
|
32
|
+
}
|
|
33
|
+
return NUM2SIZE(v);
|
|
34
|
+
}
|
|
21
35
|
|
|
22
36
|
/* T_ARRAY index parser. ridx is assumed already known to be T_ARRAY.
|
|
23
37
|
Direct VALUE * access + FIXNUM_P fast path eliminates rb_ary_entry
|
|
@@ -25,12 +39,16 @@
|
|
|
25
39
|
static inline void
|
|
26
40
|
elem_parse_idx_array (CArray *ca, VALUE rary, ca_size_t *idx)
|
|
27
41
|
{
|
|
28
|
-
const VALUE *iarr
|
|
42
|
+
const VALUE *iarr;
|
|
29
43
|
int8_t ndim = ca->ndim;
|
|
30
44
|
int8_t i;
|
|
45
|
+
if ( RARRAY_LEN(rary) != ndim ) {
|
|
46
|
+
rb_raise(rb_eIndexError, "%ld indices given for a carray of ndim %i",
|
|
47
|
+
(long) RARRAY_LEN(rary), (int) ndim);
|
|
48
|
+
}
|
|
49
|
+
iarr = RARRAY_CONST_PTR(rary);
|
|
31
50
|
for (i=0; i<ndim; i++) {
|
|
32
|
-
|
|
33
|
-
ca_size_t k = FIXNUM_P(v) ? (ca_size_t)FIX2LONG(v) : NUM2SIZE(v);
|
|
51
|
+
ca_size_t k = elem_index_value(iarr[i]);
|
|
34
52
|
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
35
53
|
idx[i] = k;
|
|
36
54
|
}
|
|
@@ -40,7 +58,7 @@ elem_parse_idx_array (CArray *ca, VALUE rary, ca_size_t *idx)
|
|
|
40
58
|
static inline ca_size_t
|
|
41
59
|
elem_parse_idx_scalar (CArray *ca, VALUE ridx)
|
|
42
60
|
{
|
|
43
|
-
ca_size_t k =
|
|
61
|
+
ca_size_t k = elem_index_value(ridx);
|
|
44
62
|
CA_CHECK_INDEX(k, ca->elements);
|
|
45
63
|
return k;
|
|
46
64
|
}
|
|
@@ -85,8 +103,8 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
85
103
|
ca_size_t idx1[CA_RANK_MAX], idx2[CA_RANK_MAX];
|
|
86
104
|
ca_size_t addr1 = 0, addr2 = 0;
|
|
87
105
|
int has_mask, has_index1, has_index2;
|
|
88
|
-
|
|
89
|
-
char *val1
|
|
106
|
+
volatile VALUE holder1, holder2;
|
|
107
|
+
char *val1, *val2;
|
|
90
108
|
boolean8_t m1 = 0, m2 = 0;
|
|
91
109
|
|
|
92
110
|
rb_ca_modify(self);
|
|
@@ -95,10 +113,8 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
95
113
|
|
|
96
114
|
has_mask = elem_probe_mask(ca);
|
|
97
115
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
val2 = xmalloc(ca->bytes);
|
|
101
|
-
}
|
|
116
|
+
val1 = ALLOCV_N(char, holder1, ca->bytes);
|
|
117
|
+
val2 = ALLOCV_N(char, holder2, ca->bytes);
|
|
102
118
|
|
|
103
119
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
104
120
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -160,10 +176,8 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
160
176
|
}
|
|
161
177
|
}
|
|
162
178
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
xfree(val2);
|
|
166
|
-
}
|
|
179
|
+
ALLOCV_END(holder2);
|
|
180
|
+
ALLOCV_END(holder1);
|
|
167
181
|
|
|
168
182
|
return self;
|
|
169
183
|
}
|
|
@@ -178,8 +192,8 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
178
192
|
ca_size_t idx1[CA_RANK_MAX], idx2[CA_RANK_MAX];
|
|
179
193
|
ca_size_t addr1 = 0, addr2 = 0;
|
|
180
194
|
int has_mask;
|
|
181
|
-
|
|
182
|
-
char *val
|
|
195
|
+
volatile VALUE holder;
|
|
196
|
+
char *val;
|
|
183
197
|
boolean8_t m = 0;
|
|
184
198
|
|
|
185
199
|
rb_ca_modify(self);
|
|
@@ -188,9 +202,7 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
188
202
|
|
|
189
203
|
has_mask = elem_probe_mask(ca);
|
|
190
204
|
|
|
191
|
-
|
|
192
|
-
val = xmalloc(ca->bytes);
|
|
193
|
-
}
|
|
205
|
+
val = ALLOCV_N(char, holder, ca->bytes);
|
|
194
206
|
|
|
195
207
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
196
208
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -222,9 +234,7 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
222
234
|
}
|
|
223
235
|
}
|
|
224
236
|
|
|
225
|
-
|
|
226
|
-
xfree(val);
|
|
227
|
-
}
|
|
237
|
+
ALLOCV_END(holder);
|
|
228
238
|
|
|
229
239
|
return self;
|
|
230
240
|
}
|
|
@@ -285,33 +295,56 @@ rb_ca_elem_store (VALUE self, VALUE ridx, VALUE obj)
|
|
|
285
295
|
if ( FIXNUM_P(obj) ) { *(int64_t *)p = (int64_t)FIX2LONG(obj); return obj; }
|
|
286
296
|
break;
|
|
287
297
|
case CA_INT32:
|
|
288
|
-
if ( FIXNUM_P(obj)
|
|
298
|
+
if ( FIXNUM_P(obj) && FIX2LONG(obj) >= INT32_MIN && FIX2LONG(obj) <= INT32_MAX ) {
|
|
299
|
+
/* fits: checked against the type's range above */
|
|
300
|
+
*(int32_t *)p = (int32_t)FIX2LONG(obj); return obj;
|
|
301
|
+
}
|
|
289
302
|
break;
|
|
290
303
|
case CA_INT16:
|
|
291
|
-
if ( FIXNUM_P(obj)
|
|
304
|
+
if ( FIXNUM_P(obj) && FIX2LONG(obj) >= INT16_MIN && FIX2LONG(obj) <= INT16_MAX ) {
|
|
305
|
+
/* fits: checked against the type's range above */
|
|
306
|
+
*(int16_t *)p = (int16_t)FIX2LONG(obj); return obj;
|
|
307
|
+
}
|
|
292
308
|
break;
|
|
293
309
|
case CA_INT8:
|
|
294
|
-
if ( FIXNUM_P(obj)
|
|
310
|
+
if ( FIXNUM_P(obj) && FIX2LONG(obj) >= INT8_MIN && FIX2LONG(obj) <= INT8_MAX ) {
|
|
311
|
+
/* fits: checked against the type's range above */
|
|
312
|
+
*(int8_t *)p = (int8_t)FIX2LONG(obj); return obj;
|
|
313
|
+
}
|
|
295
314
|
break;
|
|
296
315
|
case CA_UINT64:
|
|
297
|
-
if ( FIXNUM_P(obj)
|
|
316
|
+
if ( FIXNUM_P(obj) && FIX2LONG(obj) >= 0 ) {
|
|
317
|
+
*(uint64_t *)p = (uint64_t)FIX2LONG(obj); return obj;
|
|
318
|
+
}
|
|
298
319
|
break;
|
|
299
320
|
case CA_UINT32:
|
|
300
|
-
if ( FIXNUM_P(obj)
|
|
321
|
+
if ( FIXNUM_P(obj) && FIX2LONG(obj) >= 0 && FIX2LONG(obj) <= (long) UINT32_MAX ) {
|
|
322
|
+
/* fits: checked against the type's range above */
|
|
323
|
+
*(uint32_t *)p = (uint32_t)FIX2LONG(obj); return obj;
|
|
324
|
+
}
|
|
301
325
|
break;
|
|
302
326
|
case CA_UINT16:
|
|
303
|
-
if ( FIXNUM_P(obj)
|
|
327
|
+
if ( FIXNUM_P(obj) && FIX2LONG(obj) >= 0 && FIX2LONG(obj) <= (long) UINT16_MAX ) {
|
|
328
|
+
/* fits: checked against the type's range above */
|
|
329
|
+
*(uint16_t *)p = (uint16_t)FIX2LONG(obj); return obj;
|
|
330
|
+
}
|
|
304
331
|
break;
|
|
305
332
|
case CA_UINT8:
|
|
306
|
-
if ( FIXNUM_P(obj)
|
|
333
|
+
if ( FIXNUM_P(obj) && FIX2LONG(obj) >= 0 && FIX2LONG(obj) <= (long) UINT8_MAX ) {
|
|
334
|
+
/* fits: checked against the type's range above */
|
|
335
|
+
*(uint8_t *)p = (uint8_t)FIX2LONG(obj); return obj;
|
|
336
|
+
}
|
|
307
337
|
break;
|
|
308
338
|
case CA_BOOLEAN:
|
|
309
339
|
if ( obj == Qtrue ) { *(uint8_t *)p = 1; return obj; }
|
|
310
340
|
if ( obj == Qfalse ) { *(uint8_t *)p = 0; return obj; }
|
|
311
|
-
if (
|
|
341
|
+
if ( obj == INT2FIX(0) || obj == INT2FIX(1) ) {
|
|
342
|
+
*(uint8_t *)p = (obj == INT2FIX(1)); return obj;
|
|
343
|
+
}
|
|
312
344
|
break;
|
|
313
345
|
}
|
|
314
|
-
/* Fall through:
|
|
346
|
+
/* Fall through: the value needs the general coercion, or does not fit
|
|
347
|
+
the cell, which the general path refuses. */
|
|
315
348
|
}
|
|
316
349
|
}
|
|
317
350
|
|
|
@@ -338,14 +371,12 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
338
371
|
|
|
339
372
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
340
373
|
|
|
341
|
-
if ( ca_is_empty(ca) ) return Qnil;
|
|
342
|
-
|
|
343
374
|
if ( TYPE(ridx) == T_ARRAY ) {
|
|
344
375
|
volatile VALUE out;
|
|
345
376
|
elem_parse_idx_array(ca, ridx, idx);
|
|
346
377
|
|
|
347
378
|
/* Super-hot path: entity + common numeric data type + no mask.
|
|
348
|
-
Bypass ca_fetch_index dispatch AND
|
|
379
|
+
Bypass ca_fetch_index dispatch AND rb_ca_ptr2obj_storage cast-table dispatch.
|
|
349
380
|
Covers the bench's float64 / int64 / int32 cases. */
|
|
350
381
|
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
351
382
|
ca_size_t addr = elem_entity_addr(ca, idx);
|
|
@@ -377,13 +408,14 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
377
408
|
else {
|
|
378
409
|
ca_fetch_index(ca, idx, v);
|
|
379
410
|
}
|
|
380
|
-
out =
|
|
411
|
+
out = rb_ca_ptr2obj_storage(self, v);
|
|
381
412
|
}
|
|
382
413
|
else {
|
|
383
|
-
|
|
414
|
+
volatile VALUE holder;
|
|
415
|
+
char *v = ALLOCV_N(char, holder, ca->bytes);
|
|
384
416
|
ca_fetch_index(ca, idx, v);
|
|
385
|
-
out =
|
|
386
|
-
|
|
417
|
+
out = rb_ca_ptr2obj_storage(self, v);
|
|
418
|
+
ALLOCV_END(holder);
|
|
387
419
|
}
|
|
388
420
|
|
|
389
421
|
/* Mask check with inline skip for the entity+no-mask common case. */
|
|
@@ -401,7 +433,7 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
401
433
|
}
|
|
402
434
|
}
|
|
403
435
|
|
|
404
|
-
|
|
436
|
+
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(out, self, ca);
|
|
405
437
|
return out;
|
|
406
438
|
}
|
|
407
439
|
else {
|
|
@@ -690,10 +722,7 @@ rb_ca_elem_mask (VALUE self, VALUE ridx)
|
|
|
690
722
|
/* General path: view array. Walk parent chain + dispatch. */
|
|
691
723
|
{
|
|
692
724
|
boolean8_t one = 1;
|
|
693
|
-
|
|
694
|
-
if ( ! ca->mask ) {
|
|
695
|
-
ca_create_mask(ca);
|
|
696
|
-
}
|
|
725
|
+
ca_create_mask(ca);
|
|
697
726
|
if ( TYPE(ridx) == T_ARRAY ) {
|
|
698
727
|
elem_parse_idx_array(ca, ridx, idx);
|
|
699
728
|
ca_store_index(ca->mask, idx, &one);
|
|
@@ -758,6 +787,11 @@ rb_ca_elem_unmask (VALUE self, VALUE ridx)
|
|
|
758
787
|
* rule (NaN is treated as missing: `min(NaN, v)` returns `v`,
|
|
759
788
|
* `min(x, NaN)` returns `x`). Raises for non-numeric data_type. */
|
|
760
789
|
|
|
790
|
+
/* The entity fast path takes a Float into a float cell and an Integer
|
|
791
|
+
that fits the cell. Anything else -- a Float into an integer cell, an
|
|
792
|
+
Integer out of the type's range, a Bignum or Rational -- goes to the
|
|
793
|
+
general path, which compares in Ruby and stores as `self[idx] = v`
|
|
794
|
+
does, so a value that wins but does not fit raises. */
|
|
761
795
|
#define ELEM_MINMAX_BODY(OP) do { \
|
|
762
796
|
if ( ca_is_entity(ca) ) { \
|
|
763
797
|
ca_size_t addr; \
|
|
@@ -775,14 +809,6 @@ rb_ca_elem_unmask (VALUE self, VALUE ridx)
|
|
|
775
809
|
switch ( ca->data_type ) { \
|
|
776
810
|
case CA_FLOAT64: { double *q=(double *)p; if (v OP *q || *q != *q) *q = v; return self; } \
|
|
777
811
|
case CA_FLOAT32: { float *q=(float *)p; float vf=(float)v; if (vf OP *q || *q != *q) *q = vf; return self; } \
|
|
778
|
-
case CA_INT64: { int64_t *q=(int64_t *)p; if ((int64_t)v OP *q) *q = (int64_t)v; return self; } \
|
|
779
|
-
case CA_INT32: { int32_t *q=(int32_t *)p; if ((int32_t)v OP *q) *q = (int32_t)v; return self; } \
|
|
780
|
-
case CA_INT16: { int16_t *q=(int16_t *)p; if ((int16_t)v OP *q) *q = (int16_t)v; return self; } \
|
|
781
|
-
case CA_INT8: { int8_t *q=(int8_t *)p; if ((int8_t )v OP *q) *q = (int8_t )v; return self; } \
|
|
782
|
-
case CA_UINT64: { uint64_t *q=(uint64_t*)p; if ((uint64_t)v OP *q) *q = (uint64_t)v; return self; } \
|
|
783
|
-
case CA_UINT32: { uint32_t *q=(uint32_t*)p; if ((uint32_t)v OP *q) *q = (uint32_t)v; return self; } \
|
|
784
|
-
case CA_UINT16: { uint16_t *q=(uint16_t*)p; if ((uint16_t)v OP *q) *q = (uint16_t)v; return self; } \
|
|
785
|
-
case CA_UINT8: { uint8_t *q=(uint8_t *)p; if ((uint8_t )v OP *q) *q = (uint8_t )v; return self; } \
|
|
786
812
|
} \
|
|
787
813
|
} \
|
|
788
814
|
else if ( FIXNUM_P(rval) ) { \
|
|
@@ -791,13 +817,13 @@ rb_ca_elem_unmask (VALUE self, VALUE ridx)
|
|
|
791
817
|
case CA_FLOAT64: { double *q=(double *)p; double vd=(double)v; if (vd OP *q || *q != *q) *q = vd; return self; } \
|
|
792
818
|
case CA_FLOAT32: { float *q=(float *)p; float vf=(float )v; if (vf OP *q || *q != *q) *q = vf; return self; } \
|
|
793
819
|
case CA_INT64: { int64_t *q=(int64_t *)p; if ((int64_t)v OP *q) *q = (int64_t)v; return self; } \
|
|
794
|
-
case CA_INT32: { int32_t *q=(int32_t *)p; if ((int32_t)v OP *q) *q = (int32_t)v; return self; } \
|
|
795
|
-
case CA_INT16: { int16_t *q=(int16_t *)p; if ((int16_t)v OP *q) *q = (int16_t)v; return self; } \
|
|
796
|
-
case CA_INT8: { int8_t *q=(int8_t *)p; if ((int8_t )v OP *q) *q = (int8_t )v; return self; } \
|
|
797
|
-
case CA_UINT64: { uint64_t *q=(uint64_t*)p; if ((uint64_t)v OP *q) *q = (uint64_t)v; return self; } \
|
|
798
|
-
case CA_UINT32: { uint32_t *q=(uint32_t*)p; if ((uint32_t)v OP *q) *q = (uint32_t)v; return self; } \
|
|
799
|
-
case CA_UINT16: { uint16_t *q=(uint16_t*)p; if ((uint16_t)v OP *q) *q = (uint16_t)v; return self; } \
|
|
800
|
-
case CA_UINT8: { uint8_t *q=(uint8_t *)p; if ((uint8_t )v OP *q) *q = (uint8_t )v; return self; } \
|
|
820
|
+
case CA_INT32: { if ( ! (v >= INT32_MIN && v <= INT32_MAX) ) break; int32_t *q=(int32_t *)p; if ((int32_t)v OP *q) *q = (int32_t)v; return self; } \
|
|
821
|
+
case CA_INT16: { if ( ! (v >= INT16_MIN && v <= INT16_MAX) ) break; int16_t *q=(int16_t *)p; if ((int16_t)v OP *q) *q = (int16_t)v; return self; } \
|
|
822
|
+
case CA_INT8: { if ( ! (v >= INT8_MIN && v <= INT8_MAX) ) break; int8_t *q=(int8_t *)p; if ((int8_t )v OP *q) *q = (int8_t )v; return self; } \
|
|
823
|
+
case CA_UINT64: { if ( ! (v >= 0) ) break; uint64_t *q=(uint64_t*)p; if ((uint64_t)v OP *q) *q = (uint64_t)v; return self; } \
|
|
824
|
+
case CA_UINT32: { if ( ! (v >= 0 && v <= (long) UINT32_MAX) ) break; uint32_t *q=(uint32_t*)p; if ((uint32_t)v OP *q) *q = (uint32_t)v; return self; } \
|
|
825
|
+
case CA_UINT16: { if ( ! (v >= 0 && v <= (long) UINT16_MAX) ) break; uint16_t *q=(uint16_t*)p; if ((uint16_t)v OP *q) *q = (uint16_t)v; return self; } \
|
|
826
|
+
case CA_UINT8: { if ( ! (v >= 0 && v <= (long) UINT8_MAX) ) break; uint8_t *q=(uint8_t *)p; if ((uint8_t )v OP *q) *q = (uint8_t )v; return self; } \
|
|
801
827
|
} \
|
|
802
828
|
} \
|
|
803
829
|
} \
|
|
@@ -817,6 +843,10 @@ rb_ca_elem_min (VALUE self, VALUE ridx, VALUE rval)
|
|
|
817
843
|
rb_raise(rb_eCADataTypeError,
|
|
818
844
|
"elem_min requires a numeric array");
|
|
819
845
|
}
|
|
846
|
+
if ( ca_is_complex_type(ca) ) {
|
|
847
|
+
rb_raise(rb_eCADataTypeError,
|
|
848
|
+
"elem_min requires a real array (complex values have no order)");
|
|
849
|
+
}
|
|
820
850
|
|
|
821
851
|
/* Super-hot path: entity + numeric data type + Fixnum/Float rval. */
|
|
822
852
|
ELEM_MINMAX_BODY(<);
|
|
@@ -846,7 +876,7 @@ rb_ca_elem_min (VALUE self, VALUE ridx, VALUE rval)
|
|
|
846
876
|
|
|
847
877
|
cur = from_array ? rb_ca_fetch_index(self, idx) : rb_ca_fetch_addr(self, addr);
|
|
848
878
|
if ( cur == CA_UNDEF ) return self;
|
|
849
|
-
if (
|
|
879
|
+
if ( ca_obj_extremum_replaces(rval, cur, rb_intern("<")) ) {
|
|
850
880
|
if ( from_array ) rb_ca_store_index(self, idx, rval);
|
|
851
881
|
else rb_ca_store_addr(self, addr, rval);
|
|
852
882
|
}
|
|
@@ -873,6 +903,10 @@ rb_ca_elem_max (VALUE self, VALUE ridx, VALUE rval)
|
|
|
873
903
|
rb_raise(rb_eCADataTypeError,
|
|
874
904
|
"elem_max requires a numeric array");
|
|
875
905
|
}
|
|
906
|
+
if ( ca_is_complex_type(ca) ) {
|
|
907
|
+
rb_raise(rb_eCADataTypeError,
|
|
908
|
+
"elem_max requires a real array (complex values have no order)");
|
|
909
|
+
}
|
|
876
910
|
|
|
877
911
|
ELEM_MINMAX_BODY(>);
|
|
878
912
|
|
|
@@ -899,7 +933,7 @@ rb_ca_elem_max (VALUE self, VALUE ridx, VALUE rval)
|
|
|
899
933
|
|
|
900
934
|
cur = from_array ? rb_ca_fetch_index(self, idx) : rb_ca_fetch_addr(self, addr);
|
|
901
935
|
if ( cur == CA_UNDEF ) return self;
|
|
902
|
-
if (
|
|
936
|
+
if ( ca_obj_extremum_replaces(rval, cur, rb_intern(">")) ) {
|
|
903
937
|
if ( from_array ) rb_ca_store_index(self, idx, rval);
|
|
904
938
|
else rb_ca_store_addr(self, addr, rval);
|
|
905
939
|
}
|