carray 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +5 -25
- data/CHANGELOG.md +16 -0
- data/LICENSE +1 -1
- data/NEWS.md +3 -0
- data/README.md +128 -44
- data/carray.gemspec +22 -24
- data/ext/ca_array_pool.c +91 -0
- data/ext/ca_axis_descriptor.h +186 -0
- data/ext/ca_axis_dispatch.c +924 -0
- data/ext/ca_axis_group.c +1208 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +125 -0
- data/ext/ca_binop_dispatch.h +159 -0
- data/ext/ca_categorical_iterator.c +1375 -0
- data/ext/ca_compare.c +94 -0
- data/ext/ca_compare.h +26 -0
- data/ext/ca_composite_dispatch.c +414 -0
- data/ext/ca_composite_dispatch.h +116 -0
- data/ext/ca_for_buffer.h +96 -0
- data/ext/ca_for_each_element.h +241 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4321 -0
- data/ext/ca_kernel_iterator.h +2603 -0
- data/ext/ca_moncmp_dispatch.c +37 -0
- data/ext/ca_moncmp_dispatch.h +62 -0
- data/ext/ca_monop_dispatch.c +200 -0
- data/ext/ca_monop_dispatch.h +235 -0
- data/ext/ca_obj_array.c +355 -359
- data/ext/ca_obj_bincmp.c +809 -0
- data/ext/ca_obj_binop.c +892 -0
- data/ext/ca_obj_bitarray.c +369 -164
- data/ext/ca_obj_bitfield.c +294 -234
- data/ext/ca_obj_block.c +189 -711
- data/ext/ca_obj_byte_swap.c +766 -0
- data/ext/ca_obj_const_string.c +965 -0
- data/ext/ca_obj_face.c +670 -0
- data/ext/ca_obj_face.h +247 -0
- data/ext/ca_obj_fake.c +228 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +306 -0
- data/ext/ca_obj_grid.c +858 -440
- data/ext/ca_obj_meld.c +1034 -0
- data/ext/ca_obj_moncmp.c +569 -0
- data/ext/ca_obj_monop.c +1111 -0
- data/ext/ca_obj_object.c +774 -298
- data/ext/ca_obj_record.c +468 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +569 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +616 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1296 -0
- data/ext/ca_obj_shift.c +230 -792
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2501 -0
- data/ext/ca_obj_string.c +268 -0
- data/ext/ca_obj_tile.c +614 -0
- data/ext/ca_obj_time.c +546 -0
- data/ext/ca_obj_timedelta.c +435 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +746 -0
- data/ext/ca_obj_unbound_repeat.c +208 -241
- data/ext/ca_obj_window.c +1131 -563
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_ipower.c +319 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +430 -0
- data/ext/ca_sweep_engine.h +157 -0
- data/ext/ca_transform_common.c +228 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +795 -402
- data/ext/carray_access.c +831 -711
- data/ext/carray_attribute.c +98 -330
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +283 -0
- data/ext/carray_call_cfunc.c +1360 -828
- data/ext/carray_call_cfunc.h +160 -0
- data/ext/carray_cast.c +1212 -301
- data/ext/carray_cast_func.rb +81 -40
- data/ext/carray_class.c +53 -63
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +350 -346
- data/ext/carray_copy.c +156 -268
- data/ext/carray_core.c +1342 -199
- data/ext/carray_count.c +312 -0
- data/ext/carray_data_type.c +43 -19
- data/ext/carray_element.c +585 -213
- data/ext/carray_factorize.c +2542 -0
- data/ext/carray_generate.c +230 -559
- data/ext/carray_histogram.c +490 -0
- data/ext/carray_hold.c +228 -0
- data/ext/carray_index_classifier.c +1035 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +120 -0
- data/ext/carray_kernels_bincmp.c +4445 -0
- data/ext/carray_kernels_binop.c +10979 -0
- data/ext/carray_kernels_init.c +36 -0
- data/ext/carray_kernels_map.c +3466 -0
- data/ext/carray_kernels_moncmp.c +2096 -0
- data/ext/carray_kernels_monop.c +18312 -0
- data/ext/carray_kernels_reduce_aggregate.c +25836 -0
- data/ext/carray_kernels_reduce_boolean.c +329 -0
- data/ext/carray_kernels_reduce_cumulative.c +14592 -0
- data/ext/carray_kernels_reduce_extreme.c +16947 -0
- data/ext/carray_kernels_reduce_variance.c +3909 -0
- data/ext/carray_kernels_scan.c +3692 -0
- data/ext/carray_kernels_search.c +32137 -0
- data/ext/carray_kernels_sort.c +10625 -0
- data/ext/carray_kernels_triop.c +1391 -0
- data/ext/carray_lazy.c +567 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +848 -154
- data/ext/carray_math_kernel.h +120 -0
- data/ext/carray_mathfunc.c +10 -241
- data/ext/carray_median_percentile.c +1257 -0
- data/ext/carray_memory_view.c +1625 -0
- data/ext/carray_operator.c +1526 -318
- data/ext/carray_order.c +664 -1394
- data/ext/carray_partition.c +416 -0
- data/ext/carray_random.c +518 -0
- data/ext/carray_scatter.c +357 -0
- data/ext/carray_slab.c +1219 -0
- data/ext/carray_slab.h +84 -0
- data/ext/carray_sort.c +829 -0
- data/ext/carray_sort_kernel.c +620 -0
- data/ext/carray_struct.c +695 -0
- data/ext/carray_test.c +343 -229
- data/ext/carray_undef.c +34 -17
- data/ext/carray_utils.c +175 -74
- data/ext/extconf.rb +216 -55
- data/ext/mk_call_cfunc.rb +480 -0
- data/ext/mkkernel.rb +8842 -0
- data/ext/ruby_carray.c +202 -101
- data/ext/version.h +4 -14
- data/ext/version.rb +5 -13
- data/lib/carray/arrow_tensor.rb +401 -0
- data/lib/carray/attribute.rb +166 -0
- data/lib/carray/autoload_carray.rb +220 -0
- data/lib/carray/autoload_method_extension.rb +44 -0
- data/lib/carray/axis_group.rb +711 -0
- data/lib/carray/basics.rb +481 -0
- data/lib/carray/bincount_nd.rb +358 -0
- data/lib/carray/block_iterator.rb +604 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1062 -0
- data/lib/carray/complex.rb +150 -0
- data/lib/carray/conditional.rb +216 -0
- data/lib/carray/const_string.rb +228 -0
- data/lib/carray/construct.rb +139 -328
- data/lib/carray/core_extensions.rb +240 -0
- data/lib/carray/data_type_extension.rb +233 -0
- data/lib/carray/fixlen_string.rb +95 -0
- data/lib/carray/frame/concat.rb +132 -0
- data/lib/carray/frame/convert.rb +95 -0
- data/lib/carray/frame/csv_parser.rb +211 -0
- data/lib/carray/frame/frame.rb +649 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +164 -0
- data/lib/carray/frame/join.rb +248 -0
- data/lib/carray/frame/records.rb +99 -0
- data/lib/carray/frame/sort.rb +113 -0
- data/lib/carray/frame/verbs.rb +299 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -20
- data/lib/carray/iterator.rb +57 -349
- data/lib/carray/lazy.rb +889 -0
- data/lib/carray/mask_gap_fill.rb +200 -0
- data/lib/carray/math.rb +78 -342
- data/lib/carray/meld_reduce.rb +289 -0
- data/lib/carray/methods/align_addr.rb +116 -0
- data/lib/carray/methods/bin.rb +128 -0
- data/lib/carray/methods/bincount.rb +87 -0
- data/lib/carray/methods/bit_string.rb +92 -0
- data/lib/carray/methods/broadcast.rb +63 -0
- data/lib/carray/methods/choose.rb +39 -0
- data/lib/carray/methods/composition.rb +280 -0
- data/lib/carray/methods/gather_nd.rb +206 -0
- data/lib/carray/methods/index.rb +39 -0
- data/lib/carray/methods/insert_block.rb +99 -0
- data/lib/carray/methods/is_in.rb +141 -0
- data/lib/carray/methods/join.rb +90 -0
- data/lib/carray/methods/locate_addr.rb +47 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +91 -0
- data/lib/carray/methods/mode.rb +126 -0
- data/lib/carray/methods/nunique.rb +46 -0
- data/lib/carray/methods/resize.rb +56 -0
- data/lib/carray/methods/snap.rb +156 -0
- data/lib/carray/methods/string_format.rb +57 -0
- data/lib/carray/methods/unique.rb +47 -0
- data/lib/carray/methods/value_counts.rb +71 -0
- data/lib/carray/mkmf.rb +124 -101
- data/lib/carray/runtime.rb +108 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +292 -0
- data/lib/carray/stack.rb +291 -0
- data/lib/carray/string.rb +56 -180
- data/lib/carray/string_operation_extension.rb +289 -0
- data/lib/carray/struct.rb +335 -323
- data/lib/carray/struct_builder.rb +697 -0
- data/lib/carray/table.rb +41 -2
- data/lib/carray/time.rb +2255 -38
- data/lib/carray/window_iterator.rb +655 -0
- data/lib/carray.rb +55 -57
- metadata +163 -130
- data/Rakefile +0 -51
- data/TODO.md +0 -18
- data/ext/ca_iter_block.c +0 -257
- data/ext/ca_iter_dimension.c +0 -299
- data/ext/ca_iter_window.c +0 -214
- data/ext/ca_obj_mapping.c +0 -644
- data/ext/carray_iterator.c +0 -641
- data/ext/carray_math.rb +0 -850
- data/ext/carray_numeric.c +0 -259
- data/ext/carray_sort_addr.c +0 -254
- data/ext/carray_stat.c +0 -2100
- data/ext/carray_stat_proc.rb +0 -1999
- data/ext/mkmath.rb +0 -741
- data/ext/ruby_ccomplex.c +0 -509
- data/ext/ruby_float_func.c +0 -86
- data/lib/carray/array.rb +0 -8
- data/lib/carray/autoload/autoload_base.rb +0 -19
- data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
- data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
- data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
- data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
- data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
- data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
- data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
- data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
- data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
- data/lib/carray/autoload/autoload_gem_random.rb +0 -8
- data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
- data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
- data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
- data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
- data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
- data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
- data/lib/carray/autoload/autoload_object_link.rb +0 -1
- data/lib/carray/autoload/autoload_object_pack.rb +0 -2
- data/lib/carray/autoload.rb +0 -141
- data/lib/carray/basic.rb +0 -191
- data/lib/carray/broadcast.rb +0 -101
- data/lib/carray/compose.rb +0 -315
- data/lib/carray/convert.rb +0 -115
- data/lib/carray/info.rb +0 -110
- data/lib/carray/io/imagemagick.rb +0 -235
- data/lib/carray/mask.rb +0 -102
- data/lib/carray/math/histogram.rb +0 -177
- data/lib/carray/math/recurrence.rb +0 -93
- data/lib/carray/object/ca_obj_iterator.rb +0 -50
- data/lib/carray/object/ca_obj_link.rb +0 -50
- data/lib/carray/object/ca_obj_pack.rb +0 -99
- data/lib/carray/obsolete.rb +0 -256
- data/lib/carray/ordering.rb +0 -181
- data/lib/carray/testing.rb +0 -51
- data/lib/carray/transform.rb +0 -109
- data/misc/Methods.ja.md +0 -182
- data/misc/NOTE +0 -51
- data/spec/Classes/CABitfield_spec.rb +0 -58
- data/spec/Classes/CABlockIterator_spec.rb +0 -114
- data/spec/Classes/CABlock_spec.rb +0 -205
- data/spec/Classes/CAField_spec.rb +0 -39
- data/spec/Classes/CAGrid_spec.rb +0 -75
- data/spec/Classes/CAMap_spec.rb +0 -0
- data/spec/Classes/CAMapping_spec.rb +0 -105
- data/spec/Classes/CAObject_attribute_spec.rb +0 -33
- data/spec/Classes/CAObject_spec.rb +0 -33
- data/spec/Classes/CARefer_spec.rb +0 -93
- data/spec/Classes/CARepeat_spec.rb +0 -65
- data/spec/Classes/CASelect_spec.rb +0 -22
- data/spec/Classes/CAShift_spec.rb +0 -16
- data/spec/Classes/CAStruct_spec.rb +0 -71
- data/spec/Classes/CATranspose_spec.rb +0 -60
- data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
- data/spec/Classes/CAWindow_spec.rb +0 -54
- data/spec/Classes/CAWrap_spec.rb +0 -8
- data/spec/Classes/CArray_spec.rb +0 -184
- data/spec/Classes/CScalar_spec.rb +0 -55
- data/spec/Classes/ex1.rb +0 -46
- data/spec/Features/feature_130_spec.rb +0 -19
- data/spec/Features/feature_attributes_spec.rb +0 -280
- data/spec/Features/feature_boolean_spec.rb +0 -98
- data/spec/Features/feature_broadcast.rb +0 -116
- data/spec/Features/feature_cast_function.rb +0 -19
- data/spec/Features/feature_cast_spec.rb +0 -33
- data/spec/Features/feature_class_spec.rb +0 -84
- data/spec/Features/feature_complex_spec.rb +0 -42
- data/spec/Features/feature_composite_spec.rb +0 -124
- data/spec/Features/feature_convert_spec.rb +0 -46
- data/spec/Features/feature_copy_spec.rb +0 -123
- data/spec/Features/feature_creation_spec.rb +0 -84
- data/spec/Features/feature_element_spec.rb +0 -144
- data/spec/Features/feature_extream_spec.rb +0 -54
- data/spec/Features/feature_generate_spec.rb +0 -74
- data/spec/Features/feature_index_spec.rb +0 -69
- data/spec/Features/feature_mask_spec.rb +0 -580
- data/spec/Features/feature_math_spec.rb +0 -97
- data/spec/Features/feature_order_spec.rb +0 -146
- data/spec/Features/feature_ref_store_spec.rb +0 -209
- data/spec/Features/feature_serialization_spec.rb +0 -125
- data/spec/Features/feature_stat_spec.rb +0 -397
- data/spec/Features/feature_virtual_spec.rb +0 -48
- data/spec/Features/method_eq_spec.rb +0 -81
- data/spec/Features/method_is_nan_spec.rb +0 -12
- data/spec/Features/method_map_spec.rb +0 -54
- data/spec/Features/method_max_with.rb +0 -20
- data/spec/Features/method_min_with.rb +0 -19
- data/spec/Features/method_ne_spec.rb +0 -18
- data/spec/Features/method_project_spec.rb +0 -188
- data/spec/Features/method_ref_spec.rb +0 -27
- data/spec/Features/method_round_spec.rb +0 -11
- data/spec/Features/method_s_linspace_spec.rb +0 -48
- data/spec/Features/method_s_span_spec.rb +0 -14
- data/spec/Features/method_seq_spec.rb +0 -47
- data/spec/Features/method_sort_with.rb +0 -43
- data/spec/Features/method_sorted_with.rb +0 -29
- data/spec/Features/method_span_spec.rb +0 -42
- data/spec/Features/method_wrap_readonly_spec.rb +0 -43
- data/spec/UnitTest/test_CAVirtual.rb +0 -214
- data/spec/spec_all.rb +0 -10
- data/utils/ca_ase.rb +0 -21
- data/utils/ca_methods.rb +0 -15
- data/utils/cast_checker.rb +0 -30
- data/utils/convert_test.rb +0 -73
- data/utils/extract_yard.rb +0 -22
- data/utils/guess_shape.rb +0 -76
- data/utils/monkey_patch_methods.rb +0 -62
- data/utils/remove_resource_fork.sh +0 -5
|
@@ -0,0 +1,1035 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
Index classifier for `[]` / `[]=` — turns the argv passed to
|
|
4
|
+
CArray subscription into a CAIndexInfo describing the region
|
|
5
|
+
(POINT / BLOCK / ITERATOR / ADDRESS / GRID / SELECT / …). The
|
|
6
|
+
public entry `rb_ca_scan_index` in ca_obj_access.c forwards to
|
|
7
|
+
`rb_ca_scan_index_v2` here.
|
|
8
|
+
|
|
9
|
+
See docs/topics/Indexer_decision_tree.md for the wire-format spec.
|
|
10
|
+
|
|
11
|
+
Design shape:
|
|
12
|
+
- one REG per handler function (grep-friendly)
|
|
13
|
+
- rubber-dim pre-pass with a stack-allocated argv_expanded slot
|
|
14
|
+
- a single negative-index normaliser used by all handlers
|
|
15
|
+
- fast paths (POINT / ADDRESS, ndim == argc, all-FIXNUM) at
|
|
16
|
+
the top of the entry point
|
|
17
|
+
- single-character alphabetic Symbols (:a-:z / :A-:Z) reserved
|
|
18
|
+
for future contraction notation; the classifier raises
|
|
19
|
+
NotImplementedError when they appear.
|
|
20
|
+
|
|
21
|
+
--------------------------------------------------------------------------- */
|
|
22
|
+
|
|
23
|
+
#include "carray.h"
|
|
24
|
+
#include "carray_index_classifier.h"
|
|
25
|
+
|
|
26
|
+
/* Range accessor macros — carray_access.c keeps a private cache
|
|
27
|
+
with the same shape; the duplication here keeps this file
|
|
28
|
+
self-contained without cross-file symbol exposure. */
|
|
29
|
+
static ID ca_classifier_id_begin = 0;
|
|
30
|
+
static ID ca_classifier_id_end = 0;
|
|
31
|
+
static ID ca_classifier_id_excl_end = 0;
|
|
32
|
+
#define CA_CLASSIFIER_RANGE_BEG(r) (rb_funcall((r), ca_classifier_id_begin, 0))
|
|
33
|
+
#define CA_CLASSIFIER_RANGE_END(r) (rb_funcall((r), ca_classifier_id_end, 0))
|
|
34
|
+
#define CA_CLASSIFIER_RANGE_EXCL(r) (rb_funcall((r), ca_classifier_id_excl_end, 0))
|
|
35
|
+
|
|
36
|
+
/* -------------------------------------------------------------------- */
|
|
37
|
+
/* Symbol cache — see the range-macro comment above for why this
|
|
38
|
+
file keeps its own copy independent of carray_access.c. */
|
|
39
|
+
|
|
40
|
+
static VALUE ca_classifier_sym_star = Qundef;
|
|
41
|
+
static VALUE ca_classifier_sym_perc = Qundef;
|
|
42
|
+
static VALUE ca_classifier_sym_under = Qundef;
|
|
43
|
+
static VALUE ca_classifier_sym_gt = Qundef; /* :> slab-iterator marker */
|
|
44
|
+
static VALUE ca_classifier_sym_tilde = Qundef; /* :~ rubber-dim alias for `false` */
|
|
45
|
+
|
|
46
|
+
static inline void
|
|
47
|
+
ca_classifier_sym_cache_init (void)
|
|
48
|
+
{
|
|
49
|
+
if ( ca_classifier_sym_star == Qundef ) {
|
|
50
|
+
ca_classifier_sym_star = ID2SYM(rb_intern("*"));
|
|
51
|
+
ca_classifier_sym_perc = ID2SYM(rb_intern("%"));
|
|
52
|
+
ca_classifier_sym_under = ID2SYM(rb_intern("_"));
|
|
53
|
+
ca_classifier_sym_gt = ID2SYM(rb_intern(">"));
|
|
54
|
+
ca_classifier_sym_tilde = ID2SYM(rb_intern("~"));
|
|
55
|
+
ca_classifier_id_begin = rb_intern("begin");
|
|
56
|
+
ca_classifier_id_end = rb_intern("end");
|
|
57
|
+
ca_classifier_id_excl_end = rb_intern("exclude_end?");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* -------------------------------------------------------------------- */
|
|
62
|
+
/* Classifier context — every handler reads / writes through this
|
|
63
|
+
struct. Lives on rb_ca_scan_index_v2's stack; not exposed. */
|
|
64
|
+
|
|
65
|
+
typedef struct {
|
|
66
|
+
/* inputs (read-only after init) */
|
|
67
|
+
int ca_ndim;
|
|
68
|
+
ca_size_t *ca_dim;
|
|
69
|
+
ca_size_t ca_elements;
|
|
70
|
+
long argc; /* may be adjusted by rubber-dim expansion */
|
|
71
|
+
VALUE *argv; /* points at argv_expanded after pre-pass */
|
|
72
|
+
|
|
73
|
+
/* output (target of handlers) */
|
|
74
|
+
CAIndexInfo *info;
|
|
75
|
+
|
|
76
|
+
/* working storage for rubber-dim expansion */
|
|
77
|
+
VALUE argv_expanded[CA_RANK_MAX];
|
|
78
|
+
} ca_classifier_ctx_t;
|
|
79
|
+
|
|
80
|
+
/* -------------------------------------------------------------------- */
|
|
81
|
+
/* helpers */
|
|
82
|
+
|
|
83
|
+
/* Negative-index normalisation gathered in one place, replacing
|
|
84
|
+
the CA_CHECK_INDEX_AT macro that used to be expanded at every
|
|
85
|
+
call site. Error-message format is byte-identical with the
|
|
86
|
+
legacy path so downstream error-message assertions still match. */
|
|
87
|
+
static inline ca_size_t
|
|
88
|
+
ca_classifier_normalize_axis_index (ca_size_t k, ca_size_t dim, int axis, int range_check)
|
|
89
|
+
{
|
|
90
|
+
if ( k < 0 ) {
|
|
91
|
+
k += dim;
|
|
92
|
+
}
|
|
93
|
+
if ( range_check && ( k < 0 || k >= dim ) ) {
|
|
94
|
+
rb_raise(rb_eIndexError,
|
|
95
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
96
|
+
axis, (ca_size_t) k, (ca_size_t) (dim - 1));
|
|
97
|
+
}
|
|
98
|
+
return k;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Flat-address normalisation for the `argc == 1, ndim > 1,
|
|
102
|
+
Integer` path. CA_CHECK_INDEX does not carry axis info in its
|
|
103
|
+
message, which is the intended behaviour on the flat path. */
|
|
104
|
+
static inline ca_size_t
|
|
105
|
+
ca_classifier_normalize_flat_address (ca_size_t addr, ca_size_t elements, int range_check)
|
|
106
|
+
{
|
|
107
|
+
if ( range_check ) {
|
|
108
|
+
CA_CHECK_INDEX(addr, elements);
|
|
109
|
+
}
|
|
110
|
+
return addr;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* -------------------------------------------------------------------- */
|
|
114
|
+
/* Fast paths. */
|
|
115
|
+
|
|
116
|
+
/* Fast path 1: ca[i, j, k] all-FIXNUM, argc == ndim → POINT.
|
|
117
|
+
Returns 1 if classified, 0 if the caller should continue. */
|
|
118
|
+
static inline int
|
|
119
|
+
ca_classifier_try_point_fast_path (ca_classifier_ctx_t *ctx)
|
|
120
|
+
{
|
|
121
|
+
long i;
|
|
122
|
+
if ( ctx->argc < 1 || ctx->argc != ctx->ca_ndim ) {
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
for (i = 0; i < ctx->argc; i++) {
|
|
126
|
+
if ( ! FIXNUM_P(ctx->argv[i]) ) {
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
ctx->info->type = CA_REG_POINT;
|
|
132
|
+
ctx->info->ndim = (int16_t) ctx->argc;
|
|
133
|
+
for (i = 0; i < ctx->argc; i++) {
|
|
134
|
+
ca_size_t k = FIX2LONG(ctx->argv[i]);
|
|
135
|
+
if ( ctx->info->range_check ) {
|
|
136
|
+
/* Bignum is rejected by FIXNUM_P above; the slow path's
|
|
137
|
+
rb_obj_is_kind_of(arg, rb_cInteger) picks it up so the
|
|
138
|
+
Integer semantics are preserved end-to-end. */
|
|
139
|
+
k = ca_classifier_normalize_axis_index(k, ctx->ca_dim[i], (int) i,
|
|
140
|
+
ctx->info->range_check);
|
|
141
|
+
}
|
|
142
|
+
ctx->info->index_type[i] = CA_IDX_SCALAR;
|
|
143
|
+
ctx->info->index[i].scalar = k;
|
|
144
|
+
}
|
|
145
|
+
return 1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Fast path 2: ca[flat_addr] single FIXNUM, ndim > 1 → ADDRESS. */
|
|
149
|
+
static inline int
|
|
150
|
+
ca_classifier_try_address_fast_path (ca_classifier_ctx_t *ctx)
|
|
151
|
+
{
|
|
152
|
+
ca_size_t addr;
|
|
153
|
+
if ( ctx->argc != 1 || ctx->ca_ndim <= 1 || ! FIXNUM_P(ctx->argv[0]) ) {
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
addr = FIX2LONG(ctx->argv[0]);
|
|
157
|
+
addr = ca_classifier_normalize_flat_address(addr, ctx->ca_elements,
|
|
158
|
+
ctx->info->range_check);
|
|
159
|
+
ctx->info->type = CA_REG_ADDRESS;
|
|
160
|
+
ctx->info->ndim = 1;
|
|
161
|
+
ctx->info->index[0].scalar = addr;
|
|
162
|
+
return 1;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* -------------------------------------------------------------------- */
|
|
166
|
+
/* Single-character alphabetic Symbols (`:a`-`:z` / `:A`-`:Z`) are
|
|
167
|
+
reserved for future contraction notation. Raises
|
|
168
|
+
NotImplementedError rather than the generic IndexError. The
|
|
169
|
+
caller passes any Symbol that is not `:_` / `:*` / `:%`; a
|
|
170
|
+
non-reserved Symbol returns without action. */
|
|
171
|
+
static inline void
|
|
172
|
+
ca_classifier_check_reserved_contraction_symbol (VALUE sym)
|
|
173
|
+
{
|
|
174
|
+
const char *name;
|
|
175
|
+
if ( ! SYMBOL_P(sym) ) return;
|
|
176
|
+
name = rb_id2name(SYM2ID(sym));
|
|
177
|
+
if ( name != NULL
|
|
178
|
+
&& name[0] != '\0' && name[1] == '\0'
|
|
179
|
+
&& ( ( name[0] >= 'a' && name[0] <= 'z' )
|
|
180
|
+
|| ( name[0] >= 'A' && name[0] <= 'Z' ) )
|
|
181
|
+
&& name[0] != '_' /* :_ is iterator marker, handled separately */ ) {
|
|
182
|
+
rb_raise(rb_eNotImpError,
|
|
183
|
+
"symbol :%s is reserved for future contraction notation "
|
|
184
|
+
"(not yet implemented)",
|
|
185
|
+
name);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* -------------------------------------------------------------------- */
|
|
190
|
+
/* Per-axis BLOCK builders.
|
|
191
|
+
*
|
|
192
|
+
* Each helper takes the user-supplied arg + axis index + dim and
|
|
193
|
+
* populates info->index[axis].block plus
|
|
194
|
+
* info->index_type[axis] = BLOCK. Error messages are byte-
|
|
195
|
+
* identical with the legacy path so downstream regexes still
|
|
196
|
+
* match. */
|
|
197
|
+
|
|
198
|
+
/* Range → BLOCK */
|
|
199
|
+
static void
|
|
200
|
+
ca_classifier_axis_from_range (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
201
|
+
{
|
|
202
|
+
ca_size_t start, last, count, step;
|
|
203
|
+
int excl;
|
|
204
|
+
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
205
|
+
CAIndexInfo *info = ctx->info;
|
|
206
|
+
ca_size_t dim = ctx->ca_dim[axis];
|
|
207
|
+
|
|
208
|
+
iv_beg = CA_CLASSIFIER_RANGE_BEG(arg);
|
|
209
|
+
iv_end = CA_CLASSIFIER_RANGE_END(arg);
|
|
210
|
+
iv_excl = CA_CLASSIFIER_RANGE_EXCL(arg);
|
|
211
|
+
|
|
212
|
+
start = NIL_P(iv_beg) ? 0 : NUM2SIZE(iv_beg);
|
|
213
|
+
last = NIL_P(iv_end) ? -1 : NUM2SIZE(iv_end);
|
|
214
|
+
excl = RTEST(iv_excl);
|
|
215
|
+
|
|
216
|
+
info->index_type[axis] = CA_IDX_BLOCK;
|
|
217
|
+
|
|
218
|
+
if ( info->range_check ) {
|
|
219
|
+
/* Inlined CA_CHECK_INDEX_AT so the format string stays
|
|
220
|
+
byte-identical with the surrounding helpers. */
|
|
221
|
+
if ( start < 0 ) start += dim;
|
|
222
|
+
if ( start < 0 || start >= dim ) {
|
|
223
|
+
rb_raise(rb_eIndexError,
|
|
224
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
225
|
+
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if ( last < 0 ) {
|
|
230
|
+
last += dim; /* don't use CA_CHECK_INDEX for excl */
|
|
231
|
+
}
|
|
232
|
+
if ( excl && start == last ) {
|
|
233
|
+
info->index[axis].block.start = start;
|
|
234
|
+
info->index[axis].block.count = 0;
|
|
235
|
+
info->index[axis].block.step = 1;
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if ( excl ) {
|
|
239
|
+
last += ( last >= start ) ? -1 : 1;
|
|
240
|
+
}
|
|
241
|
+
if ( info->range_check ) {
|
|
242
|
+
if ( last < 0 || last >= dim ) {
|
|
243
|
+
rb_raise(rb_eIndexError,
|
|
244
|
+
"index %" PRId64 " is out of range (0..%" PRId64 ") at %i-dim",
|
|
245
|
+
(ca_size_t) last, (ca_size_t) (dim - 1), axis);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
count = llabs(last - start) + 1;
|
|
249
|
+
step = ( last >= start ) ? 1 : -1;
|
|
250
|
+
info->index[axis].block.start = start;
|
|
251
|
+
info->index[axis].block.count = count;
|
|
252
|
+
info->index[axis].block.step = step;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
|
|
256
|
+
/* ArithSeq → BLOCK */
|
|
257
|
+
static void
|
|
258
|
+
ca_classifier_axis_from_arithseq (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
259
|
+
{
|
|
260
|
+
ca_size_t start, last, count, step, bound;
|
|
261
|
+
int excl;
|
|
262
|
+
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
263
|
+
rb_arithmetic_sequence_components_t x;
|
|
264
|
+
CAIndexInfo *info = ctx->info;
|
|
265
|
+
ca_size_t dim = ctx->ca_dim[axis];
|
|
266
|
+
|
|
267
|
+
rb_arithmetic_sequence_extract(arg, &x);
|
|
268
|
+
iv_beg = x.begin;
|
|
269
|
+
iv_end = x.end;
|
|
270
|
+
iv_excl = x.exclude_end;
|
|
271
|
+
step = NUM2SIZE(x.step);
|
|
272
|
+
|
|
273
|
+
start = NIL_P(iv_beg) ? 0 : NUM2SIZE(iv_beg);
|
|
274
|
+
last = NIL_P(iv_end) ? -1 : NUM2SIZE(iv_end);
|
|
275
|
+
excl = RTEST(iv_excl);
|
|
276
|
+
|
|
277
|
+
if ( step == 0 ) {
|
|
278
|
+
rb_raise(rb_eRuntimeError,
|
|
279
|
+
"step in index equals to 0 in block reference");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
info->index_type[axis] = CA_IDX_BLOCK;
|
|
283
|
+
|
|
284
|
+
/* CAREFUL: always range-check start on the ArithSeq path,
|
|
285
|
+
ignoring info->range_check. An ArithSeq with a negative or
|
|
286
|
+
out-of-range start silently produces an empty region if this
|
|
287
|
+
check is deferred, which upstream callers do not expect. */
|
|
288
|
+
if ( start < 0 ) start += dim;
|
|
289
|
+
if ( start < 0 || start >= dim ) {
|
|
290
|
+
rb_raise(rb_eIndexError,
|
|
291
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
292
|
+
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if ( last < 0 ) {
|
|
296
|
+
last += dim;
|
|
297
|
+
}
|
|
298
|
+
if ( excl && start == last ) {
|
|
299
|
+
info->index[axis].block.start = start;
|
|
300
|
+
info->index[axis].block.count = 0;
|
|
301
|
+
info->index[axis].block.step = 1;
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if ( excl ) {
|
|
305
|
+
last += ( last >= start ) ? -1 : 1;
|
|
306
|
+
}
|
|
307
|
+
if ( last < 0 || last >= dim ) {
|
|
308
|
+
rb_raise(rb_eIndexError,
|
|
309
|
+
"index %" PRId64 " is out of range (0..%" PRId64 ") at %i-dim",
|
|
310
|
+
(ca_size_t) last, (ca_size_t) (dim - 1), axis);
|
|
311
|
+
}
|
|
312
|
+
if ( (last - start) * (long long) step < 0 ) {
|
|
313
|
+
count = 1;
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
count = llabs(last - start) / llabs((long long) step) + 1;
|
|
317
|
+
}
|
|
318
|
+
bound = start + (count - 1) * step;
|
|
319
|
+
if ( bound < 0 ) bound += dim; /* CA_CHECK_INDEX_AT signature */
|
|
320
|
+
if ( bound < 0 || bound >= dim ) {
|
|
321
|
+
rb_raise(rb_eIndexError,
|
|
322
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
323
|
+
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
324
|
+
}
|
|
325
|
+
info->index[axis].block.start = start;
|
|
326
|
+
info->index[axis].block.count = count;
|
|
327
|
+
info->index[axis].block.step = step;
|
|
328
|
+
}
|
|
329
|
+
#endif
|
|
330
|
+
|
|
331
|
+
/* T_ARRAY → BLOCK. Accepts [nil] / [Range] / [Integer] (len 1),
|
|
332
|
+
[nil, step] / [Range, step] / [start, count] (len 2), or
|
|
333
|
+
[start, count, step] (len 3). */
|
|
334
|
+
static void
|
|
335
|
+
ca_classifier_axis_from_array (ca_classifier_ctx_t *ctx, int axis, VALUE arg)
|
|
336
|
+
{
|
|
337
|
+
CAIndexInfo *info = ctx->info;
|
|
338
|
+
ca_size_t dim = ctx->ca_dim[axis];
|
|
339
|
+
long len = RARRAY_LEN(arg);
|
|
340
|
+
|
|
341
|
+
info->index_type[axis] = CA_IDX_BLOCK;
|
|
342
|
+
|
|
343
|
+
if ( len == 1 ) {
|
|
344
|
+
VALUE a0 = rb_ary_entry(arg, 0);
|
|
345
|
+
if ( NIL_P(a0) ) { /* [nil] → ALL */
|
|
346
|
+
info->index_type[axis] = CA_IDX_ALL;
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if ( rb_obj_is_kind_of(a0, rb_cRange) ) { /* [Range] → recurse */
|
|
350
|
+
ca_classifier_axis_from_range(ctx, axis, a0);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
/* [Integer] */
|
|
354
|
+
{
|
|
355
|
+
ca_size_t start = NUM2SIZE(a0);
|
|
356
|
+
if ( start < 0 ) start += dim;
|
|
357
|
+
if ( start < 0 || start >= dim ) {
|
|
358
|
+
rb_raise(rb_eIndexError,
|
|
359
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
360
|
+
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
361
|
+
}
|
|
362
|
+
info->index[axis].block.start = start;
|
|
363
|
+
info->index[axis].block.count = 1;
|
|
364
|
+
info->index[axis].block.step = 1;
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if ( len == 2 ) {
|
|
370
|
+
VALUE a0 = rb_ary_entry(arg, 0);
|
|
371
|
+
VALUE a1 = rb_ary_entry(arg, 1);
|
|
372
|
+
|
|
373
|
+
if ( NIL_P(a0) ) { /* [nil, step] */
|
|
374
|
+
ca_size_t start = 0, last, count, step, bound;
|
|
375
|
+
step = NUM2SIZE(a1);
|
|
376
|
+
if ( step == 0 ) {
|
|
377
|
+
rb_raise(rb_eRuntimeError,
|
|
378
|
+
"step in index equals to 0 in block reference");
|
|
379
|
+
}
|
|
380
|
+
last = dim - 1;
|
|
381
|
+
count = ( step < 0 ) ? 1 : (last / step + 1);
|
|
382
|
+
bound = start + (count - 1) * step;
|
|
383
|
+
if ( bound < 0 ) bound += dim;
|
|
384
|
+
if ( bound < 0 || bound >= dim ) {
|
|
385
|
+
rb_raise(rb_eIndexError,
|
|
386
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
387
|
+
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
388
|
+
}
|
|
389
|
+
info->index[axis].block.start = start;
|
|
390
|
+
info->index[axis].block.count = count;
|
|
391
|
+
info->index[axis].block.step = step;
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if ( rb_obj_is_kind_of(a0, rb_cRange) ) { /* [Range, step] */
|
|
396
|
+
ca_size_t start, last, count, step, bound;
|
|
397
|
+
int excl;
|
|
398
|
+
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
399
|
+
iv_beg = CA_CLASSIFIER_RANGE_BEG(a0);
|
|
400
|
+
iv_end = CA_CLASSIFIER_RANGE_END(a0);
|
|
401
|
+
iv_excl = CA_CLASSIFIER_RANGE_EXCL(a0);
|
|
402
|
+
start = NIL_P(iv_beg) ? 0 : NUM2SIZE(iv_beg);
|
|
403
|
+
last = NIL_P(iv_end) ? -1 : NUM2SIZE(iv_end);
|
|
404
|
+
excl = RTEST(iv_excl);
|
|
405
|
+
step = NUM2SIZE(a1);
|
|
406
|
+
if ( step == 0 ) {
|
|
407
|
+
rb_raise(rb_eRuntimeError,
|
|
408
|
+
"step in index equals to 0 in block reference");
|
|
409
|
+
}
|
|
410
|
+
if ( start < 0 ) start += dim;
|
|
411
|
+
if ( start < 0 || start >= dim ) {
|
|
412
|
+
rb_raise(rb_eIndexError,
|
|
413
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
414
|
+
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
415
|
+
}
|
|
416
|
+
if ( last < 0 ) last += dim;
|
|
417
|
+
if ( excl && start == last ) {
|
|
418
|
+
info->index[axis].block.start = start;
|
|
419
|
+
info->index[axis].block.count = 0;
|
|
420
|
+
info->index[axis].block.step = 1;
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if ( excl ) {
|
|
424
|
+
last += ( last >= start ) ? -1 : 1;
|
|
425
|
+
}
|
|
426
|
+
if ( last < 0 || last >= dim ) {
|
|
427
|
+
rb_raise(rb_eIndexError,
|
|
428
|
+
"index %" PRId64 " is out of range (0..%" PRId64 ") at %i-dim",
|
|
429
|
+
(ca_size_t) last, (ca_size_t) (dim - 1), axis);
|
|
430
|
+
}
|
|
431
|
+
if ( (last - start) * (long long) step < 0 ) {
|
|
432
|
+
count = 1;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
count = llabs(last - start) / llabs((long long) step) + 1;
|
|
436
|
+
}
|
|
437
|
+
bound = start + (count - 1) * step;
|
|
438
|
+
if ( bound < 0 ) bound += dim;
|
|
439
|
+
if ( bound < 0 || bound >= dim ) {
|
|
440
|
+
rb_raise(rb_eIndexError,
|
|
441
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
442
|
+
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
443
|
+
}
|
|
444
|
+
info->index[axis].block.start = start;
|
|
445
|
+
info->index[axis].block.count = count;
|
|
446
|
+
info->index[axis].block.step = step;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* [start, count] */
|
|
451
|
+
{
|
|
452
|
+
ca_size_t start, count, bound;
|
|
453
|
+
start = NUM2SIZE(a0);
|
|
454
|
+
count = NUM2SIZE(a1);
|
|
455
|
+
bound = start + (count - 1);
|
|
456
|
+
if ( start < 0 ) start += dim;
|
|
457
|
+
if ( start < 0 || start >= dim ) {
|
|
458
|
+
rb_raise(rb_eIndexError,
|
|
459
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
460
|
+
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
461
|
+
}
|
|
462
|
+
if ( bound < 0 ) bound += dim;
|
|
463
|
+
if ( bound < 0 || bound >= dim ) {
|
|
464
|
+
rb_raise(rb_eIndexError,
|
|
465
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
466
|
+
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
467
|
+
}
|
|
468
|
+
info->index[axis].block.start = start;
|
|
469
|
+
info->index[axis].block.count = count;
|
|
470
|
+
info->index[axis].block.step = 1;
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if ( len == 3 ) { /* [start, count, step] */
|
|
476
|
+
ca_size_t start, count, step, bound;
|
|
477
|
+
start = NUM2SIZE(rb_ary_entry(arg, 0));
|
|
478
|
+
count = NUM2SIZE(rb_ary_entry(arg, 1));
|
|
479
|
+
step = NUM2SIZE(rb_ary_entry(arg, 2));
|
|
480
|
+
if ( step == 0 ) {
|
|
481
|
+
rb_raise(rb_eRuntimeError,
|
|
482
|
+
"step in index equals to 0 in block reference");
|
|
483
|
+
}
|
|
484
|
+
bound = start + (count - 1) * step;
|
|
485
|
+
if ( start < 0 ) start += dim;
|
|
486
|
+
if ( start < 0 || start >= dim ) {
|
|
487
|
+
rb_raise(rb_eIndexError,
|
|
488
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
489
|
+
axis, (ca_size_t) start, (ca_size_t) (dim - 1));
|
|
490
|
+
}
|
|
491
|
+
if ( bound < 0 ) bound += dim;
|
|
492
|
+
if ( bound < 0 || bound >= dim ) {
|
|
493
|
+
rb_raise(rb_eIndexError,
|
|
494
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )",
|
|
495
|
+
axis, (ca_size_t) bound, (ca_size_t) (dim - 1));
|
|
496
|
+
}
|
|
497
|
+
info->index[axis].block.start = start;
|
|
498
|
+
info->index[axis].block.count = count;
|
|
499
|
+
info->index[axis].block.step = step;
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
rb_raise(rb_eIndexError,
|
|
504
|
+
"invalid form of index range at %i-dim "
|
|
505
|
+
"(should be [start[,count[,step]]], [range, step])",
|
|
506
|
+
axis);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/* -------------------------------------------------------------------- */
|
|
510
|
+
/* Per-axis dispatcher — main-loop body.
|
|
511
|
+
*
|
|
512
|
+
* Returns 1 to signal the main loop to STOP (a CArray at an axis
|
|
513
|
+
* position triggers a REG = GRID short-circuit that skips
|
|
514
|
+
* remaining axes and the post-loop ndim check). Otherwise
|
|
515
|
+
* returns 0. Sets *out_is_grid when the GRID short-circuit
|
|
516
|
+
* fires; out_is_grid must not be NULL. */
|
|
517
|
+
static int
|
|
518
|
+
ca_classifier_dispatch_axis_arg (ca_classifier_ctx_t *ctx, int axis, VALUE arg,
|
|
519
|
+
int *out_is_grid)
|
|
520
|
+
{
|
|
521
|
+
CAIndexInfo *info = ctx->info;
|
|
522
|
+
ca_size_t dim = ctx->ca_dim[axis];
|
|
523
|
+
|
|
524
|
+
if ( rb_obj_is_kind_of(arg, rb_cInteger) ) {
|
|
525
|
+
ca_size_t k = NUM2SIZE(arg);
|
|
526
|
+
info->index_type[axis] = CA_IDX_SCALAR;
|
|
527
|
+
if ( info->range_check ) {
|
|
528
|
+
k = ca_classifier_normalize_axis_index(k, dim, axis, info->range_check);
|
|
529
|
+
}
|
|
530
|
+
info->index[axis].scalar = k;
|
|
531
|
+
return 0;
|
|
532
|
+
}
|
|
533
|
+
if ( NIL_P(arg) ) {
|
|
534
|
+
info->index_type[axis] = CA_IDX_ALL;
|
|
535
|
+
return 0;
|
|
536
|
+
}
|
|
537
|
+
if ( rb_obj_is_kind_of(arg, rb_cRange) ) {
|
|
538
|
+
ca_classifier_axis_from_range(ctx, axis, arg);
|
|
539
|
+
return 0;
|
|
540
|
+
}
|
|
541
|
+
#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
|
|
542
|
+
if ( rb_obj_is_kind_of(arg, rb_cArithSeq) ) {
|
|
543
|
+
ca_classifier_axis_from_arithseq(ctx, axis, arg);
|
|
544
|
+
return 0;
|
|
545
|
+
}
|
|
546
|
+
#endif
|
|
547
|
+
if ( TYPE(arg) == T_ARRAY ) {
|
|
548
|
+
ca_classifier_axis_from_array(ctx, axis, arg);
|
|
549
|
+
return 0;
|
|
550
|
+
}
|
|
551
|
+
if ( SYMBOL_P(arg) ) {
|
|
552
|
+
/* :> is the slab-iterator marker. :_ is newaxis, intercepted
|
|
553
|
+
at the [] / []= entry before scan_index sees it — if it
|
|
554
|
+
reaches this branch it slipped past the newaxis hook. */
|
|
555
|
+
if ( arg == ca_classifier_sym_gt ) {
|
|
556
|
+
info->index_type[axis] = CA_IDX_SYMBOL;
|
|
557
|
+
info->index[axis].symbol.id = SYM2ID(arg);
|
|
558
|
+
info->index[axis].symbol.spec = Qnil;
|
|
559
|
+
return 0;
|
|
560
|
+
}
|
|
561
|
+
if ( arg == ca_classifier_sym_under ) {
|
|
562
|
+
/* :_ reached here because it slipped past the [] / []=
|
|
563
|
+
newaxis hook (typically CArray.scan_index called directly). */
|
|
564
|
+
rb_raise(rb_eIndexError,
|
|
565
|
+
"symbol :_ (newaxis) is handled at the [] / []= level, "
|
|
566
|
+
"not valid in scan_index");
|
|
567
|
+
}
|
|
568
|
+
ca_classifier_check_reserved_contraction_symbol(arg); /* raises if reserved */
|
|
569
|
+
rb_raise(rb_eIndexError,
|
|
570
|
+
"symbol :%s is invalid as the index for slab iterator "
|
|
571
|
+
"(use :> instead)",
|
|
572
|
+
rb_id2name(SYM2ID(arg)));
|
|
573
|
+
}
|
|
574
|
+
if ( rb_obj_is_carray(arg) ) {
|
|
575
|
+
/* CArray (boolean / integer) at an axis position → GRID.
|
|
576
|
+
Signal the caller to stop populating later axes; the
|
|
577
|
+
main-loop caller breaks out after this axis. */
|
|
578
|
+
CArray *ci;
|
|
579
|
+
TypedData_Get_Struct(arg, CArray, &carray_data_type, ci);
|
|
580
|
+
if ( ca_is_boolean_type(ci) || ca_is_integer_type(ci) ) {
|
|
581
|
+
if ( out_is_grid ) *out_is_grid = 1;
|
|
582
|
+
return 1; /* signal caller: stop main loop, REG = GRID */
|
|
583
|
+
}
|
|
584
|
+
rb_raise(rb_eIndexError,
|
|
585
|
+
"data_type %s is invalid for reference by gridding at %i-dim "
|
|
586
|
+
"(should be boolean or integer)",
|
|
587
|
+
ca_type_name[ci->data_type], axis);
|
|
588
|
+
}
|
|
589
|
+
{
|
|
590
|
+
VALUE inspect = rb_inspect(arg);
|
|
591
|
+
rb_raise(rb_eIndexError,
|
|
592
|
+
"object '%s' is invalid for the index for reference at %i-dim",
|
|
593
|
+
StringValuePtr(inspect), axis);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/* -------------------------------------------------------------------- */
|
|
598
|
+
/* Rubber-dim pre-pass. Walks ctx->argv detecting Qfalse (or its
|
|
599
|
+
`:~` alias), expands the rubber slot into `Qnil` fills in
|
|
600
|
+
ctx->argv_expanded, and re-points ctx->argv at it. At most one
|
|
601
|
+
rubber marker is honoured; a second one falls through to the
|
|
602
|
+
per-axis dispatcher and raises. */
|
|
603
|
+
|
|
604
|
+
static void
|
|
605
|
+
ca_classifier_expand_rubber_dim (ca_classifier_ctx_t *ctx)
|
|
606
|
+
{
|
|
607
|
+
long i, j;
|
|
608
|
+
long argc = ctx->argc;
|
|
609
|
+
VALUE *argv = ctx->argv;
|
|
610
|
+
int rubber_pos = -1;
|
|
611
|
+
long expanded_argc;
|
|
612
|
+
int rndim;
|
|
613
|
+
|
|
614
|
+
for (i = 0; i < argc; i++) {
|
|
615
|
+
if ( argv[i] == Qfalse || argv[i] == ca_classifier_sym_tilde ) {
|
|
616
|
+
rubber_pos = (int) i; /* :~ is an alias for the `false` rubber marker */
|
|
617
|
+
/* Only the first rubber marker is honoured; later occurrences fall
|
|
618
|
+
through to the per-axis dispatcher and raise. */
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
if ( rubber_pos < 0 ) {
|
|
624
|
+
/* No rubber dim — validate argc == ndim and pass through. */
|
|
625
|
+
if ( argc != ctx->ca_ndim ) {
|
|
626
|
+
rb_raise(rb_eIndexError,
|
|
627
|
+
"number of indices exceeds the ndim of carray (%i > %i)",
|
|
628
|
+
(int) argc, ctx->ca_ndim);
|
|
629
|
+
}
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if ( argc > ctx->ca_ndim + 1 ) {
|
|
634
|
+
rb_raise(rb_eIndexError,
|
|
635
|
+
"index specification exceeds the ndim of carray (%i)",
|
|
636
|
+
ctx->ca_ndim);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/* rndim = number of nils the rubber expands to.
|
|
640
|
+
*
|
|
641
|
+
* CAREFUL: rndim == 0 is a valid outcome — the rubber consumes
|
|
642
|
+
* nothing when argc == ndim + 1 (e.g. `[false, 0, 1]` on
|
|
643
|
+
* ndim = 2 collapses to `[0, 1]`). Clamping only at the
|
|
644
|
+
* negative side preserves that path. */
|
|
645
|
+
rndim = ctx->ca_ndim - (int)argc + 1;
|
|
646
|
+
if ( rndim < 0 ) rndim = 0;
|
|
647
|
+
expanded_argc = argc - 1 + rndim;
|
|
648
|
+
|
|
649
|
+
j = 0;
|
|
650
|
+
for (i = 0; i < argc; i++) {
|
|
651
|
+
if ( i == rubber_pos ) {
|
|
652
|
+
int k;
|
|
653
|
+
for (k = 0; k < rndim; k++) {
|
|
654
|
+
ctx->argv_expanded[j++] = Qnil;
|
|
655
|
+
}
|
|
656
|
+
} else {
|
|
657
|
+
ctx->argv_expanded[j++] = argv[i];
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
ctx->argc = expanded_argc;
|
|
661
|
+
ctx->argv = ctx->argv_expanded;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/* -------------------------------------------------------------------- */
|
|
665
|
+
/* Final REG decision — walks info->index_type[] and decides
|
|
666
|
+
POINT / BLOCK / ITERATOR / GRID. */
|
|
667
|
+
|
|
668
|
+
static void
|
|
669
|
+
ca_classifier_finalize_reg (ca_classifier_ctx_t *ctx, int is_grid)
|
|
670
|
+
{
|
|
671
|
+
int i, is_point = 1, is_iterator = 0;
|
|
672
|
+
CAIndexInfo *info = ctx->info;
|
|
673
|
+
|
|
674
|
+
for (i = 0; i < info->ndim; i++) {
|
|
675
|
+
switch ( info->index_type[i] ) {
|
|
676
|
+
case CA_IDX_SCALAR: break;
|
|
677
|
+
case CA_IDX_ALL: is_point = 0; break;
|
|
678
|
+
case CA_IDX_SYMBOL: is_iterator = 1; break;
|
|
679
|
+
default: is_point = 0; break;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if ( is_grid ) info->type = CA_REG_GRID;
|
|
684
|
+
else if ( is_iterator ) info->type = CA_REG_ITERATOR;
|
|
685
|
+
else if ( is_point ) info->type = CA_REG_POINT;
|
|
686
|
+
else info->type = CA_REG_BLOCK;
|
|
687
|
+
|
|
688
|
+
/* CAREFUL: when REG == ITERATOR, every CA_IDX_SCALAR axis must
|
|
689
|
+
be rewritten into a BLOCK with {start, count = 1, step = 1}.
|
|
690
|
+
Downstream iterator machinery treats SCALAR and BLOCK
|
|
691
|
+
differently, and skipping this rewrite silently changes the
|
|
692
|
+
iteration shape. */
|
|
693
|
+
if ( info->type == CA_REG_ITERATOR ) {
|
|
694
|
+
for (i = 0; i < info->ndim; i++) {
|
|
695
|
+
if ( info->index_type[i] == CA_IDX_SCALAR ) {
|
|
696
|
+
ca_size_t start = info->index[i].scalar;
|
|
697
|
+
info->index_type[i] = CA_IDX_BLOCK;
|
|
698
|
+
info->index[i].block.start = start;
|
|
699
|
+
info->index[i].block.step = 1;
|
|
700
|
+
info->index[i].block.count = 1;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/* -------------------------------------------------------------------- */
|
|
707
|
+
/* argc == 1 special dispatch. Returns 1 if the region was
|
|
708
|
+
classified here, 0 to continue to the main loop. */
|
|
709
|
+
|
|
710
|
+
static int
|
|
711
|
+
ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
|
|
712
|
+
{
|
|
713
|
+
VALUE arg = ctx->argv[0];
|
|
714
|
+
CAIndexInfo *info = ctx->info;
|
|
715
|
+
|
|
716
|
+
/* A single Qfalse / :~ means ALL, so `ca[:~]` and `ca[false]`
|
|
717
|
+
both collapse to `ca[]`. */
|
|
718
|
+
if ( arg == Qfalse || arg == ca_classifier_sym_tilde ) {
|
|
719
|
+
info->type = CA_REG_ALL;
|
|
720
|
+
return 1;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/* T_STRING: "@name" → ATTRIBUTE, "field" → MEMBER. */
|
|
724
|
+
if ( TYPE(arg) == T_STRING ) {
|
|
725
|
+
const char *s = StringValuePtr(arg);
|
|
726
|
+
if ( s[0] == '@' ) {
|
|
727
|
+
info->type = CA_REG_ATTRIBUTE;
|
|
728
|
+
info->symbol = rb_str_new2(s + 1);
|
|
729
|
+
} else {
|
|
730
|
+
info->type = CA_REG_MEMBER;
|
|
731
|
+
info->symbol = ID2SYM(rb_intern(s));
|
|
732
|
+
}
|
|
733
|
+
return 1;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/* argc == 1 CArray → GRID / MAPPING / SELECT. */
|
|
737
|
+
if ( rb_obj_is_carray(arg) ) {
|
|
738
|
+
CArray *cs;
|
|
739
|
+
TypedData_Get_Struct(arg, CArray, &carray_data_type, cs);
|
|
740
|
+
if ( ca_is_integer_type(cs) ) {
|
|
741
|
+
if ( ctx->ca_ndim == 1 && cs->ndim == 1 ) {
|
|
742
|
+
info->type = CA_REG_GRID;
|
|
743
|
+
} else {
|
|
744
|
+
info->type = CA_REG_MAPPING;
|
|
745
|
+
}
|
|
746
|
+
return 1;
|
|
747
|
+
}
|
|
748
|
+
if ( ca_is_boolean_type(cs) ) {
|
|
749
|
+
if ( ctx->ca_elements != cs->elements ) {
|
|
750
|
+
rb_raise(rb_eRuntimeError,
|
|
751
|
+
"mismatch of # of elements ( %" PRId64 " <=> %" PRId64 " ) "
|
|
752
|
+
"in reference by selection",
|
|
753
|
+
(ca_size_t) cs->elements,
|
|
754
|
+
(ca_size_t) ctx->ca_elements);
|
|
755
|
+
}
|
|
756
|
+
info->type = CA_REG_SELECT;
|
|
757
|
+
info->select = cs;
|
|
758
|
+
return 1;
|
|
759
|
+
}
|
|
760
|
+
rb_raise(rb_eIndexError,
|
|
761
|
+
"data_type %s is invalid for reference by selection/mapping"
|
|
762
|
+
"(should be boolean or integer)",
|
|
763
|
+
ca_type_name[cs->data_type]);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/* :* → UNBOUND_REPEAT. */
|
|
767
|
+
if ( arg == ca_classifier_sym_star ) {
|
|
768
|
+
info->type = CA_REG_UNBOUND_REPEAT;
|
|
769
|
+
return 1;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/* ndim > 1 with Integer → ADDRESS. Fixnum was caught by the
|
|
773
|
+
fast path; this branch handles Bignum. */
|
|
774
|
+
if ( ctx->ca_ndim > 1 && rb_obj_is_kind_of(arg, rb_cInteger) ) {
|
|
775
|
+
ca_size_t addr = NUM2SIZE(arg);
|
|
776
|
+
info->type = CA_REG_ADDRESS;
|
|
777
|
+
info->ndim = 1;
|
|
778
|
+
if ( info->range_check ) {
|
|
779
|
+
CA_CHECK_INDEX(addr, ctx->ca_elements);
|
|
780
|
+
}
|
|
781
|
+
info->index[0].scalar = addr;
|
|
782
|
+
return 1;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/* ndim > 1 with nil → FLATTEN. */
|
|
786
|
+
if ( ctx->ca_ndim > 1 && NIL_P(arg) ) {
|
|
787
|
+
info->type = CA_REG_FLATTEN;
|
|
788
|
+
return 1;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/* ndim > 1 with Range / ArithSeq / T_ARRAY → ADDRESS_COMPLEX.
|
|
792
|
+
The classifier only sets info->type here; the actual
|
|
793
|
+
[start, count, step] triple is built by re-scanning argv
|
|
794
|
+
against a flat dim = [elements] at the Ruby surface
|
|
795
|
+
(rb_ca_s_scan_index_v2 below). */
|
|
796
|
+
if ( ctx->ca_ndim > 1 ) {
|
|
797
|
+
info->type = CA_REG_ADDRESS_COMPLEX;
|
|
798
|
+
return 1;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/* argc == 1 && ndim == 1: fall through to the main loop
|
|
802
|
+
(which classifies this as POINT 1-D). */
|
|
803
|
+
return 0;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/* -------------------------------------------------------------------- */
|
|
807
|
+
/* Entry point. */
|
|
808
|
+
|
|
809
|
+
void
|
|
810
|
+
rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
811
|
+
long argc, VALUE *argv, CAIndexInfo *info)
|
|
812
|
+
{
|
|
813
|
+
ca_classifier_ctx_t ctx;
|
|
814
|
+
long i;
|
|
815
|
+
|
|
816
|
+
ca_classifier_sym_cache_init();
|
|
817
|
+
|
|
818
|
+
ctx.ca_ndim = ca_ndim;
|
|
819
|
+
ctx.ca_dim = ca_dim;
|
|
820
|
+
ctx.ca_elements = ca_elements;
|
|
821
|
+
ctx.argc = argc;
|
|
822
|
+
ctx.argv = argv;
|
|
823
|
+
ctx.info = info;
|
|
824
|
+
|
|
825
|
+
info->ndim = 0;
|
|
826
|
+
info->select = NULL;
|
|
827
|
+
|
|
828
|
+
/* argc == 0 → ALL */
|
|
829
|
+
if ( argc == 0 ) {
|
|
830
|
+
info->type = CA_REG_ALL;
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/* argv[0] = multi-char Symbol → METHOD_CALL. Single-char
|
|
835
|
+
specials (:_ / :* / :%) fall through the strlen check and are
|
|
836
|
+
handled downstream (argc == 1 special / fast paths / main
|
|
837
|
+
loop). Single-char alphabetic reserved-contraction Symbols
|
|
838
|
+
also fall through here and are raised later by the per-axis
|
|
839
|
+
dispatcher's SYMBOL_P branch. */
|
|
840
|
+
if ( SYMBOL_P(argv[0]) ) {
|
|
841
|
+
const char *name = rb_id2name(SYM2ID(argv[0]));
|
|
842
|
+
if ( name != NULL && strlen(name) > 1 ) {
|
|
843
|
+
info->type = CA_REG_METHOD_CALL;
|
|
844
|
+
info->symbol = argv[0];
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/* Fast paths. */
|
|
850
|
+
if ( ca_classifier_try_point_fast_path(&ctx) ) return;
|
|
851
|
+
if ( ca_classifier_try_address_fast_path(&ctx) ) return;
|
|
852
|
+
|
|
853
|
+
/* argc == 1 special cases. */
|
|
854
|
+
if ( argc == 1 ) {
|
|
855
|
+
if ( ca_classifier_try_argc1_special(&ctx) ) return;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/* Main loop entered when argc >= 1 was not handled above, or
|
|
859
|
+
when argc == 1 && ndim == 1 falls through to the POINT 1-D
|
|
860
|
+
classification below. */
|
|
861
|
+
|
|
862
|
+
/* CAREFUL: pre-scan for :% / :*. Either Symbol at any position
|
|
863
|
+
pins the final REG and short-circuits both the main loop and
|
|
864
|
+
the argc / ndim validation below — skipping the pre-scan lets
|
|
865
|
+
the ndim mismatch check fire before the Symbol is
|
|
866
|
+
recognised. */
|
|
867
|
+
for (i = 0; i < ctx.argc; i++) {
|
|
868
|
+
if ( ctx.argv[i] == ca_classifier_sym_perc ) {
|
|
869
|
+
info->type = CA_REG_REPEAT;
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
if ( ctx.argv[i] == ca_classifier_sym_star ) {
|
|
873
|
+
info->type = CA_REG_UNBOUND_REPEAT;
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
ca_classifier_expand_rubber_dim(&ctx);
|
|
879
|
+
|
|
880
|
+
info->ndim = (int16_t) ctx.argc;
|
|
881
|
+
{
|
|
882
|
+
int is_grid = 0;
|
|
883
|
+
int stop = 0;
|
|
884
|
+
for (i = 0; i < ctx.argc && ! stop; i++) {
|
|
885
|
+
stop = ca_classifier_dispatch_axis_arg(&ctx, (int) i, ctx.argv[i], &is_grid);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/* CAREFUL: the GRID short-circuit skips the post-loop ndim
|
|
889
|
+
validation. A CArray at an axis position may reduce the
|
|
890
|
+
effective info->ndim below ctx.ca_ndim, and re-checking
|
|
891
|
+
here would raise on legitimate grid regions. */
|
|
892
|
+
if ( ! is_grid && ctx.ca_ndim != info->ndim ) {
|
|
893
|
+
rb_raise(rb_eIndexError,
|
|
894
|
+
"number of indices does not equal to the ndim (%i != %i)",
|
|
895
|
+
info->ndim, ctx.ca_ndim);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
ca_classifier_finalize_reg(&ctx, is_grid);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/* -------------------------------------------------------------------- */
|
|
903
|
+
/* Debug / test surface: CArray._scan_index_v2(dim_array, idx_array)
|
|
904
|
+
returns a plain [type_int, index_array] pair rather than the
|
|
905
|
+
full CAIndexInfo struct. Kept for spec regression checks and
|
|
906
|
+
downstream introspection. */
|
|
907
|
+
|
|
908
|
+
static VALUE
|
|
909
|
+
rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
|
|
910
|
+
{
|
|
911
|
+
CAIndexInfo info;
|
|
912
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
913
|
+
ca_size_t elements;
|
|
914
|
+
int ndim, i;
|
|
915
|
+
VALUE rindex;
|
|
916
|
+
|
|
917
|
+
Check_Type(rdim, T_ARRAY);
|
|
918
|
+
Check_Type(ridx, T_ARRAY);
|
|
919
|
+
|
|
920
|
+
ndim = (int) RARRAY_LEN(rdim);
|
|
921
|
+
elements = 1;
|
|
922
|
+
for (i = 0; i < ndim; i++) {
|
|
923
|
+
dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
924
|
+
elements *= dim[i];
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
CA_CHECK_RANK(ndim);
|
|
928
|
+
CA_CHECK_DIM(ndim, dim);
|
|
929
|
+
|
|
930
|
+
info.range_check = 1;
|
|
931
|
+
rb_ca_scan_index_v2(ndim, dim, elements,
|
|
932
|
+
RARRAY_LEN(ridx),
|
|
933
|
+
(VALUE *) RARRAY_CONST_PTR(ridx), &info);
|
|
934
|
+
|
|
935
|
+
rindex = rb_ary_new();
|
|
936
|
+
switch ( info.type ) {
|
|
937
|
+
case CA_REG_ALL:
|
|
938
|
+
case CA_REG_FLATTEN:
|
|
939
|
+
case CA_REG_SELECT:
|
|
940
|
+
case CA_REG_REPEAT:
|
|
941
|
+
case CA_REG_GRID:
|
|
942
|
+
case CA_REG_MAPPING:
|
|
943
|
+
case CA_REG_METHOD_CALL:
|
|
944
|
+
case CA_REG_UNBOUND_REPEAT:
|
|
945
|
+
case CA_REG_MEMBER:
|
|
946
|
+
case CA_REG_ATTRIBUTE:
|
|
947
|
+
break;
|
|
948
|
+
case CA_REG_ADDRESS:
|
|
949
|
+
rb_ary_push(rindex, SIZE2NUM(info.index[0].scalar));
|
|
950
|
+
break;
|
|
951
|
+
case CA_REG_ADDRESS_COMPLEX: {
|
|
952
|
+
/* Recursive flat re-scan: build a 1-D dim = [elements] and
|
|
953
|
+
re-classify; the resulting BLOCK / SCALAR / ALL is wrapped
|
|
954
|
+
in a single-element array so the caller can consume it
|
|
955
|
+
uniformly with the other cases. */
|
|
956
|
+
CAIndexInfo flat_info;
|
|
957
|
+
ca_size_t flat_dim[1];
|
|
958
|
+
VALUE inner;
|
|
959
|
+
flat_dim[0] = elements;
|
|
960
|
+
flat_info.range_check = 1;
|
|
961
|
+
rb_ca_scan_index_v2(1, flat_dim, elements,
|
|
962
|
+
RARRAY_LEN(ridx),
|
|
963
|
+
(VALUE *) RARRAY_CONST_PTR(ridx), &flat_info);
|
|
964
|
+
/* Wrap index[0] as [start, count, step] / scalar / [0, elements, 1]
|
|
965
|
+
depending on which per-axis kind the flat re-scan produced. */
|
|
966
|
+
switch ( flat_info.index_type[0] ) {
|
|
967
|
+
case CA_IDX_BLOCK:
|
|
968
|
+
inner = rb_ary_new3(3,
|
|
969
|
+
SIZE2NUM(flat_info.index[0].block.start),
|
|
970
|
+
SIZE2NUM(flat_info.index[0].block.count),
|
|
971
|
+
SIZE2NUM(flat_info.index[0].block.step));
|
|
972
|
+
rb_ary_push(rindex, inner);
|
|
973
|
+
break;
|
|
974
|
+
case CA_IDX_SCALAR:
|
|
975
|
+
rb_ary_push(rindex, SIZE2NUM(flat_info.index[0].scalar));
|
|
976
|
+
break;
|
|
977
|
+
case CA_IDX_ALL:
|
|
978
|
+
rb_ary_push(rindex,
|
|
979
|
+
rb_ary_new3(3, INT2NUM(0), SIZE2NUM(elements),
|
|
980
|
+
INT2NUM(1)));
|
|
981
|
+
break;
|
|
982
|
+
default: break;
|
|
983
|
+
}
|
|
984
|
+
break;
|
|
985
|
+
}
|
|
986
|
+
case CA_REG_POINT:
|
|
987
|
+
for (i = 0; i < ndim; i++) {
|
|
988
|
+
rb_ary_push(rindex, SIZE2NUM(info.index[i].scalar));
|
|
989
|
+
}
|
|
990
|
+
break;
|
|
991
|
+
case CA_REG_BLOCK:
|
|
992
|
+
case CA_REG_ITERATOR:
|
|
993
|
+
for (i = 0; i < ndim; i++) {
|
|
994
|
+
switch ( info.index_type[i] ) {
|
|
995
|
+
case CA_IDX_SCALAR:
|
|
996
|
+
rb_ary_push(rindex, SIZE2NUM(info.index[i].scalar));
|
|
997
|
+
break;
|
|
998
|
+
case CA_IDX_ALL:
|
|
999
|
+
rb_ary_push(rindex,
|
|
1000
|
+
rb_ary_new3(3, INT2NUM(0),
|
|
1001
|
+
rb_ary_entry(rdim, i),
|
|
1002
|
+
INT2NUM(1)));
|
|
1003
|
+
break;
|
|
1004
|
+
case CA_IDX_BLOCK:
|
|
1005
|
+
rb_ary_push(rindex,
|
|
1006
|
+
rb_ary_new3(3,
|
|
1007
|
+
SIZE2NUM(info.index[i].block.start),
|
|
1008
|
+
SIZE2NUM(info.index[i].block.count),
|
|
1009
|
+
SIZE2NUM(info.index[i].block.step)));
|
|
1010
|
+
break;
|
|
1011
|
+
case CA_IDX_SYMBOL:
|
|
1012
|
+
rb_ary_push(rindex,
|
|
1013
|
+
rb_ary_new3(2,
|
|
1014
|
+
ID2SYM(info.index[i].symbol.id),
|
|
1015
|
+
info.index[i].symbol.spec));
|
|
1016
|
+
break;
|
|
1017
|
+
default:
|
|
1018
|
+
rb_raise(rb_eRuntimeError, "unknown index spec");
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
break;
|
|
1022
|
+
default:
|
|
1023
|
+
rb_raise(rb_eArgError, "unknown index specification");
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
return rb_ary_new3(2, INT2NUM(info.type), rindex);
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
void
|
|
1030
|
+
Init_carray_index_classifier (void)
|
|
1031
|
+
{
|
|
1032
|
+
ca_classifier_sym_cache_init();
|
|
1033
|
+
rb_define_singleton_method(rb_cCArray, "_scan_index_v2",
|
|
1034
|
+
rb_ca_s_scan_index_v2, 2);
|
|
1035
|
+
}
|