carray 3.0.1 → 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/CHANGELOG.md +520 -0
- data/README.md +2 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +33 -4
- data/ext/ca_axis_group.c +202 -96
- data/ext/ca_categorical_iterator.c +108 -54
- data/ext/ca_kernel_iterator.c +317 -51
- data/ext/ca_kernel_iterator.h +142 -35
- data/ext/ca_obj_array.c +62 -20
- data/ext/ca_obj_block.c +4 -4
- data/ext/ca_obj_const_string.c +85 -26
- data/ext/ca_obj_face.c +24 -0
- data/ext/ca_obj_face.h +15 -0
- data/ext/ca_obj_fixlen_string.c +18 -5
- data/ext/ca_obj_meld.c +123 -25
- data/ext/ca_obj_object.c +8 -0
- data/ext/ca_obj_select.c +49 -34
- data/ext/ca_obj_stack.c +3 -8
- data/ext/ca_obj_stride.c +72 -1
- data/ext/ca_obj_string.c +8 -4
- data/ext/ca_obj_window.c +8 -2
- data/ext/ca_op_ipower.c +1 -2
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sweep_engine.c +307 -143
- data/ext/ca_sweep_engine.h +26 -5
- data/ext/carray.h +21 -2
- data/ext/carray_access.c +32 -20
- data/ext/carray_address_basis.c +590 -0
- data/ext/carray_broadcast.c +3 -3
- data/ext/carray_call_cfunc.c +667 -483
- data/ext/carray_cast.c +115 -41
- data/ext/carray_copy.c +55 -30
- data/ext/carray_core.c +83 -3
- data/ext/carray_count.c +9 -10
- data/ext/carray_factorize.c +46 -25
- data/ext/carray_internal.h +17 -0
- data/ext/carray_kernels_reduce_aggregate.c +168 -0
- data/ext/carray_kernels_reduce_cumulative.c +270 -1
- data/ext/carray_kernels_reduce_extreme.c +554 -8
- data/ext/carray_kernels_scan.c +4 -4
- data/ext/carray_kernels_search.c +94 -14
- data/ext/carray_loop.c +7 -1
- data/ext/carray_mask.c +23 -8
- data/ext/carray_median_percentile.c +55 -0
- data/ext/carray_operator.c +4 -4
- data/ext/carray_order.c +1 -1
- data/ext/carray_random.c +384 -40
- data/ext/carray_slab.c +13 -0
- data/ext/carray_sort.c +20 -22
- data/ext/mk_call_cfunc.rb +103 -116
- data/ext/mkkernel.rb +297 -29
- data/ext/ruby_carray.c +10 -1
- data/ext/version.h +4 -4
- data/lib/carray/autoload_carray.rb +5 -3
- data/lib/carray/autoload_method_extension.rb +12 -0
- data/lib/carray/axis_group.rb +77 -0
- data/lib/carray/basics.rb +4 -0
- data/lib/carray/block_iterator.rb +92 -16
- data/lib/carray/categorical.rb +150 -33
- data/lib/carray/categorical_iterator.rb +207 -80
- data/lib/carray/const_string.rb +131 -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/csv_parser.rb +11 -4
- data/lib/carray/frame/frame.rb +81 -10
- data/lib/carray/frame/group.rb +36 -3
- data/lib/carray/frame/io.rb +67 -15
- data/lib/carray/frame/records.rb +18 -4
- data/lib/carray/frame/verbs.rb +14 -11
- data/lib/carray/inspect.rb +42 -9
- data/lib/carray/iterator.rb +143 -0
- data/lib/carray/lazy.rb +0 -37
- data/lib/carray/mask_gap_fill.rb +3 -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 +13 -2
- data/lib/carray/methods/locate_addr.rb +75 -2
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +110 -0
- data/lib/carray/methods/unique.rb +41 -1
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/slab_iterator.rb +58 -13
- data/lib/carray/string_operation_extension.rb +5 -1
- data/lib/carray/time.rb +18 -2
- data/lib/carray/window_iterator.rb +142 -20
- data/lib/carray.rb +2 -0
- data/yard-stubs/ca_obj_block.rb +2 -7
- data/yard-stubs/ca_obj_window.rb +10 -2
- data/yard-stubs/carray_access.rb +1 -1
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_core.rb +0 -80
- data/yard-stubs/carray_count.rb +7 -2
- data/yard-stubs/carray_lazy.rb +205 -0
- data/yard-stubs/carray_math.rb +1486 -3
- data/yard-stubs/carray_median_percentile.rb +16 -2
- data/yard-stubs/carray_order.rb +9 -69
- data/yard-stubs/carray_slab.rb +9 -7
- data/yard-stubs/carray_sort.rb +7 -5
- metadata +9 -1
data/ext/carray_sort.c
CHANGED
|
@@ -639,12 +639,20 @@ rb_ca_sorted_view (int argc, VALUE *argv, VALUE self)
|
|
|
639
639
|
* fiber, no pair struct, no view layer. This fast path is numeric-only
|
|
640
640
|
* and mask-free (CA_KERNEL_NO_MASK below).
|
|
641
641
|
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
642
|
+
* Everything the fast path does not cover -- any data_type outside
|
|
643
|
+
* CA_INT8..CA_FLOAT64 (fixlen, boolean, complex, object), and masked
|
|
644
|
+
* input of any type -- delegates to {sort} + copy rather than duplicate
|
|
645
|
+
* the fixlen dialect / the object comparator / the mask-position split
|
|
646
|
+
* in this per-fiber loop; masked_position: is forwarded unchanged.
|
|
647
|
+
* Masked cells keep their masked-ness (the view's remap gather carries
|
|
648
|
+
* the mask bit through, and .copy materializes it), clustered at
|
|
649
|
+
* masked_position: within each fiber -- same contract as {sort}.
|
|
650
|
+
*
|
|
651
|
+
* So sort_copy answers for exactly what sort answers for, which is what
|
|
652
|
+
* being its eager counterpart means. It once refused everything the
|
|
653
|
+
* fast path could not take: object and boolean sorted through {sort}
|
|
654
|
+
* but not through this, and complex reported its refusal in two
|
|
655
|
+
* different ways depending on which of the pair was asked.
|
|
648
656
|
*/
|
|
649
657
|
static VALUE
|
|
650
658
|
rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
@@ -677,11 +685,12 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
677
685
|
CArray *ca;
|
|
678
686
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
679
687
|
|
|
680
|
-
/*
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (
|
|
688
|
+
/* The per-fiber path below covers unmasked CA_INT8..CA_FLOAT64 only.
|
|
689
|
+
Everything else goes to {sort} (which handles the fixlen dialect,
|
|
690
|
+
the object comparator and the masked_position split) + copy, for the
|
|
691
|
+
same shape/class contract as the fast path. */
|
|
692
|
+
if ( ca->data_type < CA_INT8 || ca->data_type > CA_FLOAT64
|
|
693
|
+
|| ca_has_mask(ca) ) {
|
|
685
694
|
VALUE sv_kw = rb_hash_new();
|
|
686
695
|
if ( !NIL_P(vaxis) ) rb_hash_aset(sv_kw, ID2SYM(rb_intern("axis")), vaxis);
|
|
687
696
|
if ( !NIL_P(vkind) ) rb_hash_aset(sv_kw, ID2SYM(rb_intern("kind")), vkind);
|
|
@@ -717,17 +726,6 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
717
726
|
NUM2INT(vaxis_use), cat->ndim);
|
|
718
727
|
}
|
|
719
728
|
|
|
720
|
-
/* data_type check: ALL_NUMERIC only (CA_INT8..CA_FLOAT64).
|
|
721
|
-
Complex / object are rejected here; CA_OBJECT goes through the
|
|
722
|
-
axis: lift in rb_ca_sorted_view, and complex sort semantics
|
|
723
|
-
differ enough that we do not pick a default. */
|
|
724
|
-
if ( cat->data_type < CA_INT8 || cat->data_type > CA_FLOAT64 ) {
|
|
725
|
-
rb_raise(rb_eCADataTypeError,
|
|
726
|
-
"sort_copy: data_type %d not supported "
|
|
727
|
-
"(expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64)",
|
|
728
|
-
cat->data_type);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
729
|
/* Allocate output: same shape and data_type as target
|
|
732
730
|
(bytes=0 = preserve native bytes). */
|
|
733
731
|
volatile VALUE vout = rb_ca_template_with_type(target,
|
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;
|
|
@@ -231,33 +210,14 @@ def emit_raw_r(n)
|
|
|
231
210
|
state.owned_buf = owned_buf;
|
|
232
211
|
state.attached = attached;
|
|
233
212
|
state.no_mask = 0;
|
|
234
|
-
state.src_label = "
|
|
213
|
+
state.src_label = "#{name}";
|
|
235
214
|
|
|
236
215
|
ca_sweep_acquire(&state);
|
|
237
216
|
|
|
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);
|
|
217
|
+
ctx.st = &state;
|
|
218
|
+
ctx.func = func;
|
|
219
|
+
ctx.userdata = #{r ? "userdata" : "NULL"};
|
|
220
|
+
ca_sweep_run(&state, #{name}_walk, (VALUE) &ctx);
|
|
261
221
|
|
|
262
222
|
return rcx0;
|
|
263
223
|
}
|
|
@@ -265,6 +225,9 @@ def emit_raw_r(n)
|
|
|
265
225
|
END_C
|
|
266
226
|
end
|
|
267
227
|
|
|
228
|
+
def emit_raw(n) ; emit_raw_common(n, r: false); end
|
|
229
|
+
def emit_raw_r(n) ; emit_raw_common(n, r: true); end
|
|
230
|
+
|
|
268
231
|
# --- typed dispatchers: M outputs, N inputs ---------------------------------
|
|
269
232
|
#
|
|
270
233
|
# The four typed emitters (cfunc / cfunc_r / cslab / cslab_r) differ in one
|
|
@@ -418,7 +381,7 @@ def sig_slab_r(n)
|
|
|
418
381
|
"VALUE\nca_call_cslab_#{n}_r (ca_cslab_r_t func, const char *fsync,\n #{value_param_list(n)},\n void *userdata)"
|
|
419
382
|
end
|
|
420
383
|
|
|
421
|
-
def emit_slab_body(n, name,
|
|
384
|
+
def emit_slab_body(n, name, walker, userdata)
|
|
422
385
|
$src.puts indent(<<~END_C)
|
|
423
386
|
CArray *cx[#{n}];
|
|
424
387
|
char *base[#{n}];
|
|
@@ -427,6 +390,7 @@ def emit_slab_body(n, name, call)
|
|
|
427
390
|
char *owned_buf[#{n}];
|
|
428
391
|
int attached[#{n}];
|
|
429
392
|
ca_sweep_state_t state;
|
|
393
|
+
ca_cslab_ctx_t ctx;
|
|
430
394
|
|
|
431
395
|
END_C
|
|
432
396
|
(0...n).each do |k|
|
|
@@ -453,16 +417,11 @@ def emit_slab_body(n, name, call)
|
|
|
453
417
|
|
|
454
418
|
ca_sweep_acquire_chunked(&state);
|
|
455
419
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
while ( ca_sweep_next_chunk(&state) ) {
|
|
462
|
-
#{call};
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
ca_sweep_release_chunked(&state);
|
|
420
|
+
ctx.st = &state;
|
|
421
|
+
ctx.func = #{userdata == "NULL" ? "func" : "NULL"};
|
|
422
|
+
ctx.func_r = #{userdata == "NULL" ? "NULL" : "func"};
|
|
423
|
+
ctx.userdata = #{userdata};
|
|
424
|
+
ca_sweep_run_chunked(&state, #{walker}, (VALUE) &ctx);
|
|
466
425
|
|
|
467
426
|
return rcx0;
|
|
468
427
|
}
|
|
@@ -473,8 +432,7 @@ end
|
|
|
473
432
|
def emit_slab(n)
|
|
474
433
|
$src.puts sig_slab(n)
|
|
475
434
|
$src.puts "{"
|
|
476
|
-
emit_slab_body(n, "ca_call_cslab_#{n}",
|
|
477
|
-
"func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state))")
|
|
435
|
+
emit_slab_body(n, "ca_call_cslab_#{n}", "ca_cslab_walk", "NULL")
|
|
478
436
|
end
|
|
479
437
|
|
|
480
438
|
# Variant of emit_slab with a trailing `void *userdata` parameter passed
|
|
@@ -483,8 +441,7 @@ end
|
|
|
483
441
|
def emit_slab_r(n)
|
|
484
442
|
$src.puts sig_slab_r(n)
|
|
485
443
|
$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)")
|
|
444
|
+
emit_slab_body(n, "ca_call_cslab_#{n}_r", "ca_cslab_r_walk", "userdata")
|
|
488
445
|
end
|
|
489
446
|
|
|
490
447
|
# --- header declaration emitters --------------------------------------------
|
|
@@ -557,14 +514,44 @@ $src.puts <<~END_C
|
|
|
557
514
|
#include "ca_sweep_engine.h"
|
|
558
515
|
#include <string.h>
|
|
559
516
|
|
|
560
|
-
/*
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
517
|
+
/* Chunk walk for the ca_call_cslab_N family, run by ca_sweep_run_chunked
|
|
518
|
+
so that a callback raising part way through gives back what the engine
|
|
519
|
+
holds. Hands the author one chunk at a time. base[] is rewritten per
|
|
520
|
+
chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points at the
|
|
521
|
+
arena scratch the chunk was just gathered into, which is packed, so
|
|
522
|
+
stride[] is the element size and the author's inner loop sees
|
|
523
|
+
contiguous data. m0 is the chunk's iteration mask, or NULL when no
|
|
524
|
+
INPUT operand carried one: chunk-sized and re-gathered per chunk, so it
|
|
525
|
+
is already the slice -- one byte per cell, indexed 0..chunk_n-1
|
|
526
|
+
alongside base[] and stride[]. The arity does not appear here: the
|
|
527
|
+
operands reach the callback through base[] / stride[]. */
|
|
528
|
+
typedef struct {
|
|
529
|
+
ca_sweep_state_t *st;
|
|
530
|
+
ca_cslab_t func; /* ca_call_cslab_N */
|
|
531
|
+
ca_cslab_r_t func_r; /* ca_call_cslab_N_r */
|
|
532
|
+
void *userdata;
|
|
533
|
+
} ca_cslab_ctx_t;
|
|
534
|
+
|
|
535
|
+
static VALUE
|
|
536
|
+
ca_cslab_walk (VALUE arg)
|
|
566
537
|
{
|
|
567
|
-
|
|
538
|
+
ca_cslab_ctx_t *c = (ca_cslab_ctx_t *) arg;
|
|
539
|
+
ca_sweep_state_t *st = c->st;
|
|
540
|
+
while ( ca_sweep_next_chunk(st) ) {
|
|
541
|
+
c->func(st->base, st->stride, st->chunk_n, st->m0);
|
|
542
|
+
}
|
|
543
|
+
return Qnil;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
static VALUE
|
|
547
|
+
ca_cslab_r_walk (VALUE arg)
|
|
548
|
+
{
|
|
549
|
+
ca_cslab_ctx_t *c = (ca_cslab_ctx_t *) arg;
|
|
550
|
+
ca_sweep_state_t *st = c->st;
|
|
551
|
+
while ( ca_sweep_next_chunk(st) ) {
|
|
552
|
+
c->func_r(st->base, st->stride, st->chunk_n, st->m0, c->userdata);
|
|
553
|
+
}
|
|
554
|
+
return Qnil;
|
|
568
555
|
}
|
|
569
556
|
|
|
570
557
|
END_C
|