carray 3.0.0 → 3.0.2
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 +2 -1
- data/CHANGELOG.md +845 -3
- data/{NEWS.md → CHANGELOG.v1.md} +1 -1
- data/README.md +33 -33
- data/carray.gemspec +12 -8
- data/ext/ca_axis_dispatch.c +33 -4
- data/ext/ca_axis_group.c +256 -114
- data/ext/ca_binop_dispatch.c +5 -6
- data/ext/ca_binop_dispatch.h +0 -7
- data/ext/ca_categorical_iterator.c +121 -67
- data/ext/ca_for_each_element.h +6 -8
- data/ext/ca_group_iter.c +1 -1
- data/ext/ca_kernel_iterator.c +386 -74
- data/ext/ca_kernel_iterator.h +145 -45
- data/ext/ca_obj_array.c +62 -20
- data/ext/ca_obj_bincmp.c +57 -27
- data/ext/ca_obj_binop.c +86 -30
- data/ext/ca_obj_block.c +4 -4
- data/ext/ca_obj_const_string.c +88 -27
- data/ext/ca_obj_face.c +104 -0
- data/ext/ca_obj_face.h +48 -1
- data/ext/ca_obj_fake.c +11 -0
- data/ext/ca_obj_fixlen_string.c +21 -6
- data/ext/ca_obj_grid.c +11 -3
- data/ext/ca_obj_meld.c +125 -22
- data/ext/ca_obj_moncmp.c +33 -14
- data/ext/ca_obj_monop.c +19 -7
- data/ext/ca_obj_object.c +107 -4
- data/ext/ca_obj_record.c +3 -1
- data/ext/ca_obj_refer.c +30 -6
- data/ext/ca_obj_roll.c +13 -5
- data/ext/ca_obj_select.c +49 -34
- data/ext/ca_obj_select_axis.c +16 -6
- data/ext/ca_obj_shift.c +3 -3
- data/ext/ca_obj_stack.c +3 -8
- data/ext/ca_obj_stride.c +178 -24
- data/ext/ca_obj_string.c +11 -5
- data/ext/ca_obj_tile.c +13 -5
- data/ext/ca_obj_time.c +3 -1
- data/ext/ca_obj_timedelta.c +3 -1
- data/ext/ca_obj_transpose.c +1 -1
- data/ext/ca_obj_triop.c +62 -23
- data/ext/ca_obj_window.c +94 -19
- data/ext/ca_op_cmplx64.h +123 -0
- data/ext/ca_op_ipower.c +1 -5
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +5 -5
- data/ext/ca_sweep_engine.c +362 -155
- data/ext/ca_sweep_engine.h +39 -9
- data/ext/ca_transform_common.c +7 -0
- data/ext/carray.h +148 -132
- data/ext/carray_access.c +83 -49
- data/ext/carray_address_basis.c +590 -0
- data/ext/carray_bincount.c +8 -8
- data/ext/carray_broadcast.c +102 -9
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +2010 -335
- data/ext/carray_call_cfunc.h +153 -0
- data/ext/carray_cast.c +184 -72
- data/ext/carray_conversion.c +22 -22
- data/ext/carray_copy.c +67 -32
- data/ext/carray_core.c +140 -13
- data/ext/carray_count.c +10 -11
- data/ext/carray_element.c +7 -7
- data/ext/carray_factorize.c +72 -51
- data/ext/carray_hold.c +1 -1
- data/ext/carray_index_classifier.c +7 -21
- data/ext/carray_internal.h +36 -3
- data/ext/carray_kernels_bincmp.c +1 -0
- data/ext/carray_kernels_binop.c +320 -298
- data/ext/carray_kernels_init.c +1095 -0
- data/ext/carray_kernels_map.c +1 -0
- data/ext/carray_kernels_moncmp.c +1 -0
- data/ext/carray_kernels_monop.c +412 -411
- data/ext/carray_kernels_reduce_aggregate.c +256 -87
- data/ext/carray_kernels_reduce_boolean.c +1 -0
- data/ext/carray_kernels_reduce_cumulative.c +324 -54
- data/ext/carray_kernels_reduce_extreme.c +605 -58
- data/ext/carray_kernels_reduce_variance.c +1 -0
- data/ext/carray_kernels_scan.c +5 -4
- data/ext/carray_kernels_search.c +187 -106
- data/ext/carray_kernels_sort.c +1 -0
- data/ext/carray_kernels_triop.c +1 -0
- data/ext/carray_lazy.c +175 -5
- data/ext/carray_loop.c +7 -1
- data/ext/carray_mask.c +29 -13
- data/ext/carray_median_percentile.c +56 -1
- data/ext/carray_memory_view.c +46 -21
- data/ext/carray_operator.c +50 -53
- data/ext/carray_order.c +1 -1
- data/ext/carray_partition.c +4 -4
- data/ext/carray_random.c +391 -47
- data/ext/carray_scatter.c +1 -1
- data/ext/carray_slab.c +13 -0
- data/ext/carray_sort.c +22 -24
- data/ext/carray_sort_kernel.c +10 -10
- data/ext/carray_test.c +1 -1
- data/ext/extconf.rb +18 -0
- data/ext/mk_call_cfunc.rb +323 -145
- data/ext/mkkernel.rb +651 -129
- data/ext/ruby_carray.c +28 -17
- data/ext/version.h +4 -4
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +14 -1
- data/lib/carray/axis_group.rb +84 -7
- data/lib/carray/basics.rb +63 -59
- data/lib/carray/bincount_nd.rb +12 -12
- data/lib/carray/block_iterator.rb +111 -25
- data/lib/carray/categorical.rb +154 -37
- data/lib/carray/categorical_iterator.rb +300 -151
- data/lib/carray/conditional.rb +14 -14
- data/lib/carray/const_string.rb +131 -27
- data/lib/carray/construct.rb +61 -0
- data/lib/carray/core_extensions.rb +62 -5
- data/lib/carray/data_type_extension.rb +21 -1
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +3 -3
- data/lib/carray/frame/convert.rb +1 -1
- data/lib/carray/frame/csv_parser.rb +11 -4
- data/lib/carray/frame/frame.rb +85 -21
- data/lib/carray/frame/group.rb +36 -3
- data/lib/carray/frame/io.rb +224 -15
- data/lib/carray/frame/records.rb +18 -4
- data/lib/carray/frame/sort.rb +1 -1
- data/lib/carray/frame/verbs.rb +32 -12
- data/lib/carray/fuse_source.rb +123 -0
- data/lib/carray/fusion.rb +218 -0
- data/lib/carray/histogram.rb +16 -16
- data/lib/carray/inspect.rb +43 -16
- data/lib/carray/iterator.rb +147 -3
- data/lib/carray/lazy.rb +88 -73
- data/lib/carray/mask_gap_fill.rb +3 -1
- data/lib/carray/meld_reduce.rb +2 -2
- data/lib/carray/methods/align_addr.rb +1 -1
- data/lib/carray/methods/composition.rb +1 -1
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/is_in.rb +25 -14
- data/lib/carray/methods/locate_addr.rb +81 -3
- data/lib/carray/methods/mask_duplicates.rb +36 -2
- data/lib/carray/methods/meshgrid.rb +4 -5
- data/lib/carray/methods/mode.rb +2 -2
- data/lib/carray/methods/nunique.rb +23 -2
- data/lib/carray/methods/repeat.rb +110 -0
- data/lib/carray/methods/snap.rb +7 -2
- data/lib/carray/methods/unique.rb +44 -4
- data/lib/carray/methods/value_counts.rb +2 -2
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +0 -19
- data/lib/carray/slab_iterator.rb +77 -19
- data/lib/carray/string_operation_extension.rb +10 -6
- data/lib/carray/time.rb +906 -491
- data/lib/carray/window_iterator.rb +421 -27
- data/lib/carray.rb +7 -5
- data/yard-stubs/ca_obj_array.rb +385 -0
- data/yard-stubs/ca_obj_bitarray.rb +38 -0
- data/yard-stubs/ca_obj_bitfield.rb +43 -0
- data/yard-stubs/ca_obj_block.rb +68 -0
- data/yard-stubs/ca_obj_byte_swap.rb +56 -0
- data/yard-stubs/ca_obj_fake.rb +31 -0
- data/yard-stubs/ca_obj_farray.rb +32 -0
- data/yard-stubs/ca_obj_field.rb +45 -0
- data/yard-stubs/ca_obj_grid.rb +35 -0
- data/yard-stubs/ca_obj_refer.rb +72 -0
- data/yard-stubs/ca_obj_roll.rb +45 -0
- data/yard-stubs/ca_obj_shift.rb +43 -0
- data/yard-stubs/ca_obj_stride.rb +181 -0
- data/yard-stubs/ca_obj_tile.rb +29 -0
- data/yard-stubs/ca_obj_transpose.rb +40 -0
- data/yard-stubs/ca_obj_window.rb +57 -0
- data/yard-stubs/carray_access.rb +131 -0
- data/yard-stubs/carray_attribute.rb +246 -0
- data/yard-stubs/carray_broadcast.rb +37 -0
- data/yard-stubs/carray_cast.rb +489 -0
- data/yard-stubs/carray_class.rb +65 -0
- data/yard-stubs/carray_conversion.rb +76 -0
- data/yard-stubs/carray_copy.rb +79 -0
- data/yard-stubs/carray_core.rb +34 -0
- data/yard-stubs/carray_count.rb +84 -0
- data/yard-stubs/carray_element.rb +108 -0
- data/yard-stubs/carray_generate.rb +66 -0
- data/yard-stubs/carray_lazy.rb +228 -0
- data/yard-stubs/carray_loop.rb +140 -0
- data/yard-stubs/carray_mask.rb +259 -0
- data/yard-stubs/carray_math.rb +1615 -0
- data/yard-stubs/carray_mathfunc.rb +45 -0
- data/yard-stubs/carray_median_percentile.rb +103 -0
- data/yard-stubs/carray_memory_view.rb +163 -0
- data/yard-stubs/carray_order.rb +252 -0
- data/yard-stubs/carray_random.rb +89 -0
- data/yard-stubs/carray_scatter.rb +106 -0
- data/yard-stubs/carray_slab.rb +59 -0
- data/yard-stubs/carray_sort.rb +165 -0
- data/yard-stubs/carray_test.rb +85 -0
- data/yard-stubs/carray_undef.rb +64 -0
- data/yard-stubs/carray_utils.rb +97 -0
- data/yard-stubs/ruby_carray.rb +193 -0
- metadata +67 -10
- data/ext/ca_obj_unbound_repeat.c +0 -496
data/ext/ca_kernel_iterator.h
CHANGED
|
@@ -198,15 +198,9 @@ typedef enum {
|
|
|
198
198
|
#define CA_ITER_ERR_READONLY 4 /* WRITE on readonly view (CARepeat etc.) */
|
|
199
199
|
#define CA_ITER_ERR_MASK 5 /* masked source — step 4-5 only, lifted in step 6 */
|
|
200
200
|
#define CA_ITER_ERR_MASK_NOT_ALLOWED 6 /* NO_MASK flag set on a masked source (step 7) */
|
|
201
|
-
#define CA_ITER_ERR_UNBOUND_SHAPE 7 /* CAUnboundRepeat passed before bind() — reserved for
|
|
202
|
-
sub-step 9.3 (= used iff unbound CAUbrep smoke shows
|
|
203
|
-
unsafe behavior on the existing SRC_CASTRIDE path) */
|
|
204
|
-
|
|
205
201
|
/* ---- source kind (step 5+, internal routing) ------------------------- */
|
|
206
202
|
#define CA_ITER_SRC_NONE 0
|
|
207
|
-
#define CA_ITER_SRC_CASTRIDE 1 /* entity / CAStride family (step 1-4)
|
|
208
|
-
CAUnboundRepeat is also classified
|
|
209
|
-
here via ca_ubrep_func = ca_stride_func. */
|
|
203
|
+
#define CA_ITER_SRC_CASTRIDE 1 /* entity / CAStride family (step 1-4) */
|
|
210
204
|
#define CA_ITER_SRC_DESCRIPTOR 2 /* CSA / CAGrid / CASelect / CAMapping / CAWindow / CAShift (step 5+) */
|
|
211
205
|
#define CA_ITER_SRC_ATTACH 3 /* CAFake / CAByteSwap / CABitfield /
|
|
212
206
|
CABitarray / CAReduce — view's own
|
|
@@ -534,7 +528,24 @@ int ca_iter_state_init_l2 (ca_iter_state *st,
|
|
|
534
528
|
source carries a mask (= ca_has_mask(src)), or NULL otherwise.
|
|
535
529
|
The mask layout matches the value layout (= same iteration order
|
|
536
530
|
and same n). Step 6+: kernels use the CA_FOR_EACH_UNMASKED macro
|
|
537
|
-
family (carray.h) to skip masked cells.
|
|
531
|
+
family (carray.h) to skip masked cells.
|
|
532
|
+
|
|
533
|
+
The mask is an input. What it points at is a copy taken when the
|
|
534
|
+
walk began, so writing through it changes nothing -- not even under
|
|
535
|
+
CA_KERNEL_WRITE, where the value half of the same yield is often a
|
|
536
|
+
live alias. It also cannot express the thing an author would most
|
|
537
|
+
want it for: an unmasked source yields NULL, so there is nowhere to
|
|
538
|
+
record that a cell has become undefined. A kernel authors its
|
|
539
|
+
output mask on its own output array instead:
|
|
540
|
+
|
|
541
|
+
if ( op_mask == NULL ) {
|
|
542
|
+
ca_create_mask(co);
|
|
543
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
544
|
+
}
|
|
545
|
+
op_mask[out_i] = 1;
|
|
546
|
+
|
|
547
|
+
which is what every kernel in carray does (carray_hold.c, and the
|
|
548
|
+
reduction kernels mkkernel emits). */
|
|
538
549
|
int ca_iter_state_next_slab (ca_iter_state *st,
|
|
539
550
|
char **out_ptr,
|
|
540
551
|
boolean8_t **out_mask,
|
|
@@ -609,6 +620,13 @@ void ca_iter_state_sync_slab (ca_iter_state *st);
|
|
|
609
620
|
exactly once after a successful init (either level). */
|
|
610
621
|
void ca_iter_state_finish (ca_iter_state *st);
|
|
611
622
|
|
|
623
|
+
/* Raise unless rc is CA_ITER_OK. The block macros call this on the value
|
|
624
|
+
ca_iter_state_init_l1 / _l2 returned, so an author who never looks at a
|
|
625
|
+
return code still hears about a request the iterator would not serve.
|
|
626
|
+
Returns rc when there is nothing to report, so it composes inside the
|
|
627
|
+
macros' comma expressions. */
|
|
628
|
+
int ca_iter_check_init (int rc);
|
|
629
|
+
|
|
612
630
|
/* ---- Phase C C.3: kernel author block macros ------------------------
|
|
613
631
|
(PROPOSAL_CAPSTONE_PHASE_C.md D3.1 (A) do/while/for + D3.2 (C) 2 kinds)
|
|
614
632
|
|
|
@@ -623,17 +641,24 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
623
641
|
surrounding scope.
|
|
624
642
|
- `flags` arg propagates to init_l2 (= CA_KERNEL_WRITE supported).
|
|
625
643
|
`sync_slab` is called automatically after each iteration; it's a
|
|
626
|
-
no-op when WRITE flag is absent.
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
644
|
+
no-op when WRITE flag is absent. The mask cursor is an input even
|
|
645
|
+
under WRITE -- see ca_iter_state_next_slab above for why, and for
|
|
646
|
+
where an output mask is written instead.
|
|
647
|
+
- Init failure (ca_iter_state_init_l2 returns CA_ITER_ERR_*) raises:
|
|
648
|
+
the macro passes the code to ca_iter_check_init, which reports what
|
|
649
|
+
the iterator declined to do. The body does not run and finish is
|
|
650
|
+
not reached, which is safe because a failed init allocates nothing.
|
|
651
|
+
Kernels that want to handle a refusal rather than propagate it
|
|
652
|
+
should drop down to the raw API and read the code themselves.
|
|
632
653
|
- `break;` from inside the body exits the loop AND triggers finish
|
|
633
654
|
correctly (= outer for's "increment" clause runs once on natural
|
|
634
655
|
exit; `break` from the inner while breaks both). `return` inside
|
|
635
656
|
the body LEAKS resources (scratch_ptr, parent attach) — drop to
|
|
636
|
-
raw API if early return is needed.
|
|
657
|
+
raw API if early return is needed. A body that raises leaks the
|
|
658
|
+
same way: the engine releases what it holds when the walk itself
|
|
659
|
+
raises (a gather or a write-back through the source's slots), but
|
|
660
|
+
the body runs in the caller's frame, where it has no hold on it.
|
|
661
|
+
An object-lane body calling back into Ruby is the case to watch.
|
|
637
662
|
- Macros are not statement-equivalent (= they expand to nested for
|
|
638
663
|
constructs). Don't follow them with `else` etc. */
|
|
639
664
|
|
|
@@ -766,8 +791,9 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
766
791
|
always-constant argument). CA_SLAB_AXES is still FROZEN, because
|
|
767
792
|
raw-API kernels pass it to ca_iter_state_init_l2 directly. */
|
|
768
793
|
#define CA_FOR_EACH_SLAB(st, ca, axes, naxes, flags, p, m) \
|
|
769
|
-
for ( int __caf_init = (
|
|
770
|
-
|
|
794
|
+
for ( int __caf_init = (ca_iter_check_init( \
|
|
795
|
+
ca_iter_state_init_l2(&(st), (ca), CA_SLAB_AXES, \
|
|
796
|
+
(axes), (naxes), (flags))), \
|
|
771
797
|
1); \
|
|
772
798
|
__caf_init; \
|
|
773
799
|
__caf_init = 0, ca_iter_state_finish(&(st)) ) \
|
|
@@ -783,16 +809,18 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
783
809
|
Shape mismatch between ca_in / ca_out is NOT validated by the macro
|
|
784
810
|
— caller responsibility (= typically output is `rb_ca_template_with_type`
|
|
785
811
|
of input, guaranteeing same shape). Init failure on either iter
|
|
786
|
-
|
|
812
|
+
raises — see CA_FOR_EACH_SLAB above. */
|
|
787
813
|
/* Policy fixed to CA_SLAB_AXES internally — see CA_FOR_EACH_SLAB above. */
|
|
788
814
|
#define CA_FOR_EACH_SLAB_INOUT(st_in, st_out, ca_in, ca_out, \
|
|
789
815
|
axes, naxes, \
|
|
790
816
|
p_in, p_out, m_in, m_out) \
|
|
791
817
|
for ( int __cafi_init = ( \
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
818
|
+
ca_iter_check_init( \
|
|
819
|
+
ca_iter_state_init_l2(&(st_in), (ca_in), CA_SLAB_AXES, \
|
|
820
|
+
(axes), (naxes), 0)), \
|
|
821
|
+
ca_iter_check_init( \
|
|
822
|
+
ca_iter_state_init_l2(&(st_out), (ca_out), CA_SLAB_AXES, \
|
|
823
|
+
(axes), (naxes), CA_KERNEL_WRITE)), \
|
|
796
824
|
1); \
|
|
797
825
|
__cafi_init; \
|
|
798
826
|
__cafi_init = 0, \
|
|
@@ -833,9 +861,10 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
833
861
|
|
|
834
862
|
#define CA_FOR_EACH_FIBER(st, ca, axis, flags, p, n) \
|
|
835
863
|
for ( int __cff_init = ( \
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
864
|
+
ca_iter_check_init( \
|
|
865
|
+
ca_iter_state_init_l2(&(st), (ca), CA_SLAB_AXES, \
|
|
866
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
867
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
839
868
|
(n) = (st).slab_dims[0], \
|
|
840
869
|
1); \
|
|
841
870
|
__cff_init; \
|
|
@@ -845,9 +874,10 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
845
874
|
|
|
846
875
|
#define CA_FOR_EACH_FIBER_MASKED(st, ca, axis, flags, p, n, m) \
|
|
847
876
|
for ( int __cffm_init = ( \
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
877
|
+
ca_iter_check_init( \
|
|
878
|
+
ca_iter_state_init_l2(&(st), (ca), CA_SLAB_AXES, \
|
|
879
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
880
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
851
881
|
(n) = (st).slab_dims[0], \
|
|
852
882
|
1); \
|
|
853
883
|
__cffm_init; \
|
|
@@ -870,13 +900,15 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
870
900
|
#define CA_FOR_EACH_FIBER_INOUT(st_in, st_out, ca_in, ca_out, axis, \
|
|
871
901
|
flags, p_in, p_out, n) \
|
|
872
902
|
for ( int __cffi_init = ( \
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
903
|
+
ca_iter_check_init( \
|
|
904
|
+
ca_iter_state_init_l2(&(st_in), (ca_in), CA_SLAB_AXES, \
|
|
905
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
906
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
907
|
+
ca_iter_check_init( \
|
|
908
|
+
ca_iter_state_init_l2(&(st_out), (ca_out), CA_SLAB_AXES, \
|
|
909
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
910
|
+
((flags) | CA_KERNEL_FIBER_CONTIG \
|
|
911
|
+
| CA_KERNEL_WRITE))), \
|
|
880
912
|
(n) = (st_in).slab_dims[0], \
|
|
881
913
|
1); \
|
|
882
914
|
__cffi_init; \
|
|
@@ -894,13 +926,15 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
894
926
|
#define CA_FOR_EACH_FIBER_INOUT_MASKED(st_in, st_out, ca_in, ca_out, axis, \
|
|
895
927
|
flags, p_in, p_out, n, m) \
|
|
896
928
|
for ( int __cffim_init = ( \
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
929
|
+
ca_iter_check_init( \
|
|
930
|
+
ca_iter_state_init_l2(&(st_in), (ca_in), CA_SLAB_AXES, \
|
|
931
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
932
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
933
|
+
ca_iter_check_init( \
|
|
934
|
+
ca_iter_state_init_l2(&(st_out), (ca_out), CA_SLAB_AXES, \
|
|
935
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
936
|
+
((flags) | CA_KERNEL_FIBER_CONTIG \
|
|
937
|
+
| CA_KERNEL_WRITE))), \
|
|
904
938
|
(n) = (st_in).slab_dims[0], \
|
|
905
939
|
1); \
|
|
906
940
|
__cffim_init; \
|
|
@@ -915,6 +949,73 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
915
949
|
ca_iter_state_sync_slab(&(st_in)), \
|
|
916
950
|
ca_iter_state_sync_slab(&(st_out)) )
|
|
917
951
|
|
|
952
|
+
/* PAIR forms: two sources read together along the same axis.
|
|
953
|
+
|
|
954
|
+
The INOUT forms cover input + output. These cover input + input, which
|
|
955
|
+
is what a routine taking two vectors of the same length wants -- a
|
|
956
|
+
correlation, a dot product, a distance. Neither state gets
|
|
957
|
+
CA_KERNEL_WRITE, and `flags` must not carry it: use the INOUT forms to
|
|
958
|
+
write.
|
|
959
|
+
|
|
960
|
+
Both fibers are contig-delivered, so the pair may be handed straight to
|
|
961
|
+
a C routine that walks it itself. The MASKED form yields BOTH mask
|
|
962
|
+
cursors: which cells a pair of fibers may be used at is a question about
|
|
963
|
+
both of them, and the INOUT forms answer only about the input.
|
|
964
|
+
|
|
965
|
+
Shape agreement is guarded the way the INOUT forms guard it (ndim,
|
|
966
|
+
elements, fiber length), and the body is skipped on mismatch. The two
|
|
967
|
+
sources may be the same array. */
|
|
968
|
+
|
|
969
|
+
#define CA_FOR_EACH_FIBER_PAIR(st_a, st_b, ca_a, ca_b, axis, \
|
|
970
|
+
flags, p_a, p_b, n) \
|
|
971
|
+
for ( int __cffp_init = ( \
|
|
972
|
+
ca_iter_check_init( \
|
|
973
|
+
ca_iter_state_init_l2(&(st_a), (ca_a), CA_SLAB_AXES, \
|
|
974
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
975
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
976
|
+
ca_iter_check_init( \
|
|
977
|
+
ca_iter_state_init_l2(&(st_b), (ca_b), CA_SLAB_AXES, \
|
|
978
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
979
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
980
|
+
(n) = (st_a).slab_dims[0], \
|
|
981
|
+
1); \
|
|
982
|
+
__cffp_init; \
|
|
983
|
+
__cffp_init = 0, \
|
|
984
|
+
ca_iter_state_finish(&(st_a)), \
|
|
985
|
+
ca_iter_state_finish(&(st_b)) ) \
|
|
986
|
+
for ( ; (st_a).src->ndim == (st_b).src->ndim \
|
|
987
|
+
&& (st_a).src->elements == (st_b).src->elements \
|
|
988
|
+
&& (st_a).slab_dims[0] == (st_b).slab_dims[0] \
|
|
989
|
+
&& ca_iter_state_next_slab_axes(&(st_a), &(p_a), NULL) \
|
|
990
|
+
&& ca_iter_state_next_slab_axes(&(st_b), &(p_b), NULL); \
|
|
991
|
+
ca_iter_state_sync_slab(&(st_a)), \
|
|
992
|
+
ca_iter_state_sync_slab(&(st_b)) )
|
|
993
|
+
|
|
994
|
+
#define CA_FOR_EACH_FIBER_PAIR_MASKED(st_a, st_b, ca_a, ca_b, axis, \
|
|
995
|
+
flags, p_a, p_b, n, m_a, m_b) \
|
|
996
|
+
for ( int __cffpm_init = ( \
|
|
997
|
+
ca_iter_check_init( \
|
|
998
|
+
ca_iter_state_init_l2(&(st_a), (ca_a), CA_SLAB_AXES, \
|
|
999
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
1000
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
1001
|
+
ca_iter_check_init( \
|
|
1002
|
+
ca_iter_state_init_l2(&(st_b), (ca_b), CA_SLAB_AXES, \
|
|
1003
|
+
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
1004
|
+
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
1005
|
+
(n) = (st_a).slab_dims[0], \
|
|
1006
|
+
1); \
|
|
1007
|
+
__cffpm_init; \
|
|
1008
|
+
__cffpm_init = 0, \
|
|
1009
|
+
ca_iter_state_finish(&(st_a)), \
|
|
1010
|
+
ca_iter_state_finish(&(st_b)) ) \
|
|
1011
|
+
for ( ; (st_a).src->ndim == (st_b).src->ndim \
|
|
1012
|
+
&& (st_a).src->elements == (st_b).src->elements \
|
|
1013
|
+
&& (st_a).slab_dims[0] == (st_b).slab_dims[0] \
|
|
1014
|
+
&& ca_iter_state_next_slab_axes(&(st_a), &(p_a), &(m_a)) \
|
|
1015
|
+
&& ca_iter_state_next_slab_axes(&(st_b), &(p_b), &(m_b)); \
|
|
1016
|
+
ca_iter_state_sync_slab(&(st_a)), \
|
|
1017
|
+
ca_iter_state_sync_slab(&(st_b)) )
|
|
1018
|
+
|
|
918
1019
|
/* ---- Phase D: per-data_type reduction macro suite ----------------------- */
|
|
919
1020
|
|
|
920
1021
|
/* CA_SLAB_REDUCE_T(T, ...): generic per-data_type slab reduction. T is the
|
|
@@ -1100,8 +1201,7 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
1100
1201
|
*
|
|
1101
1202
|
* PoC (2026-06-12): N=1M f64 sum 906 us -> 116 us (= 7.8x, 68.8 GB/s).
|
|
1102
1203
|
* Parity: ε-close (relative error < 2e-16 for f64 sum), bit-exact
|
|
1103
|
-
* not guaranteed (=
|
|
1104
|
-
* ε-close policy section, SL.1.5).
|
|
1204
|
+
* not guaranteed (= the SIMD license; see guides/devel/11_kernel_iterator.md).
|
|
1105
1205
|
*
|
|
1106
1206
|
* Other state vars referenced inside REDUCE (induction counters
|
|
1107
1207
|
* like `cnt`, position counters like `idx`) are auto-vectorised
|
|
@@ -1217,7 +1317,7 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
1217
1317
|
* EXPR(x) is a function-like macro producing the per-element contribution
|
|
1218
1318
|
* (Pass 1: (double)(x); Pass 2: ((double)(x)-mean)*((double)(x)-mean)).
|
|
1219
1319
|
* Reassoc across the 8 lanes is the same ε-close license as _PLUS_EX
|
|
1220
|
-
* (bit-exact not guaranteed;
|
|
1320
|
+
* (bit-exact not guaranteed; see guides/devel/11_kernel_iterator.md).
|
|
1221
1321
|
*
|
|
1222
1322
|
* Only the no-mask + contig branch is 8-way; masked / non-contig
|
|
1223
1323
|
* branches stay single-accumulator (not the hot path). Position
|
data/ext/ca_obj_array.c
CHANGED
|
@@ -825,26 +825,17 @@ rb_ca_s_allocate (VALUE klass)
|
|
|
825
825
|
return TypedData_Make_Struct(klass, CArray, &carray_data_type, ca);
|
|
826
826
|
}
|
|
827
827
|
|
|
828
|
-
/*
|
|
828
|
+
/* Reads the (data_type, dim, bytes: nil) argument list that CArray.new
|
|
829
|
+
and CArray.__empty__ share. The two differ only in whether the buffer
|
|
830
|
+
is filled, so the rule for reading their arguments -- the optional
|
|
831
|
+
bytes for a fixlen, the refusal of a Class, the guess of the data type,
|
|
832
|
+
the demand that dim be an Array -- is written once here. */
|
|
829
833
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
The byte size of each element for the fixed length data type
|
|
834
|
-
(<code>data_type == CA_FIXLEN</code>) is specified optional argument
|
|
835
|
-
<i>bytes</i>. Otherwise, this optional argument has no
|
|
836
|
-
effect. If the block is given, the new CArray
|
|
837
|
-
object will be initialized by the value returned from the block.
|
|
838
|
-
*/
|
|
839
|
-
|
|
840
|
-
static VALUE
|
|
841
|
-
rb_ca_initialize (int argc, VALUE *argv, VALUE self)
|
|
834
|
+
static void
|
|
835
|
+
ca_scan_construct_args (int argc, VALUE *argv, int8_t *data_type,
|
|
836
|
+
ca_size_t *bytes, int8_t *ndim, ca_size_t *dim)
|
|
842
837
|
{
|
|
843
838
|
volatile VALUE rtype, rdim, ropt, rbytes = Qnil;
|
|
844
|
-
CArray *ca;
|
|
845
|
-
int8_t data_type, ndim;
|
|
846
|
-
ca_size_t dim[CA_RANK_MAX];
|
|
847
|
-
ca_size_t bytes;
|
|
848
839
|
int8_t i;
|
|
849
840
|
|
|
850
841
|
rb_scan_args(argc, argv, "21", (VALUE *)&rtype, (VALUE *) &rdim, (VALUE *) &ropt);
|
|
@@ -863,13 +854,36 @@ rb_ca_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
863
854
|
rtype, rtype, rtype);
|
|
864
855
|
}
|
|
865
856
|
|
|
866
|
-
rb_ca_guess_type_and_bytes(rtype, rbytes,
|
|
857
|
+
rb_ca_guess_type_and_bytes(rtype, rbytes, data_type, bytes);
|
|
867
858
|
|
|
868
859
|
Check_Type(rdim, T_ARRAY);
|
|
869
|
-
ndim = RARRAY_LEN(rdim);
|
|
870
|
-
for (i=0; i
|
|
860
|
+
*ndim = RARRAY_LEN(rdim);
|
|
861
|
+
for (i=0; i<*ndim; i++) {
|
|
871
862
|
dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
872
863
|
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/* @overload initialize(data_type, dim, bytes=0) { ... }
|
|
867
|
+
|
|
868
|
+
Constructs a new CArray object of <i>data_type</i>, which has the
|
|
869
|
+
ndim and the dimensions specified by an <code>Array</code> of
|
|
870
|
+
<code>Integer</code> or an argument list of <code>Integer</code>.
|
|
871
|
+
The byte size of each element for the fixed length data type
|
|
872
|
+
(<code>data_type == CA_FIXLEN</code>) is specified optional argument
|
|
873
|
+
<i>bytes</i>. Otherwise, this optional argument has no
|
|
874
|
+
effect. If the block is given, the new CArray
|
|
875
|
+
object will be initialized by the value returned from the block.
|
|
876
|
+
*/
|
|
877
|
+
|
|
878
|
+
static VALUE
|
|
879
|
+
rb_ca_initialize (int argc, VALUE *argv, VALUE self)
|
|
880
|
+
{
|
|
881
|
+
CArray *ca;
|
|
882
|
+
int8_t data_type, ndim;
|
|
883
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
884
|
+
ca_size_t bytes;
|
|
885
|
+
|
|
886
|
+
ca_scan_construct_args(argc, argv, &data_type, &bytes, &ndim, dim);
|
|
873
887
|
|
|
874
888
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
875
889
|
if ( ca_func[CA_OBJ_ARRAY].pool_init ) {
|
|
@@ -1438,6 +1452,33 @@ rb_ca_s_alloc_uninit (VALUE klass, VALUE rtype, VALUE rshape)
|
|
|
1438
1452
|
return rb_carray_new(data_type, ndim, dim, bytes, NULL);
|
|
1439
1453
|
}
|
|
1440
1454
|
|
|
1455
|
+
/* Internal primitive behind CArray.empty(data_type, dim, bytes: nil) in
|
|
1456
|
+
lib/carray/construct.rb, which also routes the compatibility spelling
|
|
1457
|
+
CArray.empty(*shape). It is CArray.new with the fill left out: the
|
|
1458
|
+
arguments are read by the same function, and the buffer comes from
|
|
1459
|
+
rb_carray_new (= no MEMZERO) rather than rb_carray_new_safe. A block
|
|
1460
|
+
is refused -- filling is what CArray.new is for. CA_OBJECT still
|
|
1461
|
+
falls through to the zero-VALUE init inside carray_setup_i (= required
|
|
1462
|
+
for GC), so any data_type is safe to ask for. */
|
|
1463
|
+
|
|
1464
|
+
static VALUE
|
|
1465
|
+
rb_ca_s_empty (int argc, VALUE *argv, VALUE klass)
|
|
1466
|
+
{
|
|
1467
|
+
int8_t data_type, ndim;
|
|
1468
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
1469
|
+
ca_size_t bytes;
|
|
1470
|
+
|
|
1471
|
+
if ( rb_block_given_p() ) {
|
|
1472
|
+
rb_raise(rb_eArgError,
|
|
1473
|
+
"CArray.empty does not take a block "
|
|
1474
|
+
"(its contents are left undefined); use CArray.new to fill.");
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
ca_scan_construct_args(argc, argv, &data_type, &bytes, &ndim, dim);
|
|
1478
|
+
|
|
1479
|
+
return rb_carray_new(data_type, ndim, dim, bytes, NULL);
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1441
1482
|
void
|
|
1442
1483
|
Init_ca_obj_array (void)
|
|
1443
1484
|
{
|
|
@@ -1449,6 +1490,7 @@ Init_ca_obj_array (void)
|
|
|
1449
1490
|
rb_define_method(rb_cCArray, "initialize", rb_ca_initialize, -1);
|
|
1450
1491
|
rb_define_singleton_method(rb_cCArray, "__alloc_uninit__",
|
|
1451
1492
|
rb_ca_s_alloc_uninit, 2);
|
|
1493
|
+
rb_define_singleton_method(rb_cCArray, "__empty__", rb_ca_s_empty, -1);
|
|
1452
1494
|
|
|
1453
1495
|
rb_define_singleton_method(rb_cCArray, "fixlen", rb_ca_s_fixlen, -1);
|
|
1454
1496
|
rb_define_singleton_method(rb_cCArray, "boolean", rb_ca_s_boolean, -1);
|
data/ext/ca_obj_bincmp.c
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
ca_bincmp_kernel_lookup from ca_bincmp_dispatch.h.
|
|
10
10
|
|
|
11
11
|
Dispatch by data_type:
|
|
12
|
-
numeric (i8..f64, +complex) -> ca_bincmp_<op>_<
|
|
12
|
+
numeric (i8..f64, +complex) -> ca_bincmp_<op>_<type> kernel
|
|
13
13
|
boolean / fixlen / object -> not implemented (raise)
|
|
14
14
|
|
|
15
15
|
CAREFUL: the binop in-place trick (= pull left into the output
|
|
@@ -60,6 +60,12 @@ typedef struct CABinCmp {
|
|
|
60
60
|
CArray *parent; /* = left */
|
|
61
61
|
uint32_t attach;
|
|
62
62
|
uint8_t nosync;
|
|
63
|
+
/* ---- CAMultiParent conformance (CA_FLAG_MULTI_PARENTS): n_parents and
|
|
64
|
+
parents[] sit immediately after the CAView header, as carray.h's
|
|
65
|
+
layout convention requires, so ca_has_mask can fold over both
|
|
66
|
+
operands and build the mask on demand instead of at setup. ---- */
|
|
67
|
+
int32_t n_parents; /* always 2 */
|
|
68
|
+
CArray **parents; /* = &operands[0]; no separate allocation */
|
|
63
69
|
/* CABinCmp-specific tail */
|
|
64
70
|
CArray *right;
|
|
65
71
|
uint16_t op_id;
|
|
@@ -72,6 +78,7 @@ typedef struct CABinCmp {
|
|
|
72
78
|
`eps` name is retained to keep the
|
|
73
79
|
`__eps__` Ruby accessor stable across
|
|
74
80
|
the dual purpose. */
|
|
81
|
+
CArray *operands[2]; /* {left, right}; what parents points at */
|
|
75
82
|
} CABinCmp;
|
|
76
83
|
|
|
77
84
|
static size_t
|
|
@@ -119,7 +126,7 @@ ca_bincmp_setup (CABinCmp *ca, CArray *left, CArray *right, uint16_t op_id,
|
|
|
119
126
|
{
|
|
120
127
|
ca->obj_type = CA_OBJ_BINCMP;
|
|
121
128
|
ca->data_type = CA_BOOLEAN; /* output is always boolean */
|
|
122
|
-
ca->flags = CA_FLAG_READ_ONLY;
|
|
129
|
+
ca->flags = CA_FLAG_READ_ONLY | CA_FLAG_MULTI_PARENTS;
|
|
123
130
|
ca->ndim = left->ndim;
|
|
124
131
|
ca->bytes = 1; /* boolean8_t */
|
|
125
132
|
ca->elements = left->elements;
|
|
@@ -137,12 +144,16 @@ ca_bincmp_setup (CABinCmp *ca, CArray *left, CArray *right, uint16_t op_id,
|
|
|
137
144
|
/* Builder has already cast both operands to common data_type. */
|
|
138
145
|
ca->common_dt = left->data_type;
|
|
139
146
|
ca->eps = eps;
|
|
147
|
+
ca->operands[0] = left;
|
|
148
|
+
ca->operands[1] = right;
|
|
149
|
+
ca->parents = ca->operands;
|
|
150
|
+
ca->n_parents = 2;
|
|
140
151
|
|
|
141
152
|
memcpy(ca->dim, left->dim, left->ndim * sizeof(ca_size_t));
|
|
142
153
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
/* The mask is NOT built here. ca_has_mask folds over parents[] for a
|
|
155
|
+
multi-parent view and creates it on demand, so an expression whose mask
|
|
156
|
+
nobody reads never allocates one. */
|
|
146
157
|
|
|
147
158
|
if ( ca_is_scalar(left) && ca_is_scalar(right) ) {
|
|
148
159
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -294,7 +305,9 @@ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
294
305
|
int8_t k;
|
|
295
306
|
void *left_scratch, *right_scratch;
|
|
296
307
|
ca_size_t operand_bytes;
|
|
308
|
+
ca_size_t operand_strides[CA_RANK_MAX];
|
|
297
309
|
ca_size_t right_step;
|
|
310
|
+
int is_contig;
|
|
298
311
|
int left_is_inplace = 0; /* skip release for leaf-opt path */
|
|
299
312
|
int right_is_inplace = 0;
|
|
300
313
|
|
|
@@ -308,10 +321,33 @@ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
308
321
|
|
|
309
322
|
operand_bytes = ca_sizeof[bc->common_dt];
|
|
310
323
|
|
|
324
|
+
/* An operand cell is operand_bytes wide where this view's is one byte
|
|
325
|
+
(CA_BOOLEAN), so the caller's strides cannot be handed to the operand
|
|
326
|
+
pull the way a binop hands them on -- they have to be restated at the
|
|
327
|
+
operand's cell size. strides[k] / bytes is the index step, which is
|
|
328
|
+
what the two spaces share.
|
|
329
|
+
|
|
330
|
+
is_contig says the caller asked for the row-major slab that xfer_all
|
|
331
|
+
and attach send. Only then does an operand's own buffer hold the
|
|
332
|
+
wanted cells in the packed order the kernel reads them in, so it is
|
|
333
|
+
also the only case the leaf in-place path is good for. */
|
|
334
|
+
{
|
|
335
|
+
ca_size_t native = bc->bytes;
|
|
336
|
+
is_contig = 1;
|
|
337
|
+
for ( k = bc->ndim - 1; k >= 0; k-- ) {
|
|
338
|
+
operand_strides[k] = strides[k] / bc->bytes * operand_bytes;
|
|
339
|
+
if ( strides[k] != native ) {
|
|
340
|
+
is_contig = 0;
|
|
341
|
+
}
|
|
342
|
+
native *= bc->dim[k];
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
311
346
|
/* === 1. pull LEFT (leaf in-place read or arena scratch) === */
|
|
312
347
|
{
|
|
313
348
|
char *left_inplace = NULL;
|
|
314
|
-
if (
|
|
349
|
+
if ( is_contig &&
|
|
350
|
+
ca_bincmp_try_leaf_inplace(bc->parent, bc->common_dt,
|
|
315
351
|
starts, counts, operand_bytes,
|
|
316
352
|
&left_inplace) ) {
|
|
317
353
|
/* Leaf-opt path: use parent->ptr + byte_offset directly. */
|
|
@@ -320,15 +356,11 @@ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
320
356
|
ca_bincmp_leaf_inplace_count++;
|
|
321
357
|
}
|
|
322
358
|
else {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
left_strides[k] = s;
|
|
327
|
-
s *= counts[k];
|
|
328
|
-
}
|
|
329
|
-
left_scratch = ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
359
|
+
left_scratch = ( bc->common_dt == CA_OBJECT )
|
|
360
|
+
? ca_lazy_arena_acquire_object(slab_n)
|
|
361
|
+
: ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
330
362
|
ca_bincmp_scratch_acquire_count++;
|
|
331
|
-
ca_xfer_stride(bc->parent, starts, counts,
|
|
363
|
+
ca_xfer_stride(bc->parent, starts, counts, operand_strides, left_scratch,
|
|
332
364
|
CA_XFER_GET);
|
|
333
365
|
}
|
|
334
366
|
}
|
|
@@ -355,7 +387,9 @@ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
355
387
|
else {
|
|
356
388
|
ca_size_t one_strides[CA_RANK_MAX];
|
|
357
389
|
for ( k = 0; k < bc->right->ndim; k++ ) one_strides[k] = operand_bytes;
|
|
358
|
-
right_scratch =
|
|
390
|
+
right_scratch = ( bc->common_dt == CA_OBJECT )
|
|
391
|
+
? ca_lazy_arena_acquire_object(1)
|
|
392
|
+
: ca_lazy_arena_acquire(operand_bytes);
|
|
359
393
|
ca_bincmp_scratch_acquire_count++;
|
|
360
394
|
ca_xfer_stride(bc->right, one_starts, one_counts, one_strides,
|
|
361
395
|
right_scratch, CA_XFER_GET);
|
|
@@ -365,7 +399,8 @@ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
365
399
|
else {
|
|
366
400
|
/* Same-shape right: full slab pull or leaf-opt. */
|
|
367
401
|
char *right_inplace = NULL;
|
|
368
|
-
if (
|
|
402
|
+
if ( is_contig &&
|
|
403
|
+
ca_bincmp_try_leaf_inplace(bc->right, bc->common_dt,
|
|
369
404
|
starts, counts, operand_bytes,
|
|
370
405
|
&right_inplace) ) {
|
|
371
406
|
right_scratch = right_inplace;
|
|
@@ -373,15 +408,11 @@ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
373
408
|
ca_bincmp_leaf_inplace_count++;
|
|
374
409
|
}
|
|
375
410
|
else {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
right_strides[k] = s;
|
|
380
|
-
s *= counts[k];
|
|
381
|
-
}
|
|
382
|
-
right_scratch = ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
411
|
+
right_scratch = ( bc->common_dt == CA_OBJECT )
|
|
412
|
+
? ca_lazy_arena_acquire_object(slab_n)
|
|
413
|
+
: ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
383
414
|
ca_bincmp_scratch_acquire_count++;
|
|
384
|
-
ca_xfer_stride(bc->right, starts, counts,
|
|
415
|
+
ca_xfer_stride(bc->right, starts, counts, operand_strides, right_scratch,
|
|
385
416
|
CA_XFER_GET);
|
|
386
417
|
}
|
|
387
418
|
right_step = 1;
|
|
@@ -644,10 +675,9 @@ rb_ca_bincmp_build (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
|
|
|
644
675
|
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
645
676
|
}
|
|
646
677
|
else {
|
|
678
|
+
/* Unreachable from Ruby; see the note in ca_obj_binop.c. */
|
|
647
679
|
rb_raise(rb_eArgError,
|
|
648
|
-
"CABinCmp:
|
|
649
|
-
"ndim size-1 broadcast is supported; cross-ndim "
|
|
650
|
-
"promotion is not adopted in CArray",
|
|
680
|
+
"CABinCmp: element count mismatch (%lld vs %lld)",
|
|
651
681
|
(long long) l->elements, (long long) r->elements);
|
|
652
682
|
}
|
|
653
683
|
}
|