carray 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +5 -25
- data/CHANGELOG.md +16 -0
- data/LICENSE +1 -1
- data/NEWS.md +3 -0
- data/README.md +128 -44
- data/carray.gemspec +22 -24
- data/ext/ca_array_pool.c +91 -0
- data/ext/ca_axis_descriptor.h +186 -0
- data/ext/ca_axis_dispatch.c +924 -0
- data/ext/ca_axis_group.c +1208 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +125 -0
- data/ext/ca_binop_dispatch.h +159 -0
- data/ext/ca_categorical_iterator.c +1375 -0
- data/ext/ca_compare.c +94 -0
- data/ext/ca_compare.h +26 -0
- data/ext/ca_composite_dispatch.c +414 -0
- data/ext/ca_composite_dispatch.h +116 -0
- data/ext/ca_for_buffer.h +96 -0
- data/ext/ca_for_each_element.h +241 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4321 -0
- data/ext/ca_kernel_iterator.h +2603 -0
- data/ext/ca_moncmp_dispatch.c +37 -0
- data/ext/ca_moncmp_dispatch.h +62 -0
- data/ext/ca_monop_dispatch.c +200 -0
- data/ext/ca_monop_dispatch.h +235 -0
- data/ext/ca_obj_array.c +355 -359
- data/ext/ca_obj_bincmp.c +809 -0
- data/ext/ca_obj_binop.c +892 -0
- data/ext/ca_obj_bitarray.c +369 -164
- data/ext/ca_obj_bitfield.c +294 -234
- data/ext/ca_obj_block.c +189 -711
- data/ext/ca_obj_byte_swap.c +766 -0
- data/ext/ca_obj_const_string.c +965 -0
- data/ext/ca_obj_face.c +670 -0
- data/ext/ca_obj_face.h +247 -0
- data/ext/ca_obj_fake.c +228 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +306 -0
- data/ext/ca_obj_grid.c +858 -440
- data/ext/ca_obj_meld.c +1034 -0
- data/ext/ca_obj_moncmp.c +569 -0
- data/ext/ca_obj_monop.c +1111 -0
- data/ext/ca_obj_object.c +774 -298
- data/ext/ca_obj_record.c +468 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +569 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +616 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1296 -0
- data/ext/ca_obj_shift.c +230 -792
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2501 -0
- data/ext/ca_obj_string.c +268 -0
- data/ext/ca_obj_tile.c +614 -0
- data/ext/ca_obj_time.c +546 -0
- data/ext/ca_obj_timedelta.c +435 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +746 -0
- data/ext/ca_obj_unbound_repeat.c +208 -241
- data/ext/ca_obj_window.c +1131 -563
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_ipower.c +319 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +430 -0
- data/ext/ca_sweep_engine.h +157 -0
- data/ext/ca_transform_common.c +228 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +795 -402
- data/ext/carray_access.c +831 -711
- data/ext/carray_attribute.c +98 -330
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +283 -0
- data/ext/carray_call_cfunc.c +1360 -828
- data/ext/carray_call_cfunc.h +160 -0
- data/ext/carray_cast.c +1212 -301
- data/ext/carray_cast_func.rb +81 -40
- data/ext/carray_class.c +53 -63
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +350 -346
- data/ext/carray_copy.c +156 -268
- data/ext/carray_core.c +1342 -199
- data/ext/carray_count.c +312 -0
- data/ext/carray_data_type.c +43 -19
- data/ext/carray_element.c +585 -213
- data/ext/carray_factorize.c +2542 -0
- data/ext/carray_generate.c +230 -559
- data/ext/carray_histogram.c +490 -0
- data/ext/carray_hold.c +228 -0
- data/ext/carray_index_classifier.c +1035 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +120 -0
- data/ext/carray_kernels_bincmp.c +4445 -0
- data/ext/carray_kernels_binop.c +10979 -0
- data/ext/carray_kernels_init.c +36 -0
- data/ext/carray_kernels_map.c +3466 -0
- data/ext/carray_kernels_moncmp.c +2096 -0
- data/ext/carray_kernels_monop.c +18312 -0
- data/ext/carray_kernels_reduce_aggregate.c +25836 -0
- data/ext/carray_kernels_reduce_boolean.c +329 -0
- data/ext/carray_kernels_reduce_cumulative.c +14592 -0
- data/ext/carray_kernels_reduce_extreme.c +16947 -0
- data/ext/carray_kernels_reduce_variance.c +3909 -0
- data/ext/carray_kernels_scan.c +3692 -0
- data/ext/carray_kernels_search.c +32137 -0
- data/ext/carray_kernels_sort.c +10625 -0
- data/ext/carray_kernels_triop.c +1391 -0
- data/ext/carray_lazy.c +567 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +848 -154
- data/ext/carray_math_kernel.h +120 -0
- data/ext/carray_mathfunc.c +10 -241
- data/ext/carray_median_percentile.c +1257 -0
- data/ext/carray_memory_view.c +1625 -0
- data/ext/carray_operator.c +1526 -318
- data/ext/carray_order.c +664 -1394
- data/ext/carray_partition.c +416 -0
- data/ext/carray_random.c +518 -0
- data/ext/carray_scatter.c +357 -0
- data/ext/carray_slab.c +1219 -0
- data/ext/carray_slab.h +84 -0
- data/ext/carray_sort.c +829 -0
- data/ext/carray_sort_kernel.c +620 -0
- data/ext/carray_struct.c +695 -0
- data/ext/carray_test.c +343 -229
- data/ext/carray_undef.c +34 -17
- data/ext/carray_utils.c +175 -74
- data/ext/extconf.rb +216 -55
- data/ext/mk_call_cfunc.rb +480 -0
- data/ext/mkkernel.rb +8842 -0
- data/ext/ruby_carray.c +202 -101
- data/ext/version.h +4 -14
- data/ext/version.rb +5 -13
- data/lib/carray/arrow_tensor.rb +401 -0
- data/lib/carray/attribute.rb +166 -0
- data/lib/carray/autoload_carray.rb +220 -0
- data/lib/carray/autoload_method_extension.rb +44 -0
- data/lib/carray/axis_group.rb +711 -0
- data/lib/carray/basics.rb +481 -0
- data/lib/carray/bincount_nd.rb +358 -0
- data/lib/carray/block_iterator.rb +604 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1062 -0
- data/lib/carray/complex.rb +150 -0
- data/lib/carray/conditional.rb +216 -0
- data/lib/carray/const_string.rb +228 -0
- data/lib/carray/construct.rb +139 -328
- data/lib/carray/core_extensions.rb +240 -0
- data/lib/carray/data_type_extension.rb +233 -0
- data/lib/carray/fixlen_string.rb +95 -0
- data/lib/carray/frame/concat.rb +132 -0
- data/lib/carray/frame/convert.rb +95 -0
- data/lib/carray/frame/csv_parser.rb +211 -0
- data/lib/carray/frame/frame.rb +649 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +164 -0
- data/lib/carray/frame/join.rb +248 -0
- data/lib/carray/frame/records.rb +99 -0
- data/lib/carray/frame/sort.rb +113 -0
- data/lib/carray/frame/verbs.rb +299 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -20
- data/lib/carray/iterator.rb +57 -349
- data/lib/carray/lazy.rb +889 -0
- data/lib/carray/mask_gap_fill.rb +200 -0
- data/lib/carray/math.rb +78 -342
- data/lib/carray/meld_reduce.rb +289 -0
- data/lib/carray/methods/align_addr.rb +116 -0
- data/lib/carray/methods/bin.rb +128 -0
- data/lib/carray/methods/bincount.rb +87 -0
- data/lib/carray/methods/bit_string.rb +92 -0
- data/lib/carray/methods/broadcast.rb +63 -0
- data/lib/carray/methods/choose.rb +39 -0
- data/lib/carray/methods/composition.rb +280 -0
- data/lib/carray/methods/gather_nd.rb +206 -0
- data/lib/carray/methods/index.rb +39 -0
- data/lib/carray/methods/insert_block.rb +99 -0
- data/lib/carray/methods/is_in.rb +141 -0
- data/lib/carray/methods/join.rb +90 -0
- data/lib/carray/methods/locate_addr.rb +47 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +91 -0
- data/lib/carray/methods/mode.rb +126 -0
- data/lib/carray/methods/nunique.rb +46 -0
- data/lib/carray/methods/resize.rb +56 -0
- data/lib/carray/methods/snap.rb +156 -0
- data/lib/carray/methods/string_format.rb +57 -0
- data/lib/carray/methods/unique.rb +47 -0
- data/lib/carray/methods/value_counts.rb +71 -0
- data/lib/carray/mkmf.rb +124 -101
- data/lib/carray/runtime.rb +108 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +292 -0
- data/lib/carray/stack.rb +291 -0
- data/lib/carray/string.rb +56 -180
- data/lib/carray/string_operation_extension.rb +289 -0
- data/lib/carray/struct.rb +335 -323
- data/lib/carray/struct_builder.rb +697 -0
- data/lib/carray/table.rb +41 -2
- data/lib/carray/time.rb +2255 -38
- data/lib/carray/window_iterator.rb +655 -0
- data/lib/carray.rb +55 -57
- metadata +163 -130
- data/Rakefile +0 -51
- data/TODO.md +0 -18
- data/ext/ca_iter_block.c +0 -257
- data/ext/ca_iter_dimension.c +0 -299
- data/ext/ca_iter_window.c +0 -214
- data/ext/ca_obj_mapping.c +0 -644
- data/ext/carray_iterator.c +0 -641
- data/ext/carray_math.rb +0 -850
- data/ext/carray_numeric.c +0 -259
- data/ext/carray_sort_addr.c +0 -254
- data/ext/carray_stat.c +0 -2100
- data/ext/carray_stat_proc.rb +0 -1999
- data/ext/mkmath.rb +0 -741
- data/ext/ruby_ccomplex.c +0 -509
- data/ext/ruby_float_func.c +0 -86
- data/lib/carray/array.rb +0 -8
- data/lib/carray/autoload/autoload_base.rb +0 -19
- data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
- data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
- data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
- data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
- data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
- data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
- data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
- data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
- data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
- data/lib/carray/autoload/autoload_gem_random.rb +0 -8
- data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
- data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
- data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
- data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
- data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
- data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
- data/lib/carray/autoload/autoload_object_link.rb +0 -1
- data/lib/carray/autoload/autoload_object_pack.rb +0 -2
- data/lib/carray/autoload.rb +0 -141
- data/lib/carray/basic.rb +0 -191
- data/lib/carray/broadcast.rb +0 -101
- data/lib/carray/compose.rb +0 -315
- data/lib/carray/convert.rb +0 -115
- data/lib/carray/info.rb +0 -110
- data/lib/carray/io/imagemagick.rb +0 -235
- data/lib/carray/mask.rb +0 -102
- data/lib/carray/math/histogram.rb +0 -177
- data/lib/carray/math/recurrence.rb +0 -93
- data/lib/carray/object/ca_obj_iterator.rb +0 -50
- data/lib/carray/object/ca_obj_link.rb +0 -50
- data/lib/carray/object/ca_obj_pack.rb +0 -99
- data/lib/carray/obsolete.rb +0 -256
- data/lib/carray/ordering.rb +0 -181
- data/lib/carray/testing.rb +0 -51
- data/lib/carray/transform.rb +0 -109
- data/misc/Methods.ja.md +0 -182
- data/misc/NOTE +0 -51
- data/spec/Classes/CABitfield_spec.rb +0 -58
- data/spec/Classes/CABlockIterator_spec.rb +0 -114
- data/spec/Classes/CABlock_spec.rb +0 -205
- data/spec/Classes/CAField_spec.rb +0 -39
- data/spec/Classes/CAGrid_spec.rb +0 -75
- data/spec/Classes/CAMap_spec.rb +0 -0
- data/spec/Classes/CAMapping_spec.rb +0 -105
- data/spec/Classes/CAObject_attribute_spec.rb +0 -33
- data/spec/Classes/CAObject_spec.rb +0 -33
- data/spec/Classes/CARefer_spec.rb +0 -93
- data/spec/Classes/CARepeat_spec.rb +0 -65
- data/spec/Classes/CASelect_spec.rb +0 -22
- data/spec/Classes/CAShift_spec.rb +0 -16
- data/spec/Classes/CAStruct_spec.rb +0 -71
- data/spec/Classes/CATranspose_spec.rb +0 -60
- data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
- data/spec/Classes/CAWindow_spec.rb +0 -54
- data/spec/Classes/CAWrap_spec.rb +0 -8
- data/spec/Classes/CArray_spec.rb +0 -184
- data/spec/Classes/CScalar_spec.rb +0 -55
- data/spec/Classes/ex1.rb +0 -46
- data/spec/Features/feature_130_spec.rb +0 -19
- data/spec/Features/feature_attributes_spec.rb +0 -280
- data/spec/Features/feature_boolean_spec.rb +0 -98
- data/spec/Features/feature_broadcast.rb +0 -116
- data/spec/Features/feature_cast_function.rb +0 -19
- data/spec/Features/feature_cast_spec.rb +0 -33
- data/spec/Features/feature_class_spec.rb +0 -84
- data/spec/Features/feature_complex_spec.rb +0 -42
- data/spec/Features/feature_composite_spec.rb +0 -124
- data/spec/Features/feature_convert_spec.rb +0 -46
- data/spec/Features/feature_copy_spec.rb +0 -123
- data/spec/Features/feature_creation_spec.rb +0 -84
- data/spec/Features/feature_element_spec.rb +0 -144
- data/spec/Features/feature_extream_spec.rb +0 -54
- data/spec/Features/feature_generate_spec.rb +0 -74
- data/spec/Features/feature_index_spec.rb +0 -69
- data/spec/Features/feature_mask_spec.rb +0 -580
- data/spec/Features/feature_math_spec.rb +0 -97
- data/spec/Features/feature_order_spec.rb +0 -146
- data/spec/Features/feature_ref_store_spec.rb +0 -209
- data/spec/Features/feature_serialization_spec.rb +0 -125
- data/spec/Features/feature_stat_spec.rb +0 -397
- data/spec/Features/feature_virtual_spec.rb +0 -48
- data/spec/Features/method_eq_spec.rb +0 -81
- data/spec/Features/method_is_nan_spec.rb +0 -12
- data/spec/Features/method_map_spec.rb +0 -54
- data/spec/Features/method_max_with.rb +0 -20
- data/spec/Features/method_min_with.rb +0 -19
- data/spec/Features/method_ne_spec.rb +0 -18
- data/spec/Features/method_project_spec.rb +0 -188
- data/spec/Features/method_ref_spec.rb +0 -27
- data/spec/Features/method_round_spec.rb +0 -11
- data/spec/Features/method_s_linspace_spec.rb +0 -48
- data/spec/Features/method_s_span_spec.rb +0 -14
- data/spec/Features/method_seq_spec.rb +0 -47
- data/spec/Features/method_sort_with.rb +0 -43
- data/spec/Features/method_sorted_with.rb +0 -29
- data/spec/Features/method_span_spec.rb +0 -42
- data/spec/Features/method_wrap_readonly_spec.rb +0 -43
- data/spec/UnitTest/test_CAVirtual.rb +0 -214
- data/spec/spec_all.rb +0 -10
- data/utils/ca_ase.rb +0 -21
- data/utils/ca_methods.rb +0 -15
- data/utils/cast_checker.rb +0 -30
- data/utils/convert_test.rb +0 -73
- data/utils/extract_yard.rb +0 -22
- data/utils/guess_shape.rb +0 -76
- data/utils/monkey_patch_methods.rb +0 -62
- data/utils/remove_resource_fork.sh +0 -5
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);
|
|
@@ -1029,29 +522,47 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
1029
522
|
|
|
1030
523
|
if ( ca->elements != cv->elements ) {
|
|
1031
524
|
rb_raise(rb_eRuntimeError,
|
|
1032
|
-
"mismatch in data size (%
|
|
525
|
+
"mismatch in data size (%" PRId64 " <-> %" PRId64 ") for storing to carray",
|
|
1033
526
|
(ca_size_t) ca->elements, (ca_size_t) cv->elements);
|
|
1034
527
|
}
|
|
1035
528
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
529
|
+
/* Source delivery via ca_xfer_all into a local scratch instead of
|
|
530
|
+
ca_attach(cv). This routes through ca_*_func_xfer_all's per-region
|
|
531
|
+
partial-materialise path, avoiding a ca_attach(root) silent
|
|
532
|
+
transitive attach. When cv composes through a view root (CAFake /
|
|
533
|
+
CAByteSwap / CAGrid / etc.), attaching the root would materialise
|
|
534
|
+
the whole root (size = root->elements * root->bytes), producing a
|
|
535
|
+
catastrophic slowdown for size-gap cases like
|
|
536
|
+
big_virtual[100..200] = big_virtual[100..200].flip(0). The scratch
|
|
537
|
+
here is sized for cv only (cv->elements * cv->bytes), so the cost
|
|
538
|
+
scales with the view, not the root. (The dst-side ca_sync_data is
|
|
539
|
+
already an xfer_all PUT.) */
|
|
540
|
+
{
|
|
541
|
+
volatile VALUE scratch_holder;
|
|
542
|
+
ca_size_t cv_bytes = cv->bytes * cv->elements;
|
|
543
|
+
char *scratch = ALLOCV_N(char, scratch_holder, cv_bytes);
|
|
544
|
+
ca_xfer_all(cv, scratch, CA_XFER_GET);
|
|
545
|
+
|
|
546
|
+
if ( ca->data_type != cv->data_type ) {
|
|
547
|
+
ca_allocate(ca);
|
|
548
|
+
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
549
|
+
if ( ca->mask ) {
|
|
550
|
+
ca_cast_block_with_mask(ca->elements, cv, scratch, ca, ca->ptr,
|
|
551
|
+
(boolean8_t*)ca->mask->ptr);
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
ca_cast_block(ca->elements, cv, scratch, ca, ca->ptr);
|
|
555
|
+
}
|
|
556
|
+
ca_sync(ca);
|
|
557
|
+
ca_detach(ca);
|
|
1043
558
|
}
|
|
1044
559
|
else {
|
|
1045
|
-
|
|
560
|
+
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
561
|
+
ca_sync_data(ca, scratch);
|
|
1046
562
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
1050
|
-
else {
|
|
1051
|
-
ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
|
|
1052
|
-
ca_sync_data(ca, cv->ptr);
|
|
563
|
+
|
|
564
|
+
ALLOCV_END(scratch_holder);
|
|
1053
565
|
}
|
|
1054
|
-
ca_detach(cv);
|
|
1055
566
|
}
|
|
1056
567
|
else if ( TYPE(rval) == T_ARRAY ) {
|
|
1057
568
|
volatile VALUE list =
|
|
@@ -1064,6 +575,8 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
1064
575
|
else {
|
|
1065
576
|
int has_mask = 0;
|
|
1066
577
|
CArray ico;
|
|
578
|
+
/* ca_cast_block reads ca_is_face(ca1), so flags must be 0-initialised. */
|
|
579
|
+
memset(&ico, 0, sizeof(CArray));
|
|
1067
580
|
ico.data_type = CA_OBJECT;
|
|
1068
581
|
ico.bytes = ca_sizeof[CA_OBJECT];
|
|
1069
582
|
for (i=0; i<ca->elements; i++) {
|
|
@@ -1073,34 +586,56 @@ rb_ca_store_all (VALUE self, VALUE rval)
|
|
|
1073
586
|
break;
|
|
1074
587
|
}
|
|
1075
588
|
}
|
|
1076
|
-
ca_allocate(
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
589
|
+
/* Use ca_allocate() instead of ca_attach() here because rb_ca_store_all()
|
|
590
|
+
overwrites ALL elements of the array from a Ruby Array. There is no need
|
|
591
|
+
to copy parent data (which ca_attach would do), since every element will
|
|
592
|
+
be replaced. Mask handling is also safe: ca_create_mask() above and
|
|
593
|
+
ca_copy_mask_overwrite() handle mask allocation and propagation internally,
|
|
594
|
+
so ca_allocate()'s simpler path (no parent data copy) is sufficient. */
|
|
595
|
+
ca_allocate(ca);
|
|
596
|
+
{
|
|
597
|
+
/* Face has surface != storage; the cast runs in the storage
|
|
598
|
+
data_type. Passing ca directly makes the cast table see FIXLEN
|
|
599
|
+
and report non-implemented, so pass a shadow CArray (storage
|
|
600
|
+
data_type, ptr aliased to ca). */
|
|
601
|
+
CArray shadow;
|
|
602
|
+
CArray *cast_target = ca;
|
|
603
|
+
memset(&shadow, 0, sizeof(CArray));
|
|
604
|
+
if ( ca_is_face(ca) ) {
|
|
605
|
+
CArray *root = ca;
|
|
606
|
+
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
607
|
+
if (root) {
|
|
608
|
+
shadow.data_type = root->data_type;
|
|
609
|
+
shadow.bytes = ca->bytes;
|
|
610
|
+
shadow.elements = ca->elements;
|
|
611
|
+
shadow.ptr = ca->ptr;
|
|
612
|
+
cast_target = &shadow;
|
|
1083
613
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
614
|
+
}
|
|
615
|
+
if ( has_mask ) {
|
|
616
|
+
boolean8_t *m;
|
|
617
|
+
m = (boolean8_t *)ca->mask->ptr;
|
|
618
|
+
for (i=0; i<ca->elements; i++) {
|
|
619
|
+
if ( rb_ary_entry(list,i) == CA_UNDEF ) {
|
|
620
|
+
*m = 1;
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
*m = 0;
|
|
624
|
+
}
|
|
625
|
+
m++;
|
|
1086
626
|
}
|
|
1087
|
-
|
|
627
|
+
ca_cast_block_with_mask(ca->elements, &ico, (VALUE *)RARRAY_CONST_PTR(list),
|
|
628
|
+
cast_target, ca->ptr,
|
|
629
|
+
(boolean8_t*)ca->mask->ptr);
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
ca_cast_block(ca->elements, &ico, (VALUE *)RARRAY_CONST_PTR(list), cast_target, ca->ptr);
|
|
1088
633
|
}
|
|
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
634
|
}
|
|
1096
635
|
ca_sync(ca);
|
|
1097
636
|
ca_detach(ca);
|
|
1098
637
|
}
|
|
1099
638
|
}
|
|
1100
|
-
else if ( rb_respond_to(rval, id_ca) ) {
|
|
1101
|
-
rval = rb_funcall(rval, id_ca, 0);
|
|
1102
|
-
goto retry;
|
|
1103
|
-
}
|
|
1104
639
|
else if ( rb_respond_to(rval, id_to_ca) ) {
|
|
1105
640
|
rval = rb_funcall(rval, id_to_ca, 0);
|
|
1106
641
|
goto retry;
|
|
@@ -1267,7 +802,22 @@ rb_ca_ref_block (VALUE self, CAIndexInfo *info)
|
|
|
1267
802
|
dim, start, step, count, &offset);
|
|
1268
803
|
}
|
|
1269
804
|
|
|
1270
|
-
|
|
805
|
+
{
|
|
806
|
+
volatile VALUE blk;
|
|
807
|
+
blk = rb_ca_block_new(refer, ndim, dim, start, step, count, offset);
|
|
808
|
+
/* The block inherits the Face source's FIXLEN surface; rewrite its
|
|
809
|
+
data_type to the storage data_type (chain bottom) so the write path
|
|
810
|
+
casts in the storage type. */
|
|
811
|
+
if ( ca_is_face(ca) ) {
|
|
812
|
+
CArray *blk_ca, *root = ca;
|
|
813
|
+
TypedData_Get_Struct(blk, CArray, &carray_data_type, blk_ca);
|
|
814
|
+
while (root && ca_is_face(root)) root = ((CAView *) root)->parent;
|
|
815
|
+
if (root && root->data_type != blk_ca->data_type) {
|
|
816
|
+
blk_ca->data_type = root->data_type;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return blk;
|
|
820
|
+
}
|
|
1271
821
|
}
|
|
1272
822
|
|
|
1273
823
|
static VALUE
|
|
@@ -1281,12 +831,120 @@ rb_ca_refer_new_flatten (VALUE self)
|
|
|
1281
831
|
return rb_ca_refer_new(self, ca->data_type, 1, &dim0, ca->bytes, 0);
|
|
1282
832
|
}
|
|
1283
833
|
|
|
1284
|
-
/*
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
834
|
+
/* CARemap routing: when self and mapper have identical shape AND
|
|
835
|
+
mapper's data_type is CA_SIZE, take the same-shape per-element gather
|
|
836
|
+
fast path. Defined in ca_obj_remap.c. */
|
|
837
|
+
extern VALUE rb_ca_remap_new (VALUE cary, VALUE rmapper);
|
|
838
|
+
|
|
839
|
+
/* a[mapper] is semantically equivalent to
|
|
840
|
+
a.flatten[mapper.flatten].reshape(*mapper.dim).
|
|
841
|
+
|
|
842
|
+
Two routes:
|
|
843
|
+
(a) Same-shape + CA_SIZE mapper -> CARemap view (fast path, avoids
|
|
844
|
+
building the flatten/gather/reshape chain).
|
|
845
|
+
(b) Otherwise -> normalize chain (a.flatten[mapper.flatten]
|
|
846
|
+
.reshape). A 1-D mapper is already routed to CAGrid upstream.
|
|
847
|
+
|
|
848
|
+
Both routes raise on a masked mapper. */
|
|
849
|
+
static VALUE
|
|
850
|
+
rb_ca_fancy_index_chain (VALUE self, VALUE rmapper)
|
|
851
|
+
{
|
|
852
|
+
CArray *ca, *cm;
|
|
853
|
+
volatile VALUE flat_self, flat_mapper, gridded, result;
|
|
854
|
+
VALUE grid_argv[1];
|
|
855
|
+
int i;
|
|
856
|
+
|
|
857
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
858
|
+
TypedData_Get_Struct(rmapper, CArray, &carray_data_type, cm);
|
|
859
|
+
|
|
860
|
+
if ( ca_is_any_masked(cm) ) {
|
|
861
|
+
rb_raise(rb_eArgError, "mapper in ca[mapper] should not be masked");
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/* (a) same-shape fast path: ndim + per-axis dim + CA_SIZE data_type. */
|
|
865
|
+
if ( cm->data_type == CA_SIZE
|
|
866
|
+
&& cm->ndim == ca->ndim
|
|
867
|
+
&& memcmp(cm->dim, ca->dim, ca->ndim * sizeof(ca_size_t)) == 0 ) {
|
|
868
|
+
return rb_ca_remap_new(self, rmapper);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
/* (b) Normalize chain fallback. */
|
|
872
|
+
flat_self = rb_ca_refer_new_flatten(self);
|
|
873
|
+
flat_mapper = (cm->ndim == 1) ? rmapper : rb_ca_flatten(rmapper);
|
|
874
|
+
grid_argv[0] = flat_mapper;
|
|
875
|
+
gridded = rb_ca_grid(1, grid_argv, flat_self);
|
|
876
|
+
|
|
877
|
+
if ( cm->ndim == 1 ) {
|
|
878
|
+
result = gridded;
|
|
879
|
+
}
|
|
880
|
+
else {
|
|
881
|
+
VALUE *dim_argv = ALLOCA_N(VALUE, cm->ndim);
|
|
882
|
+
for (i = 0; i < cm->ndim; i++) {
|
|
883
|
+
dim_argv[i] = SIZE2NUM(cm->dim[i]);
|
|
884
|
+
}
|
|
885
|
+
result = rb_ca_reshape(cm->ndim, dim_argv, gridded);
|
|
886
|
+
}
|
|
887
|
+
return result;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/* The CAMapping class is gone; rb_ca_mapping_new and rb_ca_mapping build
|
|
891
|
+
the normalize chain via rb_ca_fancy_index_chain. The public C API
|
|
892
|
+
signatures are preserved so external ext gems keep linking; the runtime
|
|
893
|
+
class of the returned VALUE is CARefer (chain outermost), not CAMapping. */
|
|
894
|
+
|
|
895
|
+
VALUE
|
|
896
|
+
rb_ca_mapping_new (VALUE cary, CArray *mapper)
|
|
897
|
+
{
|
|
898
|
+
CArray *m_copy = ca_copy(mapper);
|
|
899
|
+
volatile VALUE rmapper = ca_wrap_struct(m_copy);
|
|
900
|
+
return rb_ca_fancy_index_chain(cary, rmapper);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
VALUE
|
|
904
|
+
rb_ca_mapping (int argc, VALUE *argv, VALUE self)
|
|
905
|
+
{
|
|
906
|
+
volatile VALUE rmapper;
|
|
907
|
+
rb_scan_args(argc, argv, "1", (VALUE *) &rmapper);
|
|
908
|
+
rb_check_carray_object(rmapper);
|
|
909
|
+
return rb_ca_fancy_index_chain(self, rmapper);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/* ------------------------------------------------------------------- */
|
|
913
|
+
/* newaxis (:_) sugar. `:_` inserts a size-1 axis at its position.
|
|
914
|
+
Strategy: strip `:_`, fetch the remaining per-axis indices into a base
|
|
915
|
+
view, then reshape the base inserting size-1 axes. reshape inherits
|
|
916
|
+
the optimal view class (CAStride for stride bases, CARefer for fancy
|
|
917
|
+
bases). */
|
|
918
|
+
|
|
919
|
+
static int
|
|
920
|
+
ca_argv_has_newaxis (int argc, VALUE *argv)
|
|
921
|
+
{
|
|
922
|
+
int i;
|
|
923
|
+
for (i = 0; i < argc; i++) {
|
|
924
|
+
if ( argv[i] == sym_under ) return 1;
|
|
925
|
+
}
|
|
926
|
+
return 0;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
static int
|
|
930
|
+
ca_argv_has_slab_sigil (int argc, VALUE *argv)
|
|
931
|
+
{
|
|
932
|
+
int i;
|
|
933
|
+
for (i = 0; i < argc; i++) {
|
|
934
|
+
if ( argv[i] == sym_gt ) return 1;
|
|
935
|
+
}
|
|
936
|
+
return 0;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
static VALUE rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self,
|
|
940
|
+
CArray *ca);
|
|
941
|
+
static VALUE rb_ca_slab_iter_new (VALUE self, CAIndexInfo *info);
|
|
942
|
+
static VALUE rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self);
|
|
943
|
+
|
|
944
|
+
/* axis-group apply (ext/ca_group_iter.c): type gate that routes a
|
|
945
|
+
CACategorical/AxisGroup index to the group path. */
|
|
946
|
+
int ca_argv_has_group (int argc, VALUE *argv);
|
|
947
|
+
VALUE rb_ca_fetch_group (int argc, VALUE *argv, VALUE self);
|
|
1290
948
|
|
|
1291
949
|
static VALUE
|
|
1292
950
|
rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
@@ -1299,6 +957,29 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1299
957
|
|
|
1300
958
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1301
959
|
|
|
960
|
+
/* newaxis (:_) interception (cheap pointer scan; zero overhead beyond
|
|
961
|
+
the loop when no :_ is present). */
|
|
962
|
+
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
963
|
+
return rb_ca_fetch_newaxis(argc, argv, self, ca);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/* slab sigil (:>) interception. Pre-strip :> -> nil and Integer ->
|
|
967
|
+
length-1 Range so mask / fancy outer slots route through the regular
|
|
968
|
+
dispatch (CA_REG_SELECT / CA_REG_GRID / CA_REG_MAPPING) before being
|
|
969
|
+
wrapped in CASlabIterator. */
|
|
970
|
+
if ( ca_argv_has_slab_sigil(argc, argv) ) {
|
|
971
|
+
return rb_ca_fetch_slab_sigil(argc, argv, self);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/* Axis-group type gate: a CACategorical/AxisGroup index routes to the
|
|
975
|
+
group apply path (CAGroupIterator); plain int-array indices fall
|
|
976
|
+
through to the regular selection dispatch below. The scan short-circuits
|
|
977
|
+
when the surface classes have not been loaded, so a normal index pays
|
|
978
|
+
nothing. */
|
|
979
|
+
if ( ca_argv_has_group(argc, argv) ) {
|
|
980
|
+
return rb_ca_fetch_group(argc, argv, self);
|
|
981
|
+
}
|
|
982
|
+
|
|
1302
983
|
info.range_check = 1;
|
|
1303
984
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1304
985
|
|
|
@@ -1325,7 +1006,7 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1325
1006
|
obj = rb_ca_select_new(self, argv[0]);
|
|
1326
1007
|
break;
|
|
1327
1008
|
case CA_REG_ITERATOR:
|
|
1328
|
-
obj =
|
|
1009
|
+
obj = rb_ca_slab_iter_new(self, &info);
|
|
1329
1010
|
break;
|
|
1330
1011
|
case CA_REG_REPEAT:
|
|
1331
1012
|
obj = rb_ca_repeat(argc, argv, self);
|
|
@@ -1334,7 +1015,7 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1334
1015
|
obj = rb_funcall2(self, rb_intern("unbound_repeat"), (int) argc, argv);
|
|
1335
1016
|
break;
|
|
1336
1017
|
case CA_REG_MAPPING:
|
|
1337
|
-
obj =
|
|
1018
|
+
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1338
1019
|
break;
|
|
1339
1020
|
case CA_REG_GRID:
|
|
1340
1021
|
obj = rb_ca_grid(argc, argv, self);
|
|
@@ -1348,11 +1029,14 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1348
1029
|
case CA_REG_MEMBER: {
|
|
1349
1030
|
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1350
1031
|
if ( ! NIL_P(data_class) ) {
|
|
1351
|
-
|
|
1352
|
-
|
|
1032
|
+
/* Field projection strips Face and returns a CAField on the parent
|
|
1033
|
+
(= a different data_type). Do not re-wrap with Face (CARecord
|
|
1034
|
+
wraps structs only; a field view like float64 is not a CARecord).
|
|
1035
|
+
Early-return to bypass the trailing ca_face_lift. */
|
|
1036
|
+
return rb_ca_face_field(self, info.symbol);
|
|
1353
1037
|
}
|
|
1354
1038
|
else {
|
|
1355
|
-
rb_raise(rb_eIndexError,
|
|
1039
|
+
rb_raise(rb_eIndexError,
|
|
1356
1040
|
"can't refer member of carray doesn't have data_class");
|
|
1357
1041
|
}
|
|
1358
1042
|
break;
|
|
@@ -1365,9 +1049,222 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1365
1049
|
default:
|
|
1366
1050
|
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1367
1051
|
}
|
|
1052
|
+
|
|
1053
|
+
/* Face lift at the read touch point: if `self` is a Face, re-wrap the
|
|
1054
|
+
view result as a Face (ca_face_lift). Guards: lift only when the result
|
|
1055
|
+
is a CArray instance (excludes Hash / iterator / scalar), and only when
|
|
1056
|
+
it is not ALREADY a Face -- some builders (select / repeat / ...) lift
|
|
1057
|
+
their own result, so re-lifting here would double-wrap and leave `.parent`
|
|
1058
|
+
pointing at a Face instead of the storage. */
|
|
1059
|
+
if ( ca_is_face(ca) && rb_obj_is_kind_of(obj, rb_cCArray) ) {
|
|
1060
|
+
CArray *obj_ca;
|
|
1061
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, obj_ca);
|
|
1062
|
+
if ( ! ca_is_face(obj_ca) ) {
|
|
1063
|
+
obj = ca_face_lift(obj, self);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1368
1067
|
return obj;
|
|
1369
1068
|
}
|
|
1370
1069
|
|
|
1070
|
+
/* newaxis (:_) implementation (reshape). See the forward decl + the
|
|
1071
|
+
interception hook in rb_ca_fetch_method. Pre-condition: argv contains
|
|
1072
|
+
at least one sym_under. */
|
|
1073
|
+
static VALUE
|
|
1074
|
+
rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
1075
|
+
{
|
|
1076
|
+
int i;
|
|
1077
|
+
int nclean = 0;
|
|
1078
|
+
VALUE clean[CA_RANK_MAX];
|
|
1079
|
+
volatile VALUE base;
|
|
1080
|
+
ca_size_t final_dims[CA_RANK_MAX];
|
|
1081
|
+
int nfinal = 0;
|
|
1082
|
+
int base_cursor;
|
|
1083
|
+
CArray *cb;
|
|
1084
|
+
VALUE dim_argv[CA_RANK_MAX];
|
|
1085
|
+
|
|
1086
|
+
/* Build clean argv (strip :_); reject disjoint sigils + rubber dim. */
|
|
1087
|
+
for (i = 0; i < argc; i++) {
|
|
1088
|
+
VALUE a = argv[i];
|
|
1089
|
+
if ( a == sym_under ) continue;
|
|
1090
|
+
if ( a == sym_gt || a == sym_star || a == sym_perc
|
|
1091
|
+
|| a == Qfalse || a == sym_tilde ) {
|
|
1092
|
+
rb_raise(rb_eIndexError,
|
|
1093
|
+
"newaxis (:_) cannot be combined with :>, :*, :%%, "
|
|
1094
|
+
"or rubber dim (false / :~)");
|
|
1095
|
+
}
|
|
1096
|
+
if ( nclean >= CA_RANK_MAX ) {
|
|
1097
|
+
rb_raise(rb_eIndexError, "too many indices");
|
|
1098
|
+
}
|
|
1099
|
+
clean[nclean++] = a;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
/* newaxis requires full per-axis indexing (CArray uses flat addressing
|
|
1103
|
+
for partial indices, which is incoherent with axis-position newaxis). */
|
|
1104
|
+
if ( nclean != ca->ndim ) {
|
|
1105
|
+
rb_raise(rb_eIndexError,
|
|
1106
|
+
"newaxis (:_) requires full per-axis indexing "
|
|
1107
|
+
"(got %d non-:_ indices for ndim %d)",
|
|
1108
|
+
nclean, (int) ca->ndim);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
base = rb_ca_fetch_method(nclean, clean, self);
|
|
1112
|
+
|
|
1113
|
+
/* Degenerate: all real axes scalar -> base is a scalar element, not a
|
|
1114
|
+
CArray. Out of scope (rare + degenerate); user indexes the element
|
|
1115
|
+
and reshapes explicitly. IndexError keeps it catchable + consistent
|
|
1116
|
+
with the other newaxis rejects. */
|
|
1117
|
+
if ( ! rb_obj_is_kind_of(base, rb_cCArray) ) {
|
|
1118
|
+
rb_raise(rb_eIndexError,
|
|
1119
|
+
"newaxis (:_) needs at least one non-scalar axis "
|
|
1120
|
+
"(all-scalar indexing yields a single element)");
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
TypedData_Get_Struct(base, CArray, &carray_data_type, cb);
|
|
1124
|
+
|
|
1125
|
+
/* Reconstruct final shape: walk original argv. :_ -> size-1, scalar
|
|
1126
|
+
(Integer) -> dropped (skip), else -> base.dim[cursor]. */
|
|
1127
|
+
base_cursor = 0;
|
|
1128
|
+
for (i = 0; i < argc; i++) {
|
|
1129
|
+
VALUE a = argv[i];
|
|
1130
|
+
if ( a == sym_under ) {
|
|
1131
|
+
final_dims[nfinal++] = 1;
|
|
1132
|
+
}
|
|
1133
|
+
else if ( FIXNUM_P(a) || RB_TYPE_P(a, T_BIGNUM) ) {
|
|
1134
|
+
/* scalar index -> axis dropped in base; contributes no output axis */
|
|
1135
|
+
}
|
|
1136
|
+
else {
|
|
1137
|
+
if ( base_cursor >= cb->ndim ) {
|
|
1138
|
+
rb_raise(rb_eIndexError, "newaxis: base axis count mismatch");
|
|
1139
|
+
}
|
|
1140
|
+
final_dims[nfinal++] = cb->dim[base_cursor++];
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
if ( base_cursor != cb->ndim ) {
|
|
1144
|
+
rb_raise(rb_eIndexError, "newaxis: base axis count mismatch");
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
for (i = 0; i < nfinal; i++) {
|
|
1148
|
+
dim_argv[i] = SIZE2NUM(final_dims[i]);
|
|
1149
|
+
}
|
|
1150
|
+
return rb_ca_reshape(nfinal, dim_argv, base);
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
/* Build a CASlabIterator from a classified ITERATOR index. The
|
|
1154
|
+
`:>` axes (CA_IDX_SYMBOL) become the slab axes; they are converted to
|
|
1155
|
+
CA_IDX_ALL so rb_ca_ref_block yields the sliced base view keeping all
|
|
1156
|
+
axes (scalars are already length-1 BLOCKs via the finalize_reg post-
|
|
1157
|
+
pass). CASlabIterator delegates to each_slab / map_slab / reduce_slab. */
|
|
1158
|
+
static VALUE
|
|
1159
|
+
rb_ca_slab_iter_new (VALUE self, CAIndexInfo *info)
|
|
1160
|
+
{
|
|
1161
|
+
volatile VALUE slab_axes = rb_ary_new();
|
|
1162
|
+
volatile VALUE base;
|
|
1163
|
+
volatile VALUE klass;
|
|
1164
|
+
int i;
|
|
1165
|
+
|
|
1166
|
+
for (i = 0; i < info->ndim; i++) {
|
|
1167
|
+
if ( info->index_type[i] == CA_IDX_SYMBOL ) {
|
|
1168
|
+
rb_ary_push(slab_axes, INT2NUM(i));
|
|
1169
|
+
info->index_type[i] = CA_IDX_ALL; /* :> axis -> full range */
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
base = rb_ca_ref_block(self, info);
|
|
1174
|
+
klass = rb_const_get(rb_cObject, rb_intern("CASlabIterator"));
|
|
1175
|
+
return rb_funcall(klass, rb_intern("new"), 2, base, slab_axes);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/* Slab sigil dispatcher that supports any outer-slot index type
|
|
1179
|
+
(Integer / Range / nil / boolean mask / CArray / Symbol-method etc.).
|
|
1180
|
+
Strategy: expand rubber dim (false / :~) if present so :> positions
|
|
1181
|
+
align with the post-expansion ndim, replace :> with nil (full axis),
|
|
1182
|
+
promote Integer to length-1 Range so the base view preserves ndim,
|
|
1183
|
+
recurse through the regular indexer dispatch to build the base
|
|
1184
|
+
reference (CABlock / CASelectAxis / CAGrid / CAMapping / ...), then
|
|
1185
|
+
wrap in CASlabIterator with the recorded slab_axes positions. */
|
|
1186
|
+
static VALUE
|
|
1187
|
+
rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
1188
|
+
{
|
|
1189
|
+
VALUE expanded[CA_RANK_MAX];
|
|
1190
|
+
VALUE clean[CA_RANK_MAX];
|
|
1191
|
+
volatile VALUE slab_axes = rb_ary_new();
|
|
1192
|
+
volatile VALUE base;
|
|
1193
|
+
volatile VALUE klass;
|
|
1194
|
+
CArray *ca;
|
|
1195
|
+
int i, j;
|
|
1196
|
+
int eargc;
|
|
1197
|
+
VALUE *eargv;
|
|
1198
|
+
int rubber_pos = -1;
|
|
1199
|
+
|
|
1200
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1201
|
+
|
|
1202
|
+
/* Rubber-dim expansion (mirrors ca_classifier_expand_rubber_dim).
|
|
1203
|
+
Only the first rubber marker is honoured; later ones are left for
|
|
1204
|
+
the regular classifier to reject downstream. */
|
|
1205
|
+
for (i = 0; i < argc; i++) {
|
|
1206
|
+
if ( argv[i] == Qfalse || argv[i] == sym_tilde ) {
|
|
1207
|
+
rubber_pos = i;
|
|
1208
|
+
break;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
if ( rubber_pos < 0 ) {
|
|
1212
|
+
eargc = argc;
|
|
1213
|
+
eargv = argv;
|
|
1214
|
+
}
|
|
1215
|
+
else {
|
|
1216
|
+
int rndim;
|
|
1217
|
+
if ( argc > ca->ndim + 1 ) {
|
|
1218
|
+
rb_raise(rb_eIndexError,
|
|
1219
|
+
"index specification exceeds the ndim of carray (%i)",
|
|
1220
|
+
ca->ndim);
|
|
1221
|
+
}
|
|
1222
|
+
rndim = ca->ndim - argc + 1;
|
|
1223
|
+
if ( rndim < 0 ) rndim = 0;
|
|
1224
|
+
j = 0;
|
|
1225
|
+
for (i = 0; i < argc; i++) {
|
|
1226
|
+
if ( i == rubber_pos ) {
|
|
1227
|
+
int k;
|
|
1228
|
+
for (k = 0; k < rndim; k++) expanded[j++] = Qnil;
|
|
1229
|
+
}
|
|
1230
|
+
else {
|
|
1231
|
+
expanded[j++] = argv[i];
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
eargc = j;
|
|
1235
|
+
eargv = expanded;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
if ( eargc > CA_RANK_MAX ) {
|
|
1239
|
+
rb_raise(rb_eIndexError, "too many indices");
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
for (i = 0; i < eargc; i++) {
|
|
1243
|
+
VALUE a = eargv[i];
|
|
1244
|
+
if ( a == sym_gt ) {
|
|
1245
|
+
rb_ary_push(slab_axes, INT2NUM(i));
|
|
1246
|
+
clean[i] = Qnil;
|
|
1247
|
+
}
|
|
1248
|
+
else if ( FIXNUM_P(a) || RB_TYPE_P(a, T_BIGNUM) ) {
|
|
1249
|
+
/* Promote Integer to length-1 Range so the recursed view keeps
|
|
1250
|
+
the axis (matches the existing :> dispatcher semantics where
|
|
1251
|
+
scalars become length-1 BLOCKs via finalize_reg). */
|
|
1252
|
+
clean[i] = rb_range_new(a, a, 0);
|
|
1253
|
+
}
|
|
1254
|
+
else {
|
|
1255
|
+
clean[i] = a;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
base = rb_ca_fetch_method(eargc, clean, self);
|
|
1260
|
+
if ( ! rb_obj_is_kind_of(base, rb_cCArray) ) {
|
|
1261
|
+
rb_raise(rb_eIndexError,
|
|
1262
|
+
"slab sigil (:>) requires the base view to be a CArray");
|
|
1263
|
+
}
|
|
1264
|
+
klass = rb_const_get(rb_cObject, rb_intern("CASlabIterator"));
|
|
1265
|
+
return rb_funcall(klass, rb_intern("new"), 2, base, slab_axes);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1371
1268
|
static VALUE
|
|
1372
1269
|
rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
1373
1270
|
{
|
|
@@ -1403,7 +1300,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1403
1300
|
obj = rb_ca_select_new(self, argv[0]);
|
|
1404
1301
|
break;
|
|
1405
1302
|
case CA_REG_ITERATOR:
|
|
1406
|
-
obj =
|
|
1303
|
+
obj = rb_ca_slab_iter_new(self, &info);
|
|
1407
1304
|
break;
|
|
1408
1305
|
case CA_REG_REPEAT:
|
|
1409
1306
|
obj = rb_ca_repeat(argc, argv, self);
|
|
@@ -1412,7 +1309,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1412
1309
|
obj = rb_funcall2(self, rb_intern("unbound_repeat"), (int) argc, argv);
|
|
1413
1310
|
break;
|
|
1414
1311
|
case CA_REG_MAPPING:
|
|
1415
|
-
obj =
|
|
1312
|
+
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1416
1313
|
break;
|
|
1417
1314
|
case CA_REG_GRID:
|
|
1418
1315
|
obj = rb_ca_grid(argc, argv, self);
|
|
@@ -1426,7 +1323,7 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1426
1323
|
case CA_REG_MEMBER: {
|
|
1427
1324
|
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1428
1325
|
if ( ! NIL_P(data_class) ) {
|
|
1429
|
-
obj =
|
|
1326
|
+
obj = rb_ca_face_field(self, info.symbol);
|
|
1430
1327
|
break;
|
|
1431
1328
|
}
|
|
1432
1329
|
else {
|
|
@@ -1447,12 +1344,67 @@ rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
|
1447
1344
|
return obj;
|
|
1448
1345
|
}
|
|
1449
1346
|
|
|
1450
|
-
/*
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1347
|
+
/* Recursively convert a store rvalue's surface value objects into
|
|
1348
|
+
storage-domain values for a Face `self`, applied at the Ruby `[]=` entry
|
|
1349
|
+
before any store-side view (block / newaxis / grid / ...) is built. The
|
|
1350
|
+
store-side view is stripped to the storage data_type, so the Face is only
|
|
1351
|
+
visible here at the top of the dispatch; converting now lets every view
|
|
1352
|
+
path store a Face surface scalar correctly.
|
|
1353
|
+
|
|
1354
|
+
- a Face CArray rvalue is reconciled to self's storage via to_comparable
|
|
1355
|
+
(unit-safe: cross-group / non-exact raises), so a same-Face bulk store
|
|
1356
|
+
(t[0..1] = t[1..2]) becomes a storage int64 xfer. A non-Face CArray
|
|
1357
|
+
(e.g. datetime[0..1] = plain_int64_array) passes through unchanged --
|
|
1358
|
+
the documented raw-storage escape -- but it has to be raw *storage*: an
|
|
1359
|
+
integer-storage Face takes integer cells only. The scalar path already
|
|
1360
|
+
refuses a bare Float there (to_comparable does not recognise it) instead
|
|
1361
|
+
of letting the storage cast truncate it, and the bulk path must not be
|
|
1362
|
+
the looser door.
|
|
1363
|
+
- an Array is mapped structure-preserving (leaves converted),
|
|
1364
|
+
- a scalar goes through the write hook (ca_face_scalar_to_storage), which
|
|
1365
|
+
leaves a bare Integer / String unchanged.
|
|
1366
|
+
|
|
1367
|
+
Idempotent: an already-converted Integer passes through, so re-running on
|
|
1368
|
+
a `goto retry` iteration is harmless. */
|
|
1369
|
+
static VALUE
|
|
1370
|
+
ca_face_convert_store_rval (VALUE self, CArray *ca, VALUE val)
|
|
1371
|
+
{
|
|
1372
|
+
if ( rb_obj_is_carray(val) ) {
|
|
1373
|
+
CArray *cval;
|
|
1374
|
+
GetCArray(val, cval);
|
|
1375
|
+
/* Face RHS: reconcile to self's unit and descend to storage. Mirror of
|
|
1376
|
+
the scalar path (ca_face_scalar_to_storage) for a bulk CArray source.
|
|
1377
|
+
Guarded on self having to_comparable so a Face without a reconcile
|
|
1378
|
+
algebra (e.g. a fixlen-storage Face, whose same-storage store already
|
|
1379
|
+
takes the storage xfer branch) is left to the existing store path. */
|
|
1380
|
+
if ( ca_is_face(cval) && rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
1381
|
+
volatile VALUE reconciled = rb_funcall(self, rb_intern("to_comparable"),
|
|
1382
|
+
1, val);
|
|
1383
|
+
return rb_funcall(reconciled, rb_intern("parent"), 0);
|
|
1384
|
+
}
|
|
1385
|
+
/* Bare storage escape, integer storage: integer cells only (see above). */
|
|
1386
|
+
{
|
|
1387
|
+
CArray *storage = ca_strip_face(ca);
|
|
1388
|
+
if ( storage && ca_is_integer_type(storage) && ! ca_is_integer_type(cval) ) {
|
|
1389
|
+
rb_raise(rb_eTypeError,
|
|
1390
|
+
"%s cannot store a bare %s array as raw storage "
|
|
1391
|
+
"(use ca.parent to write the %s storage directly)",
|
|
1392
|
+
rb_obj_classname(self), ca_type_name[cval->data_type],
|
|
1393
|
+
ca_type_name[storage->data_type]);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
return val;
|
|
1397
|
+
}
|
|
1398
|
+
if ( TYPE(val) == T_ARRAY ) {
|
|
1399
|
+
long i, n = RARRAY_LEN(val);
|
|
1400
|
+
volatile VALUE out = rb_ary_new2(n);
|
|
1401
|
+
for (i = 0; i < n; i++) {
|
|
1402
|
+
rb_ary_push(out, ca_face_convert_store_rval(self, ca, rb_ary_entry(val, i)));
|
|
1403
|
+
}
|
|
1404
|
+
return out;
|
|
1405
|
+
}
|
|
1406
|
+
return ca_face_scalar_to_storage(self, ca, val);
|
|
1407
|
+
}
|
|
1456
1408
|
|
|
1457
1409
|
static VALUE
|
|
1458
1410
|
rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
@@ -1470,6 +1422,31 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1470
1422
|
|
|
1471
1423
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1472
1424
|
|
|
1425
|
+
/* Face store: bring a surface value object (Scalar / Time / DateTime) into
|
|
1426
|
+
the storage domain while self is still the Face. Store-side views strip
|
|
1427
|
+
the Face to storage, so this is the only point that sees it. */
|
|
1428
|
+
if ( ca_is_face(ca) ) {
|
|
1429
|
+
rval = ca_face_convert_store_rval(self, ca, rval);
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/* newaxis (:_) interception on store. Build the newaxis view (a
|
|
1433
|
+
writable reshape aliasing self), then assign rval into the whole view
|
|
1434
|
+
(writes propagate to self). */
|
|
1435
|
+
if ( ca_argv_has_newaxis(argc, argv) ) {
|
|
1436
|
+
volatile VALUE view = rb_ca_fetch_newaxis(argc, argv, self, ca);
|
|
1437
|
+
rb_ca_store_all(view, rval);
|
|
1438
|
+
return rval;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
/* slab sigil on store is rejected regardless of outer-slot type. Catch
|
|
1442
|
+
:> before scan_index so mask/fancy outer slots get the same "not
|
|
1443
|
+
supported" message instead of a misleading TypeError. */
|
|
1444
|
+
if ( ca_argv_has_slab_sigil(argc, argv) ) {
|
|
1445
|
+
rb_raise(rb_eIndexError,
|
|
1446
|
+
"assignment through a slab iterator (:>) is not supported "
|
|
1447
|
+
"(use a block index, e.g. ca[range, nil] = val, or each_slab)");
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1473
1450
|
info.range_check = 1;
|
|
1474
1451
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1475
1452
|
|
|
@@ -1502,8 +1479,11 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1502
1479
|
break;
|
|
1503
1480
|
}
|
|
1504
1481
|
case CA_REG_ITERATOR: {
|
|
1505
|
-
|
|
1506
|
-
|
|
1482
|
+
/* assignment through a slab iterator (:>) is not supported.
|
|
1483
|
+
Use a block index (ca[range, nil] = val) or each_slab/map_slab. */
|
|
1484
|
+
rb_raise(rb_eIndexError,
|
|
1485
|
+
"assignment through a slab iterator (:>) is not supported "
|
|
1486
|
+
"(use a block index, e.g. ca[range, nil] = val, or each_slab)");
|
|
1507
1487
|
break;
|
|
1508
1488
|
}
|
|
1509
1489
|
case CA_REG_REPEAT: {
|
|
@@ -1516,7 +1496,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1516
1496
|
obj = rb_ca_store_all(obj, rval);
|
|
1517
1497
|
break;
|
|
1518
1498
|
case CA_REG_MAPPING: {
|
|
1519
|
-
obj =
|
|
1499
|
+
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1520
1500
|
obj = rb_ca_store_all(obj, rval);
|
|
1521
1501
|
break;
|
|
1522
1502
|
}
|
|
@@ -1537,7 +1517,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1537
1517
|
case CA_REG_MEMBER: {
|
|
1538
1518
|
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1539
1519
|
if ( ! NIL_P(data_class) ) {
|
|
1540
|
-
obj =
|
|
1520
|
+
obj = rb_ca_face_field(self, info.symbol);
|
|
1541
1521
|
obj = rb_ca_store_all(obj, rval);
|
|
1542
1522
|
}
|
|
1543
1523
|
else {
|
|
@@ -1552,6 +1532,7 @@ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
|
|
|
1552
1532
|
break;
|
|
1553
1533
|
}
|
|
1554
1534
|
}
|
|
1535
|
+
|
|
1555
1536
|
return obj;
|
|
1556
1537
|
}
|
|
1557
1538
|
|
|
@@ -1560,7 +1541,7 @@ rb_ca_fetch (VALUE self, VALUE index)
|
|
|
1560
1541
|
{
|
|
1561
1542
|
switch ( TYPE(index) ) {
|
|
1562
1543
|
case T_ARRAY:
|
|
1563
|
-
return rb_ca_fetch_method((int) RARRAY_LEN(index),
|
|
1544
|
+
return rb_ca_fetch_method((int) RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1564
1545
|
default:
|
|
1565
1546
|
return rb_ca_fetch_method(1, &index, self);
|
|
1566
1547
|
}
|
|
@@ -1579,7 +1560,7 @@ rb_ca_store (VALUE self, VALUE index, VALUE rval)
|
|
|
1579
1560
|
case T_ARRAY:
|
|
1580
1561
|
index = rb_obj_clone(index);
|
|
1581
1562
|
rb_ary_push(index, rval);
|
|
1582
|
-
return rb_ca_store_method((int)RARRAY_LEN(index),
|
|
1563
|
+
return rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1583
1564
|
default: {
|
|
1584
1565
|
VALUE rindex[2] = { index, rval };
|
|
1585
1566
|
return rb_ca_store_method(2, rindex, self);
|
|
@@ -1590,16 +1571,11 @@ rb_ca_store (VALUE self, VALUE index, VALUE rval)
|
|
|
1590
1571
|
VALUE
|
|
1591
1572
|
rb_ca_store2 (VALUE self, int n, VALUE *rindex, VALUE rval)
|
|
1592
1573
|
{
|
|
1593
|
-
VALUE index = rb_ary_new4(n, rindex);
|
|
1574
|
+
volatile VALUE index = rb_ary_new4(n, rindex);
|
|
1594
1575
|
rb_ary_push(index, rval);
|
|
1595
|
-
return rb_ca_store_method((int)RARRAY_LEN(index),
|
|
1576
|
+
return rb_ca_store_method((int)RARRAY_LEN(index), (VALUE *)RARRAY_CONST_PTR(index), self);
|
|
1596
1577
|
}
|
|
1597
1578
|
|
|
1598
|
-
/* yard:
|
|
1599
|
-
def CArray.scan_index(dim, idx)
|
|
1600
|
-
end
|
|
1601
|
-
*/
|
|
1602
|
-
|
|
1603
1579
|
static VALUE
|
|
1604
1580
|
rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
1605
1581
|
{
|
|
@@ -1625,7 +1601,7 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1625
1601
|
|
|
1626
1602
|
info.range_check = 1;
|
|
1627
1603
|
rb_ca_scan_index(ndim, dim, elements,
|
|
1628
|
-
RARRAY_LEN(ridx),
|
|
1604
|
+
RARRAY_LEN(ridx), (VALUE *)RARRAY_CONST_PTR(ridx), &info);
|
|
1629
1605
|
|
|
1630
1606
|
rtype = INT2NUM(info.type);
|
|
1631
1607
|
rindex = rb_ary_new2(info.ndim);
|
|
@@ -1704,13 +1680,6 @@ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1704
1680
|
return rb_struct_new(S_CAInfo, rtype, rindex);
|
|
1705
1681
|
}
|
|
1706
1682
|
|
|
1707
|
-
/* yard:
|
|
1708
|
-
class CArray
|
|
1709
|
-
def normalize_index (idx)
|
|
1710
|
-
end
|
|
1711
|
-
end
|
|
1712
|
-
*/
|
|
1713
|
-
|
|
1714
1683
|
static VALUE
|
|
1715
1684
|
rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
1716
1685
|
{
|
|
@@ -1724,7 +1693,7 @@ rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
|
1724
1693
|
|
|
1725
1694
|
info.range_check = 1;
|
|
1726
1695
|
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements,
|
|
1727
|
-
RARRAY_LEN(ridx),
|
|
1696
|
+
RARRAY_LEN(ridx), (VALUE *)RARRAY_CONST_PTR(ridx), &info);
|
|
1728
1697
|
|
|
1729
1698
|
switch ( info.type ) {
|
|
1730
1699
|
case CA_REG_ALL:
|
|
@@ -1777,78 +1746,153 @@ rb_ca_normalize_index (VALUE self, VALUE ridx)
|
|
|
1777
1746
|
|
|
1778
1747
|
/* ------------------------------------------------------------------- */
|
|
1779
1748
|
|
|
1780
|
-
/*
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1749
|
+
/* ------------------------------------------------------------------- */
|
|
1750
|
+
/* addr <-> index conversion primitives.
|
|
1751
|
+
*
|
|
1752
|
+
* Two dispatch axes:
|
|
1753
|
+
* (a) instance form (uses self.shape) vs class form (`shape:` kwarg)
|
|
1754
|
+
* (b) scalar input vs CArray input (per method)
|
|
1755
|
+
*
|
|
1756
|
+
* The four Ruby entry points (rb_ca_{addr2index,index2addr},
|
|
1757
|
+
* rb_ca_s_{addr2index,index2addr}) all funnel into the two _do helpers
|
|
1758
|
+
* below, which take an already-resolved (ndim, dim[], elements) triple.
|
|
1759
|
+
*/
|
|
1787
1760
|
|
|
1788
|
-
|
|
1789
|
-
|
|
1761
|
+
static void
|
|
1762
|
+
parse_shape_kwarg (VALUE rshape, int *out_ndim, ca_size_t *dim,
|
|
1763
|
+
ca_size_t *out_elements)
|
|
1764
|
+
{
|
|
1765
|
+
int i, ndim;
|
|
1766
|
+
ca_size_t elements = 1;
|
|
1767
|
+
|
|
1768
|
+
Check_Type(rshape, T_ARRAY);
|
|
1769
|
+
ndim = (int) RARRAY_LEN(rshape);
|
|
1770
|
+
if ( ndim < 1 || ndim > CA_RANK_MAX ) {
|
|
1771
|
+
rb_raise(rb_eArgError, "invalid shape ndim %d (must be 1..%d)",
|
|
1772
|
+
ndim, CA_RANK_MAX);
|
|
1773
|
+
}
|
|
1774
|
+
for (i = 0; i < ndim; i++) {
|
|
1775
|
+
dim[i] = NUM2SIZE(rb_ary_entry(rshape, i));
|
|
1776
|
+
if ( dim[i] < 0 ) {
|
|
1777
|
+
rb_raise(rb_eArgError, "negative dim %" PRId64 " at axis %d",
|
|
1778
|
+
(ca_size_t) dim[i], i);
|
|
1779
|
+
}
|
|
1780
|
+
elements *= dim[i];
|
|
1781
|
+
}
|
|
1782
|
+
*out_ndim = ndim;
|
|
1783
|
+
*out_elements = elements;
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
static VALUE
|
|
1787
|
+
addr2index_do (int ndim, ca_size_t *dim, ca_size_t elements, VALUE raddr)
|
|
1790
1788
|
{
|
|
1791
1789
|
volatile VALUE out;
|
|
1792
|
-
CArray *ca;
|
|
1793
|
-
ca_size_t *dim;
|
|
1794
|
-
ca_size_t addr;
|
|
1795
1790
|
int i;
|
|
1796
1791
|
|
|
1797
|
-
|
|
1792
|
+
/* Scalar path (Integer input): returns Ruby Array of N Integers.
|
|
1793
|
+
* Preserves legacy shape for callers like `i, j = ca.addr2index(k)`. */
|
|
1794
|
+
if ( rb_obj_is_kind_of(raddr, rb_cInteger) ) {
|
|
1795
|
+
ca_size_t addr = NUM2SIZE(raddr);
|
|
1796
|
+
if ( addr < 0 || addr >= elements ) {
|
|
1797
|
+
rb_raise(rb_eArgError,
|
|
1798
|
+
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1799
|
+
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
1800
|
+
}
|
|
1801
|
+
out = rb_ary_new2(ndim);
|
|
1802
|
+
for (i = ndim - 1; i >= 0; i--) {
|
|
1803
|
+
rb_ary_store(out, i, SIZE2NUM(addr % dim[i]));
|
|
1804
|
+
addr /= dim[i];
|
|
1805
|
+
}
|
|
1806
|
+
return out;
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
/* Vector path (CArray input): returns Ruby Array of N CArrays,
|
|
1810
|
+
* each with the same shape as the input; mask propagated. */
|
|
1811
|
+
{
|
|
1812
|
+
CArray *cin, *co[CA_RANK_MAX];
|
|
1813
|
+
ca_size_t *p_out[CA_RANK_MAX];
|
|
1814
|
+
boolean8_t *m;
|
|
1815
|
+
ca_size_t j, n;
|
|
1816
|
+
volatile VALUE objs[CA_RANK_MAX];
|
|
1817
|
+
|
|
1818
|
+
cin = ca_wrap_readonly(raddr, CA_SIZE);
|
|
1819
|
+
ca_attach(cin);
|
|
1820
|
+
|
|
1821
|
+
out = rb_ary_new2(ndim);
|
|
1822
|
+
for (i = 0; i < ndim; i++) {
|
|
1823
|
+
objs[i] = rb_carray_new(CA_SIZE, cin->ndim, cin->dim, 0, NULL);
|
|
1824
|
+
TypedData_Get_Struct(objs[i], CArray, &carray_data_type, co[i]);
|
|
1825
|
+
p_out[i] = (ca_size_t *) co[i]->ptr;
|
|
1826
|
+
rb_ary_store(out, i, objs[i]);
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
m = cin->mask ? (boolean8_t *) cin->mask->ptr : NULL;
|
|
1830
|
+
if ( m ) {
|
|
1831
|
+
for (i = 0; i < ndim; i++) {
|
|
1832
|
+
ca_create_mask(co[i]);
|
|
1833
|
+
memcpy(co[i]->mask->ptr, m, cin->elements);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1798
1836
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1837
|
+
n = cin->elements;
|
|
1838
|
+
{
|
|
1839
|
+
ca_size_t *src = (ca_size_t *) cin->ptr;
|
|
1840
|
+
ca_size_t addr;
|
|
1841
|
+
int k;
|
|
1842
|
+
for (j = 0; j < n; j++) {
|
|
1843
|
+
if ( m && m[j] ) {
|
|
1844
|
+
for (k = 0; k < ndim; k++) { p_out[k][j] = 0; }
|
|
1845
|
+
continue;
|
|
1846
|
+
}
|
|
1847
|
+
addr = src[j];
|
|
1848
|
+
if ( addr < 0 || addr >= elements ) {
|
|
1849
|
+
ca_detach(cin);
|
|
1850
|
+
rb_raise(rb_eArgError,
|
|
1851
|
+
"address %" PRId64 " is out of range (0..%" PRId64 ")",
|
|
1852
|
+
(ca_size_t) addr, (ca_size_t) (elements - 1));
|
|
1853
|
+
}
|
|
1854
|
+
for (k = ndim - 1; k >= 0; k--) {
|
|
1855
|
+
p_out[k][j] = addr % dim[k];
|
|
1856
|
+
addr /= dim[k];
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1811
1860
|
|
|
1812
|
-
|
|
1861
|
+
ca_detach(cin);
|
|
1862
|
+
return out;
|
|
1863
|
+
}
|
|
1813
1864
|
}
|
|
1814
1865
|
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
def index2addr (*index)
|
|
1818
|
-
end
|
|
1819
|
-
end
|
|
1820
|
-
*/
|
|
1821
|
-
|
|
1822
|
-
VALUE
|
|
1823
|
-
rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
1866
|
+
static VALUE
|
|
1867
|
+
index2addr_do (int ndim, ca_size_t *dim, int argc, VALUE *argv)
|
|
1824
1868
|
{
|
|
1825
1869
|
volatile VALUE obj;
|
|
1826
|
-
CArray
|
|
1870
|
+
CArray *co, *cidx[CA_RANK_MAX];
|
|
1827
1871
|
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;
|
|
1872
|
+
ca_size_t addr, k, n;
|
|
1832
1873
|
boolean8_t *m;
|
|
1833
|
-
int
|
|
1874
|
+
int i, all_number = 1;
|
|
1875
|
+
int out_ndim = 1;
|
|
1876
|
+
ca_size_t out_dim[CA_RANK_MAX];
|
|
1877
|
+
ca_size_t out_elements = 1;
|
|
1878
|
+
int shape_from = -1;
|
|
1834
1879
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
rb_raise(rb_eRuntimeError, "invalid ndim of index");
|
|
1880
|
+
if ( argc != ndim ) {
|
|
1881
|
+
rb_raise(rb_eArgError,
|
|
1882
|
+
"wrong number of indices (%d for %d)", argc, ndim);
|
|
1839
1883
|
}
|
|
1840
1884
|
|
|
1841
|
-
for (i=0; i<
|
|
1885
|
+
for (i = 0; i < ndim; i++) {
|
|
1842
1886
|
if ( ! rb_obj_is_kind_of(argv[i], rb_cInteger) ) {
|
|
1843
1887
|
all_number = 0;
|
|
1844
1888
|
break;
|
|
1845
1889
|
}
|
|
1846
1890
|
}
|
|
1847
1891
|
|
|
1892
|
+
/* All-scalar path: returns single Integer (unchanged). */
|
|
1848
1893
|
if ( all_number ) {
|
|
1849
|
-
dim = ca->dim;
|
|
1850
1894
|
addr = 0;
|
|
1851
|
-
for (i=0; i<
|
|
1895
|
+
for (i = 0; i < ndim; i++) {
|
|
1852
1896
|
k = NUM2SIZE(argv[i]);
|
|
1853
1897
|
CA_CHECK_INDEX(k, dim[i]);
|
|
1854
1898
|
addr = dim[i] * addr + k;
|
|
@@ -1856,62 +1900,77 @@ rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
|
1856
1900
|
return SIZE2NUM(addr);
|
|
1857
1901
|
}
|
|
1858
1902
|
|
|
1859
|
-
|
|
1860
|
-
|
|
1903
|
+
/* Vector path: wrap each arg as CA_SIZE view. Output shape follows
|
|
1904
|
+
* the first non-scalar CArray input; other non-scalar inputs must
|
|
1905
|
+
* match that shape. */
|
|
1906
|
+
for (i = 0; i < ndim; i++) {
|
|
1861
1907
|
cidx[i] = ca_wrap_readonly(argv[i], CA_SIZE);
|
|
1862
1908
|
if ( ! ca_is_scalar(cidx[i]) ) {
|
|
1863
|
-
if (
|
|
1864
|
-
|
|
1909
|
+
if ( shape_from < 0 ) {
|
|
1910
|
+
shape_from = i;
|
|
1911
|
+
out_ndim = cidx[i]->ndim;
|
|
1912
|
+
memcpy(out_dim, cidx[i]->dim, sizeof(ca_size_t) * out_ndim);
|
|
1913
|
+
out_elements = cidx[i]->elements;
|
|
1865
1914
|
}
|
|
1866
|
-
else
|
|
1867
|
-
|
|
1915
|
+
else {
|
|
1916
|
+
int j;
|
|
1917
|
+
if ( cidx[i]->ndim != out_ndim
|
|
1918
|
+
|| cidx[i]->elements != out_elements ) {
|
|
1919
|
+
rb_raise(rb_eArgError,
|
|
1920
|
+
"shape mismatch: axis %d has shape ndim=%d elements=%"
|
|
1921
|
+
PRId64 ", expected ndim=%d elements=%" PRId64,
|
|
1922
|
+
i, cidx[i]->ndim, (ca_size_t) cidx[i]->elements,
|
|
1923
|
+
out_ndim, (ca_size_t) out_elements);
|
|
1924
|
+
}
|
|
1925
|
+
for (j = 0; j < out_ndim; j++) {
|
|
1926
|
+
if ( cidx[i]->dim[j] != out_dim[j] ) {
|
|
1927
|
+
rb_raise(rb_eArgError,
|
|
1928
|
+
"shape mismatch at axis %d dim %d", i, j);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1868
1931
|
}
|
|
1869
1932
|
}
|
|
1870
1933
|
}
|
|
1871
1934
|
|
|
1872
|
-
for (i=0; i<
|
|
1935
|
+
for (i = 0; i < ndim; i++) {
|
|
1873
1936
|
ca_attach(cidx[i]);
|
|
1874
1937
|
ca_set_iterator(1, cidx[i], &p[i], &s[i]);
|
|
1875
1938
|
}
|
|
1876
1939
|
|
|
1877
|
-
obj = rb_carray_new(CA_SIZE,
|
|
1940
|
+
obj = rb_carray_new(CA_SIZE, out_ndim, out_dim, 0, NULL);
|
|
1878
1941
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
|
|
1879
1942
|
|
|
1880
1943
|
q = (ca_size_t *) co->ptr;
|
|
1881
1944
|
|
|
1882
|
-
ca_copy_mask_overwrite_n(co,
|
|
1945
|
+
ca_copy_mask_overwrite_n(co, out_elements, ndim, cidx);
|
|
1883
1946
|
m = ( co->mask ) ? (boolean8_t *) co->mask->ptr : NULL;
|
|
1884
1947
|
|
|
1885
|
-
dim = ca->dim;
|
|
1886
|
-
|
|
1887
1948
|
if ( m ) {
|
|
1888
|
-
n =
|
|
1949
|
+
n = out_elements;
|
|
1889
1950
|
while ( n-- ) {
|
|
1890
|
-
if (
|
|
1951
|
+
if ( ! *m ) {
|
|
1891
1952
|
addr = 0;
|
|
1892
|
-
for (i=0; i<
|
|
1953
|
+
for (i = 0; i < ndim; i++) {
|
|
1893
1954
|
k = *(p[i]);
|
|
1894
|
-
p[i]+=s[i];
|
|
1955
|
+
p[i] += s[i];
|
|
1895
1956
|
CA_CHECK_INDEX(k, dim[i]);
|
|
1896
1957
|
addr = dim[i] * addr + k;
|
|
1897
1958
|
}
|
|
1898
1959
|
*q = addr;
|
|
1899
1960
|
}
|
|
1900
1961
|
else {
|
|
1901
|
-
for (i=0; i<
|
|
1902
|
-
p[i]+=s[i];
|
|
1903
|
-
}
|
|
1962
|
+
for (i = 0; i < ndim; i++) { p[i] += s[i]; }
|
|
1904
1963
|
}
|
|
1905
1964
|
m++; q++;
|
|
1906
1965
|
}
|
|
1907
1966
|
}
|
|
1908
1967
|
else {
|
|
1909
|
-
n =
|
|
1968
|
+
n = out_elements;
|
|
1910
1969
|
while ( n-- ) {
|
|
1911
1970
|
addr = 0;
|
|
1912
|
-
for (i=0; i<
|
|
1971
|
+
for (i = 0; i < ndim; i++) {
|
|
1913
1972
|
k = *(p[i]);
|
|
1914
|
-
p[i]+=s[i];
|
|
1973
|
+
p[i] += s[i];
|
|
1915
1974
|
CA_CHECK_INDEX(k, dim[i]);
|
|
1916
1975
|
addr = dim[i] * addr + k;
|
|
1917
1976
|
}
|
|
@@ -1920,26 +1979,84 @@ rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
|
1920
1979
|
}
|
|
1921
1980
|
}
|
|
1922
1981
|
|
|
1923
|
-
for (i=0; i<
|
|
1924
|
-
ca_detach(cidx[i]);
|
|
1925
|
-
}
|
|
1982
|
+
for (i = 0; i < ndim; i++) { ca_detach(cidx[i]); }
|
|
1926
1983
|
|
|
1927
1984
|
return obj;
|
|
1928
1985
|
}
|
|
1929
1986
|
|
|
1987
|
+
VALUE
|
|
1988
|
+
rb_ca_addr2index (VALUE self, VALUE raddr)
|
|
1989
|
+
{
|
|
1990
|
+
CArray *ca;
|
|
1991
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1992
|
+
return addr2index_do(ca->ndim, ca->dim, ca->elements, raddr);
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
VALUE
|
|
1996
|
+
rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
|
|
1997
|
+
{
|
|
1998
|
+
CArray *ca;
|
|
1999
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
2000
|
+
return index2addr_do(ca->ndim, ca->dim, argc, argv);
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
/* CArray.addr2index(addr, shape: [...]) */
|
|
2004
|
+
static VALUE
|
|
2005
|
+
rb_ca_s_addr2index (int argc, VALUE *argv, VALUE klass)
|
|
2006
|
+
{
|
|
2007
|
+
VALUE raddr, opts;
|
|
2008
|
+
ID kw_ids[1];
|
|
2009
|
+
VALUE kw_vals[1];
|
|
2010
|
+
int ndim;
|
|
2011
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
2012
|
+
ca_size_t elements;
|
|
2013
|
+
|
|
2014
|
+
kw_ids[0] = rb_intern("shape");
|
|
2015
|
+
rb_scan_args(argc, argv, "1:", &raddr, &opts);
|
|
2016
|
+
if ( NIL_P(opts) ) {
|
|
2017
|
+
rb_raise(rb_eArgError, "missing keyword: shape");
|
|
2018
|
+
}
|
|
2019
|
+
rb_get_kwargs(opts, kw_ids, 1, 0, kw_vals);
|
|
2020
|
+
parse_shape_kwarg(kw_vals[0], &ndim, dim, &elements);
|
|
2021
|
+
return addr2index_do(ndim, dim, elements, raddr);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
/* CArray.index2addr(*index, shape: [...]) */
|
|
2025
|
+
static VALUE
|
|
2026
|
+
rb_ca_s_index2addr (int argc, VALUE *argv, VALUE klass)
|
|
2027
|
+
{
|
|
2028
|
+
VALUE rest, opts;
|
|
2029
|
+
ID kw_ids[1];
|
|
2030
|
+
VALUE kw_vals[1];
|
|
2031
|
+
int ndim;
|
|
2032
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
2033
|
+
ca_size_t elements;
|
|
2034
|
+
|
|
2035
|
+
kw_ids[0] = rb_intern("shape");
|
|
2036
|
+
rb_scan_args(argc, argv, "*:", &rest, &opts);
|
|
2037
|
+
if ( NIL_P(opts) ) {
|
|
2038
|
+
rb_raise(rb_eArgError, "missing keyword: shape");
|
|
2039
|
+
}
|
|
2040
|
+
rb_get_kwargs(opts, kw_ids, 1, 0, kw_vals);
|
|
2041
|
+
parse_shape_kwarg(kw_vals[0], &ndim, dim, &elements);
|
|
2042
|
+
return index2addr_do(ndim, dim, (int) RARRAY_LEN(rest), RARRAY_PTR(rest));
|
|
2043
|
+
}
|
|
2044
|
+
|
|
1930
2045
|
|
|
1931
2046
|
void
|
|
1932
|
-
Init_carray_access ()
|
|
2047
|
+
Init_carray_access (void)
|
|
1933
2048
|
{
|
|
1934
2049
|
|
|
1935
2050
|
id_begin = rb_intern("begin");
|
|
1936
2051
|
id_end = rb_intern("end");
|
|
1937
2052
|
id_excl_end = rb_intern("exclude_end?");
|
|
1938
2053
|
|
|
1939
|
-
id_ca = rb_intern("ca");
|
|
1940
2054
|
id_to_ca = rb_intern("to_ca");
|
|
1941
|
-
sym_star
|
|
1942
|
-
sym_perc
|
|
2055
|
+
sym_star = ID2SYM(rb_intern("*"));
|
|
2056
|
+
sym_perc = ID2SYM(rb_intern("%"));
|
|
2057
|
+
sym_under = ID2SYM(rb_intern("_"));
|
|
2058
|
+
sym_gt = ID2SYM(rb_intern(">"));
|
|
2059
|
+
sym_tilde = ID2SYM(rb_intern("~"));
|
|
1943
2060
|
|
|
1944
2061
|
rb_define_method(rb_cCArray, "[]", rb_ca_fetch_method, -1);
|
|
1945
2062
|
rb_define_method(rb_cCArray, "[]=", rb_ca_store_method, -1);
|
|
@@ -1959,6 +2076,9 @@ Init_carray_access ()
|
|
|
1959
2076
|
rb_define_method(rb_cCArray, "index2addr", rb_ca_index2addr, -1);
|
|
1960
2077
|
rb_define_method(rb_cCArray, "addr2index", rb_ca_addr2index, 1);
|
|
1961
2078
|
|
|
2079
|
+
rb_define_singleton_method(rb_cCArray, "addr2index", rb_ca_s_addr2index, -1);
|
|
2080
|
+
rb_define_singleton_method(rb_cCArray, "index2addr", rb_ca_s_index2addr, -1);
|
|
2081
|
+
|
|
1962
2082
|
rb_define_const(rb_cObject, "CA_REG_NONE", INT2NUM(CA_REG_NONE));
|
|
1963
2083
|
rb_define_const(rb_cObject, "CA_REG_ALL", INT2NUM(CA_REG_ALL));
|
|
1964
2084
|
rb_define_const(rb_cObject, "CA_REG_ADDRESS", INT2NUM(CA_REG_ADDRESS));
|