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/ca_obj_bincmp.c
ADDED
|
@@ -0,0 +1,809 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
Lazy binadic element-wise comparison view: holds (left, right,
|
|
4
|
+
op_id, eps) and materialises a boolean result on attach. Carries
|
|
5
|
+
CA_FLAG_READ_ONLY; there is no bang path and `[]=` raises.
|
|
6
|
+
|
|
7
|
+
Sibling of ca_obj_binop.c (element-wise arithmetic) and
|
|
8
|
+
ca_obj_moncmp.c (unary comparisons); dispatched by
|
|
9
|
+
ca_bincmp_kernel_lookup from ca_bincmp_dispatch.h.
|
|
10
|
+
|
|
11
|
+
Dispatch by data_type:
|
|
12
|
+
numeric (i8..f64, +complex) -> ca_bincmp_<op>_<dtype> kernel
|
|
13
|
+
boolean / fixlen / object -> not implemented (raise)
|
|
14
|
+
|
|
15
|
+
CAREFUL: the binop in-place trick (= pull left into the output
|
|
16
|
+
buffer) is structurally unavailable here — the output is
|
|
17
|
+
boolean8_t (1 byte per cell) while operands live at the common
|
|
18
|
+
data_type (typically 8 bytes at f64), so a pull-into-output would
|
|
19
|
+
overflow. xfer_stride therefore holds two operand-typed scratch
|
|
20
|
+
slabs and writes the boolean result directly to `data`.
|
|
21
|
+
|
|
22
|
+
Comparison ops never trap, so the kernel is called with m=NULL
|
|
23
|
+
(SIMD fast path). The output mask is computed by create_mask as
|
|
24
|
+
`left.mask | right.mask` and propagated through the standard
|
|
25
|
+
CArray mask machinery.
|
|
26
|
+
|
|
27
|
+
---------------------------------------------------------------------------- */
|
|
28
|
+
|
|
29
|
+
#include "carray.h"
|
|
30
|
+
#include "carray_internal.h" /* ca_lazy_arena_* */
|
|
31
|
+
#include "ca_bincmp_dispatch.h"
|
|
32
|
+
#include "ca_monop_dispatch.h" /* CA_MONOP_CAST_BASE */
|
|
33
|
+
|
|
34
|
+
extern VALUE ca_broadcast_view (VALUE src, int8_t ndim,
|
|
35
|
+
ca_size_t *target_dim);
|
|
36
|
+
extern VALUE ca_lazy_wrap_scalar (VALUE other, CArray *self_ca);
|
|
37
|
+
extern void *ca_lazy_arena_acquire (ca_size_t bytes);
|
|
38
|
+
extern void ca_lazy_arena_release (void *ptr);
|
|
39
|
+
|
|
40
|
+
int8_t CA_OBJ_BINCMP;
|
|
41
|
+
VALUE rb_cCABinCmp;
|
|
42
|
+
|
|
43
|
+
extern int8_t CA_OBJ_LAZY_MARKER;
|
|
44
|
+
|
|
45
|
+
/* ------------------------------------------------------------------- */
|
|
46
|
+
/* CABinCmp struct */
|
|
47
|
+
/* ------------------------------------------------------------------- */
|
|
48
|
+
|
|
49
|
+
typedef struct CABinCmp {
|
|
50
|
+
int16_t obj_type;
|
|
51
|
+
int8_t data_type; /* always CA_BOOLEAN */
|
|
52
|
+
int8_t ndim;
|
|
53
|
+
int32_t flags;
|
|
54
|
+
ca_size_t bytes; /* always 1 */
|
|
55
|
+
ca_size_t elements;
|
|
56
|
+
ca_size_t *dim;
|
|
57
|
+
char *ptr;
|
|
58
|
+
CArray *mask;
|
|
59
|
+
char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path). */
|
|
60
|
+
CArray *parent; /* = left */
|
|
61
|
+
uint32_t attach;
|
|
62
|
+
uint8_t nosync;
|
|
63
|
+
/* CABinCmp-specific tail */
|
|
64
|
+
CArray *right;
|
|
65
|
+
uint16_t op_id;
|
|
66
|
+
uint8_t right_is_scalar;
|
|
67
|
+
int8_t common_dt; /* operand-data_type after promote (= cast
|
|
68
|
+
target of both left & right, also the
|
|
69
|
+
kernel lookup key) */
|
|
70
|
+
double eps; /* Runtime tolerance slot for IS_CLOSE /
|
|
71
|
+
IS_EQUIV; ignored for other ops. The
|
|
72
|
+
`eps` name is retained to keep the
|
|
73
|
+
`__eps__` Ruby accessor stable across
|
|
74
|
+
the dual purpose. */
|
|
75
|
+
} CABinCmp;
|
|
76
|
+
|
|
77
|
+
static size_t
|
|
78
|
+
ca_bincmp_dsize (const void *ap)
|
|
79
|
+
{
|
|
80
|
+
const CABinCmp *ca = (const CABinCmp *) ap;
|
|
81
|
+
return sizeof(CABinCmp) + ca->ndim * sizeof(ca_size_t);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Pool framework hooks: single ndim-sized tail (dim) in the _pool
|
|
85
|
+
buffer. See ca_array_pool.c for the shared alloc/free discipline. */
|
|
86
|
+
static size_t
|
|
87
|
+
ca_bincmp_pool_bytes (int8_t ndim)
|
|
88
|
+
{
|
|
89
|
+
ca_size_t n = (ndim > 0) ? ndim : 1;
|
|
90
|
+
return (size_t) n * sizeof(ca_size_t);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static void
|
|
94
|
+
ca_bincmp_pool_init (void *ap, int8_t ndim)
|
|
95
|
+
{
|
|
96
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
97
|
+
ca->dim = (ca_size_t *) ca->_pool;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const rb_data_type_t cabincmp_data_type = {
|
|
101
|
+
.parent = &caview_data_type,
|
|
102
|
+
.wrap_struct_name = "CABinCmp",
|
|
103
|
+
.function = {
|
|
104
|
+
.dmark = ca_mark,
|
|
105
|
+
.dfree = ca_free,
|
|
106
|
+
.dsize = ca_bincmp_dsize,
|
|
107
|
+
.dcompact = NULL
|
|
108
|
+
},
|
|
109
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/* ------------------------------------------------------------------- */
|
|
113
|
+
/* setup / new / free */
|
|
114
|
+
/* ------------------------------------------------------------------- */
|
|
115
|
+
|
|
116
|
+
static int
|
|
117
|
+
ca_bincmp_setup (CABinCmp *ca, CArray *left, CArray *right, uint16_t op_id,
|
|
118
|
+
double eps)
|
|
119
|
+
{
|
|
120
|
+
ca->obj_type = CA_OBJ_BINCMP;
|
|
121
|
+
ca->data_type = CA_BOOLEAN; /* output is always boolean */
|
|
122
|
+
ca->flags = CA_FLAG_READ_ONLY;
|
|
123
|
+
ca->ndim = left->ndim;
|
|
124
|
+
ca->bytes = 1; /* boolean8_t */
|
|
125
|
+
ca->elements = left->elements;
|
|
126
|
+
ca->ptr = NULL;
|
|
127
|
+
ca->mask = NULL;
|
|
128
|
+
if ( ! ca->_pool ) {
|
|
129
|
+
ca->dim = ALLOC_N(ca_size_t, left->ndim);
|
|
130
|
+
}
|
|
131
|
+
ca->parent = left;
|
|
132
|
+
ca->attach = 0;
|
|
133
|
+
ca->nosync = 0;
|
|
134
|
+
ca->right = right;
|
|
135
|
+
ca->op_id = op_id;
|
|
136
|
+
ca->right_is_scalar = ( right->elements == 1 && left->elements > 1 ) ? 1 : 0;
|
|
137
|
+
/* Builder has already cast both operands to common data_type. */
|
|
138
|
+
ca->common_dt = left->data_type;
|
|
139
|
+
ca->eps = eps;
|
|
140
|
+
|
|
141
|
+
memcpy(ca->dim, left->dim, left->ndim * sizeof(ca_size_t));
|
|
142
|
+
|
|
143
|
+
if ( ca_has_mask(left) || ca_has_mask(right) ) {
|
|
144
|
+
ca_create_mask(ca);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if ( ca_is_scalar(left) && ca_is_scalar(right) ) {
|
|
148
|
+
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
CABinCmp *
|
|
155
|
+
ca_bincmp_new (CArray *left, CArray *right, uint16_t op_id, double eps)
|
|
156
|
+
{
|
|
157
|
+
CABinCmp *ca = (CABinCmp *) ca_array_alloc(CA_OBJ_BINCMP, left->ndim);
|
|
158
|
+
ca_bincmp_setup(ca, left, right, op_id, eps);
|
|
159
|
+
return ca;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static void
|
|
163
|
+
free_ca_bincmp (void *ap)
|
|
164
|
+
{
|
|
165
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
166
|
+
if ( ca != NULL ) {
|
|
167
|
+
ca_free(ca->mask);
|
|
168
|
+
if ( ca->_pool ) {
|
|
169
|
+
ca_array_free(ca); /* dim lives in _pool */
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
xfree(ca->dim);
|
|
173
|
+
xfree(ca);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* ------------------------------------------------------------------- */
|
|
179
|
+
/* operation function table */
|
|
180
|
+
/* ------------------------------------------------------------------- */
|
|
181
|
+
|
|
182
|
+
static void ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts,
|
|
183
|
+
ca_size_t *counts,
|
|
184
|
+
ca_size_t *strides,
|
|
185
|
+
void *data, int dir);
|
|
186
|
+
|
|
187
|
+
static void *
|
|
188
|
+
ca_bincmp_func_clone (void *ap)
|
|
189
|
+
{
|
|
190
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
191
|
+
return ca_bincmp_new(ca->parent, ca->right, ca->op_id, ca->eps);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static void
|
|
195
|
+
ca_bincmp_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
196
|
+
{
|
|
197
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
198
|
+
ca_size_t starts[CA_RANK_MAX];
|
|
199
|
+
ca_size_t counts[CA_RANK_MAX];
|
|
200
|
+
ca_size_t strides[CA_RANK_MAX];
|
|
201
|
+
int8_t k;
|
|
202
|
+
|
|
203
|
+
if ( dir != CA_XFER_GET ) {
|
|
204
|
+
rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_index PUT)");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) {
|
|
208
|
+
starts[k] = idx[k];
|
|
209
|
+
counts[k] = 1;
|
|
210
|
+
strides[k] = 1; /* boolean8_t */
|
|
211
|
+
}
|
|
212
|
+
ca_bincmp_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static void
|
|
216
|
+
ca_bincmp_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
217
|
+
void *data, int dir)
|
|
218
|
+
{
|
|
219
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
220
|
+
ca_size_t i;
|
|
221
|
+
char *out = (char *) data;
|
|
222
|
+
|
|
223
|
+
if ( dir != CA_XFER_GET ) {
|
|
224
|
+
rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_addrs PUT)");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
for ( i = 0; i < n; i++ ) {
|
|
228
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
229
|
+
ca_addr2index((CArray *)ca, addrs[i], idx);
|
|
230
|
+
ca_bincmp_func_xfer_index(ca, idx, out + i, CA_XFER_GET);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Test / observability counters — bumped from the xfer_stride hot
|
|
235
|
+
path so specs can assert scratch acquisition and leaf in-place
|
|
236
|
+
hit rates without materialising the view. */
|
|
237
|
+
ca_size_t ca_bincmp_scratch_acquire_count = 0;
|
|
238
|
+
ca_size_t ca_bincmp_materialise_call_count = 0;
|
|
239
|
+
ca_size_t ca_bincmp_leaf_inplace_count = 0;
|
|
240
|
+
|
|
241
|
+
/* Leaf-operand in-place read eligibility. When the operand has a
|
|
242
|
+
valid contiguous backing buffer at the common data_type, we can
|
|
243
|
+
use operand->ptr + byte_offset directly, skipping the arena
|
|
244
|
+
acquire and the ca_xfer_stride pull.
|
|
245
|
+
*
|
|
246
|
+
* Eligible cases:
|
|
247
|
+
* - entity (CA_OBJ_ARRAY / CA_OBJ_SCALAR / CA_OBJ_ARRAY_WRAP) at
|
|
248
|
+
* the common data_type
|
|
249
|
+
* - already-attached view at the common data_type with a
|
|
250
|
+
* contiguous ptr
|
|
251
|
+
*
|
|
252
|
+
* The request must be a row-major slab over the operand (what
|
|
253
|
+
* xfer_all sends, which is the dominant to_ca path). */
|
|
254
|
+
static int
|
|
255
|
+
ca_bincmp_try_leaf_inplace (CArray *op, int8_t common_dt,
|
|
256
|
+
ca_size_t *starts, ca_size_t *counts,
|
|
257
|
+
ca_size_t expected_inner_byte_stride,
|
|
258
|
+
char **out_ptr)
|
|
259
|
+
{
|
|
260
|
+
ca_size_t row_strides[CA_RANK_MAX];
|
|
261
|
+
ca_size_t s, byte_off;
|
|
262
|
+
int8_t k;
|
|
263
|
+
|
|
264
|
+
if ( op->data_type != common_dt ) return 0;
|
|
265
|
+
if ( op->ptr == NULL ) return 0;
|
|
266
|
+
if ( op->bytes != expected_inner_byte_stride ) return 0;
|
|
267
|
+
|
|
268
|
+
/* Compute row-major byte offset from starts[]. We rely on the
|
|
269
|
+
caller (ca_xfer_all) providing row-major counts == op->dim or a
|
|
270
|
+
contig sub-region. byte_off = sum(starts[k] * row_stride_k)
|
|
271
|
+
where row_stride_k = product of dim[k+1..ndim-1] * bytes. */
|
|
272
|
+
s = op->bytes;
|
|
273
|
+
for ( k = op->ndim - 1; k >= 0; k-- ) {
|
|
274
|
+
row_strides[k] = s;
|
|
275
|
+
s *= op->dim[k];
|
|
276
|
+
}
|
|
277
|
+
byte_off = 0;
|
|
278
|
+
for ( k = 0; k < op->ndim; k++ ) {
|
|
279
|
+
/* require sub-region fits within parent dim (= no OOB) */
|
|
280
|
+
if ( starts[k] < 0 || starts[k] + counts[k] > op->dim[k] ) return 0;
|
|
281
|
+
byte_off += starts[k] * row_strides[k];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
*out_ptr = op->ptr + byte_off;
|
|
285
|
+
return 1;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
static void
|
|
289
|
+
ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
290
|
+
ca_size_t *strides, void *data, int dir)
|
|
291
|
+
{
|
|
292
|
+
CABinCmp *bc = (CABinCmp *) ap;
|
|
293
|
+
ca_size_t slab_n;
|
|
294
|
+
int8_t k;
|
|
295
|
+
void *left_scratch, *right_scratch;
|
|
296
|
+
ca_size_t operand_bytes;
|
|
297
|
+
ca_size_t right_step;
|
|
298
|
+
int left_is_inplace = 0; /* skip release for leaf-opt path */
|
|
299
|
+
int right_is_inplace = 0;
|
|
300
|
+
|
|
301
|
+
if ( dir != CA_XFER_GET ) {
|
|
302
|
+
rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_stride PUT)");
|
|
303
|
+
}
|
|
304
|
+
ca_bincmp_materialise_call_count++;
|
|
305
|
+
|
|
306
|
+
slab_n = 1;
|
|
307
|
+
for ( k = 0; k < bc->ndim; k++ ) slab_n *= counts[k];
|
|
308
|
+
|
|
309
|
+
operand_bytes = ca_sizeof[bc->common_dt];
|
|
310
|
+
|
|
311
|
+
/* === 1. pull LEFT (leaf in-place read or arena scratch) === */
|
|
312
|
+
{
|
|
313
|
+
char *left_inplace = NULL;
|
|
314
|
+
if ( ca_bincmp_try_leaf_inplace(bc->parent, bc->common_dt,
|
|
315
|
+
starts, counts, operand_bytes,
|
|
316
|
+
&left_inplace) ) {
|
|
317
|
+
/* Leaf-opt path: use parent->ptr + byte_offset directly. */
|
|
318
|
+
left_scratch = left_inplace;
|
|
319
|
+
left_is_inplace = 1;
|
|
320
|
+
ca_bincmp_leaf_inplace_count++;
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
ca_size_t left_strides[CA_RANK_MAX];
|
|
324
|
+
ca_size_t s = operand_bytes;
|
|
325
|
+
for ( k = bc->ndim - 1; k >= 0; k-- ) {
|
|
326
|
+
left_strides[k] = s;
|
|
327
|
+
s *= counts[k];
|
|
328
|
+
}
|
|
329
|
+
left_scratch = ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
330
|
+
ca_bincmp_scratch_acquire_count++;
|
|
331
|
+
ca_xfer_stride(bc->parent, starts, counts, left_strides, left_scratch,
|
|
332
|
+
CA_XFER_GET);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* === 2. pull RIGHT (right_is_scalar + leaf-opt) === */
|
|
337
|
+
if ( bc->right_is_scalar ) {
|
|
338
|
+
/* CScalar right: pull the single value into a 1-cell scratch
|
|
339
|
+
and walk the kernel with right_step=0. Leaf-opt applies when
|
|
340
|
+
right is an entity-shaped CScalar at the common data_type;
|
|
341
|
+
the gain per call is small but the code path stays uniform
|
|
342
|
+
with the same-shape case. */
|
|
343
|
+
char *right_inplace = NULL;
|
|
344
|
+
ca_size_t one_starts[CA_RANK_MAX] = {0};
|
|
345
|
+
ca_size_t one_counts[CA_RANK_MAX];
|
|
346
|
+
for ( k = 0; k < bc->right->ndim; k++ ) one_counts[k] = 1;
|
|
347
|
+
|
|
348
|
+
if ( ca_bincmp_try_leaf_inplace(bc->right, bc->common_dt,
|
|
349
|
+
one_starts, one_counts, operand_bytes,
|
|
350
|
+
&right_inplace) ) {
|
|
351
|
+
right_scratch = right_inplace;
|
|
352
|
+
right_is_inplace = 1;
|
|
353
|
+
ca_bincmp_leaf_inplace_count++;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
ca_size_t one_strides[CA_RANK_MAX];
|
|
357
|
+
for ( k = 0; k < bc->right->ndim; k++ ) one_strides[k] = operand_bytes;
|
|
358
|
+
right_scratch = ca_lazy_arena_acquire(operand_bytes);
|
|
359
|
+
ca_bincmp_scratch_acquire_count++;
|
|
360
|
+
ca_xfer_stride(bc->right, one_starts, one_counts, one_strides,
|
|
361
|
+
right_scratch, CA_XFER_GET);
|
|
362
|
+
}
|
|
363
|
+
right_step = 0;
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
/* Same-shape right: full slab pull or leaf-opt. */
|
|
367
|
+
char *right_inplace = NULL;
|
|
368
|
+
if ( ca_bincmp_try_leaf_inplace(bc->right, bc->common_dt,
|
|
369
|
+
starts, counts, operand_bytes,
|
|
370
|
+
&right_inplace) ) {
|
|
371
|
+
right_scratch = right_inplace;
|
|
372
|
+
right_is_inplace = 1;
|
|
373
|
+
ca_bincmp_leaf_inplace_count++;
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
ca_size_t right_strides[CA_RANK_MAX];
|
|
377
|
+
ca_size_t s = operand_bytes;
|
|
378
|
+
for ( k = bc->ndim - 1; k >= 0; k-- ) {
|
|
379
|
+
right_strides[k] = s;
|
|
380
|
+
s *= counts[k];
|
|
381
|
+
}
|
|
382
|
+
right_scratch = ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
383
|
+
ca_bincmp_scratch_acquire_count++;
|
|
384
|
+
ca_xfer_stride(bc->right, starts, counts, right_strides, right_scratch,
|
|
385
|
+
CA_XFER_GET);
|
|
386
|
+
}
|
|
387
|
+
right_step = 1;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* === 3. apply bincmp kernel ===
|
|
391
|
+
*
|
|
392
|
+
* Kernel signature (ext/carray.h):
|
|
393
|
+
* fn(n, m, ptr1, b1, i1, ptr2, b2, i2, ptr3, b3, i3)
|
|
394
|
+
*
|
|
395
|
+
* Per inspection of generated ca_bincmp_<op>_<data_type>, the `b*` args
|
|
396
|
+
* are declared but unused (kernel computes ptr + k*i*sizeof(T)). We
|
|
397
|
+
* pass 0 for the base arguments.
|
|
398
|
+
*
|
|
399
|
+
* Non-trapping: m=NULL (= SIMD fast path). Mask propagation handled
|
|
400
|
+
* by create_mask at view construction time.
|
|
401
|
+
*/
|
|
402
|
+
{
|
|
403
|
+
ca_bincmp_func_t fn = ca_bincmp_kernel_lookup(bc->op_id, bc->common_dt);
|
|
404
|
+
if ( fn == NULL ) {
|
|
405
|
+
if ( ! right_is_inplace ) ca_lazy_arena_release(right_scratch);
|
|
406
|
+
if ( ! left_is_inplace ) ca_lazy_arena_release(left_scratch);
|
|
407
|
+
rb_raise(rb_eNotImpError,
|
|
408
|
+
"CABinCmp: kernel not implemented (op_id=%u data_type=%d)",
|
|
409
|
+
(unsigned) bc->op_id, (int) bc->common_dt);
|
|
410
|
+
}
|
|
411
|
+
fn(slab_n, NULL,
|
|
412
|
+
(char *) left_scratch, 0, 1,
|
|
413
|
+
(char *) right_scratch, 0, right_step,
|
|
414
|
+
(char *) data, 0, 1,
|
|
415
|
+
bc->eps); /* Runtime tolerance for IS_CLOSE / IS_EQUIV. */
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if ( ! right_is_inplace ) ca_lazy_arena_release(right_scratch);
|
|
419
|
+
if ( ! left_is_inplace ) ca_lazy_arena_release(left_scratch);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
static void
|
|
423
|
+
ca_bincmp_func_xfer_all (void *ap, void *data, int dir)
|
|
424
|
+
{
|
|
425
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
426
|
+
ca_size_t starts[CA_RANK_MAX];
|
|
427
|
+
ca_size_t native[CA_RANK_MAX];
|
|
428
|
+
int8_t k;
|
|
429
|
+
ca_size_t s = 1; /* output stride = 1 byte */
|
|
430
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
431
|
+
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
432
|
+
ca_xfer_stride(ca, starts, ca->dim, native, data, dir);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
static void
|
|
436
|
+
ca_bincmp_func_allocate (void *ap)
|
|
437
|
+
{
|
|
438
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
439
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
static void
|
|
443
|
+
ca_bincmp_func_attach (void *ap)
|
|
444
|
+
{
|
|
445
|
+
/* CAREFUL: call the view-specific xfer_stride directly here,
|
|
446
|
+
not the public ca_xfer_stride dispatcher. The dispatcher's
|
|
447
|
+
self-memcpy fast path detects data == ca->ptr and returns
|
|
448
|
+
without materialising, so the freshly-allocated buffer would
|
|
449
|
+
still hold garbage. */
|
|
450
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
451
|
+
ca_size_t starts[CA_RANK_MAX];
|
|
452
|
+
ca_size_t native[CA_RANK_MAX];
|
|
453
|
+
int8_t k;
|
|
454
|
+
ca_size_t s;
|
|
455
|
+
|
|
456
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
457
|
+
|
|
458
|
+
s = ca->bytes;
|
|
459
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
460
|
+
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
461
|
+
ca_bincmp_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
static void
|
|
465
|
+
ca_bincmp_func_sync (void *ap)
|
|
466
|
+
{
|
|
467
|
+
/* read-only */
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
static void
|
|
471
|
+
ca_bincmp_func_detach (void *ap)
|
|
472
|
+
{
|
|
473
|
+
CABinCmp *ca = (CABinCmp *) ap;
|
|
474
|
+
xfree(ca->ptr);
|
|
475
|
+
ca->ptr = NULL;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
NORETURN(static void ca_bincmp_func_fill_data (void *ap, void *ptr));
|
|
479
|
+
static void
|
|
480
|
+
ca_bincmp_func_fill_data (void *ap, void *ptr)
|
|
481
|
+
{
|
|
482
|
+
rb_raise(rb_eRuntimeError, "CABinCmp is read-only (fill_data)");
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* mask = left.mask | right.mask, materialised as boolean8_t.
|
|
486
|
+
Mirrors CABinOp's create_mask policy. */
|
|
487
|
+
static void
|
|
488
|
+
ca_bincmp_func_create_mask (void *ap)
|
|
489
|
+
{
|
|
490
|
+
CABinCmp *bc = (CABinCmp *) ap;
|
|
491
|
+
CArray *l = bc->parent;
|
|
492
|
+
CArray *r = bc->right;
|
|
493
|
+
CArray *lm = NULL, *rm = NULL;
|
|
494
|
+
boolean8_t *dst;
|
|
495
|
+
ca_size_t i, n;
|
|
496
|
+
int has_l, has_r;
|
|
497
|
+
|
|
498
|
+
has_l = ca_has_mask(l);
|
|
499
|
+
has_r = ca_has_mask(r);
|
|
500
|
+
if ( ! has_l && ! has_r ) return;
|
|
501
|
+
|
|
502
|
+
if ( has_l ) lm = l->mask;
|
|
503
|
+
if ( has_r ) rm = r->mask;
|
|
504
|
+
|
|
505
|
+
bc->mask = (CArray *) carray_new(CA_BOOLEAN, bc->ndim, bc->dim, 0, NULL);
|
|
506
|
+
dst = (boolean8_t *) bc->mask->ptr;
|
|
507
|
+
n = bc->elements;
|
|
508
|
+
|
|
509
|
+
if ( has_l ) ca_attach(lm);
|
|
510
|
+
if ( has_r ) ca_attach(rm);
|
|
511
|
+
|
|
512
|
+
for ( i = 0; i < n; i++ ) {
|
|
513
|
+
boolean8_t a = has_l ? ((boolean8_t *) lm->ptr)[i] : 0;
|
|
514
|
+
boolean8_t b = 0;
|
|
515
|
+
if ( has_r ) {
|
|
516
|
+
ca_size_t ri = bc->right_is_scalar ? 0 : i;
|
|
517
|
+
b = ((boolean8_t *) rm->ptr)[ri];
|
|
518
|
+
}
|
|
519
|
+
dst[i] = (boolean8_t)( a | b );
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if ( has_l ) ca_detach(lm);
|
|
523
|
+
if ( has_r ) ca_detach(rm);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
ca_operation_function_t ca_bincmp_func = {
|
|
527
|
+
-1,
|
|
528
|
+
CA_VIEW_ARRAY,
|
|
529
|
+
free_ca_bincmp,
|
|
530
|
+
ca_bincmp_func_clone,
|
|
531
|
+
ca_bincmp_func_allocate,
|
|
532
|
+
ca_bincmp_func_attach,
|
|
533
|
+
ca_bincmp_func_sync,
|
|
534
|
+
ca_bincmp_func_detach,
|
|
535
|
+
ca_bincmp_func_fill_data,
|
|
536
|
+
ca_bincmp_func_create_mask,
|
|
537
|
+
ca_bincmp_func_xfer_index,
|
|
538
|
+
ca_bincmp_func_xfer_addrs,
|
|
539
|
+
NULL,
|
|
540
|
+
ca_bincmp_func_xfer_stride,
|
|
541
|
+
ca_bincmp_func_xfer_all,
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/* ------------------------------------------------------------------- */
|
|
545
|
+
/* Public builder (= lib/carray/lazy.rb dispatch entry) */
|
|
546
|
+
/* ------------------------------------------------------------------- */
|
|
547
|
+
|
|
548
|
+
static VALUE
|
|
549
|
+
collapse_marker (VALUE cary)
|
|
550
|
+
{
|
|
551
|
+
CArray *ca;
|
|
552
|
+
if ( ! rb_obj_is_carray(cary) ) return cary;
|
|
553
|
+
TypedData_Get_Struct(cary, CArray, &carray_data_type, ca);
|
|
554
|
+
if ( ca->obj_type == CA_OBJ_LAZY_MARKER ) {
|
|
555
|
+
return rb_ca_parent(cary);
|
|
556
|
+
}
|
|
557
|
+
return cary;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
static VALUE
|
|
561
|
+
rb_ca_bincmp_new (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
|
|
562
|
+
{
|
|
563
|
+
volatile VALUE obj;
|
|
564
|
+
CArray *l, *r;
|
|
565
|
+
CABinCmp *ca;
|
|
566
|
+
rb_check_carray_object(l_cary);
|
|
567
|
+
rb_check_carray_object(r_cary);
|
|
568
|
+
TypedData_Get_Struct(l_cary, CArray, &carray_data_type, l);
|
|
569
|
+
TypedData_Get_Struct(r_cary, CArray, &carray_data_type, r);
|
|
570
|
+
ca = ca_bincmp_new(l, r, op_id, eps);
|
|
571
|
+
obj = ca_wrap_struct(ca);
|
|
572
|
+
rb_ca_set_parent(obj, l_cary);
|
|
573
|
+
rb_ivar_set(obj, rb_intern("__bincmp_right__"), r_cary);
|
|
574
|
+
return obj;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
VALUE
|
|
578
|
+
rb_ca_bincmp_build (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
|
|
579
|
+
{
|
|
580
|
+
CArray *l, *r;
|
|
581
|
+
int8_t l_in_dt, r_in_dt;
|
|
582
|
+
volatile VALUE l_resolved, r_resolved;
|
|
583
|
+
|
|
584
|
+
l_resolved = collapse_marker(l_cary);
|
|
585
|
+
r_resolved = collapse_marker(r_cary);
|
|
586
|
+
|
|
587
|
+
/* Scalar wrap — same policy as CABinOp. */
|
|
588
|
+
if ( ! rb_obj_is_carray(l_resolved) ) {
|
|
589
|
+
rb_check_carray_object(r_resolved);
|
|
590
|
+
TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
|
|
591
|
+
l_resolved = ca_lazy_wrap_scalar(l_resolved, r);
|
|
592
|
+
}
|
|
593
|
+
if ( ! rb_obj_is_carray(r_resolved) ) {
|
|
594
|
+
rb_check_carray_object(l_resolved);
|
|
595
|
+
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
596
|
+
r_resolved = ca_lazy_wrap_scalar(r_resolved, l);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
600
|
+
TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
|
|
601
|
+
|
|
602
|
+
/* Cast both operands to the common data_type. */
|
|
603
|
+
ca_bincmp_kernel_input_data_types(op_id, l->data_type, r->data_type,
|
|
604
|
+
&l_in_dt, &r_in_dt);
|
|
605
|
+
|
|
606
|
+
if ( l_in_dt != l->data_type ) {
|
|
607
|
+
VALUE cast_op = INT2NUM(CA_MONOP_CAST_BASE + l_in_dt);
|
|
608
|
+
l_resolved = rb_funcall(rb_const_get(rb_cObject, rb_intern("CAMonOp")),
|
|
609
|
+
rb_intern("__build__"), 2,
|
|
610
|
+
l_resolved, cast_op);
|
|
611
|
+
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
612
|
+
}
|
|
613
|
+
if ( r_in_dt != r->data_type ) {
|
|
614
|
+
VALUE cast_op = INT2NUM(CA_MONOP_CAST_BASE + r_in_dt);
|
|
615
|
+
r_resolved = rb_funcall(rb_const_get(rb_cObject, rb_intern("CAMonOp")),
|
|
616
|
+
rb_intern("__build__"), 2,
|
|
617
|
+
r_resolved, cast_op);
|
|
618
|
+
TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/* Broadcast — same size-1-expansion logic as CABinOp. */
|
|
622
|
+
ca_broadcast_pair(&l_resolved, &r_resolved);
|
|
623
|
+
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
624
|
+
TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
|
|
625
|
+
|
|
626
|
+
if ( l->elements != r->elements ) {
|
|
627
|
+
if ( r->elements == 1 && l->elements > 1 ) {
|
|
628
|
+
/* CScalar right: handled via right_is_scalar */
|
|
629
|
+
}
|
|
630
|
+
else if ( l->elements == 1 && r->elements > 1 ) {
|
|
631
|
+
/* Comparison ops commute under negation (LT/GT/LE/GE flip to
|
|
632
|
+
their counterpart, EQ/NE are commutative), but here we
|
|
633
|
+
broadcast the left scalar up instead of swapping, so op_id
|
|
634
|
+
does not need a flip table. */
|
|
635
|
+
ca_size_t count[CA_RANK_MAX];
|
|
636
|
+
int8_t k;
|
|
637
|
+
if ( r->ndim > l->ndim ) {
|
|
638
|
+
for ( k = 0; k < r->ndim - 1; k++ ) count[k] = 1;
|
|
639
|
+
count[r->ndim - 1] = 0;
|
|
640
|
+
l_resolved = rb_ca_repeat_new(l_resolved, r->ndim, count);
|
|
641
|
+
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
642
|
+
}
|
|
643
|
+
l_resolved = ca_broadcast_view(l_resolved, r->ndim, r->dim);
|
|
644
|
+
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
rb_raise(rb_eArgError,
|
|
648
|
+
"CABinCmp: shape mismatch (%lld vs %lld) — only same-"
|
|
649
|
+
"ndim size-1 broadcast is supported; cross-ndim "
|
|
650
|
+
"promotion is not adopted in CArray",
|
|
651
|
+
(long long) l->elements, (long long) r->elements);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return rb_ca_bincmp_new(l_resolved, r_resolved, op_id, eps);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
static VALUE
|
|
659
|
+
rb_ca_bincmp_s_build (int argc, VALUE *argv, VALUE klass)
|
|
660
|
+
{
|
|
661
|
+
VALUE l_cary, r_cary, op_id_val, eps_val;
|
|
662
|
+
uint16_t op_id;
|
|
663
|
+
double eps = 0.0;
|
|
664
|
+
(void) klass;
|
|
665
|
+
rb_scan_args(argc, argv, "31", &l_cary, &r_cary, &op_id_val, &eps_val);
|
|
666
|
+
op_id = (uint16_t) NUM2UINT(op_id_val);
|
|
667
|
+
if ( argc >= 4 ) eps = NUM2DBL(eps_val);
|
|
668
|
+
return rb_ca_bincmp_build(l_cary, r_cary, op_id, eps);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
static VALUE
|
|
672
|
+
rb_ca_bincmp_op_id (VALUE self)
|
|
673
|
+
{
|
|
674
|
+
CABinCmp *bc;
|
|
675
|
+
TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, bc);
|
|
676
|
+
return UINT2NUM(bc->op_id);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
static VALUE
|
|
680
|
+
rb_ca_bincmp_right (VALUE self)
|
|
681
|
+
{
|
|
682
|
+
return rb_ivar_get(self, rb_intern("__bincmp_right__"));
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
static VALUE
|
|
686
|
+
rb_ca_bincmp_eps (VALUE self)
|
|
687
|
+
{
|
|
688
|
+
CABinCmp *bc;
|
|
689
|
+
TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, bc);
|
|
690
|
+
return rb_float_new(bc->eps);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
static VALUE
|
|
694
|
+
rb_ca_bincmp_s_reset_scratch_counter (VALUE klass)
|
|
695
|
+
{
|
|
696
|
+
(void) klass;
|
|
697
|
+
ca_bincmp_scratch_acquire_count = 0;
|
|
698
|
+
return Qnil;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
static VALUE
|
|
702
|
+
rb_ca_bincmp_s_scratch_count (VALUE klass)
|
|
703
|
+
{
|
|
704
|
+
(void) klass;
|
|
705
|
+
return SIZE2NUM(ca_bincmp_scratch_acquire_count);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
static VALUE
|
|
709
|
+
rb_ca_bincmp_s_reset_materialise_counter (VALUE klass)
|
|
710
|
+
{
|
|
711
|
+
(void) klass;
|
|
712
|
+
ca_bincmp_materialise_call_count = 0;
|
|
713
|
+
return Qnil;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
static VALUE
|
|
717
|
+
rb_ca_bincmp_s_materialise_count (VALUE klass)
|
|
718
|
+
{
|
|
719
|
+
(void) klass;
|
|
720
|
+
return SIZE2NUM(ca_bincmp_materialise_call_count);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
static VALUE
|
|
724
|
+
rb_ca_bincmp_s_reset_leaf_inplace_counter (VALUE klass)
|
|
725
|
+
{
|
|
726
|
+
(void) klass;
|
|
727
|
+
ca_bincmp_leaf_inplace_count = 0;
|
|
728
|
+
return Qnil;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
static VALUE
|
|
732
|
+
rb_ca_bincmp_s_leaf_inplace_count (VALUE klass)
|
|
733
|
+
{
|
|
734
|
+
(void) klass;
|
|
735
|
+
return SIZE2NUM(ca_bincmp_leaf_inplace_count);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
static VALUE
|
|
739
|
+
rb_ca_bincmp_s_allocate (VALUE klass)
|
|
740
|
+
{
|
|
741
|
+
CABinCmp *ca;
|
|
742
|
+
return TypedData_Make_Struct(klass, CABinCmp, &cabincmp_data_type, ca);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
static VALUE
|
|
746
|
+
rb_ca_bincmp_initialize_copy (VALUE self, VALUE other)
|
|
747
|
+
{
|
|
748
|
+
CABinCmp *ca, *cs;
|
|
749
|
+
TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, ca);
|
|
750
|
+
TypedData_Get_Struct(other, CABinCmp, &cabincmp_data_type, cs);
|
|
751
|
+
if ( ca_func[CA_OBJ_BINCMP].pool_init ) {
|
|
752
|
+
ca_array_pool_alloc(ca, CA_OBJ_BINCMP, cs->parent->ndim);
|
|
753
|
+
}
|
|
754
|
+
ca_bincmp_setup(ca, cs->parent, cs->right, cs->op_id, cs->eps);
|
|
755
|
+
return self;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
void
|
|
759
|
+
Init_ca_obj_bincmp (void)
|
|
760
|
+
{
|
|
761
|
+
rb_cCABinCmp = rb_define_class("CABinCmp", rb_cCAView);
|
|
762
|
+
|
|
763
|
+
ca_bincmp_func.struct_size = sizeof(CABinCmp);
|
|
764
|
+
ca_bincmp_func.pool_bytes = ca_bincmp_pool_bytes;
|
|
765
|
+
ca_bincmp_func.pool_init = ca_bincmp_pool_init;
|
|
766
|
+
|
|
767
|
+
CA_OBJ_BINCMP = ca_install_obj_type(rb_cCABinCmp,
|
|
768
|
+
&cabincmp_data_type,
|
|
769
|
+
rb_cCArrayMask,
|
|
770
|
+
&carray_mask_data_type, &ca_bincmp_func, sizeof(ca_bincmp_func));
|
|
771
|
+
rb_define_const(rb_cObject, "CA_OBJ_BINCMP", INT2NUM(CA_OBJ_BINCMP));
|
|
772
|
+
|
|
773
|
+
/* op_id constants shared with lib/carray/lazy.rb. */
|
|
774
|
+
rb_define_const(rb_cCABinCmp, "OP_LT", INT2NUM(CA_BINCMP_LT));
|
|
775
|
+
rb_define_const(rb_cCABinCmp, "OP_GT", INT2NUM(CA_BINCMP_GT));
|
|
776
|
+
rb_define_const(rb_cCABinCmp, "OP_LE", INT2NUM(CA_BINCMP_LE));
|
|
777
|
+
rb_define_const(rb_cCABinCmp, "OP_GE", INT2NUM(CA_BINCMP_GE));
|
|
778
|
+
rb_define_const(rb_cCABinCmp, "OP_EQ", INT2NUM(CA_BINCMP_EQ));
|
|
779
|
+
rb_define_const(rb_cCABinCmp, "OP_NE", INT2NUM(CA_BINCMP_NE));
|
|
780
|
+
rb_define_const(rb_cCABinCmp, "OP_FEQ", INT2NUM(CA_BINCMP_FEQ));
|
|
781
|
+
rb_define_const(rb_cCABinCmp, "OP_IS_CLOSE", INT2NUM(CA_BINCMP_IS_CLOSE));
|
|
782
|
+
rb_define_const(rb_cCABinCmp, "OP_IS_EQUIV", INT2NUM(CA_BINCMP_IS_EQUIV));
|
|
783
|
+
|
|
784
|
+
rb_define_alloc_func(rb_cCABinCmp, rb_ca_bincmp_s_allocate);
|
|
785
|
+
rb_define_method(rb_cCABinCmp, "initialize_copy",
|
|
786
|
+
rb_ca_bincmp_initialize_copy, 1);
|
|
787
|
+
|
|
788
|
+
/* __build__(left, right, op_id [, eps]) */
|
|
789
|
+
rb_define_singleton_method(rb_cCABinCmp, "__build__",
|
|
790
|
+
rb_ca_bincmp_s_build, -1);
|
|
791
|
+
|
|
792
|
+
rb_define_method(rb_cCABinCmp, "__op_id__", rb_ca_bincmp_op_id, 0);
|
|
793
|
+
rb_define_method(rb_cCABinCmp, "__bincmp_right__",
|
|
794
|
+
rb_ca_bincmp_right, 0);
|
|
795
|
+
rb_define_method(rb_cCABinCmp, "__eps__", rb_ca_bincmp_eps, 0);
|
|
796
|
+
|
|
797
|
+
rb_define_singleton_method(rb_cCABinCmp, "__reset_scratch_counter__",
|
|
798
|
+
rb_ca_bincmp_s_reset_scratch_counter, 0);
|
|
799
|
+
rb_define_singleton_method(rb_cCABinCmp, "__scratch_count__",
|
|
800
|
+
rb_ca_bincmp_s_scratch_count, 0);
|
|
801
|
+
rb_define_singleton_method(rb_cCABinCmp, "__reset_materialise_counter__",
|
|
802
|
+
rb_ca_bincmp_s_reset_materialise_counter, 0);
|
|
803
|
+
rb_define_singleton_method(rb_cCABinCmp, "__materialise_count__",
|
|
804
|
+
rb_ca_bincmp_s_materialise_count, 0);
|
|
805
|
+
rb_define_singleton_method(rb_cCABinCmp, "__reset_leaf_inplace_counter__",
|
|
806
|
+
rb_ca_bincmp_s_reset_leaf_inplace_counter, 0);
|
|
807
|
+
rb_define_singleton_method(rb_cCABinCmp, "__leaf_inplace_count__",
|
|
808
|
+
rb_ca_bincmp_s_leaf_inplace_count, 0);
|
|
809
|
+
}
|