carray 3.0.1 → 3.0.3
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 +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/extconf.rb
CHANGED
|
@@ -107,6 +107,17 @@ if enable_config("dev-build", false)
|
|
|
107
107
|
$stderr.puts "carray: CARRAY_DEV_BUILD enabled (smoke surface available)"
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
+
# --- signed overflow wraps (`-fwrapv`)
|
|
111
|
+
#
|
|
112
|
+
# An integer kernel that overflows answers modulo 2^N. C leaves signed
|
|
113
|
+
# overflow undefined, and a compiler that sees several operations at once
|
|
114
|
+
# rewrites them as if it could not happen -- `(x + 1) > x` becomes true --
|
|
115
|
+
# which carray-jit's fused expressions, built with these flags, would show.
|
|
116
|
+
if try_compile("int main(void) { return 0; }", "-fwrapv")
|
|
117
|
+
$CFLAGS += " -fwrapv"
|
|
118
|
+
$carray_build_flags << "-fwrapv"
|
|
119
|
+
end
|
|
120
|
+
|
|
110
121
|
# --- probe for `-fopenmp-simd` (SL.1.0, PROPOSAL_REDUCTION_SIMD_LICENSE)
|
|
111
122
|
#
|
|
112
123
|
# `-fopenmp-simd` enables `#pragma omp simd` (and its `reduction(+:acc)`
|
|
@@ -257,6 +268,8 @@ $INSTALLFILES << ['carray_config.h', '$(archdir)']
|
|
|
257
268
|
# (b) Not in the closure, but written for ext authors to include
|
|
258
269
|
# explicitly. ca_obj_face.h is the Face authoring surface: an
|
|
259
270
|
# external gem defines its own Face by including it directly.
|
|
271
|
+
# ca_for_buffer.h is whole-buffer delivery to an external library;
|
|
272
|
+
# it pulls ca_sweep_engine.h.
|
|
260
273
|
#
|
|
261
274
|
# A header that is neither is internal, however useful it looks in-tree.
|
|
262
275
|
# ca_op_powi.h (op_powi_<type> helpers for the generated kernels) and
|
|
@@ -272,11 +285,14 @@ $INSTALLFILES << ['carray_config.h', '$(archdir)']
|
|
|
272
285
|
ca_axis_descriptor.h
|
|
273
286
|
ca_monop_dispatch.h
|
|
274
287
|
ca_binop_dispatch.h
|
|
288
|
+
ca_triop_dispatch.h
|
|
275
289
|
ca_bincmp_dispatch.h
|
|
276
290
|
ca_moncmp_dispatch.h
|
|
277
291
|
ca_kernel_iterator.h
|
|
278
292
|
ca_iter_substrate.h
|
|
279
293
|
ca_obj_face.h
|
|
294
|
+
ca_for_buffer.h
|
|
295
|
+
ca_sweep_engine.h
|
|
280
296
|
].each do |h|
|
|
281
297
|
$INSTALLFILES << [h, '$(archdir)']
|
|
282
298
|
end
|
|
@@ -324,11 +340,14 @@ end
|
|
|
324
340
|
# compiling static sources, which is one pass with no race.
|
|
325
341
|
#
|
|
326
342
|
# carray_kernels.stamp is the mtime witness:
|
|
327
|
-
# - here: regenerate and touch it when mkkernel.rb
|
|
343
|
+
# - here: regenerate and touch it when mkkernel.rb or ca_op_powi.h (whose
|
|
344
|
+
# helper text the generator copies) is newer
|
|
328
345
|
# - in the Rakefile (rake build_ext): the same stamp triggers need_extconf
|
|
329
346
|
CARRAY_KERNELS_STAMP = "carray_kernels.stamp"
|
|
330
347
|
if ( not File.exist?(CARRAY_KERNELS_STAMP) ) or
|
|
331
|
-
|
|
348
|
+
%w[mkkernel.rb ca_op_powi.h].any? { |f|
|
|
349
|
+
File.stat(f).mtime > File.stat(CARRAY_KERNELS_STAMP).mtime
|
|
350
|
+
}
|
|
332
351
|
# passing "." makes the generator write the split files into ext/
|
|
333
352
|
unless system("ruby mkkernel.rb .")
|
|
334
353
|
raise "mkkernel.rb failed to generate split kernel files"
|
|
@@ -346,6 +365,12 @@ if Dir.glob("carray_kernels_*.c").empty?
|
|
|
346
365
|
raise "no carray_kernels_*.c files found after mkkernel.rb; check the generator"
|
|
347
366
|
end
|
|
348
367
|
|
|
368
|
+
# The 5^q table the decimal-to-double reader (carray_cast.c) multiplies by.
|
|
369
|
+
if ( not File.exist?("ca_pow5_table.h") ) or
|
|
370
|
+
File.stat("mk_pow5_table.rb").mtime > File.stat("ca_pow5_table.h").mtime
|
|
371
|
+
system("ruby mk_pow5_table.rb")
|
|
372
|
+
end
|
|
373
|
+
|
|
349
374
|
if ( not File.exist?("carray_call_cfunc.c") ) or
|
|
350
375
|
( not File.exist?("carray_call_cfunc.h") ) or
|
|
351
376
|
File.stat("mk_call_cfunc.rb").mtime > File.stat("carray_call_cfunc.c").mtime
|
data/ext/mk_call_cfunc.rb
CHANGED
|
@@ -128,83 +128,61 @@ def indent(s, prefix = " ")
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
# --- raw ca_call_cfunc_N ----------------------------------------------------
|
|
131
|
+
#
|
|
132
|
+
# The per-cell loop runs in a walker function of its own, handed to
|
|
133
|
+
# ca_sweep_run: a callback that raises part way through gives back the
|
|
134
|
+
# operands and scratch the engine holds, rather than leaving them behind.
|
|
135
|
+
#
|
|
136
|
+
# The `_r` variant (reentrant: + void *userdata at signature tail) passes a
|
|
137
|
+
# trailing `void *userdata` through to every per-cell `func(...)`
|
|
138
|
+
# invocation as its last argument. Naming follows POSIX convention
|
|
139
|
+
# (qsort_r / bsearch_r / strtok_r), where `_r` marks a reentrant form that
|
|
140
|
+
# takes a thunk so the callback no longer depends on file-static / global
|
|
141
|
+
# state. Use when the callback needs to share state with the caller (e.g.
|
|
142
|
+
# accumulators, configuration flags, library plan handles) without
|
|
143
|
+
# resorting to file-static plumbing.
|
|
144
|
+
def emit_raw_common(n, r:)
|
|
145
|
+
name = r ? "ca_call_cfunc_#{n}_r" : "ca_call_cfunc_#{n}"
|
|
146
|
+
fsig = r ? void_p_list_r(n) : void_p_list(n)
|
|
147
|
+
call = "c->func(#{args_p(n)}#{r ? ", c->userdata" : ""})"
|
|
131
148
|
|
|
132
|
-
def emit_raw(n)
|
|
133
|
-
$src.puts sig_raw(n)
|
|
134
|
-
$src.puts "{"
|
|
135
|
-
$src.puts indent(<<~END_C)
|
|
136
|
-
CArray *cx[#{n}];
|
|
137
|
-
char *base[#{n}];
|
|
138
|
-
ca_size_t stride[#{n}];
|
|
139
|
-
char *owned_buf[#{n}];
|
|
140
|
-
int attached[#{n}];
|
|
141
|
-
ca_sweep_state_t state;
|
|
142
|
-
int k_op;
|
|
143
|
-
|
|
144
|
-
END_C
|
|
145
|
-
# extract CArray* from VALUE
|
|
146
|
-
(0...n).each do |k|
|
|
147
|
-
$src.puts " TypedData_Get_Struct(rcx#{k}, CArray, &carray_data_type, cx[#{k}]);"
|
|
148
|
-
end
|
|
149
|
-
$src.puts ""
|
|
150
149
|
$src.puts <<~END_C
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
char *p[#{n}];
|
|
169
|
-
ca_size_t k;
|
|
170
|
-
if ( state.m0 ) {
|
|
171
|
-
for ( k = 0; k < state.n_kernel; k++ ) {
|
|
172
|
-
if ( ! state.m0[k] ) {
|
|
173
|
-
for ( k_op = 0; k_op < #{n}; k_op++ ) {
|
|
174
|
-
p[k_op] = base[k_op] + k * stride[k_op];
|
|
175
|
-
}
|
|
176
|
-
func(#{args_p(n)});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
for ( k = 0; k < state.n_kernel; k++ ) {
|
|
150
|
+
typedef struct {
|
|
151
|
+
ca_sweep_state_t *st;
|
|
152
|
+
void (*func)(#{fsig});
|
|
153
|
+
void *userdata;
|
|
154
|
+
} #{name}_ctx_t;
|
|
155
|
+
|
|
156
|
+
static VALUE
|
|
157
|
+
#{name}_walk (VALUE arg)
|
|
158
|
+
{
|
|
159
|
+
#{name}_ctx_t *c = (#{name}_ctx_t *) arg;
|
|
160
|
+
ca_sweep_state_t *st = c->st;
|
|
161
|
+
char *p[#{n}];
|
|
162
|
+
ca_size_t k;
|
|
163
|
+
int k_op;
|
|
164
|
+
if ( st->m0 ) {
|
|
165
|
+
for ( k = 0; k < st->n_kernel; k++ ) {
|
|
166
|
+
if ( ! st->m0[k] ) {
|
|
181
167
|
for ( k_op = 0; k_op < #{n}; k_op++ ) {
|
|
182
|
-
p[k_op] = base[k_op] + k * stride[k_op];
|
|
168
|
+
p[k_op] = st->base[k_op] + k * st->stride[k_op];
|
|
183
169
|
}
|
|
184
|
-
|
|
170
|
+
#{call};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
for ( k = 0; k < st->n_kernel; k++ ) {
|
|
175
|
+
for ( k_op = 0; k_op < #{n}; k_op++ ) {
|
|
176
|
+
p[k_op] = st->base[k_op] + k * st->stride[k_op];
|
|
185
177
|
}
|
|
178
|
+
#{call};
|
|
186
179
|
}
|
|
187
180
|
}
|
|
188
|
-
|
|
189
|
-
ca_sweep_release(&state);
|
|
190
|
-
|
|
191
|
-
return rcx0;
|
|
181
|
+
return Qnil;
|
|
192
182
|
}
|
|
193
183
|
|
|
194
184
|
END_C
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
# --- raw ca_call_cfunc_N_r (reentrant: + void *userdata at signature tail) --
|
|
198
|
-
#
|
|
199
|
-
# Variant of emit_raw with a trailing `void *userdata` parameter passed
|
|
200
|
-
# through to every per-cell `func(...)` invocation as its last argument.
|
|
201
|
-
# Naming follows POSIX convention (qsort_r / bsearch_r / strtok_r), where
|
|
202
|
-
# `_r` marks a reentrant form that takes a thunk so the callback no longer
|
|
203
|
-
# depends on file-static / global state. Use when the callback needs to
|
|
204
|
-
# share state with the caller (e.g. accumulators, configuration flags,
|
|
205
|
-
# library plan handles) without resorting to file-static plumbing.
|
|
206
|
-
def emit_raw_r(n)
|
|
207
|
-
$src.puts sig_raw_r(n)
|
|
185
|
+
$src.puts(r ? sig_raw_r(n) : sig_raw(n))
|
|
208
186
|
$src.puts "{"
|
|
209
187
|
$src.puts indent(<<~END_C)
|
|
210
188
|
CArray *cx[#{n}];
|
|
@@ -213,7 +191,7 @@ def emit_raw_r(n)
|
|
|
213
191
|
char *owned_buf[#{n}];
|
|
214
192
|
int attached[#{n}];
|
|
215
193
|
ca_sweep_state_t state;
|
|
216
|
-
|
|
194
|
+
#{name}_ctx_t ctx;
|
|
217
195
|
|
|
218
196
|
END_C
|
|
219
197
|
(0...n).each do |k|
|
|
@@ -221,8 +199,9 @@ def emit_raw_r(n)
|
|
|
221
199
|
end
|
|
222
200
|
$src.puts ""
|
|
223
201
|
$src.puts <<~END_C
|
|
224
|
-
/* sweep engine:
|
|
225
|
-
|
|
202
|
+
/* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
|
|
203
|
+
operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
|
|
204
|
+
Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
|
|
226
205
|
state.n_ops = #{n};
|
|
227
206
|
state.fsync = fsync;
|
|
228
207
|
state.cx = cx;
|
|
@@ -230,34 +209,14 @@ def emit_raw_r(n)
|
|
|
230
209
|
state.stride = stride;
|
|
231
210
|
state.owned_buf = owned_buf;
|
|
232
211
|
state.attached = attached;
|
|
233
|
-
state.
|
|
234
|
-
state.src_label = "ca_call_cfunc_#{n}_r";
|
|
212
|
+
state.src_label = "#{name}";
|
|
235
213
|
|
|
236
214
|
ca_sweep_acquire(&state);
|
|
237
215
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
for ( k = 0; k < state.n_kernel; k++ ) {
|
|
243
|
-
if ( ! state.m0[k] ) {
|
|
244
|
-
for ( k_op = 0; k_op < #{n}; k_op++ ) {
|
|
245
|
-
p[k_op] = base[k_op] + k * stride[k_op];
|
|
246
|
-
}
|
|
247
|
-
func(#{args_p_r(n)});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
} else {
|
|
251
|
-
for ( k = 0; k < state.n_kernel; k++ ) {
|
|
252
|
-
for ( k_op = 0; k_op < #{n}; k_op++ ) {
|
|
253
|
-
p[k_op] = base[k_op] + k * stride[k_op];
|
|
254
|
-
}
|
|
255
|
-
func(#{args_p_r(n)});
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
ca_sweep_release(&state);
|
|
216
|
+
ctx.st = &state;
|
|
217
|
+
ctx.func = func;
|
|
218
|
+
ctx.userdata = #{r ? "userdata" : "NULL"};
|
|
219
|
+
ca_sweep_run(&state, #{name}_walk, (VALUE) &ctx);
|
|
261
220
|
|
|
262
221
|
return rcx0;
|
|
263
222
|
}
|
|
@@ -265,6 +224,9 @@ def emit_raw_r(n)
|
|
|
265
224
|
END_C
|
|
266
225
|
end
|
|
267
226
|
|
|
227
|
+
def emit_raw(n) ; emit_raw_common(n, r: false); end
|
|
228
|
+
def emit_raw_r(n) ; emit_raw_common(n, r: true); end
|
|
229
|
+
|
|
268
230
|
# --- typed dispatchers: M outputs, N inputs ---------------------------------
|
|
269
231
|
#
|
|
270
232
|
# The four typed emitters (cfunc / cfunc_r / cslab / cslab_r) differ in one
|
|
@@ -418,7 +380,7 @@ def sig_slab_r(n)
|
|
|
418
380
|
"VALUE\nca_call_cslab_#{n}_r (ca_cslab_r_t func, const char *fsync,\n #{value_param_list(n)},\n void *userdata)"
|
|
419
381
|
end
|
|
420
382
|
|
|
421
|
-
def emit_slab_body(n, name,
|
|
383
|
+
def emit_slab_body(n, name, walker, userdata)
|
|
422
384
|
$src.puts indent(<<~END_C)
|
|
423
385
|
CArray *cx[#{n}];
|
|
424
386
|
char *base[#{n}];
|
|
@@ -427,6 +389,7 @@ def emit_slab_body(n, name, call)
|
|
|
427
389
|
char *owned_buf[#{n}];
|
|
428
390
|
int attached[#{n}];
|
|
429
391
|
ca_sweep_state_t state;
|
|
392
|
+
ca_cslab_ctx_t ctx;
|
|
430
393
|
|
|
431
394
|
END_C
|
|
432
395
|
(0...n).each do |k|
|
|
@@ -448,21 +411,15 @@ def emit_slab_body(n, name, call)
|
|
|
448
411
|
state.stride = stride;
|
|
449
412
|
state.owned_buf = owned_buf;
|
|
450
413
|
state.attached = attached;
|
|
451
|
-
state.no_mask = 0;
|
|
452
414
|
state.src_label = "#{name}";
|
|
453
415
|
|
|
454
416
|
ca_sweep_acquire_chunked(&state);
|
|
455
417
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
while ( ca_sweep_next_chunk(&state) ) {
|
|
462
|
-
#{call};
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
ca_sweep_release_chunked(&state);
|
|
418
|
+
ctx.st = &state;
|
|
419
|
+
ctx.func = #{userdata == "NULL" ? "func" : "NULL"};
|
|
420
|
+
ctx.func_r = #{userdata == "NULL" ? "NULL" : "func"};
|
|
421
|
+
ctx.userdata = #{userdata};
|
|
422
|
+
ca_sweep_run_chunked(&state, #{walker}, (VALUE) &ctx);
|
|
466
423
|
|
|
467
424
|
return rcx0;
|
|
468
425
|
}
|
|
@@ -473,8 +430,7 @@ end
|
|
|
473
430
|
def emit_slab(n)
|
|
474
431
|
$src.puts sig_slab(n)
|
|
475
432
|
$src.puts "{"
|
|
476
|
-
emit_slab_body(n, "ca_call_cslab_#{n}",
|
|
477
|
-
"func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state))")
|
|
433
|
+
emit_slab_body(n, "ca_call_cslab_#{n}", "ca_cslab_walk", "NULL")
|
|
478
434
|
end
|
|
479
435
|
|
|
480
436
|
# Variant of emit_slab with a trailing `void *userdata` parameter passed
|
|
@@ -483,8 +439,7 @@ end
|
|
|
483
439
|
def emit_slab_r(n)
|
|
484
440
|
$src.puts sig_slab_r(n)
|
|
485
441
|
$src.puts "{"
|
|
486
|
-
emit_slab_body(n, "ca_call_cslab_#{n}_r",
|
|
487
|
-
"func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata)")
|
|
442
|
+
emit_slab_body(n, "ca_call_cslab_#{n}_r", "ca_cslab_r_walk", "userdata")
|
|
488
443
|
end
|
|
489
444
|
|
|
490
445
|
# --- header declaration emitters --------------------------------------------
|
|
@@ -557,14 +512,44 @@ $src.puts <<~END_C
|
|
|
557
512
|
#include "ca_sweep_engine.h"
|
|
558
513
|
#include <string.h>
|
|
559
514
|
|
|
560
|
-
/*
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
515
|
+
/* Chunk walk for the ca_call_cslab_N family, run by ca_sweep_run_chunked
|
|
516
|
+
so that a callback raising part way through gives back what the engine
|
|
517
|
+
holds. Hands the author one chunk at a time. base[] is rewritten per
|
|
518
|
+
chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points at the
|
|
519
|
+
arena scratch the chunk was just gathered into, which is packed, so
|
|
520
|
+
stride[] is the element size and the author's inner loop sees
|
|
521
|
+
contiguous data. m0 is the chunk's iteration mask, or NULL when no
|
|
522
|
+
INPUT operand carried one: chunk-sized and re-gathered per chunk, so it
|
|
523
|
+
is already the slice -- one byte per cell, indexed 0..chunk_n-1
|
|
524
|
+
alongside base[] and stride[]. The arity does not appear here: the
|
|
525
|
+
operands reach the callback through base[] / stride[]. */
|
|
526
|
+
typedef struct {
|
|
527
|
+
ca_sweep_state_t *st;
|
|
528
|
+
ca_cslab_t func; /* ca_call_cslab_N */
|
|
529
|
+
ca_cslab_r_t func_r; /* ca_call_cslab_N_r */
|
|
530
|
+
void *userdata;
|
|
531
|
+
} ca_cslab_ctx_t;
|
|
532
|
+
|
|
533
|
+
static VALUE
|
|
534
|
+
ca_cslab_walk (VALUE arg)
|
|
566
535
|
{
|
|
567
|
-
|
|
536
|
+
ca_cslab_ctx_t *c = (ca_cslab_ctx_t *) arg;
|
|
537
|
+
ca_sweep_state_t *st = c->st;
|
|
538
|
+
while ( ca_sweep_next_chunk(st) ) {
|
|
539
|
+
c->func(st->base, st->stride, st->chunk_n, st->m0);
|
|
540
|
+
}
|
|
541
|
+
return Qnil;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
static VALUE
|
|
545
|
+
ca_cslab_r_walk (VALUE arg)
|
|
546
|
+
{
|
|
547
|
+
ca_cslab_ctx_t *c = (ca_cslab_ctx_t *) arg;
|
|
548
|
+
ca_sweep_state_t *st = c->st;
|
|
549
|
+
while ( ca_sweep_next_chunk(st) ) {
|
|
550
|
+
c->func_r(st->base, st->stride, st->chunk_n, st->m0, c->userdata);
|
|
551
|
+
}
|
|
552
|
+
return Qnil;
|
|
568
553
|
}
|
|
569
554
|
|
|
570
555
|
END_C
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generates ca_pow5_table.h: for each decimal exponent q in [-342, 308], a
|
|
2
|
+
# 128-bit approximation of 5^q scaled by a power of two into [2^127, 2^128),
|
|
3
|
+
# as the Eisel-Lemire decimal-to-binary64 conversion takes it.
|
|
4
|
+
#
|
|
5
|
+
# q >= 0: floor(5^q * 2^k) (exact while 5^q < 2^128, q <= 55)
|
|
6
|
+
# -27 <= q < 0: ceil(2^k / 5^-q)
|
|
7
|
+
# q < -27: floor(2^k / 5^-q)
|
|
8
|
+
# with k chosen so the value has exactly 128 bits.
|
|
9
|
+
|
|
10
|
+
Q_MIN, Q_MAX = -342, 308
|
|
11
|
+
rows = (Q_MIN..Q_MAX).map do |q|
|
|
12
|
+
if q >= 0
|
|
13
|
+
v = 5**q
|
|
14
|
+
v <<= 128 - v.bit_length if v.bit_length < 128
|
|
15
|
+
v >>= v.bit_length - 128 if v.bit_length > 128
|
|
16
|
+
else
|
|
17
|
+
p5 = 5**-q
|
|
18
|
+
k = 127 + p5.bit_length
|
|
19
|
+
v, r = (1 << k).divmod(p5)
|
|
20
|
+
v += 1 if q >= -27 && r != 0
|
|
21
|
+
v >>= v.bit_length - 128 if v.bit_length > 128
|
|
22
|
+
v <<= 128 - v.bit_length if v.bit_length < 128
|
|
23
|
+
end
|
|
24
|
+
raise "bad width at #{q}" unless v.bit_length == 128
|
|
25
|
+
[v >> 64, v & ((1 << 64) - 1)]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
File.open(File.join(__dir__, "ca_pow5_table.h"), "w") do |f|
|
|
29
|
+
f.puts "/* Generated by mk_pow5_table.rb -- do not edit. */"
|
|
30
|
+
f.puts "#define CA_POW5_Q_MIN (#{Q_MIN})"
|
|
31
|
+
f.puts "#define CA_POW5_Q_MAX #{Q_MAX}"
|
|
32
|
+
f.puts "static const uint64_t ca_pow5_table[#{rows.size * 2}] = {"
|
|
33
|
+
rows.each { |hi, lo| f.puts format(" 0x%016xULL, 0x%016xULL,", hi, lo) }
|
|
34
|
+
f.puts "};"
|
|
35
|
+
end
|