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
|
@@ -14,13 +14,15 @@
|
|
|
14
14
|
- a single negative-index normaliser used by all handlers
|
|
15
15
|
- fast paths (POINT / ADDRESS, ndim == argc, all-FIXNUM) at
|
|
16
16
|
the top of the entry point
|
|
17
|
-
- single-character alphabetic Symbols (:a-:z / :A-:Z)
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
- single-character alphabetic Symbols (:a-:z / :A-:Z) are
|
|
18
|
+
reserved and kept free of meaning; the classifier raises
|
|
19
|
+
IndexError when they appear.
|
|
20
20
|
|
|
21
21
|
--------------------------------------------------------------------------- */
|
|
22
22
|
|
|
23
23
|
#include "carray.h"
|
|
24
|
+
#include <math.h>
|
|
25
|
+
#include "carray_internal.h" /* ca_index_in_range_at */
|
|
24
26
|
#include "carray_index_classifier.h"
|
|
25
27
|
|
|
26
28
|
/* Range accessor macros — carray_access.c keeps a private cache
|
|
@@ -85,17 +87,42 @@ typedef struct {
|
|
|
85
87
|
static inline ca_size_t
|
|
86
88
|
ca_classifier_normalize_axis_index (ca_size_t k, ca_size_t dim, int axis, int range_check)
|
|
87
89
|
{
|
|
90
|
+
ca_size_t given = k;
|
|
88
91
|
if ( k < 0 ) {
|
|
89
92
|
k += dim;
|
|
90
93
|
}
|
|
91
94
|
if ( range_check && ( k < 0 || k >= dim ) ) {
|
|
92
|
-
|
|
93
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
94
|
-
axis, (ca_size_t) k, (ca_size_t) (dim - 1));
|
|
95
|
+
ca_index_out_of_range_at(given, dim, axis);
|
|
95
96
|
}
|
|
96
97
|
return k;
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
/* Whether a range picks no cells along an axis of length dim: an exclusive
|
|
101
|
+
range that ends where it starts, or an endless one that starts at the end
|
|
102
|
+
of the axis. `last` has been counted from the end already; `start` has
|
|
103
|
+
not. A range in CArray otherwise always picks a cell -- one ending
|
|
104
|
+
before its start reads backwards. */
|
|
105
|
+
static inline int
|
|
106
|
+
ca_classifier_range_is_empty (ca_size_t start, ca_size_t last, int excl,
|
|
107
|
+
int endless, ca_size_t dim)
|
|
108
|
+
{
|
|
109
|
+
ca_size_t s = ( start < 0 ) ? start + dim : start;
|
|
110
|
+
return endless ? ( s == dim ) : ( excl && s == last );
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* The first index of a run of cells along an axis. A run of no cells may
|
|
114
|
+
start at the end of the axis (position n), as an empty slice at the end
|
|
115
|
+
of a Ruby Array does; a run with cells has to start on one. */
|
|
116
|
+
static inline ca_size_t
|
|
117
|
+
ca_classifier_run_start (ca_size_t idx, ca_size_t n, int axis, int empty)
|
|
118
|
+
{
|
|
119
|
+
ca_size_t i = ( idx < 0 ) ? idx + n : idx;
|
|
120
|
+
if ( i < 0 || i > n || ( ! empty && i == n ) ) {
|
|
121
|
+
ca_index_out_of_range_at(idx, n, axis);
|
|
122
|
+
}
|
|
123
|
+
return i;
|
|
124
|
+
}
|
|
125
|
+
|
|
99
126
|
/* Flat-address normalisation for the `argc == 1, ndim > 1,
|
|
100
127
|
Integer` path. CA_CHECK_INDEX does not carry axis info in its
|
|
101
128
|
message, which is the intended behaviour on the flat path. */
|
|
@@ -108,6 +135,129 @@ ca_classifier_normalize_flat_address (ca_size_t addr, ca_size_t elements, int ra
|
|
|
108
135
|
return addr;
|
|
109
136
|
}
|
|
110
137
|
|
|
138
|
+
NORETURN(static void ca_classifier_invalid_key (VALUE v, int axis));
|
|
139
|
+
static void
|
|
140
|
+
ca_classifier_invalid_key (VALUE v, int axis)
|
|
141
|
+
{
|
|
142
|
+
volatile VALUE s = rb_inspect(v);
|
|
143
|
+
rb_raise(rb_eIndexError,
|
|
144
|
+
"%s: object '%s' is invalid for the index for reference at %i-dim",
|
|
145
|
+
ca_calling_method_name(), StringValueCStr(s), axis);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* An Integer past int64 is past the end of any axis, but has no ca_size_t
|
|
149
|
+
to report through ca_index_out_of_range_at; it is reported as given. */
|
|
150
|
+
NORETURN(static void ca_classifier_key_too_large (VALUE v, const char *where));
|
|
151
|
+
static void
|
|
152
|
+
ca_classifier_key_too_large (VALUE v, const char *where)
|
|
153
|
+
{
|
|
154
|
+
volatile VALUE s = rb_inspect(v);
|
|
155
|
+
rb_raise(rb_eIndexError, "%s: index %s is out of range%s",
|
|
156
|
+
ca_calling_method_name(), StringValueCStr(s), where);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* A key names a position when it holds an integer that fits ca_size_t
|
|
160
|
+
(int64): an Integer of that size, Bignum included (an axis of a view that
|
|
161
|
+
holds no memory can be longer than a Fixnum reaches), or a Float with no
|
|
162
|
+
fraction while it is exact (|v| <= 2**53; past that it cannot tell
|
|
163
|
+
neighbouring integers apart, and a count from `sum` is a Float).
|
|
164
|
+
Returns 1 with the position in *out, 2 for an Integer past int64 (past
|
|
165
|
+
every axis, which is no longer than int64), and 0 for anything else (a
|
|
166
|
+
Float with a fraction or past 2**53, NaN, Inf, a Rational, a String). */
|
|
167
|
+
static int
|
|
168
|
+
ca_classifier_key_position (VALUE v, ca_size_t *out)
|
|
169
|
+
{
|
|
170
|
+
if ( FIXNUM_P(v) ) {
|
|
171
|
+
*out = (ca_size_t) FIX2LONG(v);
|
|
172
|
+
return 1;
|
|
173
|
+
}
|
|
174
|
+
if ( RB_FLOAT_TYPE_P(v) ) {
|
|
175
|
+
double d = RFLOAT_VALUE(v);
|
|
176
|
+
if ( isfinite(d) && d == floor(d) && fabs(d) <= 9007199254740992.0 ) {
|
|
177
|
+
*out = (ca_size_t) d;
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
if ( RB_TYPE_P(v, T_BIGNUM) ) {
|
|
183
|
+
uint64_t mag;
|
|
184
|
+
int sign = rb_integer_pack(v, &mag, 1, sizeof(mag), 0,
|
|
185
|
+
INTEGER_PACK_NATIVE_BYTE_ORDER);
|
|
186
|
+
if ( sign == 2 || sign == -2
|
|
187
|
+
|| ( sign > 0 && mag > (uint64_t) INT64_MAX )
|
|
188
|
+
|| ( sign < 0 && mag > (uint64_t) INT64_MAX + 1 ) ) {
|
|
189
|
+
return 2; /* does not fit int64 */
|
|
190
|
+
}
|
|
191
|
+
*out = ( sign < 0 ) ? (ca_size_t) (0 - mag) : (ca_size_t) mag;
|
|
192
|
+
return 1;
|
|
193
|
+
}
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* A key that has to name a position: a scalar key, or one inside a Range,
|
|
198
|
+
an Array form or a step. `where` follows the value in the out-of-range
|
|
199
|
+
message. */
|
|
200
|
+
static ca_size_t
|
|
201
|
+
ca_classifier_key_int_where (VALUE v, int axis, const char *where)
|
|
202
|
+
{
|
|
203
|
+
ca_size_t k;
|
|
204
|
+
switch ( ca_classifier_key_position(v, &k) ) {
|
|
205
|
+
case 1:
|
|
206
|
+
return k;
|
|
207
|
+
case 2:
|
|
208
|
+
ca_classifier_key_too_large(v, where);
|
|
209
|
+
default:
|
|
210
|
+
ca_classifier_invalid_key(v, axis);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static ca_size_t
|
|
215
|
+
ca_classifier_key_int (VALUE v, int axis)
|
|
216
|
+
{
|
|
217
|
+
char where[32];
|
|
218
|
+
snprintf(where, sizeof(where), " on axis %d", axis);
|
|
219
|
+
return ca_classifier_key_int_where(v, axis, where);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
int
|
|
223
|
+
ca_index_key_is_scalar (VALUE arg)
|
|
224
|
+
{
|
|
225
|
+
return FIXNUM_P(arg) || RB_FLOAT_TYPE_P(arg) || RB_TYPE_P(arg, T_BIGNUM);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* A step: an integer like any key, except that one past int64 is not past
|
|
229
|
+
anything -- it is a step larger than any axis, so it reaches one cell.
|
|
230
|
+
It is read as the largest int64 of its sign, which does the same. */
|
|
231
|
+
static ca_size_t
|
|
232
|
+
ca_classifier_key_step (VALUE v, int axis)
|
|
233
|
+
{
|
|
234
|
+
ca_size_t k;
|
|
235
|
+
if ( ca_classifier_key_position(v, &k) == 2 ) {
|
|
236
|
+
return rb_big_sign(v) ? (ca_size_t) INT64_MAX : (ca_size_t) INT64_MIN;
|
|
237
|
+
}
|
|
238
|
+
return ca_classifier_key_int(v, axis);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* An axis of length 0 has no cells: a range on it reads none when it starts
|
|
242
|
+
at 0 (as `[][0..-1]` does), and is out of range otherwise. Returns 1 when
|
|
243
|
+
the axis was filled in. */
|
|
244
|
+
static int
|
|
245
|
+
ca_classifier_block_on_empty_axis (CAIndexInfo *info, int axis, ca_size_t dim,
|
|
246
|
+
ca_size_t start)
|
|
247
|
+
{
|
|
248
|
+
if ( dim != 0 ) {
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
if ( start != 0 ) {
|
|
252
|
+
ca_index_out_of_range_at(start, dim, axis);
|
|
253
|
+
}
|
|
254
|
+
info->index_type[axis] = CA_IDX_BLOCK;
|
|
255
|
+
info->index[axis].block.start = 0;
|
|
256
|
+
info->index[axis].block.count = 0;
|
|
257
|
+
info->index[axis].block.step = 1;
|
|
258
|
+
return 1;
|
|
259
|
+
}
|
|
260
|
+
|
|
111
261
|
/* -------------------------------------------------------------------- */
|
|
112
262
|
/* Fast paths. */
|
|
113
263
|
|
|
@@ -131,8 +281,8 @@ ca_classifier_try_point_fast_path (ca_classifier_ctx_t *ctx)
|
|
|
131
281
|
for (i = 0; i < ctx->argc; i++) {
|
|
132
282
|
ca_size_t k = FIX2LONG(ctx->argv[i]);
|
|
133
283
|
if ( ctx->info->range_check ) {
|
|
134
|
-
/* Bignum
|
|
135
|
-
|
|
284
|
+
/* Bignum and Float are rejected by FIXNUM_P above; the slow path's
|
|
285
|
+
integer-key branch picks them up so the
|
|
136
286
|
Integer semantics are preserved end-to-end. */
|
|
137
287
|
k = ca_classifier_normalize_axis_index(k, ctx->ca_dim[i], (int) i,
|
|
138
288
|
ctx->info->range_check);
|
|
@@ -162,12 +312,13 @@ ca_classifier_try_address_fast_path (ca_classifier_ctx_t *ctx)
|
|
|
162
312
|
|
|
163
313
|
/* -------------------------------------------------------------------- */
|
|
164
314
|
/* Single-character alphabetic Symbols (`:a`-`:z` / `:A`-`:Z`) are
|
|
165
|
-
reserved
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
315
|
+
reserved: no index form gives them a meaning, and none should
|
|
316
|
+
until one is decided. Raises IndexError saying so, rather than
|
|
317
|
+
the generic "invalid as the index" message. The caller passes
|
|
318
|
+
any Symbol that is not `:_` / `:%`; a non-reserved Symbol
|
|
319
|
+
returns without action. */
|
|
169
320
|
static inline void
|
|
170
|
-
|
|
321
|
+
ca_classifier_check_reserved_symbol (VALUE sym)
|
|
171
322
|
{
|
|
172
323
|
const char *name;
|
|
173
324
|
if ( ! SYMBOL_P(sym) ) return;
|
|
@@ -177,9 +328,8 @@ ca_classifier_check_reserved_contraction_symbol (VALUE sym)
|
|
|
177
328
|
&& ( ( name[0] >= 'a' && name[0] <= 'z' )
|
|
178
329
|
|| ( name[0] >= 'A' && name[0] <= 'Z' ) )
|
|
179
330
|
&& name[0] != '_' /* :_ is iterator marker, handled separately */ ) {
|
|
180
|
-
rb_raise(
|
|
181
|
-
"symbol :%s is reserved
|
|
182
|
-
"(not yet implemented)",
|
|
331
|
+
rb_raise(rb_eIndexError,
|
|
332
|
+
"symbol :%s is reserved",
|
|
183
333
|
name);
|
|
184
334
|
}
|
|
185
335
|
}
|
|
@@ -207,40 +357,38 @@ ca_classifier_axis_from_range (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
207
357
|
iv_end = CA_CLASSIFIER_RANGE_END(arg);
|
|
208
358
|
iv_excl = CA_CLASSIFIER_RANGE_EXCL(arg);
|
|
209
359
|
|
|
210
|
-
start = NIL_P(iv_beg) ? 0 :
|
|
211
|
-
last = NIL_P(iv_end) ? -1 :
|
|
360
|
+
start = NIL_P(iv_beg) ? 0 : ca_classifier_key_int(iv_beg, axis);
|
|
361
|
+
last = NIL_P(iv_end) ? -1 : ca_classifier_key_int(iv_end, axis);
|
|
212
362
|
excl = RTEST(iv_excl);
|
|
213
363
|
|
|
214
|
-
info
|
|
215
|
-
|
|
216
|
-
if ( info->range_check ) {
|
|
217
|
-
/* Inlined CA_CHECK_INDEX_AT so the format string stays
|
|
218
|
-
byte-identical with the surrounding helpers. */
|
|
219
|
-
if ( start < 0 ) start += dim;
|
|
220
|
-
if ( start < 0 || start >= dim ) {
|
|
221
|
-
rb_raise(rb_eIndexError,
|
|
222
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
223
|
-
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
224
|
-
}
|
|
364
|
+
if ( ca_classifier_block_on_empty_axis(info, axis, dim, start) ) {
|
|
365
|
+
return;
|
|
225
366
|
}
|
|
367
|
+
info->index_type[axis] = CA_IDX_BLOCK;
|
|
226
368
|
|
|
227
369
|
if ( last < 0 ) {
|
|
228
370
|
last += dim; /* don't use CA_CHECK_INDEX for excl */
|
|
229
371
|
}
|
|
230
|
-
|
|
372
|
+
/* No cells: an exclusive range that ends where it starts, or an endless
|
|
373
|
+
one that starts at the end of the axis. */
|
|
374
|
+
if ( ca_classifier_range_is_empty(start, last, excl, NIL_P(iv_end), dim) ) {
|
|
375
|
+
if ( info->range_check ) {
|
|
376
|
+
start = ca_classifier_run_start(start, dim, axis, 1);
|
|
377
|
+
}
|
|
231
378
|
info->index[axis].block.start = start;
|
|
232
379
|
info->index[axis].block.count = 0;
|
|
233
380
|
info->index[axis].block.step = 1;
|
|
234
381
|
return;
|
|
235
382
|
}
|
|
383
|
+
if ( info->range_check ) {
|
|
384
|
+
start = ca_index_in_range_at(start, dim, axis);
|
|
385
|
+
}
|
|
236
386
|
if ( excl ) {
|
|
237
387
|
last += ( last >= start ) ? -1 : 1;
|
|
238
388
|
}
|
|
239
389
|
if ( info->range_check ) {
|
|
240
390
|
if ( last < 0 || last >= dim ) {
|
|
241
|
-
|
|
242
|
-
"index %" PRId64 " is out of range (0..%" PRId64 ") at %i-dim",
|
|
243
|
-
(ca_size_t) last, (ca_size_t) (dim - 1), axis);
|
|
391
|
+
ca_index_out_of_range_at(last, dim, axis);
|
|
244
392
|
}
|
|
245
393
|
}
|
|
246
394
|
count = llabs(last - start) + 1;
|
|
@@ -250,80 +398,89 @@ ca_classifier_axis_from_range (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
250
398
|
info->index[axis].block.step = step;
|
|
251
399
|
}
|
|
252
400
|
|
|
253
|
-
|
|
254
|
-
|
|
401
|
+
/* A run of cells from `iv_beg` toward `iv_end` (inclusive unless excl)
|
|
402
|
+
taking every `step`-th: an ArithmeticSequence, or the `[range, step]`
|
|
403
|
+
form. The step says the direction, as it does for Ruby: one that points
|
|
404
|
+
away from the end reads nothing, and an endless run with a negative
|
|
405
|
+
step goes down to the first cell. A begin of nil starts at the end the
|
|
406
|
+
step walks from. */
|
|
255
407
|
static void
|
|
256
|
-
|
|
408
|
+
ca_classifier_block_stepped (ca_classifier_ctx_t *ctx, int axis,
|
|
409
|
+
VALUE iv_beg, VALUE iv_end, int excl, ca_size_t step)
|
|
257
410
|
{
|
|
258
|
-
ca_size_t start, last, count,
|
|
259
|
-
int
|
|
260
|
-
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
261
|
-
rb_arithmetic_sequence_components_t x;
|
|
411
|
+
ca_size_t start, last, count, bound, s;
|
|
412
|
+
int endless = NIL_P(iv_end);
|
|
262
413
|
CAIndexInfo *info = ctx->info;
|
|
263
414
|
ca_size_t dim = ctx->ca_dim[axis];
|
|
264
415
|
|
|
265
|
-
rb_arithmetic_sequence_extract(arg, &x);
|
|
266
|
-
iv_beg = x.begin;
|
|
267
|
-
iv_end = x.end;
|
|
268
|
-
iv_excl = x.exclude_end;
|
|
269
|
-
step = NUM2SIZE(x.step);
|
|
270
|
-
|
|
271
|
-
start = NIL_P(iv_beg) ? 0 : NUM2SIZE(iv_beg);
|
|
272
|
-
last = NIL_P(iv_end) ? -1 : NUM2SIZE(iv_end);
|
|
273
|
-
excl = RTEST(iv_excl);
|
|
274
|
-
|
|
275
416
|
if ( step == 0 ) {
|
|
276
|
-
rb_raise(
|
|
417
|
+
rb_raise(rb_eArgError,
|
|
277
418
|
"step in index equals to 0 in block reference");
|
|
278
419
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
check is deferred, which upstream callers do not expect. */
|
|
286
|
-
if ( start < 0 ) start += dim;
|
|
287
|
-
if ( start < 0 || start >= dim ) {
|
|
288
|
-
rb_raise(rb_eIndexError,
|
|
289
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
290
|
-
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
420
|
+
start = NIL_P(iv_beg) ? ( step < 0 ? dim - 1 : 0 )
|
|
421
|
+
: ca_classifier_key_int(iv_beg, axis);
|
|
422
|
+
last = endless ? ( step < 0 ? 0 : dim - 1 )
|
|
423
|
+
: ca_classifier_key_int(iv_end, axis);
|
|
424
|
+
if ( NIL_P(iv_beg) && dim == 0 ) {
|
|
425
|
+
start = 0;
|
|
291
426
|
}
|
|
292
|
-
|
|
293
|
-
|
|
427
|
+
if ( ca_classifier_block_on_empty_axis(info, axis, dim, start) ) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
info->index_type[axis] = CA_IDX_BLOCK;
|
|
431
|
+
if ( ! endless && last < 0 ) {
|
|
294
432
|
last += dim;
|
|
295
433
|
}
|
|
296
|
-
|
|
297
|
-
|
|
434
|
+
/* CAREFUL: start is range-checked here whatever info->range_check says.
|
|
435
|
+
A run that starts outside the axis would otherwise read as an empty
|
|
436
|
+
region, which upstream callers do not expect. */
|
|
437
|
+
s = ( start < 0 ) ? start + dim : start;
|
|
438
|
+
if ( ( endless && step > 0 && s == dim ) || ( ! endless && excl && s == last ) ) {
|
|
439
|
+
info->index[axis].block.start = ca_classifier_run_start(start, dim, axis, 1);
|
|
298
440
|
info->index[axis].block.count = 0;
|
|
299
441
|
info->index[axis].block.step = 1;
|
|
300
442
|
return;
|
|
301
443
|
}
|
|
302
|
-
|
|
444
|
+
start = ca_index_in_range_at(start, dim, axis);
|
|
445
|
+
if ( excl && ! endless ) {
|
|
303
446
|
last += ( last >= start ) ? -1 : 1;
|
|
304
447
|
}
|
|
305
448
|
if ( last < 0 || last >= dim ) {
|
|
306
|
-
|
|
307
|
-
"index %" PRId64 " is out of range (0..%" PRId64 ") at %i-dim",
|
|
308
|
-
(ca_size_t) last, (ca_size_t) (dim - 1), axis);
|
|
449
|
+
ca_index_out_of_range_at(last, dim, axis);
|
|
309
450
|
}
|
|
310
|
-
if ( (last
|
|
311
|
-
|
|
451
|
+
if ( (last > start && step < 0) || (last < start && step > 0) ) {
|
|
452
|
+
info->index[axis].block.start = start;
|
|
453
|
+
info->index[axis].block.count = 0;
|
|
454
|
+
info->index[axis].block.step = 1;
|
|
455
|
+
return;
|
|
312
456
|
}
|
|
313
|
-
|
|
314
|
-
|
|
457
|
+
/* start and last are both inside the axis, so their distance fits; the
|
|
458
|
+
step is taken by magnitude unsigned, since -step overflows at its
|
|
459
|
+
minimum. (count - 1) * step below is then at most that distance. */
|
|
460
|
+
{
|
|
461
|
+
unsigned long long span = (unsigned long long)
|
|
462
|
+
(last >= start ? last - start : start - last);
|
|
463
|
+
unsigned long long ustep = step < 0 ? 0ULL - (unsigned long long) step
|
|
464
|
+
: (unsigned long long) step;
|
|
465
|
+
count = (ca_size_t) (span / ustep) + 1;
|
|
315
466
|
}
|
|
316
467
|
bound = start + (count - 1) * step;
|
|
317
|
-
|
|
318
|
-
if ( bound < 0 || bound >= dim ) {
|
|
319
|
-
rb_raise(rb_eIndexError,
|
|
320
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
321
|
-
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
322
|
-
}
|
|
468
|
+
bound = ca_index_in_range_at(bound, dim, axis);
|
|
323
469
|
info->index[axis].block.start = start;
|
|
324
470
|
info->index[axis].block.count = count;
|
|
325
471
|
info->index[axis].block.step = step;
|
|
326
472
|
}
|
|
473
|
+
|
|
474
|
+
#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
|
|
475
|
+
/* ArithSeq → BLOCK */
|
|
476
|
+
static void
|
|
477
|
+
ca_classifier_axis_from_arithseq (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
478
|
+
{
|
|
479
|
+
rb_arithmetic_sequence_components_t x;
|
|
480
|
+
rb_arithmetic_sequence_extract(arg, &x);
|
|
481
|
+
ca_classifier_block_stepped(ctx, axis, x.begin, x.end, RTEST(x.exclude_end),
|
|
482
|
+
ca_classifier_key_step(x.step, axis));
|
|
483
|
+
}
|
|
327
484
|
#endif
|
|
328
485
|
|
|
329
486
|
/* T_ARRAY → BLOCK. Accepts [nil] / [Range] / [Integer] (len 1),
|
|
@@ -350,13 +507,9 @@ ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
350
507
|
}
|
|
351
508
|
/* [Integer] */
|
|
352
509
|
{
|
|
353
|
-
ca_size_t
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
rb_raise(rb_eIndexError,
|
|
357
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
358
|
-
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
359
|
-
}
|
|
510
|
+
ca_size_t given = ca_classifier_key_int(a0, axis);
|
|
511
|
+
ca_size_t start = given;
|
|
512
|
+
start = ca_index_in_range_at(start, dim, axis);
|
|
360
513
|
info->index[axis].block.start = start;
|
|
361
514
|
info->index[axis].block.count = 1;
|
|
362
515
|
info->index[axis].block.step = 1;
|
|
@@ -369,75 +522,24 @@ ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
369
522
|
VALUE a1 = rb_ary_entry(arg, 1);
|
|
370
523
|
|
|
371
524
|
if ( NIL_P(a0) ) { /* [nil, step] */
|
|
372
|
-
ca_size_t start = 0,
|
|
373
|
-
step =
|
|
374
|
-
if ( step == 0 ) {
|
|
375
|
-
rb_raise(rb_eRuntimeError,
|
|
376
|
-
"step in index equals to 0 in block reference");
|
|
377
|
-
}
|
|
378
|
-
last = dim - 1;
|
|
379
|
-
count = ( step < 0 ) ? 1 : (last / step + 1);
|
|
380
|
-
bound = start + (count - 1) * step;
|
|
381
|
-
if ( bound < 0 ) bound += dim;
|
|
382
|
-
if ( bound < 0 || bound >= dim ) {
|
|
383
|
-
rb_raise(rb_eIndexError,
|
|
384
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
385
|
-
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
386
|
-
}
|
|
387
|
-
info->index[axis].block.start = start;
|
|
388
|
-
info->index[axis].block.count = count;
|
|
389
|
-
info->index[axis].block.step = step;
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if ( rb_obj_is_kind_of(a0, rb_cRange) ) { /* [Range, step] */
|
|
394
|
-
ca_size_t start, last, count, step, bound;
|
|
395
|
-
int excl;
|
|
396
|
-
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
397
|
-
iv_beg = CA_CLASSIFIER_RANGE_BEG(a0);
|
|
398
|
-
iv_end = CA_CLASSIFIER_RANGE_END(a0);
|
|
399
|
-
iv_excl = CA_CLASSIFIER_RANGE_EXCL(a0);
|
|
400
|
-
start = NIL_P(iv_beg) ? 0 : NUM2SIZE(iv_beg);
|
|
401
|
-
last = NIL_P(iv_end) ? -1 : NUM2SIZE(iv_end);
|
|
402
|
-
excl = RTEST(iv_excl);
|
|
403
|
-
step = NUM2SIZE(a1);
|
|
525
|
+
ca_size_t start = 0, count, step;
|
|
526
|
+
step = ca_classifier_key_step(a1, axis);
|
|
404
527
|
if ( step == 0 ) {
|
|
405
|
-
rb_raise(
|
|
528
|
+
rb_raise(rb_eArgError,
|
|
406
529
|
"step in index equals to 0 in block reference");
|
|
407
530
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
if ( last < 0 ) last += dim;
|
|
415
|
-
if ( excl && start == last ) {
|
|
416
|
-
info->index[axis].block.start = start;
|
|
417
|
-
info->index[axis].block.count = 0;
|
|
418
|
-
info->index[axis].block.step = 1;
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
if ( excl ) {
|
|
422
|
-
last += ( last >= start ) ? -1 : 1;
|
|
423
|
-
}
|
|
424
|
-
if ( last < 0 || last >= dim ) {
|
|
425
|
-
rb_raise(rb_eIndexError,
|
|
426
|
-
"index %" PRId64 " is out of range (0..%" PRId64 ") at %i-dim",
|
|
427
|
-
(ca_size_t) last, (ca_size_t) (dim - 1), axis);
|
|
531
|
+
/* every cell of the axis from the first at that step: none of an
|
|
532
|
+
axis of length 0. A negative step from the first cell reaches only
|
|
533
|
+
it. */
|
|
534
|
+
if ( dim == 0 ) {
|
|
535
|
+
count = 0;
|
|
536
|
+
step = 1;
|
|
428
537
|
}
|
|
429
|
-
if (
|
|
538
|
+
else if ( step < 0 ) {
|
|
430
539
|
count = 1;
|
|
431
540
|
}
|
|
432
541
|
else {
|
|
433
|
-
count =
|
|
434
|
-
}
|
|
435
|
-
bound = start + (count - 1) * step;
|
|
436
|
-
if ( bound < 0 ) bound += dim;
|
|
437
|
-
if ( bound < 0 || bound >= dim ) {
|
|
438
|
-
rb_raise(rb_eIndexError,
|
|
439
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
440
|
-
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
542
|
+
count = (dim - 1) / step + 1;
|
|
441
543
|
}
|
|
442
544
|
info->index[axis].block.start = start;
|
|
443
545
|
info->index[axis].block.count = count;
|
|
@@ -445,23 +547,32 @@ ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
445
547
|
return;
|
|
446
548
|
}
|
|
447
549
|
|
|
550
|
+
if ( rb_obj_is_kind_of(a0, rb_cRange) ) { /* [Range, step] */
|
|
551
|
+
ca_classifier_block_stepped(ctx, axis,
|
|
552
|
+
CA_CLASSIFIER_RANGE_BEG(a0),
|
|
553
|
+
CA_CLASSIFIER_RANGE_END(a0),
|
|
554
|
+
RTEST(CA_CLASSIFIER_RANGE_EXCL(a0)),
|
|
555
|
+
ca_classifier_key_step(a1, axis));
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
448
559
|
/* [start, count] */
|
|
449
560
|
{
|
|
450
561
|
ca_size_t start, count, bound;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
562
|
+
ca_size_t given;
|
|
563
|
+
given = ca_classifier_key_int(a0, axis);
|
|
564
|
+
count = ca_classifier_key_int(a1, axis);
|
|
565
|
+
/* The start counts from the end when negative; the last cell is
|
|
566
|
+
counted from that start and has to be inside as it is. A count
|
|
567
|
+
of 0 may start at the end of the axis. */
|
|
568
|
+
start = ca_classifier_run_start(given, dim, axis, count == 0);
|
|
569
|
+
if ( count > 0 &&
|
|
570
|
+
( __builtin_add_overflow(start, count - 1, &bound) || bound >= dim ) ) {
|
|
456
571
|
rb_raise(rb_eIndexError,
|
|
457
|
-
"
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
if ( bound < 0 || bound >= dim ) {
|
|
462
|
-
rb_raise(rb_eIndexError,
|
|
463
|
-
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
464
|
-
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
572
|
+
"%s: index [%" PRId64 ", %" PRId64 "] is out of range for "
|
|
573
|
+
"length %" PRId64 " on axis %i",
|
|
574
|
+
ca_calling_method_name(), (ca_size_t) given, (ca_size_t) count,
|
|
575
|
+
(ca_size_t) dim, axis);
|
|
465
576
|
}
|
|
466
577
|
info->index[axis].block.start = start;
|
|
467
578
|
info->index[axis].block.count = count;
|
|
@@ -471,26 +582,28 @@ ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
471
582
|
}
|
|
472
583
|
|
|
473
584
|
if ( len == 3 ) { /* [start, count, step] */
|
|
474
|
-
ca_size_t start, count, step, bound;
|
|
475
|
-
|
|
476
|
-
count =
|
|
477
|
-
step =
|
|
585
|
+
ca_size_t given, start, count, step, bound;
|
|
586
|
+
given = ca_classifier_key_int(rb_ary_entry(arg, 0), axis);
|
|
587
|
+
count = ca_classifier_key_int(rb_ary_entry(arg, 1), axis);
|
|
588
|
+
step = ca_classifier_key_step(rb_ary_entry(arg, 2), axis);
|
|
478
589
|
if ( step == 0 ) {
|
|
479
|
-
rb_raise(
|
|
590
|
+
rb_raise(rb_eArgError,
|
|
480
591
|
"step in index equals to 0 in block reference");
|
|
481
592
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
593
|
+
/* The start counts from the end when negative; the last cell is
|
|
594
|
+
counted from that start and has to be inside as it is, not a bound
|
|
595
|
+
that wraps back in from either end. A count of 0 may start at the
|
|
596
|
+
end of the axis. */
|
|
597
|
+
start = ca_classifier_run_start(given, dim, axis, count == 0);
|
|
598
|
+
if ( count > 0 &&
|
|
599
|
+
( __builtin_mul_overflow(count - 1, step, &bound) ||
|
|
600
|
+
__builtin_add_overflow(start, bound, &bound) ||
|
|
601
|
+
bound < 0 || bound >= dim ) ) {
|
|
491
602
|
rb_raise(rb_eIndexError,
|
|
492
|
-
"index
|
|
493
|
-
|
|
603
|
+
"%s: index [%" PRId64 ", %" PRId64 ", %" PRId64 "] is out of "
|
|
604
|
+
"range for length %" PRId64 " on axis %i",
|
|
605
|
+
ca_calling_method_name(), (ca_size_t) given, (ca_size_t) count,
|
|
606
|
+
(ca_size_t) step, (ca_size_t) dim, axis);
|
|
494
607
|
}
|
|
495
608
|
info->index[axis].block.start = start;
|
|
496
609
|
info->index[axis].block.count = count;
|
|
@@ -519,8 +632,8 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
519
632
|
CAIndexInfo *info = ctx->info;
|
|
520
633
|
ca_size_t dim = ctx->ca_dim[axis];
|
|
521
634
|
|
|
522
|
-
if (
|
|
523
|
-
ca_size_t k =
|
|
635
|
+
if ( ca_index_key_is_scalar(arg) ) {
|
|
636
|
+
ca_size_t k = ca_classifier_key_int(arg, axis);
|
|
524
637
|
info->index_type[axis] = CA_IDX_SCALAR;
|
|
525
638
|
if ( info->range_check ) {
|
|
526
639
|
k = ca_classifier_normalize_axis_index(k, dim, axis, info->range_check);
|
|
@@ -563,11 +676,11 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
563
676
|
"symbol :_ (newaxis) is handled at the [] / []= level, "
|
|
564
677
|
"not valid in scan_index");
|
|
565
678
|
}
|
|
566
|
-
|
|
679
|
+
ca_classifier_check_reserved_symbol(arg); /* raises if reserved */
|
|
567
680
|
rb_raise(rb_eIndexError,
|
|
568
|
-
"symbol :%
|
|
681
|
+
"symbol :%"PRIsVALUE" is invalid as the index for slab iterator "
|
|
569
682
|
"(use :> instead)",
|
|
570
|
-
|
|
683
|
+
rb_sym2str(arg));
|
|
571
684
|
}
|
|
572
685
|
if ( rb_obj_is_carray(arg) ) {
|
|
573
686
|
/* CArray (boolean / integer) at an axis position → GRID.
|
|
@@ -584,12 +697,7 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
584
697
|
"(should be boolean or integer)",
|
|
585
698
|
ca_type_name[ci->data_type], axis);
|
|
586
699
|
}
|
|
587
|
-
|
|
588
|
-
VALUE inspect = rb_inspect(arg);
|
|
589
|
-
rb_raise(rb_eIndexError,
|
|
590
|
-
"object '%s' is invalid for the index for reference at %i-dim",
|
|
591
|
-
StringValuePtr(inspect), axis);
|
|
592
|
-
}
|
|
700
|
+
ca_classifier_invalid_key(arg, axis);
|
|
593
701
|
}
|
|
594
702
|
|
|
595
703
|
/* -------------------------------------------------------------------- */
|
|
@@ -599,66 +707,117 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
599
707
|
rubber marker is honoured; a second one falls through to the
|
|
600
708
|
per-axis dispatcher and raises. */
|
|
601
709
|
|
|
602
|
-
|
|
603
|
-
|
|
710
|
+
/* Expand the rubber marker (`false` or `:~`) of a key list for an
|
|
711
|
+
array of ndim axes into as many nils as it stands for, writing the
|
|
712
|
+
list into out (CA_RANK_MAX slots). Returns the new count, or -1 when
|
|
713
|
+
the list has no rubber marker (out is then untouched). Only the first
|
|
714
|
+
marker is honoured; a later one is left for the axis reader to refuse. */
|
|
715
|
+
long
|
|
716
|
+
ca_index_expand_rubber (int ndim, long argc, const VALUE *argv, VALUE *out)
|
|
604
717
|
{
|
|
605
718
|
long i, j;
|
|
606
|
-
long argc = ctx->argc;
|
|
607
|
-
VALUE *argv = ctx->argv;
|
|
608
719
|
int rubber_pos = -1;
|
|
609
|
-
|
|
610
|
-
int rndim;
|
|
720
|
+
int rndim;
|
|
611
721
|
|
|
722
|
+
ca_classifier_sym_cache_init();
|
|
612
723
|
for (i = 0; i < argc; i++) {
|
|
613
724
|
if ( argv[i] == Qfalse || argv[i] == ca_classifier_sym_tilde ) {
|
|
614
|
-
rubber_pos = (int) i;
|
|
615
|
-
/* Only the first rubber marker is honoured; later occurrences fall
|
|
616
|
-
through to the per-axis dispatcher and raise. */
|
|
725
|
+
rubber_pos = (int) i;
|
|
617
726
|
break;
|
|
618
727
|
}
|
|
619
728
|
}
|
|
620
|
-
|
|
621
729
|
if ( rubber_pos < 0 ) {
|
|
622
|
-
|
|
623
|
-
if ( argc != ctx->ca_ndim ) {
|
|
624
|
-
rb_raise(rb_eIndexError,
|
|
625
|
-
"number of indices exceeds the ndim of carray (%i > %i)",
|
|
626
|
-
(int) argc, ctx->ca_ndim);
|
|
627
|
-
}
|
|
628
|
-
return;
|
|
730
|
+
return -1;
|
|
629
731
|
}
|
|
630
|
-
|
|
631
|
-
if ( argc > ctx->ca_ndim + 1 ) {
|
|
732
|
+
if ( argc > ndim + 1 ) {
|
|
632
733
|
rb_raise(rb_eIndexError,
|
|
633
|
-
"index specification exceeds the ndim of carray (%i)",
|
|
634
|
-
ctx->ca_ndim);
|
|
734
|
+
"index specification exceeds the ndim of carray (%i)", ndim);
|
|
635
735
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
* nothing when argc == ndim + 1 (e.g. `[false, 0, 1]` on
|
|
641
|
-
* ndim = 2 collapses to `[0, 1]`). Clamping only at the
|
|
642
|
-
* negative side preserves that path. */
|
|
643
|
-
rndim = ctx->ca_ndim - (int)argc + 1;
|
|
736
|
+
/* CAREFUL: rndim == 0 is a valid outcome -- the rubber consumes nothing
|
|
737
|
+
when argc == ndim + 1 (e.g. `[false, 0, 1]` on ndim = 2 collapses to
|
|
738
|
+
`[0, 1]`). Clamping only at the negative side preserves that path. */
|
|
739
|
+
rndim = ndim - (int) argc + 1;
|
|
644
740
|
if ( rndim < 0 ) rndim = 0;
|
|
645
|
-
expanded_argc = argc - 1 + rndim;
|
|
646
|
-
|
|
647
741
|
j = 0;
|
|
648
742
|
for (i = 0; i < argc; i++) {
|
|
649
743
|
if ( i == rubber_pos ) {
|
|
650
744
|
int k;
|
|
651
745
|
for (k = 0; k < rndim; k++) {
|
|
652
|
-
|
|
746
|
+
out[j++] = Qnil;
|
|
653
747
|
}
|
|
654
748
|
} else {
|
|
655
|
-
|
|
749
|
+
out[j++] = argv[i];
|
|
656
750
|
}
|
|
657
751
|
}
|
|
658
|
-
|
|
752
|
+
return j;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
static void
|
|
756
|
+
ca_classifier_expand_rubber_dim (ca_classifier_ctx_t *ctx)
|
|
757
|
+
{
|
|
758
|
+
long n = ca_index_expand_rubber(ctx->ca_ndim, ctx->argc, ctx->argv,
|
|
759
|
+
ctx->argv_expanded);
|
|
760
|
+
if ( n < 0 ) {
|
|
761
|
+
/* No rubber dim -- validate argc == ndim and pass through. */
|
|
762
|
+
if ( ctx->argc != ctx->ca_ndim ) {
|
|
763
|
+
rb_raise(rb_eIndexError,
|
|
764
|
+
"%i indices given for a carray of ndim %i",
|
|
765
|
+
(int) ctx->argc, ctx->ca_ndim);
|
|
766
|
+
}
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
ctx->argc = n;
|
|
659
770
|
ctx->argv = ctx->argv_expanded;
|
|
660
771
|
}
|
|
661
772
|
|
|
773
|
+
/* Read one key along an axis of length dim, as the indexer reads it when
|
|
774
|
+
the key is not a CArray: an Integer, nil, a Range, an
|
|
775
|
+
ArithmeticSequence or an Array form. Fills *start / *count / *step and
|
|
776
|
+
returns CA_IDX_SCALAR (count 1), CA_IDX_ALL (the whole axis) or
|
|
777
|
+
CA_IDX_BLOCK. Anything else raises IndexError. grid and CASelectAxis
|
|
778
|
+
read their non-CArray keys through this, so a key means the same cells
|
|
779
|
+
whichever view the indexer builds. */
|
|
780
|
+
int
|
|
781
|
+
ca_index_axis_key (VALUE arg, ca_size_t dim, int axis,
|
|
782
|
+
ca_size_t *start, ca_size_t *count, ca_size_t *step)
|
|
783
|
+
{
|
|
784
|
+
ca_classifier_ctx_t ctx;
|
|
785
|
+
CAIndexInfo info;
|
|
786
|
+
ca_size_t dims[CA_RANK_MAX];
|
|
787
|
+
int is_grid = 0;
|
|
788
|
+
|
|
789
|
+
ca_classifier_sym_cache_init();
|
|
790
|
+
if ( axis < 0 || axis >= CA_RANK_MAX ) { /* rank-check: an axis number, not a rank */
|
|
791
|
+
rb_raise(rb_eArgError, "axis %d is out of range", axis);
|
|
792
|
+
}
|
|
793
|
+
dims[axis] = dim;
|
|
794
|
+
ctx.ca_ndim = axis + 1;
|
|
795
|
+
ctx.ca_dim = dims;
|
|
796
|
+
ctx.info = &info;
|
|
797
|
+
info.range_check = 1;
|
|
798
|
+
if ( rb_obj_is_carray(arg) || arg == ca_classifier_sym_gt ) {
|
|
799
|
+
ca_classifier_invalid_key(arg, axis);
|
|
800
|
+
}
|
|
801
|
+
ca_classifier_dispatch_axis_arg(&ctx, axis, arg, &is_grid);
|
|
802
|
+
switch ( info.index_type[axis] ) {
|
|
803
|
+
case CA_IDX_SCALAR:
|
|
804
|
+
*start = info.index[axis].scalar;
|
|
805
|
+
*count = 1;
|
|
806
|
+
*step = 1;
|
|
807
|
+
return CA_IDX_SCALAR;
|
|
808
|
+
case CA_IDX_ALL:
|
|
809
|
+
*start = 0;
|
|
810
|
+
*count = dim;
|
|
811
|
+
*step = 1;
|
|
812
|
+
return CA_IDX_ALL;
|
|
813
|
+
default:
|
|
814
|
+
*start = info.index[axis].block.start;
|
|
815
|
+
*count = info.index[axis].block.count;
|
|
816
|
+
*step = info.index[axis].block.step;
|
|
817
|
+
return CA_IDX_BLOCK;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
662
821
|
/* -------------------------------------------------------------------- */
|
|
663
822
|
/* Final REG decision — walks info->index_type[] and decides
|
|
664
823
|
POINT / BLOCK / ITERATOR / GRID. */
|
|
@@ -718,16 +877,13 @@ ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
|
|
|
718
877
|
return 1;
|
|
719
878
|
}
|
|
720
879
|
|
|
721
|
-
/* T_STRING: "
|
|
880
|
+
/* T_STRING: "field" → MEMBER. */
|
|
722
881
|
if ( TYPE(arg) == T_STRING ) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
info->type = CA_REG_MEMBER;
|
|
729
|
-
info->symbol = ID2SYM(rb_intern(s));
|
|
730
|
-
}
|
|
882
|
+
info->type = CA_REG_MEMBER;
|
|
883
|
+
/* A dynamic Symbol: the collector reclaims it, so indexing with
|
|
884
|
+
strings that name no member does not grow the symbol table. */
|
|
885
|
+
StringValueCStr(arg);
|
|
886
|
+
info->symbol = rb_to_symbol(arg);
|
|
731
887
|
return 1;
|
|
732
888
|
}
|
|
733
889
|
|
|
@@ -744,8 +900,26 @@ ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
|
|
|
744
900
|
return 1;
|
|
745
901
|
}
|
|
746
902
|
if ( ca_is_boolean_type(cs) ) {
|
|
903
|
+
/* A boolean selector of more than one axis states a shape, and has
|
|
904
|
+
to have the array's; a 1-D one picks by position among all the
|
|
905
|
+
cells. */
|
|
906
|
+
if ( cs->ndim > 1 ) {
|
|
907
|
+
int k, same = ( cs->ndim == ctx->ca_ndim );
|
|
908
|
+
for (k = 0; same && k < cs->ndim; k++) {
|
|
909
|
+
same = ( cs->dim[k] == ctx->ca_dim[k] );
|
|
910
|
+
}
|
|
911
|
+
if ( ! same ) {
|
|
912
|
+
volatile VALUE sshape = rb_ary_new(), ashape = rb_ary_new();
|
|
913
|
+
for (k = 0; k < cs->ndim; k++) rb_ary_push(sshape, SIZE2NUM(cs->dim[k]));
|
|
914
|
+
for (k = 0; k < ctx->ca_ndim; k++) rb_ary_push(ashape, SIZE2NUM(ctx->ca_dim[k]));
|
|
915
|
+
rb_raise(rb_eArgError,
|
|
916
|
+
"boolean selector of shape %"PRIsVALUE" for an array of shape "
|
|
917
|
+
"%"PRIsVALUE" (a selector states its shape; use .flatten to "
|
|
918
|
+
"select by position)", sshape, ashape);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
747
921
|
if ( ctx->ca_elements != cs->elements ) {
|
|
748
|
-
rb_raise(
|
|
922
|
+
rb_raise(rb_eArgError,
|
|
749
923
|
"mismatch of # of elements ( %" PRId64 " <=> %" PRId64 " ) "
|
|
750
924
|
"in reference by selection",
|
|
751
925
|
(ca_size_t) cs->elements,
|
|
@@ -761,10 +935,11 @@ ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
|
|
|
761
935
|
ca_type_name[cs->data_type]);
|
|
762
936
|
}
|
|
763
937
|
|
|
764
|
-
/* ndim > 1 with
|
|
765
|
-
fast path; this branch handles Bignum. */
|
|
766
|
-
if ( ctx->ca_ndim > 1
|
|
767
|
-
|
|
938
|
+
/* ndim > 1 with an integer key → ADDRESS. Fixnum was caught by the
|
|
939
|
+
fast path; this branch handles Bignum and Float. */
|
|
940
|
+
if ( ctx->ca_ndim > 1
|
|
941
|
+
&& ca_index_key_is_scalar(arg) ) {
|
|
942
|
+
ca_size_t addr = ca_classifier_key_int_where(arg, 0, "");
|
|
768
943
|
info->type = CA_REG_ADDRESS;
|
|
769
944
|
info->ndim = 1;
|
|
770
945
|
if ( info->range_check ) {
|
|
@@ -826,7 +1001,7 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
|
826
1001
|
/* argv[0] = multi-char Symbol → METHOD_CALL. Single-char
|
|
827
1002
|
specials (:_ / :%) fall through the strlen check and are
|
|
828
1003
|
handled downstream (argc == 1 special / fast paths / main
|
|
829
|
-
loop). Single-char alphabetic reserved
|
|
1004
|
+
loop). Single-char alphabetic reserved Symbols
|
|
830
1005
|
also fall through here and are raised later by the per-axis
|
|
831
1006
|
dispatcher's SYMBOL_P branch. */
|
|
832
1007
|
if ( SYMBOL_P(argv[0]) ) {
|
|
@@ -878,7 +1053,7 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
|
878
1053
|
here would raise on legitimate grid regions. */
|
|
879
1054
|
if ( ! is_grid && ctx.ca_ndim != info->ndim ) {
|
|
880
1055
|
rb_raise(rb_eIndexError,
|
|
881
|
-
"
|
|
1056
|
+
"%i indices given for a carray of ndim %i",
|
|
882
1057
|
info->ndim, ctx.ca_ndim);
|
|
883
1058
|
}
|
|
884
1059
|
|
|
@@ -886,6 +1061,7 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
|
886
1061
|
}
|
|
887
1062
|
}
|
|
888
1063
|
|
|
1064
|
+
#ifdef CARRAY_DEV_BUILD
|
|
889
1065
|
/* -------------------------------------------------------------------- */
|
|
890
1066
|
/* Debug / test surface: CArray._scan_index_v2(dim_array, idx_array)
|
|
891
1067
|
returns a plain [type_int, index_array] pair rather than the
|
|
@@ -911,8 +1087,8 @@ rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
911
1087
|
elements *= dim[i];
|
|
912
1088
|
}
|
|
913
1089
|
|
|
914
|
-
|
|
915
|
-
|
|
1090
|
+
CA_CHECK_RANK_GIVEN(ndim);
|
|
1091
|
+
CA_CHECK_DIM_GIVEN(ndim, dim);
|
|
916
1092
|
|
|
917
1093
|
info.range_check = 1;
|
|
918
1094
|
rb_ca_scan_index_v2(ndim, dim, elements,
|
|
@@ -1001,7 +1177,7 @@ rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1001
1177
|
info.index[i].symbol.spec));
|
|
1002
1178
|
break;
|
|
1003
1179
|
default:
|
|
1004
|
-
rb_raise(
|
|
1180
|
+
rb_raise(rb_eIndexError, "unknown index spec");
|
|
1005
1181
|
}
|
|
1006
1182
|
}
|
|
1007
1183
|
break;
|
|
@@ -1011,11 +1187,14 @@ rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1011
1187
|
|
|
1012
1188
|
return rb_ary_new3(2, INT2NUM(info.type), rindex);
|
|
1013
1189
|
}
|
|
1190
|
+
#endif
|
|
1014
1191
|
|
|
1015
1192
|
void
|
|
1016
1193
|
Init_carray_index_classifier (void)
|
|
1017
1194
|
{
|
|
1018
1195
|
ca_classifier_sym_cache_init();
|
|
1196
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1019
1197
|
rb_define_singleton_method(rb_cCArray, "_scan_index_v2",
|
|
1020
1198
|
rb_ca_s_scan_index_v2, 2);
|
|
1199
|
+
#endif
|
|
1021
1200
|
}
|