carray 3.0.2 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +568 -0
  3. data/README.md +6 -6
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_descriptor.h +27 -24
  6. data/ext/ca_axis_dispatch.c +220 -0
  7. data/ext/ca_axis_group.c +201 -123
  8. data/ext/ca_binop_dispatch.c +46 -52
  9. data/ext/ca_binop_dispatch.h +1 -1
  10. data/ext/ca_categorical_iterator.c +249 -183
  11. data/ext/ca_compare.c +7 -12
  12. data/ext/ca_for_buffer.h +21 -68
  13. data/ext/ca_group_iter.c +38 -23
  14. data/ext/ca_kernel_iterator.c +1765 -2076
  15. data/ext/ca_kernel_iterator.h +584 -566
  16. data/ext/ca_monop_dispatch.c +86 -63
  17. data/ext/ca_monop_dispatch.h +5 -0
  18. data/ext/ca_obj_array.c +223 -56
  19. data/ext/ca_obj_bincmp.c +172 -138
  20. data/ext/ca_obj_binop.c +116 -230
  21. data/ext/ca_obj_bitarray.c +40 -26
  22. data/ext/ca_obj_bitfield.c +100 -68
  23. data/ext/ca_obj_block.c +19 -9
  24. data/ext/ca_obj_byte_swap.c +45 -46
  25. data/ext/ca_obj_const_string.c +269 -44
  26. data/ext/ca_obj_face.c +612 -89
  27. data/ext/ca_obj_face.h +111 -47
  28. data/ext/ca_obj_fake.c +36 -79
  29. data/ext/ca_obj_farray.c +7 -3
  30. data/ext/ca_obj_field.c +33 -8
  31. data/ext/ca_obj_fixlen_string.c +23 -24
  32. data/ext/ca_obj_grid.c +541 -210
  33. data/ext/ca_obj_meld.c +331 -111
  34. data/ext/ca_obj_moncmp.c +80 -65
  35. data/ext/ca_obj_monop.c +177 -149
  36. data/ext/ca_obj_object.c +664 -248
  37. data/ext/ca_obj_record.c +63 -23
  38. data/ext/ca_obj_reduce.c +18 -16
  39. data/ext/ca_obj_refer.c +140 -58
  40. data/ext/ca_obj_remap.c +85 -24
  41. data/ext/ca_obj_repeat.c +24 -9
  42. data/ext/ca_obj_roll.c +121 -16
  43. data/ext/ca_obj_select.c +61 -58
  44. data/ext/ca_obj_select_axis.c +73 -107
  45. data/ext/ca_obj_shift.c +32 -102
  46. data/ext/ca_obj_stack.c +372 -122
  47. data/ext/ca_obj_stride.c +348 -140
  48. data/ext/ca_obj_string.c +88 -22
  49. data/ext/ca_obj_tile.c +38 -21
  50. data/ext/ca_obj_time.c +45 -31
  51. data/ext/ca_obj_timedelta.c +43 -29
  52. data/ext/ca_obj_transpose.c +17 -6
  53. data/ext/ca_obj_triop.c +125 -141
  54. data/ext/ca_obj_window.c +330 -44
  55. data/ext/ca_op_ipower.c +24 -11
  56. data/ext/ca_op_powi.h +57 -30
  57. data/ext/ca_pow5_table.h +656 -0
  58. data/ext/ca_sort_kernels.h +70 -0
  59. data/ext/ca_sweep_engine.c +104 -81
  60. data/ext/ca_sweep_engine.h +7 -20
  61. data/ext/ca_triop_dispatch.c +4 -1
  62. data/ext/ca_triop_dispatch.h +5 -2
  63. data/ext/caframe_csv_reader.c +542 -0
  64. data/ext/carray.h +241 -92
  65. data/ext/carray_access.c +608 -276
  66. data/ext/carray_address_basis.c +494 -97
  67. data/ext/carray_attribute.c +129 -4
  68. data/ext/carray_bincount.c +39 -7
  69. data/ext/carray_broadcast.c +56 -19
  70. data/ext/carray_build_flags.h +1 -1
  71. data/ext/carray_call_cfunc.c +108 -28
  72. data/ext/carray_cast.c +1576 -223
  73. data/ext/carray_cast_func.rb +77 -24
  74. data/ext/carray_class.c +4 -3
  75. data/ext/carray_conversion.c +208 -75
  76. data/ext/carray_copy.c +82 -24
  77. data/ext/carray_core.c +646 -162
  78. data/ext/carray_count.c +171 -88
  79. data/ext/carray_element.c +94 -60
  80. data/ext/carray_factorize.c +670 -324
  81. data/ext/carray_generate.c +260 -83
  82. data/ext/carray_histogram.c +209 -106
  83. data/ext/carray_hold.c +14 -16
  84. data/ext/carray_index_classifier.c +422 -243
  85. data/ext/carray_internal.h +692 -3
  86. data/ext/carray_kernels_bincmp.c +7 -0
  87. data/ext/carray_kernels_binop.c +487 -120
  88. data/ext/carray_kernels_init.c +653 -50
  89. data/ext/carray_kernels_moncmp.c +15 -8
  90. data/ext/carray_kernels_monop.c +99 -43
  91. data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
  92. data/ext/carray_kernels_reduce_boolean.c +112 -36
  93. data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
  94. data/ext/carray_kernels_reduce_extreme.c +3032 -2892
  95. data/ext/carray_kernels_reduce_variance.c +439 -500
  96. data/ext/carray_kernels_scan.c +1097 -488
  97. data/ext/carray_kernels_search.c +3787 -2176
  98. data/ext/carray_kernels_sort.c +1200 -920
  99. data/ext/carray_kernels_triop.c +479 -7
  100. data/ext/carray_key_windows.c +216 -0
  101. data/ext/carray_lazy.c +967 -153
  102. data/ext/carray_loop.c +81 -65
  103. data/ext/carray_mask.c +910 -324
  104. data/ext/carray_math_kernel.h +1 -0
  105. data/ext/carray_median_percentile.c +299 -100
  106. data/ext/carray_memory_view.c +872 -758
  107. data/ext/carray_operator.c +1171 -364
  108. data/ext/carray_order.c +505 -133
  109. data/ext/carray_partition.c +112 -65
  110. data/ext/carray_random.c +327 -239
  111. data/ext/carray_round.c +273 -0
  112. data/ext/carray_scatter.c +346 -78
  113. data/ext/carray_segment.c +257 -0
  114. data/ext/carray_slab.c +249 -86
  115. data/ext/carray_sort.c +224 -227
  116. data/ext/carray_sort_kernel.c +8 -1
  117. data/ext/carray_struct.c +118 -39
  118. data/ext/carray_test.c +193 -69
  119. data/ext/carray_time_text.c +1182 -0
  120. data/ext/carray_undef.c +4 -0
  121. data/ext/carray_utils.c +579 -113
  122. data/ext/extconf.rb +27 -2
  123. data/ext/mk_call_cfunc.rb +19 -4
  124. data/ext/mk_pow5_table.rb +35 -0
  125. data/ext/mkkernel.rb +1202 -1014
  126. data/ext/ruby_carray.c +17 -5
  127. data/ext/version.h +4 -4
  128. data/ext/version.rb +4 -2
  129. data/lib/carray/attribute.rb +160 -17
  130. data/lib/carray/autoload_carray.rb +23 -27
  131. data/lib/carray/autoload_method_extension.rb +20 -5
  132. data/lib/carray/axis_group.rb +360 -63
  133. data/lib/carray/basics.rb +162 -28
  134. data/lib/carray/bincount_nd.rb +18 -2
  135. data/lib/carray/block_iterator.rb +231 -58
  136. data/lib/carray/boolean_reduce.rb +34 -42
  137. data/lib/carray/categorical.rb +242 -52
  138. data/lib/carray/categorical_iterator.rb +437 -827
  139. data/lib/carray/complex.rb +41 -34
  140. data/lib/carray/conditional.rb +150 -14
  141. data/lib/carray/const_string.rb +59 -4
  142. data/lib/carray/construct.rb +15 -11
  143. data/lib/carray/data_type_extension.rb +1 -0
  144. data/lib/carray/distance_limit.rb +77 -0
  145. data/lib/carray/fixlen_string.rb +7 -1
  146. data/lib/carray/frame/column_verbs.rb +70 -0
  147. data/lib/carray/frame/concat.rb +157 -6
  148. data/lib/carray/frame/convert.rb +82 -7
  149. data/lib/carray/frame/csv_parser.rb +688 -87
  150. data/lib/carray/frame/describe.rb +80 -0
  151. data/lib/carray/frame/frame.rb +369 -45
  152. data/lib/carray/frame/group.rb +631 -90
  153. data/lib/carray/frame/io.rb +506 -79
  154. data/lib/carray/frame/join.rb +411 -62
  155. data/lib/carray/frame/records.rb +116 -19
  156. data/lib/carray/frame/reshape.rb +455 -0
  157. data/lib/carray/frame/sort.rb +30 -18
  158. data/lib/carray/frame/verbs.rb +868 -61
  159. data/lib/carray/frame/windows.rb +117 -0
  160. data/lib/carray/frame.rb +4 -0
  161. data/lib/carray/fuse_source.rb +118 -2
  162. data/lib/carray/fusion.rb +257 -42
  163. data/lib/carray/histogram.rb +6 -1
  164. data/lib/carray/inspect.rb +54 -13
  165. data/lib/carray/iterator.rb +99 -9
  166. data/lib/carray/key_windows.rb +620 -0
  167. data/lib/carray/lazy.rb +216 -193
  168. data/lib/carray/mask_gap_fill.rb +112 -92
  169. data/lib/carray/math.rb +32 -19
  170. data/lib/carray/meld_reduce.rb +52 -21
  171. data/lib/carray/methods/align_addr.rb +8 -4
  172. data/lib/carray/methods/bin.rb +26 -18
  173. data/lib/carray/methods/bincount.rb +18 -2
  174. data/lib/carray/methods/bit_string.rb +15 -4
  175. data/lib/carray/methods/choose.rb +16 -3
  176. data/lib/carray/methods/composition.rb +18 -10
  177. data/lib/carray/methods/factorize.rb +2 -2
  178. data/lib/carray/methods/gather_nd.rb +25 -5
  179. data/lib/carray/methods/insert_block.rb +9 -14
  180. data/lib/carray/methods/is_between.rb +59 -0
  181. data/lib/carray/methods/is_in.rb +140 -10
  182. data/lib/carray/methods/join.rb +2 -7
  183. data/lib/carray/methods/lag.rb +49 -0
  184. data/lib/carray/methods/locate_addr.rb +182 -45
  185. data/lib/carray/methods/mode.rb +18 -1
  186. data/lib/carray/methods/nunique.rb +11 -6
  187. data/lib/carray/methods/repeat.rb +1 -20
  188. data/lib/carray/methods/resize.rb +21 -23
  189. data/lib/carray/methods/snap.rb +34 -12
  190. data/lib/carray/methods/unique.rb +11 -2
  191. data/lib/carray/methods/value_counts.rb +4 -11
  192. data/lib/carray/record_order.rb +208 -0
  193. data/lib/carray/rng.rb +3 -0
  194. data/lib/carray/runtime.rb +65 -17
  195. data/lib/carray/segment_iterator.rb +1221 -0
  196. data/lib/carray/serialize.rb +214 -30
  197. data/lib/carray/slab_iterator.rb +101 -27
  198. data/lib/carray/stack.rb +10 -4
  199. data/lib/carray/string.rb +105 -5
  200. data/lib/carray/string_operation_extension.rb +12 -4
  201. data/lib/carray/struct.rb +137 -58
  202. data/lib/carray/struct_builder.rb +124 -17
  203. data/lib/carray/time.rb +1222 -186
  204. data/lib/carray/window_iterator.rb +242 -81
  205. data/lib/carray.rb +9 -2
  206. data/yard-stubs/ca_obj_array.rb +4 -4
  207. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  208. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  209. data/yard-stubs/ca_obj_fake.rb +1 -1
  210. data/yard-stubs/ca_obj_field.rb +5 -1
  211. data/yard-stubs/ca_obj_grid.rb +21 -10
  212. data/yard-stubs/ca_obj_refer.rb +5 -4
  213. data/yard-stubs/ca_obj_roll.rb +2 -3
  214. data/yard-stubs/ca_obj_shift.rb +5 -1
  215. data/yard-stubs/ca_obj_stride.rb +10 -7
  216. data/yard-stubs/ca_obj_tile.rb +1 -1
  217. data/yard-stubs/ca_obj_transpose.rb +1 -1
  218. data/yard-stubs/ca_obj_window.rb +9 -5
  219. data/yard-stubs/carray_access.rb +11 -5
  220. data/yard-stubs/carray_attribute.rb +0 -5
  221. data/yard-stubs/carray_broadcast.rb +1 -1
  222. data/yard-stubs/carray_cast.rb +88 -43
  223. data/yard-stubs/carray_conversion.rb +15 -2
  224. data/yard-stubs/carray_copy.rb +12 -5
  225. data/yard-stubs/carray_core.rb +3 -3
  226. data/yard-stubs/carray_count.rb +9 -0
  227. data/yard-stubs/carray_element.rb +10 -4
  228. data/yard-stubs/carray_generate.rb +21 -1
  229. data/yard-stubs/carray_lazy.rb +5 -1
  230. data/yard-stubs/carray_loop.rb +4 -1
  231. data/yard-stubs/carray_mask.rb +60 -12
  232. data/yard-stubs/carray_math.rb +52 -14
  233. data/yard-stubs/carray_median_percentile.rb +15 -8
  234. data/yard-stubs/carray_memory_view.rb +40 -23
  235. data/yard-stubs/carray_order.rb +61 -29
  236. data/yard-stubs/carray_random.rb +13 -4
  237. data/yard-stubs/carray_scatter.rb +21 -9
  238. data/yard-stubs/carray_segment.rb +72 -0
  239. data/yard-stubs/carray_slab.rb +10 -2
  240. data/yard-stubs/carray_sort.rb +49 -8
  241. data/yard-stubs/carray_test.rb +15 -3
  242. data/yard-stubs/carray_utils.rb +0 -26
  243. metadata +19 -5
  244. data/ext/ca_for_each_element.h +0 -239
  245. data/ext/carray_kernels_map.c +0 -3467
  246. data/lib/carray/arrow_tensor.rb +0 -401
  247. data/lib/carray/table.rb +0 -108
@@ -24,6 +24,13 @@
24
24
  probed by operation-table function pointer (obj_type is runtime-
25
25
  assigned, so no CA_OBJ_STACK compile-time constant exists). */
26
26
  extern ca_operation_function_t ca_stack_func;
27
+ /* The square root of a variance: an ε-negative from rounding becomes 0,
28
+ a NaN stays NaN (fmax(NaN, 0.0) is 0.0). */
29
+ #ifndef CARRAY_SQRT_CLAMP_DEFINED
30
+ #define CARRAY_SQRT_CLAMP_DEFINED
31
+ static inline double ca_sqrt_clamp (double v) { return sqrt(v < 0.0 ? 0.0 : v); }
32
+ #endif
33
+
27
34
  /* BOOL2VAL: bool -> Ruby (Qtrue/Qfalse). Used as ruby_scalar wrapper
28
35
  for the all/any flat-reduction Ruby surface so `a.all` / `a.any`
29
36
  return real true/false, not Integer 0/1. (BOOL2OBJ already exists
@@ -57,14 +64,14 @@ cumsum_ki_native_i8 (VALUE self, CArray *ca, int axis)
57
64
  slab_axes, 1, 0);
58
65
  if ( rc != CA_ITER_OK ) {
59
66
  rb_raise(rb_eRuntimeError,
60
- "cumsum_ki: input init failed rc=%d", rc);
67
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
61
68
  }
62
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
69
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
63
70
  slab_axes, 1, CA_KERNEL_WRITE);
64
71
  if ( rc != CA_ITER_OK ) {
65
72
  ca_iter_state_finish(&st_in);
66
73
  rb_raise(rb_eRuntimeError,
67
- "cumsum_ki: output init failed rc=%d", rc);
74
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
68
75
  }
69
76
 
70
77
  char *pi, *po;
@@ -99,14 +106,14 @@ cumsum_ki_native_u8 (VALUE self, CArray *ca, int axis)
99
106
  slab_axes, 1, 0);
100
107
  if ( rc != CA_ITER_OK ) {
101
108
  rb_raise(rb_eRuntimeError,
102
- "cumsum_ki: input init failed rc=%d", rc);
109
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
103
110
  }
104
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
111
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
105
112
  slab_axes, 1, CA_KERNEL_WRITE);
106
113
  if ( rc != CA_ITER_OK ) {
107
114
  ca_iter_state_finish(&st_in);
108
115
  rb_raise(rb_eRuntimeError,
109
- "cumsum_ki: output init failed rc=%d", rc);
116
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
110
117
  }
111
118
 
112
119
  char *pi, *po;
@@ -141,14 +148,14 @@ cumsum_ki_native_i16 (VALUE self, CArray *ca, int axis)
141
148
  slab_axes, 1, 0);
142
149
  if ( rc != CA_ITER_OK ) {
143
150
  rb_raise(rb_eRuntimeError,
144
- "cumsum_ki: input init failed rc=%d", rc);
151
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
145
152
  }
146
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
153
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
147
154
  slab_axes, 1, CA_KERNEL_WRITE);
148
155
  if ( rc != CA_ITER_OK ) {
149
156
  ca_iter_state_finish(&st_in);
150
157
  rb_raise(rb_eRuntimeError,
151
- "cumsum_ki: output init failed rc=%d", rc);
158
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
152
159
  }
153
160
 
154
161
  char *pi, *po;
@@ -183,14 +190,14 @@ cumsum_ki_native_u16 (VALUE self, CArray *ca, int axis)
183
190
  slab_axes, 1, 0);
184
191
  if ( rc != CA_ITER_OK ) {
185
192
  rb_raise(rb_eRuntimeError,
186
- "cumsum_ki: input init failed rc=%d", rc);
193
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
187
194
  }
188
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
195
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
189
196
  slab_axes, 1, CA_KERNEL_WRITE);
190
197
  if ( rc != CA_ITER_OK ) {
191
198
  ca_iter_state_finish(&st_in);
192
199
  rb_raise(rb_eRuntimeError,
193
- "cumsum_ki: output init failed rc=%d", rc);
200
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
194
201
  }
195
202
 
196
203
  char *pi, *po;
@@ -225,14 +232,14 @@ cumsum_ki_native_i32 (VALUE self, CArray *ca, int axis)
225
232
  slab_axes, 1, 0);
226
233
  if ( rc != CA_ITER_OK ) {
227
234
  rb_raise(rb_eRuntimeError,
228
- "cumsum_ki: input init failed rc=%d", rc);
235
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
229
236
  }
230
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
237
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
231
238
  slab_axes, 1, CA_KERNEL_WRITE);
232
239
  if ( rc != CA_ITER_OK ) {
233
240
  ca_iter_state_finish(&st_in);
234
241
  rb_raise(rb_eRuntimeError,
235
- "cumsum_ki: output init failed rc=%d", rc);
242
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
236
243
  }
237
244
 
238
245
  char *pi, *po;
@@ -267,14 +274,14 @@ cumsum_ki_native_u32 (VALUE self, CArray *ca, int axis)
267
274
  slab_axes, 1, 0);
268
275
  if ( rc != CA_ITER_OK ) {
269
276
  rb_raise(rb_eRuntimeError,
270
- "cumsum_ki: input init failed rc=%d", rc);
277
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
271
278
  }
272
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
279
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
273
280
  slab_axes, 1, CA_KERNEL_WRITE);
274
281
  if ( rc != CA_ITER_OK ) {
275
282
  ca_iter_state_finish(&st_in);
276
283
  rb_raise(rb_eRuntimeError,
277
- "cumsum_ki: output init failed rc=%d", rc);
284
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
278
285
  }
279
286
 
280
287
  char *pi, *po;
@@ -309,14 +316,14 @@ cumsum_ki_native_i64 (VALUE self, CArray *ca, int axis)
309
316
  slab_axes, 1, 0);
310
317
  if ( rc != CA_ITER_OK ) {
311
318
  rb_raise(rb_eRuntimeError,
312
- "cumsum_ki: input init failed rc=%d", rc);
319
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
313
320
  }
314
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
321
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
315
322
  slab_axes, 1, CA_KERNEL_WRITE);
316
323
  if ( rc != CA_ITER_OK ) {
317
324
  ca_iter_state_finish(&st_in);
318
325
  rb_raise(rb_eRuntimeError,
319
- "cumsum_ki: output init failed rc=%d", rc);
326
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
320
327
  }
321
328
 
322
329
  char *pi, *po;
@@ -351,14 +358,14 @@ cumsum_ki_native_u64 (VALUE self, CArray *ca, int axis)
351
358
  slab_axes, 1, 0);
352
359
  if ( rc != CA_ITER_OK ) {
353
360
  rb_raise(rb_eRuntimeError,
354
- "cumsum_ki: input init failed rc=%d", rc);
361
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
355
362
  }
356
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
363
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
357
364
  slab_axes, 1, CA_KERNEL_WRITE);
358
365
  if ( rc != CA_ITER_OK ) {
359
366
  ca_iter_state_finish(&st_in);
360
367
  rb_raise(rb_eRuntimeError,
361
- "cumsum_ki: output init failed rc=%d", rc);
368
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
362
369
  }
363
370
 
364
371
  char *pi, *po;
@@ -393,14 +400,14 @@ cumsum_ki_native_f32 (VALUE self, CArray *ca, int axis)
393
400
  slab_axes, 1, 0);
394
401
  if ( rc != CA_ITER_OK ) {
395
402
  rb_raise(rb_eRuntimeError,
396
- "cumsum_ki: input init failed rc=%d", rc);
403
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
397
404
  }
398
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
405
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
399
406
  slab_axes, 1, CA_KERNEL_WRITE);
400
407
  if ( rc != CA_ITER_OK ) {
401
408
  ca_iter_state_finish(&st_in);
402
409
  rb_raise(rb_eRuntimeError,
403
- "cumsum_ki: output init failed rc=%d", rc);
410
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
404
411
  }
405
412
 
406
413
  char *pi, *po;
@@ -435,14 +442,14 @@ cumsum_ki_native_f64 (VALUE self, CArray *ca, int axis)
435
442
  slab_axes, 1, 0);
436
443
  if ( rc != CA_ITER_OK ) {
437
444
  rb_raise(rb_eRuntimeError,
438
- "cumsum_ki: input init failed rc=%d", rc);
445
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
439
446
  }
440
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
447
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
441
448
  slab_axes, 1, CA_KERNEL_WRITE);
442
449
  if ( rc != CA_ITER_OK ) {
443
450
  ca_iter_state_finish(&st_in);
444
451
  rb_raise(rb_eRuntimeError,
445
- "cumsum_ki: output init failed rc=%d", rc);
452
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
446
453
  }
447
454
 
448
455
  char *pi, *po;
@@ -477,14 +484,14 @@ cumsum_ki_native_cmplx64 (VALUE self, CArray *ca, int axis)
477
484
  slab_axes, 1, 0);
478
485
  if ( rc != CA_ITER_OK ) {
479
486
  rb_raise(rb_eRuntimeError,
480
- "cumsum_ki: input init failed rc=%d", rc);
487
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
481
488
  }
482
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
489
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
483
490
  slab_axes, 1, CA_KERNEL_WRITE);
484
491
  if ( rc != CA_ITER_OK ) {
485
492
  ca_iter_state_finish(&st_in);
486
493
  rb_raise(rb_eRuntimeError,
487
- "cumsum_ki: output init failed rc=%d", rc);
494
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
488
495
  }
489
496
 
490
497
  char *pi, *po;
@@ -519,14 +526,14 @@ cumsum_ki_native_cmplx128 (VALUE self, CArray *ca, int axis)
519
526
  slab_axes, 1, 0);
520
527
  if ( rc != CA_ITER_OK ) {
521
528
  rb_raise(rb_eRuntimeError,
522
- "cumsum_ki: input init failed rc=%d", rc);
529
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
523
530
  }
524
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
531
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
525
532
  slab_axes, 1, CA_KERNEL_WRITE);
526
533
  if ( rc != CA_ITER_OK ) {
527
534
  ca_iter_state_finish(&st_in);
528
535
  rb_raise(rb_eRuntimeError,
529
- "cumsum_ki: output init failed rc=%d", rc);
536
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
530
537
  }
531
538
 
532
539
  char *pi, *po;
@@ -561,14 +568,14 @@ cumsum_ki_native_bool (VALUE self, CArray *ca, int axis)
561
568
  slab_axes, 1, 0);
562
569
  if ( rc != CA_ITER_OK ) {
563
570
  rb_raise(rb_eRuntimeError,
564
- "cumsum_ki: input init failed rc=%d", rc);
571
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
565
572
  }
566
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
573
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
567
574
  slab_axes, 1, CA_KERNEL_WRITE);
568
575
  if ( rc != CA_ITER_OK ) {
569
576
  ca_iter_state_finish(&st_in);
570
577
  rb_raise(rb_eRuntimeError,
571
- "cumsum_ki: output init failed rc=%d", rc);
578
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
572
579
  }
573
580
 
574
581
  char *pi, *po;
@@ -584,9 +591,28 @@ cumsum_ki_native_bool (VALUE self, CArray *ca, int axis)
584
591
  return vout;
585
592
  }
586
593
 
594
+ /* The object lane calls Ruby for every cell, so a walk can raise part
595
+ way. Its states live in the caller's frame, and ca_iter_ensure
596
+ finishes them however the body leaves. */
597
+ typedef struct {
598
+ ca_iter_state states[2];
599
+ VALUE self;
600
+ CArray *ca;
601
+ int axis;
602
+ } cumsum_ki_native_object_frame;
603
+
587
604
  static VALUE
