carray 2.0.1 → 3.0.1
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 +6 -25
- data/CHANGELOG.md +338 -0
- data/{NEWS.md → CHANGELOG.v1.md} +3 -0
- data/LICENSE +1 -1
- data/README.md +120 -36
- data/carray.gemspec +32 -30
- 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 +1244 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +124 -0
- data/ext/ca_binop_dispatch.h +152 -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 +239 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4367 -0
- data/ext/ca_kernel_iterator.h +2596 -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 +839 -0
- data/ext/ca_obj_binop.c +948 -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 +967 -0
- data/ext/ca_obj_face.c +750 -0
- data/ext/ca_obj_face.h +279 -0
- data/ext/ca_obj_fake.c +239 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +308 -0
- data/ext/ca_obj_grid.c +866 -440
- data/ext/ca_obj_meld.c +1039 -0
- data/ext/ca_obj_moncmp.c +588 -0
- data/ext/ca_obj_monop.c +1123 -0
- data/ext/ca_obj_object.c +866 -296
- data/ext/ca_obj_record.c +470 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +593 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +624 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1306 -0
- data/ext/ca_obj_shift.c +231 -793
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2584 -0
- data/ext/ca_obj_string.c +270 -0
- data/ext/ca_obj_tile.c +622 -0
- data/ext/ca_obj_time.c +548 -0
- data/ext/ca_obj_timedelta.c +437 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +785 -0
- data/ext/ca_obj_window.c +1202 -565
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_cmplx64.h +123 -0
- data/ext/ca_op_ipower.c +316 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +473 -0
- data/ext/ca_sweep_engine.h +166 -0
- data/ext/ca_transform_common.c +235 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +810 -420
- data/ext/carray_access.c +873 -731
- data/ext/carray_attribute.c +98 -329
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +376 -0
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +2897 -874
- data/ext/carray_call_cfunc.h +313 -0
- data/ext/carray_cast.c +1264 -315
- 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 +168 -270
- data/ext/carray_core.c +1396 -206
- 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 +1021 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +136 -0
- data/ext/carray_kernels_bincmp.c +4446 -0
- data/ext/carray_kernels_binop.c +11001 -0
- data/ext/carray_kernels_init.c +1131 -0
- data/ext/carray_kernels_map.c +3467 -0
- data/ext/carray_kernels_moncmp.c +2097 -0
- data/ext/carray_kernels_monop.c +18313 -0
- data/ext/carray_kernels_reduce_aggregate.c +25837 -0
- data/ext/carray_kernels_reduce_boolean.c +330 -0
- data/ext/carray_kernels_reduce_cumulative.c +14593 -0
- data/ext/carray_kernels_reduce_extreme.c +16948 -0
- data/ext/carray_kernels_reduce_variance.c +3910 -0
- data/ext/carray_kernels_scan.c +3693 -0
- data/ext/carray_kernels_search.c +32138 -0
- data/ext/carray_kernels_sort.c +10626 -0
- data/ext/carray_kernels_triop.c +1392 -0
- data/ext/carray_lazy.c +737 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +853 -158
- 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 +1650 -0
- data/ext/carray_operator.c +1525 -320
- 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 +234 -55
- data/ext/mk_call_cfunc.rb +671 -0
- data/ext/mkkernel.rb +9096 -0
- data/ext/ruby_carray.c +211 -108
- 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 +239 -0
- data/lib/carray/autoload_method_extension.rb +45 -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 +614 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1084 -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 +160 -328
- data/lib/carray/core_extensions.rb +297 -0
- data/lib/carray/data_type_extension.rb +250 -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 +642 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +321 -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 +316 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/fuse_source.rb +123 -0
- data/lib/carray/fusion.rb +218 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -26
- data/lib/carray/iterator.rb +58 -349
- data/lib/carray/lazy.rb +941 -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 +52 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +90 -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 +161 -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 +89 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +305 -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 +2654 -38
- data/lib/carray/window_iterator.rb +927 -0
- data/lib/carray.rb +55 -57
- data/yard-stubs/ca_obj_array.rb +385 -0
- data/yard-stubs/ca_obj_bitarray.rb +38 -0
- data/yard-stubs/ca_obj_bitfield.rb +43 -0
- data/yard-stubs/ca_obj_block.rb +73 -0
- data/yard-stubs/ca_obj_byte_swap.rb +56 -0
- data/yard-stubs/ca_obj_fake.rb +31 -0
- data/yard-stubs/ca_obj_farray.rb +32 -0
- data/yard-stubs/ca_obj_field.rb +45 -0
- data/yard-stubs/ca_obj_grid.rb +35 -0
- data/yard-stubs/ca_obj_refer.rb +72 -0
- data/yard-stubs/ca_obj_roll.rb +45 -0
- data/yard-stubs/ca_obj_shift.rb +43 -0
- data/yard-stubs/ca_obj_stride.rb +181 -0
- data/yard-stubs/ca_obj_tile.rb +29 -0
- data/yard-stubs/ca_obj_transpose.rb +40 -0
- data/yard-stubs/ca_obj_window.rb +49 -0
- data/yard-stubs/carray_access.rb +131 -0
- data/yard-stubs/carray_attribute.rb +246 -0
- data/yard-stubs/carray_broadcast.rb +37 -0
- data/yard-stubs/carray_cast.rb +489 -0
- data/yard-stubs/carray_class.rb +65 -0
- data/yard-stubs/carray_conversion.rb +76 -0
- data/yard-stubs/carray_copy.rb +79 -0
- data/yard-stubs/carray_core.rb +114 -0
- data/yard-stubs/carray_count.rb +79 -0
- data/yard-stubs/carray_element.rb +108 -0
- data/yard-stubs/carray_generate.rb +66 -0
- data/yard-stubs/carray_lazy.rb +23 -0
- data/yard-stubs/carray_loop.rb +140 -0
- data/yard-stubs/carray_mask.rb +259 -0
- data/yard-stubs/carray_math.rb +132 -0
- data/yard-stubs/carray_mathfunc.rb +45 -0
- data/yard-stubs/carray_median_percentile.rb +89 -0
- data/yard-stubs/carray_memory_view.rb +163 -0
- data/yard-stubs/carray_order.rb +312 -0
- data/yard-stubs/carray_random.rb +89 -0
- data/yard-stubs/carray_scatter.rb +106 -0
- data/yard-stubs/carray_slab.rb +57 -0
- data/yard-stubs/carray_sort.rb +163 -0
- data/yard-stubs/carray_test.rb +85 -0
- data/yard-stubs/carray_undef.rb +64 -0
- data/yard-stubs/carray_utils.rb +97 -0
- data/yard-stubs/ruby_carray.rb +193 -0
- metadata +220 -138
- 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/ca_obj_unbound_repeat.c +0 -529
- 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/mailmap +0 -1
- 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/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
data/ext/carray_access.c
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
The indexer: CArray#[] and #[]= plus their helpers (fill, addr2index,
|
|
4
|
+
index2addr, normalize_index, scan_index). Classifies an index spec via
|
|
5
|
+
rb_ca_scan_index (forwarded to ext/carray_index_classifier.c) and
|
|
6
|
+
dispatches each CA_REG_* case to the matching view constructor
|
|
7
|
+
(CABlock / CASelect / CAGrid / CARemap / CASlabIterator / ...).
|
|
8
8
|
|
|
9
9
|
---------------------------------------------------------------------------- */
|
|
10
10
|
|
|
11
11
|
#include "carray.h"
|
|
12
|
+
#include "carray_internal.h" /* per-obj_type view constructors */
|
|
13
|
+
#include "ca_obj_face.h"
|
|
14
|
+
#include "carray_index_classifier.h" /* rb_ca_scan_index_v2 forward decl */
|
|
12
15
|
|
|
13
16
|
static ID id_begin, id_end, id_excl_end;
|
|
14
17
|
#define RANGE_BEG(r) (rb_funcall(r, id_begin, 0))
|
|
15
18
|
#define RANGE_END(r) (rb_funcall(r, id_end, 0))
|
|
16
19
|
#define RANGE_EXCL(r) (rb_funcall(r, id_excl_end, 0))
|
|
17
20
|
|
|
18
|
-
static ID
|
|
19
|
-
static VALUE sym_star, sym_perc;
|
|
21
|
+
static ID id_to_ca;
|
|
22
|
+
static VALUE sym_star, sym_perc, sym_under, sym_gt, sym_tilde;
|
|
20
23
|
static VALUE S_CAInfo;
|
|
21
24
|
|
|
22
25
|
VALUE
|
|
@@ -54,10 +57,10 @@ rb_ca_store_index (VALUE self, ca_size_t *idx, VALUE rval)
|
|
|
54
57
|
ca_store_index(ca, idx, v);
|
|
55
58
|
}
|
|
56
59
|
else {
|
|
57
|
-
char *v =
|
|
60
|
+
char *v = xmalloc(ca->bytes);
|
|
58
61
|
rb_ca_obj2ptr(self, rval, v);
|
|
59
62
|
ca_store_index(ca, idx, v);
|
|
60
|
-
|
|
63
|
+
xfree(v);
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
|
|
@@ -82,10 +85,10 @@ rb_ca_fetch_index (VALUE self, ca_size_t *idx)
|
|
|
82
85
|
out = rb_ca_ptr2obj(self, v);
|
|
83
86
|
}
|
|
84
87
|
else {
|
|
85
|
-
char *v =
|
|
88
|
+
char *v = xmalloc(ca->bytes);
|
|
86
89
|
ca_fetch_index(ca, idx, v);
|
|
87
90
|
out = rb_ca_ptr2obj(self, v);
|
|
88
|
-
|
|
91
|
+
xfree(v);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
/* check if the element is masked */
|
|
@@ -98,6 +101,19 @@ rb_ca_fetch_index (VALUE self, ca_size_t *idx)
|
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
|
|
104
|
+
/* Face scalar decode (invoked if the subclass defines storage_to_scalar(raw)) */
|
|
105
|
+
CA_FACE_STORAGE_TO_SCALAR_IF_FACE(out, self, ca);
|
|
106
|
+
|
|
107
|
+
/* Boolean scalar access yields true/false, not Integer 0/1. Bulk paths
|
|
108
|
+
(to_a / cast / serialize via rb_ca_ptr2obj) keep 0/1. Gate on the raw
|
|
109
|
+
INT2FIX(0/1) so a boolean-storage Face that decoded to its own object is
|
|
110
|
+
left untouched; note INT2FIX(0) is truthy in Ruby, so map by value, not
|
|
111
|
+
by RTEST. */
|
|
112
|
+
if ( ca->data_type == CA_BOOLEAN &&
|
|
113
|
+
( out == INT2FIX(0) || out == INT2FIX(1) ) ) {
|
|
114
|
+
out = ( out == INT2FIX(1) ) ? Qtrue : Qfalse;
|
|
115
|
+
}
|
|
116
|
+
|
|
101
117
|
return out;
|
|
102
118
|
}
|
|
103
119
|
|
|
@@ -134,10 +150,10 @@ rb_ca_store_addr (VALUE self, ca_size_t addr, VALUE rval)
|
|
|
134
150
|
ca_store_addr(ca, addr, v);
|
|
135
151
|
}
|
|
136
152
|
else {
|
|
137
|
-
char *v =
|
|
153
|
+
char *v = xmalloc(ca->bytes);
|
|
138
154
|
rb_ca_obj2ptr(self, rval, v);
|
|
139
155
|
ca_store_addr(ca, addr, v);
|
|
140
|
-
|
|
156
|
+
xfree(v);
|
|
141
157
|
}
|
|
142
158
|
}
|
|
143
159
|
|
|
@@ -162,10 +178,10 @@ rb_ca_fetch_addr (VALUE self, ca_size_t addr)
|
|
|
162
178
|
out = rb_ca_ptr2obj(self, v);
|
|
163
179
|
}
|
|
164
180
|
else {
|
|
165
|
-
char *v =
|
|
181
|
+
char *v = xmalloc(ca->bytes);
|
|
166
182
|
ca_fetch_addr(ca, addr, v);
|
|
167
183
|
out = rb_ca_ptr2obj(self, v);
|
|
168
|
-
|
|
184
|
+
xfree(v);
|
|
169
185
|
}
|
|
170
186
|
|
|
171
187
|
/* check if the element is masked */
|
|
@@ -178,18 +194,18 @@ rb_ca_fetch_addr (VALUE self, ca_size_t addr)
|
|
|
178
194
|
}
|
|
179
195
|
}
|
|
180
196
|
|
|
197
|
+
/* Face scalar decode */
|
|
198
|
+
CA_FACE_STORAGE_TO_SCALAR_IF_FACE(out, self, ca);
|
|
199
|
+
|
|
200
|
+
/* Boolean scalar access yields true/false (see rb_ca_fetch_index). */
|
|
201
|
+
if ( ca->data_type == CA_BOOLEAN &&
|
|
202
|
+
( out == INT2FIX(0) || out == INT2FIX(1) ) ) {
|
|
203
|
+
out = ( out == INT2FIX(1) ) ? Qtrue : Qfalse;
|
|
204
|
+
}
|
|
205
|
+
|
|
181
206
|
return out;
|
|
182
207
|
}
|
|
183
208
|
|
|
184
|
-
/* yard:
|
|
185
|
-
class CArray
|
|
186
|
-
def fill
|
|
187
|
-
end
|
|
188
|
-
def fill_copy
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
*/
|
|
192
|
-
|
|
193
209
|
VALUE
|
|
194
210
|
rb_ca_fill (VALUE self, VALUE rval)
|
|
195
211
|
{
|
|
@@ -199,7 +215,7 @@ rb_ca_fill (VALUE self, VALUE rval)
|
|
|
199
215
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
200
216
|
|
|
201
217
|
if ( ca_is_empty(ca) ) {
|
|
202
|
-
return
|
|
218
|
+
return self; /* empty = no-op fill; return self for chaining */
|
|
203
219
|
}
|
|
204
220
|
|
|
205
221
|
if ( rval == CA_UNDEF ) {
|
|
@@ -211,14 +227,14 @@ rb_ca_fill (VALUE self, VALUE rval)
|
|
|
211
227
|
ca_fill(ca->mask, &one);
|
|
212
228
|
}
|
|
213
229
|
else {
|
|
214
|
-
char *fval =
|
|
230
|
+
char *fval = xmalloc(ca->bytes);
|
|
215
231
|
boolean8_t zero = 0;
|
|
216
232
|
rb_ca_obj2ptr(self, rval, fval);
|
|
217
233
|
if ( ca_has_mask(ca) ) {
|
|
218
234
|
ca_fill(ca->mask, &zero);
|
|
219
235
|
}
|
|
220
236
|
ca_fill(ca, fval);
|
|
221
|
-
|
|
237
|
+
xfree(fval);
|
|
222
238
|
}
|
|
223
239
|
|
|
224
240
|
return self;
|
|
@@ -266,11 +282,6 @@ ary_guess_shape (VALUE ary, int level, int *max_level, ca_size_t *dim)
|
|
|
266
282
|
}
|
|
267
283
|
}
|
|
268
284
|
|
|
269
|
-
/* yard:
|
|
270
|
-
def CArray.guess_array_shape (arg)
|
|
271
|
-
end
|
|
272
|
-
*/
|
|
273
|
-
|
|
274
285
|
static VALUE
|
|
275
286
|
rb_ca_s_guess_array_shape (VALUE self, VALUE ary)
|
|
276
287
|
{
|
|
@@ -340,7 +351,7 @@ rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
|
340
351
|
rb_raise(rb_eRuntimeError, "invalid shape array for conversion to carray");
|
|
341
352
|
}
|
|
342
353
|
else {
|
|
343
|
-
VALUE out = rb_ary_new2(0);
|
|
354
|
+
volatile VALUE out = rb_ary_new2(0);
|
|
344
355
|
int len = 0;
|
|
345
356
|
ary_flatten_upto_level(ary, max_level, 0, out, &len);
|
|
346
357
|
if ( len != elements ) {
|
|
@@ -366,7 +377,7 @@ rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
|
366
377
|
}
|
|
367
378
|
|
|
368
379
|
if ( same_shape ) {
|
|
369
|
-
VALUE out = rb_ary_new2(0);
|
|
380
|
+
volatile VALUE out = rb_ary_new2(0);
|
|
370
381
|
int len = 0;
|
|
371
382
|
ary_flatten_upto_level(ary, ca->ndim-1, 0, out, &len);
|
|
372
383
|
|
|
@@ -388,7 +399,7 @@ rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
|
388
399
|
}
|
|
389
400
|
|
|
390
401
|
if ( level >= 0 ) {
|
|
391
|
-
VALUE out = rb_ary_new2(0);
|
|
402
|
+
volatile VALUE out = rb_ary_new2(0);
|
|
392
403
|
int len = 0;
|
|
393
404
|
ary_flatten_upto_level(ary, level, 0, out, &len);
|
|
394
405
|
if ( len != elements ) {
|
|
@@ -411,7 +422,7 @@ rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap)
|
|
|
411
422
|
} \
|
|
412
423
|
if ( index < 0 || index >= (dim) ) { \
|
|
413
424
|
rb_raise(rb_eIndexError, \
|
|
414
|
-
"index out of range at %i-dim ( %
|
|
425
|
+
"index out of range at %i-dim ( %" PRId64 " <=> 0..%" PRId64 " )", \
|
|
415
426
|
i, (ca_size_t) index, (ca_size_t) (dim-1)); \
|
|
416
427
|
}
|
|
417
428
|
|
|
@@ -419,522 +430,8 @@ void
|
|
|
419
430
|
rb_ca_scan_index (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
420
431
|
long argc, VALUE *argv, CAIndexInfo *info)
|
|
421
432
|
{
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
info->ndim = 0;
|
|
425
|
-
info->select = NULL;
|
|
426
|
-
|
|
427
|
-
if ( argc == 0 ) { /* ca[] -> CA_REG_ALL */
|
|
428
|
-
info->type = CA_REG_ALL;
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/* ca[:method, ...] -> CA_REG_METHOD_CALL
|
|
433
|
-
ca[:i, ...] -> CA_REG_ITERATOR */
|
|
434
|
-
if ( TYPE(argv[0]) == T_SYMBOL ) {
|
|
435
|
-
const char *symstr = rb_id2name(SYM2ID(argv[0]));
|
|
436
|
-
if ( strlen(symstr) > 1 ) { /* ca[:method, ...] -> CA_REG_METHOD_CALL */
|
|
437
|
-
info->type = CA_REG_METHOD_CALL;
|
|
438
|
-
info->symbol = argv[0];
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
if ( argc == 1 ) {
|
|
444
|
-
|
|
445
|
-
volatile VALUE arg = argv[0];
|
|
446
|
-
|
|
447
|
-
if ( arg == Qfalse ) { /* ca[false] -> CA_REG_ALL */
|
|
448
|
-
info->type = CA_REG_ALL;
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
if ( rb_obj_is_carray(arg) ) {
|
|
453
|
-
CArray *cs;
|
|
454
|
-
TypedData_Get_Struct(arg, CArray, &carray_data_type, cs);
|
|
455
|
-
if ( ca_is_integer_type(cs) ) {
|
|
456
|
-
#if 0
|
|
457
|
-
if ( ca_ndim == 1 && cs->ndim == 1 ) { /* ca[g] -> CA_REG_GRID (1d) */
|
|
458
|
-
info->type = CA_REG_GRID;
|
|
459
|
-
}
|
|
460
|
-
else { /* ca[m] -> CA_REG_MAPPER (2d...) */
|
|
461
|
-
info->type = CA_REG_MAPPING;
|
|
462
|
-
}
|
|
463
|
-
#endif
|
|
464
|
-
info->type = CA_REG_MAPPING;
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
else if ( ca_is_boolean_type(cs) ) {
|
|
468
|
-
/* ca[selector] -> CA_REG_SELECT */
|
|
469
|
-
if ( ca_elements != cs->elements ) {
|
|
470
|
-
rb_raise(rb_eRuntimeError,
|
|
471
|
-
"mismatch of # of elements ( %lld <=> %lld ) in reference by selection",
|
|
472
|
-
(ca_size_t) cs->elements, (ca_size_t) ca_elements);
|
|
473
|
-
}
|
|
474
|
-
info->type = CA_REG_SELECT;
|
|
475
|
-
info->select = cs;
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
rb_raise(rb_eIndexError,
|
|
480
|
-
"data_type %s is invalid for reference by selection/mapping" \
|
|
481
|
-
"(should be boolean or integer)",
|
|
482
|
-
ca_type_name[cs->data_type]);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
if ( TYPE(arg) == T_STRING ) {
|
|
487
|
-
if ( StringValuePtr(arg)[0] == '@' ) { /* ca["@name"] -> CA_REG_ATTRIBUTE */
|
|
488
|
-
info->type = CA_REG_ATTRIBUTE;
|
|
489
|
-
info->symbol = rb_str_new2(StringValuePtr(arg)+1);
|
|
490
|
-
}
|
|
491
|
-
else { /* ca["field"] -> CA_REG_MEMBER */
|
|
492
|
-
info->type = CA_REG_MEMBER;
|
|
493
|
-
info->symbol = ID2SYM(rb_intern(StringValuePtr(arg)));
|
|
494
|
-
}
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
if ( arg == sym_star ) { /* ca[:*] -> CA_REG_UNBOUND_REPEAT */
|
|
499
|
-
info->type = CA_REG_UNBOUND_REPEAT;
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
if ( ca_ndim > 1 ) { /* ca.ndim > 1 */
|
|
504
|
-
if ( rb_obj_is_kind_of(arg, rb_cInteger) ) { /* ca[n] -> CA_REG_ADDRESS */
|
|
505
|
-
ca_size_t addr;
|
|
506
|
-
info->type = CA_REG_ADDRESS;
|
|
507
|
-
info->ndim = 1;
|
|
508
|
-
addr = NUM2SIZE(arg);
|
|
509
|
-
if ( info->range_check ) {
|
|
510
|
-
CA_CHECK_INDEX(addr, ca_elements);
|
|
511
|
-
}
|
|
512
|
-
info->index[0].scalar = addr;
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
else if ( arg == Qnil ) {
|
|
516
|
-
info->type = CA_REG_FLATTEN;
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
else { /* ca[i..j] -> CA_REG_ADDRESS_COMPLEX */
|
|
520
|
-
info->type = CA_REG_ADDRESS_COMPLEX;
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/* continue to next section */
|
|
527
|
-
|
|
528
|
-
if ( argc >= 1 ) {
|
|
529
|
-
int8_t is_point = 0, is_all = 0, is_iterator = 0, is_repeat=0, is_grid=0;
|
|
530
|
-
int8_t has_rubber = 0;
|
|
531
|
-
int32_t *index_type = info->index_type;
|
|
532
|
-
CAIndex *index = info->index;
|
|
533
|
-
|
|
534
|
-
for (i=0; i<argc; i++) {
|
|
535
|
-
if ( argv[i] == sym_perc ) {
|
|
536
|
-
is_repeat = 1;
|
|
537
|
-
goto loop_exit; /* ca[--,:%,--] -> CA_REG_REPEAT */
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
if ( argv[i] == sym_star ) {
|
|
541
|
-
is_repeat = 2;
|
|
542
|
-
goto loop_exit; /* ca[--,:*,--] -> CA_REG_UNBOUND_REPEAT */
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
if ( argv[i] == Qfalse ) { /* ca[--,false,--] (rubber dimension) */
|
|
546
|
-
has_rubber = 1;
|
|
547
|
-
if ( argc > ca_ndim + 1 ) {
|
|
548
|
-
rb_raise(rb_eIndexError,
|
|
549
|
-
"index specification exceeds the ndim of carray (%i)",
|
|
550
|
-
ca_ndim);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
if ( ! has_rubber && ca_ndim != argc ) {
|
|
556
|
-
rb_raise(rb_eIndexError,
|
|
557
|
-
"number of indices exceeds the ndim of carray (%i > %i)",
|
|
558
|
-
(int) argc, ca_ndim);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
info->ndim = argc;
|
|
562
|
-
|
|
563
|
-
for (i=0; i<argc; i++) {
|
|
564
|
-
volatile VALUE arg = argv[i];
|
|
565
|
-
|
|
566
|
-
retry:
|
|
567
|
-
|
|
568
|
-
if ( rb_obj_is_kind_of(arg, rb_cInteger) ) { /* ca[--,i,--] */
|
|
569
|
-
ca_size_t scalar;
|
|
570
|
-
index_type[i] = CA_IDX_SCALAR;
|
|
571
|
-
scalar = NUM2SIZE(arg);
|
|
572
|
-
if ( info->range_check ) {
|
|
573
|
-
CA_CHECK_INDEX_AT(scalar, ca_dim[i], i);
|
|
574
|
-
}
|
|
575
|
-
index[i].scalar = scalar;
|
|
576
|
-
}
|
|
577
|
-
else if ( NIL_P(arg) ) { /* ca[--,nil,--] */
|
|
578
|
-
index_type[i] = CA_IDX_ALL;
|
|
579
|
-
}
|
|
580
|
-
else if ( arg == Qfalse ) { /* ca[--,false,--] */
|
|
581
|
-
int8_t rndim = ca_ndim - argc + 1;
|
|
582
|
-
int8_t j;
|
|
583
|
-
for (j=0; j<rndim; j++) {
|
|
584
|
-
index_type[i+j] = CA_IDX_ALL;
|
|
585
|
-
}
|
|
586
|
-
i += rndim-1;
|
|
587
|
-
argv -= rndim-1;
|
|
588
|
-
argc = ca_ndim;
|
|
589
|
-
info->ndim = ca_ndim;
|
|
590
|
-
}
|
|
591
|
-
else if ( rb_obj_is_kind_of(arg, rb_cRange) ) { /* ca[--,i..j,--] */
|
|
592
|
-
ca_size_t start, last, excl, count, step;
|
|
593
|
-
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
594
|
-
iv_beg = RANGE_BEG(arg);
|
|
595
|
-
iv_end = RANGE_END(arg);
|
|
596
|
-
iv_excl = RANGE_EXCL(arg);
|
|
597
|
-
index_type[i] = CA_IDX_BLOCK; /* convert to block */
|
|
598
|
-
if ( NIL_P(iv_beg) ) {
|
|
599
|
-
start = 0;
|
|
600
|
-
}
|
|
601
|
-
else {
|
|
602
|
-
start = NUM2SIZE(iv_beg);
|
|
603
|
-
}
|
|
604
|
-
if ( NIL_P(iv_end) ) {
|
|
605
|
-
last = -1;
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
last = NUM2SIZE(iv_end);
|
|
609
|
-
}
|
|
610
|
-
excl = RTEST(iv_excl);
|
|
611
|
-
|
|
612
|
-
if ( info->range_check ) {
|
|
613
|
-
CA_CHECK_INDEX_AT(start, ca_dim[i], i);
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
if ( last < 0 ) { /* don't use CA_CHECK_INDEX for excl */
|
|
617
|
-
last += ca_dim[i];
|
|
618
|
-
}
|
|
619
|
-
if ( excl && ( start == last ) ) {
|
|
620
|
-
index[i].block.start = start;
|
|
621
|
-
index[i].block.count = 0;
|
|
622
|
-
index[i].block.step = 1;
|
|
623
|
-
}
|
|
624
|
-
else {
|
|
625
|
-
if ( excl ) {
|
|
626
|
-
last += ( (last>=start) ? -1 : 1 );
|
|
627
|
-
}
|
|
628
|
-
if ( info->range_check ) {
|
|
629
|
-
if ( last < 0 || last >= ca_dim[i] ) {
|
|
630
|
-
rb_raise(rb_eIndexError,
|
|
631
|
-
"index %lld is out of range (0..%lld) at %i-dim",
|
|
632
|
-
(ca_size_t) last, (ca_size_t) (ca_dim[i]-1), i);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
index[i].block.start = start;
|
|
636
|
-
index[i].block.count = count = llabs(last - start) + 1;
|
|
637
|
-
index[i].block.step = step = ( last >= start ) ? 1 : -1;
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
|
|
641
|
-
else if ( rb_obj_is_kind_of(arg, rb_cArithSeq) ) { /* ca[--,ArithSeq,--]*/
|
|
642
|
-
ca_size_t start, last, excl, count, step, bound;
|
|
643
|
-
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
644
|
-
rb_arithmetic_sequence_components_t x;
|
|
645
|
-
rb_arithmetic_sequence_extract(arg, &x);
|
|
646
|
-
iv_beg = x.begin;
|
|
647
|
-
iv_end = x.end;
|
|
648
|
-
iv_excl = x.exclude_end;
|
|
649
|
-
step = NUM2SIZE(x.step);
|
|
650
|
-
if ( NIL_P(iv_beg) ) {
|
|
651
|
-
start = 0;
|
|
652
|
-
}
|
|
653
|
-
else {
|
|
654
|
-
start = NUM2SIZE(iv_beg);
|
|
655
|
-
}
|
|
656
|
-
if ( NIL_P(iv_end) ) {
|
|
657
|
-
last = -1;
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
last = NUM2SIZE(iv_end);
|
|
661
|
-
}
|
|
662
|
-
excl = RTEST(iv_excl);
|
|
663
|
-
if ( step == 0 ) {
|
|
664
|
-
rb_raise(rb_eRuntimeError,
|
|
665
|
-
"step in index equals to 0 in block reference");
|
|
666
|
-
}
|
|
667
|
-
index_type[i] = CA_IDX_BLOCK;
|
|
668
|
-
CA_CHECK_INDEX_AT(start, ca_dim[i], i);
|
|
669
|
-
if ( last < 0 ) {
|
|
670
|
-
last += ca_dim[i];
|
|
671
|
-
}
|
|
672
|
-
if ( excl && ( start == last ) ) {
|
|
673
|
-
index[i].block.start = start;
|
|
674
|
-
index[i].block.count = 0;
|
|
675
|
-
index[i].block.step = 1;
|
|
676
|
-
}
|
|
677
|
-
else {
|
|
678
|
-
if ( excl ) {
|
|
679
|
-
last += ( (last>=start) ? -1 : 1 );
|
|
680
|
-
}
|
|
681
|
-
if ( last < 0 || last >= ca_dim[i] ) {
|
|
682
|
-
rb_raise(rb_eIndexError,
|
|
683
|
-
"index %lld is out of range (0..%lld) at %i-dim",
|
|
684
|
-
(ca_size_t) last, (ca_size_t) (ca_dim[i]-1), i);
|
|
685
|
-
}
|
|
686
|
-
if ( (last - start) * step < 0 ) {
|
|
687
|
-
count = 1;
|
|
688
|
-
}
|
|
689
|
-
else {
|
|
690
|
-
count = llabs(last - start)/llabs(step) + 1;
|
|
691
|
-
}
|
|
692
|
-
bound = start + (count - 1)*step;
|
|
693
|
-
CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
|
|
694
|
-
index[i].block.start = start;
|
|
695
|
-
index[i].block.count = count;
|
|
696
|
-
index[i].block.step = step;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
#endif
|
|
700
|
-
else if ( TYPE(arg) == T_ARRAY ) { /* ca[--,[array],--] */
|
|
701
|
-
if ( RARRAY_LEN(arg) == 1 ) {
|
|
702
|
-
VALUE arg0 = rb_ary_entry(arg, 0);
|
|
703
|
-
if ( NIL_P(arg0) ) { /* ca[--,[nil],--]*/
|
|
704
|
-
index_type[i] = CA_IDX_ALL;
|
|
705
|
-
}
|
|
706
|
-
else if ( rb_obj_is_kind_of(arg0, rb_cRange) ) {
|
|
707
|
-
/* ca[--,[i..j],--] */
|
|
708
|
-
arg = arg0;
|
|
709
|
-
goto retry;
|
|
710
|
-
}
|
|
711
|
-
else { /* ca[--,[i],--]*/
|
|
712
|
-
ca_size_t start;
|
|
713
|
-
start = NUM2SIZE(arg0);
|
|
714
|
-
CA_CHECK_INDEX_AT(start, ca_dim[i], i);
|
|
715
|
-
index_type[i] = CA_IDX_BLOCK;
|
|
716
|
-
index[i].block.start = start;
|
|
717
|
-
index[i].block.count = 1;
|
|
718
|
-
index[i].block.step = 1;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
else if ( RARRAY_LEN(arg) == 2 ) {
|
|
722
|
-
VALUE arg0 = rb_ary_entry(arg, 0);
|
|
723
|
-
VALUE arg1 = rb_ary_entry(arg, 1);
|
|
724
|
-
if ( NIL_P(arg0) ) { /* ca[--,[nil,k],--]*/
|
|
725
|
-
ca_size_t start, last, count, step, bound;
|
|
726
|
-
step = NUM2SIZE(arg1);
|
|
727
|
-
if ( step == 0 ) {
|
|
728
|
-
rb_raise(rb_eRuntimeError,
|
|
729
|
-
"step in index equals to 0 in block reference");
|
|
730
|
-
}
|
|
731
|
-
start = 0;
|
|
732
|
-
last = ca_dim[i]-1;
|
|
733
|
-
if ( step < 0 ) {
|
|
734
|
-
count = 1;
|
|
735
|
-
}
|
|
736
|
-
else {
|
|
737
|
-
count = last/step + 1;
|
|
738
|
-
}
|
|
739
|
-
bound = start + (count - 1)*step;
|
|
740
|
-
CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
|
|
741
|
-
index_type[i] = CA_IDX_BLOCK;
|
|
742
|
-
index[i].block.start = start;
|
|
743
|
-
index[i].block.count = count;
|
|
744
|
-
index[i].block.step = step;
|
|
745
|
-
}
|
|
746
|
-
else if ( rb_obj_is_kind_of(arg0, rb_cRange) ) { /* ca[--,[i..j,k],--]*/
|
|
747
|
-
ca_size_t start, last, excl, count, step, bound;
|
|
748
|
-
volatile VALUE iv_beg, iv_end, iv_excl;
|
|
749
|
-
iv_beg = RANGE_BEG(arg0);
|
|
750
|
-
iv_end = RANGE_END(arg0);
|
|
751
|
-
iv_excl = RANGE_EXCL(arg0);
|
|
752
|
-
if ( NIL_P(iv_beg) ) {
|
|
753
|
-
start = 0;
|
|
754
|
-
}
|
|
755
|
-
else {
|
|
756
|
-
start = NUM2SIZE(iv_beg);
|
|
757
|
-
}
|
|
758
|
-
if ( NIL_P(iv_end) ) {
|
|
759
|
-
last = -1;
|
|
760
|
-
}
|
|
761
|
-
else {
|
|
762
|
-
last = NUM2SIZE(iv_end);
|
|
763
|
-
}
|
|
764
|
-
excl = RTEST(iv_excl);
|
|
765
|
-
step = NUM2SIZE(arg1);
|
|
766
|
-
if ( step == 0 ) {
|
|
767
|
-
rb_raise(rb_eRuntimeError,
|
|
768
|
-
"step in index equals to 0 in block reference");
|
|
769
|
-
}
|
|
770
|
-
index_type[i] = CA_IDX_BLOCK;
|
|
771
|
-
CA_CHECK_INDEX_AT(start, ca_dim[i], i);
|
|
772
|
-
if ( last < 0 ) {
|
|
773
|
-
last += ca_dim[i];
|
|
774
|
-
}
|
|
775
|
-
if ( excl && ( start == last ) ) {
|
|
776
|
-
index[i].block.start = start;
|
|
777
|
-
index[i].block.count = 0;
|
|
778
|
-
index[i].block.step = 1;
|
|
779
|
-
}
|
|
780
|
-
else {
|
|
781
|
-
if ( excl ) {
|
|
782
|
-
last += ( (last>=start) ? -1 : 1 );
|
|
783
|
-
}
|
|
784
|
-
if ( last < 0 || last >= ca_dim[i] ) {
|
|
785
|
-
rb_raise(rb_eIndexError,
|
|
786
|
-
"index %lld is out of range (0..%lld) at %i-dim",
|
|
787
|
-
(ca_size_t) last, (ca_size_t) (ca_dim[i]-1), i);
|
|
788
|
-
}
|
|
789
|
-
if ( (last - start) * step < 0 ) {
|
|
790
|
-
count = 1;
|
|
791
|
-
}
|
|
792
|
-
else {
|
|
793
|
-
count = llabs(last - start)/llabs(step) + 1;
|
|
794
|
-
}
|
|
795
|
-
bound = start + (count - 1)*step;
|
|
796
|
-
CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
|
|
797
|
-
index[i].block.start = start;
|
|
798
|
-
index[i].block.count = count;
|
|
799
|
-
index[i].block.step = step;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
else { /* ca[--,[i,j],--]*/
|
|
803
|
-
ca_size_t start, count, bound;
|
|
804
|
-
start = NUM2SIZE(arg0);
|
|
805
|
-
count = NUM2SIZE(arg1);
|
|
806
|
-
bound = start + (count - 1);
|
|
807
|
-
CA_CHECK_INDEX_AT(start, ca_dim[i], i);
|
|
808
|
-
CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
|
|
809
|
-
index_type[i] = CA_IDX_BLOCK;
|
|
810
|
-
index[i].block.start = start;
|
|
811
|
-
index[i].block.count = count;
|
|
812
|
-
index[i].block.step = 1;
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
else if ( RARRAY_LEN(arg) == 3 ) { /* ca[--,[i,j,k],--]*/
|
|
816
|
-
ca_size_t start, count, step, bound;
|
|
817
|
-
start = NUM2SIZE(rb_ary_entry(arg, 0));
|
|
818
|
-
count = NUM2SIZE(rb_ary_entry(arg, 1));
|
|
819
|
-
step = NUM2SIZE(rb_ary_entry(arg, 2));
|
|
820
|
-
if ( step == 0 ) {
|
|
821
|
-
rb_raise(rb_eRuntimeError,
|
|
822
|
-
"step in index equals to 0 in block reference");
|
|
823
|
-
}
|
|
824
|
-
bound = start + (count - 1)*step;
|
|
825
|
-
CA_CHECK_INDEX_AT(start, ca_dim[i], i);
|
|
826
|
-
CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
|
|
827
|
-
index_type[i] = CA_IDX_BLOCK;
|
|
828
|
-
index[i].block.start = start;
|
|
829
|
-
index[i].block.count = count;
|
|
830
|
-
index[i].block.step = step;
|
|
831
|
-
}
|
|
832
|
-
else {
|
|
833
|
-
rb_raise(rb_eIndexError,
|
|
834
|
-
"invalid form of index range at %i-dim "\
|
|
835
|
-
"(should be [start[,count[,step]]], [range, step])",
|
|
836
|
-
i);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
else if ( rb_obj_is_kind_of(arg, rb_cSymbol) ) { /* ca[--,:i,--] */
|
|
840
|
-
if ( strlen(rb_id2name(SYM2ID(arg))) != 1 ) {
|
|
841
|
-
rb_raise(rb_eIndexError,
|
|
842
|
-
"symbol :%s is invalid as the index for dimension iterator "\
|
|
843
|
-
"(should be :a, :b, ... :z)",
|
|
844
|
-
rb_id2name(SYM2ID(arg)));
|
|
845
|
-
}
|
|
846
|
-
index_type[i] = CA_IDX_SYMBOL;
|
|
847
|
-
index[i].symbol.id = SYM2ID(arg);
|
|
848
|
-
index[i].symbol.spec = Qnil;
|
|
849
|
-
}
|
|
850
|
-
else if ( rb_obj_is_carray(arg) ) { /* ca[--,ca,--] */
|
|
851
|
-
CArray *ci;
|
|
852
|
-
TypedData_Get_Struct(arg, CArray, &carray_data_type, ci);
|
|
853
|
-
if ( ca_is_boolean_type(ci) || ca_is_integer_type(ci) ) {
|
|
854
|
-
is_grid = 1;
|
|
855
|
-
goto loop_exit;
|
|
856
|
-
}
|
|
857
|
-
else {
|
|
858
|
-
rb_raise(rb_eIndexError,
|
|
859
|
-
"data_type %s is invalid for reference by gridding at %i-dim "\
|
|
860
|
-
"(should be boolean or integer)",
|
|
861
|
-
ca_type_name[ci->data_type], i);
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
else {
|
|
865
|
-
VALUE inspect = rb_inspect(arg);
|
|
866
|
-
rb_raise(rb_eIndexError,
|
|
867
|
-
"object '%s' is invalid for the index for reference at %i-dim",
|
|
868
|
-
StringValuePtr(inspect), i);
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
if ( ca_ndim != info->ndim ) {
|
|
873
|
-
rb_raise(rb_eIndexError,
|
|
874
|
-
"number of indices does not equal to the ndim (%i != %i)",
|
|
875
|
-
info->ndim, ca_ndim);
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
is_point = 1;
|
|
879
|
-
is_all = 1;
|
|
880
|
-
is_iterator = 0;
|
|
881
|
-
is_grid = 0;
|
|
882
|
-
|
|
883
|
-
for (i=0; i<info->ndim; i++) {
|
|
884
|
-
switch ( info->index_type[i] ) {
|
|
885
|
-
case CA_IDX_SCALAR:
|
|
886
|
-
is_all = 0;
|
|
887
|
-
continue;
|
|
888
|
-
case CA_IDX_ALL:
|
|
889
|
-
is_point = 0;
|
|
890
|
-
continue;
|
|
891
|
-
case CA_IDX_SYMBOL:
|
|
892
|
-
is_iterator = 1;
|
|
893
|
-
goto loop_exit;
|
|
894
|
-
default:
|
|
895
|
-
is_point = 0;
|
|
896
|
-
is_all = 0;
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
loop_exit:
|
|
901
|
-
|
|
902
|
-
if ( is_repeat == 1 ) {
|
|
903
|
-
info->type = CA_REG_REPEAT;
|
|
904
|
-
}
|
|
905
|
-
else if ( is_repeat == 2 ) {
|
|
906
|
-
info->type = CA_REG_UNBOUND_REPEAT;
|
|
907
|
-
}
|
|
908
|
-
else if ( is_grid ) {
|
|
909
|
-
info->type = CA_REG_GRID;
|
|
910
|
-
}
|
|
911
|
-
else if ( is_iterator ) {
|
|
912
|
-
info->type = CA_REG_ITERATOR;
|
|
913
|
-
}
|
|
914
|
-
else if ( is_point ) {
|
|
915
|
-
info->type = CA_REG_POINT;
|
|
916
|
-
}
|
|
917
|
-
else if ( is_all ) {
|
|
918
|
-
info->type = CA_REG_BLOCK;
|
|
919
|
-
}
|
|
920
|
-
else {
|
|
921
|
-
info->type = CA_REG_BLOCK;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
if ( info->type == CA_REG_ITERATOR ) {
|
|
925
|
-
for (i=0; i<info->ndim; i++) {
|
|
926
|
-
if ( info->index_type[i] == CA_IDX_SCALAR ) {
|
|
927
|
-
ca_size_t start = info->index[i].scalar;
|
|
928
|
-
info->index_type[i] = CA_IDX_BLOCK;
|
|
929
|
-
info->index[i].block.start = start;
|
|
930
|
-
info->index[i].block.step = 1;
|
|
931
|
-
info->index[i].block.count = 1;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
433
|
+
/* Forwards to the v2 classifier in ext/carray_index_classifier.c. */
|
|
434
|
+
rb_ca_scan_index_v2(ca_ndim, ca_dim, ca_elements, argc, argv, info);
|
|
938
435
|
}
|
|
939
436
|
|
|
940
437
|
/* ----------------------------------------------------------------------- */
|
|
@@ -942,9 +439,7 @@ rb_ca_scan_index (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
|
942
439
|
static VALUE
|
|
943
440
|
rb_ca_ref_address (VALUE self, CAIndexInfo *info)
|
|
944
441
|
{
|
|
945
|
-
CArray *ca;
|
|
946
442
|
ca_size_t addr;
|
|
947
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
948
443
|
addr = info->index[0].scalar;
|
|
949
444
|
return rb_ca_fetch_addr(self, addr);
|
|
950
445
|
}
|
|
@@ -952,9 +447,7 @@ rb_ca_ref_address (VALUE self, CAIndexInfo *info)
|
|
|
952
447
|
static VALUE
|
|
953
448
|
rb_ca_store_address (VALUE self, CAIndexInfo *info, volatile VALUE rval)
|
|
954
449
|
{
|
|
955
|
-
CArray *ca;
|
|
956
450
|
ca_size_t addr;
|
|
957
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
958
451
|
addr = info->index[0].scalar;
|
|
959
452
|
if ( rb_obj_is_cscalar(rval) ) {
|
|
960
453
|
rval = rb_ca_fetch_addr(rval, 0);
|
|
@@ -999,6 +492,14 @@ rb_ca_ref_all (VALUE self, CAIndexInfo *info)
|
|
|
999
492
|
return rb_funcall(self, rb_intern("refer"), 0);
|
|
1000
493
|
}
|
|
1001
494
|
|
|
495
|
+
static ID
|
|
496
|
+
ca_id_expression_evaluator (void)
|
|
497
|
+
{
|
|
498
|
+
static ID id = 0;
|
|
499
|
+
if ( ! id ) id = rb_intern("@expression_evaluator");
|
|
500
|
+
return id;
|
|
501
|
+
}
|
|
502
|
+
|
|
1002
503
|
VALUE
|
|
1003
504
|
rb_ca_store_all (VALUE self, VALUE rval)
|
|
1004
505
|
{
|
|
@@ -1022,36 +523,72 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
1022
523
|
CArray *cv;
|
|
1023
524
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
1024
525
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
526
|
+
/* Where something is registered to compute an expression, and this is
|
|
527
|
+
one, it is asked before the walk below -- it fills the destination
|
|
528
|
+
directly, which is the whole of the saving; making an array and
|
|
529
|
+
copying it over is most of the work once the expression itself is
|
|
530
|
+
fast. It may decline, and then the walk does it. Narrow on purpose:
|
|
531
|
+
the same shape and data type, so nothing here has to broadcast or
|
|
532
|
+
cast on the way. */
|
|
533
|
+
if ( ca_is_lazy_view(cv)
|
|
534
|
+
&& ca->data_type == cv->data_type
|
|
535
|
+
&& ca->ndim == cv->ndim
|
|
536
|
+
&& ca->elements == cv->elements
|
|
537
|
+
&& RTEST(rb_attr_get(rb_cCArray, ca_id_expression_evaluator())) ) {
|
|
538
|
+
int8_t k;
|
|
539
|
+
int same = 1;
|
|
540
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
541
|
+
if ( ca->dim[k] != cv->dim[k] ) { same = 0; break; }
|
|
542
|
+
}
|
|
543
|
+
if ( same ) {
|
|
544
|
+
VALUE fusion = rb_const_get(rb_cCArray, rb_intern("Fusion"));
|
|
545
|
+
if ( RTEST(rb_funcall(fusion, rb_intern("evaluate_into"), 2, rval, self)) ) {
|
|
546
|
+
return rval;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
1028
549
|
}
|
|
1029
550
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
(ca_size_t) ca->elements, (ca_size_t) cv->elements);
|
|
1034
|
-
}
|
|
551
|
+
/* The destination owns the shape; see ca_broadcast_to_destination. */
|
|
552
|
+
ca_broadcast_to_destination(self, &rval);
|
|
553
|
+
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
1035
554
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
555
|
+
/* Source delivery via ca_xfer_all into a local scratch instead of
|
|
556
|
+
ca_attach(cv). This routes through ca_*_func_xfer_all's per-region
|
|
557
|
+
partial-materialise path, avoiding a ca_attach(root) silent
|
|
558
|
+
transitive attach. When cv composes through a view root (CAFake /
|
|
559
|
+
CAByteSwap / CAGrid / etc.), attaching the root would materialise
|
|
560
|
+
the whole root (size = root->elements * root->bytes), producing a
|
|
561
|
+
catastrophic slowdown for size-gap cases like
|
|
562
|
+
big_virtual[100..200] = big_virtual[100..200].flip(0). The scratch
|
|
563
|
+
here is sized for cv only (cv->elements * cv->bytes), so the cost
|
|
564
|
+
scales with the view, not the root. (The dst-side ca_sync_data is
|
|
565
|
+
already an xfer_all PUT.) */
|
|
566
|
+
{
|
|
567
|
+
volatile VALUE scratch_holder;
|
|
568
|
+
ca_size_t cv_bytes = cv->bytes * cv->elements;
|
|
569
|
+
char *scratch = ALLOCV_N(char, scratch_holder, cv_bytes);
|
|
570
|
+
ca_xfer_all(cv, scratch, CA_XFER_GET);
|
|
571
|
+
|
|
572
|
+
if ( ca->data_type != cv->data_type ) {
|
|
573
|
+
ca_allocate(ca);
|
|
574
|
+
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
575
|
+
if ( ca->mask ) {
|
|
576
|
+
ca_cast_block_with_mask(ca->elements, cv, scratch, ca, ca->ptr,
|
|
577
|
+
(boolean8_t*)ca->mask->ptr);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
ca_cast_block(ca->elements, cv, scratch, ca, ca->ptr);
|
|
581
|
+
}
|
|
582
|
+
ca_sync(ca);
|
|
583
|
+
ca_detach(ca);
|
|
1043
584
|
}
|
|
1044
585
|
else {
|
|
1045
|
-
|
|
586
|
+
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
587
|
+
ca_sync_data(ca, scratch);
|
|
1046
588
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
1050
|
-
else {
|
|
1051
|
-
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
1052
|
-
ca_sync_data(ca, cv->ptr);
|
|
589
|
+
|
|
590
|
+
ALLOCV_END(scratch_holder);
|
|
1053
591
|
}
|
|
1054
|
-
ca_detach(cv);
|
|
1055
592
|
}
|
|
1056
593
|
else if ( TYPE(rval) == T_ARRAY ) {
|
|
1057
594
|
volatile VALUE list =
|
|
@@ -1064,6 +601,8 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
1064
601
|
else {
|
|
1065
602
|
int has_mask = 0;
|
|
1066
603
|
CArray ico;
|
|
604
|
+
/* ca_cast_block reads ca_is_face(ca1), so flags must be 0-initialised. */
|
|
605
|
+
memset(&ico, 0, sizeof(CArray));
|
|
1067
606
|
ico.data_type = CA_OBJECT;
|
|
1068
607
|
ico.bytes = ca_sizeof[CA_OBJECT];
|
|
1069
608
|
for (i=0; i<ca->elements; i++) {
|
|
@@ -1073,34 +612,56 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
1073
612
|
break;
|
|
1074
613
|
}
|
|
1075
614
|
}
|
|
1076
|
-
ca_allocate(
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
615
|
+
/* Use ca_allocate() instead of ca_attach() here because rb_ca_store_all()
|
|
616
|
+
overwrites ALL elements of the array from a Ruby Array. There is no need
|
|
617
|
+
to copy parent data (which ca_attach would do), since every element will
|
|
618
|
+
be replaced. Mask handling is also safe: ca_create_mask() above and
|
|
619
|
+
ca_copy_mask_overwrite() handle mask allocation and propagation internally,
|
|
620
|
+
so ca_allocate()'s simpler path (no parent data copy) is sufficient. */
|
|
621
|
+
ca_allocate(ca);
|
|
622
|
+
{
|
|
623
|
+
/* Face has surface != storage; the cast runs in the storage
|
|
624
|
+
data_type. Passing ca directly makes the cast table see FIXLEN
|
|
625
|
+
and report non-implemented, so pass a shadow CArray (storage
|
|
626
|
+
data_type, ptr aliased to ca). */
|
|
627
|
+
CArray shadow;
|
|
628
|
+
CArray *cast_target = ca;
|
|
629
|
+
memset(&shadow, 0, sizeof(CArray));
|
|
630
|
+
if ( ca_is_face(ca) ) {
|
|
631
|
+
CArray *root = ca;
|
|
632
|
+
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
633
|
+
if (root) {
|
|
634
|
+
shadow.data_type = root->data_type;
|
|
635
|
+
shadow.bytes = ca->bytes;
|
|
636
|
+
shadow.elements = ca->elements;
|
|
637
|
+
shadow.ptr = ca->ptr;
|
|
638
|
+
cast_target = &shadow;
|
|
1083
639
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
640
|
+
}
|
|
641
|
+
if ( has_mask ) {
|
|
642
|
+
boolean8_t *m;
|
|
643
|
+
m = (boolean8_t *)ca->mask->ptr;
|
|
644
|
+
for (i=0; i<ca->elements; i++) {
|
|
645
|
+
if ( rb_ary_entry(list,i) == CA_UNDEF ) {
|
|
646
|
+
*m = 1;
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
*m = 0;
|
|
650
|
+
}
|
|
651
|
+
m++;
|
|
1086
652
|
}
|
|
1087
|
-
|
|
653
|
+
ca_cast_block_with_mask(ca->elements, &ico, (VALUE *)RARRAY_CONST_PTR(list),
|
|
654
|
+
cast_target, ca->ptr,
|
|
655
|
+
(boolean8_t*)ca->mask->ptr);
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
ca_cast_block(ca->elements, &ico, (VALUE *)RARRAY_CONST_PTR(list), cast_target, ca->ptr);
|
|
1088
659
|
}
|
|
1089
|
-
ca_cast_block_with_mask(ca->elements, &ico, RARRAY_PTR(list),
|
|
1090
|
-
ca, ca->ptr,
|
|
1091
|
-
(boolean8_t*)ca->mask->ptr);
|
|
1092
|
-
}
|
|
1093
|
-
else {
|
|
1094
|
-
ca_cast_block(ca->elements, &ico, RARRAY_PTR(list), ca, ca->ptr);
|
|
1095
660
|
}
|
|
1096
661
|
ca_sync(ca);
|
|
1097
662
|
ca_detach(ca);
|
|
1098
663
|
}
|
|
1099
664
|
}
|
|
1100
|
-
else if ( rb_respond_to(rval, id_ca) ) {
|
|
1101
|
-
rval = rb_funcall(rval, id_ca, 0);
|
|
1102
|
-
goto retry;
|
|
1103
|
-
}
|
|
1104
665
|
else if ( rb_respond_to(rval, id_to_ca) ) {
|
|
1105
666
|
rval = rb_funcall(rval, id_to_ca, 0);
|
|
1106
667
|
goto retry;
|
|
@@ -1267,7 +828,22 @@ rb_ca_ref_block (VALUE self, CAIndexInfo *info)
|
|
|
1267
828
|
dim, start, step, count, &offset);
|
|
1268
829
|
}
|
|
1269
830
|
|
|
1270
|
-
|
|
831
|
+
{
|
|
832
|
+
volatile VALUE blk;
|
|
833
|
+
blk = rb_ca_block_new(refer, ndim, dim, start, step, count, offset);
|
|
834
|
+
/* The block inherits the Face source's FIXLEN surface; rewrite its
|
|
835
|
+
data_type to the storage data_type (chain bottom) so the write path
|
|
836
|
+
casts in the storage type. */
|
|
837
|
+
if ( ca_is_face(ca) ) {
|
|
838
|
+
CArray *blk_ca, *root = ca;
|
|
839
|
+
TypedData_Get_Struct(blk, CArray, &carray_data_type, blk_ca);
|
|
840
|
+
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
841
|
+
if (root && root->data_type != blk_ca->data_type) {
|
|
842
|
+
blk_ca->data_type = root->data_type;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return blk;
|
|
846
|
+
}
|
|
1271
847
|
}
|
|
1272
848
|
|
|
1273
849
|
static VALUE
|
|
@@ -1281,12 +857,120 @@ rb_ca_refer_new_flatten (VALUE self)
|
|
|
1281
857
|
return rb_ca_refer_new(self, ca->data_type, 1, &dim0, ca->bytes, 0);
|
|
1282
858
|
}
|
|
1283
859
|
|
|
1284
|
-
/*
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
860
|
+
/* CARemap routing: when self and mapper have identical shape AND
|
|
861
|
+
mapper's data_type is CA_SIZE, take the same-shape per-element gather
|
|
862
|
+
fast path. Defined in ca_obj_remap.c. */
|
|
863
|
+
extern VALUE rb_ca_remap_new (VALUE cary, VALUE rmapper);
|
|
864
|
+
|
|
865
|
+
/* a[mapper] is semantically equivalent to
|
|
866
|
+
a.flatten[mapper.flatten].reshape(*mapper.dim).
|
|
867
|
+
|
|
868
|
+
Two routes:
|
|
869
|
+
(a) Same-shape + CA_SIZE mapper -> CARemap view (fast path, avoids
|
|
870
|
+
building the flatten/gather/reshape chain).
|
|
871
|
+
(b) Otherwise -> normalize chain (a.flatten[mapper.flatten]
|
|
872
|
+
.reshape). A 1-D mapper is already routed to CAGrid upstream.
|
|
873
|
+
|
|
874
|
+
Both routes raise on a masked mapper. */
|
|
875
|
+
static VALUE
|
|
876
|
+
rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
877
|
+
{
|
|
878
|
+
CArray *ca, *cm;
|
|
879
|
+
volatile VALUE flat_self, flat_mapper, gridded, result;
|
|
880
|
+
VALUE grid_argv[1];
|
|
881
|
+
int i;
|
|
882
|
+
|
|
883
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
884
|
+
TypedData_Get_Struct(rmapper, CArray, &carray_data_type, cm);
|
|
885
|
+
|
|
886
|
+
if ( ca_is_any_masked(cm) ) {
|
|
887
|
+
rb_raise(rb_eArgError, "mapper in ca[mapper] should not be masked");
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/* (a) same-shape fast path: ndim + per-axis dim + CA_SIZE data_type. */
|
|
891
|
+
if ( cm->data_type == CA_SIZE
|
|
892
|
+
&& cm->ndim == ca->ndim
|
|
893
|
+
&& memcmp(cm->dim, ca->dim, ca->ndim * sizeof(ca_size_t)) == 0 ) {
|
|
894
|
+
return rb_ca_remap_new(self, rmapper);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/* (b) Normalize chain fallback. */
|
|
898
|
+
flat_self = rb_ca_refer_new_flatten(self);
|
|
899
|
+
flat_mapper = (cm->ndim == 1) ? rmapper : rb_ca_flatten(rmapper);
|
|
900
|
+
grid_argv[0] = flat_mapper;
|
|
901
|
+
gridded = rb_ca_grid(1, grid_argv, flat_self);
|
|
902
|
+
|
|
903
|
+
if ( cm->ndim == 1 ) {
|
|
904
|
+
result = gridded;
|
|
905
|
+
}
|
|
906
|
+
else {
|
|
907
|
+
VALUE *dim_argv = ALLOCA_N(VALUE, cm->ndim);
|
|
908
|
+
for (i = 0; i < cm->ndim; i++) {
|
|
909
|
+
dim_argv[i] = SIZE2NUM(cm->dim[i]);
|
|
910
|
+
}
|
|
911
|
+
result = rb_ca_reshape(cm->ndim, dim_argv, gridded);
|
|
912
|
+
}
|
|
913
|
+
return result;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/* The CAMapping class is gone; rb_ca_mapping_new and rb_ca_mapping build
|
|
917
|
+
the normalize chain via rb_ca_fancy_index_chain. The public C API
|
|
918
|
+
signatures are preserved so external ext gems keep linking; the runtime
|
|
919
|
+
class of the returned VALUE is CARefer (chain outermost), not CAMapping. */
|
|
920
|
+
|
|
921
|
+
VALUE
|
|
922
|
+
rb_ca_mapping_new (VALUE cary, CArray *mapper)
|
|
923
|
+
{
|
|
924
|
+
CArray *m_copy = ca_copy(mapper);
|
|
925
|
+
volatile VALUE rmapper = ca_wrap_struct(m_copy);
|
|
926
|
+
return rb_ca_fancy_index_chain(cary, rmapper);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
VALUE
|
|
930
|
+
rb_ca_mapping (int argc, VALUE *argv, VALUE self)
|
|
931
|
+
{
|
|
932
|
+
volatile VALUE rmapper;
|
|
933
|
+
rb_scan_args(argc, argv, "1", (VALUE *) &rmapper);
|
|
934
|
+
rb_check_carray_object(rmapper);
|
|
935
|
+
return rb_ca_fancy_index_chain(self, rmapper);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/* ------------------------------------------------------------------- */
|
|
939
|
+
/* newaxis (:_) sugar. `:_` inserts a size-1 axis at its position.
|
|
940
|
+
Strategy: strip `:_`, fetch the remaining per-axis indices into a base
|
|
941
|
+
view, then reshape the base inserting size-1 axes. reshape inherits
|
|
942
|
+
the optimal view class (CAStride for stride bases, CARefer for fancy
|
|
943
|
+
bases). */
|
|
944
|
+
|
|
945
|
+
static int
|
|
946
|
+
ca_argv_has_newaxis (int argc, VALUE *argv)
|
|
947
|
+
{
|
|
948
|
+
int i;
|
|
949
|
+
for (i = 0; i < argc; i++) {
|
|
950
|
+
if ( argv[i] == sym_under ) return 1;
|
|
951
|
+
}
|
|
952
|
+
return 0;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
static int
|
|
956
|
+
ca_argv_has_slab_sigil (int argc, VALUE *argv)
|
|
957
|
+
{
|
|
958
|
+
int i;
|
|
959
|
+
for (i = 0; i < argc; i++) {
|
|
960
|
+
if ( argv[i] == sym_gt ) return 1;
|
|
961
|
+
}
|
|
962
|
+
return 0;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
static VALUE rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self,
|
|
966
|
+
CArray *ca);
|
|
967
|
+
static VALUE rb_ca_slab_iter_new (VALUE self, CAIndexInfo *info);
|
|
968
|
+
static VALUE rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self);
|
|
969
|
+
|
|
970
|
+
/* axis-group apply (ext/ca_group_iter.c): type gate that routes a
|
|
971
|
+
CACategorical/AxisGroup index to the group path. */
|
|
972
|
+
int ca_argv_has_group (int argc, VALUE *argv);
|
|
973
|
+
VALUE rb_ca_fetch_group (int argc, VALUE *argv, VALUE self);
|
|
1290
974
|
|
|
1291
975
|
static VALUE
|
|
1292
976
|
rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
@@ -1299,12 +983,44 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1299
983
|
|
|
1300
984
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1301
985
|
|
|
986
|
+
/* newaxis (:_) interception (cheap pointer scan; zero overhead beyond
|
|
987
|
+
the loop when no :_ is present). */
|
|
988
|
+
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
989
|
+
return rb_ca_fetch_newaxis(argc, argv, self, ca);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
/* slab sigil (:>) interception. Pre-strip :> -> nil and Integer ->
|
|
993
|
+
length-1 Range so mask / fancy outer slots route through the regular
|
|
994
|
+
dispatch (CA_REG_SELECT / CA_REG_GRID / CA_REG_MAPPING) before being
|
|
995
|
+
wrapped in CASlabIterator. */
|
|
996
|
+
if ( ca_argv_has_slab_sigil(argc, argv) ) {
|
|
997
|
+
return rb_ca_fetch_slab_sigil(argc, argv, self);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/* Axis-group type gate: a CACategorical/AxisGroup index routes to the
|
|
1001
|
+
group apply path (CAGroupIterator); plain int-array indices fall
|
|
1002
|
+
through to the regular selection dispatch below. The scan short-circuits
|
|
1003
|
+
when the surface classes have not been loaded, so a normal index pays
|
|
1004
|
+
nothing. */
|
|
1005
|
+
if ( ca_argv_has_group(argc, argv) ) {
|
|
1006
|
+
return rb_ca_fetch_group(argc, argv, self);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1302
1009
|
info.range_check = 1;
|
|
1303
1010
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1304
1011
|
|
|
1305
1012
|
switch ( info.type ) {
|
|
1306
1013
|
case CA_REG_ADDRESS_COMPLEX:
|
|
1014
|
+
/* Re-enter against a flattened view of self. rb_ca_refer_new_flatten
|
|
1015
|
+
is an internal builder and hands back a bare refer, so a marker
|
|
1016
|
+
receiver would be dropped here and the result would never be lifted
|
|
1017
|
+
at the tail. Put it back on before the re-entry. (A Face survives
|
|
1018
|
+
on its own -- the internal builder still lifts those.) */
|
|
1307
1019
|
self = rb_ca_refer_new_flatten(self);
|
|
1020
|
+
if ( ca_is_lazy_marker(ca) ) {
|
|
1021
|
+
extern VALUE rb_ca_lazy_marker_new (VALUE cary);
|
|
1022
|
+
self = rb_ca_lazy_marker_new(self);
|
|
1023
|
+
}
|
|
1308
1024
|
goto retry;
|
|
1309
1025
|
case CA_REG_ADDRESS:
|
|
1310
1026
|
obj = rb_ca_ref_address(self, &info);
|
|
@@ -1325,16 +1041,13 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1325
1041
|
obj = rb_ca_select_new(self, argv[0]);
|
|
1326
1042
|
break;
|
|
1327
1043
|
case CA_REG_ITERATOR:
|
|
1328
|
-
obj =
|
|
1044
|
+
obj = rb_ca_slab_iter_new(self, &info);
|
|
1329
1045
|
break;
|
|
1330
1046
|
case CA_REG_REPEAT:
|
|
1331
1047
|
obj = rb_ca_repeat(argc, argv, self);
|
|
1332
1048
|
break;
|
|
1333
|
-
case CA_REG_UNBOUND_REPEAT:
|
|
1334
|
-
obj = rb_funcall2(self, rb_intern("unbound_repeat"), (int) argc, argv);
|
|
1335
|
-
break;
|
|
1336
1049
|
case CA_REG_MAPPING:
|
|
1337
|
-
obj =
|
|
1050
|
+
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1338
1051
|
break;
|
|
1339
1052
|
case CA_REG_GRID:
|
|
1340
1053
|
obj = rb_ca_grid(argc, argv, self);
|
|
@@ -1348,11 +1061,14 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1348
1061
|
case CA_REG_MEMBER: {
|
|
1349
1062
|
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1350
1063
|
if ( ! NIL_P(data_class) ) {
|
|
1351
|
-
|
|
1352
|
-
|
|
1064
|
+
/* Field projection strips Face and returns a CAField on the parent
|
|
1065
|
+
(= a different data_type). Do not re-wrap with Face (CARecord
|
|
1066
|
+
wraps structs only; a field view like float64 is not a CARecord).
|
|
1067
|
+
Early-return to bypass the trailing ca_face_lift. */
|
|
1068
|
+
return rb_ca_face_field(self, info.symbol);
|
|
1353
1069
|
}
|
|
1354
1070
|
else {
|
|
1355
|
-
rb_raise(rb_eIndexError,
|
|
1071
|
+
rb_raise(rb_eIndexError,
|
|
1356
1072
|
"can't refer member of carray doesn't have data_class");
|
|
1357
1073
|
}
|
|
1358
1074
|
break;
|
|
@@ -1365,9 +1081,222 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1365
1081
|
default:
|
|
1366
1082
|
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1367
1083
|
}
|
|
1084
|
+
|
|
1085
|
+
/* Wrapper lift at the read touch point: if `self` is a Face or a
|
|
1086
|
+
CALazyMarker, re-wrap the view result so the wrapper stays on top.
|
|
1087
|
+
Guarded to CArray results, which drops the scalar / CASlabIterator /
|
|
1088
|
+
CAGroupIterator / Hash cases the switch above can produce. The
|
|
1089
|
+
already-a-Face case (some builders lift their own result) is handled
|
|
1090
|
+
inside ca_wrapper_lift.
|
|
1091
|
+
|
|
1092
|
+
Every CA_REG_* branch converges here, so this one line covers all of
|
|
1093
|
+
them -- but not every index form: `a[:*, nil]` builds a CAUnboundRepeat,
|
|
1094
|
+
whose shape stays open until an operand binds it, and a marker copies
|
|
1095
|
+
shape at construction. ca_wrapper_lift refuses that one, in one place,
|
|
1096
|
+
because `unbound_repeat` reaches it by a second route. */
|
|
1097
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
1098
|
+
|
|
1368
1099
|
return obj;
|
|
1369
1100
|
}
|
|
1370
1101
|
|
|
1102
|
+
/* newaxis (:_) implementation (reshape). See the forward decl + the
|
|
1103
|
+
interception hook in rb_ca_fetch_method. Pre-condition: argv contains
|
|
1104
|
+
at least one sym_under. */
|
|
1105
|
+
static VALUE
|
|
1106
|
+
rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
1107
|
+
{
|
|
1108
|
+
int i;
|
|
1109
|
+
int nclean = 0;
|
|
1110
|
+
VALUE clean[CA_RANK_MAX];
|
|
1111
|
+
volatile VALUE base;
|
|
1112
|
+
ca_size_t final_dims[CA_RANK_MAX];
|
|
1113
|
+
int nfinal = 0;
|
|
1114
|
+
int base_cursor;
|
|
1115
|
+
CArray *cb;
|
|
1116
|
+
VALUE dim_argv[CA_RANK_MAX];
|
|
1117
|
+
|
|
1118
|
+
/* Build clean argv (strip :_); reject disjoint sigils + rubber dim. */
|
|
1119
|
+
for (i = 0; i < argc; i++) {
|
|
1120
|
+
VALUE a = argv[i];
|
|
1121
|
+
if ( a == sym_under ) continue;
|
|
1122
|
+
if ( a == sym_gt || a == sym_star || a == sym_perc
|
|
1123
|
+
|| a == Qfalse || a == sym_tilde ) {
|
|
1124
|
+
rb_raise(rb_eIndexError,
|
|
1125
|
+
"newaxis (:_) cannot be combined with :>, :*, :%%, "
|
|
1126
|
+
"or rubber dim (false / :~)");
|
|
1127
|
+
}
|
|
1128
|
+
if ( nclean >= CA_RANK_MAX ) {
|
|
1129
|
+
rb_raise(rb_eIndexError, "too many indices");
|
|
1130
|
+
}
|
|
1131
|
+
clean[nclean++] = a;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/* newaxis requires full per-axis indexing (CArray uses flat addressing
|
|
1135
|
+
for partial indices, which is incoherent with axis-position newaxis). */
|
|
1136
|
+
if ( nclean != ca->ndim ) {
|
|
1137
|
+
rb_raise(rb_eIndexError,
|
|
1138
|
+
"newaxis (:_) requires full per-axis indexing "
|
|
1139
|
+
"(got %d non-:_ indices for ndim %d)",
|
|
1140
|
+
nclean, (int) ca->ndim);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
base = rb_ca_fetch_method(nclean, clean, self);
|
|
1144
|
+
|
|
1145
|
+
/* Degenerate: all real axes scalar -> base is a scalar element, not a
|
|
1146
|
+
CArray. Out of scope (rare + degenerate); user indexes the element
|
|
1147
|
+
and reshapes explicitly. IndexError keeps it catchable + consistent
|
|
1148
|
+
with the other newaxis rejects. */
|
|
1149
|
+
if ( ! rb_obj_is_kind_of(base, rb_cCArray) ) {
|
|
1150
|
+
rb_raise(rb_eIndexError,
|
|
1151
|
+
"newaxis (:_) needs at least one non-scalar axis "
|
|
1152
|
+
"(all-scalar indexing yields a single element)");
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
TypedData_Get_Struct(base, CArray, &carray_data_type, cb);
|
|
1156
|
+
|
|
1157
|
+
/* Reconstruct final shape: walk original argv. :_ -> size-1, scalar
|
|
1158
|
+
(Integer) -> dropped (skip), else -> base.dim[cursor]. */
|
|
1159
|
+
base_cursor = 0;
|
|
1160
|
+
for (i = 0; i < argc; i++) {
|
|
1161
|
+
VALUE a = argv[i];
|
|
1162
|
+
if ( a == sym_under ) {
|
|
1163
|
+
final_dims[nfinal++] = 1;
|
|
1164
|
+
}
|
|
1165
|
+
else if ( FIXNUM_P(a) || RB_TYPE_P(a, T_BIGNUM) ) {
|
|
1166
|
+
/* scalar index -> axis dropped in base; contributes no output axis */
|
|
1167
|
+
}
|
|
1168
|
+
else {
|
|
1169
|
+
if ( base_cursor >= cb->ndim ) {
|
|
1170
|
+
rb_raise(rb_eIndexError, "newaxis: base axis count mismatch");
|
|
1171
|
+
}
|
|
1172
|
+
final_dims[nfinal++] = cb->dim[base_cursor++];
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
if ( base_cursor != cb->ndim ) {
|
|
1176
|
+
rb_raise(rb_eIndexError, "newaxis: base axis count mismatch");
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
for (i = 0; i < nfinal; i++) {
|
|
1180
|
+
dim_argv[i] = SIZE2NUM(final_dims[i]);
|
|
1181
|
+
}
|
|
1182
|
+
return rb_ca_reshape(nfinal, dim_argv, base);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
/* Build a CASlabIterator from a classified ITERATOR index. The
|
|
1186
|
+
`:>` axes (CA_IDX_SYMBOL) become the slab axes; they are converted to
|
|
1187
|
+
CA_IDX_ALL so rb_ca_ref_block yields the sliced base view keeping all
|
|
1188
|
+
axes (scalars are already length-1 BLOCKs via the finalize_reg post-
|
|
1189
|
+
pass). CASlabIterator delegates to each_slab / map_slab / reduce_slab. */
|
|
1190
|
+
static VALUE
|
|
1191
|
+
rb_ca_slab_iter_new (VALUE self, CAIndexInfo *info)
|
|
1192
|
+
{
|
|
1193
|
+
volatile VALUE slab_axes = rb_ary_new();
|
|
1194
|
+
volatile VALUE base;
|
|
1195
|
+
volatile VALUE klass;
|
|
1196
|
+
int i;
|
|
1197
|
+
|
|
1198
|
+
for (i = 0; i < info->ndim; i++) {
|
|
1199
|
+
if ( info->index_type[i] == CA_IDX_SYMBOL ) {
|
|
1200
|
+
rb_ary_push(slab_axes, INT2NUM(i));
|
|
1201
|
+
info->index_type[i] = CA_IDX_ALL; /* :> axis -> full range */
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
base = rb_ca_ref_block(self, info);
|
|
1206
|
+
klass = rb_const_get(rb_cObject, rb_intern("CASlabIterator"));
|
|
1207
|
+
return rb_funcall(klass, rb_intern("new"), 2, base, slab_axes);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
/* Slab sigil dispatcher that supports any outer-slot index type
|
|
1211
|
+
(Integer / Range / nil / boolean mask / CArray / Symbol-method etc.).
|
|
1212
|
+
Strategy: expand rubber dim (false / :~) if present so :> positions
|
|
1213
|
+
align with the post-expansion ndim, replace :> with nil (full axis),
|
|
1214
|
+
promote Integer to length-1 Range so the base view preserves ndim,
|
|
1215
|
+
recurse through the regular indexer dispatch to build the base
|
|
1216
|
+
reference (CABlock / CASelectAxis / CAGrid / CAMapping / ...), then
|
|
1217
|
+
wrap in CASlabIterator with the recorded slab_axes positions. */
|
|
1218
|
+
static VALUE
|
|
1219
|
+
rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
1220
|
+
{
|
|
1221
|
+
VALUE expanded[CA_RANK_MAX];
|
|
1222
|
+
VALUE clean[CA_RANK_MAX];
|
|
1223
|
+
volatile VALUE slab_axes = rb_ary_new();
|
|
1224
|
+
volatile VALUE base;
|
|
1225
|
+
volatile VALUE klass;
|
|
1226
|
+
CArray *ca;
|
|
1227
|
+
int i, j;
|
|
1228
|
+
int eargc;
|
|
1229
|
+
VALUE *eargv;
|
|
1230
|
+
int rubber_pos = -1;
|
|
1231
|
+
|
|
1232
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1233
|
+
|
|
1234
|
+
/* Rubber-dim expansion (mirrors ca_classifier_expand_rubber_dim).
|
|
1235
|
+
Only the first rubber marker is honoured; later ones are left for
|
|
1236
|
+
the regular classifier to reject downstream. */
|
|
1237
|
+
for (i = 0; i < argc; i++) {
|
|
1238
|
+
if ( argv[i] == Qfalse || argv[i] == sym_tilde ) {
|
|
1239
|
+
rubber_pos = i;
|
|
1240
|
+
break;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
if ( rubber_pos < 0 ) {
|
|
1244
|
+
eargc = argc;
|
|
1245
|
+
eargv = argv;
|
|
1246
|
+
}
|
|
1247
|
+
else {
|
|
1248
|
+
int rndim;
|
|
1249
|
+
if ( argc > ca->ndim + 1 ) {
|
|
1250
|
+
rb_raise(rb_eIndexError,
|
|
1251
|
+
"index specification exceeds the ndim of carray (%i)",
|
|
1252
|
+
ca->ndim);
|
|
1253
|
+
}
|
|
1254
|
+
rndim = ca->ndim - argc + 1;
|
|
1255
|
+
if ( rndim < 0 ) rndim = 0;
|
|
1256
|
+
j = 0;
|
|
1257
|
+
for (i = 0; i < argc; i++) {
|
|
1258
|
+
if ( i == rubber_pos ) {
|
|
1259
|
+
int k;
|
|
1260
|
+
for (k = 0; k < rndim; k++) expanded[j++] = Qnil;
|
|
1261
|
+
}
|
|
1262
|
+
else {
|
|
1263
|
+
expanded[j++] = argv[i];
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
eargc = j;
|
|
1267
|
+
eargv = expanded;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
if ( eargc > CA_RANK_MAX ) {
|
|
1271
|
+
rb_raise(rb_eIndexError, "too many indices");
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
for (i = 0; i < eargc; i++) {
|
|
1275
|
+
VALUE a = eargv[i];
|
|
1276
|
+
if ( a == sym_gt ) {
|
|
1277
|
+
rb_ary_push(slab_axes, INT2NUM(i));
|
|
1278
|
+
clean[i] = Qnil;
|
|
1279
|
+
}
|
|
1280
|
+
else if ( FIXNUM_P(a) || RB_TYPE_P(a, T_BIGNUM) ) {
|
|
1281
|
+
/* Promote Integer to length-1 Range so the recursed view keeps
|
|
1282
|
+
the axis (matches the existing :> dispatcher semantics where
|
|
1283
|
+
scalars become length-1 BLOCKs via finalize_reg). */
|
|
1284
|
+
clean[i] = rb_range_new(a, a, 0);
|
|
1285
|
+
}
|
|
1286
|
+
else {
|
|
1287
|
+
clean[i] = a;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
base = rb_ca_fetch_method(eargc, clean, self);
|
|
1292
|
+
if ( ! rb_obj_is_kind_of(base, rb_cCArray) ) {
|
|
1293
|
+
rb_raise(rb_eIndexError,
|
|
1294
|
+
"slab sigil (:>) requires the base view to be a CArray");
|
|
1295
|
+
}
|
|
1296
|
+
klass = rb_const_get(rb_cObject, rb_intern("CASlabIterator"));
|
|
1297
|
+
return rb_funcall(klass, rb_intern("new"), 2, base, slab_axes);
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1371
1300
|
static VALUE
|
|
1372
1301
|
rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
1373
1302
|
{
|
|
@@ -1403,16 +1332,13 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1403
1332
|
obj = rb_ca_select_new(self, argv[0]);
|
|
1404
1333
|
break;
|
|
1405
1334
|
case CA_REG_ITERATOR:
|
|
1406
|
-
obj =
|
|
1335
|
+
obj = rb_ca_slab_iter_new(self, &info);
|
|
1407
1336
|
break;
|
|
1408
1337
|
case CA_REG_REPEAT:
|
|
1409
1338
|
obj = rb_ca_repeat(argc, argv, self);
|
|
1410
1339
|
break;
|
|
1411
|
-
case CA_REG_UNBOUND_REPEAT:
|
|
1412
|
-
obj = rb_funcall2(self, rb_intern("unbound_repeat"), (int) argc, argv);
|
|
1413
|
-
break;
|
|
1414
1340
|
case CA_REG_MAPPING:
|
|
1415
|
-
obj =
|
|
1341
|
+
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1416
1342
|
break;
|
|
1417
1343
|
case CA_REG_GRID:
|
|
1418
1344
|
obj = rb_ca_grid(argc, argv, self);
|
|
@@ -1426,7 +1352,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1426
1352
|
case CA_REG_MEMBER: {
|
|
1427
1353
|
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1428
1354
|
if ( ! NIL_P(data_class) ) {
|
|
1429
|
-
obj =
|
|
1355
|
+
obj = rb_ca_face_field(self, info.symbol);
|
|
1430
1356
|
break;
|
|
1431
1357
|
}
|
|
1432
1358
|
else {
|
|
@@ -1447,12 +1373,67 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1447
1373
|
return obj;
|
|
1448
1374
|
}
|
|
1449
1375
|
|
|
1450
|
-
/*
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1376
|
+
/* Recursively convert a store rvalue's surface value objects into
|
|
1377
|
+
storage-domain values for a Face `self`, applied at the Ruby `[]=` entry
|
|
1378
|
+
before any store-side view (block / newaxis / grid / ...) is built. The
|
|
1379
|
+
store-side view is stripped to the storage data_type, so the Face is only
|
|
1380
|
+
visible here at the top of the dispatch; converting now lets every view
|
|
1381
|
+
path store a Face surface scalar correctly.
|
|
1382
|
+
|
|
1383
|
+
- a Face CArray rvalue is reconciled to self's storage via to_comparable
|
|
1384
|
+
(unit-safe: cross-group / non-exact raises), so a same-Face bulk store
|
|
1385
|
+
(t[0..1] = t[1..2]) becomes a storage int64 xfer. A non-Face CArray
|
|
1386
|
+
(e.g. datetime[0..1] = plain_int64_array) passes through unchanged --
|
|
1387
|
+
the documented raw-storage escape -- but it has to be raw *storage*: an
|
|
1388
|
+
integer-storage Face takes integer cells only. The scalar path already
|
|
1389
|
+
refuses a bare Float there (to_comparable does not recognise it) instead
|
|
1390
|
+
of letting the storage cast truncate it, and the bulk path must not be
|
|
1391
|
+
the looser door.
|
|
1392
|
+
- an Array is mapped structure-preserving (leaves converted),
|
|
1393
|
+
- a scalar goes through the write hook (ca_face_scalar_to_storage), which
|
|
1394
|
+
leaves a bare Integer / String unchanged.
|
|
1395
|
+
|
|
1396
|
+
Idempotent: an already-converted Integer passes through, so re-running on
|
|
1397
|
+
a `goto retry` iteration is harmless. */
|
|
1398
|
+
static VALUE
|
|
1399
|
+
ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
1400
|
+
{
|
|
1401
|
+
if ( rb_obj_is_carray(val) ) {
|
|
1402
|
+
CArray *cval;
|
|
1403
|
+
GetCArray(val, cval);
|
|
1404
|
+
/* Face RHS: reconcile to self's unit and descend to storage. Mirror of
|
|
1405
|
+
the scalar path (ca_face_scalar_to_storage) for a bulk CArray source.
|
|
1406
|
+
Guarded on self having to_comparable so a Face without a reconcile
|
|
1407
|
+
algebra (e.g. a fixlen-storage Face, whose same-storage store already
|
|
1408
|
+
takes the storage xfer branch) is left to the existing store path. */
|
|
1409
|
+
if ( ca_is_face(cval) && rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
1410
|
+
volatile VALUE reconciled = rb_funcall(self, rb_intern("to_comparable"),
|
|
1411
|
+
1, val);
|
|
1412
|
+
return rb_funcall(reconciled, rb_intern("parent"), 0);
|
|
1413
|
+
}
|
|
1414
|
+
/* Bare storage escape, integer storage: integer cells only (see above). */
|
|
1415
|
+
{
|
|
1416
|
+
CArray *storage = ca_strip_face(ca);
|
|
1417
|
+
if ( storage && ca_is_integer_type(storage) && ! ca_is_integer_type(cval) ) {
|
|
1418
|
+
rb_raise(rb_eTypeError,
|
|
1419
|
+
"%s cannot store a bare %s array as raw storage "
|
|
1420
|
+
"(use ca.parent to write the %s storage directly)",
|
|
1421
|
+
rb_obj_classname(self), ca_type_name[cval->data_type],
|
|
1422
|
+
ca_type_name[storage->data_type]);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
return val;
|
|
1426
|
+
}
|
|
1427
|
+
if ( TYPE(val) == T_ARRAY ) {
|
|
1428
|
+
long i, n = RARRAY_LEN(val);
|
|
1429
|
+
volatile VALUE out = rb_ary_new2(n);
|
|
1430
|
+
for (i = 0; i < n; i++) {
|
|
1431
|
+
rb_ary_push(out, ca_face_convert_store_rval(self, ca, rb_ary_entry(val, i)));
|
|
1432
|
+
}
|
|
1433
|
+
return out;
|
|
1434
|
+
}
|
|
1435
|
+
return ca_face_scalar_to_storage(self, ca, val);
|
|
1436
|
+
}
|
|
1456
1437
|
|
|
1457
1438
|
static VALUE
|
|
1458
1439
|
rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
@@ -1470,6 +1451,31 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1470
1451
|
|
|
1471
1452
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1472
1453
|
|
|
1454
|
+
/* Face store: bring a surface value object (Scalar / Time / DateTime) into
|
|
1455
|
+
the storage domain while self is still the Face. Store-side views strip
|
|
1456
|
+
the Face to storage, so this is the only point that sees it. */
|
|
1457
|
+
if ( ca_is_face(ca) ) {
|
|
1458
|
+
rval = ca_face_convert_store_rval(self, ca, rval);
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/* newaxis (:_) interception on store. Build the newaxis view (a
|
|
1462
|
+
writable reshape aliasing self), then assign rval into the whole view
|
|
1463
|
+
(writes propagate to self). */
|
|
1464
|
+
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
1465
|
+
volatile VALUE view = rb_ca_fetch_newaxis(argc, argv, self, ca);
|
|
1466
|
+
rb_ca_store_all(view, rval);
|
|
1467
|
+
return rval;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
/* slab sigil on store is rejected regardless of outer-slot type. Catch
|
|
1471
|
+
:> before scan_index so mask/fancy outer slots get the same "not
|
|
1472
|
+
supported" message instead of a misleading TypeError. */
|
|
1473
|
+
if ( ca_argv_has_slab_sigil(argc, argv) ) {
|
|
1474
|
+
rb_raise(rb_eIndexError,
|
|
1475
|
+
"assignment through a slab iterator (:>) is not supported "
|
|
1476
|
+
"(use a block index, e.g. ca[range, nil] = val, or each_slab)");
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1473
1479
|
info.range_check = 1;
|
|
1474
1480
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1475
1481
|
|
|
@@ -1502,8 +1508,11 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1502
1508
|
break;
|
|
1503
1509
|
}
|
|
1504
1510
|
case CA_REG_ITERATOR: {
|
|
1505
|
-
|
|
1506
|
-
|
|
1511
|
+
/* assignment through a slab iterator (:>) is not supported.
|
|
1512
|
+
Use a block index (ca[range, nil] = val) or each_slab/map_slab. */
|
|
1513
|
+
rb_raise(rb_eIndexError,
|
|
1514
|
+
"assignment through a slab iterator (:>) is not supported "
|
|
1515
|
+
"(use a block index, e.g. ca[range, nil] = val, or each_slab)");
|
|
1507
1516
|
break;
|
|
1508
1517
|
}
|
|
1509
1518
|
case CA_REG_REPEAT: {
|
|
@@ -1511,12 +1520,8 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1511
1520
|
obj = rb_ca_store_all(obj, rval);
|
|
1512
1521
|
break;
|
|
1513
1522
|
}
|
|
1514
|
-
case CA_REG_UNBOUND_REPEAT:
|
|
1515
|
-
obj = rb_funcall2(self, rb_intern("unbound_repeat"), (int) argc, argv);
|
|
1516
|
-
obj = rb_ca_store_all(obj, rval);
|
|
1517
|
-
break;
|
|
1518
1523
|
case CA_REG_MAPPING: {
|
|
1519
|
-
obj =
|
|
1524
|
+
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1520
1525
|
obj = rb_ca_store_all(obj, rval);
|
|
1521
1526
|
break;
|
|
1522
1527
|
}
|
|
@@ -1537,7 +1542,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1537
1542
|
case CA_REG_MEMBER: {
|
|
1538
1543
|
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1539
1544
|
if ( ! NIL_P(data_class) ) {
|
|
1540
|
-
obj =
|
|
1545
|
+
obj = rb_ca_face_field(self, info.symbol);
|
|
1541
1546
|
obj = rb_ca_store_all(obj, rval);
|
|
1542
1547
|
}
|
|
1543
1548
|
else {
|
|
@@ -1552,6 +1557,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1552
1557
|
break;
|
|
1553
1558
|
}
|
|
1554
1559
|
}
|
|
1560
|
+
|
|
1555
1561
|
return obj;
|
|
1556
1562
|
}
|
|
1557
1563
|
|
|
@@ -1560,7 +1566,7 @@ rb_ca_fetch (VALUE self, VALUE index)
|
|
|
1560
1566
|
{
|
|
1561
1567
|
switch ( TYPE(index) ) {
|
|
1562
1568
|
case T_ARRAY:
|
|
1563
|
-
return rb_ca_fetch_method((int) RARRAY_LEN(index),
|
|
1569
|
+
return rb_ca_fetch_method((int) RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1564
1570
|
default:
|
|
1565
1571
|
return rb_ca_fetch_method(1, &index, self);
|
|
1566
1572
|
}
|
|
@@ -1579,7 +1585,7 @@ rb_ca_store (VALUE self, VALUE index, VALUE rval)
|
|
|
1579
1585
|
case T_ARRAY:
|
|
1580
1586
|
index = rb_obj_clone(index);
|
|
1581
1587
|
rb_ary_push(index, rval);
|
|
1582
|
-
return rb_ca_store_method((int)RARRAY_LEN(index),
|
|
1588
|
+
return rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1583
1589
|
default: {
|
|
1584
1590
|
VALUE rindex[2] = { index, rval };
|
|
1585
1591
|
return rb_ca_store_method(2, rindex, self);
|
|
@@ -1590,16 +1596,11 @@ rb_ca_store (VALUE self, VALUE index, VALUE rval)
|
|
|
1590
1596
|
VALUE
|
|
1591
1597
|
rb_ca_store2 (VALUE self, int n, VALUE *rindex, VALUE rval)
|
|
1592
1598
|
{
|
|
1593
|
-
VALUE index = rb_ary_new4(n, rindex);
|
|
1599
|
+
volatile VALUE index = rb_ary_new4(n, rindex);
|
|
1594
1600
|
rb_ary_push(index, rval);
|
|
1595
|
-
return rb_ca_store_method((int)RARRAY_LEN(index),
|
|
1601
|
+
return rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1596
1602
|
}
|
|
1597
1603
|
|
|
1598
|
-
/* yard:
|
|
1599
|
-
def CArray.scan_index(dim, idx)
|
|
1600
|
-
end
|
|
1601
|
-
*/
|
|
1602
|
-
|
|
1603
1604
|
static VALUE
|
|
1604
1605
|
rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
1605
1606
|
{
|
|
@@ -1625,7 +1626,7 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1625
1626
|
|
|
1626
1627
|
info.range_check = 1;
|
|
1627
1628
|
rb_ca_scan_index(ndim, dim, elements,
|
|
1628
|
-
RARRAY_LEN(ridx),
|
|
1629
|
+
RARRAY_LEN(ridx), (VALUE *)RARRAY_CONST_PTR(ridx), &info);
|
|
1629
1630
|
|
|
1630
1631
|
rtype = INT2NUM(info.type);
|
|
1631
1632
|
rindex = rb_ary_new2(info.ndim);
|
|
@@ -1693,7 +1694,6 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1693
1694
|
case CA_REG_GRID:
|
|
1694
1695
|
case CA_REG_MAPPING:
|
|
1695
1696
|
case CA_REG_METHOD_CALL:
|
|
1696
|
-
case CA_REG_UNBOUND_REPEAT:
|
|
1697
1697
|
case CA_REG_MEMBER:
|
|
1698
1698
|
case CA_REG_ATTRIBUTE:
|
|
1699
1699
|
break;
|
|
@@ -1704,13 +1704,6 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1704
1704
|
return rb_struct_new(S_CAInfo, rtype, rindex);
|
|
1705
1705
|
}
|
|
1706
1706
|
|
|
1707
|
-
/* yard:
|
|
1708
|
-
class CArray
|
|
1709
|
-
def normalize_index (idx)
|
|
1710
|
-
end
|
|
1711
|
-
end
|
|
1712
|
-
*/
|
|
1713
|
-
|
|
1714
1707
|
static VALUE
|
|
1715
1708
|
rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
1716
1709
|
{
|
|
@@ -1724,7 +1717,7 @@ rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
|
1724
1717
|
|
|
1725
1718
|
info.range_check = 1;
|
|
1726
1719
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements,
|
|
1727
|
-
RARRAY_LEN(ridx),
|
|
1720
|
+
RARRAY_LEN(ridx), (VALUE *)RARRAY_CONST_PTR(ridx), &info);
|
|
1728
1721
|
|
|
1729
1722
|
switch ( info.type ) {
|
|
1730
1723
|
case CA_REG_ALL:
|
|
@@ -1777,78 +1770,153 @@ rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
|
1777
1770
|
|
|
1778
1771
|
/* ------------------------------------------------------------------- */
|
|
1779
1772
|
|
|
1780
|
-
/*
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1773
|
+
/* ------------------------------------------------------------------- */
|
|
1774
|
+
/* addr <-> index conversion primitives.
|
|
1775
|
+
*
|
|
1776
|
+
* Two dispatch axes:
|
|
1777
|
+
* (a) instance form (uses self.shape) vs class form (`shape:` kwarg)
|
|
1778
|
+
* (b) scalar input vs CArray input (per method)
|
|
1779
|
+
*
|
|
1780
|
+
* The four Ruby entry points (rb_ca_{addr2index,index2addr},
|
|
1781
|
+
* rb_ca_s_{addr2index,index2addr}) all funnel into the two _do helpers
|
|
1782
|
+
* below, which take an already-resolved (ndim, dim[], elements) triple.
|
|
1783
|
+
*/
|
|
1787
1784
|
|
|
1788
|
-
|
|
1789
|
-
|
|
1785
|
+
static void
|
|
1786
|
+
parse_shape_kwarg (VALUE rshape, int *out_ndim, ca_size_t *dim,
|
|
1787
|
+
ca_size_t *out_elements)
|
|
1788
|
+
{
|
|
1789
|
+
int i, ndim;
|
|
1790
|
+
ca_size_t elements = 1;
|
|
1791
|
+
|
|
1792
|
+
Check_Type(rshape, T_ARRAY);
|
|
1793
|
+
ndim = (int) RARRAY_LEN(rshape);
|
|
1794
|
+
if ( ndim < 1 || ndim > CA_RANK_MAX ) {
|
|
1795
|
+
rb_raise(rb_eArgError, "invalid shape ndim %d (must be 1..%d)",
|
|
1796
|
+
ndim, CA_RANK_MAX);
|
|
1797
|
+
}
|
|
1798
|
+
for (i = 0; i < ndim; i++) {
|
|
1799
|
+
dim[i] = NUM2SIZE(rb_ary_entry(rshape, i));
|
|
1800
|
+
if ( dim[i] < 0 ) {
|
|
1801
|
+
rb_raise(rb_eArgError, "negative dim %" PRId64 " at axis %d",
|
|
1802
|
+
(ca_size_t) dim[i], i);
|
|
1803
|
+
}
|
|
1804
|
+
elements *= dim[i];
|
|
1805
|
+
}
|
|
1806
|
+
*out_ndim = ndim;
|
|
1807
|
+
*out_elements = elements;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
static VALUE
|
|
1811
|
+
addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
1790
1812
|
{
|
|
1791
1813
|
volatile VALUE out;
|
|
1792
|
-
CArray *ca;
|
|
1793
|
-
ca_size_t *dim;
|
|
1794
|
-
ca_size_t addr;
|
|
1795
1814
|
int i;
|
|
1796
1815
|
|
|
1797
|
-
|
|
1816
|
+
/* Scalar path (Integer input): returns Ruby Array of N Integers.
|
|
1817
|
+
* Preserves legacy shape for callers like `i, j = ca.addr2index(k)`. */
|
|
1818
|
+
if ( rb_obj_is_kind_of(raddr, rb_cInteger) ) {
|
|
1819
|
+
ca_size_t addr = NUM2SIZE(raddr);
|
|
1820
|
+
if ( addr < 0 || addr >= elements ) {
|
|
1821
|
+
rb_raise(rb_eArgError,
|
|
1822
|
+
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1823
|
+
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
1824
|
+
}
|
|
1825
|
+
out = rb_ary_new2(ndim);
|
|
1826
|
+
for (i = ndim - 1; i >= 0; i--) {
|
|
1827
|
+
rb_ary_store(out, i, SIZE2NUM(addr % dim[i]));
|
|
1828
|
+
addr /= dim[i];
|
|
1829
|
+
}
|
|
1830
|
+
return out;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
/* Vector path (CArray input): returns Ruby Array of N CArrays,
|
|
1834
|
+
* each with the same shape as the input; mask propagated. */
|
|
1835
|
+
{
|
|
1836
|
+
CArray *cin, *co[CA_RANK_MAX];
|
|
1837
|
+
ca_size_t *p_out[CA_RANK_MAX];
|
|
1838
|
+
boolean8_t *m;
|
|
1839
|
+
ca_size_t j, n;
|
|
1840
|
+
volatile VALUE objs[CA_RANK_MAX];
|
|
1841
|
+
|
|
1842
|
+
cin = ca_wrap_readonly(raddr, CA_SIZE);
|
|
1843
|
+
ca_attach(cin);
|
|
1844
|
+
|
|
1845
|
+
out = rb_ary_new2(ndim);
|
|
1846
|
+
for (i = 0; i < ndim; i++) {
|
|
1847
|
+
objs[i] = rb_carray_new(CA_SIZE, cin->ndim, cin->dim, 0, NULL);
|
|
1848
|
+
TypedData_Get_Struct(objs[i], CArray, &carray_data_type, co[i]);
|
|
1849
|
+
p_out[i] = (ca_size_t *) co[i]->ptr;
|
|
1850
|
+
rb_ary_store(out, i, objs[i]);
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
m = cin->mask ? (boolean8_t *) cin->mask->ptr : NULL;
|
|
1854
|
+
if ( m ) {
|
|
1855
|
+
for (i = 0; i < ndim; i++) {
|
|
1856
|
+
ca_create_mask(co[i]);
|
|
1857
|
+
memcpy(co[i]->mask->ptr, m, cin->elements);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1798
1860
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1861
|
+
n = cin->elements;
|
|
1862
|
+
{
|
|
1863
|
+
ca_size_t *src = (ca_size_t *) cin->ptr;
|
|
1864
|
+
ca_size_t addr;
|
|
1865
|
+
int k;
|
|
1866
|
+
for (j = 0; j < n; j++) {
|
|
1867
|
+
if ( m && m[j] ) {
|
|
1868
|
+
for (k = 0; k < ndim; k++) { p_out[k][j] = 0; }
|
|
1869
|
+
continue;
|
|
1870
|
+
}
|
|
1871
|
+
addr = src[j];
|
|
1872
|
+
if ( addr < 0 || addr >= elements ) {
|
|
1873
|
+
ca_detach(cin);
|
|
1874
|
+
rb_raise(rb_eArgError,
|
|
1875
|
+
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1876
|
+
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
1877
|
+
}
|
|
1878
|
+
for (k = ndim - 1; k >= 0; k--) {
|
|
1879
|
+
p_out[k][j] = addr % dim[k];
|
|
1880
|
+
addr /= dim[k];
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1811
1884
|
|
|
1812
|
-
|
|
1885
|
+
ca_detach(cin);
|
|
1886
|
+
return out;
|
|
1887
|
+
}
|
|
1813
1888
|
}
|
|
1814
1889
|
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
def index2addr (*index)
|
|
1818
|
-
end
|
|
1819
|
-
end
|
|
1820
|
-
*/
|
|
1821
|
-
|
|
1822
|
-
VALUE
|
|
1823
|
-
rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
1890
|
+
static VALUE
|
|
1891
|
+
index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
1824
1892
|
{
|
|
1825
1893
|
volatile VALUE obj;
|
|
1826
|
-
CArray
|
|
1894
|
+
CArray *co, *cidx[CA_RANK_MAX];
|
|
1827
1895
|
ca_size_t *q, *p[CA_RANK_MAX], s[CA_RANK_MAX];
|
|
1828
|
-
ca_size_t
|
|
1829
|
-
ca_size_t addr, elements = 0;
|
|
1830
|
-
int8_t i;
|
|
1831
|
-
ca_size_t k, n;
|
|
1896
|
+
ca_size_t addr, k, n;
|
|
1832
1897
|
boolean8_t *m;
|
|
1833
|
-
int
|
|
1898
|
+
int i, all_number = 1;
|
|
1899
|
+
int out_ndim = 1;
|
|
1900
|
+
ca_size_t out_dim[CA_RANK_MAX];
|
|
1901
|
+
ca_size_t out_elements = 1;
|
|
1902
|
+
int shape_from = -1;
|
|
1834
1903
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
rb_raise(rb_eRuntimeError, "invalid ndim of index");
|
|
1904
|
+
if ( argc != ndim ) {
|
|
1905
|
+
rb_raise(rb_eArgError,
|
|
1906
|
+
"wrong number of indices (%d for %d)", argc, ndim);
|
|
1839
1907
|
}
|
|
1840
1908
|
|
|
1841
|
-
for (i=0; i<
|
|
1909
|
+
for (i = 0; i < ndim; i++) {
|
|
1842
1910
|
if ( ! rb_obj_is_kind_of(argv[i], rb_cInteger) ) {
|
|
1843
1911
|
all_number = 0;
|
|
1844
1912
|
break;
|
|
1845
1913
|
}
|
|
1846
1914
|
}
|
|
1847
1915
|
|
|
1916
|
+
/* All-scalar path: returns single Integer (unchanged). */
|
|
1848
1917
|
if ( all_number ) {
|
|
1849
|
-
dim = ca->dim;
|
|
1850
1918
|
addr = 0;
|
|
1851
|
-
for (i=0; i<
|
|
1919
|
+
for (i = 0; i < ndim; i++) {
|
|
1852
1920
|
k = NUM2SIZE(argv[i]);
|
|
1853
1921
|
CA_CHECK_INDEX(k, dim[i]);
|
|
1854
1922
|
addr = dim[i] * addr + k;
|
|
@@ -1856,62 +1924,77 @@ rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
|
1856
1924
|
return SIZE2NUM(addr);
|
|
1857
1925
|
}
|
|
1858
1926
|
|
|
1859
|
-
|
|
1860
|
-
|
|
1927
|
+
/* Vector path: wrap each arg as CA_SIZE view. Output shape follows
|
|
1928
|
+
* the first non-scalar CArray input; other non-scalar inputs must
|
|
1929
|
+
* match that shape. */
|
|
1930
|
+
for (i = 0; i < ndim; i++) {
|
|
1861
1931
|
cidx[i] = ca_wrap_readonly(argv[i], CA_SIZE);
|
|
1862
1932
|
if ( ! ca_is_scalar(cidx[i]) ) {
|
|
1863
|
-
if (
|
|
1864
|
-
|
|
1933
|
+
if ( shape_from < 0 ) {
|
|
1934
|
+
shape_from = i;
|
|
1935
|
+
out_ndim = cidx[i]->ndim;
|
|
1936
|
+
memcpy(out_dim, cidx[i]->dim, sizeof(ca_size_t) * out_ndim);
|
|
1937
|
+
out_elements = cidx[i]->elements;
|
|
1865
1938
|
}
|
|
1866
|
-
else
|
|
1867
|
-
|
|
1939
|
+
else {
|
|
1940
|
+
int j;
|
|
1941
|
+
if ( cidx[i]->ndim != out_ndim
|
|
1942
|
+
|| cidx[i]->elements != out_elements ) {
|
|
1943
|
+
rb_raise(rb_eArgError,
|
|
1944
|
+
"shape mismatch: axis %d has shape ndim=%d elements=%"
|
|
1945
|
+
PRId64 ", expected ndim=%d elements=%" PRId64,
|
|
1946
|
+
i, cidx[i]->ndim, (ca_size_t) cidx[i]->elements,
|
|
1947
|
+
out_ndim, (ca_size_t) out_elements);
|
|
1948
|
+
}
|
|
1949
|
+
for (j = 0; j < out_ndim; j++) {
|
|
1950
|
+
if ( cidx[i]->dim[j] != out_dim[j] ) {
|
|
1951
|
+
rb_raise(rb_eArgError,
|
|
1952
|
+
"shape mismatch at axis %d dim %d", i, j);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1868
1955
|
}
|
|
1869
1956
|
}
|
|
1870
1957
|
}
|
|
1871
1958
|
|
|
1872
|
-
for (i=0; i<
|
|
1959
|
+
for (i = 0; i < ndim; i++) {
|
|
1873
1960
|
ca_attach(cidx[i]);
|
|
1874
1961
|
ca_set_iterator(1, cidx[i], &p[i], &s[i]);
|
|
1875
1962
|
}
|
|
1876
1963
|
|
|
1877
|
-
obj = rb_carray_new(CA_SIZE,
|
|
1964
|
+
obj = rb_carray_new(CA_SIZE, out_ndim, out_dim, 0, NULL);
|
|
1878
1965
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
|
|
1879
1966
|
|
|
1880
1967
|
q = (ca_size_t *) co->ptr;
|
|
1881
1968
|
|
|
1882
|
-
ca_copy_mask_overwrite_n(co,
|
|
1969
|
+
ca_copy_mask_overwrite_n(co, out_elements, ndim, cidx);
|
|
1883
1970
|
m = ( co->mask ) ? (boolean8_t *) co->mask->ptr : NULL;
|
|
1884
1971
|
|
|
1885
|
-
dim = ca->dim;
|
|
1886
|
-
|
|
1887
1972
|
if ( m ) {
|
|
1888
|
-
n =
|
|
1973
|
+
n = out_elements;
|
|
1889
1974
|
while ( n-- ) {
|
|
1890
|
-
if (
|
|
1975
|
+
if ( ! *m ) {
|
|
1891
1976
|
addr = 0;
|
|
1892
|
-
for (i=0; i<
|
|
1977
|
+
for (i = 0; i < ndim; i++) {
|
|
1893
1978
|
k = *(p[i]);
|
|
1894
|
-
p[i]+=s[i];
|
|
1979
|
+
p[i] += s[i];
|
|
1895
1980
|
CA_CHECK_INDEX(k, dim[i]);
|
|
1896
1981
|
addr = dim[i] * addr + k;
|
|
1897
1982
|
}
|
|
1898
1983
|
*q = addr;
|
|
1899
1984
|
}
|
|
1900
1985
|
else {
|
|
1901
|
-
for (i=0; i<
|
|
1902
|
-
p[i]+=s[i];
|
|
1903
|
-
}
|
|
1986
|
+
for (i = 0; i < ndim; i++) { p[i] += s[i]; }
|
|
1904
1987
|
}
|
|
1905
1988
|
m++; q++;
|
|
1906
1989
|
}
|
|
1907
1990
|
}
|
|
1908
1991
|
else {
|
|
1909
|
-
n =
|
|
1992
|
+
n = out_elements;
|
|
1910
1993
|
while ( n-- ) {
|
|
1911
1994
|
addr = 0;
|
|
1912
|
-
for (i=0; i<
|
|
1995
|
+
for (i = 0; i < ndim; i++) {
|
|
1913
1996
|
k = *(p[i]);
|
|
1914
|
-
p[i]+=s[i];
|
|
1997
|
+
p[i] += s[i];
|
|
1915
1998
|
CA_CHECK_INDEX(k, dim[i]);
|
|
1916
1999
|
addr = dim[i] * addr + k;
|
|
1917
2000
|
}
|
|
@@ -1920,26 +2003,84 @@ rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
|
1920
2003
|
}
|
|
1921
2004
|
}
|
|
1922
2005
|
|
|
1923
|
-
for (i=0; i<
|
|
1924
|
-
ca_detach(cidx[i]);
|
|
1925
|
-
}
|
|
2006
|
+
for (i = 0; i < ndim; i++) { ca_detach(cidx[i]); }
|
|
1926
2007
|
|
|
1927
2008
|
return obj;
|
|
1928
2009
|
}
|
|
1929
2010
|
|
|
2011
|
+
VALUE
|
|
2012
|
+
rb_ca_addr2index (VALUE self, VALUE raddr)
|
|
2013
|
+
{
|
|
2014
|
+
CArray *ca;
|
|
2015
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
2016
|
+
return addr2index_do(ca->ndim, ca->dim, ca->elements, raddr);
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
VALUE
|
|
2020
|
+
rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
2021
|
+
{
|
|
2022
|
+
CArray *ca;
|
|
2023
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
2024
|
+
return index2addr_do(ca->ndim, ca->dim, argc, argv);
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
/* CArray.addr2index(addr, shape: [...]) */
|
|
2028
|
+
static VALUE
|
|
2029
|
+
rb_ca_s_addr2index (int argc, VALUE *argv, VALUE klass)
|
|
2030
|
+
{
|
|
2031
|
+
VALUE raddr, opts;
|
|
2032
|
+
ID kw_ids[1];
|
|
2033
|
+
VALUE kw_vals[1];
|
|
2034
|
+
int ndim;
|
|
2035
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
2036
|
+
ca_size_t elements;
|
|
2037
|
+
|
|
2038
|
+
kw_ids[0] = rb_intern("shape");
|
|
2039
|
+
rb_scan_args(argc, argv, "1:", &raddr, &opts);
|
|
2040
|
+
if ( NIL_P(opts) ) {
|
|
2041
|
+
rb_raise(rb_eArgError, "missing keyword: shape");
|
|
2042
|
+
}
|
|
2043
|
+
rb_get_kwargs(opts, kw_ids, 1, 0, kw_vals);
|
|
2044
|
+
parse_shape_kwarg(kw_vals[0], &ndim, dim, &elements);
|
|
2045
|
+
return addr2index_do(ndim, dim, elements, raddr);
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
/* CArray.index2addr(*index, shape: [...]) */
|
|
2049
|
+
static VALUE
|
|
2050
|
+
rb_ca_s_index2addr (int argc, VALUE *argv, VALUE klass)
|
|
2051
|
+
{
|
|
2052
|
+
VALUE rest, opts;
|
|
2053
|
+
ID kw_ids[1];
|
|
2054
|
+
VALUE kw_vals[1];
|
|
2055
|
+
int ndim;
|
|
2056
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
2057
|
+
ca_size_t elements;
|
|
2058
|
+
|
|
2059
|
+
kw_ids[0] = rb_intern("shape");
|
|
2060
|
+
rb_scan_args(argc, argv, "*:", &rest, &opts);
|
|
2061
|
+
if ( NIL_P(opts) ) {
|
|
2062
|
+
rb_raise(rb_eArgError, "missing keyword: shape");
|
|
2063
|
+
}
|
|
2064
|
+
rb_get_kwargs(opts, kw_ids, 1, 0, kw_vals);
|
|
2065
|
+
parse_shape_kwarg(kw_vals[0], &ndim, dim, &elements);
|
|
2066
|
+
return index2addr_do(ndim, dim, (int) RARRAY_LEN(rest), RARRAY_PTR(rest));
|
|
2067
|
+
}
|
|
2068
|
+
|
|
1930
2069
|
|
|
1931
2070
|
void
|
|
1932
|
-
Init_carray_access ()
|
|
2071
|
+
Init_carray_access (void)
|
|
1933
2072
|
{
|
|
1934
2073
|
|
|
1935
2074
|
id_begin = rb_intern("begin");
|
|
1936
2075
|
id_end = rb_intern("end");
|
|
1937
2076
|
id_excl_end = rb_intern("exclude_end?");
|
|
1938
2077
|
|
|
1939
|
-
id_ca = rb_intern("ca");
|
|
1940
2078
|
id_to_ca = rb_intern("to_ca");
|
|
1941
|
-
sym_star
|
|
1942
|
-
sym_perc
|
|
2079
|
+
sym_star = ID2SYM(rb_intern("*"));
|
|
2080
|
+
sym_perc = ID2SYM(rb_intern("%"));
|
|
2081
|
+
sym_under = ID2SYM(rb_intern("_"));
|
|
2082
|
+
sym_gt = ID2SYM(rb_intern(">"));
|
|
2083
|
+
sym_tilde = ID2SYM(rb_intern("~"));
|
|
1943
2084
|
|
|
1944
2085
|
rb_define_method(rb_cCArray, "[]", rb_ca_fetch_method, -1);
|
|
1945
2086
|
rb_define_method(rb_cCArray, "[]=", rb_ca_store_method, -1);
|
|
@@ -1959,6 +2100,9 @@ Init_carray_access ()
|
|
|
1959
2100
|
rb_define_method(rb_cCArray, "index2addr", rb_ca_index2addr, -1);
|
|
1960
2101
|
rb_define_method(rb_cCArray, "addr2index", rb_ca_addr2index, 1);
|
|
1961
2102
|
|
|
2103
|
+
rb_define_singleton_method(rb_cCArray, "addr2index", rb_ca_s_addr2index, -1);
|
|
2104
|
+
rb_define_singleton_method(rb_cCArray, "index2addr", rb_ca_s_index2addr, -1);
|
|
2105
|
+
|
|
1962
2106
|
rb_define_const(rb_cObject, "CA_REG_NONE", INT2NUM(CA_REG_NONE));
|
|
1963
2107
|
rb_define_const(rb_cObject, "CA_REG_ALL", INT2NUM(CA_REG_ALL));
|
|
1964
2108
|
rb_define_const(rb_cObject, "CA_REG_ADDRESS", INT2NUM(CA_REG_ADDRESS));
|
|
@@ -1974,8 +2118,6 @@ Init_carray_access ()
|
|
|
1974
2118
|
rb_define_const(rb_cObject, "CA_REG_MAPPING", INT2NUM(CA_REG_MAPPING));
|
|
1975
2119
|
rb_define_const(rb_cObject, "CA_REG_METHOD_CALL",
|
|
1976
2120
|
INT2NUM(CA_REG_METHOD_CALL));
|
|
1977
|
-
rb_define_const(rb_cObject, "CA_REG_UNBOUND_REPEAT",
|
|
1978
|
-
INT2NUM(CA_REG_UNBOUND_REPEAT));
|
|
1979
2121
|
rb_define_const(rb_cObject, "CA_REG_MEMBER", INT2NUM(CA_REG_MEMBER));
|
|
1980
2122
|
rb_define_const(rb_cObject, "CA_REG_ATTRIBUTE", INT2NUM(CA_REG_ATTRIBUTE));
|
|
1981
2123
|
|