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.
Files changed (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +824 -0
  3. data/README.md +5 -6
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +258 -4
  6. data/ext/ca_axis_group.c +368 -184
  7. data/ext/ca_binop_dispatch.c +54 -32
  8. data/ext/ca_binop_dispatch.h +1 -0
  9. data/ext/ca_categorical_iterator.c +90 -41
  10. data/ext/ca_compare.c +8 -2
  11. data/ext/ca_for_buffer.h +21 -68
  12. data/ext/ca_group_iter.c +27 -11
  13. data/ext/ca_kernel_iterator.c +960 -245
  14. data/ext/ca_kernel_iterator.h +352 -181
  15. data/ext/ca_monop_dispatch.c +4 -4
  16. data/ext/ca_monop_dispatch.h +4 -0
  17. data/ext/ca_obj_array.c +194 -42
  18. data/ext/ca_obj_bincmp.c +152 -121
  19. data/ext/ca_obj_binop.c +107 -210
  20. data/ext/ca_obj_bitarray.c +37 -24
  21. data/ext/ca_obj_bitfield.c +95 -62
  22. data/ext/ca_obj_block.c +5 -4
  23. data/ext/ca_obj_byte_swap.c +40 -40
  24. data/ext/ca_obj_const_string.c +180 -50
  25. data/ext/ca_obj_face.c +428 -62
  26. data/ext/ca_obj_face.h +107 -47
  27. data/ext/ca_obj_fake.c +21 -50
  28. data/ext/ca_obj_farray.c +1 -0
  29. data/ext/ca_obj_field.c +16 -3
  30. data/ext/ca_obj_fixlen_string.c +39 -26
  31. data/ext/ca_obj_grid.c +181 -124
  32. data/ext/ca_obj_meld.c +235 -55
  33. data/ext/ca_obj_moncmp.c +61 -61
  34. data/ext/ca_obj_monop.c +125 -107
  35. data/ext/ca_obj_object.c +551 -233
  36. data/ext/ca_obj_record.c +51 -16
  37. data/ext/ca_obj_reduce.c +5 -8
  38. data/ext/ca_obj_refer.c +117 -33
  39. data/ext/ca_obj_remap.c +57 -17
  40. data/ext/ca_obj_repeat.c +21 -5
  41. data/ext/ca_obj_roll.c +115 -11
  42. data/ext/ca_obj_select.c +88 -75
  43. data/ext/ca_obj_select_axis.c +58 -60
  44. data/ext/ca_obj_shift.c +22 -102
  45. data/ext/ca_obj_stack.c +223 -123
  46. data/ext/ca_obj_stride.c +267 -35
  47. data/ext/ca_obj_string.c +25 -22
  48. data/ext/ca_obj_tile.c +32 -16
  49. data/ext/ca_obj_time.c +23 -25
  50. data/ext/ca_obj_timedelta.c +21 -23
  51. data/ext/ca_obj_transpose.c +12 -3
  52. data/ext/ca_obj_triop.c +110 -117
  53. data/ext/ca_obj_window.c +157 -29
  54. data/ext/ca_op_ipower.c +25 -13
  55. data/ext/ca_op_powi.h +57 -30
  56. data/ext/ca_pow5_table.h +656 -0
  57. data/ext/ca_rng_normal.h +42 -0
  58. data/ext/ca_rng_xoshiro256pp.h +105 -0
  59. data/ext/ca_sort_kernels.h +70 -0
  60. data/ext/ca_sweep_engine.c +385 -198
  61. data/ext/ca_sweep_engine.h +31 -23
  62. data/ext/ca_triop_dispatch.c +4 -1
  63. data/ext/ca_triop_dispatch.h +5 -2
  64. data/ext/caframe_csv_reader.c +463 -0
  65. data/ext/carray.h +90 -28
  66. data/ext/carray_access.c +487 -231
  67. data/ext/carray_address_basis.c +731 -0
  68. data/ext/carray_attribute.c +45 -3
  69. data/ext/carray_bincount.c +32 -2
  70. data/ext/carray_broadcast.c +49 -17
  71. data/ext/carray_call_cfunc.c +667 -511
  72. data/ext/carray_cast.c +1556 -247
  73. data/ext/carray_cast_func.rb +34 -21
  74. data/ext/carray_conversion.c +197 -73
  75. data/ext/carray_copy.c +84 -38
  76. data/ext/carray_core.c +591 -119
  77. data/ext/carray_count.c +148 -96
  78. data/ext/carray_element.c +18 -27
  79. data/ext/carray_factorize.c +604 -291
  80. data/ext/carray_generate.c +76 -40
  81. data/ext/carray_histogram.c +152 -94
  82. data/ext/carray_hold.c +2 -1
  83. data/ext/carray_index_classifier.c +63 -96
  84. data/ext/carray_internal.h +400 -1
  85. data/ext/carray_lazy.c +834 -79
  86. data/ext/carray_loop.c +88 -66
  87. data/ext/carray_mask.c +705 -324
  88. data/ext/carray_math_kernel.h +1 -0
  89. data/ext/carray_median_percentile.c +263 -63
  90. data/ext/carray_memory_view.c +254 -248
  91. data/ext/carray_operator.c +1093 -363
  92. data/ext/carray_order.c +133 -69
  93. data/ext/carray_partition.c +102 -56
  94. data/ext/carray_random.c +582 -204
  95. data/ext/carray_scatter.c +308 -65
  96. data/ext/carray_segment.c +257 -0
  97. data/ext/carray_slab.c +183 -70
  98. data/ext/carray_sort.c +235 -240
  99. data/ext/carray_sort_kernel.c +8 -1
  100. data/ext/carray_struct.c +99 -21
  101. data/ext/carray_test.c +167 -64
  102. data/ext/carray_time_text.c +1182 -0
  103. data/ext/carray_utils.c +363 -98
  104. data/ext/extconf.rb +27 -2
  105. data/ext/mk_call_cfunc.rb +103 -118
  106. data/ext/mk_pow5_table.rb +35 -0
  107. data/ext/mkkernel.rb +1349 -851
  108. data/ext/ruby_carray.c +17 -2
  109. data/ext/version.h +4 -4
  110. data/ext/version.rb +4 -2
  111. data/lib/carray/attribute.rb +39 -0
  112. data/lib/carray/autoload_carray.rb +24 -3
  113. data/lib/carray/autoload_method_extension.rb +18 -0
  114. data/lib/carray/axis_group.rb +245 -20
  115. data/lib/carray/basics.rb +95 -25
  116. data/lib/carray/bincount_nd.rb +6 -0
  117. data/lib/carray/block_iterator.rb +200 -54
  118. data/lib/carray/boolean_reduce.rb +21 -29
  119. data/lib/carray/categorical.rb +244 -59
  120. data/lib/carray/categorical_iterator.rb +391 -757
  121. data/lib/carray/complex.rb +36 -29
  122. data/lib/carray/conditional.rb +94 -7
  123. data/lib/carray/const_string.rb +177 -27
  124. data/lib/carray/construct.rb +40 -0
  125. data/lib/carray/data_type_extension.rb +3 -0
  126. data/lib/carray/data_type_limits.rb +91 -0
  127. data/lib/carray/fixlen_string.rb +1 -1
  128. data/lib/carray/frame/concat.rb +157 -6
  129. data/lib/carray/frame/convert.rb +13 -7
  130. data/lib/carray/frame/csv_parser.rb +590 -76
  131. data/lib/carray/frame/describe.rb +79 -0
  132. data/lib/carray/frame/frame.rb +205 -35
  133. data/lib/carray/frame/group.rb +199 -40
  134. data/lib/carray/frame/io.rb +452 -60
  135. data/lib/carray/frame/join.rb +134 -46
  136. data/lib/carray/frame/records.rb +54 -19
  137. data/lib/carray/frame/reshape.rb +448 -0
  138. data/lib/carray/frame/sort.rb +26 -2
  139. data/lib/carray/frame/verbs.rb +726 -56
  140. data/lib/carray/frame.rb +2 -0
  141. data/lib/carray/fuse_source.rb +111 -2
  142. data/lib/carray/fusion.rb +229 -38
  143. data/lib/carray/inspect.rb +71 -20
  144. data/lib/carray/iterator.rb +157 -2
  145. data/lib/carray/lazy.rb +54 -67
  146. data/lib/carray/mask_gap_fill.rb +66 -50
  147. data/lib/carray/math.rb +32 -19
  148. data/lib/carray/meld_reduce.rb +40 -7
  149. data/lib/carray/methods/align_addr.rb +8 -4
  150. data/lib/carray/methods/bincount.rb +2 -2
  151. data/lib/carray/methods/bit_string.rb +14 -3
  152. data/lib/carray/methods/composition.rb +16 -10
  153. data/lib/carray/methods/discovery_along.rb +74 -0
  154. data/lib/carray/methods/factorize.rb +50 -0
  155. data/lib/carray/methods/gather_nd.rb +13 -2
  156. data/lib/carray/methods/insert_block.rb +9 -14
  157. data/lib/carray/methods/is_in.rb +130 -6
  158. data/lib/carray/methods/join.rb +1 -1
  159. data/lib/carray/methods/locate_addr.rb +235 -21
  160. data/lib/carray/methods/mask_duplicates.rb +35 -1
  161. data/lib/carray/methods/mode.rb +18 -1
  162. data/lib/carray/methods/nunique.rb +22 -1
  163. data/lib/carray/methods/repeat.rb +91 -0
  164. data/lib/carray/methods/resize.rb +21 -23
  165. data/lib/carray/methods/snap.rb +34 -12
  166. data/lib/carray/methods/unique.rb +52 -3
  167. data/lib/carray/record_order.rb +208 -0
  168. data/lib/carray/rng.rb +86 -0
  169. data/lib/carray/runtime.rb +14 -11
  170. data/lib/carray/segment_iterator.rb +990 -0
  171. data/lib/carray/serialize.rb +197 -27
  172. data/lib/carray/slab_iterator.rb +109 -40
  173. data/lib/carray/stack.rb +10 -4
  174. data/lib/carray/string_operation_extension.rb +9 -4
  175. data/lib/carray/struct.rb +142 -51
  176. data/lib/carray/struct_builder.rb +110 -14
  177. data/lib/carray/table.rb +2 -2
  178. data/lib/carray/time.rb +535 -105
  179. data/lib/carray/window_iterator.rb +259 -82
  180. data/lib/carray.rb +4 -2
  181. data/yard-stubs/ca_obj_array.rb +4 -4
  182. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  183. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  184. data/yard-stubs/ca_obj_block.rb +2 -7
  185. data/yard-stubs/ca_obj_fake.rb +1 -1
  186. data/yard-stubs/ca_obj_field.rb +1 -1
  187. data/yard-stubs/ca_obj_refer.rb +3 -3
  188. data/yard-stubs/ca_obj_roll.rb +0 -1
  189. data/yard-stubs/ca_obj_stride.rb +10 -7
  190. data/yard-stubs/ca_obj_transpose.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +11 -4
  192. data/yard-stubs/carray_access.rb +6 -5
  193. data/yard-stubs/carray_broadcast.rb +2 -2
  194. data/yard-stubs/carray_cast.rb +78 -43
  195. data/yard-stubs/carray_conversion.rb +13 -1
  196. data/yard-stubs/carray_copy.rb +8 -3
  197. data/yard-stubs/carray_core.rb +3 -83
  198. data/yard-stubs/carray_count.rb +16 -2
  199. data/yard-stubs/carray_lazy.rb +210 -1
  200. data/yard-stubs/carray_loop.rb +4 -1
  201. data/yard-stubs/carray_mask.rb +34 -10
  202. data/yard-stubs/carray_math.rb +1499 -4
  203. data/yard-stubs/carray_median_percentile.rb +26 -8
  204. data/yard-stubs/carray_order.rb +43 -82
  205. data/yard-stubs/carray_scatter.rb +10 -3
  206. data/yard-stubs/carray_segment.rb +72 -0
  207. data/yard-stubs/carray_slab.rb +11 -8
  208. data/yard-stubs/carray_sort.rb +50 -8
  209. data/yard-stubs/carray_test.rb +10 -0
  210. data/yard-stubs/carray_utils.rb +0 -26
  211. metadata +19 -19
  212. data/ext/ca_for_each_element.h +0 -239
  213. data/ext/carray_build_flags.h +0 -3
  214. data/ext/carray_config.h +0 -28
  215. data/ext/carray_kernels_bincmp.c +0 -4446
  216. data/ext/carray_kernels_binop.c +0 -11001
  217. data/ext/carray_kernels_init.c +0 -1131
  218. data/ext/carray_kernels_map.c +0 -3467
  219. data/ext/carray_kernels_moncmp.c +0 -2097
  220. data/ext/carray_kernels_monop.c +0 -18313
  221. data/ext/carray_kernels_reduce_aggregate.c +0 -25837
  222. data/ext/carray_kernels_reduce_boolean.c +0 -330
  223. data/ext/carray_kernels_reduce_cumulative.c +0 -14593
  224. data/ext/carray_kernels_reduce_extreme.c +0 -16948
  225. data/ext/carray_kernels_reduce_variance.c +0 -3910
  226. data/ext/carray_kernels_scan.c +0 -3693
  227. data/ext/carray_kernels_search.c +0 -32138
  228. data/ext/carray_kernels_sort.c +0 -10626
  229. data/ext/carray_kernels_triop.c +0 -1392
@@ -48,14 +48,78 @@
48
48
  #include "ca_sweep_engine.h"
49
49
  #include <string.h>
50
50
 
51
- /* The chunk's iteration mask, or NULL when no INPUT operand carried one.
52
- m0 is chunk-sized and re-gathered per chunk by ca_sweep_next_chunk, so
53
- it is already the slice -- one byte per cell, indexed 0..chunk_n-1
54
- alongside base[] and stride[]. */
55
- static const boolean8_t *
56
- ca_sweep_chunk_mask (ca_sweep_state_t *st)
57
- {
58
- return st->m0;
51
+ /* Chunk walk for the ca_call_cslab_N family, run by ca_sweep_run_chunked
52
+ so that a callback raising part way through gives back what the engine
53
+ holds. Hands the author one chunk at a time. base[] is rewritten per
54
+ chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points at the
55
+ arena scratch the chunk was just gathered into, which is packed, so
56
+ stride[] is the element size and the author's inner loop sees
57
+ contiguous data. m0 is the chunk's iteration mask, or NULL when no
58
+ INPUT operand carried one: chunk-sized and re-gathered per chunk, so it
59
+ is already the slice -- one byte per cell, indexed 0..chunk_n-1
60
+ alongside base[] and stride[]. The arity does not appear here: the
61
+ operands reach the callback through base[] / stride[]. */
62
+ typedef struct {
63
+ ca_sweep_state_t *st;
64
+ ca_cslab_t func; /* ca_call_cslab_N */
65
+ ca_cslab_r_t func_r; /* ca_call_cslab_N_r */
66
+ void *userdata;
67
+ } ca_cslab_ctx_t;
68
+
69
+ static VALUE
70
+ ca_cslab_walk (VALUE arg)
71
+ {
72
+ ca_cslab_ctx_t *c = (ca_cslab_ctx_t *) arg;
73
+ ca_sweep_state_t *st = c->st;
74
+ while ( ca_sweep_next_chunk(st) ) {
75
+ c->func(st->base, st->stride, st->chunk_n, st->m0);
76
+ }
77
+ return Qnil;
78
+ }
79
+
80
+ static VALUE
81
+ ca_cslab_r_walk (VALUE arg)
82
+ {
83
+ ca_cslab_ctx_t *c = (ca_cslab_ctx_t *) arg;
84
+ ca_sweep_state_t *st = c->st;
85
+ while ( ca_sweep_next_chunk(st) ) {
86
+ c->func_r(st->base, st->stride, st->chunk_n, st->m0, c->userdata);
87
+ }
88
+ return Qnil;
89
+ }
90
+
91
+ typedef struct {
92
+ ca_sweep_state_t *st;
93
+ void (*func)(void *p0);
94
+ void *userdata;
95
+ } ca_call_cfunc_1_ctx_t;
96
+
97
+ static VALUE
98
+ ca_call_cfunc_1_walk (VALUE arg)
99
+ {
100
+ ca_call_cfunc_1_ctx_t *c = (ca_call_cfunc_1_ctx_t *) arg;
101
+ ca_sweep_state_t *st = c->st;
102
+ char *p[1];
103
+ ca_size_t k;
104
+ int k_op;
105
+ if ( st->m0 ) {
106
+ for ( k = 0; k < st->n_kernel; k++ ) {
107
+ if ( ! st->m0[k] ) {
108
+ for ( k_op = 0; k_op < 1; k_op++ ) {
109
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
110
+ }
111
+ c->func(p[0]);
112
+ }
113
+ }
114
+ } else {
115
+ for ( k = 0; k < st->n_kernel; k++ ) {
116
+ for ( k_op = 0; k_op < 1; k_op++ ) {
117
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
118
+ }
119
+ c->func(p[0]);
120
+ }
121
+ }
122
+ return Qnil;
59
123
  }
60
124
 
61
125
  VALUE
@@ -68,13 +132,13 @@ ca_call_cfunc_1 (void (*func)(void *p0), const char *fsync,
68
132
  char *owned_buf[1];
69
133
  int attached[1];
70
134
  ca_sweep_state_t state;
71
- int k_op;
135
+ ca_call_cfunc_1_ctx_t ctx;
72
136
 
73
137
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
74
138
 
75
139
  /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
76
- broadcast shape check, mask OR across INPUTs, mask propagate to
77
- OUTPUTs. Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
140
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
141
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
78
142
  state.n_ops = 1;
79
143
  state.fsync = fsync;
80
144
  state.cx = cx;
@@ -82,37 +146,50 @@ ca_call_cfunc_1 (void (*func)(void *p0), const char *fsync,
82
146
  state.stride = stride;
83
147
  state.owned_buf = owned_buf;
84
148
  state.attached = attached;
85
- state.no_mask = 0;
86
149
  state.src_label = "ca_call_cfunc_1";
87
150
 
88
151
  ca_sweep_acquire(&state);
89
152
 
90
- /* inner loop: advance per-cell ptrs and invoke user kernel func */
91
- {
92
- char *p[1];
93
- ca_size_t k;
94
- if ( state.m0 ) {
95
- for ( k = 0; k < state.n_kernel; k++ ) {
96
- if ( ! state.m0[k] ) {
97
- for ( k_op = 0; k_op < 1; k_op++ ) {
98
- p[k_op] = base[k_op] + k * stride[k_op];
99
- }
100
- func(p[0]);
153
+ ctx.st = &state;
154
+ ctx.func = func;
155
+ ctx.userdata = NULL;
156
+ ca_sweep_run(&state, ca_call_cfunc_1_walk, (VALUE) &ctx);
157
+
158
+ return rcx0;
159
+ }
160
+
161
+ typedef struct {
162
+ ca_sweep_state_t *st;
163
+ void (*func)(void *p0, void *p1);
164
+ void *userdata;
165
+ } ca_call_cfunc_2_ctx_t;
166
+
167
+ static VALUE
168
+ ca_call_cfunc_2_walk (VALUE arg)
169
+ {
170
+ ca_call_cfunc_2_ctx_t *c = (ca_call_cfunc_2_ctx_t *) arg;
171
+ ca_sweep_state_t *st = c->st;
172
+ char *p[2];
173
+ ca_size_t k;
174
+ int k_op;
175
+ if ( st->m0 ) {
176
+ for ( k = 0; k < st->n_kernel; k++ ) {
177
+ if ( ! st->m0[k] ) {
178
+ for ( k_op = 0; k_op < 2; k_op++ ) {
179
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
101
180
  }
181
+ c->func(p[0], p[1]);
102
182
  }
103
- } else {
104
- for ( k = 0; k < state.n_kernel; k++ ) {
105
- for ( k_op = 0; k_op < 1; k_op++ ) {
106
- p[k_op] = base[k_op] + k * stride[k_op];
107
- }
108
- func(p[0]);
183
+ }
184
+ } else {
185
+ for ( k = 0; k < st->n_kernel; k++ ) {
186
+ for ( k_op = 0; k_op < 2; k_op++ ) {
187
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
109
188
  }
189
+ c->func(p[0], p[1]);
110
190
  }
111
191
  }
112
-
113
- ca_sweep_release(&state);
114
-
115
- return rcx0;
192
+ return Qnil;
116
193
  }
117
194
 
118
195
  VALUE
@@ -125,14 +202,14 @@ ca_call_cfunc_2 (void (*func)(void *p0, void *p1), const char *fsync,
125
202
  char *owned_buf[2];
126
203
  int attached[2];
127
204
  ca_sweep_state_t state;
128
- int k_op;
205
+ ca_call_cfunc_2_ctx_t ctx;
129
206
 
130
207
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
131
208
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
132
209
 
133
210
  /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
134
- broadcast shape check, mask OR across INPUTs, mask propagate to
135
- OUTPUTs. Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
211
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
212
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
136
213
  state.n_ops = 2;
137
214
  state.fsync = fsync;
138
215
  state.cx = cx;
@@ -140,37 +217,50 @@ ca_call_cfunc_2 (void (*func)(void *p0, void *p1), const char *fsync,
140
217
  state.stride = stride;
141
218
  state.owned_buf = owned_buf;
142
219
  state.attached = attached;
143
- state.no_mask = 0;
144
220
  state.src_label = "ca_call_cfunc_2";
145
221
 
146
222
  ca_sweep_acquire(&state);
147
223
 
148
- /* inner loop: advance per-cell ptrs and invoke user kernel func */
149
- {
150
- char *p[2];
151
- ca_size_t k;
152
- if ( state.m0 ) {
153
- for ( k = 0; k < state.n_kernel; k++ ) {
154
- if ( ! state.m0[k] ) {
155
- for ( k_op = 0; k_op < 2; k_op++ ) {
156
- p[k_op] = base[k_op] + k * stride[k_op];
157
- }
158
- func(p[0], p[1]);
224
+ ctx.st = &state;
225
+ ctx.func = func;
226
+ ctx.userdata = NULL;
227
+ ca_sweep_run(&state, ca_call_cfunc_2_walk, (VALUE) &ctx);
228
+
229
+ return rcx0;
230
+ }
231
+
232
+ typedef struct {
233
+ ca_sweep_state_t *st;
234
+ void (*func)(void *p0, void *p1, void *p2);
235
+ void *userdata;
236
+ } ca_call_cfunc_3_ctx_t;
237
+
238
+ static VALUE
239
+ ca_call_cfunc_3_walk (VALUE arg)
240
+ {
241
+ ca_call_cfunc_3_ctx_t *c = (ca_call_cfunc_3_ctx_t *) arg;
242
+ ca_sweep_state_t *st = c->st;
243
+ char *p[3];
244
+ ca_size_t k;
245
+ int k_op;
246
+ if ( st->m0 ) {
247
+ for ( k = 0; k < st->n_kernel; k++ ) {
248
+ if ( ! st->m0[k] ) {
249
+ for ( k_op = 0; k_op < 3; k_op++ ) {
250
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
159
251
  }
252
+ c->func(p[0], p[1], p[2]);
160
253
  }
161
- } else {
162
- for ( k = 0; k < state.n_kernel; k++ ) {
163
- for ( k_op = 0; k_op < 2; k_op++ ) {
164
- p[k_op] = base[k_op] + k * stride[k_op];
165
- }
166
- func(p[0], p[1]);
254
+ }
255
+ } else {
256
+ for ( k = 0; k < st->n_kernel; k++ ) {
257
+ for ( k_op = 0; k_op < 3; k_op++ ) {
258
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
167
259
  }
260
+ c->func(p[0], p[1], p[2]);
168
261
  }
169
262
  }
170
-
171
- ca_sweep_release(&state);
172
-
173
- return rcx0;
263
+ return Qnil;
174
264
  }
175
265
 
176
266
  VALUE
@@ -183,15 +273,15 @@ ca_call_cfunc_3 (void (*func)(void *p0, void *p1, void *p2), const char *fsync,
183
273
  char *owned_buf[3];
184
274
  int attached[3];
185
275
  ca_sweep_state_t state;
186
- int k_op;
276
+ ca_call_cfunc_3_ctx_t ctx;
187
277
 
188
278
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
189
279
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
190
280
  TypedData_Get_Struct(rcx2, CArray, &carray_data_type, cx[2]);
191
281
 
192
282
  /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
193
- broadcast shape check, mask OR across INPUTs, mask propagate to
194
- OUTPUTs. Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
283
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
284
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
195
285
  state.n_ops = 3;
196
286
  state.fsync = fsync;
197
287
  state.cx = cx;
@@ -199,37 +289,50 @@ ca_call_cfunc_3 (void (*func)(void *p0, void *p1, void *p2), const char *fsync,
199
289
  state.stride = stride;
200
290
  state.owned_buf = owned_buf;
201
291
  state.attached = attached;
202
- state.no_mask = 0;
203
292
  state.src_label = "ca_call_cfunc_3";
204
293
 
205
294
  ca_sweep_acquire(&state);
206
295
 
207
- /* inner loop: advance per-cell ptrs and invoke user kernel func */
208
- {
209
- char *p[3];
210
- ca_size_t k;
211
- if ( state.m0 ) {
212
- for ( k = 0; k < state.n_kernel; k++ ) {
213
- if ( ! state.m0[k] ) {
214
- for ( k_op = 0; k_op < 3; k_op++ ) {
215
- p[k_op] = base[k_op] + k * stride[k_op];
216
- }
217
- func(p[0], p[1], p[2]);
296
+ ctx.st = &state;
297
+ ctx.func = func;
298
+ ctx.userdata = NULL;
299
+ ca_sweep_run(&state, ca_call_cfunc_3_walk, (VALUE) &ctx);
300
+
301
+ return rcx0;
302
+ }
303
+
304
+ typedef struct {
305
+ ca_sweep_state_t *st;
306
+ void (*func)(void *p0, void *p1, void *p2, void *p3);
307
+ void *userdata;
308
+ } ca_call_cfunc_4_ctx_t;
309
+
310
+ static VALUE
311
+ ca_call_cfunc_4_walk (VALUE arg)
312
+ {
313
+ ca_call_cfunc_4_ctx_t *c = (ca_call_cfunc_4_ctx_t *) arg;
314
+ ca_sweep_state_t *st = c->st;
315
+ char *p[4];
316
+ ca_size_t k;
317
+ int k_op;
318
+ if ( st->m0 ) {
319
+ for ( k = 0; k < st->n_kernel; k++ ) {
320
+ if ( ! st->m0[k] ) {
321
+ for ( k_op = 0; k_op < 4; k_op++ ) {
322
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
218
323
  }
324
+ c->func(p[0], p[1], p[2], p[3]);
219
325
  }
220
- } else {
221
- for ( k = 0; k < state.n_kernel; k++ ) {
222
- for ( k_op = 0; k_op < 3; k_op++ ) {
223
- p[k_op] = base[k_op] + k * stride[k_op];
224
- }
225
- func(p[0], p[1], p[2]);
326
+ }
327
+ } else {
328
+ for ( k = 0; k < st->n_kernel; k++ ) {
329
+ for ( k_op = 0; k_op < 4; k_op++ ) {
330
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
226
331
  }
332
+ c->func(p[0], p[1], p[2], p[3]);
227
333
  }
228
334
  }
229
-
230
- ca_sweep_release(&state);
231
-
232
- return rcx0;
335
+ return Qnil;
233
336
  }
234
337
 
235
338
  VALUE
@@ -242,7 +345,7 @@ ca_call_cfunc_4 (void (*func)(void *p0, void *p1, void *p2, void *p3), const cha
242
345
  char *owned_buf[4];
243
346
  int attached[4];
244
347
  ca_sweep_state_t state;
245
- int k_op;
348
+ ca_call_cfunc_4_ctx_t ctx;
246
349
 
247
350
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
248
351
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -250,8 +353,8 @@ ca_call_cfunc_4 (void (*func)(void *p0, void *p1, void *p2, void *p3), const cha
250
353
  TypedData_Get_Struct(rcx3, CArray, &carray_data_type, cx[3]);
251
354
 
252
355
  /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
253
- broadcast shape check, mask OR across INPUTs, mask propagate to
254
- OUTPUTs. Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
356
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
357
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
255
358
  state.n_ops = 4;
256
359
  state.fsync = fsync;
257
360
  state.cx = cx;
@@ -259,37 +362,50 @@ ca_call_cfunc_4 (void (*func)(void *p0, void *p1, void *p2, void *p3), const cha
259
362
  state.stride = stride;
260
363
  state.owned_buf = owned_buf;
261
364
  state.attached = attached;
262
- state.no_mask = 0;
263
365
  state.src_label = "ca_call_cfunc_4";
264
366
 
265
367
  ca_sweep_acquire(&state);
266
368
 
267
- /* inner loop: advance per-cell ptrs and invoke user kernel func */
268
- {
269
- char *p[4];
270
- ca_size_t k;
271
- if ( state.m0 ) {
272
- for ( k = 0; k < state.n_kernel; k++ ) {
273
- if ( ! state.m0[k] ) {
274
- for ( k_op = 0; k_op < 4; k_op++ ) {
275
- p[k_op] = base[k_op] + k * stride[k_op];
276
- }
277
- func(p[0], p[1], p[2], p[3]);
369
+ ctx.st = &state;
370
+ ctx.func = func;
371
+ ctx.userdata = NULL;
372
+ ca_sweep_run(&state, ca_call_cfunc_4_walk, (VALUE) &ctx);
373
+
374
+ return rcx0;
375
+ }
376
+
377
+ typedef struct {
378
+ ca_sweep_state_t *st;
379
+ void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4);
380
+ void *userdata;
381
+ } ca_call_cfunc_5_ctx_t;
382
+
383
+ static VALUE
384
+ ca_call_cfunc_5_walk (VALUE arg)
385
+ {
386
+ ca_call_cfunc_5_ctx_t *c = (ca_call_cfunc_5_ctx_t *) arg;
387
+ ca_sweep_state_t *st = c->st;
388
+ char *p[5];
389
+ ca_size_t k;
390
+ int k_op;
391
+ if ( st->m0 ) {
392
+ for ( k = 0; k < st->n_kernel; k++ ) {
393
+ if ( ! st->m0[k] ) {
394
+ for ( k_op = 0; k_op < 5; k_op++ ) {
395
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
278
396
  }
397
+ c->func(p[0], p[1], p[2], p[3], p[4]);
279
398
  }
280
- } else {
281
- for ( k = 0; k < state.n_kernel; k++ ) {
282
- for ( k_op = 0; k_op < 4; k_op++ ) {
283
- p[k_op] = base[k_op] + k * stride[k_op];
284
- }
285
- func(p[0], p[1], p[2], p[3]);
399
+ }
400
+ } else {
401
+ for ( k = 0; k < st->n_kernel; k++ ) {
402
+ for ( k_op = 0; k_op < 5; k_op++ ) {
403
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
286
404
  }
405
+ c->func(p[0], p[1], p[2], p[3], p[4]);
287
406
  }
288
407
  }
289
-
290
- ca_sweep_release(&state);
291
-
292
- return rcx0;
408
+ return Qnil;
293
409
  }
294
410
 
295
411
  VALUE
@@ -302,7 +418,7 @@ ca_call_cfunc_5 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4),
302
418
  char *owned_buf[5];
303
419
  int attached[5];
304
420
  ca_sweep_state_t state;
305
- int k_op;
421
+ ca_call_cfunc_5_ctx_t ctx;
306
422
 
307
423
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
308
424
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -311,8 +427,8 @@ ca_call_cfunc_5 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4),
311
427
  TypedData_Get_Struct(rcx4, CArray, &carray_data_type, cx[4]);
312
428
 
313
429
  /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
314
- broadcast shape check, mask OR across INPUTs, mask propagate to
315
- OUTPUTs. Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
430
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
431
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
316
432
  state.n_ops = 5;
317
433
  state.fsync = fsync;
318
434
  state.cx = cx;
@@ -320,37 +436,50 @@ ca_call_cfunc_5 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4),
320
436
  state.stride = stride;
321
437
  state.owned_buf = owned_buf;
322
438
  state.attached = attached;
323
- state.no_mask = 0;
324
439
  state.src_label = "ca_call_cfunc_5";
325
440
 
326
441
  ca_sweep_acquire(&state);
327
442
 
328
- /* inner loop: advance per-cell ptrs and invoke user kernel func */
329
- {
330
- char *p[5];
331
- ca_size_t k;
332
- if ( state.m0 ) {
333
- for ( k = 0; k < state.n_kernel; k++ ) {
334
- if ( ! state.m0[k] ) {
335
- for ( k_op = 0; k_op < 5; k_op++ ) {
336
- p[k_op] = base[k_op] + k * stride[k_op];
337
- }
338
- func(p[0], p[1], p[2], p[3], p[4]);
443
+ ctx.st = &state;
444
+ ctx.func = func;
445
+ ctx.userdata = NULL;
446
+ ca_sweep_run(&state, ca_call_cfunc_5_walk, (VALUE) &ctx);
447
+
448
+ return rcx0;
449
+ }
450
+
451
+ typedef struct {
452
+ ca_sweep_state_t *st;
453
+ void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4, void *p5);
454
+ void *userdata;
455
+ } ca_call_cfunc_6_ctx_t;
456
+
457
+ static VALUE
458
+ ca_call_cfunc_6_walk (VALUE arg)
459
+ {
460
+ ca_call_cfunc_6_ctx_t *c = (ca_call_cfunc_6_ctx_t *) arg;
461
+ ca_sweep_state_t *st = c->st;
462
+ char *p[6];
463
+ ca_size_t k;
464
+ int k_op;
465
+ if ( st->m0 ) {
466
+ for ( k = 0; k < st->n_kernel; k++ ) {
467
+ if ( ! st->m0[k] ) {
468
+ for ( k_op = 0; k_op < 6; k_op++ ) {
469
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
339
470
  }
471
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5]);
340
472
  }
341
- } else {
342
- for ( k = 0; k < state.n_kernel; k++ ) {
343
- for ( k_op = 0; k_op < 5; k_op++ ) {
344
- p[k_op] = base[k_op] + k * stride[k_op];
345
- }
346
- func(p[0], p[1], p[2], p[3], p[4]);
473
+ }
474
+ } else {
475
+ for ( k = 0; k < st->n_kernel; k++ ) {
476
+ for ( k_op = 0; k_op < 6; k_op++ ) {
477
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
347
478
  }
479
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5]);
348
480
  }
349
481
  }
350
-
351
- ca_sweep_release(&state);
352
-
353
- return rcx0;
482
+ return Qnil;
354
483
  }
355
484
 
356
485
  VALUE
@@ -363,7 +492,7 @@ ca_call_cfunc_6 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4,
363
492
  char *owned_buf[6];
364
493
  int attached[6];
365
494
  ca_sweep_state_t state;
366
- int k_op;
495
+ ca_call_cfunc_6_ctx_t ctx;
367
496
 
368
497
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
369
498
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -373,8 +502,8 @@ ca_call_cfunc_6 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4,
373
502
  TypedData_Get_Struct(rcx5, CArray, &carray_data_type, cx[5]);
374
503
 
375
504
  /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
376
- broadcast shape check, mask OR across INPUTs, mask propagate to
377
- OUTPUTs. Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
505
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
506
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
378
507
  state.n_ops = 6;
379
508
  state.fsync = fsync;
380
509
  state.cx = cx;
@@ -382,37 +511,50 @@ ca_call_cfunc_6 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4,
382
511
  state.stride = stride;
383
512
  state.owned_buf = owned_buf;
384
513
  state.attached = attached;
385
- state.no_mask = 0;
386
514
  state.src_label = "ca_call_cfunc_6";
387
515
 
388
516
  ca_sweep_acquire(&state);
389
517
 
390
- /* inner loop: advance per-cell ptrs and invoke user kernel func */
391
- {
392
- char *p[6];
393
- ca_size_t k;
394
- if ( state.m0 ) {
395
- for ( k = 0; k < state.n_kernel; k++ ) {
396
- if ( ! state.m0[k] ) {
397
- for ( k_op = 0; k_op < 6; k_op++ ) {
398
- p[k_op] = base[k_op] + k * stride[k_op];
399
- }
400
- func(p[0], p[1], p[2], p[3], p[4], p[5]);
518
+ ctx.st = &state;
519
+ ctx.func = func;
520
+ ctx.userdata = NULL;
521
+ ca_sweep_run(&state, ca_call_cfunc_6_walk, (VALUE) &ctx);
522
+
523
+ return rcx0;
524
+ }
525
+
526
+ typedef struct {
527
+ ca_sweep_state_t *st;
528
+ void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6);
529
+ void *userdata;
530
+ } ca_call_cfunc_7_ctx_t;
531
+
532
+ static VALUE
533
+ ca_call_cfunc_7_walk (VALUE arg)
534
+ {
535
+ ca_call_cfunc_7_ctx_t *c = (ca_call_cfunc_7_ctx_t *) arg;
536
+ ca_sweep_state_t *st = c->st;
537
+ char *p[7];
538
+ ca_size_t k;
539
+ int k_op;
540
+ if ( st->m0 ) {
541
+ for ( k = 0; k < st->n_kernel; k++ ) {
542
+ if ( ! st->m0[k] ) {
543
+ for ( k_op = 0; k_op < 7; k_op++ ) {
544
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
401
545
  }
546
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
402
547
  }
403
- } else {
404
- for ( k = 0; k < state.n_kernel; k++ ) {
405
- for ( k_op = 0; k_op < 6; k_op++ ) {
406
- p[k_op] = base[k_op] + k * stride[k_op];
407
- }
408
- func(p[0], p[1], p[2], p[3], p[4], p[5]);
548
+ }
549
+ } else {
550
+ for ( k = 0; k < st->n_kernel; k++ ) {
551
+ for ( k_op = 0; k_op < 7; k_op++ ) {
552
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
409
553
  }
554
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
410
555
  }
411
556
  }
412
-
413
- ca_sweep_release(&state);
414
-
415
- return rcx0;
557
+ return Qnil;
416
558
  }
417
559
 
418
560
  VALUE
@@ -425,7 +567,7 @@ ca_call_cfunc_7 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4,
425
567
  char *owned_buf[7];
426
568
  int attached[7];
427
569
  ca_sweep_state_t state;
428
- int k_op;
570
+ ca_call_cfunc_7_ctx_t ctx;
429
571
 
430
572
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
431
573
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -436,8 +578,8 @@ ca_call_cfunc_7 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4,
436
578
  TypedData_Get_Struct(rcx6, CArray, &carray_data_type, cx[6]);
437
579
 
438
580
  /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
439
- broadcast shape check, mask OR across INPUTs, mask propagate to
440
- OUTPUTs. Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
581
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
582
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
441
583
  state.n_ops = 7;
442
584
  state.fsync = fsync;
443
585
  state.cx = cx;
@@ -445,35 +587,14 @@ ca_call_cfunc_7 (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4,
445
587
  state.stride = stride;
446
588
  state.owned_buf = owned_buf;
447
589
  state.attached = attached;
448
- state.no_mask = 0;
449
590
  state.src_label = "ca_call_cfunc_7";
450
591
 
451
592
  ca_sweep_acquire(&state);
452
593
 
453
- /* inner loop: advance per-cell ptrs and invoke user kernel func */
454
- {
455
- char *p[7];
456
- ca_size_t k;
457
- if ( state.m0 ) {
458
- for ( k = 0; k < state.n_kernel; k++ ) {
459
- if ( ! state.m0[k] ) {
460
- for ( k_op = 0; k_op < 7; k_op++ ) {
461
- p[k_op] = base[k_op] + k * stride[k_op];
462
- }
463
- func(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
464
- }
465
- }
466
- } else {
467
- for ( k = 0; k < state.n_kernel; k++ ) {
468
- for ( k_op = 0; k_op < 7; k_op++ ) {
469
- p[k_op] = base[k_op] + k * stride[k_op];
470
- }
471
- func(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
472
- }
473
- }
474
- }
475
-
476
- ca_sweep_release(&state);
594
+ ctx.st = &state;
595
+ ctx.func = func;
596
+ ctx.userdata = NULL;
597
+ ca_sweep_run(&state, ca_call_cfunc_7_walk, (VALUE) &ctx);
477
598
 
478
599
  return rcx0;
479
600
  }
@@ -867,6 +988,40 @@ ca_call_cfunc_3_3 (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, int8_t dt
867
988
  /* `void *userdata` parameter forwarded to every per-cell invocation. */
868
989
  /* -------------------------------------------------------------------- */
869
990
 
991
+ typedef struct {
992
+ ca_sweep_state_t *st;
993
+ void (*func)(void *p0, void *userdata);
994
+ void *userdata;
995
+ } ca_call_cfunc_1_r_ctx_t;
996
+
997
+ static VALUE
998
+ ca_call_cfunc_1_r_walk (VALUE arg)
999
+ {
1000
+ ca_call_cfunc_1_r_ctx_t *c = (ca_call_cfunc_1_r_ctx_t *) arg;
1001
+ ca_sweep_state_t *st = c->st;
1002
+ char *p[1];
1003
+ ca_size_t k;
1004
+ int k_op;
1005
+ if ( st->m0 ) {
1006
+ for ( k = 0; k < st->n_kernel; k++ ) {
1007
+ if ( ! st->m0[k] ) {
1008
+ for ( k_op = 0; k_op < 1; k_op++ ) {
1009
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1010
+ }
1011
+ c->func(p[0], c->userdata);
1012
+ }
1013
+ }
1014
+ } else {
1015
+ for ( k = 0; k < st->n_kernel; k++ ) {
1016
+ for ( k_op = 0; k_op < 1; k_op++ ) {
1017
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1018
+ }
1019
+ c->func(p[0], c->userdata);
1020
+ }
1021
+ }
1022
+ return Qnil;
1023
+ }
1024
+
870
1025
  VALUE
871
1026
  ca_call_cfunc_1_r (void (*func)(void *p0, void *userdata), const char *fsync,
872
1027
  VALUE rcx0,
@@ -878,12 +1033,13 @@ ca_call_cfunc_1_r (void (*func)(void *p0, void *userdata), const char *fsync,
878
1033
  char *owned_buf[1];
879
1034
  int attached[1];
880
1035
  ca_sweep_state_t state;
881
- int k_op;
1036
+ ca_call_cfunc_1_r_ctx_t ctx;
882
1037
 
883
1038
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
884
1039
 
885
- /* sweep engine: same lifecycle as ca_call_cfunc_1; the difference is
886
- the per-cell `func(...)` call has `userdata` as its last argument. */
1040
+ /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
1041
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
1042
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
887
1043
  state.n_ops = 1;
888
1044
  state.fsync = fsync;
889
1045
  state.cx = cx;
@@ -891,36 +1047,50 @@ ca_call_cfunc_1_r (void (*func)(void *p0, void *userdata), const char *fsync,
891
1047
  state.stride = stride;
892
1048
  state.owned_buf = owned_buf;
893
1049
  state.attached = attached;
894
- state.no_mask = 0;
895
1050
  state.src_label = "ca_call_cfunc_1_r";
896
1051
 
897
1052
  ca_sweep_acquire(&state);
898
1053
 
899
- {
900
- char *p[1];
901
- ca_size_t k;
902
- if ( state.m0 ) {
903
- for ( k = 0; k < state.n_kernel; k++ ) {
904
- if ( ! state.m0[k] ) {
905
- for ( k_op = 0; k_op < 1; k_op++ ) {
906
- p[k_op] = base[k_op] + k * stride[k_op];
907
- }
908
- func(p[0], userdata);
1054
+ ctx.st = &state;
1055
+ ctx.func = func;
1056
+ ctx.userdata = userdata;
1057
+ ca_sweep_run(&state, ca_call_cfunc_1_r_walk, (VALUE) &ctx);
1058
+
1059
+ return rcx0;
1060
+ }
1061
+
1062
+ typedef struct {
1063
+ ca_sweep_state_t *st;
1064
+ void (*func)(void *p0, void *p1, void *userdata);
1065
+ void *userdata;
1066
+ } ca_call_cfunc_2_r_ctx_t;
1067
+
1068
+ static VALUE
1069
+ ca_call_cfunc_2_r_walk (VALUE arg)
1070
+ {
1071
+ ca_call_cfunc_2_r_ctx_t *c = (ca_call_cfunc_2_r_ctx_t *) arg;
1072
+ ca_sweep_state_t *st = c->st;
1073
+ char *p[2];
1074
+ ca_size_t k;
1075
+ int k_op;
1076
+ if ( st->m0 ) {
1077
+ for ( k = 0; k < st->n_kernel; k++ ) {
1078
+ if ( ! st->m0[k] ) {
1079
+ for ( k_op = 0; k_op < 2; k_op++ ) {
1080
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
909
1081
  }
1082
+ c->func(p[0], p[1], c->userdata);
910
1083
  }
911
- } else {
912
- for ( k = 0; k < state.n_kernel; k++ ) {
913
- for ( k_op = 0; k_op < 1; k_op++ ) {
914
- p[k_op] = base[k_op] + k * stride[k_op];
915
- }
916
- func(p[0], userdata);
1084
+ }
1085
+ } else {
1086
+ for ( k = 0; k < st->n_kernel; k++ ) {
1087
+ for ( k_op = 0; k_op < 2; k_op++ ) {
1088
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
917
1089
  }
1090
+ c->func(p[0], p[1], c->userdata);
918
1091
  }
919
1092
  }
920
-
921
- ca_sweep_release(&state);
922
-
923
- return rcx0;
1093
+ return Qnil;
924
1094
  }
925
1095
 
926
1096
  VALUE
@@ -934,13 +1104,14 @@ ca_call_cfunc_2_r (void (*func)(void *p0, void *p1, void *userdata), const char
934
1104
  char *owned_buf[2];
935
1105
  int attached[2];
936
1106
  ca_sweep_state_t state;
937
- int k_op;
1107
+ ca_call_cfunc_2_r_ctx_t ctx;
938
1108
 
939
1109
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
940
1110
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
941
1111
 
942
- /* sweep engine: same lifecycle as ca_call_cfunc_2; the difference is
943
- the per-cell `func(...)` call has `userdata` as its last argument. */
1112
+ /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
1113
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
1114
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
944
1115
  state.n_ops = 2;
945
1116
  state.fsync = fsync;
946
1117
  state.cx = cx;
@@ -948,36 +1119,50 @@ ca_call_cfunc_2_r (void (*func)(void *p0, void *p1, void *userdata), const char
948
1119
  state.stride = stride;
949
1120
  state.owned_buf = owned_buf;
950
1121
  state.attached = attached;
951
- state.no_mask = 0;
952
1122
  state.src_label = "ca_call_cfunc_2_r";
953
1123
 
954
1124
  ca_sweep_acquire(&state);
955
1125
 
956
- {
957
- char *p[2];
958
- ca_size_t k;
959
- if ( state.m0 ) {
960
- for ( k = 0; k < state.n_kernel; k++ ) {
961
- if ( ! state.m0[k] ) {
962
- for ( k_op = 0; k_op < 2; k_op++ ) {
963
- p[k_op] = base[k_op] + k * stride[k_op];
964
- }
965
- func(p[0], p[1], userdata);
1126
+ ctx.st = &state;
1127
+ ctx.func = func;
1128
+ ctx.userdata = userdata;
1129
+ ca_sweep_run(&state, ca_call_cfunc_2_r_walk, (VALUE) &ctx);
1130
+
1131
+ return rcx0;
1132
+ }
1133
+
1134
+ typedef struct {
1135
+ ca_sweep_state_t *st;
1136
+ void (*func)(void *p0, void *p1, void *p2, void *userdata);
1137
+ void *userdata;
1138
+ } ca_call_cfunc_3_r_ctx_t;
1139
+
1140
+ static VALUE
1141
+ ca_call_cfunc_3_r_walk (VALUE arg)
1142
+ {
1143
+ ca_call_cfunc_3_r_ctx_t *c = (ca_call_cfunc_3_r_ctx_t *) arg;
1144
+ ca_sweep_state_t *st = c->st;
1145
+ char *p[3];
1146
+ ca_size_t k;
1147
+ int k_op;
1148
+ if ( st->m0 ) {
1149
+ for ( k = 0; k < st->n_kernel; k++ ) {
1150
+ if ( ! st->m0[k] ) {
1151
+ for ( k_op = 0; k_op < 3; k_op++ ) {
1152
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
966
1153
  }
1154
+ c->func(p[0], p[1], p[2], c->userdata);
967
1155
  }
968
- } else {
969
- for ( k = 0; k < state.n_kernel; k++ ) {
970
- for ( k_op = 0; k_op < 2; k_op++ ) {
971
- p[k_op] = base[k_op] + k * stride[k_op];
972
- }
973
- func(p[0], p[1], userdata);
1156
+ }
1157
+ } else {
1158
+ for ( k = 0; k < st->n_kernel; k++ ) {
1159
+ for ( k_op = 0; k_op < 3; k_op++ ) {
1160
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
974
1161
  }
1162
+ c->func(p[0], p[1], p[2], c->userdata);
975
1163
  }
976
1164
  }
977
-
978
- ca_sweep_release(&state);
979
-
980
- return rcx0;
1165
+ return Qnil;
981
1166
  }
982
1167
 
983
1168
  VALUE
@@ -991,14 +1176,15 @@ ca_call_cfunc_3_r (void (*func)(void *p0, void *p1, void *p2, void *userdata), c
991
1176
  char *owned_buf[3];
992
1177
  int attached[3];
993
1178
  ca_sweep_state_t state;
994
- int k_op;
1179
+ ca_call_cfunc_3_r_ctx_t ctx;
995
1180
 
996
1181
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
997
1182
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
998
1183
  TypedData_Get_Struct(rcx2, CArray, &carray_data_type, cx[2]);
999
1184
 
1000
- /* sweep engine: same lifecycle as ca_call_cfunc_3; the difference is
1001
- the per-cell `func(...)` call has `userdata` as its last argument. */
1185
+ /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
1186
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
1187
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
1002
1188
  state.n_ops = 3;
1003
1189
  state.fsync = fsync;
1004
1190
  state.cx = cx;
@@ -1006,36 +1192,50 @@ ca_call_cfunc_3_r (void (*func)(void *p0, void *p1, void *p2, void *userdata), c
1006
1192
  state.stride = stride;
1007
1193
  state.owned_buf = owned_buf;
1008
1194
  state.attached = attached;
1009
- state.no_mask = 0;
1010
1195
  state.src_label = "ca_call_cfunc_3_r";
1011
1196
 
1012
1197
  ca_sweep_acquire(&state);
1013
1198
 
1014
- {
1015
- char *p[3];
1016
- ca_size_t k;
1017
- if ( state.m0 ) {
1018
- for ( k = 0; k < state.n_kernel; k++ ) {
1019
- if ( ! state.m0[k] ) {
1020
- for ( k_op = 0; k_op < 3; k_op++ ) {
1021
- p[k_op] = base[k_op] + k * stride[k_op];
1022
- }
1023
- func(p[0], p[1], p[2], userdata);
1199
+ ctx.st = &state;
1200
+ ctx.func = func;
1201
+ ctx.userdata = userdata;
1202
+ ca_sweep_run(&state, ca_call_cfunc_3_r_walk, (VALUE) &ctx);
1203
+
1204
+ return rcx0;
1205
+ }
1206
+
1207
+ typedef struct {
1208
+ ca_sweep_state_t *st;
1209
+ void (*func)(void *p0, void *p1, void *p2, void *p3, void *userdata);
1210
+ void *userdata;
1211
+ } ca_call_cfunc_4_r_ctx_t;
1212
+
1213
+ static VALUE
1214
+ ca_call_cfunc_4_r_walk (VALUE arg)
1215
+ {
1216
+ ca_call_cfunc_4_r_ctx_t *c = (ca_call_cfunc_4_r_ctx_t *) arg;
1217
+ ca_sweep_state_t *st = c->st;
1218
+ char *p[4];
1219
+ ca_size_t k;
1220
+ int k_op;
1221
+ if ( st->m0 ) {
1222
+ for ( k = 0; k < st->n_kernel; k++ ) {
1223
+ if ( ! st->m0[k] ) {
1224
+ for ( k_op = 0; k_op < 4; k_op++ ) {
1225
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1024
1226
  }
1227
+ c->func(p[0], p[1], p[2], p[3], c->userdata);
1025
1228
  }
1026
- } else {
1027
- for ( k = 0; k < state.n_kernel; k++ ) {
1028
- for ( k_op = 0; k_op < 3; k_op++ ) {
1029
- p[k_op] = base[k_op] + k * stride[k_op];
1030
- }
1031
- func(p[0], p[1], p[2], userdata);
1229
+ }
1230
+ } else {
1231
+ for ( k = 0; k < st->n_kernel; k++ ) {
1232
+ for ( k_op = 0; k_op < 4; k_op++ ) {
1233
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1032
1234
  }
1235
+ c->func(p[0], p[1], p[2], p[3], c->userdata);
1033
1236
  }
1034
1237
  }
1035
-
1036
- ca_sweep_release(&state);
1037
-
1038
- return rcx0;
1238
+ return Qnil;
1039
1239
  }
1040
1240
 
1041
1241
  VALUE
@@ -1049,15 +1249,16 @@ ca_call_cfunc_4_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *us
1049
1249
  char *owned_buf[4];
1050
1250
  int attached[4];
1051
1251
  ca_sweep_state_t state;
1052
- int k_op;
1252
+ ca_call_cfunc_4_r_ctx_t ctx;
1053
1253
 
1054
1254
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1055
1255
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
1056
1256
  TypedData_Get_Struct(rcx2, CArray, &carray_data_type, cx[2]);
1057
1257
  TypedData_Get_Struct(rcx3, CArray, &carray_data_type, cx[3]);
1058
1258
 
1059
- /* sweep engine: same lifecycle as ca_call_cfunc_4; the difference is
1060
- the per-cell `func(...)` call has `userdata` as its last argument. */
1259
+ /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
1260
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
1261
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
1061
1262
  state.n_ops = 4;
1062
1263
  state.fsync = fsync;
1063
1264
  state.cx = cx;
@@ -1065,36 +1266,50 @@ ca_call_cfunc_4_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *us
1065
1266
  state.stride = stride;
1066
1267
  state.owned_buf = owned_buf;
1067
1268
  state.attached = attached;
1068
- state.no_mask = 0;
1069
1269
  state.src_label = "ca_call_cfunc_4_r";
1070
1270
 
1071
1271
  ca_sweep_acquire(&state);
1072
1272
 
1073
- {
1074
- char *p[4];
1075
- ca_size_t k;
1076
- if ( state.m0 ) {
1077
- for ( k = 0; k < state.n_kernel; k++ ) {
1078
- if ( ! state.m0[k] ) {
1079
- for ( k_op = 0; k_op < 4; k_op++ ) {
1080
- p[k_op] = base[k_op] + k * stride[k_op];
1081
- }
1082
- func(p[0], p[1], p[2], p[3], userdata);
1273
+ ctx.st = &state;
1274
+ ctx.func = func;
1275
+ ctx.userdata = userdata;
1276
+ ca_sweep_run(&state, ca_call_cfunc_4_r_walk, (VALUE) &ctx);
1277
+
1278
+ return rcx0;
1279
+ }
1280
+
1281
+ typedef struct {
1282
+ ca_sweep_state_t *st;
1283
+ void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4, void *userdata);
1284
+ void *userdata;
1285
+ } ca_call_cfunc_5_r_ctx_t;
1286
+
1287
+ static VALUE
1288
+ ca_call_cfunc_5_r_walk (VALUE arg)
1289
+ {
1290
+ ca_call_cfunc_5_r_ctx_t *c = (ca_call_cfunc_5_r_ctx_t *) arg;
1291
+ ca_sweep_state_t *st = c->st;
1292
+ char *p[5];
1293
+ ca_size_t k;
1294
+ int k_op;
1295
+ if ( st->m0 ) {
1296
+ for ( k = 0; k < st->n_kernel; k++ ) {
1297
+ if ( ! st->m0[k] ) {
1298
+ for ( k_op = 0; k_op < 5; k_op++ ) {
1299
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1083
1300
  }
1301
+ c->func(p[0], p[1], p[2], p[3], p[4], c->userdata);
1084
1302
  }
1085
- } else {
1086
- for ( k = 0; k < state.n_kernel; k++ ) {
1087
- for ( k_op = 0; k_op < 4; k_op++ ) {
1088
- p[k_op] = base[k_op] + k * stride[k_op];
1089
- }
1090
- func(p[0], p[1], p[2], p[3], userdata);
1303
+ }
1304
+ } else {
1305
+ for ( k = 0; k < st->n_kernel; k++ ) {
1306
+ for ( k_op = 0; k_op < 5; k_op++ ) {
1307
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1091
1308
  }
1309
+ c->func(p[0], p[1], p[2], p[3], p[4], c->userdata);
1092
1310
  }
1093
1311
  }
1094
-
1095
- ca_sweep_release(&state);
1096
-
1097
- return rcx0;
1312
+ return Qnil;
1098
1313
  }
1099
1314
 
1100
1315
  VALUE
@@ -1108,7 +1323,7 @@ ca_call_cfunc_5_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1108
1323
  char *owned_buf[5];
1109
1324
  int attached[5];
1110
1325
  ca_sweep_state_t state;
1111
- int k_op;
1326
+ ca_call_cfunc_5_r_ctx_t ctx;
1112
1327
 
1113
1328
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1114
1329
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1116,8 +1331,9 @@ ca_call_cfunc_5_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1116
1331
  TypedData_Get_Struct(rcx3, CArray, &carray_data_type, cx[3]);
1117
1332
  TypedData_Get_Struct(rcx4, CArray, &carray_data_type, cx[4]);
1118
1333
 
1119
- /* sweep engine: same lifecycle as ca_call_cfunc_5; the difference is
1120
- the per-cell `func(...)` call has `userdata` as its last argument. */
1334
+ /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
1335
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
1336
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
1121
1337
  state.n_ops = 5;
1122
1338
  state.fsync = fsync;
1123
1339
  state.cx = cx;
@@ -1125,36 +1341,50 @@ ca_call_cfunc_5_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1125
1341
  state.stride = stride;
1126
1342
  state.owned_buf = owned_buf;
1127
1343
  state.attached = attached;
1128
- state.no_mask = 0;
1129
1344
  state.src_label = "ca_call_cfunc_5_r";
1130
1345
 
1131
1346
  ca_sweep_acquire(&state);
1132
1347
 
1133
- {
1134
- char *p[5];
1135
- ca_size_t k;
1136
- if ( state.m0 ) {
1137
- for ( k = 0; k < state.n_kernel; k++ ) {
1138
- if ( ! state.m0[k] ) {
1139
- for ( k_op = 0; k_op < 5; k_op++ ) {
1140
- p[k_op] = base[k_op] + k * stride[k_op];
1141
- }
1142
- func(p[0], p[1], p[2], p[3], p[4], userdata);
1348
+ ctx.st = &state;
1349
+ ctx.func = func;
1350
+ ctx.userdata = userdata;
1351
+ ca_sweep_run(&state, ca_call_cfunc_5_r_walk, (VALUE) &ctx);
1352
+
1353
+ return rcx0;
1354
+ }
1355
+
1356
+ typedef struct {
1357
+ ca_sweep_state_t *st;
1358
+ void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4, void *p5, void *userdata);
1359
+ void *userdata;
1360
+ } ca_call_cfunc_6_r_ctx_t;
1361
+
1362
+ static VALUE
1363
+ ca_call_cfunc_6_r_walk (VALUE arg)
1364
+ {
1365
+ ca_call_cfunc_6_r_ctx_t *c = (ca_call_cfunc_6_r_ctx_t *) arg;
1366
+ ca_sweep_state_t *st = c->st;
1367
+ char *p[6];
1368
+ ca_size_t k;
1369
+ int k_op;
1370
+ if ( st->m0 ) {
1371
+ for ( k = 0; k < st->n_kernel; k++ ) {
1372
+ if ( ! st->m0[k] ) {
1373
+ for ( k_op = 0; k_op < 6; k_op++ ) {
1374
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1143
1375
  }
1376
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5], c->userdata);
1144
1377
  }
1145
- } else {
1146
- for ( k = 0; k < state.n_kernel; k++ ) {
1147
- for ( k_op = 0; k_op < 5; k_op++ ) {
1148
- p[k_op] = base[k_op] + k * stride[k_op];
1149
- }
1150
- func(p[0], p[1], p[2], p[3], p[4], userdata);
1378
+ }
1379
+ } else {
1380
+ for ( k = 0; k < st->n_kernel; k++ ) {
1381
+ for ( k_op = 0; k_op < 6; k_op++ ) {
1382
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1151
1383
  }
1384
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5], c->userdata);
1152
1385
  }
1153
1386
  }
1154
-
1155
- ca_sweep_release(&state);
1156
-
1157
- return rcx0;
1387
+ return Qnil;
1158
1388
  }
1159
1389
 
1160
1390
  VALUE
@@ -1168,7 +1398,7 @@ ca_call_cfunc_6_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1168
1398
  char *owned_buf[6];
1169
1399
  int attached[6];
1170
1400
  ca_sweep_state_t state;
1171
- int k_op;
1401
+ ca_call_cfunc_6_r_ctx_t ctx;
1172
1402
 
1173
1403
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1174
1404
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1177,8 +1407,9 @@ ca_call_cfunc_6_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1177
1407
  TypedData_Get_Struct(rcx4, CArray, &carray_data_type, cx[4]);
1178
1408
  TypedData_Get_Struct(rcx5, CArray, &carray_data_type, cx[5]);
1179
1409
 
1180
- /* sweep engine: same lifecycle as ca_call_cfunc_6; the difference is
1181
- the per-cell `func(...)` call has `userdata` as its last argument. */
1410
+ /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
1411
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
1412
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
1182
1413
  state.n_ops = 6;
1183
1414
  state.fsync = fsync;
1184
1415
  state.cx = cx;
@@ -1186,36 +1417,50 @@ ca_call_cfunc_6_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1186
1417
  state.stride = stride;
1187
1418
  state.owned_buf = owned_buf;
1188
1419
  state.attached = attached;
1189
- state.no_mask = 0;
1190
1420
  state.src_label = "ca_call_cfunc_6_r";
1191
1421
 
1192
1422
  ca_sweep_acquire(&state);
1193
1423
 
1194
- {
1195
- char *p[6];
1196
- ca_size_t k;
1197
- if ( state.m0 ) {
1198
- for ( k = 0; k < state.n_kernel; k++ ) {
1199
- if ( ! state.m0[k] ) {
1200
- for ( k_op = 0; k_op < 6; k_op++ ) {
1201
- p[k_op] = base[k_op] + k * stride[k_op];
1202
- }
1203
- func(p[0], p[1], p[2], p[3], p[4], p[5], userdata);
1424
+ ctx.st = &state;
1425
+ ctx.func = func;
1426
+ ctx.userdata = userdata;
1427
+ ca_sweep_run(&state, ca_call_cfunc_6_r_walk, (VALUE) &ctx);
1428
+
1429
+ return rcx0;
1430
+ }
1431
+
1432
+ typedef struct {
1433
+ ca_sweep_state_t *st;
1434
+ void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6, void *userdata);
1435
+ void *userdata;
1436
+ } ca_call_cfunc_7_r_ctx_t;
1437
+
1438
+ static VALUE
1439
+ ca_call_cfunc_7_r_walk (VALUE arg)
1440
+ {
1441
+ ca_call_cfunc_7_r_ctx_t *c = (ca_call_cfunc_7_r_ctx_t *) arg;
1442
+ ca_sweep_state_t *st = c->st;
1443
+ char *p[7];
1444
+ ca_size_t k;
1445
+ int k_op;
1446
+ if ( st->m0 ) {
1447
+ for ( k = 0; k < st->n_kernel; k++ ) {
1448
+ if ( ! st->m0[k] ) {
1449
+ for ( k_op = 0; k_op < 7; k_op++ ) {
1450
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1204
1451
  }
1452
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], c->userdata);
1205
1453
  }
1206
- } else {
1207
- for ( k = 0; k < state.n_kernel; k++ ) {
1208
- for ( k_op = 0; k_op < 6; k_op++ ) {
1209
- p[k_op] = base[k_op] + k * stride[k_op];
1210
- }
1211
- func(p[0], p[1], p[2], p[3], p[4], p[5], userdata);
1454
+ }
1455
+ } else {
1456
+ for ( k = 0; k < st->n_kernel; k++ ) {
1457
+ for ( k_op = 0; k_op < 7; k_op++ ) {
1458
+ p[k_op] = st->base[k_op] + k * st->stride[k_op];
1212
1459
  }
1460
+ c->func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], c->userdata);
1213
1461
  }
1214
1462
  }
1215
-
1216
- ca_sweep_release(&state);
1217
-
1218
- return rcx0;
1463
+ return Qnil;
1219
1464
  }
1220
1465
 
1221
1466
  VALUE
@@ -1229,7 +1474,7 @@ ca_call_cfunc_7_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1229
1474
  char *owned_buf[7];
1230
1475
  int attached[7];
1231
1476
  ca_sweep_state_t state;
1232
- int k_op;
1477
+ ca_call_cfunc_7_r_ctx_t ctx;
1233
1478
 
1234
1479
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1235
1480
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1239,8 +1484,9 @@ ca_call_cfunc_7_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1239
1484
  TypedData_Get_Struct(rcx5, CArray, &carray_data_type, cx[5]);
1240
1485
  TypedData_Get_Struct(rcx6, CArray, &carray_data_type, cx[6]);
1241
1486
 
1242
- /* sweep engine: same lifecycle as ca_call_cfunc_7; the difference is
1243
- the per-cell `func(...)` call has `userdata` as its last argument. */
1487
+ /* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
1488
+ operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
1489
+ Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
1244
1490
  state.n_ops = 7;
1245
1491
  state.fsync = fsync;
1246
1492
  state.cx = cx;
@@ -1248,34 +1494,14 @@ ca_call_cfunc_7_r (void (*func)(void *p0, void *p1, void *p2, void *p3, void *p4
1248
1494
  state.stride = stride;
1249
1495
  state.owned_buf = owned_buf;
1250
1496
  state.attached = attached;
1251
- state.no_mask = 0;
1252
1497
  state.src_label = "ca_call_cfunc_7_r";
1253
1498
 
1254
1499
  ca_sweep_acquire(&state);
1255
1500
 
1256
- {
1257
- char *p[7];
1258
- ca_size_t k;
1259
- if ( state.m0 ) {
1260
- for ( k = 0; k < state.n_kernel; k++ ) {
1261
- if ( ! state.m0[k] ) {
1262
- for ( k_op = 0; k_op < 7; k_op++ ) {
1263
- p[k_op] = base[k_op] + k * stride[k_op];
1264
- }
1265
- func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], userdata);
1266
- }
1267
- }
1268
- } else {
1269
- for ( k = 0; k < state.n_kernel; k++ ) {
1270
- for ( k_op = 0; k_op < 7; k_op++ ) {
1271
- p[k_op] = base[k_op] + k * stride[k_op];
1272
- }
1273
- func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], userdata);
1274
- }
1275
- }
1276
- }
1277
-
1278
- ca_sweep_release(&state);
1501
+ ctx.st = &state;
1502
+ ctx.func = func;
1503
+ ctx.userdata = userdata;
1504
+ ca_sweep_run(&state, ca_call_cfunc_7_r_walk, (VALUE) &ctx);
1279
1505
 
1280
1506
  return rcx0;
1281
1507
  }
@@ -1676,6 +1902,7 @@ ca_call_cslab_1 (ca_cslab_t func, const char *fsync,
1676
1902
  char *owned_buf[1];
1677
1903
  int attached[1];
1678
1904
  ca_sweep_state_t state;
1905
+ ca_cslab_ctx_t ctx;
1679
1906
 
1680
1907
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1681
1908
 
@@ -1693,21 +1920,15 @@ ca_call_cslab_1 (ca_cslab_t func, const char *fsync,
1693
1920
  state.stride = stride;
1694
1921
  state.owned_buf = owned_buf;
1695
1922
  state.attached = attached;
1696
- state.no_mask = 0;
1697
1923
  state.src_label = "ca_call_cslab_1";
1698
1924
 
1699
1925
  ca_sweep_acquire_chunked(&state);
1700
1926
 
1701
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
1702
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
1703
- at the arena scratch the chunk was just gathered into, which is
1704
- packed, so stride[] is the element size and the author's inner loop
1705
- sees contiguous data. */
1706
- while ( ca_sweep_next_chunk(&state) ) {
1707
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state));
1708
- }
1709
-
1710
- ca_sweep_release_chunked(&state);
1927
+ ctx.st = &state;
1928
+ ctx.func = func;
1929
+ ctx.func_r = NULL;
1930
+ ctx.userdata = NULL;
1931
+ ca_sweep_run_chunked(&state, ca_cslab_walk, (VALUE) &ctx);
1711
1932
 
1712
1933
  return rcx0;
1713
1934
  }
@@ -1723,6 +1944,7 @@ ca_call_cslab_2 (ca_cslab_t func, const char *fsync,
1723
1944
  char *owned_buf[2];
1724
1945
  int attached[2];
1725
1946
  ca_sweep_state_t state;
1947
+ ca_cslab_ctx_t ctx;
1726
1948
 
1727
1949
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1728
1950
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1741,21 +1963,15 @@ ca_call_cslab_2 (ca_cslab_t func, const char *fsync,
1741
1963
  state.stride = stride;
1742
1964
  state.owned_buf = owned_buf;
1743
1965
  state.attached = attached;
1744
- state.no_mask = 0;
1745
1966
  state.src_label = "ca_call_cslab_2";
1746
1967
 
1747
1968
  ca_sweep_acquire_chunked(&state);
1748
1969
 
1749
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
1750
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
1751
- at the arena scratch the chunk was just gathered into, which is
1752
- packed, so stride[] is the element size and the author's inner loop
1753
- sees contiguous data. */
1754
- while ( ca_sweep_next_chunk(&state) ) {
1755
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state));
1756
- }
1757
-
1758
- ca_sweep_release_chunked(&state);
1970
+ ctx.st = &state;
1971
+ ctx.func = func;
1972
+ ctx.func_r = NULL;
1973
+ ctx.userdata = NULL;
1974
+ ca_sweep_run_chunked(&state, ca_cslab_walk, (VALUE) &ctx);
1759
1975
 
1760
1976
  return rcx0;
1761
1977
  }
@@ -1771,6 +1987,7 @@ ca_call_cslab_3 (ca_cslab_t func, const char *fsync,
1771
1987
  char *owned_buf[3];
1772
1988
  int attached[3];
1773
1989
  ca_sweep_state_t state;
1990
+ ca_cslab_ctx_t ctx;
1774
1991
 
1775
1992
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1776
1993
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1790,21 +2007,15 @@ ca_call_cslab_3 (ca_cslab_t func, const char *fsync,
1790
2007
  state.stride = stride;
1791
2008
  state.owned_buf = owned_buf;
1792
2009
  state.attached = attached;
1793
- state.no_mask = 0;
1794
2010
  state.src_label = "ca_call_cslab_3";
1795
2011
 
1796
2012
  ca_sweep_acquire_chunked(&state);
1797
2013
 
1798
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
1799
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
1800
- at the arena scratch the chunk was just gathered into, which is
1801
- packed, so stride[] is the element size and the author's inner loop
1802
- sees contiguous data. */
1803
- while ( ca_sweep_next_chunk(&state) ) {
1804
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state));
1805
- }
1806
-
1807
- ca_sweep_release_chunked(&state);
2014
+ ctx.st = &state;
2015
+ ctx.func = func;
2016
+ ctx.func_r = NULL;
2017
+ ctx.userdata = NULL;
2018
+ ca_sweep_run_chunked(&state, ca_cslab_walk, (VALUE) &ctx);
1808
2019
 
1809
2020
  return rcx0;
1810
2021
  }
@@ -1820,6 +2031,7 @@ ca_call_cslab_4 (ca_cslab_t func, const char *fsync,
1820
2031
  char *owned_buf[4];
1821
2032
  int attached[4];
1822
2033
  ca_sweep_state_t state;
2034
+ ca_cslab_ctx_t ctx;
1823
2035
 
1824
2036
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1825
2037
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1840,21 +2052,15 @@ ca_call_cslab_4 (ca_cslab_t func, const char *fsync,
1840
2052
  state.stride = stride;
1841
2053
  state.owned_buf = owned_buf;
1842
2054
  state.attached = attached;
1843
- state.no_mask = 0;
1844
2055
  state.src_label = "ca_call_cslab_4";
1845
2056
 
1846
2057
  ca_sweep_acquire_chunked(&state);
1847
2058
 
1848
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
1849
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
1850
- at the arena scratch the chunk was just gathered into, which is
1851
- packed, so stride[] is the element size and the author's inner loop
1852
- sees contiguous data. */
1853
- while ( ca_sweep_next_chunk(&state) ) {
1854
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state));
1855
- }
1856
-
1857
- ca_sweep_release_chunked(&state);
2059
+ ctx.st = &state;
2060
+ ctx.func = func;
2061
+ ctx.func_r = NULL;
2062
+ ctx.userdata = NULL;
2063
+ ca_sweep_run_chunked(&state, ca_cslab_walk, (VALUE) &ctx);
1858
2064
 
1859
2065
  return rcx0;
1860
2066
  }
@@ -1870,6 +2076,7 @@ ca_call_cslab_5 (ca_cslab_t func, const char *fsync,
1870
2076
  char *owned_buf[5];
1871
2077
  int attached[5];
1872
2078
  ca_sweep_state_t state;
2079
+ ca_cslab_ctx_t ctx;
1873
2080
 
1874
2081
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1875
2082
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1891,21 +2098,15 @@ ca_call_cslab_5 (ca_cslab_t func, const char *fsync,
1891
2098
  state.stride = stride;
1892
2099
  state.owned_buf = owned_buf;
1893
2100
  state.attached = attached;
1894
- state.no_mask = 0;
1895
2101
  state.src_label = "ca_call_cslab_5";
1896
2102
 
1897
2103
  ca_sweep_acquire_chunked(&state);
1898
2104
 
1899
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
1900
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
1901
- at the arena scratch the chunk was just gathered into, which is
1902
- packed, so stride[] is the element size and the author's inner loop
1903
- sees contiguous data. */
1904
- while ( ca_sweep_next_chunk(&state) ) {
1905
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state));
1906
- }
1907
-
1908
- ca_sweep_release_chunked(&state);
2105
+ ctx.st = &state;
2106
+ ctx.func = func;
2107
+ ctx.func_r = NULL;
2108
+ ctx.userdata = NULL;
2109
+ ca_sweep_run_chunked(&state, ca_cslab_walk, (VALUE) &ctx);
1909
2110
 
1910
2111
  return rcx0;
1911
2112
  }
@@ -1921,6 +2122,7 @@ ca_call_cslab_6 (ca_cslab_t func, const char *fsync,
1921
2122
  char *owned_buf[6];
1922
2123
  int attached[6];
1923
2124
  ca_sweep_state_t state;
2125
+ ca_cslab_ctx_t ctx;
1924
2126
 
1925
2127
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1926
2128
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1943,21 +2145,15 @@ ca_call_cslab_6 (ca_cslab_t func, const char *fsync,
1943
2145
  state.stride = stride;
1944
2146
  state.owned_buf = owned_buf;
1945
2147
  state.attached = attached;
1946
- state.no_mask = 0;
1947
2148
  state.src_label = "ca_call_cslab_6";
1948
2149
 
1949
2150
  ca_sweep_acquire_chunked(&state);
1950
2151
 
1951
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
1952
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
1953
- at the arena scratch the chunk was just gathered into, which is
1954
- packed, so stride[] is the element size and the author's inner loop
1955
- sees contiguous data. */
1956
- while ( ca_sweep_next_chunk(&state) ) {
1957
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state));
1958
- }
1959
-
1960
- ca_sweep_release_chunked(&state);
2152
+ ctx.st = &state;
2153
+ ctx.func = func;
2154
+ ctx.func_r = NULL;
2155
+ ctx.userdata = NULL;
2156
+ ca_sweep_run_chunked(&state, ca_cslab_walk, (VALUE) &ctx);
1961
2157
 
1962
2158
  return rcx0;
1963
2159
  }
@@ -1973,6 +2169,7 @@ ca_call_cslab_7 (ca_cslab_t func, const char *fsync,
1973
2169
  char *owned_buf[7];
1974
2170
  int attached[7];
1975
2171
  ca_sweep_state_t state;
2172
+ ca_cslab_ctx_t ctx;
1976
2173
 
1977
2174
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
1978
2175
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -1996,21 +2193,15 @@ ca_call_cslab_7 (ca_cslab_t func, const char *fsync,
1996
2193
  state.stride = stride;
1997
2194
  state.owned_buf = owned_buf;
1998
2195
  state.attached = attached;
1999
- state.no_mask = 0;
2000
2196
  state.src_label = "ca_call_cslab_7";
2001
2197
 
2002
2198
  ca_sweep_acquire_chunked(&state);
2003
2199
 
2004
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2005
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2006
- at the arena scratch the chunk was just gathered into, which is
2007
- packed, so stride[] is the element size and the author's inner loop
2008
- sees contiguous data. */
2009
- while ( ca_sweep_next_chunk(&state) ) {
2010
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state));
2011
- }
2012
-
2013
- ca_sweep_release_chunked(&state);
2200
+ ctx.st = &state;
2201
+ ctx.func = func;
2202
+ ctx.func_r = NULL;
2203
+ ctx.userdata = NULL;
2204
+ ca_sweep_run_chunked(&state, ca_cslab_walk, (VALUE) &ctx);
2014
2205
 
2015
2206
  return rcx0;
2016
2207
  }
@@ -2027,6 +2218,7 @@ ca_call_cslab_1_r (ca_cslab_r_t func, const char *fsync,
2027
2218
  char *owned_buf[1];
2028
2219
  int attached[1];
2029
2220
  ca_sweep_state_t state;
2221
+ ca_cslab_ctx_t ctx;
2030
2222
 
2031
2223
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
2032
2224
 
@@ -2044,21 +2236,15 @@ ca_call_cslab_1_r (ca_cslab_r_t func, const char *fsync,
2044
2236
  state.stride = stride;
2045
2237
  state.owned_buf = owned_buf;
2046
2238
  state.attached = attached;
2047
- state.no_mask = 0;
2048
2239
  state.src_label = "ca_call_cslab_1_r";
2049
2240
 
2050
2241
  ca_sweep_acquire_chunked(&state);
2051
2242
 
2052
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2053
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2054
- at the arena scratch the chunk was just gathered into, which is
2055
- packed, so stride[] is the element size and the author's inner loop
2056
- sees contiguous data. */
2057
- while ( ca_sweep_next_chunk(&state) ) {
2058
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata);
2059
- }
2060
-
2061
- ca_sweep_release_chunked(&state);
2243
+ ctx.st = &state;
2244
+ ctx.func = NULL;
2245
+ ctx.func_r = func;
2246
+ ctx.userdata = userdata;
2247
+ ca_sweep_run_chunked(&state, ca_cslab_r_walk, (VALUE) &ctx);
2062
2248
 
2063
2249
  return rcx0;
2064
2250
  }
@@ -2075,6 +2261,7 @@ ca_call_cslab_2_r (ca_cslab_r_t func, const char *fsync,
2075
2261
  char *owned_buf[2];
2076
2262
  int attached[2];
2077
2263
  ca_sweep_state_t state;
2264
+ ca_cslab_ctx_t ctx;
2078
2265
 
2079
2266
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
2080
2267
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -2093,21 +2280,15 @@ ca_call_cslab_2_r (ca_cslab_r_t func, const char *fsync,
2093
2280
  state.stride = stride;
2094
2281
  state.owned_buf = owned_buf;
2095
2282
  state.attached = attached;
2096
- state.no_mask = 0;
2097
2283
  state.src_label = "ca_call_cslab_2_r";
2098
2284
 
2099
2285
  ca_sweep_acquire_chunked(&state);
2100
2286
 
2101
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2102
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2103
- at the arena scratch the chunk was just gathered into, which is
2104
- packed, so stride[] is the element size and the author's inner loop
2105
- sees contiguous data. */
2106
- while ( ca_sweep_next_chunk(&state) ) {
2107
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata);
2108
- }
2109
-
2110
- ca_sweep_release_chunked(&state);
2287
+ ctx.st = &state;
2288
+ ctx.func = NULL;
2289
+ ctx.func_r = func;
2290
+ ctx.userdata = userdata;
2291
+ ca_sweep_run_chunked(&state, ca_cslab_r_walk, (VALUE) &ctx);
2111
2292
 
2112
2293
  return rcx0;
2113
2294
  }
@@ -2124,6 +2305,7 @@ ca_call_cslab_3_r (ca_cslab_r_t func, const char *fsync,
2124
2305
  char *owned_buf[3];
2125
2306
  int attached[3];
2126
2307
  ca_sweep_state_t state;
2308
+ ca_cslab_ctx_t ctx;
2127
2309
 
2128
2310
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
2129
2311
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -2143,21 +2325,15 @@ ca_call_cslab_3_r (ca_cslab_r_t func, const char *fsync,
2143
2325
  state.stride = stride;
2144
2326
  state.owned_buf = owned_buf;
2145
2327
  state.attached = attached;
2146
- state.no_mask = 0;
2147
2328
  state.src_label = "ca_call_cslab_3_r";
2148
2329
 
2149
2330
  ca_sweep_acquire_chunked(&state);
2150
2331
 
2151
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2152
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2153
- at the arena scratch the chunk was just gathered into, which is
2154
- packed, so stride[] is the element size and the author's inner loop
2155
- sees contiguous data. */
2156
- while ( ca_sweep_next_chunk(&state) ) {
2157
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata);
2158
- }
2159
-
2160
- ca_sweep_release_chunked(&state);
2332
+ ctx.st = &state;
2333
+ ctx.func = NULL;
2334
+ ctx.func_r = func;
2335
+ ctx.userdata = userdata;
2336
+ ca_sweep_run_chunked(&state, ca_cslab_r_walk, (VALUE) &ctx);
2161
2337
 
2162
2338
  return rcx0;
2163
2339
  }
@@ -2174,6 +2350,7 @@ ca_call_cslab_4_r (ca_cslab_r_t func, const char *fsync,
2174
2350
  char *owned_buf[4];
2175
2351
  int attached[4];
2176
2352
  ca_sweep_state_t state;
2353
+ ca_cslab_ctx_t ctx;
2177
2354
 
2178
2355
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
2179
2356
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -2194,21 +2371,15 @@ ca_call_cslab_4_r (ca_cslab_r_t func, const char *fsync,
2194
2371
  state.stride = stride;
2195
2372
  state.owned_buf = owned_buf;
2196
2373
  state.attached = attached;
2197
- state.no_mask = 0;
2198
2374
  state.src_label = "ca_call_cslab_4_r";
2199
2375
 
2200
2376
  ca_sweep_acquire_chunked(&state);
2201
2377
 
2202
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2203
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2204
- at the arena scratch the chunk was just gathered into, which is
2205
- packed, so stride[] is the element size and the author's inner loop
2206
- sees contiguous data. */
2207
- while ( ca_sweep_next_chunk(&state) ) {
2208
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata);
2209
- }
2210
-
2211
- ca_sweep_release_chunked(&state);
2378
+ ctx.st = &state;
2379
+ ctx.func = NULL;
2380
+ ctx.func_r = func;
2381
+ ctx.userdata = userdata;
2382
+ ca_sweep_run_chunked(&state, ca_cslab_r_walk, (VALUE) &ctx);
2212
2383
 
2213
2384
  return rcx0;
2214
2385
  }
@@ -2225,6 +2396,7 @@ ca_call_cslab_5_r (ca_cslab_r_t func, const char *fsync,
2225
2396
  char *owned_buf[5];
2226
2397
  int attached[5];
2227
2398
  ca_sweep_state_t state;
2399
+ ca_cslab_ctx_t ctx;
2228
2400
 
2229
2401
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
2230
2402
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -2246,21 +2418,15 @@ ca_call_cslab_5_r (ca_cslab_r_t func, const char *fsync,
2246
2418
  state.stride = stride;
2247
2419
  state.owned_buf = owned_buf;
2248
2420
  state.attached = attached;
2249
- state.no_mask = 0;
2250
2421
  state.src_label = "ca_call_cslab_5_r";
2251
2422
 
2252
2423
  ca_sweep_acquire_chunked(&state);
2253
2424
 
2254
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2255
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2256
- at the arena scratch the chunk was just gathered into, which is
2257
- packed, so stride[] is the element size and the author's inner loop
2258
- sees contiguous data. */
2259
- while ( ca_sweep_next_chunk(&state) ) {
2260
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata);
2261
- }
2262
-
2263
- ca_sweep_release_chunked(&state);
2425
+ ctx.st = &state;
2426
+ ctx.func = NULL;
2427
+ ctx.func_r = func;
2428
+ ctx.userdata = userdata;
2429
+ ca_sweep_run_chunked(&state, ca_cslab_r_walk, (VALUE) &ctx);
2264
2430
 
2265
2431
  return rcx0;
2266
2432
  }
@@ -2277,6 +2443,7 @@ ca_call_cslab_6_r (ca_cslab_r_t func, const char *fsync,
2277
2443
  char *owned_buf[6];
2278
2444
  int attached[6];
2279
2445
  ca_sweep_state_t state;
2446
+ ca_cslab_ctx_t ctx;
2280
2447
 
2281
2448
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
2282
2449
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -2299,21 +2466,15 @@ ca_call_cslab_6_r (ca_cslab_r_t func, const char *fsync,
2299
2466
  state.stride = stride;
2300
2467
  state.owned_buf = owned_buf;
2301
2468
  state.attached = attached;
2302
- state.no_mask = 0;
2303
2469
  state.src_label = "ca_call_cslab_6_r";
2304
2470
 
2305
2471
  ca_sweep_acquire_chunked(&state);
2306
2472
 
2307
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2308
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2309
- at the arena scratch the chunk was just gathered into, which is
2310
- packed, so stride[] is the element size and the author's inner loop
2311
- sees contiguous data. */
2312
- while ( ca_sweep_next_chunk(&state) ) {
2313
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata);
2314
- }
2315
-
2316
- ca_sweep_release_chunked(&state);
2473
+ ctx.st = &state;
2474
+ ctx.func = NULL;
2475
+ ctx.func_r = func;
2476
+ ctx.userdata = userdata;
2477
+ ca_sweep_run_chunked(&state, ca_cslab_r_walk, (VALUE) &ctx);
2317
2478
 
2318
2479
  return rcx0;
2319
2480
  }
@@ -2330,6 +2491,7 @@ ca_call_cslab_7_r (ca_cslab_r_t func, const char *fsync,
2330
2491
  char *owned_buf[7];
2331
2492
  int attached[7];
2332
2493
  ca_sweep_state_t state;
2494
+ ca_cslab_ctx_t ctx;
2333
2495
 
2334
2496
  TypedData_Get_Struct(rcx0, CArray, &carray_data_type, cx[0]);
2335
2497
  TypedData_Get_Struct(rcx1, CArray, &carray_data_type, cx[1]);
@@ -2353,21 +2515,15 @@ ca_call_cslab_7_r (ca_cslab_r_t func, const char *fsync,
2353
2515
  state.stride = stride;
2354
2516
  state.owned_buf = owned_buf;
2355
2517
  state.attached = attached;
2356
- state.no_mask = 0;
2357
2518
  state.src_label = "ca_call_cslab_7_r";
2358
2519
 
2359
2520
  ca_sweep_acquire_chunked(&state);
2360
2521
 
2361
- /* outer loop: hand the author one chunk at a time. base[] is rewritten
2362
- per chunk by ca_sweep_next_chunk -- for a non-alias INPUT it points
2363
- at the arena scratch the chunk was just gathered into, which is
2364
- packed, so stride[] is the element size and the author's inner loop
2365
- sees contiguous data. */
2366
- while ( ca_sweep_next_chunk(&state) ) {
2367
- func(base, stride, state.chunk_n, ca_sweep_chunk_mask(&state), userdata);
2368
- }
2369
-
2370
- ca_sweep_release_chunked(&state);
2522
+ ctx.st = &state;
2523
+ ctx.func = NULL;
2524
+ ctx.func_r = func;
2525
+ ctx.userdata = userdata;
2526
+ ca_sweep_run_chunked(&state, ca_cslab_r_walk, (VALUE) &ctx);
2371
2527
 
2372
2528
  return rcx0;
2373
2529
  }