588
- cumsum_ki_native_object (VALUE self, CArray *ca, int axis)
605
+ cumsum_ki_native_object_body (VALUE arg)
589
606
  {
607
+ cumsum_ki_native_object_frame *fr = (cumsum_ki_native_object_frame *) arg;
608
+ VALUE self = fr->self;
609
+ (void) self;
610
+ CArray *ca = fr->ca;
611
+ (void) ca;
612
+ int axis = fr->axis;
613
+ (void) axis;
614
+ #define st_in (fr->states[0])
615
+ #define st_out (fr->states[1])
590
616
  VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
591
617
  INT2NUM(sizeof(VALUE)));
592
618
  CArray *co;
@@ -597,20 +623,19 @@ cumsum_ki_native_object (VALUE self, CArray *ca, int axis)
597
623
  INIT inside the macro. */
598
624
  int8_t slab_axes[CA_RANK_MAX];
599
625
  slab_axes[0] = (int8_t) axis;
600
- ca_iter_state st_in, st_out;
601
626
  int rc;
602
627
  rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
603
628
  slab_axes, 1, 0);
604
629
  if ( rc != CA_ITER_OK ) {
605
630
  rb_raise(rb_eRuntimeError,
606
- "cumsum_ki: input init failed rc=%d", rc);
631
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
607
632
  }
608
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
633
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
609
634
  slab_axes, 1, CA_KERNEL_WRITE);
610
635
  if ( rc != CA_ITER_OK ) {
611
636
  ca_iter_state_finish(&st_in);
612
637
  rb_raise(rb_eRuntimeError,
613
- "cumsum_ki: output init failed rc=%d", rc);
638
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
614
639
  }
615
640
 
616
641
  char *pi, *po;
@@ -624,70 +649,479 @@ cumsum_ki_native_object (VALUE self, CArray *ca, int axis)
624
649
  ca_iter_state_finish(&st_in);
625
650
  ca_iter_state_finish(&st_out);
626
651
  return vout;
652
+ #undef st_in
653
+ #undef st_out
627
654
  }
628
655
 
656
+ static VALUE
657
+ cumsum_ki_native_object (VALUE self, CArray *ca, int axis)
658
+ {
659
+ cumsum_ki_native_object_frame fr;
660
+ fr.self = self;
661
+ fr.ca = ca;
662
+ fr.axis = axis;
663
+ return ca_iter_ensure(2, fr.states, cumsum_ki_native_object_body, (VALUE) &fr);
664
+ }
665
+
666
+
629
667
  static VALUE
630
668
  rb_ca_cumsum_ki (int argc, VALUE *argv, VALUE self)
631
669
  {
632
670
  CArray *src;
633
671
  GetCArray(self, src);
672
+ if ( ca_is_lazy_view(src) ) {
673
+ volatile VALUE evaluated = ca_lazy_evaluated(self);
674
+ if ( ! NIL_P(evaluated) ) {
675
+ self = evaluated;
676
+ GetCArray(self, src);
677
+ }
678
+ }
634
679
  volatile VALUE ropt = rb_pop_options(&argc, &argv);
635
680
  volatile VALUE raxis = Qnil;
636
681
  rb_scan_options(ropt, "axis", &raxis);
637
682
  if ( argc > 0 ) {
638
- rb_raise(rb_eArgError, "cumsum_ki: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cumsum(axis: 0)", argc);
683
+ rb_raise(rb_eArgError, "%s: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cumsum(axis: 0)", ca_calling_method_name(), argc);
639
684
  }
640
685
  if ( NIL_P(raxis) ) {
641
686
  volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
642
687
  CArray *fsrc;
643
688
  GetCArray(vflat, fsrc);
644
689
  switch ( fsrc->data_type ) {
645
- case CA_INT8: return cumsum_ki_native_i8(vflat, fsrc, 0);
646
- case CA_UINT8: return cumsum_ki_native_u8(vflat, fsrc, 0);
647
- case CA_INT16: return cumsum_ki_native_i16(vflat, fsrc, 0);
648
- case CA_UINT16: return cumsum_ki_native_u16(vflat, fsrc, 0);
649
- case CA_INT32: return cumsum_ki_native_i32(vflat, fsrc, 0);
650
- case CA_UINT32: return cumsum_ki_native_u32(vflat, fsrc, 0);
651
- case CA_INT64: return cumsum_ki_native_i64(vflat, fsrc, 0);
652
- case CA_UINT64: return cumsum_ki_native_u64(vflat, fsrc, 0);
653
- case CA_FLOAT32: return cumsum_ki_native_f32(vflat, fsrc, 0);
654
- case CA_FLOAT64: return cumsum_ki_native_f64(vflat, fsrc, 0);
655
- case CA_CMPLX64: return cumsum_ki_native_cmplx64(vflat, fsrc, 0);
656
- case CA_CMPLX128: return cumsum_ki_native_cmplx128(vflat, fsrc, 0);
657
- case CA_BOOLEAN: return cumsum_ki_native_bool(vflat, fsrc, 0);
658
- case CA_OBJECT: return cumsum_ki_native_object(vflat, fsrc, 0);
690
+ case CA_INT8: CA_RETURN_KEEPING(vflat, cumsum_ki_native_i8(vflat, fsrc, 0));
691
+ case CA_UINT8: CA_RETURN_KEEPING(vflat, cumsum_ki_native_u8(vflat, fsrc, 0));
692
+ case CA_INT16: CA_RETURN_KEEPING(vflat, cumsum_ki_native_i16(vflat, fsrc, 0));
693
+ case CA_UINT16: CA_RETURN_KEEPING(vflat, cumsum_ki_native_u16(vflat, fsrc, 0));
694
+ case CA_INT32: CA_RETURN_KEEPING(vflat, cumsum_ki_native_i32(vflat, fsrc, 0));
695
+ case CA_UINT32: CA_RETURN_KEEPING(vflat, cumsum_ki_native_u32(vflat, fsrc, 0));
696
+ case CA_INT64: CA_RETURN_KEEPING(vflat, cumsum_ki_native_i64(vflat, fsrc, 0));
697
+ case CA_UINT64: CA_RETURN_KEEPING(vflat, cumsum_ki_native_u64(vflat, fsrc, 0));
698
+ case CA_FLOAT32: CA_RETURN_KEEPING(vflat, cumsum_ki_native_f32(vflat, fsrc, 0));
699
+ case CA_FLOAT64: CA_RETURN_KEEPING(vflat, cumsum_ki_native_f64(vflat, fsrc, 0));
700
+ case CA_CMPLX64: CA_RETURN_KEEPING(vflat, cumsum_ki_native_cmplx64(vflat, fsrc, 0));
701
+ case CA_CMPLX128: CA_RETURN_KEEPING(vflat, cumsum_ki_native_cmplx128(vflat, fsrc, 0));
702
+ case CA_BOOLEAN: CA_RETURN_KEEPING(vflat, cumsum_ki_native_bool(vflat, fsrc, 0));
703
+ case CA_OBJECT: CA_RETURN_KEEPING(vflat, cumsum_ki_native_object(vflat, fsrc, 0));
659
704
  default:
660
- rb_raise(rb_eCADataTypeError, "cumsum_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, cmplx64, cmplx128, bool, object)", ca_type_name[fsrc->data_type]);
705
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
706
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[fsrc->data_type]);
661
707
  }
662
708
  }
