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_element.c
CHANGED
|
@@ -1,22 +1,82 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Per-cell (`elem_*`) hot-path family for tight scalar loops
|
|
4
|
+
(histogram increment, scatter writes, per-cell swap / mask).
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
These skip the indexer front-end (`ca[i,j,k]` -> scan_index_v2 ->
|
|
7
|
+
ref_point) and land at the same `rb_ca_fetch_index` backend with
|
|
8
|
+
the front-end dispatcher removed. Inline helpers below collapse
|
|
9
|
+
the remaining per-call overheads (double TypedData_Get_Struct,
|
|
10
|
+
T_ARRAY bounds check, NUM2SIZE Bignum branch, ca_update_mask
|
|
11
|
+
function-call for the entity + no-mask common case). Semantics
|
|
12
|
+
match the indexer path.
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
YARD signatures live in yard-stubs/carray_element.rb.
|
|
8
15
|
|
|
9
16
|
---------------------------------------------------------------------------- */
|
|
10
17
|
|
|
11
18
|
#include "ruby.h"
|
|
12
19
|
#include "carray.h"
|
|
20
|
+
#include "ca_obj_face.h"
|
|
13
21
|
|
|
14
|
-
/*
|
|
22
|
+
/* T_ARRAY index parser. ridx is assumed already known to be T_ARRAY.
|
|
23
|
+
Direct VALUE * access + FIXNUM_P fast path eliminates rb_ary_entry
|
|
24
|
+
bounds check and NUM2SIZE Bignum branching for the common case. */
|
|
25
|
+
static inline void
|
|
26
|
+
elem_parse_idx_array (CArray *ca, VALUE rary, ca_size_t *idx)
|
|
27
|
+
{
|
|
28
|
+
const VALUE *iarr = RARRAY_CONST_PTR(rary);
|
|
29
|
+
int8_t ndim = ca->ndim;
|
|
30
|
+
int8_t i;
|
|
31
|
+
for (i=0; i<ndim; i++) {
|
|
32
|
+
VALUE v = iarr[i];
|
|
33
|
+
ca_size_t k = FIXNUM_P(v) ? (ca_size_t)FIX2LONG(v) : NUM2SIZE(v);
|
|
34
|
+
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
35
|
+
idx[i] = k;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Scalar index parser (flat addr). FIXNUM_P fast path. */
|
|
40
|
+
static inline ca_size_t
|
|
41
|
+
elem_parse_idx_scalar (CArray *ca, VALUE ridx)
|
|
42
|
+
{
|
|
43
|
+
ca_size_t k = FIXNUM_P(ridx) ? (ca_size_t)FIX2LONG(ridx) : NUM2SIZE(ridx);
|
|
44
|
+
CA_CHECK_INDEX(k, ca->elements);
|
|
45
|
+
return k;
|
|
46
|
+
}
|
|
15
47
|
|
|
16
|
-
/*
|
|
48
|
+
/* Mask-existence probe with inline skip for the entity+no-mask common
|
|
49
|
+
case. Equivalent to `ca_update_mask(ca); has_mask = (ca->mask != NULL);`
|
|
50
|
+
but avoids the function call when the result is statically known. */
|
|
51
|
+
static inline int
|
|
52
|
+
elem_probe_mask (CArray *ca)
|
|
53
|
+
{
|
|
54
|
+
if ( ca->mask ) return 1; /* mask already materialised */
|
|
55
|
+
if ( ca_is_entity(ca) ) return 0; /* entity + no mask: definitely none */
|
|
56
|
+
ca_update_mask(ca); /* view: may need to materialise */
|
|
57
|
+
return ( ca->mask != NULL );
|
|
58
|
+
}
|
|
17
59
|
|
|
18
|
-
|
|
19
|
-
|
|
60
|
+
/* Entity-array fast path: compute flat addr from idx[] and access ptr directly.
|
|
61
|
+
Bypasses ca_func[ARRAY].xfer_index function-pointer dispatch.
|
|
62
|
+
Caller must ensure ca_is_entity(ca) and ca->ptr is attached (= entity
|
|
63
|
+
arrays are always attached by definition). */
|
|
64
|
+
static inline ca_size_t
|
|
65
|
+
elem_entity_addr (CArray *ca, ca_size_t *idx)
|
|
66
|
+
{
|
|
67
|
+
ca_size_t n = idx[0];
|
|
68
|
+
int8_t i;
|
|
69
|
+
for (i=1; i<ca->ndim; i++) {
|
|
70
|
+
n = ca->dim[i] * n + idx[i];
|
|
71
|
+
}
|
|
72
|
+
return n;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* ------------------------------------------------------------------- */
|
|
76
|
+
|
|
77
|
+
/* `elem_swap(idx1, idx2)` — exchanges the values (and mask states,
|
|
78
|
+
* if any) at cells `idx1` and `idx2` in place. `idx*` accept either
|
|
79
|
+
* a flat Integer address or an Array<Integer> of per-axis indices. */
|
|
20
80
|
|
|
21
81
|
VALUE
|
|
22
82
|
rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
@@ -24,10 +84,8 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
24
84
|
CArray *ca;
|
|
25
85
|
ca_size_t idx1[CA_RANK_MAX], idx2[CA_RANK_MAX];
|
|
26
86
|
ca_size_t addr1 = 0, addr2 = 0;
|
|
27
|
-
int8_t i;
|
|
28
|
-
ca_size_t k;
|
|
29
87
|
int has_mask, has_index1, has_index2;
|
|
30
|
-
char _val1[
|
|
88
|
+
char _val1[64], _val2[64];
|
|
31
89
|
char *val1 = _val1, *val2 = _val2;
|
|
32
90
|
boolean8_t m1 = 0, m2 = 0;
|
|
33
91
|
|
|
@@ -35,20 +93,15 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
35
93
|
|
|
36
94
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
37
95
|
|
|
38
|
-
|
|
39
|
-
has_mask = ( ca->mask ) ? 1 : 0;
|
|
96
|
+
has_mask = elem_probe_mask(ca);
|
|
40
97
|
|
|
41
|
-
if ( ca->bytes >
|
|
42
|
-
val1 =
|
|
43
|
-
val2 =
|
|
98
|
+
if ( ca->bytes > 64 ) {
|
|
99
|
+
val1 = xmalloc(ca->bytes);
|
|
100
|
+
val2 = xmalloc(ca->bytes);
|
|
44
101
|
}
|
|
45
102
|
|
|
46
103
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
47
|
-
|
|
48
|
-
k = NUM2SIZE(rb_ary_entry(ridx1, i));
|
|
49
|
-
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
50
|
-
idx1[i] = k;
|
|
51
|
-
}
|
|
104
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
52
105
|
has_index1 = 1;
|
|
53
106
|
ca_fetch_index(ca, idx1, val1);
|
|
54
107
|
if ( has_mask ) {
|
|
@@ -56,9 +109,7 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
56
109
|
}
|
|
57
110
|
}
|
|
58
111
|
else {
|
|
59
|
-
|
|
60
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
61
|
-
addr1 = k;
|
|
112
|
+
addr1 = elem_parse_idx_scalar(ca, ridx1);
|
|
62
113
|
has_index1 = 0;
|
|
63
114
|
ca_fetch_addr(ca, addr1, val1);
|
|
64
115
|
if ( has_mask ) {
|
|
@@ -67,11 +118,7 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
67
118
|
}
|
|
68
119
|
|
|
69
120
|
if ( TYPE(ridx2) == T_ARRAY ) {
|
|
70
|
-
|
|
71
|
-
k = NUM2SIZE(rb_ary_entry(ridx2, i));
|
|
72
|
-
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
73
|
-
idx2[i] = k;
|
|
74
|
-
}
|
|
121
|
+
elem_parse_idx_array(ca, ridx2, idx2);
|
|
75
122
|
has_index2 = 1;
|
|
76
123
|
ca_fetch_index(ca, idx2, val2);
|
|
77
124
|
if ( has_mask ) {
|
|
@@ -79,9 +126,7 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
79
126
|
}
|
|
80
127
|
}
|
|
81
128
|
else {
|
|
82
|
-
|
|
83
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
84
|
-
addr2 = k;
|
|
129
|
+
addr2 = elem_parse_idx_scalar(ca, ridx2);
|
|
85
130
|
has_index2 = 0;
|
|
86
131
|
ca_fetch_addr(ca, addr2, val2);
|
|
87
132
|
if ( has_mask ) {
|
|
@@ -115,18 +160,16 @@ rb_ca_elem_swap (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
115
160
|
}
|
|
116
161
|
}
|
|
117
162
|
|
|
118
|
-
if ( ca->bytes >
|
|
119
|
-
|
|
120
|
-
|
|
163
|
+
if ( ca->bytes > 64 ) {
|
|
164
|
+
xfree(val1);
|
|
165
|
+
xfree(val2);
|
|
121
166
|
}
|
|
122
167
|
|
|
123
168
|
return self;
|
|
124
169
|
}
|
|
125
170
|
|
|
126
|
-
/*
|
|
127
|
-
|
|
128
|
-
(Element) Copies the value of the element of idx1 to the element of idx2
|
|
129
|
-
*/
|
|
171
|
+
/* `elem_copy(idx1, idx2)` — copies the value (and mask state) at
|
|
172
|
+
* `idx1` into the cell at `idx2`; source cell is left unchanged. */
|
|
130
173
|
|
|
131
174
|
VALUE
|
|
132
175
|
rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
@@ -134,10 +177,8 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
134
177
|
CArray *ca;
|
|
135
178
|
ca_size_t idx1[CA_RANK_MAX], idx2[CA_RANK_MAX];
|
|
136
179
|
ca_size_t addr1 = 0, addr2 = 0;
|
|
137
|
-
int8_t i;
|
|
138
|
-
ca_size_t k;
|
|
139
180
|
int has_mask;
|
|
140
|
-
char _val[
|
|
181
|
+
char _val[64];
|
|
141
182
|
char *val = _val;
|
|
142
183
|
boolean8_t m = 0;
|
|
143
184
|
|
|
@@ -145,28 +186,21 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
145
186
|
|
|
146
187
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
147
188
|
|
|
148
|
-
|
|
149
|
-
has_mask = ( ca->mask ) ? 1 : 0;
|
|
189
|
+
has_mask = elem_probe_mask(ca);
|
|
150
190
|
|
|
151
|
-
if ( ca->bytes >
|
|
152
|
-
val =
|
|
191
|
+
if ( ca->bytes > 64 ) {
|
|
192
|
+
val = xmalloc(ca->bytes);
|
|
153
193
|
}
|
|
154
194
|
|
|
155
195
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
156
|
-
|
|
157
|
-
k = NUM2SIZE(rb_ary_entry(ridx1, i));
|
|
158
|
-
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
159
|
-
idx1[i] = k;
|
|
160
|
-
}
|
|
196
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
161
197
|
ca_fetch_index(ca, idx1, val);
|
|
162
198
|
if ( has_mask ) {
|
|
163
199
|
ca_fetch_index(ca->mask, idx1, &m);
|
|
164
200
|
}
|
|
165
201
|
}
|
|
166
202
|
else {
|
|
167
|
-
|
|
168
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
169
|
-
addr1 = k;
|
|
203
|
+
addr1 = elem_parse_idx_scalar(ca, ridx1);
|
|
170
204
|
ca_fetch_addr(ca, addr1, val);
|
|
171
205
|
if ( has_mask ) {
|
|
172
206
|
ca_fetch_addr(ca->mask, addr1, &m);
|
|
@@ -174,105 +208,228 @@ rb_ca_elem_copy (VALUE self, VALUE ridx1, VALUE ridx2)
|
|
|
174
208
|
}
|
|
175
209
|
|
|
176
210
|
if ( TYPE(ridx2) == T_ARRAY ) {
|
|
177
|
-
|
|
178
|
-
k = NUM2SIZE(rb_ary_entry(ridx2, i));
|
|
179
|
-
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
180
|
-
idx2[i] = k;
|
|
181
|
-
}
|
|
211
|
+
elem_parse_idx_array(ca, ridx2, idx2);
|
|
182
212
|
ca_store_index(ca, idx2, val);
|
|
183
213
|
if ( has_mask ) {
|
|
184
214
|
ca_store_index(ca->mask, idx2, &m);
|
|
185
215
|
}
|
|
186
216
|
}
|
|
187
217
|
else {
|
|
188
|
-
|
|
189
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
190
|
-
addr2 = k;
|
|
218
|
+
addr2 = elem_parse_idx_scalar(ca, ridx2);
|
|
191
219
|
ca_store_addr(ca, addr2, val);
|
|
192
220
|
if ( has_mask ) {
|
|
193
221
|
ca_store_addr(ca->mask, addr2, &m);
|
|
194
222
|
}
|
|
195
223
|
}
|
|
196
224
|
|
|
197
|
-
if ( ca->bytes >
|
|
198
|
-
|
|
225
|
+
if ( ca->bytes > 64 ) {
|
|
226
|
+
xfree(val);
|
|
199
227
|
}
|
|
200
228
|
|
|
201
229
|
return self;
|
|
202
230
|
}
|
|
203
231
|
|
|
204
|
-
/*
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
*/
|
|
232
|
+
/* `elem_store(idx, obj)` — stores `obj` (cast to `self.data_type`)
|
|
233
|
+
* at cell `idx`, clearing any mask state there. Passing `UNDEF`
|
|
234
|
+
* masks the cell. */
|
|
208
235
|
|
|
209
236
|
VALUE
|
|
210
237
|
rb_ca_elem_store (VALUE self, VALUE ridx, VALUE obj)
|
|
211
238
|
{
|
|
212
239
|
CArray *ca;
|
|
213
240
|
ca_size_t idx[CA_RANK_MAX];
|
|
214
|
-
ca_size_t addr
|
|
215
|
-
|
|
216
|
-
ca_size_t k;
|
|
241
|
+
ca_size_t addr;
|
|
242
|
+
int from_array;
|
|
217
243
|
|
|
218
244
|
rb_ca_modify(self);
|
|
219
245
|
|
|
220
246
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
221
247
|
|
|
222
248
|
if ( TYPE(ridx) == T_ARRAY ) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
249
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
250
|
+
from_array = 1;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
addr = elem_parse_idx_scalar(ca, ridx);
|
|
254
|
+
from_array = 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* Super-hot path: entity + no mask + common numeric dtype + Numeric obj.
|
|
258
|
+
Bypasses rb_ca_store_index/addr -> ca_update_mask + rb_ca_obj2ptr ->
|
|
259
|
+
cast_table dispatch. Falls through to general path for: views,
|
|
260
|
+
existing mask, non-numeric dtype, UNDEF, or non-Numeric obj. */
|
|
261
|
+
if ( ca_is_entity(ca) && ! ca->mask && obj != CA_UNDEF ) {
|
|
262
|
+
int8_t dt = ca->data_type;
|
|
263
|
+
if ( dt == CA_FLOAT64 || dt == CA_FLOAT32 ||
|
|
264
|
+
dt == CA_INT64 || dt == CA_INT32 ||
|
|
265
|
+
dt == CA_INT16 || dt == CA_INT8 ||
|
|
266
|
+
dt == CA_UINT64 || dt == CA_UINT32 ||
|
|
267
|
+
dt == CA_UINT16 || dt == CA_UINT8 ||
|
|
268
|
+
dt == CA_BOOLEAN ) {
|
|
269
|
+
/* Compute flat addr if T_ARRAY index path. */
|
|
270
|
+
if ( from_array ) addr = elem_entity_addr(ca, idx);
|
|
271
|
+
char *p = ca->ptr + ca->bytes * addr;
|
|
272
|
+
/* Convert obj to dtype + store. Restrict to Fixnum / Float / true
|
|
273
|
+
/ false to avoid Bignum / Rational / Complex coercion that the
|
|
274
|
+
cast_table handles in the general path. */
|
|
275
|
+
switch ( dt ) {
|
|
276
|
+
case CA_FLOAT64:
|
|
277
|
+
if ( RB_FLOAT_TYPE_P(obj) ) { *(double *)p = RFLOAT_VALUE(obj); return obj; }
|
|
278
|
+
if ( FIXNUM_P(obj) ) { *(double *)p = (double)FIX2LONG(obj); return obj; }
|
|
279
|
+
break;
|
|
280
|
+
case CA_FLOAT32:
|
|
281
|
+
if ( RB_FLOAT_TYPE_P(obj) ) { *(float *)p = (float)RFLOAT_VALUE(obj); return obj; }
|
|
282
|
+
if ( FIXNUM_P(obj) ) { *(float *)p = (float)FIX2LONG(obj); return obj; }
|
|
283
|
+
break;
|
|
284
|
+
case CA_INT64:
|
|
285
|
+
if ( FIXNUM_P(obj) ) { *(int64_t *)p = (int64_t)FIX2LONG(obj); return obj; }
|
|
286
|
+
break;
|
|
287
|
+
case CA_INT32:
|
|
288
|
+
if ( FIXNUM_P(obj) ) { *(int32_t *)p = (int32_t)FIX2LONG(obj); return obj; }
|
|
289
|
+
break;
|
|
290
|
+
case CA_INT16:
|
|
291
|
+
if ( FIXNUM_P(obj) ) { *(int16_t *)p = (int16_t)FIX2LONG(obj); return obj; }
|
|
292
|
+
break;
|
|
293
|
+
case CA_INT8:
|
|
294
|
+
if ( FIXNUM_P(obj) ) { *(int8_t *)p = (int8_t)FIX2LONG(obj); return obj; }
|
|
295
|
+
break;
|
|
296
|
+
case CA_UINT64:
|
|
297
|
+
if ( FIXNUM_P(obj) ) { *(uint64_t *)p = (uint64_t)FIX2LONG(obj); return obj; }
|
|
298
|
+
break;
|
|
299
|
+
case CA_UINT32:
|
|
300
|
+
if ( FIXNUM_P(obj) ) { *(uint32_t *)p = (uint32_t)FIX2LONG(obj); return obj; }
|
|
301
|
+
break;
|
|
302
|
+
case CA_UINT16:
|
|
303
|
+
if ( FIXNUM_P(obj) ) { *(uint16_t *)p = (uint16_t)FIX2LONG(obj); return obj; }
|
|
304
|
+
break;
|
|
305
|
+
case CA_UINT8:
|
|
306
|
+
if ( FIXNUM_P(obj) ) { *(uint8_t *)p = (uint8_t)FIX2LONG(obj); return obj; }
|
|
307
|
+
break;
|
|
308
|
+
case CA_BOOLEAN:
|
|
309
|
+
if ( obj == Qtrue ) { *(uint8_t *)p = 1; return obj; }
|
|
310
|
+
if ( obj == Qfalse ) { *(uint8_t *)p = 0; return obj; }
|
|
311
|
+
if ( FIXNUM_P(obj) ) { *(uint8_t *)p = (FIX2LONG(obj) != 0); return obj; }
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
/* Fall through: dtype matches but obj kind needs general coercion. */
|
|
227
315
|
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/* General path: dispatch through rb_ca_store_index/addr. */
|
|
319
|
+
if ( from_array ) {
|
|
228
320
|
rb_ca_store_index(self, idx, obj);
|
|
229
321
|
}
|
|
230
322
|
else {
|
|
231
|
-
k = NUM2SIZE(ridx);
|
|
232
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
233
|
-
addr = k;
|
|
234
323
|
rb_ca_store_addr(self, addr, obj);
|
|
235
324
|
}
|
|
236
325
|
|
|
237
326
|
return obj;
|
|
238
327
|
}
|
|
239
328
|
|
|
240
|
-
/*
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
*/
|
|
329
|
+
/* `elem_fetch(idx)` — returns the value at cell `idx` (cast to a
|
|
330
|
+
* Ruby object). Returns `UNDEF` if the cell is masked, `nil` if
|
|
331
|
+
* `self` is empty. */
|
|
244
332
|
|
|
245
333
|
VALUE
|
|
246
334
|
rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
247
335
|
{
|
|
248
336
|
CArray *ca;
|
|
249
337
|
ca_size_t idx[CA_RANK_MAX];
|
|
250
|
-
ca_size_t addr = 0;
|
|
251
|
-
int8_t i;
|
|
252
|
-
ca_size_t k;
|
|
253
338
|
|
|
254
339
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
255
340
|
|
|
341
|
+
if ( ca_is_empty(ca) ) return Qnil;
|
|
342
|
+
|
|
256
343
|
if ( TYPE(ridx) == T_ARRAY ) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
344
|
+
volatile VALUE out;
|
|
345
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
346
|
+
|
|
347
|
+
/* Super-hot path: entity + common numeric dtype + no mask.
|
|
348
|
+
Bypass ca_fetch_index dispatch AND rb_ca_ptr2obj cast-table dispatch.
|
|
349
|
+
Covers the bench's float64 / int64 / int32 cases. */
|
|
350
|
+
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
351
|
+
ca_size_t addr = elem_entity_addr(ca, idx);
|
|
352
|
+
char *p = ca->ptr + ca->bytes * addr;
|
|
353
|
+
switch ( ca->data_type ) {
|
|
354
|
+
case CA_FLOAT64: return rb_float_new(*(double *)p);
|
|
355
|
+
case CA_INT64: return LL2NUM(*(int64_t *)p);
|
|
356
|
+
case CA_INT32: return INT2NUM(*(int32_t *)p);
|
|
357
|
+
case CA_FLOAT32: return rb_float_new((double)*(float *)p);
|
|
358
|
+
case CA_INT16: return INT2FIX(*(int16_t *)p);
|
|
359
|
+
case CA_INT8: return INT2FIX(*(int8_t *)p);
|
|
360
|
+
case CA_UINT8: return INT2FIX(*(uint8_t *)p);
|
|
361
|
+
case CA_UINT16: return INT2FIX(*(uint16_t *)p);
|
|
362
|
+
case CA_UINT32: return UINT2NUM(*(uint32_t *)p);
|
|
363
|
+
case CA_UINT64: return ULL2NUM(*(uint64_t *)p);
|
|
364
|
+
case CA_BOOLEAN: return (*(uint8_t *)p) ? Qtrue : Qfalse;
|
|
365
|
+
/* default: fall through to general path below */
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/* General path: inlined rb_ca_fetch_index body (avoid duplicate
|
|
370
|
+
TypedData_Get_Struct). Semantics identical to rb_ca_fetch_index. */
|
|
371
|
+
if ( ca->bytes <= 64 ) {
|
|
372
|
+
char v[64];
|
|
373
|
+
if ( ca_is_entity(ca) ) {
|
|
374
|
+
ca_size_t addr = elem_entity_addr(ca, idx);
|
|
375
|
+
memcpy(v, ca->ptr + ca->bytes * addr, ca->bytes);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
ca_fetch_index(ca, idx, v);
|
|
379
|
+
}
|
|
380
|
+
out = rb_ca_ptr2obj(self, v);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
char *v = xmalloc(ca->bytes);
|
|
384
|
+
ca_fetch_index(ca, idx, v);
|
|
385
|
+
out = rb_ca_ptr2obj(self, v);
|
|
386
|
+
xfree(v);
|
|
261
387
|
}
|
|
262
|
-
|
|
388
|
+
|
|
389
|
+
/* Mask check with inline skip for the entity+no-mask common case. */
|
|
390
|
+
if ( ca->mask ) {
|
|
391
|
+
boolean8_t mval;
|
|
392
|
+
ca_fetch_index(ca->mask, idx, &mval);
|
|
393
|
+
if ( mval ) return CA_UNDEF;
|
|
394
|
+
}
|
|
395
|
+
else if ( ! ca_is_entity(ca) ) {
|
|
396
|
+
ca_update_mask(ca);
|
|
397
|
+
if ( ca->mask ) {
|
|
398
|
+
boolean8_t mval;
|
|
399
|
+
ca_fetch_index(ca->mask, idx, &mval);
|
|
400
|
+
if ( mval ) return CA_UNDEF;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
CA_FACE_STORAGE_TO_SCALAR_IF_FACE(out, self, ca);
|
|
405
|
+
return out;
|
|
263
406
|
}
|
|
264
407
|
else {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
408
|
+
ca_size_t addr = elem_parse_idx_scalar(ca, ridx);
|
|
409
|
+
/* Super-hot flat-addr path: entity + numeric + no mask. */
|
|
410
|
+
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
411
|
+
char *p = ca->ptr + ca->bytes * addr;
|
|
412
|
+
switch ( ca->data_type ) {
|
|
413
|
+
case CA_FLOAT64: return rb_float_new(*(double *)p);
|
|
414
|
+
case CA_INT64: return LL2NUM(*(int64_t *)p);
|
|
415
|
+
case CA_INT32: return INT2NUM(*(int32_t *)p);
|
|
416
|
+
case CA_FLOAT32: return rb_float_new((double)*(float *)p);
|
|
417
|
+
case CA_INT16: return INT2FIX(*(int16_t *)p);
|
|
418
|
+
case CA_INT8: return INT2FIX(*(int8_t *)p);
|
|
419
|
+
case CA_UINT8: return INT2FIX(*(uint8_t *)p);
|
|
420
|
+
case CA_UINT16: return INT2FIX(*(uint16_t *)p);
|
|
421
|
+
case CA_UINT32: return UINT2NUM(*(uint32_t *)p);
|
|
422
|
+
case CA_UINT64: return ULL2NUM(*(uint64_t *)p);
|
|
423
|
+
case CA_BOOLEAN: return (*(uint8_t *)p) ? Qtrue : Qfalse;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
268
426
|
return rb_ca_fetch_addr(self, addr);
|
|
269
427
|
}
|
|
270
428
|
}
|
|
271
429
|
|
|
272
|
-
/*
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
*/
|
|
430
|
+
/* `elem_incr(idx)` — increments the integer cell at `idx` by 1 in
|
|
431
|
+
* place, returning the new value. Masked cells are skipped (returns
|
|
432
|
+
* `nil`). Raises for non-integer data_type. */
|
|
276
433
|
|
|
277
434
|
VALUE
|
|
278
435
|
rb_ca_elem_incr (VALUE self, VALUE ridx1)
|
|
@@ -281,12 +438,9 @@ rb_ca_elem_incr (VALUE self, VALUE ridx1)
|
|
|
281
438
|
CArray *ca;
|
|
282
439
|
ca_size_t idx1[CA_RANK_MAX];
|
|
283
440
|
ca_size_t addr1 = 0;
|
|
284
|
-
int8_t i;
|
|
285
|
-
ca_size_t k;
|
|
286
441
|
int has_index1 = 0;
|
|
287
442
|
int has_mask;
|
|
288
|
-
char
|
|
289
|
-
char *val = _val;
|
|
443
|
+
char val[8];
|
|
290
444
|
boolean8_t m = 0;
|
|
291
445
|
|
|
292
446
|
rb_ca_modify(self);
|
|
@@ -298,39 +452,49 @@ rb_ca_elem_incr (VALUE self, VALUE ridx1)
|
|
|
298
452
|
"incremented array should be an integer array");
|
|
299
453
|
}
|
|
300
454
|
|
|
301
|
-
|
|
302
|
-
has_mask = ( ca->mask ) ? 1 : 0;
|
|
455
|
+
has_mask = elem_probe_mask(ca);
|
|
303
456
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
457
|
+
/* Super-hot path: entity + no mask + integer dtype.
|
|
458
|
+
Reads p directly, modifies in place — no separate fetch/store dispatch. */
|
|
459
|
+
if ( ca_is_entity(ca) && ! has_mask ) {
|
|
460
|
+
ca_size_t addr;
|
|
461
|
+
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
462
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
463
|
+
addr = elem_entity_addr(ca, idx1);
|
|
309
464
|
}
|
|
310
|
-
|
|
311
|
-
|
|
465
|
+
else {
|
|
466
|
+
addr = elem_parse_idx_scalar(ca, ridx1);
|
|
312
467
|
}
|
|
313
|
-
|
|
314
|
-
|
|
468
|
+
void *p = ca->ptr + ca->bytes * addr;
|
|
469
|
+
switch ( ca->data_type ) {
|
|
470
|
+
case CA_INT8: return INT2FIX(++*((int8_t *)p));
|
|
471
|
+
case CA_UINT8: return INT2FIX(++*((uint8_t *)p));
|
|
472
|
+
case CA_INT16: return INT2FIX(++*((int16_t *)p));
|
|
473
|
+
case CA_UINT16: return INT2FIX(++*((uint16_t*)p));
|
|
474
|
+
case CA_INT32: return INT2NUM(++*((int32_t *)p));
|
|
475
|
+
case CA_UINT32: return UINT2NUM(++*((uint32_t*)p));
|
|
476
|
+
case CA_INT64: return LL2NUM(++*((int64_t *)p));
|
|
477
|
+
case CA_UINT64: return ULL2NUM(++*((uint64_t*)p));
|
|
315
478
|
}
|
|
316
|
-
|
|
317
|
-
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/* General path: view array or masked. */
|
|
482
|
+
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
483
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
484
|
+
if ( has_mask ) {
|
|
485
|
+
ca_fetch_index(ca->mask, idx1, &m);
|
|
486
|
+
if ( m ) return Qnil;
|
|
318
487
|
}
|
|
488
|
+
ca_fetch_index(ca, idx1, val);
|
|
319
489
|
has_index1 = 1;
|
|
320
490
|
}
|
|
321
491
|
else {
|
|
322
|
-
|
|
323
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
324
|
-
addr1 = k;
|
|
492
|
+
addr1 = elem_parse_idx_scalar(ca, ridx1);
|
|
325
493
|
if ( has_mask ) {
|
|
326
494
|
ca_fetch_addr(ca->mask, addr1, &m);
|
|
495
|
+
if ( m ) return Qnil;
|
|
327
496
|
}
|
|
328
|
-
|
|
329
|
-
return Qnil;
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
ca_fetch_addr(ca, addr1, val);
|
|
333
|
-
}
|
|
497
|
+
ca_fetch_addr(ca, addr1, val);
|
|
334
498
|
}
|
|
335
499
|
|
|
336
500
|
switch ( ca->data_type ) {
|
|
@@ -354,10 +518,9 @@ rb_ca_elem_incr (VALUE self, VALUE ridx1)
|
|
|
354
518
|
return out;
|
|
355
519
|
}
|
|
356
520
|
|
|
357
|
-
/*
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
*/
|
|
521
|
+
/* `elem_decr(idx)` — decrements the integer cell at `idx` by 1 in
|
|
522
|
+
* place, returning the new value. Masked cells are skipped (returns
|
|
523
|
+
* `nil`). Raises for non-integer data_type. */
|
|
361
524
|
|
|
362
525
|
VALUE
|
|
363
526
|
rb_ca_elem_decr (VALUE self, VALUE ridx1)
|
|
@@ -366,12 +529,9 @@ rb_ca_elem_decr (VALUE self, VALUE ridx1)
|
|
|
366
529
|
CArray *ca;
|
|
367
530
|
ca_size_t idx1[CA_RANK_MAX];
|
|
368
531
|
ca_size_t addr1 = 0;
|
|
369
|
-
int8_t i;
|
|
370
|
-
ca_size_t k;
|
|
371
532
|
int has_index1 = 0;
|
|
372
533
|
int has_mask;
|
|
373
|
-
char
|
|
374
|
-
char *val = _val;
|
|
534
|
+
char val[8];
|
|
375
535
|
boolean8_t m = 0;
|
|
376
536
|
|
|
377
537
|
rb_ca_modify(self);
|
|
@@ -383,39 +543,47 @@ rb_ca_elem_decr (VALUE self, VALUE ridx1)
|
|
|
383
543
|
"decremented array should be an integer array");
|
|
384
544
|
}
|
|
385
545
|
|
|
386
|
-
|
|
387
|
-
has_mask = ( ca->mask ) ? 1 : 0;
|
|
546
|
+
has_mask = elem_probe_mask(ca);
|
|
388
547
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
548
|
+
/* Super-hot path: mirror of elem_incr. */
|
|
549
|
+
if ( ca_is_entity(ca) && ! has_mask ) {
|
|
550
|
+
ca_size_t addr;
|
|
551
|
+
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
552
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
553
|
+
addr = elem_entity_addr(ca, idx1);
|
|
394
554
|
}
|
|
395
|
-
|
|
396
|
-
|
|
555
|
+
else {
|
|
556
|
+
addr = elem_parse_idx_scalar(ca, ridx1);
|
|
397
557
|
}
|
|
398
|
-
|
|
399
|
-
|
|
558
|
+
void *p = ca->ptr + ca->bytes * addr;
|
|
559
|
+
switch ( ca->data_type ) {
|
|
560
|
+
case CA_INT8: return INT2FIX(--*((int8_t *)p));
|
|
561
|
+
case CA_UINT8: return INT2FIX(--*((uint8_t *)p));
|
|
562
|
+
case CA_INT16: return INT2FIX(--*((int16_t *)p));
|
|
563
|
+
case CA_UINT16: return INT2FIX(--*((uint16_t*)p));
|
|
564
|
+
case CA_INT32: return INT2NUM(--*((int32_t *)p));
|
|
565
|
+
case CA_UINT32: return UINT2NUM(--*((uint32_t*)p));
|
|
566
|
+
case CA_INT64: return LL2NUM(--*((int64_t *)p));
|
|
567
|
+
case CA_UINT64: return ULL2NUM(--*((uint64_t*)p));
|
|
400
568
|
}
|
|
401
|
-
|
|
402
|
-
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
572
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
573
|
+
if ( has_mask ) {
|
|
574
|
+
ca_fetch_index(ca->mask, idx1, &m);
|
|
575
|
+
if ( m ) return Qnil;
|
|
403
576
|
}
|
|
577
|
+
ca_fetch_index(ca, idx1, val);
|
|
404
578
|
has_index1 = 1;
|
|
405
579
|
}
|
|
406
580
|
else {
|
|
407
|
-
|
|
408
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
409
|
-
addr1 = k;
|
|
581
|
+
addr1 = elem_parse_idx_scalar(ca, ridx1);
|
|
410
582
|
if ( has_mask ) {
|
|
411
583
|
ca_fetch_addr(ca->mask, addr1, &m);
|
|
584
|
+
if ( m ) return Qnil;
|
|
412
585
|
}
|
|
413
|
-
|
|
414
|
-
return Qnil;
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
ca_fetch_addr(ca, addr1, val);
|
|
418
|
-
}
|
|
586
|
+
ca_fetch_addr(ca, addr1, val);
|
|
419
587
|
}
|
|
420
588
|
|
|
421
589
|
switch ( ca->data_type ) {
|
|
@@ -425,8 +593,8 @@ rb_ca_elem_decr (VALUE self, VALUE ridx1)
|
|
|
425
593
|
case CA_UINT16: out = UINT2NUM(--*((uint16_t*) val)); break;
|
|
426
594
|
case CA_INT32: out = INT2NUM(--*((int32_t*) val)); break;
|
|
427
595
|
case CA_UINT32: out = UINT2NUM(--*((uint32_t*) val)); break;
|
|
428
|
-
case CA_INT64: out =
|
|
429
|
-
case CA_UINT64: out =
|
|
596
|
+
case CA_INT64: out = LL2NUM(--*((int64_t*) val)); break;
|
|
597
|
+
case CA_UINT64: out = ULL2NUM(--*((uint64_t*) val)); break;
|
|
430
598
|
}
|
|
431
599
|
|
|
432
600
|
if ( has_index1 ) {
|
|
@@ -439,39 +607,46 @@ rb_ca_elem_decr (VALUE self, VALUE ridx1)
|
|
|
439
607
|
return out;
|
|
440
608
|
}
|
|
441
609
|
|
|
442
|
-
/*
|
|
443
|
-
|
|
444
|
-
(Masking, Element) Returns true if the element at given idx is masked.
|
|
445
|
-
*/
|
|
610
|
+
/* `elem_masked?(idx)` — returns `true` if the cell at `idx` is
|
|
611
|
+
* masked. */
|
|
446
612
|
|
|
447
613
|
VALUE
|
|
448
614
|
rb_ca_elem_test_masked (VALUE self, VALUE ridx1)
|
|
449
615
|
{
|
|
450
616
|
CArray *ca;
|
|
451
617
|
ca_size_t idx1[CA_RANK_MAX];
|
|
452
|
-
ca_size_t addr1 = 0;
|
|
453
|
-
int8_t i;
|
|
454
|
-
ca_size_t k;
|
|
455
618
|
boolean8_t m = 0;
|
|
456
619
|
|
|
457
620
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
458
621
|
|
|
622
|
+
/* Super-hot path: entity. Covers both no-mask (Qfalse fast) and masked
|
|
623
|
+
(direct ca->mask->ptr read) cases without dispatch. Mask itself is
|
|
624
|
+
always a boolean8_t entity (= 1 byte / element, same shape as ca),
|
|
625
|
+
so flat addr from elem_entity_addr applies directly. */
|
|
626
|
+
if ( ca_is_entity(ca) ) {
|
|
627
|
+
ca_size_t addr;
|
|
628
|
+
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
629
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
630
|
+
addr = elem_entity_addr(ca, idx1);
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
addr = elem_parse_idx_scalar(ca, ridx1);
|
|
634
|
+
}
|
|
635
|
+
if ( ! ca->mask ) return Qfalse;
|
|
636
|
+
return ((boolean8_t *)ca->mask->ptr)[addr] ? Qtrue : Qfalse;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/* General path: view array. Walk parent chain to materialise mask. */
|
|
459
640
|
ca_update_mask(ca);
|
|
460
641
|
|
|
461
642
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
462
|
-
|
|
463
|
-
k = NUM2SIZE(rb_ary_entry(ridx1, i));
|
|
464
|
-
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
465
|
-
idx1[i] = k;
|
|
466
|
-
}
|
|
643
|
+
elem_parse_idx_array(ca, ridx1, idx1);
|
|
467
644
|
if ( ca->mask ) {
|
|
468
645
|
ca_fetch_index(ca->mask, idx1, &m);
|
|
469
646
|
}
|
|
470
647
|
}
|
|
471
648
|
else {
|
|
472
|
-
|
|
473
|
-
CA_CHECK_INDEX(k, ca->elements);
|
|
474
|
-
addr1 = k;
|
|
649
|
+
ca_size_t addr1 = elem_parse_idx_scalar(ca, ridx1);
|
|
475
650
|
if ( ca->mask ) {
|
|
476
651
|
ca_fetch_addr(ca->mask, addr1, &m);
|
|
477
652
|
}
|
|
@@ -480,71 +655,265 @@ rb_ca_elem_test_masked (VALUE self, VALUE ridx1)
|
|
|
480
655
|
return m ? Qtrue : Qfalse;
|
|
481
656
|
}
|
|
482
657
|
|
|
483
|
-
/*
|
|
658
|
+
/* `elem_mask(idx)` — sets the mask bit at cell `idx`. Unlike
|
|
659
|
+
* `a[idx] = UNDEF`, this preserves the underlying stored value, so a
|
|
660
|
+
* later `elem_unmask(idx)` restores it. */
|
|
484
661
|
|
|
485
|
-
|
|
662
|
+
VALUE
|
|
663
|
+
rb_ca_elem_mask (VALUE self, VALUE ridx)
|
|
664
|
+
{
|
|
665
|
+
CArray *ca;
|
|
666
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
667
|
+
|
|
668
|
+
rb_ca_modify(self);
|
|
669
|
+
|
|
670
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
671
|
+
|
|
672
|
+
/* Super-hot path: entity. Materialise mask on first call (one-time per
|
|
673
|
+
array), then direct ptr write. */
|
|
674
|
+
if ( ca_is_entity(ca) ) {
|
|
675
|
+
ca_size_t addr;
|
|
676
|
+
if ( TYPE(ridx) == T_ARRAY ) {
|
|
677
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
678
|
+
addr = elem_entity_addr(ca, idx);
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
addr = elem_parse_idx_scalar(ca, ridx);
|
|
682
|
+
}
|
|
683
|
+
if ( ! ca->mask ) {
|
|
684
|
+
ca_create_mask(ca); /* raises for value-array / mask-array */
|
|
685
|
+
}
|
|
686
|
+
((boolean8_t *)ca->mask->ptr)[addr] = 1;
|
|
687
|
+
return self;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/* General path: view array. Walk parent chain + dispatch. */
|
|
691
|
+
{
|
|
692
|
+
boolean8_t one = 1;
|
|
693
|
+
ca_update_mask(ca);
|
|
694
|
+
if ( ! ca->mask ) {
|
|
695
|
+
ca_create_mask(ca);
|
|
696
|
+
}
|
|
697
|
+
if ( TYPE(ridx) == T_ARRAY ) {
|
|
698
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
699
|
+
ca_store_index(ca->mask, idx, &one);
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
ca_size_t addr = elem_parse_idx_scalar(ca, ridx);
|
|
703
|
+
ca_store_addr(ca->mask, addr, &one);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return self;
|
|
708
|
+
}
|
|
486
709
|
|
|
487
|
-
(
|
|
488
|
-
*/
|
|
710
|
+
/* `elem_unmask(idx)` — clears the mask bit at cell `idx`, leaving
|
|
711
|
+
* the stored data unchanged. No-op if `self` has no mask. */
|
|
489
712
|
|
|
490
|
-
|
|
491
|
-
|
|
713
|
+
VALUE
|
|
714
|
+
rb_ca_elem_unmask (VALUE self, VALUE ridx)
|
|
492
715
|
{
|
|
493
|
-
CArray
|
|
494
|
-
|
|
495
|
-
ca_size_t k, elements;
|
|
496
|
-
ca_size_t i;
|
|
497
|
-
boolean8_t *m;
|
|
716
|
+
CArray *ca;
|
|
717
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
498
718
|
|
|
499
719
|
rb_ca_modify(self);
|
|
500
720
|
|
|
501
|
-
self = rb_ca_wrap_writable(self, INT2NUM(CA_INT64));
|
|
502
|
-
raddr = rb_ca_wrap_readonly(raddr, INT2NUM(CA_INT64));
|
|
503
|
-
|
|
504
721
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
505
|
-
TypedData_Get_Struct(raddr, CArray, &carray_data_type, ci);
|
|
506
722
|
|
|
507
|
-
|
|
723
|
+
/* Super-hot path: entity. If no mask exists, nothing to clear. */
|
|
724
|
+
if ( ca_is_entity(ca) ) {
|
|
725
|
+
if ( ! ca->mask ) return self;
|
|
726
|
+
ca_size_t addr;
|
|
727
|
+
if ( TYPE(ridx) == T_ARRAY ) {
|
|
728
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
729
|
+
addr = elem_entity_addr(ca, idx);
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
addr = elem_parse_idx_scalar(ca, ridx);
|
|
733
|
+
}
|
|
734
|
+
((boolean8_t *)ca->mask->ptr)[addr] = 0;
|
|
735
|
+
return self;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/* General path: view array. */
|
|
739
|
+
{
|
|
740
|
+
boolean8_t zero = 0;
|
|
741
|
+
ca_update_mask(ca);
|
|
742
|
+
if ( ! ca->mask ) return self;
|
|
743
|
+
if ( TYPE(ridx) == T_ARRAY ) {
|
|
744
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
745
|
+
ca_store_index(ca->mask, idx, &zero);
|
|
746
|
+
}
|
|
747
|
+
else {
|
|
748
|
+
ca_size_t addr = elem_parse_idx_scalar(ca, ridx);
|
|
749
|
+
ca_store_addr(ca->mask, addr, &zero);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
return self;
|
|
754
|
+
}
|
|
508
755
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
756
|
+
/* `elem_min(idx, v)` — updates the cell at `idx` to `min(self[idx],
|
|
757
|
+
* v)` in place. Masked cells are skipped. NaN follows the `fmin`
|
|
758
|
+
* rule (NaN is treated as missing: `min(NaN, v)` returns `v`,
|
|
759
|
+
* `min(x, NaN)` returns `x`). Raises for non-numeric data_type. */
|
|
760
|
+
|
|
761
|
+
#define ELEM_MINMAX_BODY(OP) do { \
|
|
762
|
+
if ( ca_is_entity(ca) ) { \
|
|
763
|
+
ca_size_t addr; \
|
|
764
|
+
if ( TYPE(ridx) == T_ARRAY ) { \
|
|
765
|
+
elem_parse_idx_array(ca, ridx, idx); \
|
|
766
|
+
addr = elem_entity_addr(ca, idx); \
|
|
767
|
+
} \
|
|
768
|
+
else { \
|
|
769
|
+
addr = elem_parse_idx_scalar(ca, ridx); \
|
|
770
|
+
} \
|
|
771
|
+
if ( ca->mask && ((boolean8_t *)ca->mask->ptr)[addr] ) return self; \
|
|
772
|
+
void *p = ca->ptr + ca->bytes * addr; \
|
|
773
|
+
if ( RB_FLOAT_TYPE_P(rval) ) { \
|
|
774
|
+
double v = RFLOAT_VALUE(rval); \
|
|
775
|
+
switch ( ca->data_type ) { \
|
|
776
|
+
case CA_FLOAT64: { double *q=(double *)p; if (v OP *q || *q != *q) *q = v; return self; } \
|
|
777
|
+
case CA_FLOAT32: { float *q=(float *)p; float vf=(float)v; if (vf OP *q || *q != *q) *q = vf; return self; } \
|
|
778
|
+
case CA_INT64: { int64_t *q=(int64_t *)p; if ((int64_t)v OP *q) *q = (int64_t)v; return self; } \
|
|
779
|
+
case CA_INT32: { int32_t *q=(int32_t *)p; if ((int32_t)v OP *q) *q = (int32_t)v; return self; } \
|
|
780
|
+
case CA_INT16: { int16_t *q=(int16_t *)p; if ((int16_t)v OP *q) *q = (int16_t)v; return self; } \
|
|
781
|
+
case CA_INT8: { int8_t *q=(int8_t *)p; if ((int8_t )v OP *q) *q = (int8_t )v; return self; } \
|
|
782
|
+
case CA_UINT64: { uint64_t *q=(uint64_t*)p; if ((uint64_t)v OP *q) *q = (uint64_t)v; return self; } \
|
|
783
|
+
case CA_UINT32: { uint32_t *q=(uint32_t*)p; if ((uint32_t)v OP *q) *q = (uint32_t)v; return self; } \
|
|
784
|
+
case CA_UINT16: { uint16_t *q=(uint16_t*)p; if ((uint16_t)v OP *q) *q = (uint16_t)v; return self; } \
|
|
785
|
+
case CA_UINT8: { uint8_t *q=(uint8_t *)p; if ((uint8_t )v OP *q) *q = (uint8_t )v; return self; } \
|
|
786
|
+
} \
|
|
787
|
+
} \
|
|
788
|
+
else if ( FIXNUM_P(rval) ) { \
|
|
789
|
+
long v = FIX2LONG(rval); \
|
|
790
|
+
switch ( ca->data_type ) { \
|
|
791
|
+
case CA_FLOAT64: { double *q=(double *)p; double vd=(double)v; if (vd OP *q || *q != *q) *q = vd; return self; } \
|
|
792
|
+
case CA_FLOAT32: { float *q=(float *)p; float vf=(float )v; if (vf OP *q || *q != *q) *q = vf; return self; } \
|
|
793
|
+
case CA_INT64: { int64_t *q=(int64_t *)p; if ((int64_t)v OP *q) *q = (int64_t)v; return self; } \
|
|
794
|
+
case CA_INT32: { int32_t *q=(int32_t *)p; if ((int32_t)v OP *q) *q = (int32_t)v; return self; } \
|
|
795
|
+
case CA_INT16: { int16_t *q=(int16_t *)p; if ((int16_t)v OP *q) *q = (int16_t)v; return self; } \
|
|
796
|
+
case CA_INT8: { int8_t *q=(int8_t *)p; if ((int8_t )v OP *q) *q = (int8_t )v; return self; } \
|
|
797
|
+
case CA_UINT64: { uint64_t *q=(uint64_t*)p; if ((uint64_t)v OP *q) *q = (uint64_t)v; return self; } \
|
|
798
|
+
case CA_UINT32: { uint32_t *q=(uint32_t*)p; if ((uint32_t)v OP *q) *q = (uint32_t)v; return self; } \
|
|
799
|
+
case CA_UINT16: { uint16_t *q=(uint16_t*)p; if ((uint16_t)v OP *q) *q = (uint16_t)v; return self; } \
|
|
800
|
+
case CA_UINT8: { uint8_t *q=(uint8_t *)p; if ((uint8_t )v OP *q) *q = (uint8_t )v; return self; } \
|
|
801
|
+
} \
|
|
802
|
+
} \
|
|
803
|
+
} \
|
|
804
|
+
} while (0)
|
|
512
805
|
|
|
513
|
-
|
|
806
|
+
VALUE
|
|
807
|
+
rb_ca_elem_min (VALUE self, VALUE ridx, VALUE rval)
|
|
808
|
+
{
|
|
809
|
+
CArray *ca;
|
|
810
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
514
811
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
CA_CHECK_INDEX(k, elements);
|
|
523
|
-
*(q + k) += 1;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
812
|
+
rb_ca_modify(self);
|
|
813
|
+
|
|
814
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
815
|
+
|
|
816
|
+
if ( ! ca_is_numeric_type(ca) ) {
|
|
817
|
+
rb_raise(rb_eCADataTypeError,
|
|
818
|
+
"elem_min requires a numeric array");
|
|
526
819
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
820
|
+
|
|
821
|
+
/* Super-hot path: entity + numeric dtype + Fixnum/Float rval. */
|
|
822
|
+
ELEM_MINMAX_BODY(<);
|
|
823
|
+
|
|
824
|
+
/* General path: view / Bignum-Rational-Complex rval / fall-through.
|
|
825
|
+
fetch, compare via Ruby, store back. */
|
|
826
|
+
{
|
|
827
|
+
VALUE cur;
|
|
828
|
+
boolean8_t m = 0;
|
|
829
|
+
ca_size_t addr;
|
|
830
|
+
int from_array = (TYPE(ridx) == T_ARRAY);
|
|
831
|
+
|
|
832
|
+
if ( from_array ) {
|
|
833
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
addr = elem_parse_idx_scalar(ca, ridx);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/* Probe mask (view may need ca_update_mask). */
|
|
840
|
+
if ( ! ca->mask && ! ca_is_entity(ca) ) ca_update_mask(ca);
|
|
841
|
+
if ( ca->mask ) {
|
|
842
|
+
if ( from_array ) ca_fetch_index(ca->mask, idx, &m);
|
|
843
|
+
else ca_fetch_addr(ca->mask, addr, &m);
|
|
844
|
+
if ( m ) return self;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
cur = from_array ? rb_ca_fetch_index(self, idx) : rb_ca_fetch_addr(self, addr);
|
|
848
|
+
if ( cur == CA_UNDEF ) return self;
|
|
849
|
+
if ( RTEST(rb_funcall(rval, rb_intern("<"), 1, cur)) ) {
|
|
850
|
+
if ( from_array ) rb_ca_store_index(self, idx, rval);
|
|
851
|
+
else rb_ca_store_addr(self, addr, rval);
|
|
535
852
|
}
|
|
536
853
|
}
|
|
537
854
|
|
|
538
|
-
|
|
539
|
-
|
|
855
|
+
return self;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/* `elem_max(idx, v)` — updates the cell at `idx` to `max(self[idx],
|
|
859
|
+
* v)` in place. Masked cells are skipped. NaN follows the `fmax`
|
|
860
|
+
* rule. Raises for non-numeric data_type. */
|
|
861
|
+
|
|
862
|
+
VALUE
|
|
863
|
+
rb_ca_elem_max (VALUE self, VALUE ridx, VALUE rval)
|
|
864
|
+
{
|
|
865
|
+
CArray *ca;
|
|
866
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
867
|
+
|
|
868
|
+
rb_ca_modify(self);
|
|
869
|
+
|
|
870
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
871
|
+
|
|
872
|
+
if ( ! ca_is_numeric_type(ca) ) {
|
|
873
|
+
rb_raise(rb_eCADataTypeError,
|
|
874
|
+
"elem_max requires a numeric array");
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
ELEM_MINMAX_BODY(>);
|
|
878
|
+
|
|
879
|
+
/* General path: view / Bignum-Rational-Complex rval. */
|
|
880
|
+
{
|
|
881
|
+
VALUE cur;
|
|
882
|
+
boolean8_t m = 0;
|
|
883
|
+
ca_size_t addr;
|
|
884
|
+
int from_array = (TYPE(ridx) == T_ARRAY);
|
|
885
|
+
|
|
886
|
+
if ( from_array ) {
|
|
887
|
+
elem_parse_idx_array(ca, ridx, idx);
|
|
888
|
+
}
|
|
889
|
+
else {
|
|
890
|
+
addr = elem_parse_idx_scalar(ca, ridx);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
if ( ! ca->mask && ! ca_is_entity(ca) ) ca_update_mask(ca);
|
|
894
|
+
if ( ca->mask ) {
|
|
895
|
+
if ( from_array ) ca_fetch_index(ca->mask, idx, &m);
|
|
896
|
+
else ca_fetch_addr(ca->mask, addr, &m);
|
|
897
|
+
if ( m ) return self;
|
|
898
|
+
}
|
|
540
899
|
|
|
541
|
-
|
|
900
|
+
cur = from_array ? rb_ca_fetch_index(self, idx) : rb_ca_fetch_addr(self, addr);
|
|
901
|
+
if ( cur == CA_UNDEF ) return self;
|
|
902
|
+
if ( RTEST(rb_funcall(rval, rb_intern(">"), 1, cur)) ) {
|
|
903
|
+
if ( from_array ) rb_ca_store_index(self, idx, rval);
|
|
904
|
+
else rb_ca_store_addr(self, addr, rval);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
return self;
|
|
542
909
|
}
|
|
543
910
|
|
|
911
|
+
#undef ELEM_MINMAX_BODY
|
|
912
|
+
|
|
544
913
|
/* ----------------------------------------------------------------- */
|
|
545
914
|
|
|
546
915
|
void
|
|
547
|
-
Init_carray_element ()
|
|
916
|
+
Init_carray_element (void)
|
|
548
917
|
{
|
|
549
918
|
rb_define_method(rb_cCArray, "elem_swap", rb_ca_elem_swap, 2);
|
|
550
919
|
rb_define_method(rb_cCArray, "elem_copy", rb_ca_elem_copy, 2);
|
|
@@ -555,7 +924,10 @@ Init_carray_element ()
|
|
|
555
924
|
rb_define_method(rb_cCArray, "elem_decr", rb_ca_elem_decr, 1);
|
|
556
925
|
|
|
557
926
|
rb_define_method(rb_cCArray, "elem_masked?", rb_ca_elem_test_masked, 1);
|
|
927
|
+
rb_define_method(rb_cCArray, "elem_mask", rb_ca_elem_mask, 1);
|
|
928
|
+
rb_define_method(rb_cCArray, "elem_unmask", rb_ca_elem_unmask, 1);
|
|
558
929
|
|
|
559
|
-
rb_define_method(rb_cCArray, "
|
|
930
|
+
rb_define_method(rb_cCArray, "elem_min", rb_ca_elem_min, 2);
|
|
931
|
+
rb_define_method(rb_cCArray, "elem_max", rb_ca_elem_max, 2);
|
|
560
932
|
}
|
|
561
933
|
|