carray 3.0.3 → 3.0.4
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/CHANGELOG.md +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/lib/carray/lazy.rb
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
#
|
|
3
3
|
# Per-op lazy-or-eager method redefinition on CArray.
|
|
4
4
|
#
|
|
5
|
-
# For each of the monop/monfunc methods,
|
|
6
|
-
# implementation as
|
|
5
|
+
# For each of the monop/monfunc methods, keep the existing eager
|
|
6
|
+
# implementation as an UnboundMethod and redefine `<name>` to dispatch:
|
|
7
7
|
#
|
|
8
|
-
# - if self.
|
|
8
|
+
# - if self.lazy_view? → CAMonOp.__build__(self, OP_<NAME>)
|
|
9
9
|
# (cast node insertion handled in C if data_type mismatch)
|
|
10
|
-
# - else →
|
|
10
|
+
# - else → the eager implementation
|
|
11
11
|
#
|
|
12
12
|
# CAREFUL: the redefinition must run once at load time AFTER the eager
|
|
13
13
|
# methods are bound by Init_carray_math. carray_ext.bundle Init order
|
|
@@ -84,31 +84,42 @@ class CArray
|
|
|
84
84
|
imag_i: CAMonOp::OP_IMAG_I,
|
|
85
85
|
}.freeze
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
# The lazy-or-eager dispatch of the operators, in a module in front of
|
|
88
|
+
# the eager methods: each reaches its eager method with super. The
|
|
89
|
+
# blocks are shareable (they capture an op id at most), so the operators
|
|
90
|
+
# can be called from any Ractor.
|
|
91
|
+
module LazyDispatch; end
|
|
92
|
+
prepend LazyDispatch
|
|
93
|
+
|
|
94
|
+
CArray.send(:define_named_methods, LazyDispatch,
|
|
95
|
+
LAZY_MONOP_OP_IDS.reject { |name, _| name == :round }, template: <<~'RUBY')
|
|
96
|
+
def __NAME__
|
|
97
|
+
if lazy_view?
|
|
98
|
+
CAMonOp.__build__(self, __VALUE__)
|
|
98
99
|
else
|
|
99
|
-
|
|
100
|
+
super()
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
RUBY
|
|
104
|
+
|
|
105
|
+
# round takes digits, which the lazy node does not carry: rounding to
|
|
106
|
+
# digits evaluates the expression and rounds the result.
|
|
107
|
+
module LazyDispatch
|
|
108
|
+
def round(*digits)
|
|
109
|
+
if digits.empty? && lazy_view?
|
|
110
|
+
CAMonOp.__build__(self, CAMonOp::OP_ROUND)
|
|
111
|
+
else
|
|
112
|
+
super
|
|
100
113
|
end
|
|
101
114
|
end
|
|
102
115
|
end
|
|
103
116
|
|
|
104
|
-
# Operator aliases (`~` -> bit_neg, `-@` -> neg) were installed
|
|
105
|
-
# rb_define_alias at Init time (see MkKernel.alias_monop in
|
|
106
|
-
# ext/carray_kernels_monop.c)
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
# of building a CAMonOp node. Re-alias here so the operator form
|
|
111
|
-
# follows the redefined lazy-or-eager dispatch.
|
|
117
|
+
# Operator aliases (`~` -> bit_neg, `-@` -> neg) were installed in
|
|
118
|
+
# CArray by rb_define_alias at Init time (see MkKernel.alias_monop in
|
|
119
|
+
# ext/carray_kernels_monop.c), and name the eager C function: `~a` on a
|
|
120
|
+
# lazy view would materialise instead of building a CAMonOp node. Made
|
|
121
|
+
# again here, an alias resolves through the prepended modules, so the
|
|
122
|
+
# operator form takes the dispatch above.
|
|
112
123
|
alias_method :"~", :bit_neg
|
|
113
124
|
alias_method :"-@", :neg
|
|
114
125
|
|
|
@@ -129,26 +140,24 @@ class CArray
|
|
|
129
140
|
# ---------------------------------------------------------------------------
|
|
130
141
|
|
|
131
142
|
# @private
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
module LazyDispatch
|
|
144
|
+
def abs
|
|
145
|
+
if lazy_view?
|
|
146
|
+
# A boolean has no absolute value: the eager abs refuses it.
|
|
147
|
+
return super() if boolean?
|
|
148
|
+
abs_i_node = CAMonOp.__build__(self, CAMonOp::OP_ABS_I)
|
|
149
|
+
if complex?
|
|
150
|
+
# float_dt is a Symbol; convert via data_type_code so the cast
|
|
151
|
+
# op_id can be computed by Integer arithmetic.
|
|
152
|
+
float_dt = (data_type == CA_CMPLX64) ? CA_FLOAT32 : CA_FLOAT64
|
|
153
|
+
CAMonOp.__build__(abs_i_node,
|
|
154
|
+
CAMonOp::CAST_BASE + CArray.data_type_code(float_dt))
|
|
155
|
+
else
|
|
156
|
+
abs_i_node
|
|
157
|
+
end
|
|
147
158
|
else
|
|
148
|
-
|
|
159
|
+
super()
|
|
149
160
|
end
|
|
150
|
-
else
|
|
151
|
-
__abs_eager_um__.bind_call(self)
|
|
152
161
|
end
|
|
153
162
|
end
|
|
154
163
|
|
|
@@ -183,48 +192,48 @@ class CArray
|
|
|
183
192
|
# ---------------------------------------------------------------------------
|
|
184
193
|
|
|
185
194
|
# @private
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
195
|
+
module LazyDispatch
|
|
196
|
+
def real
|
|
197
|
+
if lazy_view?
|
|
198
|
+
if complex?
|
|
199
|
+
float_dt = (data_type == CA_CMPLX64) ? CA_FLOAT32 : CA_FLOAT64
|
|
200
|
+
# float_dt is a Symbol; convert via data_type_code for kernel
|
|
201
|
+
# op_id arithmetic.
|
|
202
|
+
CAMonOp.__build__(self,
|
|
203
|
+
CAMonOp::CAST_BASE + CArray.data_type_code(float_dt))
|
|
204
|
+
else
|
|
205
|
+
# `real` of a real array is the array itself; preserve the lazy
|
|
206
|
+
# chain unchanged (eager returns self[] = CARefer wrap, but for
|
|
207
|
+
# lazy chain consumption returning self keeps streaming intact).
|
|
208
|
+
self
|
|
209
|
+
end
|
|
196
210
|
else
|
|
197
|
-
|
|
198
|
-
# chain unchanged (eager returns self[] = CARefer wrap, but for
|
|
199
|
-
# lazy chain consumption returning self keeps streaming intact).
|
|
200
|
-
self
|
|
211
|
+
super()
|
|
201
212
|
end
|
|
202
|
-
else
|
|
203
|
-
__real_eager_um__.bind_call(self)
|
|
204
213
|
end
|
|
205
214
|
end
|
|
206
215
|
|
|
207
216
|
# @!visibility private
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
217
|
+
module LazyDispatch
|
|
218
|
+
def imag
|
|
219
|
+
if lazy_view?
|
|
220
|
+
imag_i_node = CAMonOp.__build__(self, CAMonOp::OP_IMAG_I)
|
|
221
|
+
if boolean?
|
|
222
|
+
# imag_i reads a boolean as int64; the eager imag stays boolean.
|
|
223
|
+
CAMonOp.__build__(imag_i_node,
|
|
224
|
+
CAMonOp::CAST_BASE + CArray.data_type_code(CA_BOOLEAN))
|
|
225
|
+
elsif complex?
|
|
226
|
+
float_dt = (data_type == CA_CMPLX64) ? CA_FLOAT32 : CA_FLOAT64
|
|
227
|
+
# float_dt is a Symbol; convert via data_type_code for kernel
|
|
228
|
+
# op_id arithmetic.
|
|
229
|
+
CAMonOp.__build__(imag_i_node,
|
|
230
|
+
CAMonOp::CAST_BASE + CArray.data_type_code(float_dt))
|
|
231
|
+
else
|
|
232
|
+
imag_i_node
|
|
233
|
+
end
|
|
223
234
|
else
|
|
224
|
-
|
|
235
|
+
super()
|
|
225
236
|
end
|
|
226
|
-
else
|
|
227
|
-
__imag_eager_um__.bind_call(self)
|
|
228
237
|
end
|
|
229
238
|
end
|
|
230
239
|
|
|
@@ -247,29 +256,27 @@ class CArray
|
|
|
247
256
|
# ---------------------------------------------------------------------------
|
|
248
257
|
|
|
249
258
|
# @private
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
259
|
+
module LazyDispatch
|
|
260
|
+
def arg
|
|
261
|
+
if lazy_view?
|
|
262
|
+
return super() if boolean? # the eager arg refuses it
|
|
263
|
+
parent = self
|
|
264
|
+
if integer?
|
|
265
|
+
parent = CAMonOp.__build__(parent,
|
|
266
|
+
CAMonOp::CAST_BASE +
|
|
267
|
+
CArray.data_type_code(CA_FLOAT64))
|
|
268
|
+
end
|
|
269
|
+
arg_i_node = CAMonOp.__build__(parent, CAMonOp::OP_ARG_I)
|
|
270
|
+
if complex?
|
|
271
|
+
float_dt = (data_type == CA_CMPLX64) ? CA_FLOAT32 : CA_FLOAT64
|
|
272
|
+
CAMonOp.__build__(arg_i_node,
|
|
273
|
+
CAMonOp::CAST_BASE + CArray.data_type_code(float_dt))
|
|
274
|
+
else
|
|
275
|
+
arg_i_node
|
|
276
|
+
end
|
|
268
277
|
else
|
|
269
|
-
|
|
278
|
+
super()
|
|
270
279
|
end
|
|
271
|
-
else
|
|
272
|
-
__arg_eager_um__.bind_call(self)
|
|
273
280
|
end
|
|
274
281
|
end
|
|
275
282
|
|
|
@@ -323,30 +330,26 @@ class CArray
|
|
|
323
330
|
# branch uses C99 `remainder`, round-half-to-even).
|
|
324
331
|
}.freeze
|
|
325
332
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
define_method(method_name) do |other|
|
|
331
|
-
if __lazy_view__? || (other.is_a?(CArray) && other.__lazy_view__?)
|
|
332
|
-
CABinOp.__build__(self, other, op_id)
|
|
333
|
+
CArray.send(:define_named_methods, LazyDispatch, LAZY_BINOP_OP_IDS, template: <<~'RUBY')
|
|
334
|
+
def __NAME__(other)
|
|
335
|
+
if lazy_view? || (other.is_a?(CArray) && other.lazy_view?)
|
|
336
|
+
CABinOp.__build__(self, other, __VALUE__)
|
|
333
337
|
else
|
|
334
|
-
|
|
338
|
+
super(other)
|
|
335
339
|
end
|
|
336
340
|
end
|
|
337
|
-
|
|
341
|
+
RUBY
|
|
338
342
|
|
|
339
343
|
# The shift count of an Integer is brought into the array's type before
|
|
340
344
|
# either form sees it (see CArray::IntegerShiftCount).
|
|
341
345
|
prepend IntegerShiftCount
|
|
342
346
|
|
|
343
347
|
# Binop word aliases (`add` -> `+`, `mul` -> `*`, `bit_and` -> `&`, …) were
|
|
344
|
-
# installed by rb_define_alias at Init time (see
|
|
345
|
-
# ext/carray_kernels_*.c)
|
|
346
|
-
#
|
|
347
|
-
#
|
|
348
|
-
#
|
|
349
|
-
# word form follows the redefined operator method.
|
|
348
|
+
# installed in CArray by rb_define_alias at Init time (see
|
|
349
|
+
# MkKernel.alias_binop in ext/carray_kernels_*.c) and name the eager C
|
|
350
|
+
# function, so `a.lazy.add(1)` would materialise. Made again here, an
|
|
351
|
+
# alias resolves through the prepended modules -- IntegerShiftCount, then
|
|
352
|
+
# LazyDispatch -- so the word form takes the operator's.
|
|
350
353
|
{
|
|
351
354
|
add: :+,
|
|
352
355
|
sub: :-,
|
|
@@ -359,21 +362,20 @@ class CArray
|
|
|
359
362
|
bit_lshift: :<<,
|
|
360
363
|
bit_rshift: :>>,
|
|
361
364
|
}.each do |word, op|
|
|
362
|
-
alias_method
|
|
365
|
+
alias_method word, op
|
|
363
366
|
end
|
|
364
367
|
|
|
365
368
|
# `pow` is the canonical C method (defined by rb_define_method in
|
|
366
369
|
# ext/ca_op_ipower.c) that `**` is rb_define_alias'd to. The `**`
|
|
367
|
-
#
|
|
368
|
-
#
|
|
369
|
-
# falls to eager. Re-alias so `pow` follows the redefined `**`.
|
|
370
|
+
# dispatch in this file does not reach `pow` through the C alias, so
|
|
371
|
+
# `a.lazy.pow(2)` would fall to eager; `pow` is aliased again here.
|
|
370
372
|
alias_method :pow, :**
|
|
371
373
|
|
|
372
374
|
# `fmax` / `fmin` are rb_define_alias'd to `pmax` / `pmin` at Init
|
|
373
|
-
# time (same C
|
|
374
|
-
#
|
|
375
|
-
alias_method :fmax, :pmax
|
|
376
|
-
alias_method :fmin, :pmin
|
|
375
|
+
# time (the same C alias); they are aliased again beside them, in
|
|
376
|
+
# LazyDispatch.
|
|
377
|
+
LazyDispatch.send(:alias_method, :fmax, :pmax)
|
|
378
|
+
LazyDispatch.send(:alias_method, :fmin, :pmin)
|
|
377
379
|
|
|
378
380
|
# ---------------------------------------------------------------------------
|
|
379
381
|
# Triop dispatch (fma / fms / clip). CATriOp is the CABinOp analog for
|
|
@@ -381,7 +383,7 @@ class CArray
|
|
|
381
383
|
# dispatches to CATriOp.__build__ when any of self / op2 / op3 is a
|
|
382
384
|
# lazy view, and falls to the eager C method otherwise.
|
|
383
385
|
#
|
|
384
|
-
# `clip` is the strict-clamp entry (`
|
|
386
|
+
# `clip` is the strict-clamp entry (`clamp_between`, called by the
|
|
385
387
|
# lib/carray/basics.rb `clip` wrapper's both-bounds-present path). The
|
|
386
388
|
# nil-bound one-sided cases route through the wrapper's `pmax` / `pmin`
|
|
387
389
|
# calls, which themselves lazy-fuse via LAZY_BINOP_OP_IDS above — so
|
|
@@ -390,26 +392,26 @@ class CArray
|
|
|
390
392
|
# ---------------------------------------------------------------------------
|
|
391
393
|
|
|
392
394
|
LAZY_TRIOP_OP_IDS = {
|
|
393
|
-
fma:
|
|
394
|
-
fms:
|
|
395
|
-
|
|
395
|
+
fma: CATriOp::OP_FMA,
|
|
396
|
+
fms: CATriOp::OP_FMS,
|
|
397
|
+
clamp_between: CATriOp::OP_CLIP,
|
|
396
398
|
}.freeze
|
|
397
399
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
lazy_receiver = __lazy_view__? ||
|
|
404
|
-
(op2.is_a?(CArray) && op2.__lazy_view__?) ||
|
|
405
|
-
(op3.is_a?(CArray) && op3.__lazy_view__?)
|
|
400
|
+
CArray.send(:define_named_methods, LazyDispatch, LAZY_TRIOP_OP_IDS, template: <<~'RUBY')
|
|
401
|
+
def __NAME__(op2, op3)
|
|
402
|
+
lazy_receiver = lazy_view? ||
|
|
403
|
+
(op2.is_a?(CArray) && op2.lazy_view?) ||
|
|
404
|
+
(op3.is_a?(CArray) && op3.lazy_view?)
|
|
406
405
|
if lazy_receiver
|
|
407
|
-
CATriOp.__build__(self, op2, op3,
|
|
406
|
+
CATriOp.__build__(self, op2, op3, __VALUE__)
|
|
408
407
|
else
|
|
409
|
-
|
|
408
|
+
super(op2, op3)
|
|
410
409
|
end
|
|
411
410
|
end
|
|
412
|
-
|
|
411
|
+
RUBY
|
|
412
|
+
# The clip kernel takes both bounds; the public entry is `clip`.
|
|
413
|
+
private :clamp_between
|
|
414
|
+
LazyDispatch.send(:private, :clamp_between)
|
|
413
415
|
|
|
414
416
|
# `**` integer-exponent lazy fast path.
|
|
415
417
|
#
|
|
@@ -431,16 +433,17 @@ class CArray
|
|
|
431
433
|
# `power` binop kernel already uses `op_powi_<type>` for integer data_types
|
|
432
434
|
# via the `int:` expr in MkKernel.binop :power, so OP_POW + int parent
|
|
433
435
|
# is already fast. The lazy-substrate gap was Float/Complex only.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
436
|
+
module LazyDispatch
|
|
437
|
+
def **(other)
|
|
438
|
+
if other.is_a?(Integer) && (float? || complex?) &&
|
|
439
|
+
(lazy_view? || (other.is_a?(CArray) && other.lazy_view?))
|
|
440
|
+
CABinOp.__build__(self, CScalar.int64.tap { |s| s[0] = other },
|
|
441
|
+
CABinOp::OP_IPOWER)
|
|
442
|
+
elsif lazy_view? || (other.is_a?(CArray) && other.lazy_view?)
|
|
443
|
+
CABinOp.__build__(self, other, CABinOp::OP_POW)
|
|
444
|
+
else
|
|
445
|
+
super(other)
|
|
446
|
+
end
|
|
444
447
|
end
|
|
445
448
|
end
|
|
446
449
|
|
|
@@ -486,40 +489,34 @@ class CArray
|
|
|
486
489
|
:feq => CABinCmp::OP_FEQ,
|
|
487
490
|
}.freeze
|
|
488
491
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
define_method(method_name) do |other|
|
|
494
|
-
if __lazy_view__? || (other.is_a?(CArray) && other.__lazy_view__?)
|
|
495
|
-
CABinCmp.__build__(self, other, op_id)
|
|
492
|
+
CArray.send(:define_named_methods, LazyDispatch, LAZY_BINCMP_OP_IDS, template: <<~'RUBY')
|
|
493
|
+
def __NAME__(other)
|
|
494
|
+
if lazy_view? || (other.is_a?(CArray) && other.lazy_view?)
|
|
495
|
+
CABinCmp.__build__(self, other, __VALUE__)
|
|
496
496
|
else
|
|
497
|
-
|
|
497
|
+
super(other)
|
|
498
498
|
end
|
|
499
499
|
end
|
|
500
|
-
|
|
500
|
+
RUBY
|
|
501
501
|
|
|
502
502
|
# tolerance-bearing bincmp ops (= is_close / is_equiv) use the same
|
|
503
503
|
# CABinCmp dispatch but with a 2nd `tol` positional arg. Kept in a
|
|
504
|
-
# separate dict because the LAZY_BINCMP_OP_IDS
|
|
504
|
+
# separate dict because the LAZY_BINCMP_OP_IDS template above
|
|
505
505
|
# uses arity 1 (|other|); these need arity 2 (|other, tol|).
|
|
506
506
|
LAZY_BINCMP_TOL_OP_IDS = {
|
|
507
507
|
:is_close => CABinCmp::OP_IS_CLOSE,
|
|
508
508
|
:is_equiv => CABinCmp::OP_IS_EQUIV,
|
|
509
509
|
}.freeze
|
|
510
510
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
define_method(method_name) do |other, tol|
|
|
516
|
-
if __lazy_view__? || (other.is_a?(CArray) && other.__lazy_view__?)
|
|
517
|
-
CABinCmp.__build__(self, other, op_id, tol.to_f.abs)
|
|
511
|
+
CArray.send(:define_named_methods, LazyDispatch, LAZY_BINCMP_TOL_OP_IDS, template: <<~'RUBY')
|
|
512
|
+
def __NAME__(other, tol)
|
|
513
|
+
if lazy_view? || (other.is_a?(CArray) && other.lazy_view?)
|
|
514
|
+
CABinCmp.__build__(self, other, __VALUE__, tol.to_f.abs)
|
|
518
515
|
else
|
|
519
|
-
|
|
516
|
+
super(other, tol)
|
|
520
517
|
end
|
|
521
518
|
end
|
|
522
|
-
|
|
519
|
+
RUBY
|
|
523
520
|
|
|
524
521
|
# @!visibility private
|
|
525
522
|
LAZY_MONCMP_OP_IDS = {
|
|
@@ -530,32 +527,29 @@ class CArray
|
|
|
530
527
|
signbit: CAMonCmp::OP_SIGNBIT,
|
|
531
528
|
}.freeze
|
|
532
529
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
define_method(name) do
|
|
538
|
-
if __lazy_view__?
|
|
539
|
-
CAMonCmp.__build__(self, op_id)
|
|
530
|
+
CArray.send(:define_named_methods, LazyDispatch, LAZY_MONCMP_OP_IDS, template: <<~'RUBY')
|
|
531
|
+
def __NAME__
|
|
532
|
+
if lazy_view?
|
|
533
|
+
CAMonCmp.__build__(self, __VALUE__)
|
|
540
534
|
else
|
|
541
|
-
|
|
535
|
+
super()
|
|
542
536
|
end
|
|
543
537
|
end
|
|
544
|
-
|
|
538
|
+
RUBY
|
|
545
539
|
|
|
546
540
|
# A lazy receiver takes the scalar the eager coerce makes, and stays
|
|
547
541
|
# lazy itself: the builder promotes the pair as the eager operator does.
|
|
548
542
|
# @!visibility private
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
543
|
+
module LazyDispatch
|
|
544
|
+
def coerce(other)
|
|
545
|
+
begin
|
|
546
|
+
scalar, receiver = super(other)
|
|
547
|
+
rescue RangeError => e
|
|
548
|
+
raise unless other.is_a?(Integer)
|
|
549
|
+
return [OutOfRangeInteger.new(other, self, e), self]
|
|
550
|
+
end
|
|
551
|
+
lazy_view? ? [scalar, self] : [scalar, receiver]
|
|
557
552
|
end
|
|
558
|
-
__lazy_view__? ? [scalar, self] : [scalar, receiver]
|
|
559
553
|
end
|
|
560
554
|
|
|
561
555
|
# An Integer the array's type cannot hold, on the left of an operator.
|
|
@@ -880,8 +874,13 @@ class << CArray
|
|
|
880
874
|
# is not an answer: one that raises is dropped, with a warning, and
|
|
881
875
|
# expressions are walked from there on.
|
|
882
876
|
#
|
|
877
|
+
# Only the main Ractor asks it: it is registered there, and is not
|
|
878
|
+
# shared with the others, where expressions are walked.
|
|
879
|
+
#
|
|
883
880
|
# @return [#call, nil]
|
|
884
|
-
|
|
881
|
+
def expression_evaluator
|
|
882
|
+
Ractor.current == Ractor.main ? @expression_evaluator : nil
|
|
883
|
+
end
|
|
885
884
|
|
|
886
885
|
# @param object [#call, nil] see {#expression_evaluator}
|
|
887
886
|
# @raise [ArgumentError] when it cannot be called.
|