663
709
  if ( TYPE(raxis) == T_ARRAY ) {
664
- rb_raise(rb_eArgError, "cumsum_ki: axis: must be Integer (got Array); multi-axis scan is semantically ambiguous, chain explicitly: a.cumsum(axis: 0).cumsum(axis: 1)");
710
+ rb_raise(rb_eArgError, "%s: axis must be a single Integer (got Array); a scan over several axes is ambiguous, chain explicitly: a.cumsum(axis: 0).cumsum(axis: 1)", ca_calling_method_name());
711
+ }
712
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
713
+ switch ( src->data_type ) {
714
+ case CA_INT8: CA_RETURN_KEEPING(self, cumsum_ki_native_i8(self, src, axis));
715
+ case CA_UINT8: CA_RETURN_KEEPING(self, cumsum_ki_native_u8(self, src, axis));
716
+ case CA_INT16: CA_RETURN_KEEPING(self, cumsum_ki_native_i16(self, src, axis));
717
+ case CA_UINT16: CA_RETURN_KEEPING(self, cumsum_ki_native_u16(self, src, axis));
718
+ case CA_INT32: CA_RETURN_KEEPING(self, cumsum_ki_native_i32(self, src, axis));
719
+ case CA_UINT32: CA_RETURN_KEEPING(self, cumsum_ki_native_u32(self, src, axis));
720
+ case CA_INT64: CA_RETURN_KEEPING(self, cumsum_ki_native_i64(self, src, axis));
721
+ case CA_UINT64: CA_RETURN_KEEPING(self, cumsum_ki_native_u64(self, src, axis));
722
+ case CA_FLOAT32: CA_RETURN_KEEPING(self, cumsum_ki_native_f32(self, src, axis));
723
+ case CA_FLOAT64: CA_RETURN_KEEPING(self, cumsum_ki_native_f64(self, src, axis));
724
+ case CA_CMPLX64: CA_RETURN_KEEPING(self, cumsum_ki_native_cmplx64(self, src, axis));
725
+ case CA_CMPLX128: CA_RETURN_KEEPING(self, cumsum_ki_native_cmplx128(self, src, axis));
726
+ case CA_BOOLEAN: CA_RETURN_KEEPING(self, cumsum_ki_native_bool(self, src, axis));
727
+ case CA_OBJECT: CA_RETURN_KEEPING(self, cumsum_ki_native_object(self, src, axis));
728
+ default:
729
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
730
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
731
+ }
732
+ return Qnil; /* unreachable */
733
+ }
734
+
735
+ /* ===== cumsum_in_own_type_ki ============================================ */
736
+
737
+ static VALUE
738
+ cumsum_in_own_type_ki_native_i8 (VALUE self, CArray *ca, int axis)
739
+ {
740
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT8),
741
+ INT2NUM(sizeof(int8_t)));
742
+ CArray *co;
743
+ GetCArray(vout, co);
744
+
745
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
746
+ iteration is one "fiber" along that axis with acc reset to
747
+ INIT inside the macro. */
748
+ int8_t slab_axes[CA_RANK_MAX];
749
+ slab_axes[0] = (int8_t) axis;
750
+ ca_iter_state st_in, st_out;
751
+ int rc;
752
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
753
+ slab_axes, 1, 0);
754
+ if ( rc != CA_ITER_OK ) {
755
+ rb_raise(rb_eRuntimeError,
756
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
757
+ }
758
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
759
+ slab_axes, 1, CA_KERNEL_WRITE);
760
+ if ( rc != CA_ITER_OK ) {
761
+ ca_iter_state_finish(&st_in);
762
+ rb_raise(rb_eRuntimeError,
763
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
764
+ }
765
+
766
+ char *pi, *po;
767
+ boolean8_t *mi, *mo;
768
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
769
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
770
+ CA_SLAB_SCAN_T(int8_t, int8_t, st_in, pi, mi,
771
+ st_out, po, 0, acc += v; r = acc);
772
+ ca_iter_state_sync_slab(&st_out);
773
+ }
774
+ ca_iter_state_finish(&st_in);
775
+ ca_iter_state_finish(&st_out);
776
+ return vout;
777
+ }
778
+
779
+ static VALUE
780
+ cumsum_in_own_type_ki_native_u8 (VALUE self, CArray *ca, int axis)
781
+ {
782
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT8),
783
+ INT2NUM(sizeof(uint8_t)));
784
+ CArray *co;
785
+ GetCArray(vout, co);
786
+
787
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
788
+ iteration is one "fiber" along that axis with acc reset to
789
+ INIT inside the macro. */
790
+ int8_t slab_axes[CA_RANK_MAX];
791
+ slab_axes[0] = (int8_t) axis;
792
+ ca_iter_state st_in, st_out;
793
+ int rc;
794
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
795
+ slab_axes, 1, 0);
796
+ if ( rc != CA_ITER_OK ) {
797
+ rb_raise(rb_eRuntimeError,
798
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
799
+ }
800
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
801
+ slab_axes, 1, CA_KERNEL_WRITE);
802
+ if ( rc != CA_ITER_OK ) {
803
+ ca_iter_state_finish(&st_in);
804
+ rb_raise(rb_eRuntimeError,
805
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
806
+ }
807
+
808
+ char *pi, *po;
809
+ boolean8_t *mi, *mo;
810
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
811
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
812
+ CA_SLAB_SCAN_T(uint8_t, uint8_t, st_in, pi, mi,
813
+ st_out, po, 0, acc += v; r = acc);
814
+ ca_iter_state_sync_slab(&st_out);
815
+ }
816
+ ca_iter_state_finish(&st_in);
817
+ ca_iter_state_finish(&st_out);
818
+ return vout;
819
+ }
820
+
821
+ static VALUE
822
+ cumsum_in_own_type_ki_native_i16 (VALUE self, CArray *ca, int axis)
823
+ {
824
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT16),
825
+ INT2NUM(sizeof(int16_t)));
826
+ CArray *co;
827
+ GetCArray(vout, co);
828
+
829
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
830
+ iteration is one "fiber" along that axis with acc reset to
831
+ INIT inside the macro. */
832
+ int8_t slab_axes[CA_RANK_MAX];
833
+ slab_axes[0] = (int8_t) axis;
834
+ ca_iter_state st_in, st_out;
835
+ int rc;
836
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
837
+ slab_axes, 1, 0);
838
+ if ( rc != CA_ITER_OK ) {
839
+ rb_raise(rb_eRuntimeError,
840
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
841
+ }
842
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
843
+ slab_axes, 1, CA_KERNEL_WRITE);
844
+ if ( rc != CA_ITER_OK ) {
845
+ ca_iter_state_finish(&st_in);
846
+ rb_raise(rb_eRuntimeError,
847
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
848
+ }
849
+
850
+ char *pi, *po;
851
+ boolean8_t *mi, *mo;
852
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
853
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
854
+ CA_SLAB_SCAN_T(int16_t, int16_t, st_in, pi, mi,
855
+ st_out, po, 0, acc += v; r = acc);
856
+ ca_iter_state_sync_slab(&st_out);
857
+ }
858
+ ca_iter_state_finish(&st_in);
859
+ ca_iter_state_finish(&st_out);
860
+ return vout;
861
+ }
862
+
863
+ static VALUE
864
+ cumsum_in_own_type_ki_native_u16 (VALUE self, CArray *ca, int axis)
865
+ {
866
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT16),
867
+ INT2NUM(sizeof(uint16_t)));
868
+ CArray *co;
869
+ GetCArray(vout, co);
870
+
871
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
872
+ iteration is one "fiber" along that axis with acc reset to
873
+ INIT inside the macro. */
874
+ int8_t slab_axes[CA_RANK_MAX];
875
+ slab_axes[0] = (int8_t) axis;
876
+ ca_iter_state st_in, st_out;
877
+ int rc;
878
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
879
+ slab_axes, 1, 0);
880
+ if ( rc != CA_ITER_OK ) {
881
+ rb_raise(rb_eRuntimeError,
882
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
883
+ }
884
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
885
+ slab_axes, 1, CA_KERNEL_WRITE);
886
+ if ( rc != CA_ITER_OK ) {
887
+ ca_iter_state_finish(&st_in);
888
+ rb_raise(rb_eRuntimeError,
889
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
890
+ }
891
+
892
+ char *pi, *po;
893
+ boolean8_t *mi, *mo;
894
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
895
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
896
+ CA_SLAB_SCAN_T(uint16_t, uint16_t, st_in, pi, mi,
897
+ st_out, po, 0, acc += v; r = acc);
898
+ ca_iter_state_sync_slab(&st_out);
899
+ }
900
+ ca_iter_state_finish(&st_in);
901
+ ca_iter_state_finish(&st_out);
902
+ return vout;
903
+ }
904
+
905
+ static VALUE
906
+ cumsum_in_own_type_ki_native_i32 (VALUE self, CArray *ca, int axis)
907
+ {
908
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT32),
909
+ INT2NUM(sizeof(int32_t)));
910
+ CArray *co;
911
+ GetCArray(vout, co);
912
+
913
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
914
+ iteration is one "fiber" along that axis with acc reset to
915
+ INIT inside the macro. */
916
+ int8_t slab_axes[CA_RANK_MAX];
917
+ slab_axes[0] = (int8_t) axis;
918
+ ca_iter_state st_in, st_out;
919
+ int rc;
920
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
921
+ slab_axes, 1, 0);
922
+ if ( rc != CA_ITER_OK ) {
923
+ rb_raise(rb_eRuntimeError,
924
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
665
925
  }
666
- if ( ! rb_obj_is_kind_of(raxis, rb_cInteger) ) {
667
- rb_raise(rb_eTypeError, "cumsum_ki: axis: must be Integer (got %"PRIsVALUE")", rb_obj_class(raxis));
926
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
927
+ slab_axes, 1, CA_KERNEL_WRITE);
928
+ if ( rc != CA_ITER_OK ) {
929
+ ca_iter_state_finish(&st_in);
930
+ rb_raise(rb_eRuntimeError,
931
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
668
932
  }
669
- int axis = NUM2INT(raxis);
670
- if ( axis < 0 ) axis += src->ndim;
671
- if ( axis < 0 || axis >= src->ndim ) {
672
- rb_raise(rb_eArgError, "cumsum_ki: axis %d out of range for ndim %d", NUM2INT(raxis), src->ndim);
933
+
934
+ char *pi, *po;
935
+ boolean8_t *mi, *mo;
936
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
937
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
938
+ CA_SLAB_SCAN_T(int32_t, int32_t, st_in, pi, mi,
939
+ st_out, po, 0, acc += v; r = acc);
940
+ ca_iter_state_sync_slab(&st_out);
673
941
  }
942
+ ca_iter_state_finish(&st_in);
943
+ ca_iter_state_finish(&st_out);
944
+ return vout;
945
+ }
946
+
947
+ static VALUE
948
+ cumsum_in_own_type_ki_native_u32 (VALUE self, CArray *ca, int axis)
949
+ {
950
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT32),
951
+ INT2NUM(sizeof(uint32_t)));
952
+ CArray *co;
953
+ GetCArray(vout, co);
954
+
955
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
956
+ iteration is one "fiber" along that axis with acc reset to
957
+ INIT inside the macro. */
958
+ int8_t slab_axes[CA_RANK_MAX];
959
+ slab_axes[0] = (int8_t) axis;
960
+ ca_iter_state st_in, st_out;
961
+ int rc;
962
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
963
+ slab_axes, 1, 0);
964
+ if ( rc != CA_ITER_OK ) {
965
+ rb_raise(rb_eRuntimeError,
966
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
967
+ }
968
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
969
+ slab_axes, 1, CA_KERNEL_WRITE);
970
+ if ( rc != CA_ITER_OK ) {
971
+ ca_iter_state_finish(&st_in);
972
+ rb_raise(rb_eRuntimeError,
973
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
974
+ }
975
+
976
+ char *pi, *po;
977
+ boolean8_t *mi, *mo;
978
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
979
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
980
+ CA_SLAB_SCAN_T(uint32_t, uint32_t, st_in, pi, mi,
981
+ st_out, po, 0, acc += v; r = acc);
982
+ ca_iter_state_sync_slab(&st_out);
983
+ }
984
+ ca_iter_state_finish(&st_in);
985
+ ca_iter_state_finish(&st_out);
986
+ return vout;
987
+ }
988
+
989
+ static VALUE
990
+ cumsum_in_own_type_ki_native_i64 (VALUE self, CArray *ca, int axis)
991
+ {
992
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
993
+ INT2NUM(sizeof(int64_t)));
994
+ CArray *co;
995
+ GetCArray(vout, co);
996
+
997
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
998
+ iteration is one "fiber" along that axis with acc reset to
999
+ INIT inside the macro. */
1000
+ int8_t slab_axes[CA_RANK_MAX];
1001
+ slab_axes[0] = (int8_t) axis;
1002
+ ca_iter_state st_in, st_out;
1003
+ int rc;
1004
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1005
+ slab_axes, 1, 0);
1006
+ if ( rc != CA_ITER_OK ) {
1007
+ rb_raise(rb_eRuntimeError,
1008
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1009
+ }
1010
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1011
+ slab_axes, 1, CA_KERNEL_WRITE);
1012
+ if ( rc != CA_ITER_OK ) {
1013
+ ca_iter_state_finish(&st_in);
1014
+ rb_raise(rb_eRuntimeError,
1015
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1016
+ }
1017
+
1018
+ char *pi, *po;
1019
+ boolean8_t *mi, *mo;
1020
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1021
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1022
+ CA_SLAB_SCAN_T(int64_t, int64_t, st_in, pi, mi,
1023
+ st_out, po, 0, acc += v; r = acc);
1024
+ ca_iter_state_sync_slab(&st_out);
1025
+ }
1026
+ ca_iter_state_finish(&st_in);
1027
+ ca_iter_state_finish(&st_out);
1028
+ return vout;
1029
+ }
1030
+
1031
+ static VALUE
1032
+ cumsum_in_own_type_ki_native_u64 (VALUE self, CArray *ca, int axis)
1033
+ {
1034
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT64),
1035
+ INT2NUM(sizeof(uint64_t)));
1036
+ CArray *co;
1037
+ GetCArray(vout, co);
1038
+
1039
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1040
+ iteration is one "fiber" along that axis with acc reset to
1041
+ INIT inside the macro. */
1042
+ int8_t slab_axes[CA_RANK_MAX];
1043
+ slab_axes[0] = (int8_t) axis;
1044
+ ca_iter_state st_in, st_out;
1045
+ int rc;
1046
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1047
+ slab_axes, 1, 0);
1048
+ if ( rc != CA_ITER_OK ) {
1049
+ rb_raise(rb_eRuntimeError,
1050
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1051
+ }
1052
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1053
+ slab_axes, 1, CA_KERNEL_WRITE);
1054
+ if ( rc != CA_ITER_OK ) {
1055
+ ca_iter_state_finish(&st_in);
1056
+ rb_raise(rb_eRuntimeError,
1057
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1058
+ }
1059
+
1060
+ char *pi, *po;
1061
+ boolean8_t *mi, *mo;
1062
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1063
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1064
+ CA_SLAB_SCAN_T(uint64_t, uint64_t, st_in, pi, mi,
1065
+ st_out, po, 0, acc += v; r = acc);
1066
+ ca_iter_state_sync_slab(&st_out);
1067
+ }
1068
+ ca_iter_state_finish(&st_in);
1069
+ ca_iter_state_finish(&st_out);
1070
+ return vout;
1071
+ }
1072
+
1073
+ static VALUE
1074
+ rb_ca_cumsum_in_own_type_ki (int argc, VALUE *argv, VALUE self)
1075
+ {
1076
+ CArray *src;
1077
+ GetCArray(self, src);
1078
+ if ( ca_is_lazy_view(src) ) {
1079
+ volatile VALUE evaluated = ca_lazy_evaluated(self);
1080
+ if ( ! NIL_P(evaluated) ) {
1081
+ self = evaluated;
1082
+ GetCArray(self, src);
1083
+ }
1084
+ }
1085
+ volatile VALUE ropt = rb_pop_options(&argc, &argv);
1086
+ volatile VALUE raxis = Qnil;
1087
+ rb_scan_options(ropt, "axis", &raxis);
1088
+ if ( argc > 0 ) {
1089
+ rb_raise(rb_eArgError, "%s: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cumsum_in_own_type(axis: 0)", ca_calling_method_name(), argc);
1090
+ }
1091
+ if ( NIL_P(raxis) ) {
1092
+ volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
1093
+ CArray *fsrc;
1094
+ GetCArray(vflat, fsrc);
1095
+ switch ( fsrc->data_type ) {
1096
+ case CA_INT8: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_i8(vflat, fsrc, 0));
1097
+ case CA_UINT8: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_u8(vflat, fsrc, 0));
1098
+ case CA_INT16: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_i16(vflat, fsrc, 0));
1099
+ case CA_UINT16: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_u16(vflat, fsrc, 0));
1100
+ case CA_INT32: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_i32(vflat, fsrc, 0));
1101
+ case CA_UINT32: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_u32(vflat, fsrc, 0));
1102
+ case CA_INT64: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_i64(vflat, fsrc, 0));
1103
+ case CA_UINT64: CA_RETURN_KEEPING(vflat, cumsum_in_own_type_ki_native_u64(vflat, fsrc, 0));
1104
+ default:
1105
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
1106
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64)", ca_calling_method_name(), ca_type_name[fsrc->data_type]);
1107
+ }
1108
+ }
1109
+ if ( TYPE(raxis) == T_ARRAY ) {
1110
+ rb_raise(rb_eArgError, "%s: axis must be a single Integer (got Array); a scan over several axes is ambiguous, chain explicitly: a.cumsum_in_own_type(axis: 0).cumsum_in_own_type(axis: 1)", ca_calling_method_name());
1111
+ }
1112
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
674
1113
  switch ( src->data_type ) {
675
- case CA_INT8: return cumsum_ki_native_i8(self, src, axis);
676
- case CA_UINT8: return cumsum_ki_native_u8(self, src, axis);
677
- case CA_INT16: return cumsum_ki_native_i16(self, src, axis);
678
- case CA_UINT16: return cumsum_ki_native_u16(self, src, axis);
679
- case CA_INT32: return cumsum_ki_native_i32(self, src, axis);
680
- case CA_UINT32: return cumsum_ki_native_u32(self, src, axis);
681
- case CA_INT64: return cumsum_ki_native_i64(self, src, axis);
682
- case CA_UINT64: return cumsum_ki_native_u64(self, src, axis);
683
- case CA_FLOAT32: return cumsum_ki_native_f32(self, src, axis);
684
- case CA_FLOAT64: return cumsum_ki_native_f64(self, src, axis);
685
- case CA_CMPLX64: return cumsum_ki_native_cmplx64(self, src, axis);
686
- case CA_CMPLX128: return cumsum_ki_native_cmplx128(self, src, axis);
687
- case CA_BOOLEAN: return cumsum_ki_native_bool(self, src, axis);
688
- case CA_OBJECT: return cumsum_ki_native_object(self, src, axis);
1114
+ case CA_INT8: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_i8(self, src, axis));
1115
+ case CA_UINT8: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_u8(self, src, axis));
1116
+ case CA_INT16: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_i16(self, src, axis));
1117
+ case CA_UINT16: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_u16(self, src, axis));
1118
+ case CA_INT32: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_i32(self, src, axis));
1119
+ case CA_UINT32: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_u32(self, src, axis));
1120
+ case CA_INT64: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_i64(self, src, axis));
1121
+ case CA_UINT64: CA_RETURN_KEEPING(self, cumsum_in_own_type_ki_native_u64(self, src, axis));
689
1122
  default:
690
- rb_raise(rb_eCADataTypeError, "cumsum_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, cmplx64, cmplx128, bool, object)", ca_type_name[src->data_type]);
1123
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
1124
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64)", ca_calling_method_name(), ca_type_name[src->data_type]);
691
1125
  }
692
1126
  return Qnil; /* unreachable */
693
1127
  }
@@ -713,14 +1147,14 @@ cumprod_ki_native_i8 (VALUE self, CArray *ca, int axis)
713
1147
  slab_axes, 1, 0);
714
1148
  if ( rc != CA_ITER_OK ) {
715
1149
  rb_raise(rb_eRuntimeError,
716
- "cumprod_ki: input init failed rc=%d", rc);
1150
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
717
1151
  }
718
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1152
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
719
1153
  slab_axes, 1, CA_KERNEL_WRITE);
720
1154
  if ( rc != CA_ITER_OK ) {
721
1155
  ca_iter_state_finish(&st_in);
722
1156
  rb_raise(rb_eRuntimeError,
723
- "cumprod_ki: output init failed rc=%d", rc);
1157
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
724
1158
  }
725
1159
 
726
1160
  char *pi, *po;
@@ -755,14 +1189,14 @@ cumprod_ki_native_u8 (VALUE self, CArray *ca, int axis)
755
1189
  slab_axes, 1, 0);
756
1190
  if ( rc != CA_ITER_OK ) {
757
1191
  rb_raise(rb_eRuntimeError,
758
- "cumprod_ki: input init failed rc=%d", rc);
1192
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
759
1193
  }
760
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1194
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
761
1195
  slab_axes, 1, CA_KERNEL_WRITE);
762
1196
  if ( rc != CA_ITER_OK ) {
763
1197
  ca_iter_state_finish(&st_in);
764
1198
  rb_raise(rb_eRuntimeError,
765
- "cumprod_ki: output init failed rc=%d", rc);
1199
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
766
1200
  }
767
1201
 
768
1202
  char *pi, *po;
@@ -797,14 +1231,14 @@ cumprod_ki_native_i16 (VALUE self, CArray *ca, int axis)
797
1231
  slab_axes, 1, 0);
798
1232
  if ( rc != CA_ITER_OK ) {
799
1233
  rb_raise(rb_eRuntimeError,
800
- "cumprod_ki: input init failed rc=%d", rc);
1234
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
801
1235
  }
802
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1236
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
803
1237
  slab_axes, 1, CA_KERNEL_WRITE);
804
1238
  if ( rc != CA_ITER_OK ) {
805
1239
  ca_iter_state_finish(&st_in);
806
1240
  rb_raise(rb_eRuntimeError,
807
- "cumprod_ki: output init failed rc=%d", rc);
1241
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
808
1242
  }
809
1243
 
810
1244
  char *pi, *po;
@@ -839,14 +1273,14 @@ cumprod_ki_native_u16 (VALUE self, CArray *ca, int axis)
839
1273
  slab_axes, 1, 0);
840
1274
  if ( rc != CA_ITER_OK ) {
841
1275
  rb_raise(rb_eRuntimeError,
842
- "cumprod_ki: input init failed rc=%d", rc);
1276
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
843
1277
  }
844
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1278
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
845
1279
  slab_axes, 1, CA_KERNEL_WRITE);
846
1280
  if ( rc != CA_ITER_OK ) {
847
1281
  ca_iter_state_finish(&st_in);
848
1282
  rb_raise(rb_eRuntimeError,
849
- "cumprod_ki: output init failed rc=%d", rc);
1283
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
850
1284
  }
851
1285
 
852
1286
  char *pi, *po;
@@ -881,14 +1315,14 @@ cumprod_ki_native_i32 (VALUE self, CArray *ca, int axis)
881
1315
  slab_axes, 1, 0);
882
1316
  if ( rc != CA_ITER_OK ) {
883
1317
  rb_raise(rb_eRuntimeError,
884
- "cumprod_ki: input init failed rc=%d", rc);
1318
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
885
1319
  }
886
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1320
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
887
1321
  slab_axes, 1, CA_KERNEL_WRITE);
888
1322
  if ( rc != CA_ITER_OK ) {
889
1323
  ca_iter_state_finish(&st_in);
890
1324
  rb_raise(rb_eRuntimeError,
891
- "cumprod_ki: output init failed rc=%d", rc);
1325
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
892
1326
  }
893
1327
 
894
1328
  char *pi, *po;
@@ -923,14 +1357,14 @@ cumprod_ki_native_u32 (VALUE self, CArray *ca, int axis)
923
1357
  slab_axes, 1, 0);
924
1358
  if ( rc != CA_ITER_OK ) {
925
1359
  rb_raise(rb_eRuntimeError,
926
- "cumprod_ki: input init failed rc=%d", rc);
1360
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
927
1361
  }
928
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1362
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
929
1363
  slab_axes, 1, CA_KERNEL_WRITE);
930
1364
  if ( rc != CA_ITER_OK ) {
931
1365
  ca_iter_state_finish(&st_in);
932
1366
  rb_raise(rb_eRuntimeError,
933
- "cumprod_ki: output init failed rc=%d", rc);
1367
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
934
1368
  }
935
1369
 
936
1370
  char *pi, *po;
@@ -965,14 +1399,14 @@ cumprod_ki_native_i64 (VALUE self, CArray *ca, int axis)
965
1399
  slab_axes, 1, 0);
966
1400
  if ( rc != CA_ITER_OK ) {
967
1401
  rb_raise(rb_eRuntimeError,
968
- "cumprod_ki: input init failed rc=%d", rc);
1402
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
969
1403
  }
970
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1404
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
971
1405
  slab_axes, 1, CA_KERNEL_WRITE);
972
1406
  if ( rc != CA_ITER_OK ) {
973
1407
  ca_iter_state_finish(&st_in);
974
1408
  rb_raise(rb_eRuntimeError,
975
- "cumprod_ki: output init failed rc=%d", rc);
1409
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
976
1410
  }
977
1411
 
978
1412
  char *pi, *po;
@@ -1007,14 +1441,14 @@ cumprod_ki_native_u64 (VALUE self, CArray *ca, int axis)
1007
1441
  slab_axes, 1, 0);
1008
1442
  if ( rc != CA_ITER_OK ) {
1009
1443
  rb_raise(rb_eRuntimeError,
1010
- "cumprod_ki: input init failed rc=%d", rc);
1444
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1011
1445
  }
1012
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1446
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1013
1447
  slab_axes, 1, CA_KERNEL_WRITE);
1014
1448
  if ( rc != CA_ITER_OK ) {
1015
1449
  ca_iter_state_finish(&st_in);
1016
1450
  rb_raise(rb_eRuntimeError,
1017
- "cumprod_ki: output init failed rc=%d", rc);
1451
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1018
1452
  }
1019
1453
 
1020
1454
  char *pi, *po;
@@ -1049,14 +1483,14 @@ cumprod_ki_native_f32 (VALUE self, CArray *ca, int axis)
1049
1483
  slab_axes, 1, 0);
1050
1484
  if ( rc != CA_ITER_OK ) {
1051
1485
  rb_raise(rb_eRuntimeError,
1052
- "cumprod_ki: input init failed rc=%d", rc);
1486
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1053
1487
  }
1054
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1488
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1055
1489
  slab_axes, 1, CA_KERNEL_WRITE);
1056
1490
  if ( rc != CA_ITER_OK ) {
1057
1491
  ca_iter_state_finish(&st_in);
1058
1492
  rb_raise(rb_eRuntimeError,
1059
- "cumprod_ki: output init failed rc=%d", rc);
1493
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1060
1494
  }
1061
1495
 
1062
1496
  char *pi, *po;
@@ -1091,14 +1525,14 @@ cumprod_ki_native_f64 (VALUE self, CArray *ca, int axis)
1091
1525
  slab_axes, 1, 0);
1092
1526
  if ( rc != CA_ITER_OK ) {
1093
1527
  rb_raise(rb_eRuntimeError,
1094
- "cumprod_ki: input init failed rc=%d", rc);
1528
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1095
1529
  }
1096
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1530
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1097
1531
  slab_axes, 1, CA_KERNEL_WRITE);
1098
1532
  if ( rc != CA_ITER_OK ) {
1099
1533
  ca_iter_state_finish(&st_in);
1100
1534
  rb_raise(rb_eRuntimeError,
1101
- "cumprod_ki: output init failed rc=%d", rc);
1535
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1102
1536
  }
1103
1537
 
1104
1538
  char *pi, *po;
@@ -1133,14 +1567,14 @@ cumprod_ki_native_cmplx64 (VALUE self, CArray *ca, int axis)
1133
1567
  slab_axes, 1, 0);
1134
1568
  if ( rc != CA_ITER_OK ) {
1135
1569
  rb_raise(rb_eRuntimeError,
1136
- "cumprod_ki: input init failed rc=%d", rc);
1570
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1137
1571
  }
1138
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1572
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1139
1573
  slab_axes, 1, CA_KERNEL_WRITE);
1140
1574
  if ( rc != CA_ITER_OK ) {
1141
1575
  ca_iter_state_finish(&st_in);
1142
1576
  rb_raise(rb_eRuntimeError,
1143
- "cumprod_ki: output init failed rc=%d", rc);
1577
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1144
1578
  }
1145
1579
 
1146
1580
  char *pi, *po;
@@ -1175,14 +1609,14 @@ cumprod_ki_native_cmplx128 (VALUE self, CArray *ca, int axis)
1175
1609
  slab_axes, 1, 0);
1176
1610
  if ( rc != CA_ITER_OK ) {
1177
1611
  rb_raise(rb_eRuntimeError,
1178
- "cumprod_ki: input init failed rc=%d", rc);
1612
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1179
1613
  }
1180
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1614
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1181
1615
  slab_axes, 1, CA_KERNEL_WRITE);
1182
1616
  if ( rc != CA_ITER_OK ) {
1183
1617
  ca_iter_state_finish(&st_in);
1184
1618
  rb_raise(rb_eRuntimeError,
1185
- "cumprod_ki: output init failed rc=%d", rc);
1619
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1186
1620
  }
1187
1621
 
1188
1622
  char *pi, *po;
@@ -1217,14 +1651,14 @@ cumprod_ki_native_bool (VALUE self, CArray *ca, int axis)
1217
1651
  slab_axes, 1, 0);
1218
1652
  if ( rc != CA_ITER_OK ) {
1219
1653
  rb_raise(rb_eRuntimeError,
1220
- "cumprod_ki: input init failed rc=%d", rc);
1654
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1221
1655
  }
1222
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1656
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1223
1657
  slab_axes, 1, CA_KERNEL_WRITE);
1224
1658
  if ( rc != CA_ITER_OK ) {
1225
1659
  ca_iter_state_finish(&st_in);
1226
1660
  rb_raise(rb_eRuntimeError,
1227
- "cumprod_ki: output init failed rc=%d", rc);
1661
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1228
1662
  }
1229
1663
 
1230
1664
  char *pi, *po;
@@ -1240,9 +1674,28 @@ cumprod_ki_native_bool (VALUE self, CArray *ca, int axis)
1240
1674
  return vout;
