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,481 @@
|
|
|
1
|
+
# Frequently-used CArray convenience methods kept eager-loaded.
|
|
2
|
+
#
|
|
3
|
+
# Rationale: a method lands here NOT because of its topic / domain (those
|
|
4
|
+
# have their own files such as compose.rb / math.rb / datetime.rb, many of
|
|
5
|
+
# them autoloaded) but because it is reached often enough that the
|
|
6
|
+
# lazy-autoload indirection is not worth it. These methods are NOT
|
|
7
|
+
# load-bearing -- the core works without them; that distinguishes this file
|
|
8
|
+
# from carray/runtime.rb (which holds the support the core depends on).
|
|
9
|
+
#
|
|
10
|
+
# Keep this file small and obvious. If a method is domain-specific or only
|
|
11
|
+
# occasionally used, it belongs in its topic file (autoloaded when possible),
|
|
12
|
+
# not here.
|
|
13
|
+
|
|
14
|
+
class CArray
|
|
15
|
+
|
|
16
|
+
# reshape / flatten / transpose! are defined in C
|
|
17
|
+
# (ext/ca_obj_refer.c and ext/ca_obj_transpose.c). The bare size-1
|
|
18
|
+
# insertion primitive is `__insert_axis_size1__` (C); `insert_axis` below
|
|
19
|
+
# is the user-facing method that owns the name and adds `repeat:`.
|
|
20
|
+
|
|
21
|
+
# @overload insert_axis(*positions, repeat: nil)
|
|
22
|
+
# Returns a view of `self` with one or more new axes inserted,
|
|
23
|
+
# optionally repeating along them.
|
|
24
|
+
#
|
|
25
|
+
# Each entry of `positions` names the source axis the new axis
|
|
26
|
+
# goes *before*. `ndim` (one past the last axis) appends at the
|
|
27
|
+
# end; negative positions count from the end. Repeating the same
|
|
28
|
+
# position inserts several axes before that axis, in argument
|
|
29
|
+
# order. Positions are in the *source* frame, so they do not
|
|
30
|
+
# shift as other axes are inserted (e.g. `insert_axis(0, 1, 2)`
|
|
31
|
+
# puts one axis before each of the first three source axes).
|
|
32
|
+
#
|
|
33
|
+
# Each inserted axis takes one of three forms, chosen by its
|
|
34
|
+
# `repeat` value: `1` (or `nil`) for a plain size-1 axis, an
|
|
35
|
+
# Integer `N > 1` for a read-only bound repeat view, or `:*` for
|
|
36
|
+
# an unbound repeat that binds on assignment. `repeat` is either
|
|
37
|
+
# a single value applied to every inserted axis, or an Array
|
|
38
|
+
# giving one value per position.
|
|
39
|
+
#
|
|
40
|
+
# The everyday way to add an axis is the `:_` / `:*` indexer
|
|
41
|
+
# when the shape is known at the call site; `insert_axis` is for
|
|
42
|
+
# library code that builds the axis list programmatically.
|
|
43
|
+
#
|
|
44
|
+
# @param positions [Array<Integer>] source-frame positions of the
|
|
45
|
+
# new axes.
|
|
46
|
+
# @param repeat [Integer, Symbol, Array, nil] repeat spec applied
|
|
47
|
+
# to each inserted axis.
|
|
48
|
+
# @return [CArray] view with the new axes inserted.
|
|
49
|
+
# @example
|
|
50
|
+
# a = CArray.int32(3, 4).seq
|
|
51
|
+
# a.insert_axis(0) # shape (1, 3, 4)
|
|
52
|
+
# a.insert_axis(1, repeat: 5) # shape (3, 5, 4)
|
|
53
|
+
# a.insert_axis(0, 1, repeat: [:*, 3]) # mixed unbound + bound
|
|
54
|
+
def insert_axis (*positions, repeat: nil)
|
|
55
|
+
flat = positions.flatten
|
|
56
|
+
if flat.empty?
|
|
57
|
+
raise ArgumentError, "insert_axis: at least one position is required"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# No repeat: -> plain size-1 insertion. The source-frame C primitive
|
|
61
|
+
# handles normalization, range check and multiplicity directly.
|
|
62
|
+
return __insert_axis_size1__(*flat) if repeat.nil?
|
|
63
|
+
|
|
64
|
+
# Source frame: each position names the source axis the new axis goes
|
|
65
|
+
# before. Gaps live in [0, ndim] (ndim = append at end); negatives count
|
|
66
|
+
# from the end gap. Duplicates are allowed (several axes before one
|
|
67
|
+
# source axis), kept in argument order.
|
|
68
|
+
gaps = flat.map { |p| CArray.normalize_axis(p, ndim + 1, "insert_axis") }
|
|
69
|
+
|
|
70
|
+
# One repeat value per position, in argument order.
|
|
71
|
+
reps =
|
|
72
|
+
case repeat
|
|
73
|
+
when Array
|
|
74
|
+
unless repeat.length == flat.length
|
|
75
|
+
raise ArgumentError,
|
|
76
|
+
"insert_axis: repeat array length (#{repeat.length}) " \
|
|
77
|
+
"must match number of positions (#{flat.length})"
|
|
78
|
+
end
|
|
79
|
+
repeat
|
|
80
|
+
else
|
|
81
|
+
Array.new(flat.length, repeat)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Validate each value. A positive Integer or :* only; nil is not a
|
|
85
|
+
# valid per-axis repeat.
|
|
86
|
+
reps.each do |r|
|
|
87
|
+
case r
|
|
88
|
+
when Integer
|
|
89
|
+
raise ArgumentError, "insert_axis: repeat count must be >= 1" if r < 1
|
|
90
|
+
when :*
|
|
91
|
+
# ok
|
|
92
|
+
else
|
|
93
|
+
raise ArgumentError,
|
|
94
|
+
"insert_axis: repeat must be a positive Integer or :*, got #{r.inspect}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Final output layout: stable order by (gap, argument index) keeps
|
|
99
|
+
# same-gap axes in argument order; the k-th inserted axis lands at output
|
|
100
|
+
# position gap + k. This output position is only used to drive the
|
|
101
|
+
# output-shaped view constructors (broadcast_to / unbound_repeat); the
|
|
102
|
+
# actual insertion always goes through the source-frame primitive below.
|
|
103
|
+
order = (0...flat.length).sort_by { |i| [gaps[i], i] }
|
|
104
|
+
final = {}
|
|
105
|
+
order.each_with_index { |i, k| final[i] = gaps[i] + k }
|
|
106
|
+
|
|
107
|
+
unbound_args = order.select { |i| reps[i] == :* }
|
|
108
|
+
concrete_args = order.reject { |i| reps[i] == :* } # in output order
|
|
109
|
+
|
|
110
|
+
# Stage 1: insert the concrete (size-1 / bound) axes by their source
|
|
111
|
+
# gaps, then grow the bound ones with broadcast_to.
|
|
112
|
+
inter = self
|
|
113
|
+
unless concrete_args.empty?
|
|
114
|
+
inter = __insert_axis_size1__(*concrete_args.map { |i| gaps[i] })
|
|
115
|
+
if concrete_args.any? { |i| reps[i].is_a?(Integer) && reps[i] > 1 }
|
|
116
|
+
shp = inter.shape
|
|
117
|
+
concrete_args.each do |i|
|
|
118
|
+
r = reps[i]
|
|
119
|
+
next unless r.is_a?(Integer) && r > 1
|
|
120
|
+
# intermediate position = final position minus unbound axes before it
|
|
121
|
+
shp[final[i] - unbound_args.count { |u| final[u] < final[i] }] = r
|
|
122
|
+
end
|
|
123
|
+
inter = inter.broadcast_to(*shp)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
return inter if unbound_args.empty?
|
|
128
|
+
|
|
129
|
+
# Stage 2: add the unbound axes over the final ndim (`:*` at unbound
|
|
130
|
+
# positions, nil consumes one stage-1 axis in order).
|
|
131
|
+
pattern = Array.new(ndim + flat.length, nil)
|
|
132
|
+
unbound_args.each { |i| pattern[final[i]] = :* }
|
|
133
|
+
inter.unbound_repeat(*pattern)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @overload drop_axis
|
|
137
|
+
# Returns a view of `self` with every size-1 axis dropped.
|
|
138
|
+
# @return [CArray] view with reduced `ndim`.
|
|
139
|
+
def drop_axis
|
|
140
|
+
if ndim == 1
|
|
141
|
+
return self[]
|
|
142
|
+
else
|
|
143
|
+
newdim = shape.reject{|x| x == 1 }
|
|
144
|
+
return ( ndim != newdim.size ) ? reshape(*newdim) : self[]
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# @overload address
|
|
149
|
+
# Returns an int32 CArray of the same shape as `self` where each
|
|
150
|
+
# cell holds its row-major flat address.
|
|
151
|
+
# @return [CArray]
|
|
152
|
+
def address
|
|
153
|
+
return CArray.int32(*shape).seq!
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# @overload false
|
|
157
|
+
# Returns a boolean CArray of the same shape as `self` filled
|
|
158
|
+
# with `false`.
|
|
159
|
+
# @return [CArray]
|
|
160
|
+
def false ()
|
|
161
|
+
return template(:boolean)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# @overload true
|
|
165
|
+
# Returns a boolean CArray of the same shape as `self` filled
|
|
166
|
+
# with `true`.
|
|
167
|
+
# @return [CArray]
|
|
168
|
+
def true ()
|
|
169
|
+
return template(:boolean) { 1 }
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Sub-region copy (paste / crop), the old C `ca_paste` / `ca_clip` pair.
|
|
173
|
+
# `clip` is reserved for value clamping (clamp to a min/max range), so
|
|
174
|
+
# the read-out side is `crop`. Kept together as a pair (crop is rare, but paste is reached
|
|
175
|
+
# often -- concatenate / mosaic / resize / bit_string all use it). Both
|
|
176
|
+
# accept negative offsets.
|
|
177
|
+
|
|
178
|
+
# @overload paste(offset, src)
|
|
179
|
+
# Sets `self` at `offset` by copying `src`. Out-of-bounds cells
|
|
180
|
+
# (`src` extending past `self`'s edge or before its origin) are
|
|
181
|
+
# silently dropped via CAWindow's interior-only PUT scatter.
|
|
182
|
+
# @param offset [Array<Integer>] starting indices, length equal
|
|
183
|
+
# to `self.ndim`.
|
|
184
|
+
# @param src [CArray] source array.
|
|
185
|
+
# @return [self]
|
|
186
|
+
# @raise [ArgumentError] when `offset.length != self.ndim`.
|
|
187
|
+
def paste (offset, src)
|
|
188
|
+
raise ArgumentError, "offset length must equal ndim" if offset.length != ndim
|
|
189
|
+
ranges = offset.each_with_index.map { |o, i| o...(o + src.shape[i]) }
|
|
190
|
+
self.window(*ranges)[] = src
|
|
191
|
+
self
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# @overload crop(offset, dst)
|
|
195
|
+
# Reads a `dst.shape`-sized region from `self` starting at
|
|
196
|
+
# `offset` into `dst`. Cells whose read position falls outside
|
|
197
|
+
# `self` leave the corresponding `dst` cells untouched.
|
|
198
|
+
# @param offset [Array<Integer>] source starting indices, length
|
|
199
|
+
# equal to `self.ndim`.
|
|
200
|
+
# @param dst [CArray] destination array; mutated in place.
|
|
201
|
+
# @return [CArray] `dst`.
|
|
202
|
+
# @raise [ArgumentError] when `offset.length != self.ndim`.
|
|
203
|
+
def crop (offset, dst)
|
|
204
|
+
raise ArgumentError, "offset length must equal ndim" if offset.length != ndim
|
|
205
|
+
src_ranges = []
|
|
206
|
+
dst_ranges = []
|
|
207
|
+
ndim.times do |i|
|
|
208
|
+
s_lo = [offset[i], 0].max
|
|
209
|
+
s_hi = [offset[i] + dst.shape[i], shape[i]].min
|
|
210
|
+
return dst if s_lo >= s_hi
|
|
211
|
+
src_ranges << (s_lo...s_hi)
|
|
212
|
+
dst_ranges << ((s_lo - offset[i])...(s_hi - offset[i]))
|
|
213
|
+
end
|
|
214
|
+
dst[*dst_ranges] = self[*src_ranges]
|
|
215
|
+
dst
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# @overload lookup(table, fill_value = nil, lfill: nil, ufill: nil)
|
|
219
|
+
# Returns values gathered from `table` at the indices given by
|
|
220
|
+
# `self`. Equivalent to `table.project(self, lfill, ufill)` with
|
|
221
|
+
# the receiver / first argument swapped so the index reads as
|
|
222
|
+
# the subject. `fill_value` is sugar for symmetric dual-fill;
|
|
223
|
+
# `lfill` / `ufill` override per side (`UNDEF` or `nil` masks
|
|
224
|
+
# that end), following the `project` vocabulary.
|
|
225
|
+
# @param table [CArray] value table indexed by `self`.
|
|
226
|
+
# @param fill_value [Object, nil] symmetric fill for below- and
|
|
227
|
+
# above-range indices.
|
|
228
|
+
# @param lfill [Object, nil] override for below-range fill.
|
|
229
|
+
# @param ufill [Object, nil] override for above-range fill.
|
|
230
|
+
# @return [CArray] gathered values with the shape of `self`.
|
|
231
|
+
def lookup(table, fill_value=nil, lfill: nil, ufill: nil)
|
|
232
|
+
lfill = fill_value if lfill.nil?
|
|
233
|
+
ufill = fill_value if ufill.nil?
|
|
234
|
+
table.project(self, lfill, ufill)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# @overload <=>(other)
|
|
238
|
+
# Returns an element-wise 3-way comparison: `+1` where
|
|
239
|
+
# `self > other`, `-1` where `self < other`, `0` where equal.
|
|
240
|
+
# Output `data_type` is `CA_INT8`.
|
|
241
|
+
# @param other [CArray, Numeric] operand to compare against.
|
|
242
|
+
# @return [CArray]
|
|
243
|
+
def <=> (other)
|
|
244
|
+
(self > other).as_int8 - (self < other).as_int8
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
alias cmp <=>
|
|
248
|
+
|
|
249
|
+
# @overload clip(min, max = nil, fill_value = nil, lfill: nil, ufill: nil)
|
|
250
|
+
# Returns `self` with every element clamped to `[min, max]`.
|
|
251
|
+
#
|
|
252
|
+
# Either bound may be `nil` for a one-sided clip; that side
|
|
253
|
+
# dispatches to the `pmax` / `pmin` binop kernels. When
|
|
254
|
+
# `fill_value` (or `lfill` / `ufill`) is given, out-of-range
|
|
255
|
+
# cells are replaced by the fill instead of clamped -- pass
|
|
256
|
+
# `UNDEF` to mask that end. `fill_value` is sugar for symmetric
|
|
257
|
+
# dual-fill; `lfill` / `ufill` override per side.
|
|
258
|
+
#
|
|
259
|
+
# Boundary is strict `[min, max]`: values equal to a bound
|
|
260
|
+
# remain unchanged in both the clamped and filled variants.
|
|
261
|
+
#
|
|
262
|
+
# @param min [Numeric, nil] lower bound; `nil` for one-sided
|
|
263
|
+
# clip above.
|
|
264
|
+
# @param max [Numeric, nil] upper bound; `nil` for one-sided
|
|
265
|
+
# clip below.
|
|
266
|
+
# @param fill_value [Object, nil] symmetric fill for
|
|
267
|
+
# out-of-range cells.
|
|
268
|
+
# @param lfill [Object, nil] override below-range fill.
|
|
269
|
+
# @param ufill [Object, nil] override above-range fill.
|
|
270
|
+
# @return [CArray] new CArray with clamped or filled values.
|
|
271
|
+
# @raise [ArgumentError] when both `min` and `max` are `nil`.
|
|
272
|
+
# @example
|
|
273
|
+
# a.clip(0, 10) # strict clamp
|
|
274
|
+
# a.clip(0, 10, -1) # both ends -> -1
|
|
275
|
+
# a.clip(0, 10, lfill: UNDEF, ufill: 99) # below masks
|
|
276
|
+
def clip(min, max=nil, fill_value=nil, lfill: nil, ufill: nil)
|
|
277
|
+
if min.nil? && max.nil?
|
|
278
|
+
raise ArgumentError, "clip: at least one of (min, max) must be given"
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# `fill_value` as a single argument is sugar applied to both ends; kwargs override.
|
|
282
|
+
lfill = fill_value if lfill.nil?
|
|
283
|
+
ufill = fill_value if ufill.nil?
|
|
284
|
+
|
|
285
|
+
if lfill.nil? && ufill.nil?
|
|
286
|
+
return __clip_ki__(min, max) if !min.nil? && !max.nil?
|
|
287
|
+
return pmax(min) if max.nil?
|
|
288
|
+
return pmin(max)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
out = self.copy
|
|
292
|
+
out[:lt, min] = lfill unless min.nil? || lfill.nil?
|
|
293
|
+
out[:gt, max] = ufill unless max.nil? || ufill.nil?
|
|
294
|
+
out
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# `contains` was retired in favour of {#is_in} (value-hash membership).
|
|
298
|
+
# `a.contains(v1, v2)` -> `a.is_in([v1, v2])`;
|
|
299
|
+
# `a.contains(v1, v2, axis: k)` -> `a.is_in([v1, v2]).any(axis: k)`.
|
|
300
|
+
# See carray/methods/is_in.rb. Note is_in collapses NaN (a NaN cell is in a
|
|
301
|
+
# set containing NaN), whereas contains (self.eq) never matched NaN.
|
|
302
|
+
|
|
303
|
+
# `windows` (the sliding-window iterator entry) lives in
|
|
304
|
+
# carray/window_iterator.rb, autoloaded on first use.
|
|
305
|
+
|
|
306
|
+
# ---------------------------------------------------------------------------
|
|
307
|
+
# Sequence fill over a range (span / span!) and a linear interval
|
|
308
|
+
# (scale / scale!).
|
|
309
|
+
# ---------------------------------------------------------------------------
|
|
310
|
+
|
|
311
|
+
# @overload span!(range)
|
|
312
|
+
# Sets `self` to a linear sequence over `range`, with the step
|
|
313
|
+
# chosen so that `range.end` (or `range.end` when the range is
|
|
314
|
+
# exclusive-end, treated as the limit not reached) determines the
|
|
315
|
+
# endpoint. Concretely:
|
|
316
|
+
#
|
|
317
|
+
# - inclusive range `a..b`: `self[0] == a`, `self[-1] == b`,
|
|
318
|
+
# intermediate values are evenly spaced.
|
|
319
|
+
# - exclusive range `a...b`: `self[0] == a`, `self[-1] == a + (N-1)
|
|
320
|
+
# * (b-a)/N` (endpoint `b` is not reached).
|
|
321
|
+
#
|
|
322
|
+
# Only **float** arrays are supported. Integer arrays raise —
|
|
323
|
+
# "N evenly-spaced integers" is not a well-defined concept; the
|
|
324
|
+
# error message shows the two idioms that cover the two distinct
|
|
325
|
+
# integer use cases:
|
|
326
|
+
#
|
|
327
|
+
# - (A) N points with both endpoints hitting `a` and `b` exactly
|
|
328
|
+
# (linspace-like): use the manual integer form
|
|
329
|
+
# `CArray.int32(N).seq * (b - a) / (N - 1) + a`, or sample as
|
|
330
|
+
# float then cast: `CArray.float64(N).span(a.to_f..b.to_f).int32`.
|
|
331
|
+
# - (B) N labels distributed uniformly over the value range so
|
|
332
|
+
# each of the `(b - a + 1)` values appears approximately the
|
|
333
|
+
# same number of times (bucket distribution): use
|
|
334
|
+
# `CArray.int32(N).seq * (b - a + 1) / N + a`.
|
|
335
|
+
#
|
|
336
|
+
# @param range [Range<Numeric>] value range to span.
|
|
337
|
+
# @return [self]
|
|
338
|
+
# @raise [ArgumentError] when `self` is not a float array.
|
|
339
|
+
def span! (range)
|
|
340
|
+
unless float?
|
|
341
|
+
raise ArgumentError,
|
|
342
|
+
"span!: integer arrays are ambiguous — 'N evenly-spaced " \
|
|
343
|
+
"integers' has two distinct meanings. Pick the one you want:\n" \
|
|
344
|
+
" (A) N points hitting both endpoints exactly (linspace-like):\n" \
|
|
345
|
+
" CArray.int32(N).seq * (b - a) / (N - 1) + a\n" \
|
|
346
|
+
" or CArray.float64(N).span(a.to_f..b.to_f).int32\n" \
|
|
347
|
+
" (B) N labels distributed uniformly over range values:\n" \
|
|
348
|
+
" CArray.int32(N).seq * (b - a + 1) / N + a"
|
|
349
|
+
end
|
|
350
|
+
first = range.begin.to_r
|
|
351
|
+
last = range.end.to_r
|
|
352
|
+
step = range.exclude_end? ? (last-first)/elements : (last-first)/(elements-1)
|
|
353
|
+
seq!(first, step)
|
|
354
|
+
return self
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# @overload span(range)
|
|
358
|
+
# Returns a fresh CArray shaped like `self` filled with the
|
|
359
|
+
# linear sequence produced by {#span!}. Float arrays only.
|
|
360
|
+
# @param range [Range<Numeric>] value range to span.
|
|
361
|
+
# @return [CArray]
|
|
362
|
+
# @raise [ArgumentError] when `self` is not a float array.
|
|
363
|
+
def span (range)
|
|
364
|
+
return template.span!(range)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# @overload scale!(xa, xb)
|
|
368
|
+
# Sets `self` to `elements` evenly spaced float64 values from
|
|
369
|
+
# `xa` to `xb` inclusive.
|
|
370
|
+
# @param xa [Numeric] first value.
|
|
371
|
+
# @param xb [Numeric] last value.
|
|
372
|
+
# @return [self]
|
|
373
|
+
def scale! (xa, xb)
|
|
374
|
+
xa = xa.to_f
|
|
375
|
+
xb = xb.to_f
|
|
376
|
+
seq!(xa, (xb-xa)/(elements-1))
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# @overload scale(xa, xb)
|
|
380
|
+
# Returns a fresh CArray shaped like `self` holding `elements`
|
|
381
|
+
# evenly spaced values from `xa` to `xb` inclusive.
|
|
382
|
+
# @param xa [Numeric] first value.
|
|
383
|
+
# @param xb [Numeric] last value.
|
|
384
|
+
# @return [CArray]
|
|
385
|
+
def scale (xa, xb)
|
|
386
|
+
template.scale!(xa, xb)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
# ---------------------------------------------------------------------------
|
|
392
|
+
# Container -> CArray coercion (relocated from former basic.rb)
|
|
393
|
+
# ---------------------------------------------------------------------------
|
|
394
|
+
|
|
395
|
+
class Array
|
|
396
|
+
|
|
397
|
+
# @overload to_ca(writable: false)
|
|
398
|
+
# Returns `self` coerced into a `CA_OBJECT` CArray of matching
|
|
399
|
+
# shape.
|
|
400
|
+
#
|
|
401
|
+
# The result is a freshly built array that shares nothing with the
|
|
402
|
+
# receiver, so `writable: true` — a demand for a result whose writes
|
|
403
|
+
# reach the source — is refused.
|
|
404
|
+
# @return [CArray]
|
|
405
|
+
# @raise [RuntimeError] when `writable: true` is given.
|
|
406
|
+
def to_ca(writable: false)
|
|
407
|
+
if writable
|
|
408
|
+
raise "#{self.class}#to_ca builds a new array; " \
|
|
409
|
+
"it can't satisfy `writable: true'"
|
|
410
|
+
end
|
|
411
|
+
return CA_OBJECT(self)
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
# Reopened to add {#to_ca}, so a Range can be handed to any CArray entry
|
|
416
|
+
# point that coerces its operand (`CArray.cast`, `wrap_readonly`, `meshgrid`).
|
|
417
|
+
class Range
|
|
418
|
+
|
|
419
|
+
# @overload to_ca(writable: false)
|
|
420
|
+
# Returns the members of `self` as a 1-D `CA_OBJECT` CArray.
|
|
421
|
+
#
|
|
422
|
+
# Enumeration follows Ruby, so a Float range raises (`TypeError`,
|
|
423
|
+
# not iterable) and an endless range raises (`RangeError`); use
|
|
424
|
+
# {CArray.linspace} or `span!` for a float axis. A descending
|
|
425
|
+
# integer range is the one departure: it counts down
|
|
426
|
+
# (`(3..0).to_ca` gives `[3, 2, 1, 0]`, not the empty array
|
|
427
|
+
# `(3..0).to_a` gives), so that it agrees with the cast form
|
|
428
|
+
# `CA_INT32(3..0)`.
|
|
429
|
+
#
|
|
430
|
+
# As with {Array#to_ca} the result is newly built, so `writable: true`
|
|
431
|
+
# is refused.
|
|
432
|
+
#
|
|
433
|
+
# @return [CArray]
|
|
434
|
+
# @raise [RuntimeError] when `writable: true` is given.
|
|
435
|
+
def to_ca(writable: false)
|
|
436
|
+
if writable
|
|
437
|
+
raise "#{self.class}#to_ca builds a new array; " \
|
|
438
|
+
"it can't satisfy `writable: true'"
|
|
439
|
+
end
|
|
440
|
+
first, last = self.begin, self.end
|
|
441
|
+
if first.is_a?(Integer) and last.is_a?(Integer) and first > last
|
|
442
|
+
return CA_OBJECT(self, 1) # step 1: signed arange
|
|
443
|
+
end
|
|
444
|
+
return CA_OBJECT(self)
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
# Reopened to add {#to_ca}, so a stepped sequence can be handed to any CArray
|
|
449
|
+
# entry point that coerces its operand.
|
|
450
|
+
class Enumerator::ArithmeticSequence
|
|
451
|
+
|
|
452
|
+
# @overload to_ca(writable: false)
|
|
453
|
+
# Returns the members of `self` as a 1-D `CA_OBJECT` CArray, so that
|
|
454
|
+
# a strided axis can be written `(0..10).step(2)` or `(0.0..1.0).step(0.25)`.
|
|
455
|
+
#
|
|
456
|
+
# An endless sequence is rejected up front: unlike an endless Range,
|
|
457
|
+
# which `RangeError`s, enumerating one runs forever. As with
|
|
458
|
+
# {Range#to_ca}, descending integer bounds count down rather than
|
|
459
|
+
# coming back empty.
|
|
460
|
+
#
|
|
461
|
+
# As with {Array#to_ca} the result is newly built, so `writable: true`
|
|
462
|
+
# is refused.
|
|
463
|
+
#
|
|
464
|
+
# @return [CArray]
|
|
465
|
+
# @raise [RangeError] when the sequence has no end.
|
|
466
|
+
# @raise [RuntimeError] when `writable: true` is given.
|
|
467
|
+
def to_ca(writable: false)
|
|
468
|
+
if writable
|
|
469
|
+
raise "#{self.class}#to_ca builds a new array; " \
|
|
470
|
+
"it can't satisfy `writable: true'"
|
|
471
|
+
end
|
|
472
|
+
first, last, by = self.begin, self.end, self.step
|
|
473
|
+
if last.nil?
|
|
474
|
+
raise RangeError, "cannot convert endless arithmetic sequence to an array"
|
|
475
|
+
end
|
|
476
|
+
if first.is_a?(Integer) and last.is_a?(Integer) and by > 0 and first > last
|
|
477
|
+
return CA_OBJECT(Range.new(first, last, exclude_end?), by)
|
|
478
|
+
end
|
|
479
|
+
return CA_OBJECT(to_a)
|
|
480
|
+
end
|
|
481
|
+
end
|