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
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
carray_bincount.c — dedicated bincount kernels (count-only + weighted)
|
|
4
|
+
|
|
5
|
+
Tight per-element scatter into a pre-sized 1-D output buffer. The
|
|
6
|
+
inner loop reads labels in their native integer dtype (no cast to
|
|
7
|
+
int64), skips per-iteration bounds checking (caller validates label
|
|
8
|
+
range), and emits the output dtype directly.
|
|
9
|
+
|
|
10
|
+
Output dtype:
|
|
11
|
+
- count-only: UInt32 if length < 2^32, else UInt64.
|
|
12
|
+
- weighted: weights.data_type.
|
|
13
|
+
|
|
14
|
+
Mask: a masked label is skipped; for the weighted kernel a masked
|
|
15
|
+
weight is also skipped (its label contributes 0).
|
|
16
|
+
|
|
17
|
+
Caller contract (= lib/carray/methods/bincount.rb's CArray#bincount):
|
|
18
|
+
- self is integer dtype.
|
|
19
|
+
- length is the output size, pre-sized to max(length, label_max+1)
|
|
20
|
+
with label_min >= 0 already verified.
|
|
21
|
+
|
|
22
|
+
Public Ruby surface is CArray#bincount(weights:, length:) in
|
|
23
|
+
lib/carray/methods/bincount.rb; this file provides the private
|
|
24
|
+
kernels __bincount_count__(length) and
|
|
25
|
+
__bincount_weighted__(weights, length).
|
|
26
|
+
|
|
27
|
+
Design: devel/PROPOSAL_BINCOUNT_DEDICATED_KERNEL.md.
|
|
28
|
+
|
|
29
|
+
--------------------------------------------------------------------------- */
|
|
30
|
+
|
|
31
|
+
#include "carray.h"
|
|
32
|
+
|
|
33
|
+
/* Tight inner loop: 2 mask-aware variants × 8 label dtypes × 2 output
|
|
34
|
+
dtypes = 32 specializations. Generated via macro expansion.
|
|
35
|
+
|
|
36
|
+
Layout:
|
|
37
|
+
COUNT_KERNEL(LABEL_T, OUT_T)
|
|
38
|
+
no-mask path: for i; out[label[i]]++
|
|
39
|
+
label-mask path: for i; if (mlabel[i]) continue; out[label[i]]++
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
#define COUNT_KERNEL(LABEL_T, OUT_T) do { \
|
|
43
|
+
const LABEL_T *lp = (const LABEL_T *) cl->ptr; \
|
|
44
|
+
OUT_T *op = (OUT_T *) co->ptr; \
|
|
45
|
+
if ( mlabel ) { \
|
|
46
|
+
for (i = 0; i < n; i++) { \
|
|
47
|
+
if ( mlabel[i] ) continue; \
|
|
48
|
+
op[(size_t) lp[i]]++; \
|
|
49
|
+
} \
|
|
50
|
+
} \
|
|
51
|
+
else { \
|
|
52
|
+
for (i = 0; i < n; i++) { \
|
|
53
|
+
op[(size_t) lp[i]]++; \
|
|
54
|
+
} \
|
|
55
|
+
} \
|
|
56
|
+
} while (0)
|
|
57
|
+
|
|
58
|
+
#define COUNT_DISPATCH_LABEL(OUT_T) do { \
|
|
59
|
+
switch ( cl->data_type ) { \
|
|
60
|
+
case CA_INT8: COUNT_KERNEL(int8_t, OUT_T); break; \
|
|
61
|
+
case CA_INT16: COUNT_KERNEL(int16_t, OUT_T); break; \
|
|
62
|
+
case CA_INT32: COUNT_KERNEL(int32_t, OUT_T); break; \
|
|
63
|
+
case CA_INT64: COUNT_KERNEL(int64_t, OUT_T); break; \
|
|
64
|
+
case CA_UINT8: COUNT_KERNEL(uint8_t, OUT_T); break; \
|
|
65
|
+
case CA_UINT16: COUNT_KERNEL(uint16_t, OUT_T); break; \
|
|
66
|
+
case CA_UINT32: COUNT_KERNEL(uint32_t, OUT_T); break; \
|
|
67
|
+
case CA_UINT64: COUNT_KERNEL(uint64_t, OUT_T); break; \
|
|
68
|
+
default: \
|
|
69
|
+
rb_raise(rb_eCADataTypeError, \
|
|
70
|
+
"bincount: integer label array required (got %d)", \
|
|
71
|
+
cl->data_type); \
|
|
72
|
+
} \
|
|
73
|
+
} while (0)
|
|
74
|
+
|
|
75
|
+
/* __bincount_count__(length) -- count occurrences of each label in
|
|
76
|
+
self. Allocates a zero-filled UInt32 (or UInt64 if length >= 2^32)
|
|
77
|
+
output of size `length`, then runs the 8-way label dispatch. */
|
|
78
|
+
static VALUE
|
|
79
|
+
rb_ca_bincount_count_kernel (VALUE self, VALUE rlength)
|
|
80
|
+
{
|
|
81
|
+
CArray *cl, *co;
|
|
82
|
+
VALUE vout;
|
|
83
|
+
ca_size_t i, n, length;
|
|
84
|
+
ca_size_t shape_out[1];
|
|
85
|
+
boolean8_t *mlabel;
|
|
86
|
+
int out_type;
|
|
87
|
+
|
|
88
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, cl);
|
|
89
|
+
length = (ca_size_t) NUM2SIZET(rlength);
|
|
90
|
+
if ( length < 0 ) {
|
|
91
|
+
rb_raise(rb_eArgError, "bincount: length must be non-negative");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Output dtype: UInt32 default; UInt64 if length doesn't fit. */
|
|
95
|
+
out_type = (length > 0xFFFFFFFFLL) ? CA_UINT64 : CA_UINT32;
|
|
96
|
+
shape_out[0] = length;
|
|
97
|
+
vout = rb_carray_new(out_type, 1, shape_out, 0, NULL);
|
|
98
|
+
TypedData_Get_Struct(vout, CArray, &carray_data_type, co);
|
|
99
|
+
|
|
100
|
+
/* Zero-fill output (we own it, just allocated). */
|
|
101
|
+
memset(co->ptr, 0, (size_t) co->bytes * (size_t) co->elements);
|
|
102
|
+
|
|
103
|
+
if ( cl->elements == 0 ) {
|
|
104
|
+
return vout;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
ca_attach(cl);
|
|
108
|
+
n = cl->elements;
|
|
109
|
+
mlabel = cl->mask ? (boolean8_t *) cl->mask->ptr : NULL;
|
|
110
|
+
|
|
111
|
+
if ( out_type == CA_UINT32 ) {
|
|
112
|
+
COUNT_DISPATCH_LABEL(uint32_t);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
COUNT_DISPATCH_LABEL(uint64_t);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
ca_detach(cl);
|
|
119
|
+
|
|
120
|
+
return vout;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
#undef COUNT_KERNEL
|
|
124
|
+
#undef COUNT_DISPATCH_LABEL
|
|
125
|
+
|
|
126
|
+
/* --------------------------------------------------------------- */
|
|
127
|
+
|
|
128
|
+
/* Weighted variant: output dtype = weights dtype.
|
|
129
|
+
Inner: out[label[i]] += weight[i].
|
|
130
|
+
Mask: skip if label[i] masked OR weight[i] masked. */
|
|
131
|
+
|
|
132
|
+
#define WEIGHTED_KERNEL(LABEL_T, W_T) do { \
|
|
133
|
+
const LABEL_T *lp = (const LABEL_T *) cl->ptr; \
|
|
134
|
+
const W_T *wp = (const W_T *) cw->ptr; \
|
|
135
|
+
W_T *op = (W_T *) co->ptr; \
|
|
136
|
+
if ( mlabel && mweight ) { \
|
|
137
|
+
for (i = 0; i < n; i++) { \
|
|
138
|
+
if ( mlabel[i] || mweight[i] ) continue; \
|
|
139
|
+
op[(size_t) lp[i]] += wp[i]; \
|
|
140
|
+
} \
|
|
141
|
+
} \
|
|
142
|
+
else if ( mlabel ) { \
|
|
143
|
+
for (i = 0; i < n; i++) { \
|
|
144
|
+
if ( mlabel[i] ) continue; \
|
|
145
|
+
op[(size_t) lp[i]] += wp[i]; \
|
|
146
|
+
} \
|
|
147
|
+
} \
|
|
148
|
+
else if ( mweight ) { \
|
|
149
|
+
for (i = 0; i < n; i++) { \
|
|
150
|
+
if ( mweight[i] ) continue; \
|
|
151
|
+
op[(size_t) lp[i]] += wp[i]; \
|
|
152
|
+
} \
|
|
153
|
+
} \
|
|
154
|
+
else { \
|
|
155
|
+
for (i = 0; i < n; i++) { \
|
|
156
|
+
op[(size_t) lp[i]] += wp[i]; \
|
|
157
|
+
} \
|
|
158
|
+
} \
|
|
159
|
+
} while (0)
|
|
160
|
+
|
|
161
|
+
#define WEIGHTED_DISPATCH_LABEL(W_T) do { \
|
|
162
|
+
switch ( cl->data_type ) { \
|
|
163
|
+
case CA_INT8: WEIGHTED_KERNEL(int8_t, W_T); break; \
|
|
164
|
+
case CA_INT16: WEIGHTED_KERNEL(int16_t, W_T); break; \
|
|
165
|
+
case CA_INT32: WEIGHTED_KERNEL(int32_t, W_T); break; \
|
|
166
|
+
case CA_INT64: WEIGHTED_KERNEL(int64_t, W_T); break; \
|
|
167
|
+
case CA_UINT8: WEIGHTED_KERNEL(uint8_t, W_T); break; \
|
|
168
|
+
case CA_UINT16: WEIGHTED_KERNEL(uint16_t, W_T); break; \
|
|
169
|
+
case CA_UINT32: WEIGHTED_KERNEL(uint32_t, W_T); break; \
|
|
170
|
+
case CA_UINT64: WEIGHTED_KERNEL(uint64_t, W_T); break; \
|
|
171
|
+
default: \
|
|
172
|
+
rb_raise(rb_eCADataTypeError, \
|
|
173
|
+
"bincount: integer label array required (got %d)", \
|
|
174
|
+
cl->data_type); \
|
|
175
|
+
} \
|
|
176
|
+
} while (0)
|
|
177
|
+
|
|
178
|
+
/* __bincount_weighted__(weights, length) -- sum `weights[i]` into
|
|
179
|
+
`out[label[i]]`. Allocates a zero-filled output of weights.data_type
|
|
180
|
+
and size `length`, then runs the 8 label × 10 weight dispatch
|
|
181
|
+
(integer + float; the inner WEIGHTED_KERNEL macro branches over the
|
|
182
|
+
four mask combinations). */
|
|
183
|
+
static VALUE
|
|
184
|
+
rb_ca_bincount_weighted_kernel (VALUE self, VALUE rweights, VALUE rlength)
|
|
185
|
+
{
|
|
186
|
+
CArray *cl, *cw, *co;
|
|
187
|
+
VALUE vout;
|
|
188
|
+
ca_size_t i, n, length;
|
|
189
|
+
ca_size_t shape_out[1];
|
|
190
|
+
boolean8_t *mlabel, *mweight;
|
|
191
|
+
int w_type;
|
|
192
|
+
|
|
193
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, cl);
|
|
194
|
+
TypedData_Get_Struct(rweights, CArray, &carray_data_type, cw);
|
|
195
|
+
length = (ca_size_t) NUM2SIZET(rlength);
|
|
196
|
+
if ( length < 0 ) {
|
|
197
|
+
rb_raise(rb_eArgError, "bincount: length must be non-negative");
|
|
198
|
+
}
|
|
199
|
+
if ( cw->elements != cl->elements ) {
|
|
200
|
+
rb_raise(rb_eArgError,
|
|
201
|
+
"bincount: weights length (%lld) doesn't match labels length (%lld)",
|
|
202
|
+
(long long) cw->elements, (long long) cl->elements);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
w_type = cw->data_type;
|
|
206
|
+
shape_out[0] = length;
|
|
207
|
+
vout = rb_carray_new(w_type, 1, shape_out, 0, NULL);
|
|
208
|
+
TypedData_Get_Struct(vout, CArray, &carray_data_type, co);
|
|
209
|
+
|
|
210
|
+
memset(co->ptr, 0, (size_t) co->bytes * (size_t) co->elements);
|
|
211
|
+
|
|
212
|
+
if ( cl->elements == 0 ) {
|
|
213
|
+
return vout;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
ca_attach_n(2, cl, cw);
|
|
217
|
+
n = cl->elements;
|
|
218
|
+
mlabel = cl->mask ? (boolean8_t *) cl->mask->ptr : NULL;
|
|
219
|
+
mweight = cw->mask ? (boolean8_t *) cw->mask->ptr : NULL;
|
|
220
|
+
|
|
221
|
+
switch ( w_type ) {
|
|
222
|
+
case CA_FLOAT64: WEIGHTED_DISPATCH_LABEL(double); break;
|
|
223
|
+
case CA_FLOAT32: WEIGHTED_DISPATCH_LABEL(float); break;
|
|
224
|
+
case CA_INT64: WEIGHTED_DISPATCH_LABEL(int64_t); break;
|
|
225
|
+
case CA_INT32: WEIGHTED_DISPATCH_LABEL(int32_t); break;
|
|
226
|
+
case CA_INT16: WEIGHTED_DISPATCH_LABEL(int16_t); break;
|
|
227
|
+
case CA_INT8: WEIGHTED_DISPATCH_LABEL(int8_t); break;
|
|
228
|
+
case CA_UINT64: WEIGHTED_DISPATCH_LABEL(uint64_t); break;
|
|
229
|
+
case CA_UINT32: WEIGHTED_DISPATCH_LABEL(uint32_t); break;
|
|
230
|
+
case CA_UINT16: WEIGHTED_DISPATCH_LABEL(uint16_t); break;
|
|
231
|
+
case CA_UINT8: WEIGHTED_DISPATCH_LABEL(uint8_t); break;
|
|
232
|
+
default:
|
|
233
|
+
ca_detach_n(2, cl, cw);
|
|
234
|
+
rb_raise(rb_eCADataTypeError,
|
|
235
|
+
"bincount: weights must be numeric (got %d)", w_type);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
ca_detach_n(2, cl, cw);
|
|
239
|
+
|
|
240
|
+
return vout;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#undef WEIGHTED_KERNEL
|
|
244
|
+
#undef WEIGHTED_DISPATCH_LABEL
|
|
245
|
+
|
|
246
|
+
/* --------------------------------------------------------------- */
|
|
247
|
+
|
|
248
|
+
void
|
|
249
|
+
Init_carray_bincount (void)
|
|
250
|
+
{
|
|
251
|
+
rb_define_private_method(rb_cCArray, "__bincount_count__",
|
|
252
|
+
rb_ca_bincount_count_kernel, 1);
|
|
253
|
+
rb_define_private_method(rb_cCArray, "__bincount_weighted__",
|
|
254
|
+
rb_ca_bincount_weighted_kernel, 2);
|
|
255
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
Implicit broadcasting helpers and CArray#broadcast_to.
|
|
4
|
+
|
|
5
|
+
ca_broadcast_view (src, ndim, target_dim)
|
|
6
|
+
Wrap `src` in a CAStride view whose shape is `target_dim`,
|
|
7
|
+
treating size-1 axes of `src` as broadcast (stride 0).
|
|
8
|
+
Returns `src` unchanged when no expansion is needed.
|
|
9
|
+
Called by ca_broadcast_pair below and by the binop dispatcher
|
|
10
|
+
in ext/ca_obj_binop.c.
|
|
11
|
+
|
|
12
|
+
ca_broadcast_pair (&self, &other)
|
|
13
|
+
Two-sided expansion for binary ops (case A only: same ndim,
|
|
14
|
+
size-1 axes broadcast pairwise). Leaves both operands
|
|
15
|
+
unchanged when shapes are already equal or when they are
|
|
16
|
+
incompatible (the caller's existing elements-mismatch raise
|
|
17
|
+
path then handles the error). Called by carray_cast.c's
|
|
18
|
+
coercion path and by the binop dispatcher.
|
|
19
|
+
|
|
20
|
+
rb_ca_broadcast_to -- backs the public CArray#broadcast_to method
|
|
21
|
+
(right-to-left axis pairing; see the docstring at the function).
|
|
22
|
+
|
|
23
|
+
Case B (cross-ndim dim-prepending) is not handled by the implicit
|
|
24
|
+
helpers; users with cross-ndim operands keep using the explicit :*
|
|
25
|
+
form or #broadcast_to (which does accept cross-ndim with target axes
|
|
26
|
+
pinned to size 1). See PROPOSAL_BROADCASTING_AND_UNBOUND.md.
|
|
27
|
+
|
|
28
|
+
---------------------------------------------------------------------------- */
|
|
29
|
+
|
|
30
|
+
#include "carray.h"
|
|
31
|
+
|
|
32
|
+
/* Build a CAStride view of `src` with shape `target_dim`. For each
|
|
33
|
+
axis where src.dim[i] == target_dim[i], inherit the row-major byte
|
|
34
|
+
stride; for src.dim[i] == 1 and target_dim[i] > 1, use stride 0.
|
|
35
|
+
Otherwise, raise. If no axis needs expansion, return src as-is. */
|
|
36
|
+
VALUE
|
|
37
|
+
ca_broadcast_view (VALUE src, int8_t ndim, ca_size_t *target_dim)
|
|
38
|
+
{
|
|
39
|
+
CArray *cs;
|
|
40
|
+
ca_size_t src_strides[CA_RANK_MAX];
|
|
41
|
+
ca_size_t new_strides[CA_RANK_MAX];
|
|
42
|
+
ca_size_t s;
|
|
43
|
+
int needs_broadcast = 0;
|
|
44
|
+
int i;
|
|
45
|
+
CAStride *view;
|
|
46
|
+
volatile VALUE obj;
|
|
47
|
+
|
|
48
|
+
TypedData_Get_Struct(src, CArray, &carray_data_type, cs);
|
|
49
|
+
|
|
50
|
+
if (cs->ndim != ndim) {
|
|
51
|
+
rb_raise(rb_eRuntimeError,
|
|
52
|
+
"broadcast: ndim mismatch (%d vs %d)",
|
|
53
|
+
(int) cs->ndim, (int) ndim);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Row-major byte strides for src treated as contiguous. When src is
|
|
57
|
+
itself a CAStride, the compose-fold path at attach time collapses
|
|
58
|
+
the chain to root, so passing parent-relative row-major strides
|
|
59
|
+
is correct. */
|
|
60
|
+
s = cs->bytes;
|
|
61
|
+
for (i = ndim - 1; i >= 0; i--) {
|
|
62
|
+
src_strides[i] = s;
|
|
63
|
+
s *= cs->dim[i];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (i = 0; i < ndim; i++) {
|
|
67
|
+
if (cs->dim[i] == target_dim[i]) {
|
|
68
|
+
new_strides[i] = src_strides[i];
|
|
69
|
+
}
|
|
70
|
+
else if (cs->dim[i] == 1) {
|
|
71
|
+
new_strides[i] = 0;
|
|
72
|
+
needs_broadcast = 1;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
rb_raise(rb_eRuntimeError,
|
|
76
|
+
"broadcast: cannot broadcast axis %d (%lld vs %lld)",
|
|
77
|
+
i, (long long) cs->dim[i], (long long) target_dim[i]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!needs_broadcast) return src;
|
|
82
|
+
|
|
83
|
+
view = ca_stride_new(CA_OBJ_STRIDE, cs,
|
|
84
|
+
cs->data_type, cs->bytes,
|
|
85
|
+
ndim, target_dim, new_strides, 0);
|
|
86
|
+
ca_set_flag(view, CA_FLAG_READ_ONLY);
|
|
87
|
+
if (view->mask) {
|
|
88
|
+
ca_set_flag(view->mask, CA_FLAG_READ_ONLY);
|
|
89
|
+
}
|
|
90
|
+
obj = ca_wrap_struct(view);
|
|
91
|
+
rb_ca_set_parent(obj, src);
|
|
92
|
+
return obj;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Two-sided broadcast for binary ops (case A only). When both
|
|
96
|
+
operands are non-scalar with equal ndim and at least one axis pair
|
|
97
|
+
is (1, N) / (N, 1) / (1, 1), wrap each in a CAStride with stride-0
|
|
98
|
+
axes so the downstream iterator sees matched shapes. If shapes are
|
|
99
|
+
pairwise equal, no-op. If any axis pair is incompatible (neither
|
|
100
|
+
side is 1 nor equal), no-op (caller's existing element-count check
|
|
101
|
+
raises). */
|
|
102
|
+
void
|
|
103
|
+
ca_broadcast_pair (volatile VALUE *self, volatile VALUE *other)
|
|
104
|
+
{
|
|
105
|
+
CArray *ca, *cb;
|
|
106
|
+
ca_size_t target_dim[CA_RANK_MAX];
|
|
107
|
+
int can_broadcast = 1;
|
|
108
|
+
int needs_broadcast = 0;
|
|
109
|
+
int i;
|
|
110
|
+
|
|
111
|
+
TypedData_Get_Struct(*self, CArray, &carray_data_type, ca);
|
|
112
|
+
TypedData_Get_Struct(*other, CArray, &carray_data_type, cb);
|
|
113
|
+
|
|
114
|
+
if (ca_is_scalar(ca) || ca_is_scalar(cb)) return;
|
|
115
|
+
if (ca->ndim != cb->ndim) return;
|
|
116
|
+
if (ca->ndim == 0) return;
|
|
117
|
+
|
|
118
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
119
|
+
if (ca->dim[i] == cb->dim[i]) {
|
|
120
|
+
target_dim[i] = ca->dim[i];
|
|
121
|
+
}
|
|
122
|
+
else if (ca->dim[i] == 1) {
|
|
123
|
+
target_dim[i] = cb->dim[i];
|
|
124
|
+
needs_broadcast = 1;
|
|
125
|
+
}
|
|
126
|
+
else if (cb->dim[i] == 1) {
|
|
127
|
+
target_dim[i] = ca->dim[i];
|
|
128
|
+
needs_broadcast = 1;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
can_broadcast = 0;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!can_broadcast || !needs_broadcast) return;
|
|
137
|
+
|
|
138
|
+
*self = ca_broadcast_view(*self, ca->ndim, target_dim);
|
|
139
|
+
*other = ca_broadcast_view(*other, ca->ndim, target_dim);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* CArray#broadcast_to(*newdim) -- pairs axes right-to-left:
|
|
143
|
+
- source axis == target axis -> data axis (inherit stride)
|
|
144
|
+
- target axis == 1 -> size-1 collapse, source consumed
|
|
145
|
+
only when it is also 1
|
|
146
|
+
- source axis == 1 -> broadcast (stride 0, source
|
|
147
|
+
consumed)
|
|
148
|
+
- source exhausted, target 1 -> insert size-1 axis
|
|
149
|
+
- otherwise -> RuntimeError
|
|
150
|
+
|
|
151
|
+
Intentionally conservative on cross-ndim: prepended axes are only
|
|
152
|
+
inserted as size-1. Target > 1 on a prepended axis raises, in
|
|
153
|
+
keeping with PROPOSAL_BROADCASTING_AND_UNBOUND.md's strict-ndim
|
|
154
|
+
policy.
|
|
155
|
+
|
|
156
|
+
Result is tagged CA_OBJ_REPEAT (CARepeat) rather than plain CAStride
|
|
157
|
+
so introspection (`view.class`) surfaces the broadcast intent. */
|
|
158
|
+
|
|
159
|
+
static VALUE
|
|
160
|
+
rb_ca_broadcast_to (int argc, VALUE *argv, VALUE self)
|
|
161
|
+
{
|
|
162
|
+
CArray *cs;
|
|
163
|
+
ca_size_t target_dim[CA_RANK_MAX];
|
|
164
|
+
ca_size_t new_strides[CA_RANK_MAX];
|
|
165
|
+
ca_size_t src_strides[CA_RANK_MAX];
|
|
166
|
+
ca_size_t s;
|
|
167
|
+
int8_t target_ndim;
|
|
168
|
+
int needs_view = 0;
|
|
169
|
+
int t_idx, s_idx;
|
|
170
|
+
int i;
|
|
171
|
+
CAStride *view;
|
|
172
|
+
volatile VALUE obj;
|
|
173
|
+
|
|
174
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, cs);
|
|
175
|
+
|
|
176
|
+
if (argc < 0 || argc > CA_RANK_MAX) {
|
|
177
|
+
rb_raise(rb_eArgError, "broadcast_to: invalid number of dims (%d)", argc);
|
|
178
|
+
}
|
|
179
|
+
target_ndim = (int8_t) argc;
|
|
180
|
+
|
|
181
|
+
if (target_ndim < cs->ndim) {
|
|
182
|
+
rb_raise(rb_eRuntimeError,
|
|
183
|
+
"broadcast_to: target ndim %d smaller than source ndim %d",
|
|
184
|
+
(int) target_ndim, (int) cs->ndim);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
for (i = 0; i < target_ndim; i++) {
|
|
188
|
+
target_dim[i] = NUM2SIZE(argv[i]);
|
|
189
|
+
if (target_dim[i] < 0) {
|
|
190
|
+
rb_raise(rb_eArgError,
|
|
191
|
+
"broadcast_to: negative dim at axis %d", i);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* CScalar source: build an all-stride-0 CARepeat view of any
|
|
196
|
+
target shape. Generalises the cross-ndim rule, which is strict
|
|
197
|
+
for non-scalar sources (each source axis must pair with a target
|
|
198
|
+
axis); for a scalar the natural extension is "any target shape,
|
|
199
|
+
stride 0 everywhere". */
|
|
200
|
+
if (ca_is_scalar(cs)) {
|
|
201
|
+
for (i = 0; i < target_ndim; i++) {
|
|
202
|
+
new_strides[i] = 0;
|
|
203
|
+
}
|
|
204
|
+
view = ca_stride_new(CA_OBJ_REPEAT, cs,
|
|
205
|
+
cs->data_type, cs->bytes,
|
|
206
|
+
target_ndim, target_dim, new_strides, 0);
|
|
207
|
+
ca_set_flag(view, CA_FLAG_READ_ONLY);
|
|
208
|
+
if (view->mask) {
|
|
209
|
+
ca_set_flag(view->mask, CA_FLAG_READ_ONLY);
|
|
210
|
+
}
|
|
211
|
+
obj = ca_wrap_struct(view);
|
|
212
|
+
rb_ca_set_parent(obj, self);
|
|
213
|
+
return obj;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* Row-major byte strides for source (interpreted as contiguous;
|
|
217
|
+
compose-fold at attach time handles non-contiguous parents). */
|
|
218
|
+
s = cs->bytes;
|
|
219
|
+
for (i = cs->ndim - 1; i >= 0; i--) {
|
|
220
|
+
src_strides[i] = s;
|
|
221
|
+
s *= cs->dim[i];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Pair right-to-left. s_idx tracks the next source axis to be
|
|
225
|
+
consumed; -1 means source is exhausted. */
|
|
226
|
+
t_idx = target_ndim - 1;
|
|
227
|
+
s_idx = cs->ndim - 1;
|
|
228
|
+
|
|
229
|
+
while (t_idx >= 0) {
|
|
230
|
+
ca_size_t dd = target_dim[t_idx];
|
|
231
|
+
ca_size_t sd = (s_idx >= 0) ? cs->dim[s_idx] : -1;
|
|
232
|
+
|
|
233
|
+
if (sd == dd) {
|
|
234
|
+
new_strides[t_idx] = src_strides[s_idx];
|
|
235
|
+
s_idx--;
|
|
236
|
+
}
|
|
237
|
+
else if (dd == 1) {
|
|
238
|
+
new_strides[t_idx] = 0;
|
|
239
|
+
if (sd == 1) s_idx--;
|
|
240
|
+
needs_view = 1;
|
|
241
|
+
}
|
|
242
|
+
else if (sd == 1) {
|
|
243
|
+
new_strides[t_idx] = 0;
|
|
244
|
+
s_idx--;
|
|
245
|
+
needs_view = 1;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
/* sd == -1 (source exhausted) with dd > 1, or sd > 1 with
|
|
249
|
+
dd > 1 and not equal: cannot broadcast. */
|
|
250
|
+
rb_raise(rb_eRuntimeError,
|
|
251
|
+
"broadcast_to: cannot broadcast axis %d "
|
|
252
|
+
"(source %s, target %lld)",
|
|
253
|
+
t_idx,
|
|
254
|
+
(sd < 0 ? "(exhausted)" : "non-1"),
|
|
255
|
+
(long long) dd);
|
|
256
|
+
}
|
|
257
|
+
t_idx--;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (s_idx >= 0) {
|
|
261
|
+
rb_raise(rb_eRuntimeError,
|
|
262
|
+
"broadcast_to: %d source axes left unmatched", s_idx + 1);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!needs_view) return self;
|
|
266
|
+
|
|
267
|
+
view = ca_stride_new(CA_OBJ_REPEAT, cs,
|
|
268
|
+
cs->data_type, cs->bytes,
|
|
269
|
+
target_ndim, target_dim, new_strides, 0);
|
|
270
|
+
ca_set_flag(view, CA_FLAG_READ_ONLY);
|
|
271
|
+
if (view->mask) {
|
|
272
|
+
ca_set_flag(view->mask, CA_FLAG_READ_ONLY);
|
|
273
|
+
}
|
|
274
|
+
obj = ca_wrap_struct(view);
|
|
275
|
+
rb_ca_set_parent(obj, self);
|
|
276
|
+
return obj;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
void
|
|
280
|
+
Init_carray_broadcast (void)
|
|
281
|
+
{
|
|
282
|
+
rb_define_method(rb_cCArray, "broadcast_to", rb_ca_broadcast_to, -1);
|
|
283
|
+
}
|