1241
1675
  }
1242
1676
 
1677
+ /* The object lane calls Ruby for every cell, so a walk can raise part
1678
+ way. Its states live in the caller's frame, and ca_iter_ensure
1679
+ finishes them however the body leaves. */
1680
+ typedef struct {
1681
+ ca_iter_state states[2];
1682
+ VALUE self;
1683
+ CArray *ca;
1684
+ int axis;
1685
+ } cumprod_ki_native_object_frame;
1686
+
1243
1687
  static VALUE
1244
- cumprod_ki_native_object (VALUE self, CArray *ca, int axis)
1688
+ cumprod_ki_native_object_body (VALUE arg)
1245
1689
  {
1690
+ cumprod_ki_native_object_frame *fr = (cumprod_ki_native_object_frame *) arg;
1691
+ VALUE self = fr->self;
1692
+ (void) self;
1693
+ CArray *ca = fr->ca;
1694
+ (void) ca;
1695
+ int axis = fr->axis;
1696
+ (void) axis;
1697
+ #define st_in (fr->states[0])
1698
+ #define st_out (fr->states[1])
1246
1699
  VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
1247
1700
  INT2NUM(sizeof(VALUE)));
1248
1701
  CArray *co;
@@ -1253,20 +1706,19 @@ cumprod_ki_native_object (VALUE self, CArray *ca, int axis)
1253
1706
  INIT inside the macro. */
1254
1707
  int8_t slab_axes[CA_RANK_MAX];
1255
1708
  slab_axes[0] = (int8_t) axis;
1256
- ca_iter_state st_in, st_out;
1257
1709
  int rc;
1258
1710
  rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1259
1711
  slab_axes, 1, 0);
1260
1712
  if ( rc != CA_ITER_OK ) {
1261
1713
  rb_raise(rb_eRuntimeError,
1262
- "cumprod_ki: input init failed rc=%d", rc);
1714
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1263
1715
  }
1264
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1716
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1265
1717
  slab_axes, 1, CA_KERNEL_WRITE);
1266
1718
  if ( rc != CA_ITER_OK ) {
1267
1719
  ca_iter_state_finish(&st_in);
1268
1720
  rb_raise(rb_eRuntimeError,
1269
- "cumprod_ki: output init failed rc=%d", rc);
1721
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1270
1722
  }
1271
1723
 
1272
1724
  char *pi, *po;
@@ -1280,70 +1732,85 @@ cumprod_ki_native_object (VALUE self, CArray *ca, int axis)
1280
1732
  ca_iter_state_finish(&st_in);
1281
1733
  ca_iter_state_finish(&st_out);
1282
1734
  return vout;
1735
+ #undef st_in
1736
+ #undef st_out
1283
1737
  }
1284
1738
 
1739
+ static VALUE
1740
+ cumprod_ki_native_object (VALUE self, CArray *ca, int axis)
1741
+ {
1742
+ cumprod_ki_native_object_frame fr;
1743
+ fr.self = self;
1744
+ fr.ca = ca;
1745
+ fr.axis = axis;
1746
+ return ca_iter_ensure(2, fr.states, cumprod_ki_native_object_body, (VALUE) &fr);
1747
+ }
1748
+
1749
+
1285
1750
  static VALUE
1286
1751
  rb_ca_cumprod_ki (int argc, VALUE *argv, VALUE self)
1287
1752
  {
1288
1753
  CArray *src;
1289
1754
  GetCArray(self, src);
1755
+ if ( ca_is_lazy_view(src) ) {
1756
+ volatile VALUE evaluated = ca_lazy_evaluated(self);
1757
+ if ( ! NIL_P(evaluated) ) {
1758
+ self = evaluated;
1759
+ GetCArray(self, src);
1760
+ }
1761
+ }
1290
1762
  volatile VALUE ropt = rb_pop_options(&argc, &argv);
1291
1763
  volatile VALUE raxis = Qnil;
1292
1764
  rb_scan_options(ropt, "axis", &raxis);
1293
1765
  if ( argc > 0 ) {
1294
- rb_raise(rb_eArgError, "cumprod_ki: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cumprod(axis: 0)", argc);
1766
+ rb_raise(rb_eArgError, "%s: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cumprod(axis: 0)", ca_calling_method_name(), argc);
1295
1767
  }
1296
1768
  if ( NIL_P(raxis) ) {
1297
1769
  volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
1298
1770
  CArray *fsrc;
1299
1771
  GetCArray(vflat, fsrc);
1300
1772
  switch ( fsrc->data_type ) {
1301
- case CA_INT8: return cumprod_ki_native_i8(vflat, fsrc, 0);
1302
- case CA_UINT8: return cumprod_ki_native_u8(vflat, fsrc, 0);
1303
- case CA_INT16: return cumprod_ki_native_i16(vflat, fsrc, 0);
1304
- case CA_UINT16: return cumprod_ki_native_u16(vflat, fsrc, 0);
1305
- case CA_INT32: return cumprod_ki_native_i32(vflat, fsrc, 0);
1306
- case CA_UINT32: return cumprod_ki_native_u32(vflat, fsrc, 0);
1307
- case CA_INT64: return cumprod_ki_native_i64(vflat, fsrc, 0);
1308
- case CA_UINT64: return cumprod_ki_native_u64(vflat, fsrc, 0);
1309
- case CA_FLOAT32: return cumprod_ki_native_f32(vflat, fsrc, 0);
1310
- case CA_FLOAT64: return cumprod_ki_native_f64(vflat, fsrc, 0);
1311
- case CA_CMPLX64: return cumprod_ki_native_cmplx64(vflat, fsrc, 0);
1312
- case CA_CMPLX128: return cumprod_ki_native_cmplx128(vflat, fsrc, 0);
1313
- case CA_BOOLEAN: return cumprod_ki_native_bool(vflat, fsrc, 0);
1314
- case CA_OBJECT: return cumprod_ki_native_object(vflat, fsrc, 0);
1773
+ case CA_INT8: CA_RETURN_KEEPING(vflat, cumprod_ki_native_i8(vflat, fsrc, 0));
1774
+ case CA_UINT8: CA_RETURN_KEEPING(vflat, cumprod_ki_native_u8(vflat, fsrc, 0));
1775
+ case CA_INT16: CA_RETURN_KEEPING(vflat, cumprod_ki_native_i16(vflat, fsrc, 0));
1776
+ case CA_UINT16: CA_RETURN_KEEPING(vflat, cumprod_ki_native_u16(vflat, fsrc, 0));
1777
+ case CA_INT32: CA_RETURN_KEEPING(vflat, cumprod_ki_native_i32(vflat, fsrc, 0));
1778
+ case CA_UINT32: CA_RETURN_KEEPING(vflat, cumprod_ki_native_u32(vflat, fsrc, 0));
1779
+ case CA_INT64: CA_RETURN_KEEPING(vflat, cumprod_ki_native_i64(vflat, fsrc, 0));
1780
+ case CA_UINT64: CA_RETURN_KEEPING(vflat, cumprod_ki_native_u64(vflat, fsrc, 0));
1781
+ case CA_FLOAT32: CA_RETURN_KEEPING(vflat, cumprod_ki_native_f32(vflat, fsrc, 0));
1782
+ case CA_FLOAT64: CA_RETURN_KEEPING(vflat, cumprod_ki_native_f64(vflat, fsrc, 0));
1783
+ case CA_CMPLX64: CA_RETURN_KEEPING(vflat, cumprod_ki_native_cmplx64(vflat, fsrc, 0));
1784
+ case CA_CMPLX128: CA_RETURN_KEEPING(vflat, cumprod_ki_native_cmplx128(vflat, fsrc, 0));
1785
+ case CA_BOOLEAN: CA_RETURN_KEEPING(vflat, cumprod_ki_native_bool(vflat, fsrc, 0));
1786
+ case CA_OBJECT: CA_RETURN_KEEPING(vflat, cumprod_ki_native_object(vflat, fsrc, 0));
1315
1787
  default:
1316
- rb_raise(rb_eCADataTypeError, "cumprod_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, cmplx64, cmplx128, bool, object)", ca_type_name[fsrc->data_type]);
1788
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
1789
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[fsrc->data_type]);
1317
1790
  }
1318
1791
  }
1319
1792
  if ( TYPE(raxis) == T_ARRAY ) {
1320
- rb_raise(rb_eArgError, "cumprod_ki: axis: must be Integer (got Array); multi-axis scan is semantically ambiguous, chain explicitly: a.cumprod(axis: 0).cumprod(axis: 1)");
1321
- }
1322
- if ( ! rb_obj_is_kind_of(raxis, rb_cInteger) ) {
1323
- rb_raise(rb_eTypeError, "cumprod_ki: axis: must be Integer (got %"PRIsVALUE")", rb_obj_class(raxis));
1324
- }
1325
- int axis = NUM2INT(raxis);
1326
- if ( axis < 0 ) axis += src->ndim;
1327
- if ( axis < 0 || axis >= src->ndim ) {
1328
- rb_raise(rb_eArgError, "cumprod_ki: axis %d out of range for ndim %d", NUM2INT(raxis), src->ndim);
1793
+ rb_raise(rb_eArgError, "%s: axis must be a single Integer (got Array); a scan over several axes is ambiguous, chain explicitly: a.cumprod(axis: 0).cumprod(axis: 1)", ca_calling_method_name());
1329
1794
  }
1795
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
1330
1796
  switch ( src->data_type ) {
1331
- case CA_INT8: return cumprod_ki_native_i8(self, src, axis);
1332
- case CA_UINT8: return cumprod_ki_native_u8(self, src, axis);
1333
- case CA_INT16: return cumprod_ki_native_i16(self, src, axis);
1334
- case CA_UINT16: return cumprod_ki_native_u16(self, src, axis);
1335
- case CA_INT32: return cumprod_ki_native_i32(self, src, axis);
1336
- case CA_UINT32: return cumprod_ki_native_u32(self, src, axis);
1337
- case CA_INT64: return cumprod_ki_native_i64(self, src, axis);
1338
- case CA_UINT64: return cumprod_ki_native_u64(self, src, axis);
1339
- case CA_FLOAT32: return cumprod_ki_native_f32(self, src, axis);
1340
- case CA_FLOAT64: return cumprod_ki_native_f64(self, src, axis);
1341
- case CA_CMPLX64: return cumprod_ki_native_cmplx64(self, src, axis);
1342
- case CA_CMPLX128: return cumprod_ki_native_cmplx128(self, src, axis);
1343
- case CA_BOOLEAN: return cumprod_ki_native_bool(self, src, axis);
1344
- case CA_OBJECT: return cumprod_ki_native_object(self, src, axis);
1797
+ case CA_INT8: CA_RETURN_KEEPING(self, cumprod_ki_native_i8(self, src, axis));
1798
+ case CA_UINT8: CA_RETURN_KEEPING(self, cumprod_ki_native_u8(self, src, axis));
1799
+ case CA_INT16: CA_RETURN_KEEPING(self, cumprod_ki_native_i16(self, src, axis));
1800
+ case CA_UINT16: CA_RETURN_KEEPING(self, cumprod_ki_native_u16(self, src, axis));
1801
+ case CA_INT32: CA_RETURN_KEEPING(self, cumprod_ki_native_i32(self, src, axis));
1802
+ case CA_UINT32: CA_RETURN_KEEPING(self, cumprod_ki_native_u32(self, src, axis));
1803
+ case CA_INT64: CA_RETURN_KEEPING(self, cumprod_ki_native_i64(self, src, axis));
1804
+ case CA_UINT64: CA_RETURN_KEEPING(self, cumprod_ki_native_u64(self, src, axis));
1805
+ case CA_FLOAT32: CA_RETURN_KEEPING(self, cumprod_ki_native_f32(self, src, axis));
1806
+ case CA_FLOAT64: CA_RETURN_KEEPING(self, cumprod_ki_native_f64(self, src, axis));
1807
+ case CA_CMPLX64: CA_RETURN_KEEPING(self, cumprod_ki_native_cmplx64(self, src, axis));
1808
+ case CA_CMPLX128: CA_RETURN_KEEPING(self, cumprod_ki_native_cmplx128(self, src, axis));
1809
+ case CA_BOOLEAN: CA_RETURN_KEEPING(self, cumprod_ki_native_bool(self, src, axis));
1810
+ case CA_OBJECT: CA_RETURN_KEEPING(self, cumprod_ki_native_object(self, src, axis));
1345
1811
  default:
1346
- rb_raise(rb_eCADataTypeError, "cumprod_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, cmplx64, cmplx128, bool, object)", ca_type_name[src->data_type]);
1812
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
1813
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
1347
1814
  }
1348
1815
  return Qnil; /* unreachable */
1349
1816
  }
@@ -1369,18 +1836,17 @@ cummax_ki_native_i8 (VALUE self, CArray *ca, int axis)
1369
1836
  slab_axes, 1, 0);
1370
1837
  if ( rc != CA_ITER_OK ) {
1371
1838
  rb_raise(rb_eRuntimeError,
1372
- "cummax_ki: input init failed rc=%d", rc);
1839
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1373
1840
  }
1374
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1841
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1375
1842
  slab_axes, 1, CA_KERNEL_WRITE);
1376
1843
  if ( rc != CA_ITER_OK ) {
1377
1844
  ca_iter_state_finish(&st_in);
1378
1845
  rb_raise(rb_eRuntimeError,
1379
- "cummax_ki: output init failed rc=%d", rc);
1846
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1380
1847
  }
1381
1848
 
1382
1849
  boolean8_t *op_mask = NULL;
1383
- char *co_root = (char *) co->ptr;
1384
1850
  if ( ca_has_mask(ca) ) {
1385
1851
  ca_create_mask(co);
1386
1852
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1391,7 +1857,7 @@ cummax_ki_native_i8 (VALUE self, CArray *ca, int axis)
1391
1857
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1392
1858
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1393
1859
  boolean8_t *mo_fiber = op_mask
1394
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
1860
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1395
1861
  : NULL;
1396
1862
  CA_SLAB_SCAN_T_GATED(int8_t, int8_t, st_in, pi, mi,
1397
1863
  st_out, po, mo_fiber, INT8_MIN, if (v > acc) acc = v; r = acc);
@@ -1421,18 +1887,17 @@ cummax_ki_native_u8 (VALUE self, CArray *ca, int axis)
1421
1887
  slab_axes, 1, 0);
1422
1888
  if ( rc != CA_ITER_OK ) {
1423
1889
  rb_raise(rb_eRuntimeError,
1424
- "cummax_ki: input init failed rc=%d", rc);
1890
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1425
1891
  }
1426
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1892
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1427
1893
  slab_axes, 1, CA_KERNEL_WRITE);
1428
1894
  if ( rc != CA_ITER_OK ) {
1429
1895
  ca_iter_state_finish(&st_in);
1430
1896
  rb_raise(rb_eRuntimeError,
1431
- "cummax_ki: output init failed rc=%d", rc);
1897
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1432
1898
  }
1433
1899
 
1434
1900
  boolean8_t *op_mask = NULL;
1435
- char *co_root = (char *) co->ptr;
1436
1901
  if ( ca_has_mask(ca) ) {
1437
1902
  ca_create_mask(co);
1438
1903
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1443,7 +1908,7 @@ cummax_ki_native_u8 (VALUE self, CArray *ca, int axis)
1443
1908
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1444
1909
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1445
1910
  boolean8_t *mo_fiber = op_mask
1446
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
1911
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1447
1912
  : NULL;
1448
1913
  CA_SLAB_SCAN_T_GATED(uint8_t, uint8_t, st_in, pi, mi,
1449
1914
  st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
@@ -1473,18 +1938,17 @@ cummax_ki_native_i16 (VALUE self, CArray *ca, int axis)
1473
1938
  slab_axes, 1, 0);
1474
1939
  if ( rc != CA_ITER_OK ) {
1475
1940
  rb_raise(rb_eRuntimeError,
1476
- "cummax_ki: input init failed rc=%d", rc);
1941
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1477
1942
  }
1478
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1943
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1479
1944
  slab_axes, 1, CA_KERNEL_WRITE);
1480
1945
  if ( rc != CA_ITER_OK ) {
1481
1946
  ca_iter_state_finish(&st_in);
1482
1947
  rb_raise(rb_eRuntimeError,
1483
- "cummax_ki: output init failed rc=%d", rc);
1948
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1484
1949
  }
1485
1950
 
1486
1951
  boolean8_t *op_mask = NULL;
1487
- char *co_root = (char *) co->ptr;
1488
1952
  if ( ca_has_mask(ca) ) {
1489
1953
  ca_create_mask(co);
1490
1954
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1495,7 +1959,7 @@ cummax_ki_native_i16 (VALUE self, CArray *ca, int axis)
1495
1959
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1496
1960
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1497
1961
  boolean8_t *mo_fiber = op_mask
1498
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
1962
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1499
1963
  : NULL;
1500
1964
  CA_SLAB_SCAN_T_GATED(int16_t, int16_t, st_in, pi, mi,
1501
1965
  st_out, po, mo_fiber, INT16_MIN, if (v > acc) acc = v; r = acc);
@@ -1525,18 +1989,17 @@ cummax_ki_native_u16 (VALUE self, CArray *ca, int axis)
1525
1989
  slab_axes, 1, 0);
1526
1990
  if ( rc != CA_ITER_OK ) {
1527
1991
  rb_raise(rb_eRuntimeError,
1528
- "cummax_ki: input init failed rc=%d", rc);
1992
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1529
1993
  }
1530
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
1994
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1531
1995
  slab_axes, 1, CA_KERNEL_WRITE);
1532
1996
  if ( rc != CA_ITER_OK ) {
1533
1997
  ca_iter_state_finish(&st_in);
1534
1998
  rb_raise(rb_eRuntimeError,
1535
- "cummax_ki: output init failed rc=%d", rc);
1999
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1536
2000
  }
1537
2001
 
1538
2002
  boolean8_t *op_mask = NULL;
1539
- char *co_root = (char *) co->ptr;
1540
2003
  if ( ca_has_mask(ca) ) {
1541
2004
  ca_create_mask(co);
1542
2005
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1547,7 +2010,7 @@ cummax_ki_native_u16 (VALUE self, CArray *ca, int axis)
1547
2010
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1548
2011
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1549
2012
  boolean8_t *mo_fiber = op_mask
1550
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2013
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1551
2014
  : NULL;
1552
2015
  CA_SLAB_SCAN_T_GATED(uint16_t, uint16_t, st_in, pi, mi,
1553
2016
  st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
@@ -1577,18 +2040,17 @@ cummax_ki_native_i32 (VALUE self, CArray *ca, int axis)
1577
2040
  slab_axes, 1, 0);
1578
2041
  if ( rc != CA_ITER_OK ) {
1579
2042
  rb_raise(rb_eRuntimeError,
1580
- "cummax_ki: input init failed rc=%d", rc);
2043
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1581
2044
  }
1582
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2045
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1583
2046
  slab_axes, 1, CA_KERNEL_WRITE);
1584
2047
  if ( rc != CA_ITER_OK ) {
1585
2048
  ca_iter_state_finish(&st_in);
1586
2049
  rb_raise(rb_eRuntimeError,
1587
- "cummax_ki: output init failed rc=%d", rc);
2050
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1588
2051
  }
1589
2052
 
1590
2053
  boolean8_t *op_mask = NULL;
1591
- char *co_root = (char *) co->ptr;
1592
2054
  if ( ca_has_mask(ca) ) {
1593
2055
  ca_create_mask(co);
1594
2056
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1599,7 +2061,7 @@ cummax_ki_native_i32 (VALUE self, CArray *ca, int axis)
1599
2061
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1600
2062
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1601
2063
  boolean8_t *mo_fiber = op_mask
1602
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2064
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1603
2065
  : NULL;
1604
2066
  CA_SLAB_SCAN_T_GATED(int32_t, int32_t, st_in, pi, mi,
1605
2067
  st_out, po, mo_fiber, INT32_MIN, if (v > acc) acc = v; r = acc);
@@ -1629,18 +2091,17 @@ cummax_ki_native_u32 (VALUE self, CArray *ca, int axis)
1629
2091
  slab_axes, 1, 0);
1630
2092
  if ( rc != CA_ITER_OK ) {
1631
2093
  rb_raise(rb_eRuntimeError,
1632
- "cummax_ki: input init failed rc=%d", rc);
2094
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1633
2095
  }
1634
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2096
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1635
2097
  slab_axes, 1, CA_KERNEL_WRITE);
1636
2098
  if ( rc != CA_ITER_OK ) {
1637
2099
  ca_iter_state_finish(&st_in);
1638
2100
  rb_raise(rb_eRuntimeError,
1639
- "cummax_ki: output init failed rc=%d", rc);
2101
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1640
2102
  }
1641
2103
 
1642
2104
  boolean8_t *op_mask = NULL;
