carray 3.0.3 → 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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- 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/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
|
@@ -14,13 +14,14 @@
|
|
|
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>
|
|
24
25
|
#include "carray_internal.h" /* ca_index_in_range_at */
|
|
25
26
|
#include "carray_index_classifier.h"
|
|
26
27
|
|
|
@@ -96,6 +97,32 @@ ca_classifier_normalize_axis_index (ca_size_t k, ca_size_t dim, int axis, int ra
|
|
|
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;
|
|
@@ -178,7 +329,7 @@ ca_classifier_check_reserved_contraction_symbol (VALUE sym)
|
|
|
178
329
|
|| ( name[0] >= 'A' && name[0] <= 'Z' ) )
|
|
179
330
|
&& name[0] != '_' /* :_ is iterator marker, handled separately */ ) {
|
|
180
331
|
rb_raise(rb_eIndexError,
|
|
181
|
-
"symbol :%s is reserved
|
|
332
|
+
"symbol :%s is reserved",
|
|
182
333
|
name);
|
|
183
334
|
}
|
|
184
335
|
}
|
|
@@ -206,25 +357,32 @@ ca_classifier_axis_from_range (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
206
357
|
iv_end = CA_CLASSIFIER_RANGE_END(arg);
|
|
207
358
|
iv_excl = CA_CLASSIFIER_RANGE_EXCL(arg);
|
|
208
359
|
|
|
209
|
-
start = NIL_P(iv_beg) ? 0 :
|
|
210
|
-
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);
|
|
211
362
|
excl = RTEST(iv_excl);
|
|
212
363
|
|
|
213
|
-
info
|
|
214
|
-
|
|
215
|
-
if ( info->range_check ) {
|
|
216
|
-
start = ca_index_in_range_at(start, dim, axis);
|
|
364
|
+
if ( ca_classifier_block_on_empty_axis(info, axis, dim, start) ) {
|
|
365
|
+
return;
|
|
217
366
|
}
|
|
367
|
+
info->index_type[axis] = CA_IDX_BLOCK;
|
|
218
368
|
|
|
219
369
|
if ( last < 0 ) {
|
|
220
370
|
last += dim; /* don't use CA_CHECK_INDEX for excl */
|
|
221
371
|
}
|
|
222
|
-
|
|
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
|
+
}
|
|
223
378
|
info->index[axis].block.start = start;
|
|
224
379
|
info->index[axis].block.count = 0;
|
|
225
380
|
info->index[axis].block.step = 1;
|
|
226
381
|
return;
|
|
227
382
|
}
|
|
383
|
+
if ( info->range_check ) {
|
|
384
|
+
start = ca_index_in_range_at(start, dim, axis);
|
|
385
|
+
}
|
|
228
386
|
if ( excl ) {
|
|
229
387
|
last += ( last >= start ) ? -1 : 1;
|
|
230
388
|
}
|
|
@@ -240,63 +398,66 @@ ca_classifier_axis_from_range (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
240
398
|
info->index[axis].block.step = step;
|
|
241
399
|
}
|
|
242
400
|
|
|
243
|
-
|
|
244
|
-
|
|
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. */
|
|
245
407
|
static void
|
|
246
|
-
|
|
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)
|
|
247
410
|
{
|
|
248
|
-
ca_size_t start, last, count,
|
|
249
|
-
int
|
|
250
|
-
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
251
|
-
rb_arithmetic_sequence_components_t x;
|
|
411
|
+
ca_size_t start, last, count, bound, s;
|
|
412
|
+
int endless = NIL_P(iv_end);
|
|
252
413
|
CAIndexInfo *info = ctx->info;
|
|
253
414
|
ca_size_t dim = ctx->ca_dim[axis];
|
|
254
415
|
|
|
255
|
-
rb_arithmetic_sequence_extract(arg, &x);
|
|
256
|
-
iv_beg = x.begin;
|
|
257
|
-
iv_end = x.end;
|
|
258
|
-
iv_excl = x.exclude_end;
|
|
259
|
-
step = NUM2SIZE(x.step);
|
|
260
|
-
|
|
261
|
-
start = NIL_P(iv_beg) ? 0 : NUM2SIZE(iv_beg);
|
|
262
|
-
last = NIL_P(iv_end) ? -1 : NUM2SIZE(iv_end);
|
|
263
|
-
excl = RTEST(iv_excl);
|
|
264
|
-
|
|
265
416
|
if ( step == 0 ) {
|
|
266
417
|
rb_raise(rb_eArgError,
|
|
267
418
|
"step in index equals to 0 in block reference");
|
|
268
419
|
}
|
|
269
|
-
|
|
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;
|
|
426
|
+
}
|
|
427
|
+
if ( ca_classifier_block_on_empty_axis(info, axis, dim, start) ) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
270
430
|
info->index_type[axis] = CA_IDX_BLOCK;
|
|
271
|
-
|
|
272
|
-
/* CAREFUL: always range-check start on the ArithSeq path,
|
|
273
|
-
ignoring info->range_check. An ArithSeq with a negative or
|
|
274
|
-
out-of-range start silently produces an empty region if this
|
|
275
|
-
check is deferred, which upstream callers do not expect. */
|
|
276
|
-
start = ca_index_in_range_at(start, dim, axis);
|
|
277
|
-
|
|
278
|
-
if ( last < 0 ) {
|
|
431
|
+
if ( ! endless && last < 0 ) {
|
|
279
432
|
last += dim;
|
|
280
433
|
}
|
|
281
|
-
|
|
282
|
-
|
|
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);
|
|
283
440
|
info->index[axis].block.count = 0;
|
|
284
441
|
info->index[axis].block.step = 1;
|
|
285
442
|
return;
|
|
286
443
|
}
|
|
287
|
-
|
|
444
|
+
start = ca_index_in_range_at(start, dim, axis);
|
|
445
|
+
if ( excl && ! endless ) {
|
|
288
446
|
last += ( last >= start ) ? -1 : 1;
|
|
289
447
|
}
|
|
290
448
|
if ( last < 0 || last >= dim ) {
|
|
291
449
|
ca_index_out_of_range_at(last, dim, axis);
|
|
292
450
|
}
|
|
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;
|
|
456
|
+
}
|
|
293
457
|
/* start and last are both inside the axis, so their distance fits; the
|
|
294
458
|
step is taken by magnitude unsigned, since -step overflows at its
|
|
295
459
|
minimum. (count - 1) * step below is then at most that distance. */
|
|
296
|
-
|
|
297
|
-
count = 1;
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
460
|
+
{
|
|
300
461
|
unsigned long long span = (unsigned long long)
|
|
301
462
|
(last >= start ? last - start : start - last);
|
|
302
463
|
unsigned long long ustep = step < 0 ? 0ULL - (unsigned long long) step
|
|
@@ -309,6 +470,17 @@ ca_classifier_axis_from_arithseq (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
309
470
|
info->index[axis].block.count = count;
|
|
310
471
|
info->index[axis].block.step = step;
|
|
311
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
|
+
}
|
|
312
484
|
#endif
|
|
313
485
|
|
|
314
486
|
/* T_ARRAY → BLOCK. Accepts [nil] / [Range] / [Integer] (len 1),
|
|
@@ -335,7 +507,7 @@ ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
335
507
|
}
|
|
336
508
|
/* [Integer] */
|
|
337
509
|
{
|
|
338
|
-
ca_size_t given =
|
|
510
|
+
ca_size_t given = ca_classifier_key_int(a0, axis);
|
|
339
511
|
ca_size_t start = given;
|
|
340
512
|
start = ca_index_in_range_at(start, dim, axis);
|
|
341
513
|
info->index[axis].block.start = start;
|
|
@@ -350,83 +522,58 @@ ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
350
522
|
VALUE a1 = rb_ary_entry(arg, 1);
|
|
351
523
|
|
|
352
524
|
if ( NIL_P(a0) ) { /* [nil, step] */
|
|
353
|
-
ca_size_t start = 0,
|
|
354
|
-
step =
|
|
355
|
-
if ( step == 0 ) {
|
|
356
|
-
rb_raise(rb_eArgError,
|
|
357
|
-
"step in index equals to 0 in block reference");
|
|
358
|
-
}
|
|
359
|
-
last = dim - 1;
|
|
360
|
-
count = ( step < 0 ) ? 1 : (last / step + 1);
|
|
361
|
-
bound = start + (count - 1) * step;
|
|
362
|
-
bound = ca_index_in_range_at(bound, dim, axis);
|
|
363
|
-
info->index[axis].block.start = start;
|
|
364
|
-
info->index[axis].block.count = count;
|
|
365
|
-
info->index[axis].block.step = step;
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
if ( rb_obj_is_kind_of(a0, rb_cRange) ) { /* [Range, step] */
|
|
370
|
-
ca_size_t start, last, count, step, bound;
|
|
371
|
-
int excl;
|
|
372
|
-
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
373
|
-
iv_beg = CA_CLASSIFIER_RANGE_BEG(a0);
|
|
374
|
-
iv_end = CA_CLASSIFIER_RANGE_END(a0);
|
|
375
|
-
iv_excl = CA_CLASSIFIER_RANGE_EXCL(a0);
|
|
376
|
-
start = NIL_P(iv_beg) ? 0 : NUM2SIZE(iv_beg);
|
|
377
|
-
last = NIL_P(iv_end) ? -1 : NUM2SIZE(iv_end);
|
|
378
|
-
excl = RTEST(iv_excl);
|
|
379
|
-
step = NUM2SIZE(a1);
|
|
525
|
+
ca_size_t start = 0, count, step;
|
|
526
|
+
step = ca_classifier_key_step(a1, axis);
|
|
380
527
|
if ( step == 0 ) {
|
|
381
528
|
rb_raise(rb_eArgError,
|
|
382
529
|
"step in index equals to 0 in block reference");
|
|
383
530
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
if ( excl ) {
|
|
393
|
-
last += ( last >= start ) ? -1 : 1;
|
|
394
|
-
}
|
|
395
|
-
if ( last < 0 || last >= dim ) {
|
|
396
|
-
ca_index_out_of_range_at(last, dim, 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;
|
|
397
537
|
}
|
|
398
|
-
if (
|
|
538
|
+
else if ( step < 0 ) {
|
|
399
539
|
count = 1;
|
|
400
540
|
}
|
|
401
541
|
else {
|
|
402
|
-
|
|
403
|
-
(last >= start ? last - start : start - last);
|
|
404
|
-
unsigned long long ustep = step < 0 ? 0ULL - (unsigned long long) step
|
|
405
|
-
: (unsigned long long) step;
|
|
406
|
-
count = (ca_size_t) (span / ustep) + 1;
|
|
542
|
+
count = (dim - 1) / step + 1;
|
|
407
543
|
}
|
|
408
|
-
bound = start + (count - 1) * step;
|
|
409
|
-
bound = ca_index_in_range_at(bound, dim, axis);
|
|
410
544
|
info->index[axis].block.start = start;
|
|
411
545
|
info->index[axis].block.count = count;
|
|
412
546
|
info->index[axis].block.step = step;
|
|
413
547
|
return;
|
|
414
548
|
}
|
|
415
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
|
+
|
|
416
559
|
/* [start, count] */
|
|
417
560
|
{
|
|
418
561
|
ca_size_t start, count, bound;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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 ) ) {
|
|
422
571
|
rb_raise(rb_eIndexError,
|
|
423
572
|
"%s: index [%" PRId64 ", %" PRId64 "] is out of range for "
|
|
424
573
|
"length %" PRId64 " on axis %i",
|
|
425
|
-
ca_calling_method_name(), (ca_size_t)
|
|
574
|
+
ca_calling_method_name(), (ca_size_t) given, (ca_size_t) count,
|
|
426
575
|
(ca_size_t) dim, axis);
|
|
427
576
|
}
|
|
428
|
-
start = ca_index_in_range_at(start, dim, axis);
|
|
429
|
-
bound = ca_index_in_range_at(bound, dim, axis);
|
|
430
577
|
info->index[axis].block.start = start;
|
|
431
578
|
info->index[axis].block.count = count;
|
|
432
579
|
info->index[axis].block.step = 1;
|
|
@@ -435,26 +582,29 @@ ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
|
435
582
|
}
|
|
436
583
|
|
|
437
584
|
if ( len == 3 ) { /* [start, count, step] */
|
|
438
|
-
ca_size_t start, count, step, bound;
|
|
439
|
-
|
|
440
|
-
count =
|
|
441
|
-
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);
|
|
442
589
|
if ( step == 0 ) {
|
|
443
590
|
rb_raise(rb_eArgError,
|
|
444
591
|
"step in index equals to 0 in block reference");
|
|
445
592
|
}
|
|
446
|
-
/*
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
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 ) ) {
|
|
450
602
|
rb_raise(rb_eIndexError,
|
|
451
603
|
"%s: index [%" PRId64 ", %" PRId64 ", %" PRId64 "] is out of "
|
|
452
604
|
"range for length %" PRId64 " on axis %i",
|
|
453
|
-
ca_calling_method_name(), (ca_size_t)
|
|
605
|
+
ca_calling_method_name(), (ca_size_t) given, (ca_size_t) count,
|
|
454
606
|
(ca_size_t) step, (ca_size_t) dim, axis);
|
|
455
607
|
}
|
|
456
|
-
start = ca_index_in_range_at(start, dim, axis);
|
|
457
|
-
bound = ca_index_in_range_at(bound, dim, axis);
|
|
458
608
|
info->index[axis].block.start = start;
|
|
459
609
|
info->index[axis].block.count = count;
|
|
460
610
|
info->index[axis].block.step = step;
|
|
@@ -482,8 +632,8 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
482
632
|
CAIndexInfo *info = ctx->info;
|
|
483
633
|
ca_size_t dim = ctx->ca_dim[axis];
|
|
484
634
|
|
|
485
|
-
if (
|
|
486
|
-
ca_size_t k =
|
|
635
|
+
if ( ca_index_key_is_scalar(arg) ) {
|
|
636
|
+
ca_size_t k = ca_classifier_key_int(arg, axis);
|
|
487
637
|
info->index_type[axis] = CA_IDX_SCALAR;
|
|
488
638
|
if ( info->range_check ) {
|
|
489
639
|
k = ca_classifier_normalize_axis_index(k, dim, axis, info->range_check);
|
|
@@ -526,7 +676,7 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
526
676
|
"symbol :_ (newaxis) is handled at the [] / []= level, "
|
|
527
677
|
"not valid in scan_index");
|
|
528
678
|
}
|
|
529
|
-
|
|
679
|
+
ca_classifier_check_reserved_symbol(arg); /* raises if reserved */
|
|
530
680
|
rb_raise(rb_eIndexError,
|
|
531
681
|
"symbol :%"PRIsVALUE" is invalid as the index for slab iterator "
|
|
532
682
|
"(use :> instead)",
|
|
@@ -547,12 +697,7 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
547
697
|
"(should be boolean or integer)",
|
|
548
698
|
ca_type_name[ci->data_type], axis);
|
|
549
699
|
}
|
|
550
|
-
|
|
551
|
-
VALUE inspect = rb_inspect(arg);
|
|
552
|
-
rb_raise(rb_eIndexError,
|
|
553
|
-
"object '%s' is invalid for the index for reference at %i-dim",
|
|
554
|
-
StringValuePtr(inspect), axis);
|
|
555
|
-
}
|
|
700
|
+
ca_classifier_invalid_key(arg, axis);
|
|
556
701
|
}
|
|
557
702
|
|
|
558
703
|
/* -------------------------------------------------------------------- */
|
|
@@ -562,66 +707,117 @@ ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
|
562
707
|
rubber marker is honoured; a second one falls through to the
|
|
563
708
|
per-axis dispatcher and raises. */
|
|
564
709
|
|
|
565
|
-
|
|
566
|
-
|
|
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)
|
|
567
717
|
{
|
|
568
718
|
long i, j;
|
|
569
|
-
long argc = ctx->argc;
|
|
570
|
-
VALUE *argv = ctx->argv;
|
|
571
719
|
int rubber_pos = -1;
|
|
572
|
-
|
|
573
|
-
int rndim;
|
|
720
|
+
int rndim;
|
|
574
721
|
|
|
722
|
+
ca_classifier_sym_cache_init();
|
|
575
723
|
for (i = 0; i < argc; i++) {
|
|
576
724
|
if ( argv[i] == Qfalse || argv[i] == ca_classifier_sym_tilde ) {
|
|
577
|
-
rubber_pos = (int) i;
|
|
578
|
-
/* Only the first rubber marker is honoured; later occurrences fall
|
|
579
|
-
through to the per-axis dispatcher and raise. */
|
|
725
|
+
rubber_pos = (int) i;
|
|
580
726
|
break;
|
|
581
727
|
}
|
|
582
728
|
}
|
|
583
|
-
|
|
584
729
|
if ( rubber_pos < 0 ) {
|
|
585
|
-
|
|
586
|
-
if ( argc != ctx->ca_ndim ) {
|
|
587
|
-
rb_raise(rb_eIndexError,
|
|
588
|
-
"%i indices given for a carray of ndim %i",
|
|
589
|
-
(int) argc, ctx->ca_ndim);
|
|
590
|
-
}
|
|
591
|
-
return;
|
|
730
|
+
return -1;
|
|
592
731
|
}
|
|
593
|
-
|
|
594
|
-
if ( argc > ctx->ca_ndim + 1 ) {
|
|
732
|
+
if ( argc > ndim + 1 ) {
|
|
595
733
|
rb_raise(rb_eIndexError,
|
|
596
|
-
"index specification exceeds the ndim of carray (%i)",
|
|
597
|
-
ctx->ca_ndim);
|
|
734
|
+
"index specification exceeds the ndim of carray (%i)", ndim);
|
|
598
735
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
* nothing when argc == ndim + 1 (e.g. `[false, 0, 1]` on
|
|
604
|
-
* ndim = 2 collapses to `[0, 1]`). Clamping only at the
|
|
605
|
-
* negative side preserves that path. */
|
|
606
|
-
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;
|
|
607
740
|
if ( rndim < 0 ) rndim = 0;
|
|
608
|
-
expanded_argc = argc - 1 + rndim;
|
|
609
|
-
|
|
610
741
|
j = 0;
|
|
611
742
|
for (i = 0; i < argc; i++) {
|
|
612
743
|
if ( i == rubber_pos ) {
|
|
613
744
|
int k;
|
|
614
745
|
for (k = 0; k < rndim; k++) {
|
|
615
|
-
|
|
746
|
+
out[j++] = Qnil;
|
|
616
747
|
}
|
|
617
748
|
} else {
|
|
618
|
-
|
|
749
|
+
out[j++] = argv[i];
|
|
619
750
|
}
|
|
620
751
|
}
|
|
621
|
-
|
|
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;
|
|
622
770
|
ctx->argv = ctx->argv_expanded;
|
|
623
771
|
}
|
|
624
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
|
+
|
|
625
821
|
/* -------------------------------------------------------------------- */
|
|
626
822
|
/* Final REG decision — walks info->index_type[] and decides
|
|
627
823
|
POINT / BLOCK / ITERATOR / GRID. */
|
|
@@ -681,16 +877,13 @@ ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
|
|
|
681
877
|
return 1;
|
|
682
878
|
}
|
|
683
879
|
|
|
684
|
-
/* T_STRING: "
|
|
880
|
+
/* T_STRING: "field" → MEMBER. */
|
|
685
881
|
if ( TYPE(arg) == T_STRING ) {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
info->type = CA_REG_MEMBER;
|
|
692
|
-
info->symbol = ID2SYM(rb_intern(s));
|
|
693
|
-
}
|
|
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);
|
|
694
887
|
return 1;
|
|
695
888
|
}
|
|
696
889
|
|
|
@@ -707,6 +900,24 @@ ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
|
|
|
707
900
|
return 1;
|
|
708
901
|
}
|
|
709
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
|
+
}
|
|
710
921
|
if ( ctx->ca_elements != cs->elements ) {
|
|
711
922
|
rb_raise(rb_eArgError,
|
|
712
923
|
"mismatch of # of elements ( %" PRId64 " <=> %" PRId64 " ) "
|
|
@@ -724,10 +935,11 @@ ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
|
|
|
724
935
|
ca_type_name[cs->data_type]);
|
|
725
936
|
}
|
|
726
937
|
|
|
727
|
-
/* ndim > 1 with
|
|
728
|
-
fast path; this branch handles Bignum. */
|
|
729
|
-
if ( ctx->ca_ndim > 1
|
|
730
|
-
|
|
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, "");
|
|
731
943
|
info->type = CA_REG_ADDRESS;
|
|
732
944
|
info->ndim = 1;
|
|
733
945
|
if ( info->range_check ) {
|
|
@@ -789,7 +1001,7 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
|
789
1001
|
/* argv[0] = multi-char Symbol → METHOD_CALL. Single-char
|
|
790
1002
|
specials (:_ / :%) fall through the strlen check and are
|
|
791
1003
|
handled downstream (argc == 1 special / fast paths / main
|
|
792
|
-
loop). Single-char alphabetic reserved
|
|
1004
|
+
loop). Single-char alphabetic reserved Symbols
|
|
793
1005
|
also fall through here and are raised later by the per-axis
|
|
794
1006
|
dispatcher's SYMBOL_P branch. */
|
|
795
1007
|
if ( SYMBOL_P(argv[0]) ) {
|
|
@@ -875,8 +1087,8 @@ rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
875
1087
|
elements *= dim[i];
|
|
876
1088
|
}
|
|
877
1089
|
|
|
878
|
-
|
|
879
|
-
|
|
1090
|
+
CA_CHECK_RANK_GIVEN(ndim);
|
|
1091
|
+
CA_CHECK_DIM_GIVEN(ndim, dim);
|
|
880
1092
|
|
|
881
1093
|
info.range_check = 1;
|
|
882
1094
|
rb_ca_scan_index_v2(ndim, dim, elements,
|