carray 3.0.2 → 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 +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- 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 +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- 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 +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -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 +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -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 +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- 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 +149 -27
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +102 -79
- data/ext/ca_sweep_engine.h +7 -20
- 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 +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- 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 +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- 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 +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- 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 +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- 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 +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- 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/factorize.rb +2 -2
- 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 +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/record_order.rb +208 -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 +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- 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 +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -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_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 +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- 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 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -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 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_kernel_iterator.h
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
CA_SLAB_REDUCE_* / _MAP_* / _SCAN_* suites, CA_L2_FOR_EACH,
|
|
16
16
|
CA_*_UNMASKED helpers)
|
|
17
17
|
- the raw-API entry points the macros expand to: ca_iter_state_
|
|
18
|
-
init_l2 / next_slab_axes / sync_slab / finish
|
|
18
|
+
init_l2 / init_l2_paired / next_slab_axes / sync_slab / finish /
|
|
19
|
+
close, ca_iter_check_init, ca_iter_check_same_shape
|
|
19
20
|
- the enum/status tokens authors write literally: CA_SLAB_AXES,
|
|
20
21
|
CA_KERNEL_WRITE, CA_KERNEL_NO_MASK, CA_ITER_OK, CA_ITER_ERR_*
|
|
21
22
|
- the slab-delivery representation = the ca_iter_state fields a
|
|
@@ -41,21 +42,6 @@
|
|
|
41
42
|
devel/MEMO_KERNEL_ITERATOR_OOP_PATH.vev4.md for the planned engine
|
|
42
43
|
overhaul this contract insulates against.)
|
|
43
44
|
|
|
44
|
-
Step 1 scope (this commit):
|
|
45
|
-
- struct definition (subset used by step 1; chunk_pos / scratch /
|
|
46
|
-
descs / outer_idx fields are present but unused, reserved for
|
|
47
|
-
later steps per proposal §3.1)
|
|
48
|
-
- CA_SLAB_WHOLE policy only (single slab = whole array)
|
|
49
|
-
- alias path only: ca_attach_is_alias(src) must hold, else init
|
|
50
|
-
returns CA_ITER_ERR_NOT_CHEAP (renamed from ca_attach_is_cheap
|
|
51
|
-
in T1 step 9.4a)
|
|
52
|
-
- READ-only, no mask handling, no WRITE sync
|
|
53
|
-
|
|
54
|
-
Later steps will fill in scratch materialize (step 2), L2 strided
|
|
55
|
-
(step 3), WRITE + sync_slab (step 4), descriptor 6-view connection
|
|
56
|
-
via P3 ca_axis_dispatch_for_each_slab (step 5), mask + macros
|
|
57
|
-
(step 6), NO_MASK enforcement (step 7).
|
|
58
|
-
|
|
59
45
|
--------------------------------------------------------------------------- */
|
|
60
46
|
|
|
61
47
|
#ifndef CA_KERNEL_ITERATOR_H
|
|
@@ -66,9 +52,10 @@
|
|
|
66
52
|
|
|
67
53
|
/* ---- slab policy (proposal §2.2) ------------------------------------- */
|
|
68
54
|
typedef enum {
|
|
69
|
-
CA_SLAB_FREE = 0, /* engine-chosen chunk
|
|
70
|
-
|
|
71
|
-
|
|
55
|
+
CA_SLAB_FREE = 0, /* engine-chosen chunk. Not implemented:
|
|
56
|
+
init returns CA_ITER_ERR_POLICY. */
|
|
57
|
+
CA_SLAB_AXES = 1, /* user-pinned axes inside the slab (init_l2) */
|
|
58
|
+
CA_SLAB_WHOLE = 2 /* whole array in one slab */
|
|
72
59
|
} ca_slab_policy_t;
|
|
73
60
|
|
|
74
61
|
/* ---- kernel flags (proposal §2.2) ------------------------------------ */
|
|
@@ -93,9 +80,11 @@ typedef enum {
|
|
|
93
80
|
#define CA_ITER_ALIAS_NONE 0 /* scratch materialize. step 2+. */
|
|
94
81
|
#define CA_ITER_ALIAS_CONTIG 1 /* parent.ptr+offset direct slab. */
|
|
95
82
|
#define CA_ITER_ALIAS_STRIDED 2 /* L2 stride-aware. step 3+. */
|
|
96
|
-
#define CA_ITER_ALIAS_ATTACH 3 /*
|
|
97
|
-
|
|
98
|
-
|
|
83
|
+
#define CA_ITER_ALIAS_ATTACH 3 /* Not set by the engine. A
|
|
84
|
+
SRC_ATTACH walk runs with
|
|
85
|
+
CA_ITER_ALIAS_NONE over an
|
|
86
|
+
iterator-owned scratch filled and
|
|
87
|
+
written back with ca_xfer_all. */
|
|
99
88
|
#define CA_ITER_ALIAS_PER_SLAB 4 /* Phase C T3 fallback: per-slab
|
|
100
89
|
materialise via ca_axis_dispatch_gather
|
|
101
90
|
with subset descriptor (= caller-built
|
|
@@ -120,34 +109,28 @@ typedef enum {
|
|
|
120
109
|
mask in fiber_mask_scratch
|
|
121
110
|
(= rev2 §3.3, (data,mask)
|
|
122
111
|
pair). */
|
|
123
|
-
#define CA_ITER_ALIAS_STACK_OUTER_K 8 /*
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
entity case = eager-equivalent
|
|
140
|
-
memory bandwidth. Mask aliases
|
|
141
|
-
parent->mask similarly. Scoped
|
|
142
|
-
to slab_axes that exclude axis 0
|
|
143
|
-
(= axis 0 must be an outer iter
|
|
144
|
-
axis). */
|
|
112
|
+
#define CA_ITER_ALIAS_STACK_OUTER_K 8 /* CAStack source + CA_SLAB_AXES
|
|
113
|
+
whose slab leaves out the stack
|
|
114
|
+
axis (k_axis), which is then an
|
|
115
|
+
outer axis. Each slab lies inside
|
|
116
|
+
ONE parent, selected by
|
|
117
|
+
outer_idx[stack_k_outer_pos].
|
|
118
|
+
init_l2 attaches the K parents and
|
|
119
|
+
caches their ptrs and parent byte
|
|
120
|
+
strides; next_slab_axes reads
|
|
121
|
+
parents[k]->ptr + parent_off
|
|
122
|
+
directly. The parents' masks are
|
|
123
|
+
copied at init and the cursor
|
|
124
|
+
points into the copy. A fiber
|
|
125
|
+
that is not contiguous in its
|
|
126
|
+
parent is gathered (FIBER_CONTIG).
|
|
127
|
+
READ only. */
|
|
145
128
|
#define CA_ITER_ALIAS_STACK 7 /* PROPOSAL_CASTACK_LOOP_INTERCHANGE
|
|
146
129
|
Vector A rev2 (direct per-parent
|
|
147
130
|
ptr access): CAStack source +
|
|
148
131
|
CA_SLAB_AXES with slab_axes ==
|
|
149
|
-
[
|
|
150
|
-
view.mean(axis:
|
|
132
|
+
[k_axis] (= the stack axis alone,
|
|
133
|
+
e.g. view.mean(axis: k_axis)).
|
|
151
134
|
init_l2 attaches K parents up
|
|
152
135
|
front (= O(1) per entity parent),
|
|
153
136
|
caches parent->ptr aliases +
|
|
@@ -192,19 +175,30 @@ typedef enum {
|
|
|
192
175
|
|
|
193
176
|
/* ---- error codes ----------------------------------------------------- */
|
|
194
177
|
#define CA_ITER_OK 0
|
|
195
|
-
#define CA_ITER_ERR_NOT_CHEAP 1 /*
|
|
178
|
+
#define CA_ITER_ERR_NOT_CHEAP 1 /* the classifier does not recognise
|
|
179
|
+
the source (a view with no attach
|
|
180
|
+
slot; any other external obj_type
|
|
181
|
+
is delivered by attaching it) */
|
|
196
182
|
#define CA_ITER_ERR_POLICY 2 /* policy not implemented yet */
|
|
197
|
-
#define CA_ITER_ERR_FLAGS 3 /* flag combination unsupported
|
|
183
|
+
#define CA_ITER_ERR_FLAGS 3 /* flag combination unsupported;
|
|
184
|
+
also returned for a NULL state
|
|
185
|
+
or source */
|
|
198
186
|
#define CA_ITER_ERR_READONLY 4 /* WRITE on readonly view (CARepeat etc.) */
|
|
199
|
-
#define CA_ITER_ERR_MASK 5 /*
|
|
200
|
-
|
|
187
|
+
#define CA_ITER_ERR_MASK 5 /* reserved: no entry point returns
|
|
188
|
+
it (masked sources are accepted) */
|
|
189
|
+
#define CA_ITER_ERR_MASK_NOT_ALLOWED 6 /* NO_MASK flag set on a masked source */
|
|
201
190
|
/* ---- source kind (step 5+, internal routing) ------------------------- */
|
|
202
191
|
#define CA_ITER_SRC_NONE 0
|
|
203
192
|
#define CA_ITER_SRC_CASTRIDE 1 /* entity / CAStride family (step 1-4) */
|
|
204
|
-
#define CA_ITER_SRC_DESCRIPTOR 2 /*
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
193
|
+
#define CA_ITER_SRC_DESCRIPTOR 2 /* CASelectAxis / CAGrid / CASelect /
|
|
194
|
+
CAWindow / CAShift: per-axis
|
|
195
|
+
descriptors (describe_axes) */
|
|
196
|
+
#define CA_ITER_SRC_ATTACH 3 /* every other view the classifier
|
|
197
|
+
knows (conversion views, CATile,
|
|
198
|
+
CARoll, CAStack, CAMeld, CARemap,
|
|
199
|
+
CAObject, the lazy views) and any
|
|
200
|
+
registered external obj_type: the
|
|
201
|
+
view's own transfer gathers it */
|
|
208
202
|
#define CA_ITER_SRC_DESCRIPTOR_L2_ALIASABLE 4
|
|
209
203
|
/* F-2 (PROPOSAL_F2_KERNEL_ITERATOR_ALIAS
|
|
210
204
|
rev6): descriptor view whose innermost
|
|
@@ -220,13 +214,13 @@ typedef enum {
|
|
|
220
214
|
The classifier recognises the core's own view classes by comparing
|
|
221
215
|
their operation table against a list compiled into the engine. A view
|
|
222
216
|
class installed by a companion gem through ca_install_obj_type matches
|
|
223
|
-
nothing on that list
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
declares the routing here instead, once, in the class's Init:
|
|
217
|
+
nothing on that list; it is delivered as CA_ITER_SRC_ATTACH (the view's
|
|
218
|
+
own attach gathers it), and so is one that registers here, once, in the
|
|
219
|
+
class's Init:
|
|
227
220
|
|
|
228
221
|
ca_iter_register_source_kind(CA_OBJ_MY_VIEW, CA_ITER_SRC_ATTACH);
|
|
229
222
|
|
|
223
|
+
Registering states the routing rather than changing it.
|
|
230
224
|
CA_ITER_SRC_ATTACH is the only kind that may be registered. It is the
|
|
231
225
|
one whose contract an external class can meet on its own: func_attach
|
|
232
226
|
materialises (or aliases) src->ptr and func_sync scatters back — the
|
|
@@ -257,7 +251,10 @@ typedef struct {
|
|
|
257
251
|
ca_slab_policy_t policy;
|
|
258
252
|
int8_t ndim;
|
|
259
253
|
int8_t naxes; /* [step 5+] AXES policy axis count */
|
|
260
|
-
|
|
254
|
+
void *pair; /* the other state of a two-state
|
|
255
|
+
walk (ca_iter_state_init_l2_paired),
|
|
256
|
+
else NULL; finished with this one
|
|
257
|
+
when the walk raises */
|
|
261
258
|
uint32_t flags;
|
|
262
259
|
ca_size_t bytes; /* element size */
|
|
263
260
|
|
|
@@ -273,9 +270,9 @@ typedef struct {
|
|
|
273
270
|
ca_size_t composed_strides[CA_RANK_MAX]; /* byte units */
|
|
274
271
|
ca_size_t composed_base; /* byte offset from root->ptr */
|
|
275
272
|
|
|
276
|
-
/* --- descriptor framework cache (
|
|
277
|
-
For
|
|
278
|
-
|
|
273
|
+
/* --- descriptor framework cache (descriptor sources) ---
|
|
274
|
+
For CASelectAxis / CAGrid / CASelect / CAWindow / CAShift, init runs
|
|
275
|
+
the view's *_describe_axes once then
|
|
279
276
|
reuses the P3 substrate (ca_axis_dispatch_prepare / _layout /
|
|
280
277
|
_classify_prefix) to derive the slab layout. Cached inline so
|
|
281
278
|
next_slab walks the prefix axes without re-doing the analysis. */
|
|
@@ -315,8 +312,8 @@ typedef struct {
|
|
|
315
312
|
uint8_t write_dirty;
|
|
316
313
|
|
|
317
314
|
/* --- CA_SLAB_AXES policy fields (Phase A capstone, T1) ---
|
|
318
|
-
Populated when init_l2 is called with policy = CA_SLAB_AXES
|
|
319
|
-
|
|
315
|
+
Populated when init_l2 is called with policy = CA_SLAB_AXES, for
|
|
316
|
+
every kind of source. The kernel reads slab metadata directly
|
|
320
317
|
from these fields (= per-walk metadata, unchanged across slabs).
|
|
321
318
|
outer_axes / outer_dims / outer_strides drive the prefix walk;
|
|
322
319
|
slab_axes_buf / slab_dims / slab_strides describe the K-D slab
|
|
@@ -355,14 +352,14 @@ typedef struct {
|
|
|
355
352
|
gather and gathers each fiber here before yielding. Reused across
|
|
356
353
|
fibers; size grows to max slab_dims[0] * bytes.
|
|
357
354
|
|
|
358
|
-
last_data_off is
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
355
|
+
last_data_off is the byte offset of the current slab from alias_ptr,
|
|
356
|
+
set by next_slab_axes on its default path BEFORE the outer_idx
|
|
357
|
+
advance. sync_slab reads it for the fiber it scatters back and for
|
|
358
|
+
the cells of a whole-view scratch it compares; the slab iterator's
|
|
359
|
+
map_slab reads it to mark the output's mask.
|
|
362
360
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
touch these fields. */
|
|
361
|
+
The per-slab paths (CA_ITER_ALIAS_PER_SLAB / _HOIST) and the stack
|
|
362
|
+
paths do not set it. */
|
|
366
363
|
char *fiber_data_scratch;
|
|
367
364
|
ca_size_t fiber_data_scratch_cap;
|
|
368
365
|
ca_size_t last_data_off;
|
|
@@ -410,12 +407,10 @@ typedef struct {
|
|
|
410
407
|
here lets next_slab_axes compute mask_off without downcasting to
|
|
411
408
|
CAStack (= AC3 layering goal). */
|
|
412
409
|
ca_size_t stack_parent_mask_strides[CA_RANK_MAX];
|
|
413
|
-
/* --- PROPOSAL_CASTACK_XFER_OPT_LAYERING P.2 Case A (2026-06-18) --- */
|
|
414
410
|
/* When alias_mode == CA_ITER_ALIAS_STACK_OUTER_K and the CAStack
|
|
415
|
-
source carries a mask, init_l2
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
(xfree in finish). */
|
|
411
|
+
source carries a mask, init_l2 copies the K parent masks here, read
|
|
412
|
+
alongside parents[k]->ptr. NULL when the source has no mask. Owned
|
|
413
|
+
by the iterator (xfree in finish). */
|
|
419
414
|
boolean8_t **stack_parent_mask_ptrs; /* [n_parents] or NULL */
|
|
420
415
|
/* K axis position within the outer iter axis list. Set by init_l2
|
|
421
416
|
when alias_mode == CA_ITER_ALIAS_STACK_OUTER_K; next_slab_axes uses
|
|
@@ -461,10 +456,12 @@ typedef struct {
|
|
|
461
456
|
Not implemented in Phase 1 — falls back to L1 semantics so the predicate
|
|
462
457
|
stays well-defined for callers that probe ahead.
|
|
463
458
|
|
|
464
|
-
Descriptor
|
|
465
|
-
CAShift
|
|
466
|
-
CABitarray) return 0 at every level
|
|
467
|
-
|
|
459
|
+
Descriptor views (CASelectAxis / CAGrid / CASelect / CAWindow /
|
|
460
|
+
CAShift) and conversion views (CAFake / CAByteSwap / CABitfield /
|
|
461
|
+
CABitarray) return 0 at every level. init_l2 still reads a
|
|
462
|
+
descriptor view in place when its innermost axis is a stride
|
|
463
|
+
(CA_ITER_SRC_DESCRIPTOR_L2_ALIASABLE); this predicate does not
|
|
464
|
+
report that case.
|
|
468
465
|
|
|
469
466
|
ca_attach_is_alias is retained as the level=1 oracle for the Tier A
|
|
470
467
|
(PROPOSAL_DELEGATE_COPY_DATA) defer site; callers that already use
|
|
@@ -481,19 +478,21 @@ int ca_iter_can_alias (void *ap, int level);
|
|
|
481
478
|
src->ptr, stride implicit = bytes)
|
|
482
479
|
- CAStride family non-contig: scratch path (ca_copy_data
|
|
483
480
|
compose-fold gather into a malloc'd buffer)
|
|
484
|
-
-
|
|
481
|
+
- descriptor views (CAGrid / CASelect / CAMapping / CAWindow /
|
|
482
|
+
CAShift / CASelectAxis): gathered into a scratch buffer
|
|
483
|
+
- SRC_ATTACH views (overlays, lazy views, CAObject, CAStack, ...):
|
|
484
|
+
iterator-owned scratch filled through ca_xfer_all
|
|
485
|
+
- sources the classifier does not recognise: CA_ITER_ERR_NOT_CHEAP
|
|
485
486
|
|
|
486
|
-
policy: only
|
|
487
|
-
|
|
487
|
+
policy: CA_SLAB_WHOLE only (CA_SLAB_AXES and CA_SLAB_FREE return
|
|
488
|
+
CA_ITER_ERR_POLICY).
|
|
489
|
+
flags: any of CA_KERNEL_WRITE / CA_KERNEL_NO_MASK /
|
|
490
|
+
CA_KERNEL_FIBER_CONTIG; other bits return CA_ITER_ERR_FLAGS.
|
|
488
491
|
|
|
489
492
|
On success returns CA_ITER_OK; on error returns CA_ITER_ERR_*
|
|
490
493
|
without claiming resources (finish need not be called).
|
|
491
494
|
|
|
492
|
-
Pair with ca_iter_state_next_slab.
|
|
493
|
-
level-specific entry points so each setup path stays focused
|
|
494
|
-
(proposal §3.2 rev: original single-init was relaxed when L2 setup
|
|
495
|
-
diverged enough to warrant its own state initialiser; see
|
|
496
|
-
ROADMAP/CHANGELOG rev). */
|
|
495
|
+
Pair with ca_iter_state_next_slab. */
|
|
497
496
|
int ca_iter_state_init_l1 (ca_iter_state *st,
|
|
498
497
|
struct _CArray *src,
|
|
499
498
|
ca_slab_policy_t policy,
|
|
@@ -509,9 +508,23 @@ int ca_iter_state_init_l1 (ca_iter_state *st,
|
|
|
509
508
|
- CAStride non-contig: alias_mode = STRIDED, multi-slab walk over
|
|
510
509
|
prefix axes, each yield carries native inner stride_bytes. No
|
|
511
510
|
scratch.
|
|
512
|
-
-
|
|
513
|
-
|
|
514
|
-
|
|
511
|
+
- descriptor views: aliased when the innermost axis is a STRIDE
|
|
512
|
+
axis, otherwise gathered into scratch (per slab under
|
|
513
|
+
CA_SLAB_AXES when a slab axis is an INDEX or SHIFT axis)
|
|
514
|
+
- SRC_ATTACH views: iterator-owned scratch filled through
|
|
515
|
+
ca_xfer_all and written back the same way
|
|
516
|
+
- sources the classifier does not recognise: CA_ITER_ERR_NOT_CHEAP
|
|
517
|
+
|
|
518
|
+
policy: CA_SLAB_WHOLE or CA_SLAB_AXES (CA_SLAB_FREE returns
|
|
519
|
+
CA_ITER_ERR_POLICY, as do out-of-range or duplicate axes, and
|
|
520
|
+
CA_SLAB_AXES over a descriptor view whose descriptor rank
|
|
521
|
+
differs from the view's rank).
|
|
522
|
+
flags: as init_l1. CA_KERNEL_WRITE is refused with
|
|
523
|
+
CA_ITER_ERR_FLAGS when a CA_SLAB_AXES slab axis is an INDEX
|
|
524
|
+
or SHIFT axis of a descriptor view.
|
|
525
|
+
|
|
526
|
+
Pair with ca_iter_state_next_slab_strided (CA_SLAB_WHOLE) or
|
|
527
|
+
ca_iter_state_next_slab_axes (CA_SLAB_AXES). */
|
|
515
528
|
int ca_iter_state_init_l2 (ca_iter_state *st,
|
|
516
529
|
struct _CArray *src,
|
|
517
530
|
ca_slab_policy_t policy,
|
|
@@ -555,12 +568,9 @@ int ca_iter_state_next_slab (ca_iter_state *st,
|
|
|
555
568
|
*out_mask / *out_n / *out_stride_bytes when a slab is yielded;
|
|
556
569
|
returns 0 when the walk is complete. The kernel walks `*out_n`
|
|
557
570
|
elements by stepping `*out_stride_bytes` between consecutive
|
|
558
|
-
elements starting at `*out_ptr
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
since mask is boolean8_t == 1 byte, mask stride is 1 byte when the
|
|
562
|
-
value stride is bytes, and proportional otherwise). Only valid
|
|
563
|
-
when init_l2 was used. */
|
|
571
|
+
elements starting at `*out_ptr`. The mask, when non-NULL, is
|
|
572
|
+
contiguous whatever the value stride: mask[i] pairs with the value
|
|
573
|
+
at ptr + i * stride_bytes. Only valid when init_l2 was used. */
|
|
564
574
|
int ca_iter_state_next_slab_strided (ca_iter_state *st,
|
|
565
575
|
char **out_ptr,
|
|
566
576
|
boolean8_t **out_mask,
|
|
@@ -606,20 +616,52 @@ int ca_iter_state_next_slab_axes (ca_iter_state *st,
|
|
|
606
616
|
next_slab_strided + kernel invocation; the alias_mode branch lives
|
|
607
617
|
inside the state machine so the caller never has to inspect it.
|
|
608
618
|
|
|
609
|
-
Behaviour
|
|
619
|
+
Behaviour:
|
|
610
620
|
- !(flags & CA_KERNEL_WRITE): no-op (READ walk)
|
|
621
|
+
- per-fiber gather (CA_KERNEL_FIBER_CONTIG on a strided fiber):
|
|
622
|
+
the fiber is scattered back from its scratch first
|
|
611
623
|
- alias path (scratch_ptr == NULL): no-op — kernel wrote to
|
|
612
|
-
parent directly through alias_ptr
|
|
613
|
-
- scratch path
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
assert; step 5 re-evaluation noted in the proposal. */
|
|
624
|
+
parent directly through alias_ptr
|
|
625
|
+
- scratch path, at L1 or L2: written back through the source —
|
|
626
|
+
ca_xfer_all for SRC_ATTACH, ca_sync_data for CAStride, the
|
|
627
|
+
descriptor scatter for descriptor views */
|
|
617
628
|
void ca_iter_state_sync_slab (ca_iter_state *st);
|
|
618
629
|
|
|
619
|
-
/* Release any resources held by `st` and detach parent.
|
|
620
|
-
|
|
630
|
+
/* Release any resources held by `st` and detach parent. Idempotent:
|
|
631
|
+
a second call is a no-op. Also safe after a failed init, which holds
|
|
632
|
+
nothing to release (the call is then not required). */
|
|
621
633
|
void ca_iter_state_finish (ca_iter_state *st);
|
|
622
634
|
|
|
635
|
+
/* Open `st` as the second state of a walk whose first state is already
|
|
636
|
+
open -- an input and an output walked together. Takes what
|
|
637
|
+
ca_iter_state_init_l2 takes, plus `first`.
|
|
638
|
+
|
|
639
|
+
The two are then finished together when either walk raises (a gather
|
|
640
|
+
or a write-back through a source's slots): each is open in the
|
|
641
|
+
caller's frame, and the raise would jump over the other's finish. If
|
|
642
|
+
opening `st` raises, or is declined (the code is returned), `first` is
|
|
643
|
+
finished here, so the caller has nothing left to close.
|
|
644
|
+
|
|
645
|
+
When `st` writes (CA_KERNEL_WRITE), `first` reads, both walk by
|
|
646
|
+
CA_SLAB_AXES, and their arrays live in the same root, `first` is
|
|
647
|
+
reopened on a copy of its array taken before anything is written, so
|
|
648
|
+
the kernel reads the values the input held when the walk began. Two
|
|
649
|
+
walks opened separately with ca_iter_state_init_l2 know nothing of
|
|
650
|
+
each other: a read walk over memory a write walk writes into must be
|
|
651
|
+
given a copy by the caller. */
|
|
652
|
+
int ca_iter_state_init_l2_paired (ca_iter_state *st,
|
|
653
|
+
ca_iter_state *first,
|
|
654
|
+
struct _CArray *src,
|
|
655
|
+
ca_slab_policy_t policy,
|
|
656
|
+
int8_t *axes,
|
|
657
|
+
int8_t naxes,
|
|
658
|
+
uint32_t flags);
|
|
659
|
+
|
|
660
|
+
/* Finish a walk as the block macros leave it: when the body left a write
|
|
661
|
+
walk with `break`, the slab it was in is written back before the walk is
|
|
662
|
+
finished. ca_iter_state_finish itself abandons such a slab. */
|
|
663
|
+
void ca_iter_state_close (ca_iter_state *st);
|
|
664
|
+
|
|
623
665
|
/* Raise unless rc is CA_ITER_OK. The block macros call this on the value
|
|
624
666
|
ca_iter_state_init_l1 / _l2 returned, so an author who never looks at a
|
|
625
667
|
return code still hears about a request the iterator would not serve.
|
|
@@ -627,6 +669,32 @@ void ca_iter_state_finish (ca_iter_state *st);
|
|
|
627
669
|
macros' comma expressions. */
|
|
628
670
|
int ca_iter_check_init (int rc);
|
|
629
671
|
|
|
672
|
+
/* Raise ArgumentError unless the two arrays have the same shape. The
|
|
673
|
+
INOUT and PAIR fiber macros call this before opening either walk. */
|
|
674
|
+
int ca_iter_check_same_shape (struct _CArray *a, struct _CArray *b);
|
|
675
|
+
|
|
676
|
+
/* Run body(arg) so that the walks in states[0..n) are finished however the
|
|
677
|
+
body leaves: by returning, by `break`, or by raising.
|
|
678
|
+
|
|
679
|
+
A walk releases what it holds in ca_iter_state_finish, and a body that
|
|
680
|
+
raises jumps over the finish -- the block macros put it in the `for`
|
|
681
|
+
increment, and a hand-written walk has it after the loop. A body that
|
|
682
|
+
calls back into Ruby (an object-lane kernel) can raise at any cell, so
|
|
683
|
+
it runs through this function.
|
|
684
|
+
|
|
685
|
+
The states belong to the caller's frame, not to the body's: after a
|
|
686
|
+
raise, the body's frame is gone, and the cleanup runs where it was.
|
|
687
|
+
Pass them to the body inside `arg` and open each one there, with
|
|
688
|
+
ca_iter_state_init_* or a block macro (`CA_FOR_EACH_SLAB(c->st, ...)`).
|
|
689
|
+
A state declared inside the body is not covered.
|
|
690
|
+
|
|
691
|
+
The states are marked unopened before the body runs, so one the body
|
|
692
|
+
never opens costs nothing, and the body may finish a walk itself:
|
|
693
|
+
finishing is idempotent. Returns what the body returns; a raise propagates
|
|
694
|
+
after the walks are finished. */
|
|
695
|
+
VALUE ca_iter_ensure (int32_t n, ca_iter_state *states,
|
|
696
|
+
VALUE (*body)(VALUE), VALUE arg);
|
|
697
|
+
|
|
630
698
|
/* ---- Phase C C.3: kernel author block macros ------------------------
|
|
631
699
|
(PROPOSAL_CAPSTONE_PHASE_C.md D3.1 (A) do/while/for + D3.2 (C) 2 kinds)
|
|
632
700
|
|
|
@@ -652,13 +720,16 @@ int ca_iter_check_init (int rc);
|
|
|
652
720
|
should drop down to the raw API and read the code themselves.
|
|
653
721
|
- `break;` from inside the body exits the loop AND triggers finish
|
|
654
722
|
correctly (= outer for's "increment" clause runs once on natural
|
|
655
|
-
exit; `break` from the inner while breaks both).
|
|
723
|
+
exit; `break` from the inner while breaks both). In a write walk
|
|
724
|
+
finish writes back the slab the body was in. `return` inside
|
|
656
725
|
the body LEAKS resources (scratch_ptr, parent attach) — drop to
|
|
657
726
|
raw API if early return is needed. A body that raises leaks the
|
|
658
727
|
same way: the engine releases what it holds when the walk itself
|
|
659
728
|
raises (a gather or a write-back through the source's slots), but
|
|
660
729
|
the body runs in the caller's frame, where it has no hold on it.
|
|
661
|
-
|
|
730
|
+
A body that can raise -- one that calls back into Ruby, as an
|
|
731
|
+
object-lane kernel does -- runs through ca_iter_ensure, with the
|
|
732
|
+
state in the caller's frame.
|
|
662
733
|
- Macros are not statement-equivalent (= they expand to nested for
|
|
663
734
|
constructs). Don't follow them with `else` etc. */
|
|
664
735
|
|
|
@@ -796,7 +867,7 @@ int ca_iter_check_init (int rc);
|
|
|
796
867
|
(axes), (naxes), (flags))), \
|
|
797
868
|
1); \
|
|
798
869
|
__caf_init; \
|
|
799
|
-
__caf_init = 0,
|
|
870
|
+
__caf_init = 0, ca_iter_state_close(&(st)) ) \
|
|
800
871
|
for ( ; ca_iter_state_next_slab_axes(&(st), &(p), &(m)); \
|
|
801
872
|
ca_iter_state_sync_slab(&(st)) )
|
|
802
873
|
|
|
@@ -819,13 +890,14 @@ int ca_iter_check_init (int rc);
|
|
|
819
890
|
ca_iter_state_init_l2(&(st_in), (ca_in), CA_SLAB_AXES, \
|
|
820
891
|
(axes), (naxes), 0)), \
|
|
821
892
|
ca_iter_check_init( \
|
|
822
|
-
|
|
893
|
+
ca_iter_state_init_l2_paired(&(st_out), &(st_in), (ca_out), \
|
|
894
|
+
CA_SLAB_AXES, \
|
|
823
895
|
(axes), (naxes), CA_KERNEL_WRITE)), \
|
|
824
896
|
1); \
|
|
825
897
|
__cafi_init; \
|
|
826
898
|
__cafi_init = 0, \
|
|
827
|
-
|
|
828
|
-
|
|
899
|
+
ca_iter_state_close(&(st_in)), \
|
|
900
|
+
ca_iter_state_close(&(st_out)) ) \
|
|
829
901
|
for ( ; ca_iter_state_next_slab_axes(&(st_in), &(p_in), &(m_in)) && \
|
|
830
902
|
ca_iter_state_next_slab_axes(&(st_out), &(p_out), &(m_out)); \
|
|
831
903
|
ca_iter_state_sync_slab(&(st_out)) )
|
|
@@ -843,21 +915,25 @@ int ca_iter_check_init (int rc);
|
|
|
843
915
|
The CA_KERNEL_FIBER_CONTIG flag is auto-set; engine gathers strided
|
|
844
916
|
fibers into per-state scratch when slab_strides[0] != bytes (= F.1a/b).
|
|
845
917
|
|
|
846
|
-
`axis`
|
|
847
|
-
|
|
848
|
-
|
|
918
|
+
`axis`, `ca`, `ca_in` and `ca_out` may be evaluated more than once:
|
|
919
|
+
pass variables, not expressions with side effects. `n` is set to the
|
|
920
|
+
fiber length (= slab_dims[0], constant per walk).
|
|
921
|
+
|
|
922
|
+
The forms without MASKED in the name hand out no mask cursor: a masked
|
|
923
|
+
source is walked with its masked cells read as values. Pass
|
|
924
|
+
CA_KERNEL_NO_MASK to have a masked source refused, or use a MASKED
|
|
925
|
+
form to see the mask.
|
|
849
926
|
|
|
850
927
|
Same constraints as CA_FOR_EACH_SLAB family:
|
|
851
|
-
- `break;` from body exits cleanly (finish runs
|
|
928
|
+
- `break;` from body exits cleanly (finish runs, and a write walk
|
|
929
|
+
writes back the fiber it was in).
|
|
852
930
|
- `return;` from body LEAKS scratch / parent attach -- use raw API.
|
|
853
931
|
- Macros are NOT statement-equivalent (nested for); no trailing else.
|
|
854
932
|
|
|
855
|
-
INOUT forms (form 2 / 4) require
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
macros runtime-assert shape equality and skip body on mismatch.
|
|
860
|
-
Authors that need broadcasting must drop to raw API. */
|
|
933
|
+
INOUT forms (form 2 / 4) require `ca_in` and `ca_out` to have the same
|
|
934
|
+
shape (ndim and every dim[k]), and raise ArgumentError before opening
|
|
935
|
+
either walk when they do not. Authors that need broadcasting must
|
|
936
|
+
drop to raw API. */
|
|
861
937
|
|
|
862
938
|
#define CA_FOR_EACH_FIBER(st, ca, axis, flags, p, n) \
|
|
863
939
|
for ( int __cff_init = ( \
|
|
@@ -868,7 +944,7 @@ int ca_iter_check_init (int rc);
|
|
|
868
944
|
(n) = (st).slab_dims[0], \
|
|
869
945
|
1); \
|
|
870
946
|
__cff_init; \
|
|
871
|
-
__cff_init = 0,
|
|
947
|
+
__cff_init = 0, ca_iter_state_close(&(st)) ) \
|
|
872
948
|
for ( ; ca_iter_state_next_slab_axes(&(st), &(p), NULL); \
|
|
873
949
|
ca_iter_state_sync_slab(&(st)) )
|
|
874
950
|
|
|
@@ -881,31 +957,23 @@ int ca_iter_check_init (int rc);
|
|
|
881
957
|
(n) = (st).slab_dims[0], \
|
|
882
958
|
1); \
|
|
883
959
|
__cffm_init; \
|
|
884
|
-
__cffm_init = 0,
|
|
960
|
+
__cffm_init = 0, ca_iter_state_close(&(st)) ) \
|
|
885
961
|
for ( ; ca_iter_state_next_slab_axes(&(st), &(p), &(m)); \
|
|
886
962
|
ca_iter_state_sync_slab(&(st)) )
|
|
887
963
|
|
|
888
|
-
/* INOUT form 2
|
|
889
|
-
|
|
890
|
-
STRICT FULL SHAPE EQUALITY (rev4 §2.3): the inner for-condition
|
|
891
|
-
re-evaluates ca_in->ndim == ca_out->ndim and dim[axis] equality (=
|
|
892
|
-
minimal seam coverage given the macro can't loop over k). Full
|
|
893
|
-
per-axis equality lives one level up in the init-time short-circuit
|
|
894
|
-
below: we compare elements + ndim + axis dim, which catches the
|
|
895
|
-
common silent-corruption seam (= e.g. (3,5) vs (4,5) axis=1 with
|
|
896
|
-
matching fiber length but different fiber count). Comprehensive
|
|
897
|
-
per-dim check is the caller's responsibility for now (= simpler than
|
|
898
|
-
building a per-dim k loop into a macro; ext authors can drop to raw
|
|
899
|
-
API for arbitrary broadcasting designs). */
|
|
964
|
+
/* INOUT form 2. Output gets CA_KERNEL_WRITE auto-set. The shapes are
|
|
965
|
+
checked first (ca_iter_check_same_shape). */
|
|
900
966
|
#define CA_FOR_EACH_FIBER_INOUT(st_in, st_out, ca_in, ca_out, axis, \
|
|
901
967
|
flags, p_in, p_out, n) \
|
|
902
968
|
for ( int __cffi_init = ( \
|
|
969
|
+
ca_iter_check_same_shape((ca_in), (ca_out)), \
|
|
903
970
|
ca_iter_check_init( \
|
|
904
971
|
ca_iter_state_init_l2(&(st_in), (ca_in), CA_SLAB_AXES, \
|
|
905
972
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
906
973
|
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
907
974
|
ca_iter_check_init( \
|
|
908
|
-
|
|
975
|
+
ca_iter_state_init_l2_paired(&(st_out), &(st_in), (ca_out), \
|
|
976
|
+
CA_SLAB_AXES, \
|
|
909
977
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
910
978
|
((flags) | CA_KERNEL_FIBER_CONTIG \
|
|
911
979
|
| CA_KERNEL_WRITE))), \
|
|
@@ -913,12 +981,9 @@ int ca_iter_check_init (int rc);
|
|
|
913
981
|
1); \
|
|
914
982
|
__cffi_init; \
|
|
915
983
|
__cffi_init = 0, \
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
for ( ; (st_in)
|
|
919
|
-
&& (st_in).src->elements == (st_out).src->elements \
|
|
920
|
-
&& (st_in).slab_dims[0] == (st_out).slab_dims[0] \
|
|
921
|
-
&& ca_iter_state_next_slab_axes(&(st_in), &(p_in), NULL) \
|
|
984
|
+
ca_iter_state_close(&(st_in)), \
|
|
985
|
+
ca_iter_state_close(&(st_out)) ) \
|
|
986
|
+
for ( ; ca_iter_state_next_slab_axes(&(st_in), &(p_in), NULL) \
|
|
922
987
|
&& ca_iter_state_next_slab_axes(&(st_out), &(p_out), NULL); \
|
|
923
988
|
ca_iter_state_sync_slab(&(st_in)), \
|
|
924
989
|
ca_iter_state_sync_slab(&(st_out)) )
|
|
@@ -926,12 +991,14 @@ int ca_iter_check_init (int rc);
|
|
|
926
991
|
#define CA_FOR_EACH_FIBER_INOUT_MASKED(st_in, st_out, ca_in, ca_out, axis, \
|
|
927
992
|
flags, p_in, p_out, n, m) \
|
|
928
993
|
for ( int __cffim_init = ( \
|
|
994
|
+
ca_iter_check_same_shape((ca_in), (ca_out)), \
|
|
929
995
|
ca_iter_check_init( \
|
|
930
996
|
ca_iter_state_init_l2(&(st_in), (ca_in), CA_SLAB_AXES, \
|
|
931
997
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
932
998
|
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
933
999
|
ca_iter_check_init( \
|
|
934
|
-
|
|
1000
|
+
ca_iter_state_init_l2_paired(&(st_out), &(st_in), (ca_out), \
|
|
1001
|
+
CA_SLAB_AXES, \
|
|
935
1002
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
936
1003
|
((flags) | CA_KERNEL_FIBER_CONTIG \
|
|
937
1004
|
| CA_KERNEL_WRITE))), \
|
|
@@ -939,12 +1006,9 @@ int ca_iter_check_init (int rc);
|
|
|
939
1006
|
1); \
|
|
940
1007
|
__cffim_init; \
|
|
941
1008
|
__cffim_init = 0, \
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
for ( ; (st_in)
|
|
945
|
-
&& (st_in).src->elements == (st_out).src->elements \
|
|
946
|
-
&& (st_in).slab_dims[0] == (st_out).slab_dims[0] \
|
|
947
|
-
&& ca_iter_state_next_slab_axes(&(st_in), &(p_in), &(m)) \
|
|
1009
|
+
ca_iter_state_close(&(st_in)), \
|
|
1010
|
+
ca_iter_state_close(&(st_out)) ) \
|
|
1011
|
+
for ( ; ca_iter_state_next_slab_axes(&(st_in), &(p_in), &(m)) \
|
|
948
1012
|
&& ca_iter_state_next_slab_axes(&(st_out), &(p_out), NULL); \
|
|
949
1013
|
ca_iter_state_sync_slab(&(st_in)), \
|
|
950
1014
|
ca_iter_state_sync_slab(&(st_out)) )
|
|
@@ -962,31 +1026,32 @@ int ca_iter_check_init (int rc);
|
|
|
962
1026
|
cursors: which cells a pair of fibers may be used at is a question about
|
|
963
1027
|
both of them, and the INOUT forms answer only about the input.
|
|
964
1028
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
sources may be the same array.
|
|
1029
|
+
The two sources must have the same shape, as for the INOUT forms:
|
|
1030
|
+
ca_iter_check_same_shape raises ArgumentError before either walk is
|
|
1031
|
+
opened. The two sources may be the same array. The second state is
|
|
1032
|
+
opened paired with the first, so a refusal or a raise on either side
|
|
1033
|
+
closes both. */
|
|
968
1034
|
|
|
969
1035
|
#define CA_FOR_EACH_FIBER_PAIR(st_a, st_b, ca_a, ca_b, axis, \
|
|
970
1036
|
flags, p_a, p_b, n) \
|
|
971
1037
|
for ( int __cffp_init = ( \
|
|
1038
|
+
ca_iter_check_same_shape((ca_a), (ca_b)), \
|
|
972
1039
|
ca_iter_check_init( \
|
|
973
1040
|
ca_iter_state_init_l2(&(st_a), (ca_a), CA_SLAB_AXES, \
|
|
974
1041
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
975
1042
|
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
976
1043
|
ca_iter_check_init( \
|
|
977
|
-
|
|
1044
|
+
ca_iter_state_init_l2_paired(&(st_b), &(st_a), (ca_b), \
|
|
1045
|
+
CA_SLAB_AXES, \
|
|
978
1046
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
979
1047
|
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
980
1048
|
(n) = (st_a).slab_dims[0], \
|
|
981
1049
|
1); \
|
|
982
1050
|
__cffp_init; \
|
|
983
1051
|
__cffp_init = 0, \
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
for ( ; (st_a)
|
|
987
|
-
&& (st_a).src->elements == (st_b).src->elements \
|
|
988
|
-
&& (st_a).slab_dims[0] == (st_b).slab_dims[0] \
|
|
989
|
-
&& ca_iter_state_next_slab_axes(&(st_a), &(p_a), NULL) \
|
|
1052
|
+
ca_iter_state_close(&(st_a)), \
|
|
1053
|
+
ca_iter_state_close(&(st_b)) ) \
|
|
1054
|
+
for ( ; ca_iter_state_next_slab_axes(&(st_a), &(p_a), NULL) \
|
|
990
1055
|
&& ca_iter_state_next_slab_axes(&(st_b), &(p_b), NULL); \
|
|
991
1056
|
ca_iter_state_sync_slab(&(st_a)), \
|
|
992
1057
|
ca_iter_state_sync_slab(&(st_b)) )
|
|
@@ -994,24 +1059,23 @@ int ca_iter_check_init (int rc);
|
|
|
994
1059
|
#define CA_FOR_EACH_FIBER_PAIR_MASKED(st_a, st_b, ca_a, ca_b, axis, \
|
|
995
1060
|
flags, p_a, p_b, n, m_a, m_b) \
|
|
996
1061
|
for ( int __cffpm_init = ( \
|
|
1062
|
+
ca_iter_check_same_shape((ca_a), (ca_b)), \
|
|
997
1063
|
ca_iter_check_init( \
|
|
998
1064
|
ca_iter_state_init_l2(&(st_a), (ca_a), CA_SLAB_AXES, \
|
|
999
1065
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
1000
1066
|
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
1001
1067
|
ca_iter_check_init( \
|
|
1002
|
-
|
|
1068
|
+
ca_iter_state_init_l2_paired(&(st_b), &(st_a), (ca_b), \
|
|
1069
|
+
CA_SLAB_AXES, \
|
|
1003
1070
|
(int8_t[]){(int8_t)(axis)}, 1, \
|
|
1004
1071
|
(flags) | CA_KERNEL_FIBER_CONTIG)), \
|
|
1005
1072
|
(n) = (st_a).slab_dims[0], \
|
|
1006
1073
|
1); \
|
|
1007
1074
|
__cffpm_init; \
|
|
1008
1075
|
__cffpm_init = 0, \
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
for ( ; (st_a)
|
|
1012
|
-
&& (st_a).src->elements == (st_b).src->elements \
|
|
1013
|
-
&& (st_a).slab_dims[0] == (st_b).slab_dims[0] \
|
|
1014
|
-
&& ca_iter_state_next_slab_axes(&(st_a), &(p_a), &(m_a)) \
|
|
1076
|
+
ca_iter_state_close(&(st_a)), \
|
|
1077
|
+
ca_iter_state_close(&(st_b)) ) \
|
|
1078
|
+
for ( ; ca_iter_state_next_slab_axes(&(st_a), &(p_a), &(m_a)) \
|
|
1015
1079
|
&& ca_iter_state_next_slab_axes(&(st_b), &(p_b), &(m_b)); \
|
|
1016
1080
|
ca_iter_state_sync_slab(&(st_a)), \
|
|
1017
1081
|
ca_iter_state_sync_slab(&(st_b)) )
|
|
@@ -2351,7 +2415,7 @@ int ca_iter_check_init (int rc);
|
|
|
2351
2415
|
Both states must share slab geometry (= same slab_ndim and slab_dims),
|
|
2352
2416
|
typically by initialising both with the same policy + axes on
|
|
2353
2417
|
shape-equal CArrays. Mask handling is **not** done by this macro —
|
|
2354
|
-
if your input is masked, see §
|
|
2418
|
+
if your input is masked, see §8 Mask handling in
|
|
2355
2419
|
docs/authoring/HOW_TO_WRITE_KERNEL.md. Caller is responsible for invoking
|
|
2356
2420
|
ca_iter_state_sync_slab on the output state after each slab.
|
|
2357
2421
|
|