1643
- char *co_root = (char *) co->ptr;
1644
2105
  if ( ca_has_mask(ca) ) {
1645
2106
  ca_create_mask(co);
1646
2107
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1651,7 +2112,7 @@ cummax_ki_native_u32 (VALUE self, CArray *ca, int axis)
1651
2112
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1652
2113
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1653
2114
  boolean8_t *mo_fiber = op_mask
1654
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2115
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1655
2116
  : NULL;
1656
2117
  CA_SLAB_SCAN_T_GATED(uint32_t, uint32_t, st_in, pi, mi,
1657
2118
  st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
@@ -1681,18 +2142,17 @@ cummax_ki_native_i64 (VALUE self, CArray *ca, int axis)
1681
2142
  slab_axes, 1, 0);
1682
2143
  if ( rc != CA_ITER_OK ) {
1683
2144
  rb_raise(rb_eRuntimeError,
1684
- "cummax_ki: input init failed rc=%d", rc);
2145
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1685
2146
  }
1686
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2147
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1687
2148
  slab_axes, 1, CA_KERNEL_WRITE);
1688
2149
  if ( rc != CA_ITER_OK ) {
1689
2150
  ca_iter_state_finish(&st_in);
1690
2151
  rb_raise(rb_eRuntimeError,
1691
- "cummax_ki: output init failed rc=%d", rc);
2152
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1692
2153
  }
1693
2154
 
1694
2155
  boolean8_t *op_mask = NULL;
1695
- char *co_root = (char *) co->ptr;
1696
2156
  if ( ca_has_mask(ca) ) {
1697
2157
  ca_create_mask(co);
1698
2158
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1703,7 +2163,7 @@ cummax_ki_native_i64 (VALUE self, CArray *ca, int axis)
1703
2163
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1704
2164
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1705
2165
  boolean8_t *mo_fiber = op_mask
1706
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2166
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1707
2167
  : NULL;
1708
2168
  CA_SLAB_SCAN_T_GATED(int64_t, int64_t, st_in, pi, mi,
1709
2169
  st_out, po, mo_fiber, INT64_MIN, if (v > acc) acc = v; r = acc);
@@ -1733,18 +2193,17 @@ cummax_ki_native_u64 (VALUE self, CArray *ca, int axis)
1733
2193
  slab_axes, 1, 0);
1734
2194
  if ( rc != CA_ITER_OK ) {
1735
2195
  rb_raise(rb_eRuntimeError,
1736
- "cummax_ki: input init failed rc=%d", rc);
2196
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1737
2197
  }
1738
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2198
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1739
2199
  slab_axes, 1, CA_KERNEL_WRITE);
1740
2200
  if ( rc != CA_ITER_OK ) {
1741
2201
  ca_iter_state_finish(&st_in);
1742
2202
  rb_raise(rb_eRuntimeError,
1743
- "cummax_ki: output init failed rc=%d", rc);
2203
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1744
2204
  }
1745
2205
 
1746
2206
  boolean8_t *op_mask = NULL;
1747
- char *co_root = (char *) co->ptr;
1748
2207
  if ( ca_has_mask(ca) ) {
1749
2208
  ca_create_mask(co);
1750
2209
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1755,7 +2214,7 @@ cummax_ki_native_u64 (VALUE self, CArray *ca, int axis)
1755
2214
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1756
2215
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1757
2216
  boolean8_t *mo_fiber = op_mask
1758
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2217
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1759
2218
  : NULL;
1760
2219
  CA_SLAB_SCAN_T_GATED(uint64_t, uint64_t, st_in, pi, mi,
1761
2220
  st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
@@ -1785,18 +2244,17 @@ cummax_ki_native_f32 (VALUE self, CArray *ca, int axis)
1785
2244
  slab_axes, 1, 0);
1786
2245
  if ( rc != CA_ITER_OK ) {
1787
2246
  rb_raise(rb_eRuntimeError,
1788
- "cummax_ki: input init failed rc=%d", rc);
2247
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1789
2248
  }
1790
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2249
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1791
2250
  slab_axes, 1, CA_KERNEL_WRITE);
1792
2251
  if ( rc != CA_ITER_OK ) {
1793
2252
  ca_iter_state_finish(&st_in);
1794
2253
  rb_raise(rb_eRuntimeError,
1795
- "cummax_ki: output init failed rc=%d", rc);
2254
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1796
2255
  }
1797
2256
 
1798
2257
  boolean8_t *op_mask = NULL;
1799
- char *co_root = (char *) co->ptr;
1800
2258
  if ( ca_has_mask(ca) ) {
1801
2259
  ca_create_mask(co);
1802
2260
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1807,7 +2265,7 @@ cummax_ki_native_f32 (VALUE self, CArray *ca, int axis)
1807
2265
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1808
2266
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1809
2267
  boolean8_t *mo_fiber = op_mask
1810
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2268
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1811
2269
  : NULL;
1812
2270
  CA_SLAB_SCAN_T_GATED(float, float, st_in, pi, mi,
1813
2271
  st_out, po, mo_fiber, NAN, acc = fmax(acc, v); r = acc);
@@ -1837,18 +2295,17 @@ cummax_ki_native_f64 (VALUE self, CArray *ca, int axis)
1837
2295
  slab_axes, 1, 0);
1838
2296
  if ( rc != CA_ITER_OK ) {
1839
2297
  rb_raise(rb_eRuntimeError,
1840
- "cummax_ki: input init failed rc=%d", rc);
2298
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1841
2299
  }
1842
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2300
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1843
2301
  slab_axes, 1, CA_KERNEL_WRITE);
1844
2302
  if ( rc != CA_ITER_OK ) {
1845
2303
  ca_iter_state_finish(&st_in);
1846
2304
  rb_raise(rb_eRuntimeError,
1847
- "cummax_ki: output init failed rc=%d", rc);
2305
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1848
2306
  }
1849
2307
 
1850
2308
  boolean8_t *op_mask = NULL;
1851
- char *co_root = (char *) co->ptr;
1852
2309
  if ( ca_has_mask(ca) ) {
1853
2310
  ca_create_mask(co);
1854
2311
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1859,7 +2316,7 @@ cummax_ki_native_f64 (VALUE self, CArray *ca, int axis)
1859
2316
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1860
2317
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1861
2318
  boolean8_t *mo_fiber = op_mask
1862
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2319
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1863
2320
  : NULL;
1864
2321
  CA_SLAB_SCAN_T_GATED(double, double, st_in, pi, mi,
1865
2322
  st_out, po, mo_fiber, NAN, acc = fmax(acc, v); r = acc);
@@ -1889,18 +2346,17 @@ cummax_ki_native_bool (VALUE self, CArray *ca, int axis)
1889
2346
  slab_axes, 1, 0);
1890
2347
  if ( rc != CA_ITER_OK ) {
1891
2348
  rb_raise(rb_eRuntimeError,
1892
- "cummax_ki: input init failed rc=%d", rc);
2349
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1893
2350
  }
1894
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2351
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1895
2352
  slab_axes, 1, CA_KERNEL_WRITE);
1896
2353
  if ( rc != CA_ITER_OK ) {
1897
2354
  ca_iter_state_finish(&st_in);
1898
2355
  rb_raise(rb_eRuntimeError,
1899
- "cummax_ki: output init failed rc=%d", rc);
2356
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1900
2357
  }
1901
2358
 
1902
2359
  boolean8_t *op_mask = NULL;
1903
- char *co_root = (char *) co->ptr;
1904
2360
  if ( ca_has_mask(ca) ) {
1905
2361
  ca_create_mask(co);
1906
2362
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1911,7 +2367,7 @@ cummax_ki_native_bool (VALUE self, CArray *ca, int axis)
1911
2367
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1912
2368
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1913
2369
  boolean8_t *mo_fiber = op_mask
1914
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2370
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1915
2371
  : NULL;
1916
2372
  CA_SLAB_SCAN_T_GATED(boolean8_t, uint64_t, st_in, pi, mi,
1917
2373
  st_out, po, mo_fiber, 0, if ((uint64_t) v > acc) acc = v; r = acc);
@@ -1922,9 +2378,28 @@ cummax_ki_native_bool (VALUE self, CArray *ca, int axis)
1922
2378
  return vout;
1923
2379
  }
1924
2380
 
2381
+ /* The object lane calls Ruby for every cell, so a walk can raise part
2382
+ way. Its states live in the caller's frame, and ca_iter_ensure
2383
+ finishes them however the body leaves. */
2384
+ typedef struct {
2385
+ ca_iter_state states[2];
2386
+ VALUE self;
2387
+ CArray *ca;
2388
+ int axis;
2389
+ } cummax_ki_native_object_frame;
2390
+
1925
2391
  static VALUE
1926
- cummax_ki_native_object (VALUE self, CArray *ca, int axis)
2392
+ cummax_ki_native_object_body (VALUE arg)
1927
2393
  {
2394
+ cummax_ki_native_object_frame *fr = (cummax_ki_native_object_frame *) arg;
2395
+ VALUE self = fr->self;
2396
+ (void) self;
2397
+ CArray *ca = fr->ca;
2398
+ (void) ca;
2399
+ int axis = fr->axis;
2400
+ (void) axis;
2401
+ #define st_in (fr->states[0])
2402
+ #define st_out (fr->states[1])
1928
2403
  VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
1929
2404
  INT2NUM(sizeof(VALUE)));
1930
2405
  CArray *co;
@@ -1935,24 +2410,22 @@ cummax_ki_native_object (VALUE self, CArray *ca, int axis)
1935
2410
  INIT inside the macro. */
1936
2411
  int8_t slab_axes[CA_RANK_MAX];
1937
2412
  slab_axes[0] = (int8_t) axis;
1938
- ca_iter_state st_in, st_out;
1939
2413
  int rc;
1940
2414
  rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1941
2415
  slab_axes, 1, 0);
1942
2416
  if ( rc != CA_ITER_OK ) {
1943
2417
  rb_raise(rb_eRuntimeError,
1944
- "cummax_ki: input init failed rc=%d", rc);
2418
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1945
2419
  }
1946
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2420
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1947
2421
  slab_axes, 1, CA_KERNEL_WRITE);
1948
2422
  if ( rc != CA_ITER_OK ) {
1949
2423
  ca_iter_state_finish(&st_in);
1950
2424
  rb_raise(rb_eRuntimeError,
1951
- "cummax_ki: output init failed rc=%d", rc);
2425
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1952
2426
  }
1953
2427
 
1954
2428
  boolean8_t *op_mask = NULL;
1955
- char *co_root = (char *) co->ptr;
1956
2429
  if ( ca_has_mask(ca) ) {
1957
2430
  ca_create_mask(co);
1958
2431
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -1963,75 +2436,143 @@ cummax_ki_native_object (VALUE self, CArray *ca, int axis)
1963
2436
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1964
2437
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1965
2438
  boolean8_t *mo_fiber = op_mask
1966
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2439
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1967
2440
  : NULL;
1968
2441
  CA_SLAB_SCAN_T_GATED(VALUE, VALUE, st_in, pi, mi,
1969
- st_out, po, mo_fiber, Qnil, if (acc == Qnil) acc = v; else if (RTEST(rb_funcall(v, rb_intern(">"), 1, acc))) acc = v; r = acc);
2442
+ st_out, po, mo_fiber, Qnil, if (acc == Qnil || ca_obj_extremum_replaces(v, acc, rb_intern(">"))) acc = v; r = acc);
1970
2443
  ca_iter_state_sync_slab(&st_out);
1971
2444
  }
1972
2445
  ca_iter_state_finish(&st_in);
1973
2446
  ca_iter_state_finish(&st_out);
1974
2447
  return vout;
2448
+ #undef st_in
2449
+ #undef st_out
1975
2450
  }
1976
2451
 
2452
+ static VALUE
2453
+ cummax_ki_native_object (VALUE self, CArray *ca, int axis)
2454
+ {
2455
+ cummax_ki_native_object_frame fr;
2456
+ fr.self = self;
2457
+ fr.ca = ca;
2458
+ fr.axis = axis;
2459
+ return ca_iter_ensure(2, fr.states, cummax_ki_native_object_body, (VALUE) &fr);
2460
+ }
2461
+
2462
+
2463
+ static VALUE rb_ca_cummax_ki_storage (int argc, VALUE *argv, VALUE self);
2464
+
1977
2465
  static VALUE
1978
2466
  rb_ca_cummax_ki (int argc, VALUE *argv, VALUE self)
1979
2467
  {
1980
2468
  CArray *src;
2469
+ VALUE result;
1981
2470
  GetCArray(self, src);
2471
+ volatile VALUE _reduce_face = Qnil; /* original Face, for output re-lift */
2472
+ if ( ca_is_face(src) ) {
2473
+ VALUE _face = self;
2474
+ VALUE _st;
2475
+ CArray *_sc;
2476
+ ca_face_require_orderable(_face, ca_calling_method_name(), "order");
2477
+ _st = rb_ca_strip_face_value(self);
2478
+ GetCArray(_st, _sc);
2479
+ _reduce_face = _face;
2480
+ self = _st;
2481
+ src = _sc;
2482
+ }
2483
+ result = rb_ca_cummax_ki_storage(argc, argv, self);
2484
+ if ( _reduce_face != Qnil && RB_TYPE_P(result, T_ARRAY) ) {
2485
+ /* a multi-output reduction (minmax): re-lift each output. */
2486
+ long _i;
2487
+ for ( _i = 0; _i < RARRAY_LEN(result); _i++ ) {
2488
+ VALUE _r = rb_ary_entry(result, _i);
2489
+ if ( _r == CA_UNDEF || _r == Qnil ) continue;
2490
+ if ( rb_obj_is_kind_of(_r, rb_cCArray) ) {
2491
+ _r = ca_face_relift_entity(_reduce_face, _r);
2492
+ }
2493
+ else {
2494
+ CArray *_fca;
2495
+ GetCArray(_reduce_face, _fca);
2496
+ CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(_r, _reduce_face, _fca);
2497
+ }
2498
+ rb_ary_store(result, _i, _r);
2499
+ }
2500
+ }
2501
+ else if ( _reduce_face != Qnil && result != CA_UNDEF && result != Qnil ) {
2502
+ if ( rb_obj_is_kind_of(result, rb_cCArray) ) {
2503
+ /* per-axis: re-lift the storage result as a Face of the same class. */
2504
+ result = ca_face_relift_entity(_reduce_face, result);
2505
+ }
2506
+ else {
2507
+ /* full reduction: decode the scalar via the registered hook. */
2508
+ CArray *_fca;
2509
+ GetCArray(_reduce_face, _fca);
2510
+ CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(result, _reduce_face, _fca);
2511
+ }
2512
+ }
2513
+ return result;
2514
+ }
2515
+
2516
+ static VALUE
2517
+ rb_ca_cummax_ki_storage (int argc, VALUE *argv, VALUE self)
2518
+ {
2519
+ CArray *src;
2520
+ GetCArray(self, src);
2521
+ if ( ca_is_lazy_view(src) ) {
2522
+ volatile VALUE evaluated = ca_lazy_evaluated(self);
2523
+ if ( ! NIL_P(evaluated) ) {
2524
+ self = evaluated;
2525
+ GetCArray(self, src);
2526
+ }
2527
+ }
1982
2528
  volatile VALUE ropt = rb_pop_options(&argc, &argv);
1983
2529
  volatile VALUE raxis = Qnil;
1984
2530
  rb_scan_options(ropt, "axis", &raxis);
1985
2531
  if ( argc > 0 ) {
1986
- rb_raise(rb_eArgError, "cummax_ki: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cummax(axis: 0)", argc);
2532
+ rb_raise(rb_eArgError, "%s: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cummax(axis: 0)", ca_calling_method_name(), argc);
1987
2533
  }
1988
2534
  if ( NIL_P(raxis) ) {
1989
2535
  volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
1990
2536
  CArray *fsrc;
1991
2537
  GetCArray(vflat, fsrc);
1992
2538
  switch ( fsrc->data_type ) {
1993
- case CA_INT8: return cummax_ki_native_i8(vflat, fsrc, 0);
1994
- case CA_UINT8: return cummax_ki_native_u8(vflat, fsrc, 0);
1995
- case CA_INT16: return cummax_ki_native_i16(vflat, fsrc, 0);
1996
- case CA_UINT16: return cummax_ki_native_u16(vflat, fsrc, 0);
1997
- case CA_INT32: return cummax_ki_native_i32(vflat, fsrc, 0);
1998
- case CA_UINT32: return cummax_ki_native_u32(vflat, fsrc, 0);
1999
- case CA_INT64: return cummax_ki_native_i64(vflat, fsrc, 0);
2000
- case CA_UINT64: return cummax_ki_native_u64(vflat, fsrc, 0);
2001
- case CA_FLOAT32: return cummax_ki_native_f32(vflat, fsrc, 0);
2002
- case CA_FLOAT64: return cummax_ki_native_f64(vflat, fsrc, 0);
2003
- case CA_BOOLEAN: return cummax_ki_native_bool(vflat, fsrc, 0);
2004
- case CA_OBJECT: return cummax_ki_native_object(vflat, fsrc, 0);
2539
+ case CA_INT8: CA_RETURN_KEEPING(vflat, cummax_ki_native_i8(vflat, fsrc, 0));
2540
+ case CA_UINT8: CA_RETURN_KEEPING(vflat, cummax_ki_native_u8(vflat, fsrc, 0));
2541
+ case CA_INT16: CA_RETURN_KEEPING(vflat, cummax_ki_native_i16(vflat, fsrc, 0));
2542
+ case CA_UINT16: CA_RETURN_KEEPING(vflat, cummax_ki_native_u16(vflat, fsrc, 0));
2543
+ case CA_INT32: CA_RETURN_KEEPING(vflat, cummax_ki_native_i32(vflat, fsrc, 0));
2544
+ case CA_UINT32: CA_RETURN_KEEPING(vflat, cummax_ki_native_u32(vflat, fsrc, 0));
2545
+ case CA_INT64: CA_RETURN_KEEPING(vflat, cummax_ki_native_i64(vflat, fsrc, 0));
2546
+ case CA_UINT64: CA_RETURN_KEEPING(vflat, cummax_ki_native_u64(vflat, fsrc, 0));
2547
+ case CA_FLOAT32: CA_RETURN_KEEPING(vflat, cummax_ki_native_f32(vflat, fsrc, 0));
2548
+ case CA_FLOAT64: CA_RETURN_KEEPING(vflat, cummax_ki_native_f64(vflat, fsrc, 0));
2549
+ case CA_BOOLEAN: CA_RETURN_KEEPING(vflat, cummax_ki_native_bool(vflat, fsrc, 0));
2550
+ case CA_OBJECT: CA_RETURN_KEEPING(vflat, cummax_ki_native_object(vflat, fsrc, 0));
2005
2551
  default:
2006
- rb_raise(rb_eCADataTypeError, "cummax_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, bool, object)", ca_type_name[fsrc->data_type]);
2552
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
2553
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, boolean, object)", ca_calling_method_name(), ca_type_name[fsrc->data_type]);
2007
2554
  }
2008
2555
  }
2009
2556
  if ( TYPE(raxis) == T_ARRAY ) {
2010
- rb_raise(rb_eArgError, "cummax_ki: axis: must be Integer (got Array); multi-axis scan is semantically ambiguous, chain explicitly: a.cummax(axis: 0).cummax(axis: 1)");
2011
- }
2012
- if ( ! rb_obj_is_kind_of(raxis, rb_cInteger) ) {
2013
- rb_raise(rb_eTypeError, "cummax_ki: axis: must be Integer (got %"PRIsVALUE")", rb_obj_class(raxis));
2014
- }
2015
- int axis = NUM2INT(raxis);
2016
- if ( axis < 0 ) axis += src->ndim;
2017
- if ( axis < 0 || axis >= src->ndim ) {
2018
- rb_raise(rb_eArgError, "cummax_ki: axis %d out of range for ndim %d", NUM2INT(raxis), src->ndim);
2557
+ rb_raise(rb_eArgError, "%s: axis must be a single Integer (got Array); a scan over several axes is ambiguous, chain explicitly: a.cummax(axis: 0).cummax(axis: 1)", ca_calling_method_name());
2019
2558
  }
2559
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
2020
2560
  switch ( src->data_type ) {
2021
- case CA_INT8: return cummax_ki_native_i8(self, src, axis);
2022
- case CA_UINT8: return cummax_ki_native_u8(self, src, axis);
2023
- case CA_INT16: return cummax_ki_native_i16(self, src, axis);
2024
- case CA_UINT16: return cummax_ki_native_u16(self, src, axis);
2025
- case CA_INT32: return cummax_ki_native_i32(self, src, axis);
2026
- case CA_UINT32: return cummax_ki_native_u32(self, src, axis);
2027
- case CA_INT64: return cummax_ki_native_i64(self, src, axis);
2028
- case CA_UINT64: return cummax_ki_native_u64(self, src, axis);
2029
- case CA_FLOAT32: return cummax_ki_native_f32(self, src, axis);
2030
- case CA_FLOAT64: return cummax_ki_native_f64(self, src, axis);
2031
- case CA_BOOLEAN: return cummax_ki_native_bool(self, src, axis);
2032
- case CA_OBJECT: return cummax_ki_native_object(self, src, axis);
2561
+ case CA_INT8: CA_RETURN_KEEPING(self, cummax_ki_native_i8(self, src, axis));
2562
+ case CA_UINT8: CA_RETURN_KEEPING(self, cummax_ki_native_u8(self, src, axis));
2563
+ case CA_INT16: CA_RETURN_KEEPING(self, cummax_ki_native_i16(self, src, axis));
2564
+ case CA_UINT16: CA_RETURN_KEEPING(self, cummax_ki_native_u16(self, src, axis));
2565
+ case CA_INT32: CA_RETURN_KEEPING(self, cummax_ki_native_i32(self, src, axis));
2566
+ case CA_UINT32: CA_RETURN_KEEPING(self, cummax_ki_native_u32(self, src, axis));
2567
+ case CA_INT64: CA_RETURN_KEEPING(self, cummax_ki_native_i64(self, src, axis));
2568
+ case CA_UINT64: CA_RETURN_KEEPING(self, cummax_ki_native_u64(self, src, axis));
2569
+ case CA_FLOAT32: CA_RETURN_KEEPING(self, cummax_ki_native_f32(self, src, axis));
2570
+ case CA_FLOAT64: CA_RETURN_KEEPING(self, cummax_ki_native_f64(self, src, axis));
2571
+ case CA_BOOLEAN: CA_RETURN_KEEPING(self, cummax_ki_native_bool(self, src, axis));
2572
+ case CA_OBJECT: CA_RETURN_KEEPING(self, cummax_ki_native_object(self, src, axis));
2033
2573
  default:
2034
- rb_raise(rb_eCADataTypeError, "cummax_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, bool, object)", ca_type_name[src->data_type]);
2574
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
2575
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
2035
2576
  }
