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/lib/carray/conditional.rb
CHANGED
|
@@ -81,7 +81,7 @@ class CArray
|
|
|
81
81
|
result
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# @overload conditional(cond, then_fn, else_fn,
|
|
84
|
+
# @overload conditional(cond, then_fn, else_fn, data_type: nil)
|
|
85
85
|
# Returns per-cell `then_fn.call(self[cond])` where `cond` is
|
|
86
86
|
# true and `else_fn.call(self[cond.not])` where it is false.
|
|
87
87
|
# The two callables are applied only to their own subset of
|
|
@@ -91,14 +91,14 @@ class CArray
|
|
|
91
91
|
# Scalar returns from a callable (e.g. `->(v) { 0 }`) broadcast
|
|
92
92
|
# to the subset shape. The result `data_type` is the promotion
|
|
93
93
|
# of the two subset results via `CArray.result_type`, or
|
|
94
|
-
# `
|
|
94
|
+
# `data_type` when given. Masked cells in `cond` propagate to
|
|
95
95
|
# `UNDEF` in the result.
|
|
96
96
|
#
|
|
97
97
|
# @param cond [CArray] boolean selector; same shape as `self`.
|
|
98
98
|
# @param then_fn [#call] callable applied to `self[cond]`.
|
|
99
99
|
# @param else_fn [#call] callable applied to `self[cond.not]`.
|
|
100
|
-
# @param
|
|
101
|
-
#
|
|
100
|
+
# @param data_type [Symbol, Integer, nil] override for the result
|
|
101
|
+
# data type.
|
|
102
102
|
# @return [CArray] new array with the same shape as `self`.
|
|
103
103
|
# @raise [ArgumentError] when `cond` is not a same-shape
|
|
104
104
|
# boolean CArray.
|
|
@@ -108,7 +108,7 @@ class CArray
|
|
|
108
108
|
# ->(v) { v.log }, # domain-safe: only positive cells
|
|
109
109
|
# ->(v) { -v })
|
|
110
110
|
# # => [2.0, 1.0, -0.0, 0.0, 0.6931..., 1.0986...]
|
|
111
|
-
def conditional (cond, then_fn, else_fn,
|
|
111
|
+
def conditional (cond, then_fn, else_fn, data_type: nil)
|
|
112
112
|
unless cond.is_a?(CArray) && cond.boolean? && cond.shape == self.shape
|
|
113
113
|
raise ArgumentError,
|
|
114
114
|
"conditional: cond must be a boolean CArray with same shape as self"
|
|
@@ -123,13 +123,13 @@ class CArray
|
|
|
123
123
|
# to the subset shape; wrap it here so the scatter step below sees a
|
|
124
124
|
# same-length CArray.
|
|
125
125
|
unless y_then.is_a?(CArray)
|
|
126
|
-
y_then = CArray.new(
|
|
126
|
+
y_then = CArray.new(data_type || CArray.result_type(y_then), x_then.shape).fill(y_then)
|
|
127
127
|
end
|
|
128
128
|
unless y_else.is_a?(CArray)
|
|
129
|
-
y_else = CArray.new(
|
|
129
|
+
y_else = CArray.new(data_type || CArray.result_type(y_else), x_else.shape).fill(y_else)
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
-
dt =
|
|
132
|
+
dt = data_type || CArray.result_type(y_then, y_else)
|
|
133
133
|
out = CArray.new(dt, self.shape)
|
|
134
134
|
out[cond] = y_then
|
|
135
135
|
out[cond.not] = y_else
|
|
@@ -141,7 +141,7 @@ class CArray
|
|
|
141
141
|
out
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
-
# @overload select(condlist, choicelist, default: 0,
|
|
144
|
+
# @overload select(condlist, choicelist, default: 0, data_type: nil)
|
|
145
145
|
# Multi-way ternary select: for each cell, picks the value from
|
|
146
146
|
# the first `choicelist[k]` whose matching `condlist[k]` is true,
|
|
147
147
|
# falling back to `default` when no condition holds. When several
|
|
@@ -151,15 +151,15 @@ class CArray
|
|
|
151
151
|
# Each `choicelist[k]` is either a same-shape CArray or a scalar
|
|
152
152
|
# broadcast to every cell. The result `data_type` is the promotion
|
|
153
153
|
# of every choice plus `default` via `CArray.result_type`, or
|
|
154
|
-
# `
|
|
154
|
+
# `data_type` when given.
|
|
155
155
|
#
|
|
156
156
|
# @param condlist [Array<CArray>] boolean selectors.
|
|
157
157
|
# @param choicelist [Array<CArray, Numeric, Object>] values, one
|
|
158
158
|
# per condition (same length as `condlist`).
|
|
159
159
|
# @param default [CArray, Numeric, Object] value written where no
|
|
160
160
|
# condition holds.
|
|
161
|
-
# @param
|
|
162
|
-
#
|
|
161
|
+
# @param data_type [Symbol, Integer, nil] override for the result
|
|
162
|
+
# data type.
|
|
163
163
|
# @return [CArray] new array with the shape of `condlist[0]`.
|
|
164
164
|
# @raise [ArgumentError] on size mismatch, empty `condlist`, or a
|
|
165
165
|
# non-boolean / wrong-shape entry in `condlist`.
|
|
@@ -169,7 +169,7 @@ class CArray
|
|
|
169
169
|
# [-x, x * 10],
|
|
170
170
|
# default: 999)
|
|
171
171
|
# # => [5.0, 3.0, -10.0, 0.0, 10.0, 999.0]
|
|
172
|
-
def self.select (condlist, choicelist, default: 0,
|
|
172
|
+
def self.select (condlist, choicelist, default: 0, data_type: nil)
|
|
173
173
|
unless condlist.is_a?(Array) && choicelist.is_a?(Array)
|
|
174
174
|
raise ArgumentError, "select: condlist and choicelist must be Arrays"
|
|
175
175
|
end
|
|
@@ -187,7 +187,7 @@ class CArray
|
|
|
187
187
|
end
|
|
188
188
|
shape = first.shape
|
|
189
189
|
|
|
190
|
-
dt =
|
|
190
|
+
dt = data_type || CArray.result_type(*choicelist, default)
|
|
191
191
|
# `default` can be either a same-shape CArray (per-cell fallback) or a
|
|
192
192
|
# scalar (broadcast to every cell).
|
|
193
193
|
default_full = default.is_a?(CArray) && !default.scalar?
|
data/lib/carray/const_string.rb
CHANGED
|
@@ -5,12 +5,15 @@
|
|
|
5
5
|
# CAConstString high-level construction + conversion surface.
|
|
6
6
|
#
|
|
7
7
|
# CAConstString itself (the Face + tail buffer + fetch decode + numeric gate) lives
|
|
8
|
-
# in ext/ca_obj_const_string.c. This file provides the ergonomic builders that
|
|
9
|
-
# Ruby Strings into the
|
|
10
|
-
#
|
|
8
|
+
# in ext/ca_obj_const_string.c. This file provides the ergonomic builders that
|
|
9
|
+
# pack Ruby Strings into the shared buffer + (start,end) pair entity, via the
|
|
10
|
+
# CAConstString.__build__ C primitive.
|
|
11
11
|
#
|
|
12
|
-
# Internal buffer format: concatenation of
|
|
13
|
-
#
|
|
12
|
+
# Internal buffer format: a pure concatenation of the element bytes, with no
|
|
13
|
+
# per-record length prefix (= the Arrow values buffer). Each element carries
|
|
14
|
+
# its own `(start, end)` byte range in the storage, so it is self-describing
|
|
15
|
+
# and a gather / sort / select view over the pairs decodes correctly with no
|
|
16
|
+
# buffer copy.
|
|
14
17
|
#
|
|
15
18
|
# ----------------------------------------------------------------------------
|
|
16
19
|
|
|
@@ -89,21 +92,118 @@ class CAConstString
|
|
|
89
92
|
# override the L1 generics where present.
|
|
90
93
|
include CArray::StringOperationMixin
|
|
91
94
|
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
95
|
+
# ---- ordering family ---------------------------------------------------
|
|
96
|
+
#
|
|
97
|
+
# A storage cell is a `(start, end)` byte range into the shared buffer, so
|
|
98
|
+
# storage order is the order the strings were packed in, not the order they
|
|
99
|
+
# compare in. Without these overrides the family sorted the offsets: the
|
|
100
|
+
# answers came back well-formed and wrong -- `%w[pear apple].sort_addr` gave
|
|
101
|
+
# the identity, and `partition_copy` gave NUL bytes.
|
|
102
|
+
#
|
|
103
|
+
# Every member therefore reads the bytes. The flat forms do it natively
|
|
104
|
+
# (a byte-memcmp scan over the packed buffer, an order of magnitude faster
|
|
105
|
+
# than decoding a Ruby String per cell), the per-axis forms through
|
|
106
|
+
# {#to_string}, where a cell is the string and CArray's own kernels apply.
|
|
107
|
+
# Arguments are forwarded verbatim, so `kind:` / `masked_position:` /
|
|
108
|
+
# `keep_axis:` mean here what they mean on CArray.
|
|
109
|
+
#
|
|
110
|
+
# Anything whose cells are strings comes back a CAConstString, gathered
|
|
111
|
+
# over the same buffer where it can be (sort / sort_copy) and rebuilt where
|
|
112
|
+
# it cannot. Indices, addresses and counts need no conversion.
|
|
113
|
+
|
|
114
|
+
# @overload sort(axis: nil, kind: :quick, masked_position: :last)
|
|
115
|
+
# Returns a sorted {CAConstString} view, gathered over the same buffer
|
|
116
|
+
# and offsets. With no `axis:` the array is flattened first, as
|
|
117
|
+
# `CArray#sort` does.
|
|
96
118
|
# @return [CAConstString]
|
|
97
|
-
def sort
|
|
98
|
-
|
|
119
|
+
def sort (*args, **kw)
|
|
120
|
+
addr = sort_addr(*args, **kw)
|
|
121
|
+
kw[:axis].nil? ? self[addr.flatten] : self[addr]
|
|
99
122
|
end
|
|
100
123
|
|
|
101
|
-
# @overload sort_copy
|
|
102
|
-
# Returns an owned sorted {CAConstString}; the materialised
|
|
103
|
-
#
|
|
124
|
+
# @overload sort_copy(axis: nil, kind: :quick, masked_position: :last)
|
|
125
|
+
# Returns an owned sorted {CAConstString}; the materialised counterpart
|
|
126
|
+
# to {#sort}.
|
|
104
127
|
# @return [CAConstString]
|
|
105
|
-
def sort_copy
|
|
106
|
-
|
|
128
|
+
def sort_copy (*args, **kw)
|
|
129
|
+
sort(*args, **kw).copy
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# @overload sort_addr(axis: nil, kind: :quick, masked_position: :last)
|
|
133
|
+
# Returns the view-flat addresses that index a sort by string order.
|
|
134
|
+
# @return [CArray] `:int64` addresses.
|
|
135
|
+
def sort_addr (*args, **kw)
|
|
136
|
+
# The native scan has no notion of an incomparable sentinel, so a masked
|
|
137
|
+
# column goes the same way a per-axis one does.
|
|
138
|
+
return __sort_addr_bytes__ if args.empty? && kw.empty? && ! has_mask?
|
|
139
|
+
to_string.sort_addr(*args, **kw)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @overload sort_index(axis: nil, kind: :quick, masked_position: :last)
|
|
143
|
+
# Returns the per-fiber indices that index a sort by string order.
|
|
144
|
+
# @return [CArray] `:int64` indices.
|
|
145
|
+
def sort_index (*args, **kw)
|
|
146
|
+
to_string.sort_index(*args, **kw)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# @overload rank_index(axis: nil)
|
|
150
|
+
# @return [CArray] each cell's rank in string order.
|
|
151
|
+
def rank_index (*args, **kw)
|
|
152
|
+
to_string.rank_index(*args, **kw)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# @overload order(*args)
|
|
156
|
+
# @return [CArray] the ordering of the cells by string order.
|
|
157
|
+
def order (*args, **kw)
|
|
158
|
+
to_string.order(*args, **kw)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# @overload min(axis: nil, keep_axis: false)
|
|
162
|
+
# Returns the byte-smallest string, skipping masked cells; UNDEF when
|
|
163
|
+
# every cell is masked or the array is empty.
|
|
164
|
+
# @return [String, CAConstString]
|
|
165
|
+
def min (*args, **kw)
|
|
166
|
+
return __min_bytes__ || UNDEF if args.empty? && kw.empty?
|
|
167
|
+
const_string_lift(to_string.min(*args, **kw))
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @overload max(axis: nil, keep_axis: false)
|
|
171
|
+
# Byte-largest counterpart of {#min}.
|
|
172
|
+
# @return [String, CAConstString]
|
|
173
|
+
def max (*args, **kw)
|
|
174
|
+
return __max_bytes__ || UNDEF if args.empty? && kw.empty?
|
|
175
|
+
const_string_lift(to_string.max(*args, **kw))
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# @overload minmax(axis: nil, keep_axis: false)
|
|
179
|
+
# @return [Array] `[min, max]`.
|
|
180
|
+
def minmax (*args, **kw)
|
|
181
|
+
return [min, max] if args.empty? && kw.empty?
|
|
182
|
+
to_string.minmax(*args, **kw).map { |r| const_string_lift(r) }
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# @overload min_index(axis: nil)
|
|
186
|
+
# @return [Integer, CArray] where the byte-smallest string sits.
|
|
187
|
+
def min_index (*args, **kw)
|
|
188
|
+
to_string.min_index(*args, **kw)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# @overload max_index(axis: nil)
|
|
192
|
+
# @return [Integer, CArray] where the byte-largest string sits.
|
|
193
|
+
def max_index (*args, **kw)
|
|
194
|
+
to_string.max_index(*args, **kw)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# @overload partition_copy(kth, axis: nil)
|
|
198
|
+
# @return [CAConstString] partitioned about the `kth` string in order.
|
|
199
|
+
def partition_copy (*args, **kw)
|
|
200
|
+
const_string_lift(to_string.partition_copy(*args, **kw))
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# @overload partition_index(kth, axis: nil)
|
|
204
|
+
# @return [CArray] the indices that partition about the `kth` string.
|
|
205
|
+
def partition_index (*args, **kw)
|
|
206
|
+
to_string.partition_index(*args, **kw)
|
|
107
207
|
end
|
|
108
208
|
|
|
109
209
|
# CAConstString is the one Face with three separate entities -- storage
|
|
@@ -144,14 +244,14 @@ class CAConstString
|
|
|
144
244
|
# @overload unique(sort: false)
|
|
145
245
|
# @return [CAConstString] the distinct strings.
|
|
146
246
|
def unique (sort: false)
|
|
147
|
-
to_string.unique(sort: sort)
|
|
247
|
+
const_string_lift(to_string.unique(sort: sort))
|
|
148
248
|
end
|
|
149
249
|
|
|
150
250
|
# @overload value_counts(sort: false)
|
|
151
251
|
# @return [Array(CAConstString, CArray)] `[values, counts]`.
|
|
152
252
|
def value_counts (sort: false)
|
|
153
253
|
values, counts = to_string.value_counts(sort: sort)
|
|
154
|
-
[values
|
|
254
|
+
[const_string_lift(values), counts]
|
|
155
255
|
end
|
|
156
256
|
|
|
157
257
|
# @overload nunique(axis: nil, keep_axis: false)
|
|
@@ -164,11 +264,7 @@ class CAConstString
|
|
|
164
264
|
# @return [CAConstString, Array] the most frequent string(s).
|
|
165
265
|
def mode (axis: nil)
|
|
166
266
|
r = to_string.mode(axis: axis)
|
|
167
|
-
|
|
168
|
-
when CArray then r.to_const_string
|
|
169
|
-
when Array then r.map { |c| c.is_a?(CArray) ? c.to_const_string : c }
|
|
170
|
-
else r
|
|
171
|
-
end
|
|
267
|
+
r.is_a?(Array) ? r.map { |c| const_string_lift(c) } : const_string_lift(r)
|
|
172
268
|
end
|
|
173
269
|
|
|
174
270
|
# @overload is_mode(axis: nil)
|
|
@@ -180,7 +276,7 @@ class CAConstString
|
|
|
180
276
|
# @overload mask_duplicates(axis: nil)
|
|
181
277
|
# @return [CAConstString] a copy with every repeat occurrence masked.
|
|
182
278
|
def mask_duplicates (axis: nil)
|
|
183
|
-
to_string.mask_duplicates(axis: axis)
|
|
279
|
+
const_string_lift(to_string.mask_duplicates(axis: axis))
|
|
184
280
|
end
|
|
185
281
|
|
|
186
282
|
# @overload is_in(values)
|
|
@@ -192,19 +288,19 @@ class CAConstString
|
|
|
192
288
|
# @overload intersection(other, sort: false)
|
|
193
289
|
# @return [CAConstString] the distinct strings present in both.
|
|
194
290
|
def intersection (other, sort: false)
|
|
195
|
-
to_string.intersection(string_operand(other), sort: sort)
|
|
291
|
+
const_string_lift(to_string.intersection(string_operand(other), sort: sort))
|
|
196
292
|
end
|
|
197
293
|
|
|
198
294
|
# @overload difference(other, sort: false)
|
|
199
295
|
# @return [CAConstString] the distinct strings only `self` has.
|
|
200
296
|
def difference (other, sort: false)
|
|
201
|
-
to_string.difference(string_operand(other), sort: sort)
|
|
297
|
+
const_string_lift(to_string.difference(string_operand(other), sort: sort))
|
|
202
298
|
end
|
|
203
299
|
|
|
204
300
|
# @overload union(other, sort: false)
|
|
205
301
|
# @return [CAConstString] the distinct strings of either side.
|
|
206
302
|
def union (other, sort: false)
|
|
207
|
-
to_string.union(string_operand(other), sort: sort)
|
|
303
|
+
const_string_lift(to_string.union(string_operand(other), sort: sort))
|
|
208
304
|
end
|
|
209
305
|
|
|
210
306
|
# @overload locate_addr(ref)
|
|
@@ -225,4 +321,12 @@ class CAConstString
|
|
|
225
321
|
other.is_a?(CAConstString) ? other.to_string : other
|
|
226
322
|
end
|
|
227
323
|
|
|
324
|
+
# Pack a string-bearing result back into a column of this one's encoding.
|
|
325
|
+
# The encoding has to be carried: the builder checks each element against
|
|
326
|
+
# the column's, so a Shift_JIS column rebuilt as the UTF-8 default raised
|
|
327
|
+
# rather than coming back.
|
|
328
|
+
private def const_string_lift (x)
|
|
329
|
+
x.is_a?(CArray) ? CArray.const_string(x, encoding: encoding) : x
|
|
330
|
+
end
|
|
331
|
+
|
|
228
332
|
end
|
data/lib/carray/construct.rb
CHANGED
|
@@ -35,6 +35,7 @@ class CArray
|
|
|
35
35
|
# CArray whose elements are `boolean`. Naming the element type as a
|
|
36
36
|
# class lets a constructor be spelled `CArray::Boolean.new(...)`; see
|
|
37
37
|
# {DataTypeNewConstructor} for what that form adds.
|
|
38
|
+
# @private
|
|
38
39
|
class Boolean
|
|
39
40
|
extend DataTypeNewConstructor
|
|
40
41
|
extend DataTypeExtension
|
|
@@ -47,6 +48,7 @@ class CArray
|
|
|
47
48
|
# CArray whose elements are `uint8`. Naming the element type as a
|
|
48
49
|
# class lets a constructor be spelled `CArray::UInt8.new(...)`; see
|
|
49
50
|
# {DataTypeNewConstructor} for what that form adds.
|
|
51
|
+
# @private
|
|
50
52
|
class UInt8
|
|
51
53
|
extend DataTypeNewConstructor
|
|
52
54
|
extend DataTypeExtension
|
|
@@ -59,6 +61,7 @@ class CArray
|
|
|
59
61
|
# CArray whose elements are `uint16`. Naming the element type as a
|
|
60
62
|
# class lets a constructor be spelled `CArray::UInt16.new(...)`; see
|
|
61
63
|
# {DataTypeNewConstructor} for what that form adds.
|
|
64
|
+
# @private
|
|
62
65
|
class UInt16
|
|
63
66
|
extend DataTypeNewConstructor
|
|
64
67
|
extend DataTypeExtension
|
|
@@ -71,6 +74,7 @@ class CArray
|
|
|
71
74
|
# CArray whose elements are `uint32`. Naming the element type as a
|
|
72
75
|
# class lets a constructor be spelled `CArray::UInt32.new(...)`; see
|
|
73
76
|
# {DataTypeNewConstructor} for what that form adds.
|
|
77
|
+
# @private
|
|
74
78
|
class UInt32
|
|
75
79
|
extend DataTypeNewConstructor
|
|
76
80
|
extend DataTypeExtension
|
|
@@ -83,6 +87,7 @@ class CArray
|
|
|
83
87
|
# CArray whose elements are `uint64`. Naming the element type as a
|
|
84
88
|
# class lets a constructor be spelled `CArray::UInt64.new(...)`; see
|
|
85
89
|
# {DataTypeNewConstructor} for what that form adds.
|
|
90
|
+
# @private
|
|
86
91
|
class UInt64
|
|
87
92
|
extend DataTypeNewConstructor
|
|
88
93
|
extend DataTypeExtension
|
|
@@ -95,6 +100,7 @@ class CArray
|
|
|
95
100
|
# CArray whose elements are `int8`. Naming the element type as a
|
|
96
101
|
# class lets a constructor be spelled `CArray::Int8.new(...)`; see
|
|
97
102
|
# {DataTypeNewConstructor} for what that form adds.
|
|
103
|
+
# @private
|
|
98
104
|
class Int8
|
|
99
105
|
extend DataTypeNewConstructor
|
|
100
106
|
extend DataTypeExtension
|
|
@@ -107,6 +113,7 @@ class CArray
|
|
|
107
113
|
# CArray whose elements are `int16`. Naming the element type as a
|
|
108
114
|
# class lets a constructor be spelled `CArray::Int16.new(...)`; see
|
|
109
115
|
# {DataTypeNewConstructor} for what that form adds.
|
|
116
|
+
# @private
|
|
110
117
|
class Int16
|
|
111
118
|
extend DataTypeNewConstructor
|
|
112
119
|
extend DataTypeExtension
|
|
@@ -119,6 +126,7 @@ class CArray
|
|
|
119
126
|
# CArray whose elements are `int32`. Naming the element type as a
|
|
120
127
|
# class lets a constructor be spelled `CArray::Int32.new(...)`; see
|
|
121
128
|
# {DataTypeNewConstructor} for what that form adds.
|
|
129
|
+
# @private
|
|
122
130
|
class Int32
|
|
123
131
|
extend DataTypeNewConstructor
|
|
124
132
|
extend DataTypeExtension
|
|
@@ -131,6 +139,7 @@ class CArray
|
|
|
131
139
|
# CArray whose elements are `int64`. Naming the element type as a
|
|
132
140
|
# class lets a constructor be spelled `CArray::Int64.new(...)`; see
|
|
133
141
|
# {DataTypeNewConstructor} for what that form adds.
|
|
142
|
+
# @private
|
|
134
143
|
class Int64
|
|
135
144
|
extend DataTypeNewConstructor
|
|
136
145
|
extend DataTypeExtension
|
|
@@ -143,6 +152,7 @@ class CArray
|
|
|
143
152
|
# CArray whose elements are `float32`. Naming the element type as a
|
|
144
153
|
# class lets a constructor be spelled `CArray::Float32.new(...)`; see
|
|
145
154
|
# {DataTypeNewConstructor} for what that form adds.
|
|
155
|
+
# @private
|
|
146
156
|
class Float32
|
|
147
157
|
extend DataTypeNewConstructor
|
|
148
158
|
extend DataTypeExtension
|
|
@@ -153,11 +163,13 @@ class CArray
|
|
|
153
163
|
end
|
|
154
164
|
|
|
155
165
|
# Numo-compatible alias of {Float32}.
|
|
166
|
+
# @private
|
|
156
167
|
SFloat = Float32
|
|
157
168
|
|
|
158
169
|
# CArray whose elements are `float64`. Naming the element type as a
|
|
159
170
|
# class lets a constructor be spelled `CArray::Float64.new(...)`; see
|
|
160
171
|
# {DataTypeNewConstructor} for what that form adds.
|
|
172
|
+
# @private
|
|
161
173
|
class Float64
|
|
162
174
|
extend DataTypeNewConstructor
|
|
163
175
|
extend DataTypeExtension
|
|
@@ -168,11 +180,13 @@ class CArray
|
|
|
168
180
|
end
|
|
169
181
|
|
|
170
182
|
# Numo-compatible alias of {Float64}.
|
|
183
|
+
# @private
|
|
171
184
|
DFloat = Float64
|
|
172
185
|
|
|
173
186
|
# CArray whose elements are `complex64`. Naming the element type as a
|
|
174
187
|
# class lets a constructor be spelled `CArray::Complex64.new(...)`; see
|
|
175
188
|
# {DataTypeNewConstructor} for what that form adds.
|
|
189
|
+
# @private
|
|
176
190
|
class Complex64
|
|
177
191
|
extend DataTypeNewConstructor
|
|
178
192
|
extend DataTypeExtension
|
|
@@ -183,11 +197,13 @@ class CArray
|
|
|
183
197
|
end
|
|
184
198
|
|
|
185
199
|
# Numo-compatible alias of {Complex64}.
|
|
200
|
+
# @private
|
|
186
201
|
SComplex = Complex64
|
|
187
202
|
|
|
188
203
|
# CArray whose elements are `complex128`. Naming the element type as a
|
|
189
204
|
# class lets a constructor be spelled `CArray::Complex128.new(...)`; see
|
|
190
205
|
# {DataTypeNewConstructor} for what that form adds.
|
|
206
|
+
# @private
|
|
191
207
|
class Complex128
|
|
192
208
|
extend DataTypeNewConstructor
|
|
193
209
|
extend DataTypeExtension
|
|
@@ -198,11 +214,13 @@ class CArray
|
|
|
198
214
|
end
|
|
199
215
|
|
|
200
216
|
# Numo-compatible alias of {Complex128}.
|
|
217
|
+
# @private
|
|
201
218
|
DComplex = Complex128
|
|
202
219
|
|
|
203
220
|
# CArray whose elements are `object`. Naming the element type as a
|
|
204
221
|
# class lets a constructor be spelled `CArray::Object.new(...)`; see
|
|
205
222
|
# {DataTypeNewConstructor} for what that form adds.
|
|
223
|
+
# @private
|
|
206
224
|
class Object
|
|
207
225
|
extend DataTypeNewConstructor
|
|
208
226
|
extend DataTypeExtension
|
|
@@ -213,11 +231,13 @@ class CArray
|
|
|
213
231
|
end
|
|
214
232
|
|
|
215
233
|
# Numo-compatible alias of {Object}.
|
|
234
|
+
# @private
|
|
216
235
|
RObject = Object
|
|
217
236
|
|
|
218
237
|
# CArray whose elements are `fixlen`. Naming the element type as a
|
|
219
238
|
# class lets a constructor be spelled `CArray::Fixlen.new(...)`; see
|
|
220
239
|
# {DataTypeNewConstructor} for what that form adds.
|
|
240
|
+
# @private
|
|
221
241
|
class Fixlen
|
|
222
242
|
extend DataTypeNewConstructor
|
|
223
243
|
extend DataTypeExtension
|
|
@@ -232,9 +252,50 @@ end
|
|
|
232
252
|
class CArray
|
|
233
253
|
extend DataTypeExtension
|
|
234
254
|
# @!visibility private
|
|
255
|
+
# @private
|
|
235
256
|
TypeSymbol = nil
|
|
236
257
|
# @!visibility private
|
|
237
258
|
DataType = nil
|
|
259
|
+
|
|
260
|
+
# @overload empty(data_type, dim, bytes: nil)
|
|
261
|
+
# Returns a new CArray of `data_type` with the shape `dim`, whose
|
|
262
|
+
# contents are **undefined**. This is {CArray.new} without the fill:
|
|
263
|
+
# the arguments are read the same way, and the cost of zeroing the
|
|
264
|
+
# buffer is not paid. Use it when every cell is written before it is
|
|
265
|
+
# read; otherwise use `CArray.new`, which zero-fills.
|
|
266
|
+
#
|
|
267
|
+
# `CA_OBJECT` is the exception: its cells are zero-initialised
|
|
268
|
+
# anyway, because the garbage collector walks them.
|
|
269
|
+
#
|
|
270
|
+
# @param data_type [Symbol, String, Integer] element type.
|
|
271
|
+
# @param dim [Array<Integer>] shape of the new CArray.
|
|
272
|
+
# @param bytes [Integer, nil] element width, for `:fixlen` only.
|
|
273
|
+
# @return [CArray]
|
|
274
|
+
# @raise [ArgumentError] if a block is given -- filling an array is
|
|
275
|
+
# what `CArray.new` is for.
|
|
276
|
+
# @overload empty(*shape)
|
|
277
|
+
# (Numo / NumPy compatibility) Returns an uninitialised CArray of
|
|
278
|
+
# the given shape. The element type comes from the receiver, so
|
|
279
|
+
# `CArray` itself gives `CA_FLOAT64`; see
|
|
280
|
+
# {DataTypeExtension#empty}.
|
|
281
|
+
# @param shape [Array<Integer>, Array<Array<Integer>>] shape.
|
|
282
|
+
# @return [CArray]
|
|
283
|
+
def self.empty (*args, **options, &block)
|
|
284
|
+
if block
|
|
285
|
+
raise ArgumentError,
|
|
286
|
+
"CArray.empty does not take a block " \
|
|
287
|
+
"(its contents are left undefined); use CArray.new to fill."
|
|
288
|
+
end
|
|
289
|
+
if args.size == 2 and args[1].is_a?(Array)
|
|
290
|
+
return __empty__(*args, **options)
|
|
291
|
+
end
|
|
292
|
+
unless options.empty?
|
|
293
|
+
raise ArgumentError,
|
|
294
|
+
"CArray.empty(*shape) takes no options; bytes: belongs to " \
|
|
295
|
+
"CArray.empty(data_type, dim)"
|
|
296
|
+
end
|
|
297
|
+
super(*args)
|
|
298
|
+
end
|
|
238
299
|
end
|
|
239
300
|
|
|
240
301
|
class CArray
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
# - Postfix math on Float/Integer/Rational (sqrt, exp, log, sin, ...)
|
|
11
11
|
# enabling scalar/CArray polymorphism: the same expression
|
|
12
12
|
# `(0.0415*(t-218.8)).tanh` works whether t is a Float or a CArray.
|
|
13
|
+
# - The same postfix math on Complex, so an expression written for a
|
|
14
|
+
# complex CArray still reads for a single cell taken out of it.
|
|
13
15
|
# - Angle normalisation on Numeric (deg_360 / deg_180 / rad_2pi / rad_pi).
|
|
14
16
|
# - Comparison helpers on Numeric (#eq / #ne) for symmetric usage:
|
|
15
17
|
# `5.eq(ca)` dispatches to `ca.eq(5)`.
|
|
@@ -36,9 +38,9 @@ class CArray
|
|
|
36
38
|
# `using CArray::CoreExtensions`.
|
|
37
39
|
#
|
|
38
40
|
# It provides postfix math on scalars (so `(0.0415*(t-218.8)).tanh` reads
|
|
39
|
-
# the same whether `t` is a Float or a CArray), angle
|
|
40
|
-
# comparison helpers. Being a refinement, it is
|
|
41
|
-
# changes for code that does not opt in.
|
|
41
|
+
# the same whether `t` is a Float, a Complex or a CArray), angle
|
|
42
|
+
# normalisation, and comparison helpers. Being a refinement, it is
|
|
43
|
+
# lexically scoped: nothing changes for code that does not opt in.
|
|
42
44
|
module CoreExtensions
|
|
43
45
|
|
|
44
46
|
# @!visibility private
|
|
@@ -51,7 +53,11 @@ class CArray
|
|
|
51
53
|
[Float, Integer, Rational].each do |klass|
|
|
52
54
|
refine(klass) do
|
|
53
55
|
MATH_METHODS.each do |m|
|
|
54
|
-
|
|
56
|
+
module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
57
|
+
def #{m}
|
|
58
|
+
Math.#{m}(self)
|
|
59
|
+
end
|
|
60
|
+
RUBY
|
|
55
61
|
end
|
|
56
62
|
def rad
|
|
57
63
|
self.to_f * Math::PI / 180.0
|
|
@@ -65,7 +71,7 @@ class CArray
|
|
|
65
71
|
# M.1 (PyTorch alignment) scalar polymorphism additions.
|
|
66
72
|
# `trunc` is left to Ruby's built-in semantics (Float#truncate
|
|
67
73
|
# returns Integer when arg=0) — its CArray counterpart preserves
|
|
68
|
-
#
|
|
74
|
+
# data type, so scalar-side use should call .to_f.trunc explicitly.
|
|
69
75
|
# Math.expm1 / Math.log1p don't exist in stdlib; hand-roll.
|
|
70
76
|
def expm1
|
|
71
77
|
Math.exp(self) - 1.0
|
|
@@ -85,6 +91,57 @@ class CArray
|
|
|
85
91
|
end
|
|
86
92
|
end
|
|
87
93
|
|
|
94
|
+
# The subset of MATH_METHODS that CArray's complex kernels implement,
|
|
95
|
+
# plus the two elementwise helpers that also accept complex input.
|
|
96
|
+
#
|
|
97
|
+
# Absent, because a complex CArray raises CArray::DataTypeError for
|
|
98
|
+
# them: log10 (C99 has no clog10) and expm1 / log1p (no complex form
|
|
99
|
+
# in C99 either). Leaving them undefined on Complex keeps the scalar
|
|
100
|
+
# side failing wherever the array side fails. rad / deg / distance /
|
|
101
|
+
# signbit are absent for the same reason from the other direction:
|
|
102
|
+
# they go through #to_f, which Complex does not have.
|
|
103
|
+
#
|
|
104
|
+
# @!visibility private
|
|
105
|
+
COMPLEX_MATH_METHODS = %i[
|
|
106
|
+
sqrt exp log
|
|
107
|
+
sin cos tan sinh cosh tanh
|
|
108
|
+
asin acos atan asinh acosh atanh
|
|
109
|
+
square rsqrt
|
|
110
|
+
].freeze
|
|
111
|
+
|
|
112
|
+
# Complex is not handled the way Float / Integer / Rational are.
|
|
113
|
+
# Math.tanh(Complex(1,2)) raises RangeError -- of the stdlib Math
|
|
114
|
+
# methods only Math.sqrt accepts a Complex -- so the complex forms
|
|
115
|
+
# need their own implementation.
|
|
116
|
+
#
|
|
117
|
+
# Each one runs the value through a one-element cmplx128 CScalar, so
|
|
118
|
+
# the answer comes from the very kernel the array form would have
|
|
119
|
+
# used. That is the point: the branch cuts of csqrt / clog / casin /
|
|
120
|
+
# cacosh / catanh, and the sign of a zero on either side of them, are
|
|
121
|
+
# whatever the platform's C99 complex.h says they are, and they are
|
|
122
|
+
# not the same everywhere. On this machine, for instance,
|
|
123
|
+
# catanh(-1+0i) yields -Infinity+(pi/4)i where C99 Annex G describes
|
|
124
|
+
# -Infinity+0i. A hand-written Complex implementation would have to
|
|
125
|
+
# reproduce each such quirk to agree with the array form, and would
|
|
126
|
+
# stop agreeing on the next platform; delegating agrees by
|
|
127
|
+
# construction on all of them. The cost is one CScalar per call
|
|
128
|
+
# (~0.4 microseconds), which is the right trade for a scalar
|
|
129
|
+
# convenience whose whole purpose is to read the same as the array.
|
|
130
|
+
#
|
|
131
|
+
# `square` is delegated rather than written as `self * self`: Ruby's
|
|
132
|
+
# Complex multiplication and C's `double _Complex` multiplication part
|
|
133
|
+
# ways on infinities (Complex(1, Inf) squared gives -Inf+Inf*i in Ruby
|
|
134
|
+
# and -Inf+NaN*i in C).
|
|
135
|
+
refine Complex do
|
|
136
|
+
COMPLEX_MATH_METHODS.each do |m|
|
|
137
|
+
module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
138
|
+
def #{m}
|
|
139
|
+
CA_CMPLX128(self).#{m}[0]
|
|
140
|
+
end
|
|
141
|
+
RUBY
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
88
145
|
refine Numeric do
|
|
89
146
|
def deg_360
|
|
90
147
|
a = self.to_f
|
|
@@ -194,10 +194,27 @@ class CArray
|
|
|
194
194
|
start = 0
|
|
195
195
|
stop, = *args
|
|
196
196
|
step = 1
|
|
197
|
+
else
|
|
198
|
+
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1..3)"
|
|
197
199
|
end
|
|
200
|
+
raise ArgumentError, "step must not be 0" if step == 0
|
|
198
201
|
data_type = self::DataType
|
|
199
202
|
data_type ||= guess_data_type_from_values(start, stop, step)
|
|
200
|
-
|
|
203
|
+
# Element count comes from the arguments as given, not from the
|
|
204
|
+
# target data type: CArray::Int32.arange(0, 1, 0.25) counts four
|
|
205
|
+
# elements from the float step and truncates them on store.
|
|
206
|
+
# Integer arguments count exactly (divmod) so that a step dividing
|
|
207
|
+
# the span evenly does not gain a spurious element through float
|
|
208
|
+
# rounding.
|
|
209
|
+
span = stop - start
|
|
210
|
+
if span.is_a?(Integer) && step.is_a?(Integer)
|
|
211
|
+
q, r = span.divmod(step)
|
|
212
|
+
n = r.zero? ? q : q + 1
|
|
213
|
+
else
|
|
214
|
+
n = (span.to_f / step).ceil
|
|
215
|
+
end
|
|
216
|
+
n = 0 if n < 0
|
|
217
|
+
CArray.new(data_type, [n]).seq(start, step)
|
|
201
218
|
end
|
|
202
219
|
|
|
203
220
|
# @overload full(shape, fill_value)
|
|
@@ -220,6 +237,9 @@ class CArray
|
|
|
220
237
|
# **uninitialised**. The caller must overwrite the array
|
|
221
238
|
# before reading from it. `CA_OBJECT` silently falls back to
|
|
222
239
|
# a zero-VALUE init required for GC safety.
|
|
240
|
+
#
|
|
241
|
+
# carray's own spelling is `CArray.empty(data_type, dim)`, which
|
|
242
|
+
# names the element type instead of taking it from the receiver.
|
|
223
243
|
# @param shape [Array<Integer>, Array<Array<Integer>>]
|
|
224
244
|
# @return [CArray]
|
|
225
245
|
def empty (*args)
|