2036
2577
  return Qnil; /* unreachable */
2037
2578
  }
@@ -2057,18 +2598,17 @@ cummin_ki_native_i8 (VALUE self, CArray *ca, int axis)
2057
2598
  slab_axes, 1, 0);
2058
2599
  if ( rc != CA_ITER_OK ) {
2059
2600
  rb_raise(rb_eRuntimeError,
2060
- "cummin_ki: input init failed rc=%d", rc);
2601
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2061
2602
  }
2062
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2603
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2063
2604
  slab_axes, 1, CA_KERNEL_WRITE);
2064
2605
  if ( rc != CA_ITER_OK ) {
2065
2606
  ca_iter_state_finish(&st_in);
2066
2607
  rb_raise(rb_eRuntimeError,
2067
- "cummin_ki: output init failed rc=%d", rc);
2608
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2068
2609
  }
2069
2610
 
2070
2611
  boolean8_t *op_mask = NULL;
2071
- char *co_root = (char *) co->ptr;
2072
2612
  if ( ca_has_mask(ca) ) {
2073
2613
  ca_create_mask(co);
2074
2614
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2079,7 +2619,7 @@ cummin_ki_native_i8 (VALUE self, CArray *ca, int axis)
2079
2619
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2080
2620
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2081
2621
  boolean8_t *mo_fiber = op_mask
2082
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2622
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2083
2623
  : NULL;
2084
2624
  CA_SLAB_SCAN_T_GATED(int8_t, int8_t, st_in, pi, mi,
2085
2625
  st_out, po, mo_fiber, INT8_MAX, if (v < acc) acc = v; r = acc);
@@ -2109,18 +2649,17 @@ cummin_ki_native_u8 (VALUE self, CArray *ca, int axis)
2109
2649
  slab_axes, 1, 0);
2110
2650
  if ( rc != CA_ITER_OK ) {
2111
2651
  rb_raise(rb_eRuntimeError,
2112
- "cummin_ki: input init failed rc=%d", rc);
2652
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2113
2653
  }
2114
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2654
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2115
2655
  slab_axes, 1, CA_KERNEL_WRITE);
2116
2656
  if ( rc != CA_ITER_OK ) {
2117
2657
  ca_iter_state_finish(&st_in);
2118
2658
  rb_raise(rb_eRuntimeError,
2119
- "cummin_ki: output init failed rc=%d", rc);
2659
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2120
2660
  }
2121
2661
 
2122
2662
  boolean8_t *op_mask = NULL;
2123
- char *co_root = (char *) co->ptr;
2124
2663
  if ( ca_has_mask(ca) ) {
2125
2664
  ca_create_mask(co);
2126
2665
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2131,7 +2670,7 @@ cummin_ki_native_u8 (VALUE self, CArray *ca, int axis)
2131
2670
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2132
2671
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2133
2672
  boolean8_t *mo_fiber = op_mask
2134
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2673
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2135
2674
  : NULL;
2136
2675
  CA_SLAB_SCAN_T_GATED(uint8_t, uint8_t, st_in, pi, mi,
2137
2676
  st_out, po, mo_fiber, UINT8_MAX, if (v < acc) acc = v; r = acc);
@@ -2161,18 +2700,17 @@ cummin_ki_native_i16 (VALUE self, CArray *ca, int axis)
2161
2700
  slab_axes, 1, 0);
2162
2701
  if ( rc != CA_ITER_OK ) {
2163
2702
  rb_raise(rb_eRuntimeError,
2164
- "cummin_ki: input init failed rc=%d", rc);
2703
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2165
2704
  }
2166
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2705
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2167
2706
  slab_axes, 1, CA_KERNEL_WRITE);
2168
2707
  if ( rc != CA_ITER_OK ) {
2169
2708
  ca_iter_state_finish(&st_in);
2170
2709
  rb_raise(rb_eRuntimeError,
2171
- "cummin_ki: output init failed rc=%d", rc);
2710
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2172
2711
  }
2173
2712
 
2174
2713
  boolean8_t *op_mask = NULL;
2175
- char *co_root = (char *) co->ptr;
2176
2714
  if ( ca_has_mask(ca) ) {
2177
2715
  ca_create_mask(co);
2178
2716
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2183,7 +2721,7 @@ cummin_ki_native_i16 (VALUE self, CArray *ca, int axis)
2183
2721
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2184
2722
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2185
2723
  boolean8_t *mo_fiber = op_mask
2186
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2724
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2187
2725
  : NULL;
2188
2726
  CA_SLAB_SCAN_T_GATED(int16_t, int16_t, st_in, pi, mi,
2189
2727
  st_out, po, mo_fiber, INT16_MAX, if (v < acc) acc = v; r = acc);
@@ -2213,18 +2751,17 @@ cummin_ki_native_u16 (VALUE self, CArray *ca, int axis)
2213
2751
  slab_axes, 1, 0);
2214
2752
  if ( rc != CA_ITER_OK ) {
2215
2753
  rb_raise(rb_eRuntimeError,
2216
- "cummin_ki: input init failed rc=%d", rc);
2754
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2217
2755
  }
2218
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2756
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2219
2757
  slab_axes, 1, CA_KERNEL_WRITE);
2220
2758
  if ( rc != CA_ITER_OK ) {
2221
2759
  ca_iter_state_finish(&st_in);
2222
2760
  rb_raise(rb_eRuntimeError,
2223
- "cummin_ki: output init failed rc=%d", rc);
2761
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2224
2762
  }
2225
2763
 
2226
2764
  boolean8_t *op_mask = NULL;
2227
- char *co_root = (char *) co->ptr;
2228
2765
  if ( ca_has_mask(ca) ) {
2229
2766
  ca_create_mask(co);
2230
2767
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2235,7 +2772,7 @@ cummin_ki_native_u16 (VALUE self, CArray *ca, int axis)
2235
2772
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2236
2773
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2237
2774
  boolean8_t *mo_fiber = op_mask
2238
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2775
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2239
2776
  : NULL;
2240
2777
  CA_SLAB_SCAN_T_GATED(uint16_t, uint16_t, st_in, pi, mi,
2241
2778
  st_out, po, mo_fiber, UINT16_MAX, if (v < acc) acc = v; r = acc);
@@ -2265,18 +2802,17 @@ cummin_ki_native_i32 (VALUE self, CArray *ca, int axis)
2265
2802
  slab_axes, 1, 0);
2266
2803
  if ( rc != CA_ITER_OK ) {
2267
2804
  rb_raise(rb_eRuntimeError,
2268
- "cummin_ki: input init failed rc=%d", rc);
2805
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2269
2806
  }
2270
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2807
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2271
2808
  slab_axes, 1, CA_KERNEL_WRITE);
2272
2809
  if ( rc != CA_ITER_OK ) {
2273
2810
  ca_iter_state_finish(&st_in);
2274
2811
  rb_raise(rb_eRuntimeError,
2275
- "cummin_ki: output init failed rc=%d", rc);
2812
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2276
2813
  }
2277
2814
 
2278
2815
  boolean8_t *op_mask = NULL;
2279
- char *co_root = (char *) co->ptr;
2280
2816
  if ( ca_has_mask(ca) ) {
2281
2817
  ca_create_mask(co);
2282
2818
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2287,7 +2823,7 @@ cummin_ki_native_i32 (VALUE self, CArray *ca, int axis)
2287
2823
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2288
2824
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2289
2825
  boolean8_t *mo_fiber = op_mask
2290
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2826
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2291
2827
  : NULL;
2292
2828
  CA_SLAB_SCAN_T_GATED(int32_t, int32_t, st_in, pi, mi,
2293
2829
  st_out, po, mo_fiber, INT32_MAX, if (v < acc) acc = v; r = acc);
@@ -2317,18 +2853,17 @@ cummin_ki_native_u32 (VALUE self, CArray *ca, int axis)
2317
2853
  slab_axes, 1, 0);
2318
2854
  if ( rc != CA_ITER_OK ) {
2319
2855
  rb_raise(rb_eRuntimeError,
2320
- "cummin_ki: input init failed rc=%d", rc);
2856
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2321
2857
  }
2322
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2858
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2323
2859
  slab_axes, 1, CA_KERNEL_WRITE);
2324
2860
  if ( rc != CA_ITER_OK ) {
2325
2861
  ca_iter_state_finish(&st_in);
2326
2862
  rb_raise(rb_eRuntimeError,
2327
- "cummin_ki: output init failed rc=%d", rc);
2863
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2328
2864
  }
2329
2865
 
2330
2866
  boolean8_t *op_mask = NULL;
2331
- char *co_root = (char *) co->ptr;
2332
2867
  if ( ca_has_mask(ca) ) {
2333
2868
  ca_create_mask(co);
2334
2869
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2339,7 +2874,7 @@ cummin_ki_native_u32 (VALUE self, CArray *ca, int axis)
2339
2874
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2340
2875
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2341
2876
  boolean8_t *mo_fiber = op_mask
2342
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2877
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2343
2878
  : NULL;
2344
2879
  CA_SLAB_SCAN_T_GATED(uint32_t, uint32_t, st_in, pi, mi,
2345
2880
  st_out, po, mo_fiber, UINT32_MAX, if (v < acc) acc = v; r = acc);
@@ -2369,18 +2904,17 @@ cummin_ki_native_i64 (VALUE self, CArray *ca, int axis)
2369
2904
  slab_axes, 1, 0);
2370
2905
  if ( rc != CA_ITER_OK ) {
2371
2906
  rb_raise(rb_eRuntimeError,
2372
- "cummin_ki: input init failed rc=%d", rc);
2907
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2373
2908
  }
2374
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2909
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2375
2910
  slab_axes, 1, CA_KERNEL_WRITE);
2376
2911
  if ( rc != CA_ITER_OK ) {
2377
2912
  ca_iter_state_finish(&st_in);
2378
2913
  rb_raise(rb_eRuntimeError,
2379
- "cummin_ki: output init failed rc=%d", rc);
2914
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2380
2915
  }
2381
2916
 
2382
2917
  boolean8_t *op_mask = NULL;
2383
- char *co_root = (char *) co->ptr;
2384
2918
  if ( ca_has_mask(ca) ) {
2385
2919
  ca_create_mask(co);
2386
2920
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2391,7 +2925,7 @@ cummin_ki_native_i64 (VALUE self, CArray *ca, int axis)
2391
2925
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2392
2926
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2393
2927
  boolean8_t *mo_fiber = op_mask
2394
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2928
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2395
2929
  : NULL;
2396
2930
  CA_SLAB_SCAN_T_GATED(int64_t, int64_t, st_in, pi, mi,
2397
2931
  st_out, po, mo_fiber, INT64_MAX, if (v < acc) acc = v; r = acc);
@@ -2421,18 +2955,17 @@ cummin_ki_native_u64 (VALUE self, CArray *ca, int axis)
2421
2955
  slab_axes, 1, 0);
2422
2956
  if ( rc != CA_ITER_OK ) {
2423
2957
  rb_raise(rb_eRuntimeError,
2424
- "cummin_ki: input init failed rc=%d", rc);
2958
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2425
2959
  }
2426
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
2960
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2427
2961
  slab_axes, 1, CA_KERNEL_WRITE);
2428
2962
  if ( rc != CA_ITER_OK ) {
2429
2963
  ca_iter_state_finish(&st_in);
2430
2964
  rb_raise(rb_eRuntimeError,
2431
- "cummin_ki: output init failed rc=%d", rc);
2965
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2432
2966
  }
2433
2967
 
2434
2968
  boolean8_t *op_mask = NULL;
2435
- char *co_root = (char *) co->ptr;
2436
2969
  if ( ca_has_mask(ca) ) {
2437
2970
  ca_create_mask(co);
2438
2971
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2443,7 +2976,7 @@ cummin_ki_native_u64 (VALUE self, CArray *ca, int axis)
2443
2976
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2444
2977
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2445
2978
  boolean8_t *mo_fiber = op_mask
2446
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
2979
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2447
2980
  : NULL;
2448
2981
  CA_SLAB_SCAN_T_GATED(uint64_t, uint64_t, st_in, pi, mi,
2449
2982
  st_out, po, mo_fiber, UINT64_MAX, if (v < acc) acc = v; r = acc);
@@ -2473,18 +3006,17 @@ cummin_ki_native_f32 (VALUE self, CArray *ca, int axis)
2473
3006
  slab_axes, 1, 0);
2474
3007
  if ( rc != CA_ITER_OK ) {
2475
3008
  rb_raise(rb_eRuntimeError,
2476
- "cummin_ki: input init failed rc=%d", rc);
3009
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2477
3010
  }
2478
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3011
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2479
3012
  slab_axes, 1, CA_KERNEL_WRITE);
2480
3013
  if ( rc != CA_ITER_OK ) {
2481
3014
  ca_iter_state_finish(&st_in);
2482
3015
  rb_raise(rb_eRuntimeError,
2483
- "cummin_ki: output init failed rc=%d", rc);
3016
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2484
3017
  }
2485
3018
 
2486
3019
  boolean8_t *op_mask = NULL;
2487
- char *co_root = (char *) co->ptr;
2488
3020
  if ( ca_has_mask(ca) ) {
2489
3021
  ca_create_mask(co);
2490
3022
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2495,7 +3027,7 @@ cummin_ki_native_f32 (VALUE self, CArray *ca, int axis)
2495
3027
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2496
3028
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2497
3029
  boolean8_t *mo_fiber = op_mask
2498
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
3030
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2499
3031
  : NULL;
2500
3032
  CA_SLAB_SCAN_T_GATED(float, float, st_in, pi, mi,
2501
3033
  st_out, po, mo_fiber, NAN, acc = fmin(acc, v); r = acc);
@@ -2525,18 +3057,17 @@ cummin_ki_native_f64 (VALUE self, CArray *ca, int axis)
2525
3057
  slab_axes, 1, 0);
2526
3058
  if ( rc != CA_ITER_OK ) {
2527
3059
  rb_raise(rb_eRuntimeError,
2528
- "cummin_ki: input init failed rc=%d", rc);
3060
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2529
3061
  }
2530
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3062
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2531
3063
  slab_axes, 1, CA_KERNEL_WRITE);
2532
3064
  if ( rc != CA_ITER_OK ) {
2533
3065
  ca_iter_state_finish(&st_in);
2534
3066
  rb_raise(rb_eRuntimeError,
2535
- "cummin_ki: output init failed rc=%d", rc);
3067
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2536
3068
  }
2537
3069
 
2538
3070
  boolean8_t *op_mask = NULL;
2539
- char *co_root = (char *) co->ptr;
2540
3071
  if ( ca_has_mask(ca) ) {
2541
3072
  ca_create_mask(co);
2542
3073
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2547,7 +3078,7 @@ cummin_ki_native_f64 (VALUE self, CArray *ca, int axis)
2547
3078
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2548
3079
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2549
3080
  boolean8_t *mo_fiber = op_mask
2550
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
3081
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2551
3082
  : NULL;
2552
3083
  CA_SLAB_SCAN_T_GATED(double, double, st_in, pi, mi,
2553
3084
  st_out, po, mo_fiber, NAN, acc = fmin(acc, v); r = acc);
@@ -2577,18 +3108,17 @@ cummin_ki_native_bool (VALUE self, CArray *ca, int axis)
2577
3108
  slab_axes, 1, 0);
2578
3109
  if ( rc != CA_ITER_OK ) {
2579
3110
  rb_raise(rb_eRuntimeError,
2580
- "cummin_ki: input init failed rc=%d", rc);
3111
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2581
3112
  }
2582
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3113
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2583
3114
  slab_axes, 1, CA_KERNEL_WRITE);
2584
3115
  if ( rc != CA_ITER_OK ) {
2585
3116
  ca_iter_state_finish(&st_in);
2586
3117
  rb_raise(rb_eRuntimeError,
2587
- "cummin_ki: output init failed rc=%d", rc);
3118
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2588
3119
  }
2589
3120
 
2590
3121
  boolean8_t *op_mask = NULL;
2591
- char *co_root = (char *) co->ptr;
2592
3122
  if ( ca_has_mask(ca) ) {
2593
3123
  ca_create_mask(co);
2594
3124
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2599,7 +3129,7 @@ cummin_ki_native_bool (VALUE self, CArray *ca, int axis)
2599
3129
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2600
3130
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2601
3131
  boolean8_t *mo_fiber = op_mask
2602
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
3132
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2603
3133
  : NULL;
2604
3134
  CA_SLAB_SCAN_T_GATED(boolean8_t, uint64_t, st_in, pi, mi,
2605
3135
  st_out, po, mo_fiber, 1, if ((uint64_t) v < acc) acc = v; r = acc);
@@ -2610,9 +3140,28 @@ cummin_ki_native_bool (VALUE self, CArray *ca, int axis)
2610
3140
  return vout;
2611
3141
  }
2612
3142
 
3143
+ /* The object lane calls Ruby for every cell, so a walk can raise part
3144
+ way. Its states live in the caller's frame, and ca_iter_ensure
3145
+ finishes them however the body leaves. */
3146
+ typedef struct {
3147
+ ca_iter_state states[2];
3148
+ VALUE self;
3149
+ CArray *ca;
3150
+ int axis;
3151
+ } cummin_ki_native_object_frame;
3152
+
2613
3153
  static VALUE
2614
- cummin_ki_native_object (VALUE self, CArray *ca, int axis)
3154
+ cummin_ki_native_object_body (VALUE arg)
2615
3155
  {
3156
+ cummin_ki_native_object_frame *fr = (cummin_ki_native_object_frame *) arg;
3157
+ VALUE self = fr->self;
3158
+ (void) self;
3159
+ CArray *ca = fr->ca;
3160
+ (void) ca;
3161
+ int axis = fr->axis;
3162
+ (void) axis;
3163
+ #define st_in (fr->states[0])
3164
+ #define st_out (fr->states[1])
2616
3165
  VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
2617
3166
  INT2NUM(sizeof(VALUE)));
2618
3167
  CArray *co;
@@ -2623,24 +3172,22 @@ cummin_ki_native_object (VALUE self, CArray *ca, int axis)
2623
3172
  INIT inside the macro. */
2624
3173
  int8_t slab_axes[CA_RANK_MAX];
2625
3174
  slab_axes[0] = (int8_t) axis;
2626
- ca_iter_state st_in, st_out;
2627
3175
  int rc;
2628
3176
  rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2629
3177
  slab_axes, 1, 0);
2630
3178
  if ( rc != CA_ITER_OK ) {
2631
3179
  rb_raise(rb_eRuntimeError,
2632
- "cummin_ki: input init failed rc=%d", rc);
3180
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2633
3181
  }
2634
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3182
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2635
3183
  slab_axes, 1, CA_KERNEL_WRITE);
2636
3184
  if ( rc != CA_ITER_OK ) {
2637
3185
  ca_iter_state_finish(&st_in);
2638
3186
  rb_raise(rb_eRuntimeError,
2639
- "cummin_ki: output init failed rc=%d", rc);
3187
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2640
3188
  }
2641
3189
 
2642
3190
  boolean8_t *op_mask = NULL;
2643
- char *co_root = (char *) co->ptr;
2644
3191
  if ( ca_has_mask(ca) ) {
2645
3192
  ca_create_mask(co);
2646
3193
  op_mask = (boolean8_t *) co->mask->ptr;
@@ -2651,75 +3198,143 @@ cummin_ki_native_object (VALUE self, CArray *ca, int axis)
2651
3198
  while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2652
3199
  ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2653
3200
  boolean8_t *mo_fiber = op_mask
2654
- ? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
3201
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2655
3202
  : NULL;
2656
3203
  CA_SLAB_SCAN_T_GATED(VALUE, VALUE, st_in, pi, mi,
2657
- st_out, po, mo_fiber, Qnil, if (acc == Qnil) acc = v; else if (RTEST(rb_funcall(v, rb_intern("<"), 1, acc))) acc = v; r = acc);
3204
+ st_out, po, mo_fiber, Qnil, if (acc == Qnil || ca_obj_extremum_replaces(v, acc, rb_intern("<"))) acc = v; r = acc);
2658
3205
  ca_iter_state_sync_slab(&st_out);
2659
3206
  }
2660
3207
  ca_iter_state_finish(&st_in);
2661
3208
  ca_iter_state_finish(&st_out);
2662
3209
  return vout;
3210
+ #undef st_in
3211
+ #undef st_out
2663
3212
  }
2664
3213
 
3214
+ static VALUE
3215
+ cummin_ki_native_object (VALUE self, CArray *ca, int axis)
3216
+ {
3217
+ cummin_ki_native_object_frame fr;
3218
+ fr.self = self;
3219
+ fr.ca = ca;
3220
+ fr.axis = axis;
3221
+ return ca_iter_ensure(2, fr.states, cummin_ki_native_object_body, (VALUE) &fr);
3222
+ }
3223
+
3224
+
3225
+ static VALUE rb_ca_cummin_ki_storage (int argc, VALUE *argv, VALUE self);
3226
+
2665
3227
  static VALUE
2666
3228
  rb_ca_cummin_ki (int argc, VALUE *argv, VALUE self)
2667
3229
  {
2668
3230
  CArray *src;
3231
+ VALUE result;
2669
3232
  GetCArray(self, src);
3233
+ volatile VALUE _reduce_face = Qnil; /* original Face, for output re-lift */
3234
+ if ( ca_is_face(src) ) {
3235
+ VALUE _face = self;
3236
+ VALUE _st;
3237
+ CArray *_sc;
3238
+ ca_face_require_orderable(_face, ca_calling_method_name(), "order");
3239
+ _st = rb_ca_strip_face_value(self);
3240
+ GetCArray(_st, _sc);
3241
+ _reduce_face = _face;
3242
+ self = _st;
3243
+ src = _sc;
3244
+ }
3245
+ result = rb_ca_cummin_ki_storage(argc, argv, self);
3246
+ if ( _reduce_face != Qnil && RB_TYPE_P(result, T_ARRAY) ) {
3247
+ /* a multi-output reduction (minmax): re-lift each output. */
3248
+ long _i;
3249
+ for ( _i = 0; _i < RARRAY_LEN(result); _i++ ) {
3250
+ VALUE _r = rb_ary_entry(result, _i);
3251
+ if ( _r == CA_UNDEF || _r == Qnil ) continue;
3252
+ if ( rb_obj_is_kind_of(_r, rb_cCArray) ) {
3253
+ _r = ca_face_relift_entity(_reduce_face, _r);
3254
+ }
3255
+ else {
3256
+ CArray *_fca;
3257
+ GetCArray(_reduce_face, _fca);
3258
+ CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(_r, _reduce_face, _fca);
3259
+ }
3260
+ rb_ary_store(result, _i, _r);
3261
+ }
3262
+ }
3263
+ else if ( _reduce_face != Qnil && result != CA_UNDEF && result != Qnil ) {
3264
+ if ( rb_obj_is_kind_of(result, rb_cCArray) ) {
3265
+ /* per-axis: re-lift the storage result as a Face of the same class. */
3266
+ result = ca_face_relift_entity(_reduce_face, result);
3267
+ }
3268
+ else {
3269
+ /* full reduction: decode the scalar via the registered hook. */
3270
+ CArray *_fca;
3271
+ GetCArray(_reduce_face, _fca);
3272
+ CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(result, _reduce_face, _fca);
3273
+ }
3274
+ }
3275
+ return result;
3276
+ }
3277
+
3278
+ static VALUE
3279
+ rb_ca_cummin_ki_storage (int argc, VALUE *argv, VALUE self)
3280
+ {
3281
+ CArray *src;
3282
+ GetCArray(self, src);
3283
+ if ( ca_is_lazy_view(src) ) {
3284
+ volatile VALUE evaluated = ca_lazy_evaluated(self);
3285
+ if ( ! NIL_P(evaluated) ) {
3286
+ self = evaluated;
3287
+ GetCArray(self, src);
3288
+ }
3289
+ }
2670
3290
  volatile VALUE ropt = rb_pop_options(&argc, &argv);
2671
3291
  volatile VALUE raxis = Qnil;
2672
3292
  rb_scan_options(ropt, "axis", &raxis);
2673
3293
  if ( argc > 0 ) {
2674
- rb_raise(rb_eArgError, "cummin_ki: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cummin(axis: 0)", argc);
3294
+ rb_raise(rb_eArgError, "%s: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cummin(axis: 0)", ca_calling_method_name(), argc);
2675
3295
  }
2676
3296
  if ( NIL_P(raxis) ) {
2677
3297
  volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
2678
3298
  CArray *fsrc;
2679
3299
  GetCArray(vflat, fsrc);
2680
3300
  switch ( fsrc->data_type ) {
2681
- case CA_INT8: return cummin_ki_native_i8(vflat, fsrc, 0);
2682
- case CA_UINT8: return cummin_ki_native_u8(vflat, fsrc, 0);
2683
- case CA_INT16: return cummin_ki_native_i16(vflat, fsrc, 0);
2684
- case CA_UINT16: return cummin_ki_native_u16(vflat, fsrc, 0);
2685
- case CA_INT32: return cummin_ki_native_i32(vflat, fsrc, 0);
2686
- case CA_UINT32: return cummin_ki_native_u32(vflat, fsrc, 0);
2687
- case CA_INT64: return cummin_ki_native_i64(vflat, fsrc, 0);
2688
- case CA_UINT64: return cummin_ki_native_u64(vflat, fsrc, 0);
2689
- case CA_FLOAT32: return cummin_ki_native_f32(vflat, fsrc, 0);
2690
- case CA_FLOAT64: return cummin_ki_native_f64(vflat, fsrc, 0);
2691
- case CA_BOOLEAN: return cummin_ki_native_bool(vflat, fsrc, 0);
2692
- case CA_OBJECT: return cummin_ki_native_object(vflat, fsrc, 0);
3301
+ case CA_INT8: CA_RETURN_KEEPING(vflat, cummin_ki_native_i8(vflat, fsrc, 0));
3302
+ case CA_UINT8: CA_RETURN_KEEPING(vflat, cummin_ki_native_u8(vflat, fsrc, 0));
3303
+ case CA_INT16: CA_RETURN_KEEPING(vflat, cummin_ki_native_i16(vflat, fsrc, 0));
3304
+ case CA_UINT16: CA_RETURN_KEEPING(vflat, cummin_ki_native_u16(vflat, fsrc, 0));
3305
+ case CA_INT32: CA_RETURN_KEEPING(vflat, cummin_ki_native_i32(vflat, fsrc, 0));
3306
+ case CA_UINT32: CA_RETURN_KEEPING(vflat, cummin_ki_native_u32(vflat, fsrc, 0));
3307
+ case CA_INT64: CA_RETURN_KEEPING(vflat, cummin_ki_native_i64(vflat, fsrc, 0));
3308
+ case CA_UINT64: CA_RETURN_KEEPING(vflat, cummin_ki_native_u64(vflat, fsrc, 0));
3309
+ case CA_FLOAT32: CA_RETURN_KEEPING(vflat, cummin_ki_native_f32(vflat, fsrc, 0));
3310
+ case CA_FLOAT64: CA_RETURN_KEEPING(vflat, cummin_ki_native_f64(vflat, fsrc, 0));
3311
+ case CA_BOOLEAN: CA_RETURN_KEEPING(vflat, cummin_ki_native_bool(vflat, fsrc, 0));
3312
+ case CA_OBJECT: CA_RETURN_KEEPING(vflat, cummin_ki_native_object(vflat, fsrc, 0));
2693
3313
  default:
2694
- rb_raise(rb_eCADataTypeError, "cummin_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, bool, object)", ca_type_name[fsrc->data_type]);
3314
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
3315
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, boolean, object)", ca_calling_method_name(), ca_type_name[fsrc->data_type]);
2695
3316
  }
2696
3317
  }
2697
3318
  if ( TYPE(raxis) == T_ARRAY ) {
2698
- rb_raise(rb_eArgError, "cummin_ki: axis: must be Integer (got Array); multi-axis scan is semantically ambiguous, chain explicitly: a.cummin(axis: 0).cummin(axis: 1)");
2699
- }
2700
- if ( ! rb_obj_is_kind_of(raxis, rb_cInteger) ) {
2701
- rb_raise(rb_eTypeError, "cummin_ki: axis: must be Integer (got %"PRIsVALUE")", rb_obj_class(raxis));
2702
- }
2703
- int axis = NUM2INT(raxis);
2704
- if ( axis < 0 ) axis += src->ndim;
2705
- if ( axis < 0 || axis >= src->ndim ) {
2706
- rb_raise(rb_eArgError, "cummin_ki: axis %d out of range for ndim %d", NUM2INT(raxis), src->ndim);
3319
+ rb_raise(rb_eArgError, "%s: axis must be a single Integer (got Array); a scan over several axes is ambiguous, chain explicitly: a.cummin(axis: 0).cummin(axis: 1)", ca_calling_method_name());
2707
3320
  }
3321
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
2708
3322
  switch ( src->data_type ) {
2709
- case CA_INT8: return cummin_ki_native_i8(self, src, axis);
2710
- case CA_UINT8: return cummin_ki_native_u8(self, src, axis);
2711
- case CA_INT16: return cummin_ki_native_i16(self, src, axis);
2712
- case CA_UINT16: return cummin_ki_native_u16(self, src, axis);
2713
- case CA_INT32: return cummin_ki_native_i32(self, src, axis);
2714
- case CA_UINT32: return cummin_ki_native_u32(self, src, axis);
2715
- case CA_INT64: return cummin_ki_native_i64(self, src, axis);
2716
- case CA_UINT64: return cummin_ki_native_u64(self, src, axis);
2717
- case CA_FLOAT32: return cummin_ki_native_f32(self, src, axis);
2718
- case CA_FLOAT64: return cummin_ki_native_f64(self, src, axis);
2719
- case CA_BOOLEAN: return cummin_ki_native_bool(self, src, axis);
2720
- case CA_OBJECT: return cummin_ki_native_object(self, src, axis);
3323
+ case CA_INT8: CA_RETURN_KEEPING(self, cummin_ki_native_i8(self, src, axis));
3324
+ case CA_UINT8: CA_RETURN_KEEPING(self, cummin_ki_native_u8(self, src, axis));
3325
+ case CA_INT16: CA_RETURN_KEEPING(self, cummin_ki_native_i16(self, src, axis));
3326
+ case CA_UINT16: CA_RETURN_KEEPING(self, cummin_ki_native_u16(self, src, axis));
3327
+ case CA_INT32: CA_RETURN_KEEPING(self, cummin_ki_native_i32(self, src, axis));
3328
+ case CA_UINT32: CA_RETURN_KEEPING(self, cummin_ki_native_u32(self, src, axis));
3329
+ case CA_INT64: CA_RETURN_KEEPING(self, cummin_ki_native_i64(self, src, axis));
3330
+ case CA_UINT64: CA_RETURN_KEEPING(self, cummin_ki_native_u64(self, src, axis));
3331
+ case CA_FLOAT32: CA_RETURN_KEEPING(self, cummin_ki_native_f32(self, src, axis));
3332
+ case CA_FLOAT64: CA_RETURN_KEEPING(self, cummin_ki_native_f64(self, src, axis));
3333
+ case CA_BOOLEAN: CA_RETURN_KEEPING(self, cummin_ki_native_bool(self, src, axis));
3334
+ case CA_OBJECT: CA_RETURN_KEEPING(self, cummin_ki_native_object(self, src, axis));
2721
3335
  default:
2722
- rb_raise(rb_eCADataTypeError, "cummin_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, bool, object)", ca_type_name[src->data_type]);
3336
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
3337
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
2723
3338
  }
2724
3339
  return Qnil; /* unreachable */
2725
3340
  }
@@ -2745,14 +3360,14 @@ cumcount_ki_native_i8 (VALUE self, CArray *ca, int axis)
2745
3360
  slab_axes, 1, 0);
2746
3361
  if ( rc != CA_ITER_OK ) {
2747
3362
  rb_raise(rb_eRuntimeError,
2748
- "cumcount_ki: input init failed rc=%d", rc);
3363
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2749
3364
  }
2750
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3365
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2751
3366
  slab_axes, 1, CA_KERNEL_WRITE);
2752
3367
  if ( rc != CA_ITER_OK ) {
2753
3368
  ca_iter_state_finish(&st_in);
2754
3369
  rb_raise(rb_eRuntimeError,
2755
- "cumcount_ki: output init failed rc=%d", rc);
3370
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2756
3371
  }
2757
3372
 
2758
3373
  char *pi, *po;
@@ -2787,14 +3402,14 @@ cumcount_ki_native_u8 (VALUE self, CArray *ca, int axis)
2787
3402
  slab_axes, 1, 0);
2788
3403
  if ( rc != CA_ITER_OK ) {
2789
3404
  rb_raise(rb_eRuntimeError,
2790
- "cumcount_ki: input init failed rc=%d", rc);
3405
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2791
3406
  }
2792
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3407
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2793
3408
  slab_axes, 1, CA_KERNEL_WRITE);
2794
3409
  if ( rc != CA_ITER_OK ) {
2795
3410
  ca_iter_state_finish(&st_in);
2796
3411
  rb_raise(rb_eRuntimeError,
2797
- "cumcount_ki: output init failed rc=%d", rc);
3412
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2798
3413
  }
2799
3414
 
2800
3415
  char *pi, *po;
@@ -2829,14 +3444,14 @@ cumcount_ki_native_i16 (VALUE self, CArray *ca, int axis)
2829
3444
  slab_axes, 1, 0);
2830
3445
  if ( rc != CA_ITER_OK ) {
2831
3446
  rb_raise(rb_eRuntimeError,
2832
- "cumcount_ki: input init failed rc=%d", rc);
3447
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2833
3448
  }
2834
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3449
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2835
3450
  slab_axes, 1, CA_KERNEL_WRITE);
2836
3451
  if ( rc != CA_ITER_OK ) {
2837
3452
  ca_iter_state_finish(&st_in);
2838
3453
  rb_raise(rb_eRuntimeError,
2839
- "cumcount_ki: output init failed rc=%d", rc);
3454
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2840
3455
  }
2841
3456
 
2842
3457
  char *pi, *po;
@@ -2871,14 +3486,14 @@ cumcount_ki_native_u16 (VALUE self, CArray *ca, int axis)
2871
3486
  slab_axes, 1, 0);
2872
3487
  if ( rc != CA_ITER_OK ) {
2873
3488
  rb_raise(rb_eRuntimeError,
2874
- "cumcount_ki: input init failed rc=%d", rc);
3489
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2875
3490
  }
2876
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3491
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2877
3492
  slab_axes, 1, CA_KERNEL_WRITE);
2878
3493
  if ( rc != CA_ITER_OK ) {
2879
3494
  ca_iter_state_finish(&st_in);
2880
3495
  rb_raise(rb_eRuntimeError,
2881
- "cumcount_ki: output init failed rc=%d", rc);
3496
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2882
3497
  }
2883
3498
 
2884
3499
  char *pi, *po;
@@ -2913,14 +3528,14 @@ cumcount_ki_native_i32 (VALUE self, CArray *ca, int axis)
2913
3528
  slab_axes, 1, 0);
2914
3529
  if ( rc != CA_ITER_OK ) {
2915
3530
  rb_raise(rb_eRuntimeError,
2916
- "cumcount_ki: input init failed rc=%d", rc);
3531
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2917
3532
  }
2918
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3533
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2919
3534
  slab_axes, 1, CA_KERNEL_WRITE);
2920
3535
  if ( rc != CA_ITER_OK ) {
2921
3536
  ca_iter_state_finish(&st_in);
2922
3537
  rb_raise(rb_eRuntimeError,
2923
- "cumcount_ki: output init failed rc=%d", rc);
3538
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2924
3539
  }
2925
3540
 
2926
3541
  char *pi, *po;
@@ -2955,14 +3570,14 @@ cumcount_ki_native_u32 (VALUE self, CArray *ca, int axis)
2955
3570
  slab_axes, 1, 0);
2956
3571
  if ( rc != CA_ITER_OK ) {
2957
3572
  rb_raise(rb_eRuntimeError,
2958
- "cumcount_ki: input init failed rc=%d", rc);
3573
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2959
3574
  }
2960
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3575
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2961
3576
  slab_axes, 1, CA_KERNEL_WRITE);
2962
3577
  if ( rc != CA_ITER_OK ) {
2963
3578
  ca_iter_state_finish(&st_in);
2964
3579
  rb_raise(rb_eRuntimeError,
2965
- "cumcount_ki: output init failed rc=%d", rc);
3580
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2966
3581
  }
2967
3582
 
2968
3583
  char *pi, *po;
@@ -2997,14 +3612,14 @@ cumcount_ki_native_i64 (VALUE self, CArray *ca, int axis)
2997
3612
  slab_axes, 1, 0);
2998
3613
  if ( rc != CA_ITER_OK ) {
2999
3614
  rb_raise(rb_eRuntimeError,
3000
- "cumcount_ki: input init failed rc=%d", rc);
3615
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3001
3616
  }
3002
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3617
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3003
3618
  slab_axes, 1, CA_KERNEL_WRITE);
3004
3619
  if ( rc != CA_ITER_OK ) {
3005
3620
  ca_iter_state_finish(&st_in);
3006
3621
  rb_raise(rb_eRuntimeError,
3007
- "cumcount_ki: output init failed rc=%d", rc);
3622
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3008
3623
  }
3009
3624
 
3010
3625
  char *pi, *po;
@@ -3039,14 +3654,14 @@ cumcount_ki_native_u64 (VALUE self, CArray *ca, int axis)
3039
3654
  slab_axes, 1, 0);
3040
3655
  if ( rc != CA_ITER_OK ) {
3041
3656
  rb_raise(rb_eRuntimeError,
3042
- "cumcount_ki: input init failed rc=%d", rc);
3657
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3043
3658
  }
3044
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3659
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3045
3660
  slab_axes, 1, CA_KERNEL_WRITE);
3046
3661
  if ( rc != CA_ITER_OK ) {
3047
3662
  ca_iter_state_finish(&st_in);
3048
3663
  rb_raise(rb_eRuntimeError,
3049
- "cumcount_ki: output init failed rc=%d", rc);
3664
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3050
3665
  }
3051
3666
 
3052
3667
  char *pi, *po;
@@ -3081,14 +3696,14 @@ cumcount_ki_native_f32 (VALUE self, CArray *ca, int axis)
3081
3696
  slab_axes, 1, 0);
3082
3697
  if ( rc != CA_ITER_OK ) {
3083
3698
  rb_raise(rb_eRuntimeError,
3084
- "cumcount_ki: input init failed rc=%d", rc);
3699
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3085
3700
  }
3086
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3701
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3087
3702
  slab_axes, 1, CA_KERNEL_WRITE);
3088
3703
  if ( rc != CA_ITER_OK ) {
3089
3704
  ca_iter_state_finish(&st_in);
3090
3705
  rb_raise(rb_eRuntimeError,
3091
- "cumcount_ki: output init failed rc=%d", rc);
3706
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3092
3707
  }
3093
3708
 
3094
3709
  char *pi, *po;
@@ -3123,14 +3738,14 @@ cumcount_ki_native_f64 (VALUE self, CArray *ca, int axis)
3123
3738
  slab_axes, 1, 0);
3124
3739
  if ( rc != CA_ITER_OK ) {
3125
3740
  rb_raise(rb_eRuntimeError,
3126
- "cumcount_ki: input init failed rc=%d", rc);
3741
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3127
3742
  }
3128
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3743
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3129
3744
  slab_axes, 1, CA_KERNEL_WRITE);
3130
3745
  if ( rc != CA_ITER_OK ) {
3131
3746
  ca_iter_state_finish(&st_in);
3132
3747
  rb_raise(rb_eRuntimeError,
3133
- "cumcount_ki: output init failed rc=%d", rc);
3748
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3134
3749
  }
3135
3750
 
3136
3751
  char *pi, *po;
@@ -3151,63 +3766,55 @@ rb_ca_cumcount_ki (int argc, VALUE *argv, VALUE self)
3151
3766
  {
3152
3767
  CArray *src;
3153
3768
  GetCArray(self, src);
3769
+ if ( ca_is_lazy_view(src) ) {
3770
+ volatile VALUE evaluated = ca_lazy_evaluated(self);
3771
+ if ( ! NIL_P(evaluated) ) {
3772
+ self = evaluated;
3773
+ GetCArray(self, src);
3774
+ }
3775
+ }
3154
3776
  volatile VALUE ropt = rb_pop_options(&argc, &argv);
3155
3777
  volatile VALUE raxis = Qnil;
3156
3778
  rb_scan_options(ropt, "axis", &raxis);
3157
3779
  if ( argc > 0 ) {
3158
- rb_raise(rb_eArgError, "cumcount_ki: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cumcount(axis: 0)", argc);
3780
+ rb_raise(rb_eArgError, "%s: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.cumcount(axis: 0)", ca_calling_method_name(), argc);
3159
3781
  }
3160
3782
  if ( NIL_P(raxis) ) {
3161
3783
  volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
3162
3784
  CArray *fsrc;
3163
3785
  GetCArray(vflat, fsrc);
3164
3786
  switch ( fsrc->data_type ) {
3165
- case CA_INT8: return cumcount_ki_native_i8(vflat, fsrc, 0);
3166
- case CA_UINT8: return cumcount_ki_native_u8(vflat, fsrc, 0);
3167
- case CA_INT16: return cumcount_ki_native_i16(vflat, fsrc, 0);
3168
- case CA_UINT16: return cumcount_ki_native_u16(vflat, fsrc, 0);
3169
- case CA_INT32: return cumcount_ki_native_i32(vflat, fsrc, 0);
3170
- case CA_UINT32: return cumcount_ki_native_u32(vflat, fsrc, 0);
3171
- case CA_INT64: return cumcount_ki_native_i64(vflat, fsrc, 0);
3172
- case CA_UINT64: return cumcount_ki_native_u64(vflat, fsrc, 0);
3173
- case CA_FLOAT32: return cumcount_ki_native_f32(vflat, fsrc, 0);
3174
- case CA_FLOAT64: return cumcount_ki_native_f64(vflat, fsrc, 0);
3175
- default: {
3176
- VALUE vsrc = rb_ca_wrap_readonly(vflat, INT2NUM(CA_FLOAT64));
3177
- CArray *casted;
3178
- GetCArray(vsrc, casted);
3179
- return cumcount_ki_native_f64(vsrc, casted, 0);
3180
- }
3787
+ case CA_INT8: CA_RETURN_KEEPING(vflat, cumcount_ki_native_i8(vflat, fsrc, 0));
3788
+ case CA_UINT8: CA_RETURN_KEEPING(vflat, cumcount_ki_native_u8(vflat, fsrc, 0));
3789
+ case CA_INT16: CA_RETURN_KEEPING(vflat, cumcount_ki_native_i16(vflat, fsrc, 0));
3790
+ case CA_UINT16: CA_RETURN_KEEPING(vflat, cumcount_ki_native_u16(vflat, fsrc, 0));
3791
+ case CA_INT32: CA_RETURN_KEEPING(vflat, cumcount_ki_native_i32(vflat, fsrc, 0));
3792
+ case CA_UINT32: CA_RETURN_KEEPING(vflat, cumcount_ki_native_u32(vflat, fsrc, 0));
3793
+ case CA_INT64: CA_RETURN_KEEPING(vflat, cumcount_ki_native_i64(vflat, fsrc, 0));
3794
+ case CA_UINT64: CA_RETURN_KEEPING(vflat, cumcount_ki_native_u64(vflat, fsrc, 0));
3795
+ case CA_FLOAT32: CA_RETURN_KEEPING(vflat, cumcount_ki_native_f32(vflat, fsrc, 0));
3796
+ case CA_FLOAT64: CA_RETURN_KEEPING(vflat, cumcount_ki_native_f64(vflat, fsrc, 0));
3797
+ default:
3798
+ return rb_ca_scan_mask_count(self, Qnil);
3181
3799
  }
3182
3800
  }
3183
3801
  if ( TYPE(raxis) == T_ARRAY ) {
3184
- rb_raise(rb_eArgError, "cumcount_ki: axis: must be Integer (got Array); multi-axis scan is semantically ambiguous, chain explicitly: a.cumcount(axis: 0).cumcount(axis: 1)");
3185
- }
3186
- if ( ! rb_obj_is_kind_of(raxis, rb_cInteger) ) {
3187
- rb_raise(rb_eTypeError, "cumcount_ki: axis: must be Integer (got %"PRIsVALUE")", rb_obj_class(raxis));
3188
- }
3189
- int axis = NUM2INT(raxis);
3190
- if ( axis < 0 ) axis += src->ndim;
3191
- if ( axis < 0 || axis >= src->ndim ) {
3192
- rb_raise(rb_eArgError, "cumcount_ki: axis %d out of range for ndim %d", NUM2INT(raxis), src->ndim);
3802
+ rb_raise(rb_eArgError, "%s: axis must be a single Integer (got Array); a scan over several axes is ambiguous, chain explicitly: a.cumcount(axis: 0).cumcount(axis: 1)", ca_calling_method_name());
3193
3803
  }
3804
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
3194
3805
  switch ( src->data_type ) {
3195
- case CA_INT8: return cumcount_ki_native_i8(self, src, axis);
3196
- case CA_UINT8: return cumcount_ki_native_u8(self, src, axis);
3197
- case CA_INT16: return cumcount_ki_native_i16(self, src, axis);
3198
- case CA_UINT16: return cumcount_ki_native_u16(self, src, axis);
3199
- case CA_INT32: return cumcount_ki_native_i32(self, src, axis);
3200
- case CA_UINT32: return cumcount_ki_native_u32(self, src, axis);
3201
- case CA_INT64: return cumcount_ki_native_i64(self, src, axis);
3202
- case CA_UINT64: return cumcount_ki_native_u64(self, src, axis);
3203
- case CA_FLOAT32: return cumcount_ki_native_f32(self, src, axis);
3204
- case CA_FLOAT64: return cumcount_ki_native_f64(self, src, axis);
3205
- default: {
3206
- VALUE vsrc = rb_ca_wrap_readonly(self, INT2NUM(CA_FLOAT64));
3207
- CArray *casted;
3208
- GetCArray(vsrc, casted);
3209
- return cumcount_ki_native_f64(vsrc, casted, axis);
3210
- }
3806
+ case CA_INT8: CA_RETURN_KEEPING(self, cumcount_ki_native_i8(self, src, axis));
3807
+ case CA_UINT8: CA_RETURN_KEEPING(self, cumcount_ki_native_u8(self, src, axis));
3808
+ case CA_INT16: CA_RETURN_KEEPING(self, cumcount_ki_native_i16(self, src, axis));
3809
+ case CA_UINT16: CA_RETURN_KEEPING(self, cumcount_ki_native_u16(self, src, axis));
3810
+ case CA_INT32: CA_RETURN_KEEPING(self, cumcount_ki_native_i32(self, src, axis));
3811
+ case CA_UINT32: CA_RETURN_KEEPING(self, cumcount_ki_native_u32(self, src, axis));
3812
+ case CA_INT64: CA_RETURN_KEEPING(self, cumcount_ki_native_i64(self, src, axis));
3813
+ case CA_UINT64: CA_RETURN_KEEPING(self, cumcount_ki_native_u64(self, src, axis));
3814
+ case CA_FLOAT32: CA_RETURN_KEEPING(self, cumcount_ki_native_f32(self, src, axis));
3815
+ case CA_FLOAT64: CA_RETURN_KEEPING(self, cumcount_ki_native_f64(self, src, axis));
3816
+ default:
3817
+ return rb_ca_scan_mask_count(self, INT2NUM(axis));
3211
3818
  }
3212
3819
  return Qnil; /* unreachable */
3213
3820
  }
@@ -3233,14 +3840,14 @@ uniq_scan_ki_native_i8 (VALUE self, CArray *ca, int axis)
3233
3840
  slab_axes, 1, 0);
3234
3841
  if ( rc != CA_ITER_OK ) {
3235
3842
  rb_raise(rb_eRuntimeError,
3236
- "uniq_scan_ki: input init failed rc=%d", rc);
3843
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3237
3844
  }
3238
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3845
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3239
3846
  slab_axes, 1, CA_KERNEL_WRITE);
3240
3847
  if ( rc != CA_ITER_OK ) {
3241
3848
  ca_iter_state_finish(&st_in);
3242
3849
  rb_raise(rb_eRuntimeError,
3243
- "uniq_scan_ki: output init failed rc=%d", rc);
3850
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3244
3851
  }
3245
3852
 
3246
3853
  char *pi, *po;
@@ -3275,14 +3882,14 @@ uniq_scan_ki_native_u8 (VALUE self, CArray *ca, int axis)
3275
3882
  slab_axes, 1, 0);
3276
3883
  if ( rc != CA_ITER_OK ) {
3277
3884
  rb_raise(rb_eRuntimeError,
3278
- "uniq_scan_ki: input init failed rc=%d", rc);
3885
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3279
3886
  }
3280
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3887
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3281
3888
  slab_axes, 1, CA_KERNEL_WRITE);
3282
3889
  if ( rc != CA_ITER_OK ) {
3283
3890
  ca_iter_state_finish(&st_in);
3284
3891
  rb_raise(rb_eRuntimeError,
3285
- "uniq_scan_ki: output init failed rc=%d", rc);
3892
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3286
3893
  }
3287
3894
 
3288
3895
  char *pi, *po;
@@ -3317,14 +3924,14 @@ uniq_scan_ki_native_i16 (VALUE self, CArray *ca, int axis)
3317
3924
  slab_axes, 1, 0);
3318
3925
  if ( rc != CA_ITER_OK ) {
3319
3926
  rb_raise(rb_eRuntimeError,
3320
- "uniq_scan_ki: input init failed rc=%d", rc);
3927
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3321
3928
  }
3322
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3929
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3323
3930
  slab_axes, 1, CA_KERNEL_WRITE);
3324
3931
  if ( rc != CA_ITER_OK ) {
3325
3932
  ca_iter_state_finish(&st_in);
3326
3933
  rb_raise(rb_eRuntimeError,
3327
- "uniq_scan_ki: output init failed rc=%d", rc);
3934
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3328
3935
  }
3329
3936
 
3330
3937
  char *pi, *po;
@@ -3359,14 +3966,14 @@ uniq_scan_ki_native_u16 (VALUE self, CArray *ca, int axis)
3359
3966
  slab_axes, 1, 0);
3360
3967
  if ( rc != CA_ITER_OK ) {
3361
3968
  rb_raise(rb_eRuntimeError,
3362
- "uniq_scan_ki: input init failed rc=%d", rc);
3969
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3363
3970
  }
3364
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
3971
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3365
3972
  slab_axes, 1, CA_KERNEL_WRITE);
3366
3973
  if ( rc != CA_ITER_OK ) {
3367
3974
  ca_iter_state_finish(&st_in);
3368
3975
  rb_raise(rb_eRuntimeError,
3369
- "uniq_scan_ki: output init failed rc=%d", rc);
3976
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3370
3977
  }
3371
3978
 
3372
3979
  char *pi, *po;
@@ -3401,14 +4008,14 @@ uniq_scan_ki_native_i32 (VALUE self, CArray *ca, int axis)
3401
4008
  slab_axes, 1, 0);
3402
4009
  if ( rc != CA_ITER_OK ) {
3403
4010
  rb_raise(rb_eRuntimeError,
3404
- "uniq_scan_ki: input init failed rc=%d", rc);
4011
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3405
4012
  }
3406
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
4013
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3407
4014
  slab_axes, 1, CA_KERNEL_WRITE);
3408
4015
  if ( rc != CA_ITER_OK ) {
3409
4016
  ca_iter_state_finish(&st_in);
3410
4017
  rb_raise(rb_eRuntimeError,
3411
- "uniq_scan_ki: output init failed rc=%d", rc);
4018
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3412
4019
  }
3413
4020
 
3414
4021
  char *pi, *po;
@@ -3443,14 +4050,14 @@ uniq_scan_ki_native_u32 (VALUE self, CArray *ca, int axis)
3443
4050
  slab_axes, 1, 0);
3444
4051
  if ( rc != CA_ITER_OK ) {
3445
4052
  rb_raise(rb_eRuntimeError,
3446
- "uniq_scan_ki: input init failed rc=%d", rc);
4053
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3447
4054
  }
3448
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
4055
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3449
4056
  slab_axes, 1, CA_KERNEL_WRITE);
3450
4057
  if ( rc != CA_ITER_OK ) {
3451
4058
  ca_iter_state_finish(&st_in);
3452
4059
  rb_raise(rb_eRuntimeError,
3453
- "uniq_scan_ki: output init failed rc=%d", rc);
4060
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3454
4061
  }
3455
4062
 
3456
4063
  char *pi, *po;
@@ -3485,14 +4092,14 @@ uniq_scan_ki_native_i64 (VALUE self, CArray *ca, int axis)
3485
4092
  slab_axes, 1, 0);
3486
4093
  if ( rc != CA_ITER_OK ) {
3487
4094
  rb_raise(rb_eRuntimeError,
3488
- "uniq_scan_ki: input init failed rc=%d", rc);
4095
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3489
4096
  }
3490
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
4097
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3491
4098
  slab_axes, 1, CA_KERNEL_WRITE);
3492
4099
  if ( rc != CA_ITER_OK ) {
3493
4100
  ca_iter_state_finish(&st_in);
3494
4101
  rb_raise(rb_eRuntimeError,
3495
- "uniq_scan_ki: output init failed rc=%d", rc);
4102
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3496
4103
  }
3497
4104
 
3498
4105
  char *pi, *po;
@@ -3527,14 +4134,14 @@ uniq_scan_ki_native_u64 (VALUE self, CArray *ca, int axis)
3527
4134
  slab_axes, 1, 0);
3528
4135
  if ( rc != CA_ITER_OK ) {
3529
4136
  rb_raise(rb_eRuntimeError,
3530
- "uniq_scan_ki: input init failed rc=%d", rc);
4137
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3531
4138
  }
3532
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
4139
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3533
4140
  slab_axes, 1, CA_KERNEL_WRITE);
3534
4141
  if ( rc != CA_ITER_OK ) {
3535
4142
  ca_iter_state_finish(&st_in);
3536
4143
  rb_raise(rb_eRuntimeError,
3537
- "uniq_scan_ki: output init failed rc=%d", rc);
4144
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3538
4145
  }
3539
4146
 
3540
4147
  char *pi, *po;
@@ -3569,14 +4176,14 @@ uniq_scan_ki_native_f32 (VALUE self, CArray *ca, int axis)
3569
4176
  slab_axes, 1, 0);
3570
4177
  if ( rc != CA_ITER_OK ) {
3571
4178
  rb_raise(rb_eRuntimeError,
3572
- "uniq_scan_ki: input init failed rc=%d", rc);
4179
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3573
4180
  }
3574
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
4181
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3575
4182
  slab_axes, 1, CA_KERNEL_WRITE);
3576
4183
  if ( rc != CA_ITER_OK ) {
3577
4184
  ca_iter_state_finish(&st_in);
3578
4185
  rb_raise(rb_eRuntimeError,
3579
- "uniq_scan_ki: output init failed rc=%d", rc);
4186
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3580
4187
  }
3581
4188
 
3582
4189
  char *pi, *po;
@@ -3611,14 +4218,14 @@ uniq_scan_ki_native_f64 (VALUE self, CArray *ca, int axis)
3611
4218
  slab_axes, 1, 0);
3612
4219
  if ( rc != CA_ITER_OK ) {
3613
4220
  rb_raise(rb_eRuntimeError,
3614
- "uniq_scan_ki: input init failed rc=%d", rc);
4221
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3615
4222
  }
3616
- rc = ca_iter_state_init_l2(&st_out, co, CA_SLAB_AXES,
4223
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3617
4224
  slab_axes, 1, CA_KERNEL_WRITE);
3618
4225
  if ( rc != CA_ITER_OK ) {
3619
4226
  ca_iter_state_finish(&st_in);
3620
4227
  rb_raise(rb_eRuntimeError,
3621
- "uniq_scan_ki: output init failed rc=%d", rc);
4228
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3622
4229
  }
3623
4230
 
3624
4231
  char *pi, *po;
@@ -3639,39 +4246,40 @@ rb_ca_uniq_scan_ki (int argc, VALUE *argv, VALUE self)
3639
4246
  {
3640
4247
  CArray *src;
3641
4248
  GetCArray(self, src);
4249
+ if ( ca_is_lazy_view(src) ) {
4250
+ volatile VALUE evaluated = ca_lazy_evaluated(self);
4251
+ if ( ! NIL_P(evaluated) ) {
4252
+ self = evaluated;
4253
+ GetCArray(self, src);
4254
+ }
4255
+ }
3642
4256
  volatile VALUE ropt = rb_pop_options(&argc, &argv);
3643
4257
  volatile VALUE raxis = Qnil;
3644
4258
  rb_scan_options(ropt, "axis", &raxis);
3645
4259
  if ( argc > 0 ) {
3646
- rb_raise(rb_eArgError, "uniq_scan_ki: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.uniq_scan(axis: 0)", argc);
4260
+ rb_raise(rb_eArgError, "%s: positional axis is no longer accepted (got %d); use axis: kwarg, e.g. a.uniq_scan(axis: 0)", ca_calling_method_name(), argc);
3647
4261
  }
3648
4262
  if ( NIL_P(raxis) ) {
3649
- rb_raise(rb_eArgError, "uniq_scan_ki: axis: kwarg is required (single axis Integer; multi-axis scan is semantically ambiguous)");
4263
+ rb_raise(rb_eArgError, "%s: axis: is required (a single Integer; a scan over several axes is ambiguous)", ca_calling_method_name());
3650
4264
  }
3651
4265
  if ( TYPE(raxis) == T_ARRAY ) {
3652
- rb_raise(rb_eArgError, "uniq_scan_ki: axis: must be Integer (got Array); multi-axis scan is semantically ambiguous, chain explicitly: a.uniq_scan(axis: 0).uniq_scan(axis: 1)");
3653
- }
3654
- if ( ! rb_obj_is_kind_of(raxis, rb_cInteger) ) {
3655
- rb_raise(rb_eTypeError, "uniq_scan_ki: axis: must be Integer (got %"PRIsVALUE")", rb_obj_class(raxis));
3656
- }
3657
- int axis = NUM2INT(raxis);
3658
- if ( axis < 0 ) axis += src->ndim;
3659
- if ( axis < 0 || axis >= src->ndim ) {
3660
- rb_raise(rb_eArgError, "uniq_scan_ki: axis %d out of range for ndim %d", NUM2INT(raxis), src->ndim);
4266
+ rb_raise(rb_eArgError, "%s: axis must be a single Integer (got Array); a scan over several axes is ambiguous, chain explicitly: a.uniq_scan(axis: 0).uniq_scan(axis: 1)", ca_calling_method_name());
3661
4267
  }
4268
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
3662
4269
  switch ( src->data_type ) {
3663
- case CA_INT8: return uniq_scan_ki_native_i8(self, src, axis);
3664
- case CA_UINT8: return uniq_scan_ki_native_u8(self, src, axis);
3665
- case CA_INT16: return uniq_scan_ki_native_i16(self, src, axis);
3666
- case CA_UINT16: return uniq_scan_ki_native_u16(self, src, axis);
3667
- case CA_INT32: return uniq_scan_ki_native_i32(self, src, axis);
3668
- case CA_UINT32: return uniq_scan_ki_native_u32(self, src, axis);
3669
- case CA_INT64: return uniq_scan_ki_native_i64(self, src, axis);
3670
- case CA_UINT64: return uniq_scan_ki_native_u64(self, src, axis);
3671
- case CA_FLOAT32: return uniq_scan_ki_native_f32(self, src, axis);
3672
- case CA_FLOAT64: return uniq_scan_ki_native_f64(self, src, axis);
4270
+ case CA_INT8: CA_RETURN_KEEPING(self, uniq_scan_ki_native_i8(self, src, axis));
4271
+ case CA_UINT8: CA_RETURN_KEEPING(self, uniq_scan_ki_native_u8(self, src, axis));
4272
+ case CA_INT16: CA_RETURN_KEEPING(self, uniq_scan_ki_native_i16(self, src, axis));
4273
+ case CA_UINT16: CA_RETURN_KEEPING(self, uniq_scan_ki_native_u16(self, src, axis));
4274
+ case CA_INT32: CA_RETURN_KEEPING(self, uniq_scan_ki_native_i32(self, src, axis));
4275
+ case CA_UINT32: CA_RETURN_KEEPING(self, uniq_scan_ki_native_u32(self, src, axis));
4276
+ case CA_INT64: CA_RETURN_KEEPING(self, uniq_scan_ki_native_i64(self, src, axis));
4277
+ case CA_UINT64: CA_RETURN_KEEPING(self, uniq_scan_ki_native_u64(self, src, axis));
4278
+ case CA_FLOAT32: CA_RETURN_KEEPING(self, uniq_scan_ki_native_f32(self, src, axis));
4279
+ case CA_FLOAT64: CA_RETURN_KEEPING(self, uniq_scan_ki_native_f64(self, src, axis));
3673
4280
  default:
3674
- rb_raise(rb_eCADataTypeError, "uniq_scan_ki: source data_type :%s not supported (expected one of: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64)", ca_type_name[src->data_type]);
4281
+ ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
4282
+ rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64)", ca_calling_method_name(), ca_type_name[src->data_type]);
3675
4283
  }
3676
4284
  return Qnil; /* unreachable */
3677
4285
  }
@@ -3681,6 +4289,7 @@ Init_carray_kernels_scan (void)
3681
4289
  {
3682
4290
  rb_define_method(rb_cCArray, "cumsum_ki", rb_ca_cumsum_ki, -1);
3683
4291
  rb_define_method(rb_cCArray, "cumsum", rb_ca_cumsum_ki, -1);
4292
+ rb_define_private_method(rb_cCArray, "cumsum_in_own_type", rb_ca_cumsum_in_own_type_ki, -1);
3684
4293
  rb_define_method(rb_cCArray, "cumprod_ki", rb_ca_cumprod_ki, -1);
3685
4294
  rb_define_method(rb_cCArray, "cumprod", rb_ca_cumprod_ki, -1);
3686
4295
  rb_define_method(rb_cCArray, "cummax_ki", rb_ca_cummax_ki, -1);