carray 3.0.3 → 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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +264 -0
  3. data/README.md +3 -2
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_descriptor.h +27 -24
  6. data/ext/ca_axis_dispatch.c +1 -6
  7. data/ext/ca_axis_group.c +27 -27
  8. data/ext/ca_binop_dispatch.c +1 -29
  9. data/ext/ca_binop_dispatch.h +0 -1
  10. data/ext/ca_categorical_iterator.c +205 -134
  11. data/ext/ca_compare.c +7 -18
  12. data/ext/ca_group_iter.c +16 -17
  13. data/ext/ca_kernel_iterator.c +1234 -1994
  14. data/ext/ca_kernel_iterator.h +391 -437
  15. data/ext/ca_monop_dispatch.c +82 -59
  16. data/ext/ca_monop_dispatch.h +1 -0
  17. data/ext/ca_obj_array.c +96 -39
  18. data/ext/ca_obj_bincmp.c +24 -21
  19. data/ext/ca_obj_binop.c +15 -26
  20. data/ext/ca_obj_bitarray.c +3 -2
  21. data/ext/ca_obj_bitfield.c +5 -6
  22. data/ext/ca_obj_block.c +18 -9
  23. data/ext/ca_obj_byte_swap.c +5 -6
  24. data/ext/ca_obj_const_string.c +173 -19
  25. data/ext/ca_obj_face.c +238 -57
  26. data/ext/ca_obj_face.h +19 -0
  27. data/ext/ca_obj_fake.c +15 -29
  28. data/ext/ca_obj_farray.c +6 -3
  29. data/ext/ca_obj_field.c +17 -5
  30. data/ext/ca_obj_fixlen_string.c +2 -3
  31. data/ext/ca_obj_grid.c +406 -132
  32. data/ext/ca_obj_meld.c +172 -34
  33. data/ext/ca_obj_moncmp.c +23 -8
  34. data/ext/ca_obj_monop.c +67 -57
  35. data/ext/ca_obj_object.c +157 -51
  36. data/ext/ca_obj_record.c +12 -7
  37. data/ext/ca_obj_reduce.c +13 -8
  38. data/ext/ca_obj_refer.c +25 -27
  39. data/ext/ca_obj_remap.c +30 -9
  40. data/ext/ca_obj_repeat.c +9 -10
  41. data/ext/ca_obj_roll.c +6 -5
  42. data/ext/ca_obj_select.c +14 -9
  43. data/ext/ca_obj_select_axis.c +15 -47
  44. data/ext/ca_obj_shift.c +11 -1
  45. data/ext/ca_obj_stack.c +179 -34
  46. data/ext/ca_obj_stride.c +162 -115
  47. data/ext/ca_obj_string.c +71 -4
  48. data/ext/ca_obj_tile.c +6 -5
  49. data/ext/ca_obj_time.c +22 -6
  50. data/ext/ca_obj_timedelta.c +22 -6
  51. data/ext/ca_obj_transpose.c +5 -3
  52. data/ext/ca_obj_triop.c +23 -32
  53. data/ext/ca_obj_window.c +190 -26
  54. data/ext/ca_sweep_engine.c +2 -2
  55. data/ext/caframe_csv_reader.c +80 -1
  56. data/ext/carray.h +181 -75
  57. data/ext/carray_access.c +184 -96
  58. data/ext/carray_address_basis.c +343 -87
  59. data/ext/carray_attribute.c +89 -6
  60. data/ext/carray_bincount.c +10 -8
  61. data/ext/carray_broadcast.c +13 -8
  62. data/ext/carray_build_flags.h +3 -0
  63. data/ext/carray_call_cfunc.c +108 -0
  64. data/ext/carray_cast.c +142 -24
  65. data/ext/carray_cast_func.rb +46 -6
  66. data/ext/carray_class.c +4 -3
  67. data/ext/carray_config.h +28 -0
  68. data/ext/carray_conversion.c +16 -7
  69. data/ext/carray_copy.c +51 -14
  70. data/ext/carray_core.c +147 -55
  71. data/ext/carray_count.c +50 -20
  72. data/ext/carray_element.c +76 -33
  73. data/ext/carray_factorize.c +118 -64
  74. data/ext/carray_generate.c +191 -50
  75. data/ext/carray_histogram.c +62 -17
  76. data/ext/carray_hold.c +12 -15
  77. data/ext/carray_index_classifier.c +388 -176
  78. data/ext/carray_internal.h +336 -29
  79. data/ext/carray_kernels_bincmp.c +4453 -0
  80. data/ext/carray_kernels_binop.c +11368 -0
  81. data/ext/carray_kernels_init.c +1734 -0
  82. data/ext/carray_kernels_moncmp.c +2104 -0
  83. data/ext/carray_kernels_monop.c +18369 -0
  84. data/ext/carray_kernels_reduce_aggregate.c +23818 -0
  85. data/ext/carray_kernels_reduce_boolean.c +406 -0
  86. data/ext/carray_kernels_reduce_cumulative.c +10086 -0
  87. data/ext/carray_kernels_reduce_extreme.c +17634 -0
  88. data/ext/carray_kernels_reduce_variance.c +3849 -0
  89. data/ext/carray_kernels_scan.c +4302 -0
  90. data/ext/carray_kernels_search.c +33829 -0
  91. data/ext/carray_kernels_sort.c +10906 -0
  92. data/ext/carray_kernels_triop.c +1864 -0
  93. data/ext/carray_key_windows.c +216 -0
  94. data/ext/carray_lazy.c +170 -111
  95. data/ext/carray_mask.c +292 -72
  96. data/ext/carray_median_percentile.c +82 -28
  97. data/ext/carray_memory_view.c +669 -561
  98. data/ext/carray_operator.c +124 -47
  99. data/ext/carray_order.c +384 -76
  100. data/ext/carray_partition.c +28 -27
  101. data/ext/carray_random.c +67 -13
  102. data/ext/carray_round.c +273 -0
  103. data/ext/carray_scatter.c +63 -38
  104. data/ext/carray_segment.c +3 -3
  105. data/ext/carray_slab.c +91 -28
  106. data/ext/carray_sort.c +35 -35
  107. data/ext/carray_struct.c +19 -18
  108. data/ext/carray_test.c +26 -5
  109. data/ext/carray_undef.c +4 -0
  110. data/ext/carray_utils.c +246 -45
  111. data/ext/mk_call_cfunc.rb +19 -2
  112. data/ext/mkkernel.rb +198 -240
  113. data/ext/ruby_carray.c +10 -4
  114. data/ext/version.h +4 -4
  115. data/lib/carray/attribute.rb +126 -22
  116. data/lib/carray/autoload_carray.rb +8 -31
  117. data/lib/carray/autoload_method_extension.rb +14 -5
  118. data/lib/carray/axis_group.rb +255 -106
  119. data/lib/carray/basics.rb +78 -10
  120. data/lib/carray/bincount_nd.rb +12 -2
  121. data/lib/carray/block_iterator.rb +126 -23
  122. data/lib/carray/boolean_reduce.rb +17 -17
  123. data/lib/carray/categorical.rb +165 -43
  124. data/lib/carray/categorical_iterator.rb +130 -27
  125. data/lib/carray/complex.rb +5 -5
  126. data/lib/carray/conditional.rb +67 -18
  127. data/lib/carray/const_string.rb +14 -5
  128. data/lib/carray/construct.rb +15 -11
  129. data/lib/carray/data_type_extension.rb +1 -0
  130. data/lib/carray/distance_limit.rb +77 -0
  131. data/lib/carray/fixlen_string.rb +7 -1
  132. data/lib/carray/frame/column_verbs.rb +70 -0
  133. data/lib/carray/frame/convert.rb +69 -0
  134. data/lib/carray/frame/csv_parser.rb +111 -17
  135. data/lib/carray/frame/describe.rb +3 -2
  136. data/lib/carray/frame/frame.rb +246 -21
  137. data/lib/carray/frame/group.rb +510 -95
  138. data/lib/carray/frame/io.rb +115 -28
  139. data/lib/carray/frame/join.rb +312 -51
  140. data/lib/carray/frame/records.rb +83 -7
  141. data/lib/carray/frame/reshape.rb +42 -35
  142. data/lib/carray/frame/sort.rb +7 -19
  143. data/lib/carray/frame/verbs.rb +188 -48
  144. data/lib/carray/frame/windows.rb +117 -0
  145. data/lib/carray/frame.rb +2 -0
  146. data/lib/carray/fuse_source.rb +11 -4
  147. data/lib/carray/fusion.rb +40 -16
  148. data/lib/carray/histogram.rb +6 -1
  149. data/lib/carray/inspect.rb +31 -8
  150. data/lib/carray/iterator.rb +85 -7
  151. data/lib/carray/key_windows.rb +620 -0
  152. data/lib/carray/lazy.rb +182 -183
  153. data/lib/carray/mask_gap_fill.rb +63 -57
  154. data/lib/carray/meld_reduce.rb +12 -14
  155. data/lib/carray/methods/bin.rb +26 -18
  156. data/lib/carray/methods/bincount.rb +16 -0
  157. data/lib/carray/methods/bit_string.rb +1 -1
  158. data/lib/carray/methods/choose.rb +16 -3
  159. data/lib/carray/methods/composition.rb +3 -1
  160. data/lib/carray/methods/gather_nd.rb +14 -5
  161. data/lib/carray/methods/insert_block.rb +2 -2
  162. data/lib/carray/methods/is_between.rb +59 -0
  163. data/lib/carray/methods/is_in.rb +53 -36
  164. data/lib/carray/methods/join.rb +1 -6
  165. data/lib/carray/methods/lag.rb +49 -0
  166. data/lib/carray/methods/locate_addr.rb +47 -51
  167. data/lib/carray/methods/mode.rb +1 -1
  168. data/lib/carray/methods/nunique.rb +11 -6
  169. data/lib/carray/methods/resize.rb +3 -3
  170. data/lib/carray/methods/value_counts.rb +4 -11
  171. data/lib/carray/record_order.rb +3 -3
  172. data/lib/carray/rng.rb +3 -0
  173. data/lib/carray/runtime.rb +53 -8
  174. data/lib/carray/segment_iterator.rb +313 -82
  175. data/lib/carray/serialize.rb +24 -10
  176. data/lib/carray/slab_iterator.rb +50 -0
  177. data/lib/carray/string.rb +105 -5
  178. data/lib/carray/string_operation_extension.rb +8 -1
  179. data/lib/carray/struct.rb +9 -21
  180. data/lib/carray/struct_builder.rb +19 -8
  181. data/lib/carray/time.rb +726 -104
  182. data/lib/carray/window_iterator.rb +122 -16
  183. data/lib/carray.rb +7 -0
  184. data/yard-stubs/ca_obj_bitfield.rb +1 -1
  185. data/yard-stubs/ca_obj_field.rb +4 -0
  186. data/yard-stubs/ca_obj_grid.rb +21 -10
  187. data/yard-stubs/ca_obj_refer.rb +2 -1
  188. data/yard-stubs/ca_obj_roll.rb +2 -2
  189. data/yard-stubs/ca_obj_shift.rb +5 -1
  190. data/yard-stubs/ca_obj_tile.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +8 -3
  192. data/yard-stubs/carray_access.rb +6 -1
  193. data/yard-stubs/carray_attribute.rb +0 -5
  194. data/yard-stubs/carray_cast.rb +10 -0
  195. data/yard-stubs/carray_conversion.rb +2 -1
  196. data/yard-stubs/carray_copy.rb +4 -2
  197. data/yard-stubs/carray_count.rb +4 -4
  198. data/yard-stubs/carray_element.rb +10 -4
  199. data/yard-stubs/carray_generate.rb +21 -1
  200. data/yard-stubs/carray_mask.rb +26 -2
  201. data/yard-stubs/carray_math.rb +27 -1
  202. data/yard-stubs/carray_median_percentile.rb +5 -2
  203. data/yard-stubs/carray_memory_view.rb +40 -23
  204. data/yard-stubs/carray_order.rb +29 -18
  205. data/yard-stubs/carray_random.rb +13 -4
  206. data/yard-stubs/carray_scatter.rb +14 -9
  207. data/yard-stubs/carray_slab.rb +9 -2
  208. data/yard-stubs/carray_sort.rb +6 -5
  209. data/yard-stubs/carray_test.rb +5 -3
  210. metadata +25 -3
  211. data/lib/carray/arrow_tensor.rb +0 -401
  212. data/lib/carray/table.rb +0 -108
@@ -0,0 +1,4302 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ carray_kernels.c -- GENERATED by ext/mkkernel.rb -- DO NOT EDIT
4
+
5
+ Kernel definitions live in mkkernel.rb (search for `MkKernel.reduce`).
6
+ Regenerate by running:
7
+
8
+ cd ext && ruby mkkernel.rb > carray_kernels.c
9
+
10
+ extconf.rb regenerates automatically when mkkernel.rb is touched.
11
+
12
+ --------------------------------------------------------------------------- */
13
+
14
+ #include "carray.h"
15
+ #include "ca_kernel_iterator.h"
16
+ #include "ca_sort_kernels.h" /* sort kernels: internal, not via the carray.h umbrella */
17
+ #include "carray_internal.h" /* ca_lazy_arena_*, ca_is_lazy_view (streaming reduce) */
18
+ #include "ca_obj_face.h" /* rb_ca_strip_face_value (Face ordering gate) */
19
+ #include <math.h>
20
+ #include <stdint.h>
21
+ #include <stdlib.h> /* qsort, mergesort (HAVE_MERGESORT) -- for :sort kind */
22
+
23
+ /* MEMO_REDUCTION_FASTPATH_ENTITY_ONLY_GUARD Tier 2: CAStack identity is
24
+ probed by operation-table function pointer (obj_type is runtime-
25
+ assigned, so no CA_OBJ_STACK compile-time constant exists). */
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
+
34
+ /* BOOL2VAL: bool -> Ruby (Qtrue/Qfalse). Used as ruby_scalar wrapper
35
+ for the all/any flat-reduction Ruby surface so `a.all` / `a.any`
36
+ return real true/false, not Integer 0/1. (BOOL2OBJ already exists
37
+ but returns Integer per CArray's boolean-as-int convention.) */
38
+ #ifndef CARRAY_BOOL2VAL_DEFINED
39
+ #define CARRAY_BOOL2VAL_DEFINED
40
+ static inline VALUE BOOL2VAL (boolean8_t x) { return x ? Qtrue : Qfalse; }
41
+ #endif
42
+
43
+ #include "ca_op_powi.h"
44
+ #include "ca_op_cmplx64.h"
45
+
46
+ /* ===== cumsum_ki ============================================ */
47
+
48
+ static VALUE
49
+ cumsum_ki_native_i8 (VALUE self, CArray *ca, int axis)
50
+ {
51
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
52
+ INT2NUM(sizeof(double)));
53
+ CArray *co;
54
+ GetCArray(vout, co);
55
+
56
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
57
+ iteration is one "fiber" along that axis with acc reset to
58
+ INIT inside the macro. */
59
+ int8_t slab_axes[CA_RANK_MAX];
60
+ slab_axes[0] = (int8_t) axis;
61
+ ca_iter_state st_in, st_out;
62
+ int rc;
63
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
64
+ slab_axes, 1, 0);
65
+ if ( rc != CA_ITER_OK ) {
66
+ rb_raise(rb_eRuntimeError,
67
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
68
+ }
69
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
70
+ slab_axes, 1, CA_KERNEL_WRITE);
71
+ if ( rc != CA_ITER_OK ) {
72
+ ca_iter_state_finish(&st_in);
73
+ rb_raise(rb_eRuntimeError,
74
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
75
+ }
76
+
77
+ char *pi, *po;
78
+ boolean8_t *mi, *mo;
79
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
80
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
81
+ CA_SLAB_SCAN_T(int8_t, double, st_in, pi, mi,
82
+ st_out, po, 0, acc += v; r = acc);
83
+ ca_iter_state_sync_slab(&st_out);
84
+ }
85
+ ca_iter_state_finish(&st_in);
86
+ ca_iter_state_finish(&st_out);
87
+ return vout;
88
+ }
89
+
90
+ static VALUE
91
+ cumsum_ki_native_u8 (VALUE self, CArray *ca, int axis)
92
+ {
93
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
94
+ INT2NUM(sizeof(double)));
95
+ CArray *co;
96
+ GetCArray(vout, co);
97
+
98
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
99
+ iteration is one "fiber" along that axis with acc reset to
100
+ INIT inside the macro. */
101
+ int8_t slab_axes[CA_RANK_MAX];
102
+ slab_axes[0] = (int8_t) axis;
103
+ ca_iter_state st_in, st_out;
104
+ int rc;
105
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
106
+ slab_axes, 1, 0);
107
+ if ( rc != CA_ITER_OK ) {
108
+ rb_raise(rb_eRuntimeError,
109
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
110
+ }
111
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
112
+ slab_axes, 1, CA_KERNEL_WRITE);
113
+ if ( rc != CA_ITER_OK ) {
114
+ ca_iter_state_finish(&st_in);
115
+ rb_raise(rb_eRuntimeError,
116
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
117
+ }
118
+
119
+ char *pi, *po;
120
+ boolean8_t *mi, *mo;
121
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
122
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
123
+ CA_SLAB_SCAN_T(uint8_t, double, st_in, pi, mi,
124
+ st_out, po, 0, acc += v; r = acc);
125
+ ca_iter_state_sync_slab(&st_out);
126
+ }
127
+ ca_iter_state_finish(&st_in);
128
+ ca_iter_state_finish(&st_out);
129
+ return vout;
130
+ }
131
+
132
+ static VALUE
133
+ cumsum_ki_native_i16 (VALUE self, CArray *ca, int axis)
134
+ {
135
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
136
+ INT2NUM(sizeof(double)));
137
+ CArray *co;
138
+ GetCArray(vout, co);
139
+
140
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
141
+ iteration is one "fiber" along that axis with acc reset to
142
+ INIT inside the macro. */
143
+ int8_t slab_axes[CA_RANK_MAX];
144
+ slab_axes[0] = (int8_t) axis;
145
+ ca_iter_state st_in, st_out;
146
+ int rc;
147
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
148
+ slab_axes, 1, 0);
149
+ if ( rc != CA_ITER_OK ) {
150
+ rb_raise(rb_eRuntimeError,
151
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
152
+ }
153
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
154
+ slab_axes, 1, CA_KERNEL_WRITE);
155
+ if ( rc != CA_ITER_OK ) {
156
+ ca_iter_state_finish(&st_in);
157
+ rb_raise(rb_eRuntimeError,
158
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
159
+ }
160
+
161
+ char *pi, *po;
162
+ boolean8_t *mi, *mo;
163
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
164
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
165
+ CA_SLAB_SCAN_T(int16_t, double, st_in, pi, mi,
166
+ st_out, po, 0, acc += v; r = acc);
167
+ ca_iter_state_sync_slab(&st_out);
168
+ }
169
+ ca_iter_state_finish(&st_in);
170
+ ca_iter_state_finish(&st_out);
171
+ return vout;
172
+ }
173
+
174
+ static VALUE
175
+ cumsum_ki_native_u16 (VALUE self, CArray *ca, int axis)
176
+ {
177
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
178
+ INT2NUM(sizeof(double)));
179
+ CArray *co;
180
+ GetCArray(vout, co);
181
+
182
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
183
+ iteration is one "fiber" along that axis with acc reset to
184
+ INIT inside the macro. */
185
+ int8_t slab_axes[CA_RANK_MAX];
186
+ slab_axes[0] = (int8_t) axis;
187
+ ca_iter_state st_in, st_out;
188
+ int rc;
189
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
190
+ slab_axes, 1, 0);
191
+ if ( rc != CA_ITER_OK ) {
192
+ rb_raise(rb_eRuntimeError,
193
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
194
+ }
195
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
196
+ slab_axes, 1, CA_KERNEL_WRITE);
197
+ if ( rc != CA_ITER_OK ) {
198
+ ca_iter_state_finish(&st_in);
199
+ rb_raise(rb_eRuntimeError,
200
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
201
+ }
202
+
203
+ char *pi, *po;
204
+ boolean8_t *mi, *mo;
205
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
206
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
207
+ CA_SLAB_SCAN_T(uint16_t, double, st_in, pi, mi,
208
+ st_out, po, 0, acc += v; r = acc);
209
+ ca_iter_state_sync_slab(&st_out);
210
+ }
211
+ ca_iter_state_finish(&st_in);
212
+ ca_iter_state_finish(&st_out);
213
+ return vout;
214
+ }
215
+
216
+ static VALUE
217
+ cumsum_ki_native_i32 (VALUE self, CArray *ca, int axis)
218
+ {
219
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
220
+ INT2NUM(sizeof(double)));
221
+ CArray *co;
222
+ GetCArray(vout, co);
223
+
224
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
225
+ iteration is one "fiber" along that axis with acc reset to
226
+ INIT inside the macro. */
227
+ int8_t slab_axes[CA_RANK_MAX];
228
+ slab_axes[0] = (int8_t) axis;
229
+ ca_iter_state st_in, st_out;
230
+ int rc;
231
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
232
+ slab_axes, 1, 0);
233
+ if ( rc != CA_ITER_OK ) {
234
+ rb_raise(rb_eRuntimeError,
235
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
236
+ }
237
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
238
+ slab_axes, 1, CA_KERNEL_WRITE);
239
+ if ( rc != CA_ITER_OK ) {
240
+ ca_iter_state_finish(&st_in);
241
+ rb_raise(rb_eRuntimeError,
242
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
243
+ }
244
+
245
+ char *pi, *po;
246
+ boolean8_t *mi, *mo;
247
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
248
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
249
+ CA_SLAB_SCAN_T(int32_t, double, st_in, pi, mi,
250
+ st_out, po, 0, acc += v; r = acc);
251
+ ca_iter_state_sync_slab(&st_out);
252
+ }
253
+ ca_iter_state_finish(&st_in);
254
+ ca_iter_state_finish(&st_out);
255
+ return vout;
256
+ }
257
+
258
+ static VALUE
259
+ cumsum_ki_native_u32 (VALUE self, CArray *ca, int axis)
260
+ {
261
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
262
+ INT2NUM(sizeof(double)));
263
+ CArray *co;
264
+ GetCArray(vout, co);
265
+
266
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
267
+ iteration is one "fiber" along that axis with acc reset to
268
+ INIT inside the macro. */
269
+ int8_t slab_axes[CA_RANK_MAX];
270
+ slab_axes[0] = (int8_t) axis;
271
+ ca_iter_state st_in, st_out;
272
+ int rc;
273
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
274
+ slab_axes, 1, 0);
275
+ if ( rc != CA_ITER_OK ) {
276
+ rb_raise(rb_eRuntimeError,
277
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
278
+ }
279
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
280
+ slab_axes, 1, CA_KERNEL_WRITE);
281
+ if ( rc != CA_ITER_OK ) {
282
+ ca_iter_state_finish(&st_in);
283
+ rb_raise(rb_eRuntimeError,
284
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
285
+ }
286
+
287
+ char *pi, *po;
288
+ boolean8_t *mi, *mo;
289
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
290
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
291
+ CA_SLAB_SCAN_T(uint32_t, double, st_in, pi, mi,
292
+ st_out, po, 0, acc += v; r = acc);
293
+ ca_iter_state_sync_slab(&st_out);
294
+ }
295
+ ca_iter_state_finish(&st_in);
296
+ ca_iter_state_finish(&st_out);
297
+ return vout;
298
+ }
299
+
300
+ static VALUE
301
+ cumsum_ki_native_i64 (VALUE self, CArray *ca, int axis)
302
+ {
303
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
304
+ INT2NUM(sizeof(double)));
305
+ CArray *co;
306
+ GetCArray(vout, co);
307
+
308
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
309
+ iteration is one "fiber" along that axis with acc reset to
310
+ INIT inside the macro. */
311
+ int8_t slab_axes[CA_RANK_MAX];
312
+ slab_axes[0] = (int8_t) axis;
313
+ ca_iter_state st_in, st_out;
314
+ int rc;
315
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
316
+ slab_axes, 1, 0);
317
+ if ( rc != CA_ITER_OK ) {
318
+ rb_raise(rb_eRuntimeError,
319
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
320
+ }
321
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
322
+ slab_axes, 1, CA_KERNEL_WRITE);
323
+ if ( rc != CA_ITER_OK ) {
324
+ ca_iter_state_finish(&st_in);
325
+ rb_raise(rb_eRuntimeError,
326
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
327
+ }
328
+
329
+ char *pi, *po;
330
+ boolean8_t *mi, *mo;
331
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
332
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
333
+ CA_SLAB_SCAN_T(int64_t, double, st_in, pi, mi,
334
+ st_out, po, 0, acc += v; r = acc);
335
+ ca_iter_state_sync_slab(&st_out);
336
+ }
337
+ ca_iter_state_finish(&st_in);
338
+ ca_iter_state_finish(&st_out);
339
+ return vout;
340
+ }
341
+
342
+ static VALUE
343
+ cumsum_ki_native_u64 (VALUE self, CArray *ca, int axis)
344
+ {
345
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
346
+ INT2NUM(sizeof(double)));
347
+ CArray *co;
348
+ GetCArray(vout, co);
349
+
350
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
351
+ iteration is one "fiber" along that axis with acc reset to
352
+ INIT inside the macro. */
353
+ int8_t slab_axes[CA_RANK_MAX];
354
+ slab_axes[0] = (int8_t) axis;
355
+ ca_iter_state st_in, st_out;
356
+ int rc;
357
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
358
+ slab_axes, 1, 0);
359
+ if ( rc != CA_ITER_OK ) {
360
+ rb_raise(rb_eRuntimeError,
361
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
362
+ }
363
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
364
+ slab_axes, 1, CA_KERNEL_WRITE);
365
+ if ( rc != CA_ITER_OK ) {
366
+ ca_iter_state_finish(&st_in);
367
+ rb_raise(rb_eRuntimeError,
368
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
369
+ }
370
+
371
+ char *pi, *po;
372
+ boolean8_t *mi, *mo;
373
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
374
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
375
+ CA_SLAB_SCAN_T(uint64_t, double, st_in, pi, mi,
376
+ st_out, po, 0, acc += v; r = acc);
377
+ ca_iter_state_sync_slab(&st_out);
378
+ }
379
+ ca_iter_state_finish(&st_in);
380
+ ca_iter_state_finish(&st_out);
381
+ return vout;
382
+ }
383
+
384
+ static VALUE
385
+ cumsum_ki_native_f32 (VALUE self, CArray *ca, int axis)
386
+ {
387
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
388
+ INT2NUM(sizeof(double)));
389
+ CArray *co;
390
+ GetCArray(vout, co);
391
+
392
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
393
+ iteration is one "fiber" along that axis with acc reset to
394
+ INIT inside the macro. */
395
+ int8_t slab_axes[CA_RANK_MAX];
396
+ slab_axes[0] = (int8_t) axis;
397
+ ca_iter_state st_in, st_out;
398
+ int rc;
399
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
400
+ slab_axes, 1, 0);
401
+ if ( rc != CA_ITER_OK ) {
402
+ rb_raise(rb_eRuntimeError,
403
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
404
+ }
405
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
406
+ slab_axes, 1, CA_KERNEL_WRITE);
407
+ if ( rc != CA_ITER_OK ) {
408
+ ca_iter_state_finish(&st_in);
409
+ rb_raise(rb_eRuntimeError,
410
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
411
+ }
412
+
413
+ char *pi, *po;
414
+ boolean8_t *mi, *mo;
415
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
416
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
417
+ CA_SLAB_SCAN_T(float, double, st_in, pi, mi,
418
+ st_out, po, 0, acc += v; r = acc);
419
+ ca_iter_state_sync_slab(&st_out);
420
+ }
421
+ ca_iter_state_finish(&st_in);
422
+ ca_iter_state_finish(&st_out);
423
+ return vout;
424
+ }
425
+
426
+ static VALUE
427
+ cumsum_ki_native_f64 (VALUE self, CArray *ca, int axis)
428
+ {
429
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
430
+ INT2NUM(sizeof(double)));
431
+ CArray *co;
432
+ GetCArray(vout, co);
433
+
434
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
435
+ iteration is one "fiber" along that axis with acc reset to
436
+ INIT inside the macro. */
437
+ int8_t slab_axes[CA_RANK_MAX];
438
+ slab_axes[0] = (int8_t) axis;
439
+ ca_iter_state st_in, st_out;
440
+ int rc;
441
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
442
+ slab_axes, 1, 0);
443
+ if ( rc != CA_ITER_OK ) {
444
+ rb_raise(rb_eRuntimeError,
445
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
446
+ }
447
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
448
+ slab_axes, 1, CA_KERNEL_WRITE);
449
+ if ( rc != CA_ITER_OK ) {
450
+ ca_iter_state_finish(&st_in);
451
+ rb_raise(rb_eRuntimeError,
452
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
453
+ }
454
+
455
+ char *pi, *po;
456
+ boolean8_t *mi, *mo;
457
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
458
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
459
+ CA_SLAB_SCAN_T(double, double, st_in, pi, mi,
460
+ st_out, po, 0, acc += v; r = acc);
461
+ ca_iter_state_sync_slab(&st_out);
462
+ }
463
+ ca_iter_state_finish(&st_in);
464
+ ca_iter_state_finish(&st_out);
465
+ return vout;
466
+ }
467
+
468
+ static VALUE
469
+ cumsum_ki_native_cmplx64 (VALUE self, CArray *ca, int axis)
470
+ {
471
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_CMPLX128),
472
+ INT2NUM(sizeof(cmplx128_t)));
473
+ CArray *co;
474
+ GetCArray(vout, co);
475
+
476
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
477
+ iteration is one "fiber" along that axis with acc reset to
478
+ INIT inside the macro. */
479
+ int8_t slab_axes[CA_RANK_MAX];
480
+ slab_axes[0] = (int8_t) axis;
481
+ ca_iter_state st_in, st_out;
482
+ int rc;
483
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
484
+ slab_axes, 1, 0);
485
+ if ( rc != CA_ITER_OK ) {
486
+ rb_raise(rb_eRuntimeError,
487
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
488
+ }
489
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
490
+ slab_axes, 1, CA_KERNEL_WRITE);
491
+ if ( rc != CA_ITER_OK ) {
492
+ ca_iter_state_finish(&st_in);
493
+ rb_raise(rb_eRuntimeError,
494
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
495
+ }
496
+
497
+ char *pi, *po;
498
+ boolean8_t *mi, *mo;
499
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
500
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
501
+ CA_SLAB_SCAN_T(cmplx64_t, cmplx128_t, st_in, pi, mi,
502
+ st_out, po, 0, acc += v; r = acc);
503
+ ca_iter_state_sync_slab(&st_out);
504
+ }
505
+ ca_iter_state_finish(&st_in);
506
+ ca_iter_state_finish(&st_out);
507
+ return vout;
508
+ }
509
+
510
+ static VALUE
511
+ cumsum_ki_native_cmplx128 (VALUE self, CArray *ca, int axis)
512
+ {
513
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_CMPLX128),
514
+ INT2NUM(sizeof(cmplx128_t)));
515
+ CArray *co;
516
+ GetCArray(vout, co);
517
+
518
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
519
+ iteration is one "fiber" along that axis with acc reset to
520
+ INIT inside the macro. */
521
+ int8_t slab_axes[CA_RANK_MAX];
522
+ slab_axes[0] = (int8_t) axis;
523
+ ca_iter_state st_in, st_out;
524
+ int rc;
525
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
526
+ slab_axes, 1, 0);
527
+ if ( rc != CA_ITER_OK ) {
528
+ rb_raise(rb_eRuntimeError,
529
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
530
+ }
531
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
532
+ slab_axes, 1, CA_KERNEL_WRITE);
533
+ if ( rc != CA_ITER_OK ) {
534
+ ca_iter_state_finish(&st_in);
535
+ rb_raise(rb_eRuntimeError,
536
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
537
+ }
538
+
539
+ char *pi, *po;
540
+ boolean8_t *mi, *mo;
541
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
542
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
543
+ CA_SLAB_SCAN_T(cmplx128_t, cmplx128_t, st_in, pi, mi,
544
+ st_out, po, 0, acc += v; r = acc);
545
+ ca_iter_state_sync_slab(&st_out);
546
+ }
547
+ ca_iter_state_finish(&st_in);
548
+ ca_iter_state_finish(&st_out);
549
+ return vout;
550
+ }
551
+
552
+ static VALUE
553
+ cumsum_ki_native_bool (VALUE self, CArray *ca, int axis)
554
+ {
555
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT64),
556
+ INT2NUM(sizeof(uint64_t)));
557
+ CArray *co;
558
+ GetCArray(vout, co);
559
+
560
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
561
+ iteration is one "fiber" along that axis with acc reset to
562
+ INIT inside the macro. */
563
+ int8_t slab_axes[CA_RANK_MAX];
564
+ slab_axes[0] = (int8_t) axis;
565
+ ca_iter_state st_in, st_out;
566
+ int rc;
567
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
568
+ slab_axes, 1, 0);
569
+ if ( rc != CA_ITER_OK ) {
570
+ rb_raise(rb_eRuntimeError,
571
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
572
+ }
573
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
574
+ slab_axes, 1, CA_KERNEL_WRITE);
575
+ if ( rc != CA_ITER_OK ) {
576
+ ca_iter_state_finish(&st_in);
577
+ rb_raise(rb_eRuntimeError,
578
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
579
+ }
580
+
581
+ char *pi, *po;
582
+ boolean8_t *mi, *mo;
583
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
584
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
585
+ CA_SLAB_SCAN_T(boolean8_t, uint64_t, st_in, pi, mi,
586
+ st_out, po, 0, acc += v; r = acc);
587
+ ca_iter_state_sync_slab(&st_out);
588
+ }
589
+ ca_iter_state_finish(&st_in);
590
+ ca_iter_state_finish(&st_out);
591
+ return vout;
592
+ }
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
+
604
+ static VALUE
605
+ cumsum_ki_native_object_body (VALUE arg)
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])
616
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
617
+ INT2NUM(sizeof(VALUE)));
618
+ CArray *co;
619
+ GetCArray(vout, co);
620
+
621
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
622
+ iteration is one "fiber" along that axis with acc reset to
623
+ INIT inside the macro. */
624
+ int8_t slab_axes[CA_RANK_MAX];
625
+ slab_axes[0] = (int8_t) axis;
626
+ int rc;
627
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
628
+ slab_axes, 1, 0);
629
+ if ( rc != CA_ITER_OK ) {
630
+ rb_raise(rb_eRuntimeError,
631
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
632
+ }
633
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
634
+ slab_axes, 1, CA_KERNEL_WRITE);
635
+ if ( rc != CA_ITER_OK ) {
636
+ ca_iter_state_finish(&st_in);
637
+ rb_raise(rb_eRuntimeError,
638
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
639
+ }
640
+
641
+ char *pi, *po;
642
+ boolean8_t *mi, *mo;
643
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
644
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
645
+ CA_SLAB_SCAN_T(VALUE, VALUE, st_in, pi, mi,
646
+ st_out, po, INT2FIX(0), acc = rb_funcall(acc, rb_intern("+"), 1, v); r = acc);
647
+ ca_iter_state_sync_slab(&st_out);
648
+ }
649
+ ca_iter_state_finish(&st_in);
650
+ ca_iter_state_finish(&st_out);
651
+ return vout;
652
+ #undef st_in
653
+ #undef st_out
654
+ }
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
+
667
+ static VALUE
668
+ rb_ca_cumsum_ki (int argc, VALUE *argv, VALUE self)
669
+ {
670
+ CArray *src;
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
+ }
679
+ volatile VALUE ropt = rb_pop_options(&argc, &argv);
680
+ volatile VALUE raxis = Qnil;
681
+ rb_scan_options(ropt, "axis", &raxis);
682
+ if ( argc > 0 ) {
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);
684
+ }
685
+ if ( NIL_P(raxis) ) {
686
+ volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
687
+ CArray *fsrc;
688
+ GetCArray(vflat, fsrc);
689
+ switch ( fsrc->data_type ) {
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));
704
+ default:
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]);
707
+ }
708
+ }
709
+ if ( TYPE(raxis) == T_ARRAY ) {
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);
925
+ }
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);
932
+ }
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);
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);
1113
+ switch ( src->data_type ) {
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));
1122
+ default:
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]);
1125
+ }
1126
+ return Qnil; /* unreachable */
1127
+ }
1128
+
1129
+ /* ===== cumprod_ki ============================================ */
1130
+
1131
+ static VALUE
1132
+ cumprod_ki_native_i8 (VALUE self, CArray *ca, int axis)
1133
+ {
1134
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1135
+ INT2NUM(sizeof(double)));
1136
+ CArray *co;
1137
+ GetCArray(vout, co);
1138
+
1139
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1140
+ iteration is one "fiber" along that axis with acc reset to
1141
+ INIT inside the macro. */
1142
+ int8_t slab_axes[CA_RANK_MAX];
1143
+ slab_axes[0] = (int8_t) axis;
1144
+ ca_iter_state st_in, st_out;
1145
+ int rc;
1146
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1147
+ slab_axes, 1, 0);
1148
+ if ( rc != CA_ITER_OK ) {
1149
+ rb_raise(rb_eRuntimeError,
1150
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1151
+ }
1152
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1153
+ slab_axes, 1, CA_KERNEL_WRITE);
1154
+ if ( rc != CA_ITER_OK ) {
1155
+ ca_iter_state_finish(&st_in);
1156
+ rb_raise(rb_eRuntimeError,
1157
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1158
+ }
1159
+
1160
+ char *pi, *po;
1161
+ boolean8_t *mi, *mo;
1162
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1163
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1164
+ CA_SLAB_SCAN_T(int8_t, double, st_in, pi, mi,
1165
+ st_out, po, 1, acc *= v; r = acc);
1166
+ ca_iter_state_sync_slab(&st_out);
1167
+ }
1168
+ ca_iter_state_finish(&st_in);
1169
+ ca_iter_state_finish(&st_out);
1170
+ return vout;
1171
+ }
1172
+
1173
+ static VALUE
1174
+ cumprod_ki_native_u8 (VALUE self, CArray *ca, int axis)
1175
+ {
1176
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1177
+ INT2NUM(sizeof(double)));
1178
+ CArray *co;
1179
+ GetCArray(vout, co);
1180
+
1181
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1182
+ iteration is one "fiber" along that axis with acc reset to
1183
+ INIT inside the macro. */
1184
+ int8_t slab_axes[CA_RANK_MAX];
1185
+ slab_axes[0] = (int8_t) axis;
1186
+ ca_iter_state st_in, st_out;
1187
+ int rc;
1188
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1189
+ slab_axes, 1, 0);
1190
+ if ( rc != CA_ITER_OK ) {
1191
+ rb_raise(rb_eRuntimeError,
1192
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1193
+ }
1194
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1195
+ slab_axes, 1, CA_KERNEL_WRITE);
1196
+ if ( rc != CA_ITER_OK ) {
1197
+ ca_iter_state_finish(&st_in);
1198
+ rb_raise(rb_eRuntimeError,
1199
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1200
+ }
1201
+
1202
+ char *pi, *po;
1203
+ boolean8_t *mi, *mo;
1204
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1205
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1206
+ CA_SLAB_SCAN_T(uint8_t, double, st_in, pi, mi,
1207
+ st_out, po, 1, acc *= v; r = acc);
1208
+ ca_iter_state_sync_slab(&st_out);
1209
+ }
1210
+ ca_iter_state_finish(&st_in);
1211
+ ca_iter_state_finish(&st_out);
1212
+ return vout;
1213
+ }
1214
+
1215
+ static VALUE
1216
+ cumprod_ki_native_i16 (VALUE self, CArray *ca, int axis)
1217
+ {
1218
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1219
+ INT2NUM(sizeof(double)));
1220
+ CArray *co;
1221
+ GetCArray(vout, co);
1222
+
1223
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1224
+ iteration is one "fiber" along that axis with acc reset to
1225
+ INIT inside the macro. */
1226
+ int8_t slab_axes[CA_RANK_MAX];
1227
+ slab_axes[0] = (int8_t) axis;
1228
+ ca_iter_state st_in, st_out;
1229
+ int rc;
1230
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1231
+ slab_axes, 1, 0);
1232
+ if ( rc != CA_ITER_OK ) {
1233
+ rb_raise(rb_eRuntimeError,
1234
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1235
+ }
1236
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1237
+ slab_axes, 1, CA_KERNEL_WRITE);
1238
+ if ( rc != CA_ITER_OK ) {
1239
+ ca_iter_state_finish(&st_in);
1240
+ rb_raise(rb_eRuntimeError,
1241
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1242
+ }
1243
+
1244
+ char *pi, *po;
1245
+ boolean8_t *mi, *mo;
1246
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1247
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1248
+ CA_SLAB_SCAN_T(int16_t, double, st_in, pi, mi,
1249
+ st_out, po, 1, acc *= v; r = acc);
1250
+ ca_iter_state_sync_slab(&st_out);
1251
+ }
1252
+ ca_iter_state_finish(&st_in);
1253
+ ca_iter_state_finish(&st_out);
1254
+ return vout;
1255
+ }
1256
+
1257
+ static VALUE
1258
+ cumprod_ki_native_u16 (VALUE self, CArray *ca, int axis)
1259
+ {
1260
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1261
+ INT2NUM(sizeof(double)));
1262
+ CArray *co;
1263
+ GetCArray(vout, co);
1264
+
1265
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1266
+ iteration is one "fiber" along that axis with acc reset to
1267
+ INIT inside the macro. */
1268
+ int8_t slab_axes[CA_RANK_MAX];
1269
+ slab_axes[0] = (int8_t) axis;
1270
+ ca_iter_state st_in, st_out;
1271
+ int rc;
1272
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1273
+ slab_axes, 1, 0);
1274
+ if ( rc != CA_ITER_OK ) {
1275
+ rb_raise(rb_eRuntimeError,
1276
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1277
+ }
1278
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1279
+ slab_axes, 1, CA_KERNEL_WRITE);
1280
+ if ( rc != CA_ITER_OK ) {
1281
+ ca_iter_state_finish(&st_in);
1282
+ rb_raise(rb_eRuntimeError,
1283
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1284
+ }
1285
+
1286
+ char *pi, *po;
1287
+ boolean8_t *mi, *mo;
1288
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1289
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1290
+ CA_SLAB_SCAN_T(uint16_t, double, st_in, pi, mi,
1291
+ st_out, po, 1, acc *= v; r = acc);
1292
+ ca_iter_state_sync_slab(&st_out);
1293
+ }
1294
+ ca_iter_state_finish(&st_in);
1295
+ ca_iter_state_finish(&st_out);
1296
+ return vout;
1297
+ }
1298
+
1299
+ static VALUE
1300
+ cumprod_ki_native_i32 (VALUE self, CArray *ca, int axis)
1301
+ {
1302
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1303
+ INT2NUM(sizeof(double)));
1304
+ CArray *co;
1305
+ GetCArray(vout, co);
1306
+
1307
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1308
+ iteration is one "fiber" along that axis with acc reset to
1309
+ INIT inside the macro. */
1310
+ int8_t slab_axes[CA_RANK_MAX];
1311
+ slab_axes[0] = (int8_t) axis;
1312
+ ca_iter_state st_in, st_out;
1313
+ int rc;
1314
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1315
+ slab_axes, 1, 0);
1316
+ if ( rc != CA_ITER_OK ) {
1317
+ rb_raise(rb_eRuntimeError,
1318
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1319
+ }
1320
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1321
+ slab_axes, 1, CA_KERNEL_WRITE);
1322
+ if ( rc != CA_ITER_OK ) {
1323
+ ca_iter_state_finish(&st_in);
1324
+ rb_raise(rb_eRuntimeError,
1325
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1326
+ }
1327
+
1328
+ char *pi, *po;
1329
+ boolean8_t *mi, *mo;
1330
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1331
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1332
+ CA_SLAB_SCAN_T(int32_t, double, st_in, pi, mi,
1333
+ st_out, po, 1, acc *= v; r = acc);
1334
+ ca_iter_state_sync_slab(&st_out);
1335
+ }
1336
+ ca_iter_state_finish(&st_in);
1337
+ ca_iter_state_finish(&st_out);
1338
+ return vout;
1339
+ }
1340
+
1341
+ static VALUE
1342
+ cumprod_ki_native_u32 (VALUE self, CArray *ca, int axis)
1343
+ {
1344
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1345
+ INT2NUM(sizeof(double)));
1346
+ CArray *co;
1347
+ GetCArray(vout, co);
1348
+
1349
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1350
+ iteration is one "fiber" along that axis with acc reset to
1351
+ INIT inside the macro. */
1352
+ int8_t slab_axes[CA_RANK_MAX];
1353
+ slab_axes[0] = (int8_t) axis;
1354
+ ca_iter_state st_in, st_out;
1355
+ int rc;
1356
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1357
+ slab_axes, 1, 0);
1358
+ if ( rc != CA_ITER_OK ) {
1359
+ rb_raise(rb_eRuntimeError,
1360
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1361
+ }
1362
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1363
+ slab_axes, 1, CA_KERNEL_WRITE);
1364
+ if ( rc != CA_ITER_OK ) {
1365
+ ca_iter_state_finish(&st_in);
1366
+ rb_raise(rb_eRuntimeError,
1367
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1368
+ }
1369
+
1370
+ char *pi, *po;
1371
+ boolean8_t *mi, *mo;
1372
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1373
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1374
+ CA_SLAB_SCAN_T(uint32_t, double, st_in, pi, mi,
1375
+ st_out, po, 1, acc *= v; r = acc);
1376
+ ca_iter_state_sync_slab(&st_out);
1377
+ }
1378
+ ca_iter_state_finish(&st_in);
1379
+ ca_iter_state_finish(&st_out);
1380
+ return vout;
1381
+ }
1382
+
1383
+ static VALUE
1384
+ cumprod_ki_native_i64 (VALUE self, CArray *ca, int axis)
1385
+ {
1386
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1387
+ INT2NUM(sizeof(double)));
1388
+ CArray *co;
1389
+ GetCArray(vout, co);
1390
+
1391
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1392
+ iteration is one "fiber" along that axis with acc reset to
1393
+ INIT inside the macro. */
1394
+ int8_t slab_axes[CA_RANK_MAX];
1395
+ slab_axes[0] = (int8_t) axis;
1396
+ ca_iter_state st_in, st_out;
1397
+ int rc;
1398
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1399
+ slab_axes, 1, 0);
1400
+ if ( rc != CA_ITER_OK ) {
1401
+ rb_raise(rb_eRuntimeError,
1402
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1403
+ }
1404
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1405
+ slab_axes, 1, CA_KERNEL_WRITE);
1406
+ if ( rc != CA_ITER_OK ) {
1407
+ ca_iter_state_finish(&st_in);
1408
+ rb_raise(rb_eRuntimeError,
1409
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1410
+ }
1411
+
1412
+ char *pi, *po;
1413
+ boolean8_t *mi, *mo;
1414
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1415
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1416
+ CA_SLAB_SCAN_T(int64_t, double, st_in, pi, mi,
1417
+ st_out, po, 1, acc *= v; r = acc);
1418
+ ca_iter_state_sync_slab(&st_out);
1419
+ }
1420
+ ca_iter_state_finish(&st_in);
1421
+ ca_iter_state_finish(&st_out);
1422
+ return vout;
1423
+ }
1424
+
1425
+ static VALUE
1426
+ cumprod_ki_native_u64 (VALUE self, CArray *ca, int axis)
1427
+ {
1428
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1429
+ INT2NUM(sizeof(double)));
1430
+ CArray *co;
1431
+ GetCArray(vout, co);
1432
+
1433
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1434
+ iteration is one "fiber" along that axis with acc reset to
1435
+ INIT inside the macro. */
1436
+ int8_t slab_axes[CA_RANK_MAX];
1437
+ slab_axes[0] = (int8_t) axis;
1438
+ ca_iter_state st_in, st_out;
1439
+ int rc;
1440
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1441
+ slab_axes, 1, 0);
1442
+ if ( rc != CA_ITER_OK ) {
1443
+ rb_raise(rb_eRuntimeError,
1444
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1445
+ }
1446
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1447
+ slab_axes, 1, CA_KERNEL_WRITE);
1448
+ if ( rc != CA_ITER_OK ) {
1449
+ ca_iter_state_finish(&st_in);
1450
+ rb_raise(rb_eRuntimeError,
1451
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1452
+ }
1453
+
1454
+ char *pi, *po;
1455
+ boolean8_t *mi, *mo;
1456
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1457
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1458
+ CA_SLAB_SCAN_T(uint64_t, double, st_in, pi, mi,
1459
+ st_out, po, 1, acc *= v; r = acc);
1460
+ ca_iter_state_sync_slab(&st_out);
1461
+ }
1462
+ ca_iter_state_finish(&st_in);
1463
+ ca_iter_state_finish(&st_out);
1464
+ return vout;
1465
+ }
1466
+
1467
+ static VALUE
1468
+ cumprod_ki_native_f32 (VALUE self, CArray *ca, int axis)
1469
+ {
1470
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1471
+ INT2NUM(sizeof(double)));
1472
+ CArray *co;
1473
+ GetCArray(vout, co);
1474
+
1475
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1476
+ iteration is one "fiber" along that axis with acc reset to
1477
+ INIT inside the macro. */
1478
+ int8_t slab_axes[CA_RANK_MAX];
1479
+ slab_axes[0] = (int8_t) axis;
1480
+ ca_iter_state st_in, st_out;
1481
+ int rc;
1482
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1483
+ slab_axes, 1, 0);
1484
+ if ( rc != CA_ITER_OK ) {
1485
+ rb_raise(rb_eRuntimeError,
1486
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1487
+ }
1488
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1489
+ slab_axes, 1, CA_KERNEL_WRITE);
1490
+ if ( rc != CA_ITER_OK ) {
1491
+ ca_iter_state_finish(&st_in);
1492
+ rb_raise(rb_eRuntimeError,
1493
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1494
+ }
1495
+
1496
+ char *pi, *po;
1497
+ boolean8_t *mi, *mo;
1498
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1499
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1500
+ CA_SLAB_SCAN_T(float, double, st_in, pi, mi,
1501
+ st_out, po, 1, acc *= v; r = acc);
1502
+ ca_iter_state_sync_slab(&st_out);
1503
+ }
1504
+ ca_iter_state_finish(&st_in);
1505
+ ca_iter_state_finish(&st_out);
1506
+ return vout;
1507
+ }
1508
+
1509
+ static VALUE
1510
+ cumprod_ki_native_f64 (VALUE self, CArray *ca, int axis)
1511
+ {
1512
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
1513
+ INT2NUM(sizeof(double)));
1514
+ CArray *co;
1515
+ GetCArray(vout, co);
1516
+
1517
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1518
+ iteration is one "fiber" along that axis with acc reset to
1519
+ INIT inside the macro. */
1520
+ int8_t slab_axes[CA_RANK_MAX];
1521
+ slab_axes[0] = (int8_t) axis;
1522
+ ca_iter_state st_in, st_out;
1523
+ int rc;
1524
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1525
+ slab_axes, 1, 0);
1526
+ if ( rc != CA_ITER_OK ) {
1527
+ rb_raise(rb_eRuntimeError,
1528
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1529
+ }
1530
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1531
+ slab_axes, 1, CA_KERNEL_WRITE);
1532
+ if ( rc != CA_ITER_OK ) {
1533
+ ca_iter_state_finish(&st_in);
1534
+ rb_raise(rb_eRuntimeError,
1535
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1536
+ }
1537
+
1538
+ char *pi, *po;
1539
+ boolean8_t *mi, *mo;
1540
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1541
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1542
+ CA_SLAB_SCAN_T(double, double, st_in, pi, mi,
1543
+ st_out, po, 1, acc *= v; r = acc);
1544
+ ca_iter_state_sync_slab(&st_out);
1545
+ }
1546
+ ca_iter_state_finish(&st_in);
1547
+ ca_iter_state_finish(&st_out);
1548
+ return vout;
1549
+ }
1550
+
1551
+ static VALUE
1552
+ cumprod_ki_native_cmplx64 (VALUE self, CArray *ca, int axis)
1553
+ {
1554
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_CMPLX128),
1555
+ INT2NUM(sizeof(cmplx128_t)));
1556
+ CArray *co;
1557
+ GetCArray(vout, co);
1558
+
1559
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1560
+ iteration is one "fiber" along that axis with acc reset to
1561
+ INIT inside the macro. */
1562
+ int8_t slab_axes[CA_RANK_MAX];
1563
+ slab_axes[0] = (int8_t) axis;
1564
+ ca_iter_state st_in, st_out;
1565
+ int rc;
1566
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1567
+ slab_axes, 1, 0);
1568
+ if ( rc != CA_ITER_OK ) {
1569
+ rb_raise(rb_eRuntimeError,
1570
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1571
+ }
1572
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1573
+ slab_axes, 1, CA_KERNEL_WRITE);
1574
+ if ( rc != CA_ITER_OK ) {
1575
+ ca_iter_state_finish(&st_in);
1576
+ rb_raise(rb_eRuntimeError,
1577
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1578
+ }
1579
+
1580
+ char *pi, *po;
1581
+ boolean8_t *mi, *mo;
1582
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1583
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1584
+ CA_SLAB_SCAN_T(cmplx64_t, cmplx128_t, st_in, pi, mi,
1585
+ st_out, po, 1, acc *= v; r = acc);
1586
+ ca_iter_state_sync_slab(&st_out);
1587
+ }
1588
+ ca_iter_state_finish(&st_in);
1589
+ ca_iter_state_finish(&st_out);
1590
+ return vout;
1591
+ }
1592
+
1593
+ static VALUE
1594
+ cumprod_ki_native_cmplx128 (VALUE self, CArray *ca, int axis)
1595
+ {
1596
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_CMPLX128),
1597
+ INT2NUM(sizeof(cmplx128_t)));
1598
+ CArray *co;
1599
+ GetCArray(vout, co);
1600
+
1601
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1602
+ iteration is one "fiber" along that axis with acc reset to
1603
+ INIT inside the macro. */
1604
+ int8_t slab_axes[CA_RANK_MAX];
1605
+ slab_axes[0] = (int8_t) axis;
1606
+ ca_iter_state st_in, st_out;
1607
+ int rc;
1608
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1609
+ slab_axes, 1, 0);
1610
+ if ( rc != CA_ITER_OK ) {
1611
+ rb_raise(rb_eRuntimeError,
1612
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1613
+ }
1614
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1615
+ slab_axes, 1, CA_KERNEL_WRITE);
1616
+ if ( rc != CA_ITER_OK ) {
1617
+ ca_iter_state_finish(&st_in);
1618
+ rb_raise(rb_eRuntimeError,
1619
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1620
+ }
1621
+
1622
+ char *pi, *po;
1623
+ boolean8_t *mi, *mo;
1624
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1625
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1626
+ CA_SLAB_SCAN_T(cmplx128_t, cmplx128_t, st_in, pi, mi,
1627
+ st_out, po, 1, acc *= v; r = acc);
1628
+ ca_iter_state_sync_slab(&st_out);
1629
+ }
1630
+ ca_iter_state_finish(&st_in);
1631
+ ca_iter_state_finish(&st_out);
1632
+ return vout;
1633
+ }
1634
+
1635
+ static VALUE
1636
+ cumprod_ki_native_bool (VALUE self, CArray *ca, int axis)
1637
+ {
1638
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT64),
1639
+ INT2NUM(sizeof(uint64_t)));
1640
+ CArray *co;
1641
+ GetCArray(vout, co);
1642
+
1643
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1644
+ iteration is one "fiber" along that axis with acc reset to
1645
+ INIT inside the macro. */
1646
+ int8_t slab_axes[CA_RANK_MAX];
1647
+ slab_axes[0] = (int8_t) axis;
1648
+ ca_iter_state st_in, st_out;
1649
+ int rc;
1650
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1651
+ slab_axes, 1, 0);
1652
+ if ( rc != CA_ITER_OK ) {
1653
+ rb_raise(rb_eRuntimeError,
1654
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1655
+ }
1656
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1657
+ slab_axes, 1, CA_KERNEL_WRITE);
1658
+ if ( rc != CA_ITER_OK ) {
1659
+ ca_iter_state_finish(&st_in);
1660
+ rb_raise(rb_eRuntimeError,
1661
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1662
+ }
1663
+
1664
+ char *pi, *po;
1665
+ boolean8_t *mi, *mo;
1666
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1667
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1668
+ CA_SLAB_SCAN_T(boolean8_t, uint64_t, st_in, pi, mi,
1669
+ st_out, po, 1, acc *= v; r = acc);
1670
+ ca_iter_state_sync_slab(&st_out);
1671
+ }
1672
+ ca_iter_state_finish(&st_in);
1673
+ ca_iter_state_finish(&st_out);
1674
+ return vout;
1675
+ }
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
+
1687
+ static VALUE
1688
+ cumprod_ki_native_object_body (VALUE arg)
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])
1699
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
1700
+ INT2NUM(sizeof(VALUE)));
1701
+ CArray *co;
1702
+ GetCArray(vout, co);
1703
+
1704
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1705
+ iteration is one "fiber" along that axis with acc reset to
1706
+ INIT inside the macro. */
1707
+ int8_t slab_axes[CA_RANK_MAX];
1708
+ slab_axes[0] = (int8_t) axis;
1709
+ int rc;
1710
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1711
+ slab_axes, 1, 0);
1712
+ if ( rc != CA_ITER_OK ) {
1713
+ rb_raise(rb_eRuntimeError,
1714
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1715
+ }
1716
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1717
+ slab_axes, 1, CA_KERNEL_WRITE);
1718
+ if ( rc != CA_ITER_OK ) {
1719
+ ca_iter_state_finish(&st_in);
1720
+ rb_raise(rb_eRuntimeError,
1721
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1722
+ }
1723
+
1724
+ char *pi, *po;
1725
+ boolean8_t *mi, *mo;
1726
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1727
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1728
+ CA_SLAB_SCAN_T(VALUE, VALUE, st_in, pi, mi,
1729
+ st_out, po, INT2FIX(1), acc = rb_funcall(acc, rb_intern("*"), 1, v); r = acc);
1730
+ ca_iter_state_sync_slab(&st_out);
1731
+ }
1732
+ ca_iter_state_finish(&st_in);
1733
+ ca_iter_state_finish(&st_out);
1734
+ return vout;
1735
+ #undef st_in
1736
+ #undef st_out
1737
+ }
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
+
1750
+ static VALUE
1751
+ rb_ca_cumprod_ki (int argc, VALUE *argv, VALUE self)
1752
+ {
1753
+ CArray *src;
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
+ }
1762
+ volatile VALUE ropt = rb_pop_options(&argc, &argv);
1763
+ volatile VALUE raxis = Qnil;
1764
+ rb_scan_options(ropt, "axis", &raxis);
1765
+ if ( argc > 0 ) {
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);
1767
+ }
1768
+ if ( NIL_P(raxis) ) {
1769
+ volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
1770
+ CArray *fsrc;
1771
+ GetCArray(vflat, fsrc);
1772
+ switch ( fsrc->data_type ) {
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));
1787
+ default:
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]);
1790
+ }
1791
+ }
1792
+ if ( TYPE(raxis) == T_ARRAY ) {
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());
1794
+ }
1795
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
1796
+ switch ( src->data_type ) {
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));
1811
+ default:
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]);
1814
+ }
1815
+ return Qnil; /* unreachable */
1816
+ }
1817
+
1818
+ /* ===== cummax_ki ============================================ */
1819
+
1820
+ static VALUE
1821
+ cummax_ki_native_i8 (VALUE self, CArray *ca, int axis)
1822
+ {
1823
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT8),
1824
+ INT2NUM(sizeof(int8_t)));
1825
+ CArray *co;
1826
+ GetCArray(vout, co);
1827
+
1828
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1829
+ iteration is one "fiber" along that axis with acc reset to
1830
+ INIT inside the macro. */
1831
+ int8_t slab_axes[CA_RANK_MAX];
1832
+ slab_axes[0] = (int8_t) axis;
1833
+ ca_iter_state st_in, st_out;
1834
+ int rc;
1835
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1836
+ slab_axes, 1, 0);
1837
+ if ( rc != CA_ITER_OK ) {
1838
+ rb_raise(rb_eRuntimeError,
1839
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1840
+ }
1841
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1842
+ slab_axes, 1, CA_KERNEL_WRITE);
1843
+ if ( rc != CA_ITER_OK ) {
1844
+ ca_iter_state_finish(&st_in);
1845
+ rb_raise(rb_eRuntimeError,
1846
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1847
+ }
1848
+
1849
+ boolean8_t *op_mask = NULL;
1850
+ if ( ca_has_mask(ca) ) {
1851
+ ca_create_mask(co);
1852
+ op_mask = (boolean8_t *) co->mask->ptr;
1853
+ }
1854
+
1855
+ char *pi, *po;
1856
+ boolean8_t *mi, *mo;
1857
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1858
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1859
+ boolean8_t *mo_fiber = op_mask
1860
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1861
+ : NULL;
1862
+ CA_SLAB_SCAN_T_GATED(int8_t, int8_t, st_in, pi, mi,
1863
+ st_out, po, mo_fiber, INT8_MIN, if (v > acc) acc = v; r = acc);
1864
+ ca_iter_state_sync_slab(&st_out);
1865
+ }
1866
+ ca_iter_state_finish(&st_in);
1867
+ ca_iter_state_finish(&st_out);
1868
+ return vout;
1869
+ }
1870
+
1871
+ static VALUE
1872
+ cummax_ki_native_u8 (VALUE self, CArray *ca, int axis)
1873
+ {
1874
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT8),
1875
+ INT2NUM(sizeof(uint8_t)));
1876
+ CArray *co;
1877
+ GetCArray(vout, co);
1878
+
1879
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1880
+ iteration is one "fiber" along that axis with acc reset to
1881
+ INIT inside the macro. */
1882
+ int8_t slab_axes[CA_RANK_MAX];
1883
+ slab_axes[0] = (int8_t) axis;
1884
+ ca_iter_state st_in, st_out;
1885
+ int rc;
1886
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1887
+ slab_axes, 1, 0);
1888
+ if ( rc != CA_ITER_OK ) {
1889
+ rb_raise(rb_eRuntimeError,
1890
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1891
+ }
1892
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1893
+ slab_axes, 1, CA_KERNEL_WRITE);
1894
+ if ( rc != CA_ITER_OK ) {
1895
+ ca_iter_state_finish(&st_in);
1896
+ rb_raise(rb_eRuntimeError,
1897
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1898
+ }
1899
+
1900
+ boolean8_t *op_mask = NULL;
1901
+ if ( ca_has_mask(ca) ) {
1902
+ ca_create_mask(co);
1903
+ op_mask = (boolean8_t *) co->mask->ptr;
1904
+ }
1905
+
1906
+ char *pi, *po;
1907
+ boolean8_t *mi, *mo;
1908
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1909
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1910
+ boolean8_t *mo_fiber = op_mask
1911
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1912
+ : NULL;
1913
+ CA_SLAB_SCAN_T_GATED(uint8_t, uint8_t, st_in, pi, mi,
1914
+ st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
1915
+ ca_iter_state_sync_slab(&st_out);
1916
+ }
1917
+ ca_iter_state_finish(&st_in);
1918
+ ca_iter_state_finish(&st_out);
1919
+ return vout;
1920
+ }
1921
+
1922
+ static VALUE
1923
+ cummax_ki_native_i16 (VALUE self, CArray *ca, int axis)
1924
+ {
1925
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT16),
1926
+ INT2NUM(sizeof(int16_t)));
1927
+ CArray *co;
1928
+ GetCArray(vout, co);
1929
+
1930
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1931
+ iteration is one "fiber" along that axis with acc reset to
1932
+ INIT inside the macro. */
1933
+ int8_t slab_axes[CA_RANK_MAX];
1934
+ slab_axes[0] = (int8_t) axis;
1935
+ ca_iter_state st_in, st_out;
1936
+ int rc;
1937
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1938
+ slab_axes, 1, 0);
1939
+ if ( rc != CA_ITER_OK ) {
1940
+ rb_raise(rb_eRuntimeError,
1941
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1942
+ }
1943
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1944
+ slab_axes, 1, CA_KERNEL_WRITE);
1945
+ if ( rc != CA_ITER_OK ) {
1946
+ ca_iter_state_finish(&st_in);
1947
+ rb_raise(rb_eRuntimeError,
1948
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
1949
+ }
1950
+
1951
+ boolean8_t *op_mask = NULL;
1952
+ if ( ca_has_mask(ca) ) {
1953
+ ca_create_mask(co);
1954
+ op_mask = (boolean8_t *) co->mask->ptr;
1955
+ }
1956
+
1957
+ char *pi, *po;
1958
+ boolean8_t *mi, *mo;
1959
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
1960
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
1961
+ boolean8_t *mo_fiber = op_mask
1962
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
1963
+ : NULL;
1964
+ CA_SLAB_SCAN_T_GATED(int16_t, int16_t, st_in, pi, mi,
1965
+ st_out, po, mo_fiber, INT16_MIN, if (v > acc) acc = v; r = acc);
1966
+ ca_iter_state_sync_slab(&st_out);
1967
+ }
1968
+ ca_iter_state_finish(&st_in);
1969
+ ca_iter_state_finish(&st_out);
1970
+ return vout;
1971
+ }
1972
+
1973
+ static VALUE
1974
+ cummax_ki_native_u16 (VALUE self, CArray *ca, int axis)
1975
+ {
1976
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT16),
1977
+ INT2NUM(sizeof(uint16_t)));
1978
+ CArray *co;
1979
+ GetCArray(vout, co);
1980
+
1981
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
1982
+ iteration is one "fiber" along that axis with acc reset to
1983
+ INIT inside the macro. */
1984
+ int8_t slab_axes[CA_RANK_MAX];
1985
+ slab_axes[0] = (int8_t) axis;
1986
+ ca_iter_state st_in, st_out;
1987
+ int rc;
1988
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
1989
+ slab_axes, 1, 0);
1990
+ if ( rc != CA_ITER_OK ) {
1991
+ rb_raise(rb_eRuntimeError,
1992
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
1993
+ }
1994
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
1995
+ slab_axes, 1, CA_KERNEL_WRITE);
1996
+ if ( rc != CA_ITER_OK ) {
1997
+ ca_iter_state_finish(&st_in);
1998
+ rb_raise(rb_eRuntimeError,
1999
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2000
+ }
2001
+
2002
+ boolean8_t *op_mask = NULL;
2003
+ if ( ca_has_mask(ca) ) {
2004
+ ca_create_mask(co);
2005
+ op_mask = (boolean8_t *) co->mask->ptr;
2006
+ }
2007
+
2008
+ char *pi, *po;
2009
+ boolean8_t *mi, *mo;
2010
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2011
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2012
+ boolean8_t *mo_fiber = op_mask
2013
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2014
+ : NULL;
2015
+ CA_SLAB_SCAN_T_GATED(uint16_t, uint16_t, st_in, pi, mi,
2016
+ st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
2017
+ ca_iter_state_sync_slab(&st_out);
2018
+ }
2019
+ ca_iter_state_finish(&st_in);
2020
+ ca_iter_state_finish(&st_out);
2021
+ return vout;
2022
+ }
2023
+
2024
+ static VALUE
2025
+ cummax_ki_native_i32 (VALUE self, CArray *ca, int axis)
2026
+ {
2027
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT32),
2028
+ INT2NUM(sizeof(int32_t)));
2029
+ CArray *co;
2030
+ GetCArray(vout, co);
2031
+
2032
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2033
+ iteration is one "fiber" along that axis with acc reset to
2034
+ INIT inside the macro. */
2035
+ int8_t slab_axes[CA_RANK_MAX];
2036
+ slab_axes[0] = (int8_t) axis;
2037
+ ca_iter_state st_in, st_out;
2038
+ int rc;
2039
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2040
+ slab_axes, 1, 0);
2041
+ if ( rc != CA_ITER_OK ) {
2042
+ rb_raise(rb_eRuntimeError,
2043
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2044
+ }
2045
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2046
+ slab_axes, 1, CA_KERNEL_WRITE);
2047
+ if ( rc != CA_ITER_OK ) {
2048
+ ca_iter_state_finish(&st_in);
2049
+ rb_raise(rb_eRuntimeError,
2050
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2051
+ }
2052
+
2053
+ boolean8_t *op_mask = NULL;
2054
+ if ( ca_has_mask(ca) ) {
2055
+ ca_create_mask(co);
2056
+ op_mask = (boolean8_t *) co->mask->ptr;
2057
+ }
2058
+
2059
+ char *pi, *po;
2060
+ boolean8_t *mi, *mo;
2061
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2062
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2063
+ boolean8_t *mo_fiber = op_mask
2064
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2065
+ : NULL;
2066
+ CA_SLAB_SCAN_T_GATED(int32_t, int32_t, st_in, pi, mi,
2067
+ st_out, po, mo_fiber, INT32_MIN, if (v > acc) acc = v; r = acc);
2068
+ ca_iter_state_sync_slab(&st_out);
2069
+ }
2070
+ ca_iter_state_finish(&st_in);
2071
+ ca_iter_state_finish(&st_out);
2072
+ return vout;
2073
+ }
2074
+
2075
+ static VALUE
2076
+ cummax_ki_native_u32 (VALUE self, CArray *ca, int axis)
2077
+ {
2078
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT32),
2079
+ INT2NUM(sizeof(uint32_t)));
2080
+ CArray *co;
2081
+ GetCArray(vout, co);
2082
+
2083
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2084
+ iteration is one "fiber" along that axis with acc reset to
2085
+ INIT inside the macro. */
2086
+ int8_t slab_axes[CA_RANK_MAX];
2087
+ slab_axes[0] = (int8_t) axis;
2088
+ ca_iter_state st_in, st_out;
2089
+ int rc;
2090
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2091
+ slab_axes, 1, 0);
2092
+ if ( rc != CA_ITER_OK ) {
2093
+ rb_raise(rb_eRuntimeError,
2094
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2095
+ }
2096
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2097
+ slab_axes, 1, CA_KERNEL_WRITE);
2098
+ if ( rc != CA_ITER_OK ) {
2099
+ ca_iter_state_finish(&st_in);
2100
+ rb_raise(rb_eRuntimeError,
2101
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2102
+ }
2103
+
2104
+ boolean8_t *op_mask = NULL;
2105
+ if ( ca_has_mask(ca) ) {
2106
+ ca_create_mask(co);
2107
+ op_mask = (boolean8_t *) co->mask->ptr;
2108
+ }
2109
+
2110
+ char *pi, *po;
2111
+ boolean8_t *mi, *mo;
2112
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2113
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2114
+ boolean8_t *mo_fiber = op_mask
2115
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2116
+ : NULL;
2117
+ CA_SLAB_SCAN_T_GATED(uint32_t, uint32_t, st_in, pi, mi,
2118
+ st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
2119
+ ca_iter_state_sync_slab(&st_out);
2120
+ }
2121
+ ca_iter_state_finish(&st_in);
2122
+ ca_iter_state_finish(&st_out);
2123
+ return vout;
2124
+ }
2125
+
2126
+ static VALUE
2127
+ cummax_ki_native_i64 (VALUE self, CArray *ca, int axis)
2128
+ {
2129
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
2130
+ INT2NUM(sizeof(int64_t)));
2131
+ CArray *co;
2132
+ GetCArray(vout, co);
2133
+
2134
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2135
+ iteration is one "fiber" along that axis with acc reset to
2136
+ INIT inside the macro. */
2137
+ int8_t slab_axes[CA_RANK_MAX];
2138
+ slab_axes[0] = (int8_t) axis;
2139
+ ca_iter_state st_in, st_out;
2140
+ int rc;
2141
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2142
+ slab_axes, 1, 0);
2143
+ if ( rc != CA_ITER_OK ) {
2144
+ rb_raise(rb_eRuntimeError,
2145
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2146
+ }
2147
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2148
+ slab_axes, 1, CA_KERNEL_WRITE);
2149
+ if ( rc != CA_ITER_OK ) {
2150
+ ca_iter_state_finish(&st_in);
2151
+ rb_raise(rb_eRuntimeError,
2152
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2153
+ }
2154
+
2155
+ boolean8_t *op_mask = NULL;
2156
+ if ( ca_has_mask(ca) ) {
2157
+ ca_create_mask(co);
2158
+ op_mask = (boolean8_t *) co->mask->ptr;
2159
+ }
2160
+
2161
+ char *pi, *po;
2162
+ boolean8_t *mi, *mo;
2163
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2164
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2165
+ boolean8_t *mo_fiber = op_mask
2166
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2167
+ : NULL;
2168
+ CA_SLAB_SCAN_T_GATED(int64_t, int64_t, st_in, pi, mi,
2169
+ st_out, po, mo_fiber, INT64_MIN, if (v > acc) acc = v; r = acc);
2170
+ ca_iter_state_sync_slab(&st_out);
2171
+ }
2172
+ ca_iter_state_finish(&st_in);
2173
+ ca_iter_state_finish(&st_out);
2174
+ return vout;
2175
+ }
2176
+
2177
+ static VALUE
2178
+ cummax_ki_native_u64 (VALUE self, CArray *ca, int axis)
2179
+ {
2180
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT64),
2181
+ INT2NUM(sizeof(uint64_t)));
2182
+ CArray *co;
2183
+ GetCArray(vout, co);
2184
+
2185
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2186
+ iteration is one "fiber" along that axis with acc reset to
2187
+ INIT inside the macro. */
2188
+ int8_t slab_axes[CA_RANK_MAX];
2189
+ slab_axes[0] = (int8_t) axis;
2190
+ ca_iter_state st_in, st_out;
2191
+ int rc;
2192
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2193
+ slab_axes, 1, 0);
2194
+ if ( rc != CA_ITER_OK ) {
2195
+ rb_raise(rb_eRuntimeError,
2196
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2197
+ }
2198
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2199
+ slab_axes, 1, CA_KERNEL_WRITE);
2200
+ if ( rc != CA_ITER_OK ) {
2201
+ ca_iter_state_finish(&st_in);
2202
+ rb_raise(rb_eRuntimeError,
2203
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2204
+ }
2205
+
2206
+ boolean8_t *op_mask = NULL;
2207
+ if ( ca_has_mask(ca) ) {
2208
+ ca_create_mask(co);
2209
+ op_mask = (boolean8_t *) co->mask->ptr;
2210
+ }
2211
+
2212
+ char *pi, *po;
2213
+ boolean8_t *mi, *mo;
2214
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2215
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2216
+ boolean8_t *mo_fiber = op_mask
2217
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2218
+ : NULL;
2219
+ CA_SLAB_SCAN_T_GATED(uint64_t, uint64_t, st_in, pi, mi,
2220
+ st_out, po, mo_fiber, 0, if (v > acc) acc = v; r = acc);
2221
+ ca_iter_state_sync_slab(&st_out);
2222
+ }
2223
+ ca_iter_state_finish(&st_in);
2224
+ ca_iter_state_finish(&st_out);
2225
+ return vout;
2226
+ }
2227
+
2228
+ static VALUE
2229
+ cummax_ki_native_f32 (VALUE self, CArray *ca, int axis)
2230
+ {
2231
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT32),
2232
+ INT2NUM(sizeof(float)));
2233
+ CArray *co;
2234
+ GetCArray(vout, co);
2235
+
2236
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2237
+ iteration is one "fiber" along that axis with acc reset to
2238
+ INIT inside the macro. */
2239
+ int8_t slab_axes[CA_RANK_MAX];
2240
+ slab_axes[0] = (int8_t) axis;
2241
+ ca_iter_state st_in, st_out;
2242
+ int rc;
2243
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2244
+ slab_axes, 1, 0);
2245
+ if ( rc != CA_ITER_OK ) {
2246
+ rb_raise(rb_eRuntimeError,
2247
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2248
+ }
2249
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2250
+ slab_axes, 1, CA_KERNEL_WRITE);
2251
+ if ( rc != CA_ITER_OK ) {
2252
+ ca_iter_state_finish(&st_in);
2253
+ rb_raise(rb_eRuntimeError,
2254
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2255
+ }
2256
+
2257
+ boolean8_t *op_mask = NULL;
2258
+ if ( ca_has_mask(ca) ) {
2259
+ ca_create_mask(co);
2260
+ op_mask = (boolean8_t *) co->mask->ptr;
2261
+ }
2262
+
2263
+ char *pi, *po;
2264
+ boolean8_t *mi, *mo;
2265
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2266
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2267
+ boolean8_t *mo_fiber = op_mask
2268
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2269
+ : NULL;
2270
+ CA_SLAB_SCAN_T_GATED(float, float, st_in, pi, mi,
2271
+ st_out, po, mo_fiber, NAN, acc = fmax(acc, v); r = acc);
2272
+ ca_iter_state_sync_slab(&st_out);
2273
+ }
2274
+ ca_iter_state_finish(&st_in);
2275
+ ca_iter_state_finish(&st_out);
2276
+ return vout;
2277
+ }
2278
+
2279
+ static VALUE
2280
+ cummax_ki_native_f64 (VALUE self, CArray *ca, int axis)
2281
+ {
2282
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
2283
+ INT2NUM(sizeof(double)));
2284
+ CArray *co;
2285
+ GetCArray(vout, co);
2286
+
2287
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2288
+ iteration is one "fiber" along that axis with acc reset to
2289
+ INIT inside the macro. */
2290
+ int8_t slab_axes[CA_RANK_MAX];
2291
+ slab_axes[0] = (int8_t) axis;
2292
+ ca_iter_state st_in, st_out;
2293
+ int rc;
2294
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2295
+ slab_axes, 1, 0);
2296
+ if ( rc != CA_ITER_OK ) {
2297
+ rb_raise(rb_eRuntimeError,
2298
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2299
+ }
2300
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2301
+ slab_axes, 1, CA_KERNEL_WRITE);
2302
+ if ( rc != CA_ITER_OK ) {
2303
+ ca_iter_state_finish(&st_in);
2304
+ rb_raise(rb_eRuntimeError,
2305
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2306
+ }
2307
+
2308
+ boolean8_t *op_mask = NULL;
2309
+ if ( ca_has_mask(ca) ) {
2310
+ ca_create_mask(co);
2311
+ op_mask = (boolean8_t *) co->mask->ptr;
2312
+ }
2313
+
2314
+ char *pi, *po;
2315
+ boolean8_t *mi, *mo;
2316
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2317
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2318
+ boolean8_t *mo_fiber = op_mask
2319
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2320
+ : NULL;
2321
+ CA_SLAB_SCAN_T_GATED(double, double, st_in, pi, mi,
2322
+ st_out, po, mo_fiber, NAN, acc = fmax(acc, v); r = acc);
2323
+ ca_iter_state_sync_slab(&st_out);
2324
+ }
2325
+ ca_iter_state_finish(&st_in);
2326
+ ca_iter_state_finish(&st_out);
2327
+ return vout;
2328
+ }
2329
+
2330
+ static VALUE
2331
+ cummax_ki_native_bool (VALUE self, CArray *ca, int axis)
2332
+ {
2333
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT64),
2334
+ INT2NUM(sizeof(uint64_t)));
2335
+ CArray *co;
2336
+ GetCArray(vout, co);
2337
+
2338
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2339
+ iteration is one "fiber" along that axis with acc reset to
2340
+ INIT inside the macro. */
2341
+ int8_t slab_axes[CA_RANK_MAX];
2342
+ slab_axes[0] = (int8_t) axis;
2343
+ ca_iter_state st_in, st_out;
2344
+ int rc;
2345
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2346
+ slab_axes, 1, 0);
2347
+ if ( rc != CA_ITER_OK ) {
2348
+ rb_raise(rb_eRuntimeError,
2349
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2350
+ }
2351
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2352
+ slab_axes, 1, CA_KERNEL_WRITE);
2353
+ if ( rc != CA_ITER_OK ) {
2354
+ ca_iter_state_finish(&st_in);
2355
+ rb_raise(rb_eRuntimeError,
2356
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2357
+ }
2358
+
2359
+ boolean8_t *op_mask = NULL;
2360
+ if ( ca_has_mask(ca) ) {
2361
+ ca_create_mask(co);
2362
+ op_mask = (boolean8_t *) co->mask->ptr;
2363
+ }
2364
+
2365
+ char *pi, *po;
2366
+ boolean8_t *mi, *mo;
2367
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2368
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2369
+ boolean8_t *mo_fiber = op_mask
2370
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2371
+ : NULL;
2372
+ CA_SLAB_SCAN_T_GATED(boolean8_t, uint64_t, st_in, pi, mi,
2373
+ st_out, po, mo_fiber, 0, if ((uint64_t) v > acc) acc = v; r = acc);
2374
+ ca_iter_state_sync_slab(&st_out);
2375
+ }
2376
+ ca_iter_state_finish(&st_in);
2377
+ ca_iter_state_finish(&st_out);
2378
+ return vout;
2379
+ }
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
+
2391
+ static VALUE
2392
+ cummax_ki_native_object_body (VALUE arg)
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])
2403
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
2404
+ INT2NUM(sizeof(VALUE)));
2405
+ CArray *co;
2406
+ GetCArray(vout, co);
2407
+
2408
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2409
+ iteration is one "fiber" along that axis with acc reset to
2410
+ INIT inside the macro. */
2411
+ int8_t slab_axes[CA_RANK_MAX];
2412
+ slab_axes[0] = (int8_t) axis;
2413
+ int rc;
2414
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2415
+ slab_axes, 1, 0);
2416
+ if ( rc != CA_ITER_OK ) {
2417
+ rb_raise(rb_eRuntimeError,
2418
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2419
+ }
2420
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2421
+ slab_axes, 1, CA_KERNEL_WRITE);
2422
+ if ( rc != CA_ITER_OK ) {
2423
+ ca_iter_state_finish(&st_in);
2424
+ rb_raise(rb_eRuntimeError,
2425
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2426
+ }
2427
+
2428
+ boolean8_t *op_mask = NULL;
2429
+ if ( ca_has_mask(ca) ) {
2430
+ ca_create_mask(co);
2431
+ op_mask = (boolean8_t *) co->mask->ptr;
2432
+ }
2433
+
2434
+ char *pi, *po;
2435
+ boolean8_t *mi, *mo;
2436
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2437
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2438
+ boolean8_t *mo_fiber = op_mask
2439
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2440
+ : NULL;
2441
+ CA_SLAB_SCAN_T_GATED(VALUE, VALUE, st_in, pi, mi,
2442
+ st_out, po, mo_fiber, Qnil, if (acc == Qnil || ca_obj_extremum_replaces(v, acc, rb_intern(">"))) acc = v; r = acc);
2443
+ ca_iter_state_sync_slab(&st_out);
2444
+ }
2445
+ ca_iter_state_finish(&st_in);
2446
+ ca_iter_state_finish(&st_out);
2447
+ return vout;
2448
+ #undef st_in
2449
+ #undef st_out
2450
+ }
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
+
2465
+ static VALUE
2466
+ rb_ca_cummax_ki (int argc, VALUE *argv, VALUE self)
2467
+ {
2468
+ CArray *src;
2469
+ VALUE result;
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
+ }
2528
+ volatile VALUE ropt = rb_pop_options(&argc, &argv);
2529
+ volatile VALUE raxis = Qnil;
2530
+ rb_scan_options(ropt, "axis", &raxis);
2531
+ if ( argc > 0 ) {
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);
2533
+ }
2534
+ if ( NIL_P(raxis) ) {
2535
+ volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
2536
+ CArray *fsrc;
2537
+ GetCArray(vflat, fsrc);
2538
+ switch ( fsrc->data_type ) {
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));
2551
+ default:
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]);
2554
+ }
2555
+ }
2556
+ if ( TYPE(raxis) == T_ARRAY ) {
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());
2558
+ }
2559
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
2560
+ switch ( src->data_type ) {
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));
2573
+ default:
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]);
2576
+ }
2577
+ return Qnil; /* unreachable */
2578
+ }
2579
+
2580
+ /* ===== cummin_ki ============================================ */
2581
+
2582
+ static VALUE
2583
+ cummin_ki_native_i8 (VALUE self, CArray *ca, int axis)
2584
+ {
2585
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT8),
2586
+ INT2NUM(sizeof(int8_t)));
2587
+ CArray *co;
2588
+ GetCArray(vout, co);
2589
+
2590
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2591
+ iteration is one "fiber" along that axis with acc reset to
2592
+ INIT inside the macro. */
2593
+ int8_t slab_axes[CA_RANK_MAX];
2594
+ slab_axes[0] = (int8_t) axis;
2595
+ ca_iter_state st_in, st_out;
2596
+ int rc;
2597
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2598
+ slab_axes, 1, 0);
2599
+ if ( rc != CA_ITER_OK ) {
2600
+ rb_raise(rb_eRuntimeError,
2601
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2602
+ }
2603
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2604
+ slab_axes, 1, CA_KERNEL_WRITE);
2605
+ if ( rc != CA_ITER_OK ) {
2606
+ ca_iter_state_finish(&st_in);
2607
+ rb_raise(rb_eRuntimeError,
2608
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2609
+ }
2610
+
2611
+ boolean8_t *op_mask = NULL;
2612
+ if ( ca_has_mask(ca) ) {
2613
+ ca_create_mask(co);
2614
+ op_mask = (boolean8_t *) co->mask->ptr;
2615
+ }
2616
+
2617
+ char *pi, *po;
2618
+ boolean8_t *mi, *mo;
2619
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2620
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2621
+ boolean8_t *mo_fiber = op_mask
2622
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2623
+ : NULL;
2624
+ CA_SLAB_SCAN_T_GATED(int8_t, int8_t, st_in, pi, mi,
2625
+ st_out, po, mo_fiber, INT8_MAX, if (v < acc) acc = v; r = acc);
2626
+ ca_iter_state_sync_slab(&st_out);
2627
+ }
2628
+ ca_iter_state_finish(&st_in);
2629
+ ca_iter_state_finish(&st_out);
2630
+ return vout;
2631
+ }
2632
+
2633
+ static VALUE
2634
+ cummin_ki_native_u8 (VALUE self, CArray *ca, int axis)
2635
+ {
2636
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT8),
2637
+ INT2NUM(sizeof(uint8_t)));
2638
+ CArray *co;
2639
+ GetCArray(vout, co);
2640
+
2641
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2642
+ iteration is one "fiber" along that axis with acc reset to
2643
+ INIT inside the macro. */
2644
+ int8_t slab_axes[CA_RANK_MAX];
2645
+ slab_axes[0] = (int8_t) axis;
2646
+ ca_iter_state st_in, st_out;
2647
+ int rc;
2648
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2649
+ slab_axes, 1, 0);
2650
+ if ( rc != CA_ITER_OK ) {
2651
+ rb_raise(rb_eRuntimeError,
2652
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2653
+ }
2654
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2655
+ slab_axes, 1, CA_KERNEL_WRITE);
2656
+ if ( rc != CA_ITER_OK ) {
2657
+ ca_iter_state_finish(&st_in);
2658
+ rb_raise(rb_eRuntimeError,
2659
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2660
+ }
2661
+
2662
+ boolean8_t *op_mask = NULL;
2663
+ if ( ca_has_mask(ca) ) {
2664
+ ca_create_mask(co);
2665
+ op_mask = (boolean8_t *) co->mask->ptr;
2666
+ }
2667
+
2668
+ char *pi, *po;
2669
+ boolean8_t *mi, *mo;
2670
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2671
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2672
+ boolean8_t *mo_fiber = op_mask
2673
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2674
+ : NULL;
2675
+ CA_SLAB_SCAN_T_GATED(uint8_t, uint8_t, st_in, pi, mi,
2676
+ st_out, po, mo_fiber, UINT8_MAX, if (v < acc) acc = v; r = acc);
2677
+ ca_iter_state_sync_slab(&st_out);
2678
+ }
2679
+ ca_iter_state_finish(&st_in);
2680
+ ca_iter_state_finish(&st_out);
2681
+ return vout;
2682
+ }
2683
+
2684
+ static VALUE
2685
+ cummin_ki_native_i16 (VALUE self, CArray *ca, int axis)
2686
+ {
2687
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT16),
2688
+ INT2NUM(sizeof(int16_t)));
2689
+ CArray *co;
2690
+ GetCArray(vout, co);
2691
+
2692
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2693
+ iteration is one "fiber" along that axis with acc reset to
2694
+ INIT inside the macro. */
2695
+ int8_t slab_axes[CA_RANK_MAX];
2696
+ slab_axes[0] = (int8_t) axis;
2697
+ ca_iter_state st_in, st_out;
2698
+ int rc;
2699
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2700
+ slab_axes, 1, 0);
2701
+ if ( rc != CA_ITER_OK ) {
2702
+ rb_raise(rb_eRuntimeError,
2703
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2704
+ }
2705
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2706
+ slab_axes, 1, CA_KERNEL_WRITE);
2707
+ if ( rc != CA_ITER_OK ) {
2708
+ ca_iter_state_finish(&st_in);
2709
+ rb_raise(rb_eRuntimeError,
2710
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2711
+ }
2712
+
2713
+ boolean8_t *op_mask = NULL;
2714
+ if ( ca_has_mask(ca) ) {
2715
+ ca_create_mask(co);
2716
+ op_mask = (boolean8_t *) co->mask->ptr;
2717
+ }
2718
+
2719
+ char *pi, *po;
2720
+ boolean8_t *mi, *mo;
2721
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2722
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2723
+ boolean8_t *mo_fiber = op_mask
2724
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2725
+ : NULL;
2726
+ CA_SLAB_SCAN_T_GATED(int16_t, int16_t, st_in, pi, mi,
2727
+ st_out, po, mo_fiber, INT16_MAX, if (v < acc) acc = v; r = acc);
2728
+ ca_iter_state_sync_slab(&st_out);
2729
+ }
2730
+ ca_iter_state_finish(&st_in);
2731
+ ca_iter_state_finish(&st_out);
2732
+ return vout;
2733
+ }
2734
+
2735
+ static VALUE
2736
+ cummin_ki_native_u16 (VALUE self, CArray *ca, int axis)
2737
+ {
2738
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT16),
2739
+ INT2NUM(sizeof(uint16_t)));
2740
+ CArray *co;
2741
+ GetCArray(vout, co);
2742
+
2743
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2744
+ iteration is one "fiber" along that axis with acc reset to
2745
+ INIT inside the macro. */
2746
+ int8_t slab_axes[CA_RANK_MAX];
2747
+ slab_axes[0] = (int8_t) axis;
2748
+ ca_iter_state st_in, st_out;
2749
+ int rc;
2750
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2751
+ slab_axes, 1, 0);
2752
+ if ( rc != CA_ITER_OK ) {
2753
+ rb_raise(rb_eRuntimeError,
2754
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2755
+ }
2756
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2757
+ slab_axes, 1, CA_KERNEL_WRITE);
2758
+ if ( rc != CA_ITER_OK ) {
2759
+ ca_iter_state_finish(&st_in);
2760
+ rb_raise(rb_eRuntimeError,
2761
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2762
+ }
2763
+
2764
+ boolean8_t *op_mask = NULL;
2765
+ if ( ca_has_mask(ca) ) {
2766
+ ca_create_mask(co);
2767
+ op_mask = (boolean8_t *) co->mask->ptr;
2768
+ }
2769
+
2770
+ char *pi, *po;
2771
+ boolean8_t *mi, *mo;
2772
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2773
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2774
+ boolean8_t *mo_fiber = op_mask
2775
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2776
+ : NULL;
2777
+ CA_SLAB_SCAN_T_GATED(uint16_t, uint16_t, st_in, pi, mi,
2778
+ st_out, po, mo_fiber, UINT16_MAX, if (v < acc) acc = v; r = acc);
2779
+ ca_iter_state_sync_slab(&st_out);
2780
+ }
2781
+ ca_iter_state_finish(&st_in);
2782
+ ca_iter_state_finish(&st_out);
2783
+ return vout;
2784
+ }
2785
+
2786
+ static VALUE
2787
+ cummin_ki_native_i32 (VALUE self, CArray *ca, int axis)
2788
+ {
2789
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT32),
2790
+ INT2NUM(sizeof(int32_t)));
2791
+ CArray *co;
2792
+ GetCArray(vout, co);
2793
+
2794
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2795
+ iteration is one "fiber" along that axis with acc reset to
2796
+ INIT inside the macro. */
2797
+ int8_t slab_axes[CA_RANK_MAX];
2798
+ slab_axes[0] = (int8_t) axis;
2799
+ ca_iter_state st_in, st_out;
2800
+ int rc;
2801
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2802
+ slab_axes, 1, 0);
2803
+ if ( rc != CA_ITER_OK ) {
2804
+ rb_raise(rb_eRuntimeError,
2805
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2806
+ }
2807
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2808
+ slab_axes, 1, CA_KERNEL_WRITE);
2809
+ if ( rc != CA_ITER_OK ) {
2810
+ ca_iter_state_finish(&st_in);
2811
+ rb_raise(rb_eRuntimeError,
2812
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2813
+ }
2814
+
2815
+ boolean8_t *op_mask = NULL;
2816
+ if ( ca_has_mask(ca) ) {
2817
+ ca_create_mask(co);
2818
+ op_mask = (boolean8_t *) co->mask->ptr;
2819
+ }
2820
+
2821
+ char *pi, *po;
2822
+ boolean8_t *mi, *mo;
2823
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2824
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2825
+ boolean8_t *mo_fiber = op_mask
2826
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2827
+ : NULL;
2828
+ CA_SLAB_SCAN_T_GATED(int32_t, int32_t, st_in, pi, mi,
2829
+ st_out, po, mo_fiber, INT32_MAX, if (v < acc) acc = v; r = acc);
2830
+ ca_iter_state_sync_slab(&st_out);
2831
+ }
2832
+ ca_iter_state_finish(&st_in);
2833
+ ca_iter_state_finish(&st_out);
2834
+ return vout;
2835
+ }
2836
+
2837
+ static VALUE
2838
+ cummin_ki_native_u32 (VALUE self, CArray *ca, int axis)
2839
+ {
2840
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT32),
2841
+ INT2NUM(sizeof(uint32_t)));
2842
+ CArray *co;
2843
+ GetCArray(vout, co);
2844
+
2845
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2846
+ iteration is one "fiber" along that axis with acc reset to
2847
+ INIT inside the macro. */
2848
+ int8_t slab_axes[CA_RANK_MAX];
2849
+ slab_axes[0] = (int8_t) axis;
2850
+ ca_iter_state st_in, st_out;
2851
+ int rc;
2852
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2853
+ slab_axes, 1, 0);
2854
+ if ( rc != CA_ITER_OK ) {
2855
+ rb_raise(rb_eRuntimeError,
2856
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2857
+ }
2858
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2859
+ slab_axes, 1, CA_KERNEL_WRITE);
2860
+ if ( rc != CA_ITER_OK ) {
2861
+ ca_iter_state_finish(&st_in);
2862
+ rb_raise(rb_eRuntimeError,
2863
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2864
+ }
2865
+
2866
+ boolean8_t *op_mask = NULL;
2867
+ if ( ca_has_mask(ca) ) {
2868
+ ca_create_mask(co);
2869
+ op_mask = (boolean8_t *) co->mask->ptr;
2870
+ }
2871
+
2872
+ char *pi, *po;
2873
+ boolean8_t *mi, *mo;
2874
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2875
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2876
+ boolean8_t *mo_fiber = op_mask
2877
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2878
+ : NULL;
2879
+ CA_SLAB_SCAN_T_GATED(uint32_t, uint32_t, st_in, pi, mi,
2880
+ st_out, po, mo_fiber, UINT32_MAX, if (v < acc) acc = v; r = acc);
2881
+ ca_iter_state_sync_slab(&st_out);
2882
+ }
2883
+ ca_iter_state_finish(&st_in);
2884
+ ca_iter_state_finish(&st_out);
2885
+ return vout;
2886
+ }
2887
+
2888
+ static VALUE
2889
+ cummin_ki_native_i64 (VALUE self, CArray *ca, int axis)
2890
+ {
2891
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
2892
+ INT2NUM(sizeof(int64_t)));
2893
+ CArray *co;
2894
+ GetCArray(vout, co);
2895
+
2896
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2897
+ iteration is one "fiber" along that axis with acc reset to
2898
+ INIT inside the macro. */
2899
+ int8_t slab_axes[CA_RANK_MAX];
2900
+ slab_axes[0] = (int8_t) axis;
2901
+ ca_iter_state st_in, st_out;
2902
+ int rc;
2903
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2904
+ slab_axes, 1, 0);
2905
+ if ( rc != CA_ITER_OK ) {
2906
+ rb_raise(rb_eRuntimeError,
2907
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2908
+ }
2909
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2910
+ slab_axes, 1, CA_KERNEL_WRITE);
2911
+ if ( rc != CA_ITER_OK ) {
2912
+ ca_iter_state_finish(&st_in);
2913
+ rb_raise(rb_eRuntimeError,
2914
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2915
+ }
2916
+
2917
+ boolean8_t *op_mask = NULL;
2918
+ if ( ca_has_mask(ca) ) {
2919
+ ca_create_mask(co);
2920
+ op_mask = (boolean8_t *) co->mask->ptr;
2921
+ }
2922
+
2923
+ char *pi, *po;
2924
+ boolean8_t *mi, *mo;
2925
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2926
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2927
+ boolean8_t *mo_fiber = op_mask
2928
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2929
+ : NULL;
2930
+ CA_SLAB_SCAN_T_GATED(int64_t, int64_t, st_in, pi, mi,
2931
+ st_out, po, mo_fiber, INT64_MAX, if (v < acc) acc = v; r = acc);
2932
+ ca_iter_state_sync_slab(&st_out);
2933
+ }
2934
+ ca_iter_state_finish(&st_in);
2935
+ ca_iter_state_finish(&st_out);
2936
+ return vout;
2937
+ }
2938
+
2939
+ static VALUE
2940
+ cummin_ki_native_u64 (VALUE self, CArray *ca, int axis)
2941
+ {
2942
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT64),
2943
+ INT2NUM(sizeof(uint64_t)));
2944
+ CArray *co;
2945
+ GetCArray(vout, co);
2946
+
2947
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2948
+ iteration is one "fiber" along that axis with acc reset to
2949
+ INIT inside the macro. */
2950
+ int8_t slab_axes[CA_RANK_MAX];
2951
+ slab_axes[0] = (int8_t) axis;
2952
+ ca_iter_state st_in, st_out;
2953
+ int rc;
2954
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
2955
+ slab_axes, 1, 0);
2956
+ if ( rc != CA_ITER_OK ) {
2957
+ rb_raise(rb_eRuntimeError,
2958
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
2959
+ }
2960
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
2961
+ slab_axes, 1, CA_KERNEL_WRITE);
2962
+ if ( rc != CA_ITER_OK ) {
2963
+ ca_iter_state_finish(&st_in);
2964
+ rb_raise(rb_eRuntimeError,
2965
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
2966
+ }
2967
+
2968
+ boolean8_t *op_mask = NULL;
2969
+ if ( ca_has_mask(ca) ) {
2970
+ ca_create_mask(co);
2971
+ op_mask = (boolean8_t *) co->mask->ptr;
2972
+ }
2973
+
2974
+ char *pi, *po;
2975
+ boolean8_t *mi, *mo;
2976
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
2977
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
2978
+ boolean8_t *mo_fiber = op_mask
2979
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
2980
+ : NULL;
2981
+ CA_SLAB_SCAN_T_GATED(uint64_t, uint64_t, st_in, pi, mi,
2982
+ st_out, po, mo_fiber, UINT64_MAX, if (v < acc) acc = v; r = acc);
2983
+ ca_iter_state_sync_slab(&st_out);
2984
+ }
2985
+ ca_iter_state_finish(&st_in);
2986
+ ca_iter_state_finish(&st_out);
2987
+ return vout;
2988
+ }
2989
+
2990
+ static VALUE
2991
+ cummin_ki_native_f32 (VALUE self, CArray *ca, int axis)
2992
+ {
2993
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT32),
2994
+ INT2NUM(sizeof(float)));
2995
+ CArray *co;
2996
+ GetCArray(vout, co);
2997
+
2998
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
2999
+ iteration is one "fiber" along that axis with acc reset to
3000
+ INIT inside the macro. */
3001
+ int8_t slab_axes[CA_RANK_MAX];
3002
+ slab_axes[0] = (int8_t) axis;
3003
+ ca_iter_state st_in, st_out;
3004
+ int rc;
3005
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3006
+ slab_axes, 1, 0);
3007
+ if ( rc != CA_ITER_OK ) {
3008
+ rb_raise(rb_eRuntimeError,
3009
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3010
+ }
3011
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3012
+ slab_axes, 1, CA_KERNEL_WRITE);
3013
+ if ( rc != CA_ITER_OK ) {
3014
+ ca_iter_state_finish(&st_in);
3015
+ rb_raise(rb_eRuntimeError,
3016
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3017
+ }
3018
+
3019
+ boolean8_t *op_mask = NULL;
3020
+ if ( ca_has_mask(ca) ) {
3021
+ ca_create_mask(co);
3022
+ op_mask = (boolean8_t *) co->mask->ptr;
3023
+ }
3024
+
3025
+ char *pi, *po;
3026
+ boolean8_t *mi, *mo;
3027
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3028
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3029
+ boolean8_t *mo_fiber = op_mask
3030
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
3031
+ : NULL;
3032
+ CA_SLAB_SCAN_T_GATED(float, float, st_in, pi, mi,
3033
+ st_out, po, mo_fiber, NAN, acc = fmin(acc, v); r = acc);
3034
+ ca_iter_state_sync_slab(&st_out);
3035
+ }
3036
+ ca_iter_state_finish(&st_in);
3037
+ ca_iter_state_finish(&st_out);
3038
+ return vout;
3039
+ }
3040
+
3041
+ static VALUE
3042
+ cummin_ki_native_f64 (VALUE self, CArray *ca, int axis)
3043
+ {
3044
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_FLOAT64),
3045
+ INT2NUM(sizeof(double)));
3046
+ CArray *co;
3047
+ GetCArray(vout, co);
3048
+
3049
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3050
+ iteration is one "fiber" along that axis with acc reset to
3051
+ INIT inside the macro. */
3052
+ int8_t slab_axes[CA_RANK_MAX];
3053
+ slab_axes[0] = (int8_t) axis;
3054
+ ca_iter_state st_in, st_out;
3055
+ int rc;
3056
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3057
+ slab_axes, 1, 0);
3058
+ if ( rc != CA_ITER_OK ) {
3059
+ rb_raise(rb_eRuntimeError,
3060
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3061
+ }
3062
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3063
+ slab_axes, 1, CA_KERNEL_WRITE);
3064
+ if ( rc != CA_ITER_OK ) {
3065
+ ca_iter_state_finish(&st_in);
3066
+ rb_raise(rb_eRuntimeError,
3067
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3068
+ }
3069
+
3070
+ boolean8_t *op_mask = NULL;
3071
+ if ( ca_has_mask(ca) ) {
3072
+ ca_create_mask(co);
3073
+ op_mask = (boolean8_t *) co->mask->ptr;
3074
+ }
3075
+
3076
+ char *pi, *po;
3077
+ boolean8_t *mi, *mo;
3078
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3079
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3080
+ boolean8_t *mo_fiber = op_mask
3081
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
3082
+ : NULL;
3083
+ CA_SLAB_SCAN_T_GATED(double, double, st_in, pi, mi,
3084
+ st_out, po, mo_fiber, NAN, acc = fmin(acc, v); r = acc);
3085
+ ca_iter_state_sync_slab(&st_out);
3086
+ }
3087
+ ca_iter_state_finish(&st_in);
3088
+ ca_iter_state_finish(&st_out);
3089
+ return vout;
3090
+ }
3091
+
3092
+ static VALUE
3093
+ cummin_ki_native_bool (VALUE self, CArray *ca, int axis)
3094
+ {
3095
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_UINT64),
3096
+ INT2NUM(sizeof(uint64_t)));
3097
+ CArray *co;
3098
+ GetCArray(vout, co);
3099
+
3100
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3101
+ iteration is one "fiber" along that axis with acc reset to
3102
+ INIT inside the macro. */
3103
+ int8_t slab_axes[CA_RANK_MAX];
3104
+ slab_axes[0] = (int8_t) axis;
3105
+ ca_iter_state st_in, st_out;
3106
+ int rc;
3107
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3108
+ slab_axes, 1, 0);
3109
+ if ( rc != CA_ITER_OK ) {
3110
+ rb_raise(rb_eRuntimeError,
3111
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3112
+ }
3113
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3114
+ slab_axes, 1, CA_KERNEL_WRITE);
3115
+ if ( rc != CA_ITER_OK ) {
3116
+ ca_iter_state_finish(&st_in);
3117
+ rb_raise(rb_eRuntimeError,
3118
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3119
+ }
3120
+
3121
+ boolean8_t *op_mask = NULL;
3122
+ if ( ca_has_mask(ca) ) {
3123
+ ca_create_mask(co);
3124
+ op_mask = (boolean8_t *) co->mask->ptr;
3125
+ }
3126
+
3127
+ char *pi, *po;
3128
+ boolean8_t *mi, *mo;
3129
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3130
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3131
+ boolean8_t *mo_fiber = op_mask
3132
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
3133
+ : NULL;
3134
+ CA_SLAB_SCAN_T_GATED(boolean8_t, uint64_t, st_in, pi, mi,
3135
+ st_out, po, mo_fiber, 1, if ((uint64_t) v < acc) acc = v; r = acc);
3136
+ ca_iter_state_sync_slab(&st_out);
3137
+ }
3138
+ ca_iter_state_finish(&st_in);
3139
+ ca_iter_state_finish(&st_out);
3140
+ return vout;
3141
+ }
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
+
3153
+ static VALUE
3154
+ cummin_ki_native_object_body (VALUE arg)
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])
3165
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT),
3166
+ INT2NUM(sizeof(VALUE)));
3167
+ CArray *co;
3168
+ GetCArray(vout, co);
3169
+
3170
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3171
+ iteration is one "fiber" along that axis with acc reset to
3172
+ INIT inside the macro. */
3173
+ int8_t slab_axes[CA_RANK_MAX];
3174
+ slab_axes[0] = (int8_t) axis;
3175
+ int rc;
3176
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3177
+ slab_axes, 1, 0);
3178
+ if ( rc != CA_ITER_OK ) {
3179
+ rb_raise(rb_eRuntimeError,
3180
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3181
+ }
3182
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3183
+ slab_axes, 1, CA_KERNEL_WRITE);
3184
+ if ( rc != CA_ITER_OK ) {
3185
+ ca_iter_state_finish(&st_in);
3186
+ rb_raise(rb_eRuntimeError,
3187
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3188
+ }
3189
+
3190
+ boolean8_t *op_mask = NULL;
3191
+ if ( ca_has_mask(ca) ) {
3192
+ ca_create_mask(co);
3193
+ op_mask = (boolean8_t *) co->mask->ptr;
3194
+ }
3195
+
3196
+ char *pi, *po;
3197
+ boolean8_t *mi, *mo;
3198
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3199
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3200
+ boolean8_t *mo_fiber = op_mask
3201
+ ? op_mask + (ca_size_t)(po - st_out.alias_ptr) / (ca_size_t) co->bytes
3202
+ : NULL;
3203
+ CA_SLAB_SCAN_T_GATED(VALUE, VALUE, st_in, pi, mi,
3204
+ st_out, po, mo_fiber, Qnil, if (acc == Qnil || ca_obj_extremum_replaces(v, acc, rb_intern("<"))) acc = v; r = acc);
3205
+ ca_iter_state_sync_slab(&st_out);
3206
+ }
3207
+ ca_iter_state_finish(&st_in);
3208
+ ca_iter_state_finish(&st_out);
3209
+ return vout;
3210
+ #undef st_in
3211
+ #undef st_out
3212
+ }
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
+
3227
+ static VALUE
3228
+ rb_ca_cummin_ki (int argc, VALUE *argv, VALUE self)
3229
+ {
3230
+ CArray *src;
3231
+ VALUE result;
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
+ }
3290
+ volatile VALUE ropt = rb_pop_options(&argc, &argv);
3291
+ volatile VALUE raxis = Qnil;
3292
+ rb_scan_options(ropt, "axis", &raxis);
3293
+ if ( argc > 0 ) {
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);
3295
+ }
3296
+ if ( NIL_P(raxis) ) {
3297
+ volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
3298
+ CArray *fsrc;
3299
+ GetCArray(vflat, fsrc);
3300
+ switch ( fsrc->data_type ) {
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));
3313
+ default:
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]);
3316
+ }
3317
+ }
3318
+ if ( TYPE(raxis) == T_ARRAY ) {
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());
3320
+ }
3321
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
3322
+ switch ( src->data_type ) {
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));
3335
+ default:
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]);
3338
+ }
3339
+ return Qnil; /* unreachable */
3340
+ }
3341
+
3342
+ /* ===== cumcount_ki ============================================ */
3343
+
3344
+ static VALUE
3345
+ cumcount_ki_native_i8 (VALUE self, CArray *ca, int axis)
3346
+ {
3347
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3348
+ INT2NUM(sizeof(int64_t)));
3349
+ CArray *co;
3350
+ GetCArray(vout, co);
3351
+
3352
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3353
+ iteration is one "fiber" along that axis with acc reset to
3354
+ INIT inside the macro. */
3355
+ int8_t slab_axes[CA_RANK_MAX];
3356
+ slab_axes[0] = (int8_t) axis;
3357
+ ca_iter_state st_in, st_out;
3358
+ int rc;
3359
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3360
+ slab_axes, 1, 0);
3361
+ if ( rc != CA_ITER_OK ) {
3362
+ rb_raise(rb_eRuntimeError,
3363
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3364
+ }
3365
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3366
+ slab_axes, 1, CA_KERNEL_WRITE);
3367
+ if ( rc != CA_ITER_OK ) {
3368
+ ca_iter_state_finish(&st_in);
3369
+ rb_raise(rb_eRuntimeError,
3370
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3371
+ }
3372
+
3373
+ char *pi, *po;
3374
+ boolean8_t *mi, *mo;
3375
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3376
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3377
+ CA_SLAB_SCAN_T(int8_t, int64_t, st_in, pi, mi,
3378
+ st_out, po, 0, (void) v; r = ++acc);
3379
+ ca_iter_state_sync_slab(&st_out);
3380
+ }
3381
+ ca_iter_state_finish(&st_in);
3382
+ ca_iter_state_finish(&st_out);
3383
+ return vout;
3384
+ }
3385
+
3386
+ static VALUE
3387
+ cumcount_ki_native_u8 (VALUE self, CArray *ca, int axis)
3388
+ {
3389
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3390
+ INT2NUM(sizeof(int64_t)));
3391
+ CArray *co;
3392
+ GetCArray(vout, co);
3393
+
3394
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3395
+ iteration is one "fiber" along that axis with acc reset to
3396
+ INIT inside the macro. */
3397
+ int8_t slab_axes[CA_RANK_MAX];
3398
+ slab_axes[0] = (int8_t) axis;
3399
+ ca_iter_state st_in, st_out;
3400
+ int rc;
3401
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3402
+ slab_axes, 1, 0);
3403
+ if ( rc != CA_ITER_OK ) {
3404
+ rb_raise(rb_eRuntimeError,
3405
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3406
+ }
3407
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3408
+ slab_axes, 1, CA_KERNEL_WRITE);
3409
+ if ( rc != CA_ITER_OK ) {
3410
+ ca_iter_state_finish(&st_in);
3411
+ rb_raise(rb_eRuntimeError,
3412
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3413
+ }
3414
+
3415
+ char *pi, *po;
3416
+ boolean8_t *mi, *mo;
3417
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3418
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3419
+ CA_SLAB_SCAN_T(uint8_t, int64_t, st_in, pi, mi,
3420
+ st_out, po, 0, (void) v; r = ++acc);
3421
+ ca_iter_state_sync_slab(&st_out);
3422
+ }
3423
+ ca_iter_state_finish(&st_in);
3424
+ ca_iter_state_finish(&st_out);
3425
+ return vout;
3426
+ }
3427
+
3428
+ static VALUE
3429
+ cumcount_ki_native_i16 (VALUE self, CArray *ca, int axis)
3430
+ {
3431
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3432
+ INT2NUM(sizeof(int64_t)));
3433
+ CArray *co;
3434
+ GetCArray(vout, co);
3435
+
3436
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3437
+ iteration is one "fiber" along that axis with acc reset to
3438
+ INIT inside the macro. */
3439
+ int8_t slab_axes[CA_RANK_MAX];
3440
+ slab_axes[0] = (int8_t) axis;
3441
+ ca_iter_state st_in, st_out;
3442
+ int rc;
3443
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3444
+ slab_axes, 1, 0);
3445
+ if ( rc != CA_ITER_OK ) {
3446
+ rb_raise(rb_eRuntimeError,
3447
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3448
+ }
3449
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3450
+ slab_axes, 1, CA_KERNEL_WRITE);
3451
+ if ( rc != CA_ITER_OK ) {
3452
+ ca_iter_state_finish(&st_in);
3453
+ rb_raise(rb_eRuntimeError,
3454
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3455
+ }
3456
+
3457
+ char *pi, *po;
3458
+ boolean8_t *mi, *mo;
3459
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3460
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3461
+ CA_SLAB_SCAN_T(int16_t, int64_t, st_in, pi, mi,
3462
+ st_out, po, 0, (void) v; r = ++acc);
3463
+ ca_iter_state_sync_slab(&st_out);
3464
+ }
3465
+ ca_iter_state_finish(&st_in);
3466
+ ca_iter_state_finish(&st_out);
3467
+ return vout;
3468
+ }
3469
+
3470
+ static VALUE
3471
+ cumcount_ki_native_u16 (VALUE self, CArray *ca, int axis)
3472
+ {
3473
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3474
+ INT2NUM(sizeof(int64_t)));
3475
+ CArray *co;
3476
+ GetCArray(vout, co);
3477
+
3478
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3479
+ iteration is one "fiber" along that axis with acc reset to
3480
+ INIT inside the macro. */
3481
+ int8_t slab_axes[CA_RANK_MAX];
3482
+ slab_axes[0] = (int8_t) axis;
3483
+ ca_iter_state st_in, st_out;
3484
+ int rc;
3485
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3486
+ slab_axes, 1, 0);
3487
+ if ( rc != CA_ITER_OK ) {
3488
+ rb_raise(rb_eRuntimeError,
3489
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3490
+ }
3491
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3492
+ slab_axes, 1, CA_KERNEL_WRITE);
3493
+ if ( rc != CA_ITER_OK ) {
3494
+ ca_iter_state_finish(&st_in);
3495
+ rb_raise(rb_eRuntimeError,
3496
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3497
+ }
3498
+
3499
+ char *pi, *po;
3500
+ boolean8_t *mi, *mo;
3501
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3502
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3503
+ CA_SLAB_SCAN_T(uint16_t, int64_t, st_in, pi, mi,
3504
+ st_out, po, 0, (void) v; r = ++acc);
3505
+ ca_iter_state_sync_slab(&st_out);
3506
+ }
3507
+ ca_iter_state_finish(&st_in);
3508
+ ca_iter_state_finish(&st_out);
3509
+ return vout;
3510
+ }
3511
+
3512
+ static VALUE
3513
+ cumcount_ki_native_i32 (VALUE self, CArray *ca, int axis)
3514
+ {
3515
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3516
+ INT2NUM(sizeof(int64_t)));
3517
+ CArray *co;
3518
+ GetCArray(vout, co);
3519
+
3520
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3521
+ iteration is one "fiber" along that axis with acc reset to
3522
+ INIT inside the macro. */
3523
+ int8_t slab_axes[CA_RANK_MAX];
3524
+ slab_axes[0] = (int8_t) axis;
3525
+ ca_iter_state st_in, st_out;
3526
+ int rc;
3527
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3528
+ slab_axes, 1, 0);
3529
+ if ( rc != CA_ITER_OK ) {
3530
+ rb_raise(rb_eRuntimeError,
3531
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3532
+ }
3533
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3534
+ slab_axes, 1, CA_KERNEL_WRITE);
3535
+ if ( rc != CA_ITER_OK ) {
3536
+ ca_iter_state_finish(&st_in);
3537
+ rb_raise(rb_eRuntimeError,
3538
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3539
+ }
3540
+
3541
+ char *pi, *po;
3542
+ boolean8_t *mi, *mo;
3543
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3544
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3545
+ CA_SLAB_SCAN_T(int32_t, int64_t, st_in, pi, mi,
3546
+ st_out, po, 0, (void) v; r = ++acc);
3547
+ ca_iter_state_sync_slab(&st_out);
3548
+ }
3549
+ ca_iter_state_finish(&st_in);
3550
+ ca_iter_state_finish(&st_out);
3551
+ return vout;
3552
+ }
3553
+
3554
+ static VALUE
3555
+ cumcount_ki_native_u32 (VALUE self, CArray *ca, int axis)
3556
+ {
3557
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3558
+ INT2NUM(sizeof(int64_t)));
3559
+ CArray *co;
3560
+ GetCArray(vout, co);
3561
+
3562
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3563
+ iteration is one "fiber" along that axis with acc reset to
3564
+ INIT inside the macro. */
3565
+ int8_t slab_axes[CA_RANK_MAX];
3566
+ slab_axes[0] = (int8_t) axis;
3567
+ ca_iter_state st_in, st_out;
3568
+ int rc;
3569
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3570
+ slab_axes, 1, 0);
3571
+ if ( rc != CA_ITER_OK ) {
3572
+ rb_raise(rb_eRuntimeError,
3573
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3574
+ }
3575
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3576
+ slab_axes, 1, CA_KERNEL_WRITE);
3577
+ if ( rc != CA_ITER_OK ) {
3578
+ ca_iter_state_finish(&st_in);
3579
+ rb_raise(rb_eRuntimeError,
3580
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3581
+ }
3582
+
3583
+ char *pi, *po;
3584
+ boolean8_t *mi, *mo;
3585
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3586
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3587
+ CA_SLAB_SCAN_T(uint32_t, int64_t, st_in, pi, mi,
3588
+ st_out, po, 0, (void) v; r = ++acc);
3589
+ ca_iter_state_sync_slab(&st_out);
3590
+ }
3591
+ ca_iter_state_finish(&st_in);
3592
+ ca_iter_state_finish(&st_out);
3593
+ return vout;
3594
+ }
3595
+
3596
+ static VALUE
3597
+ cumcount_ki_native_i64 (VALUE self, CArray *ca, int axis)
3598
+ {
3599
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3600
+ INT2NUM(sizeof(int64_t)));
3601
+ CArray *co;
3602
+ GetCArray(vout, co);
3603
+
3604
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3605
+ iteration is one "fiber" along that axis with acc reset to
3606
+ INIT inside the macro. */
3607
+ int8_t slab_axes[CA_RANK_MAX];
3608
+ slab_axes[0] = (int8_t) axis;
3609
+ ca_iter_state st_in, st_out;
3610
+ int rc;
3611
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3612
+ slab_axes, 1, 0);
3613
+ if ( rc != CA_ITER_OK ) {
3614
+ rb_raise(rb_eRuntimeError,
3615
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3616
+ }
3617
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3618
+ slab_axes, 1, CA_KERNEL_WRITE);
3619
+ if ( rc != CA_ITER_OK ) {
3620
+ ca_iter_state_finish(&st_in);
3621
+ rb_raise(rb_eRuntimeError,
3622
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3623
+ }
3624
+
3625
+ char *pi, *po;
3626
+ boolean8_t *mi, *mo;
3627
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3628
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3629
+ CA_SLAB_SCAN_T(int64_t, int64_t, st_in, pi, mi,
3630
+ st_out, po, 0, (void) v; r = ++acc);
3631
+ ca_iter_state_sync_slab(&st_out);
3632
+ }
3633
+ ca_iter_state_finish(&st_in);
3634
+ ca_iter_state_finish(&st_out);
3635
+ return vout;
3636
+ }
3637
+
3638
+ static VALUE
3639
+ cumcount_ki_native_u64 (VALUE self, CArray *ca, int axis)
3640
+ {
3641
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3642
+ INT2NUM(sizeof(int64_t)));
3643
+ CArray *co;
3644
+ GetCArray(vout, co);
3645
+
3646
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3647
+ iteration is one "fiber" along that axis with acc reset to
3648
+ INIT inside the macro. */
3649
+ int8_t slab_axes[CA_RANK_MAX];
3650
+ slab_axes[0] = (int8_t) axis;
3651
+ ca_iter_state st_in, st_out;
3652
+ int rc;
3653
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3654
+ slab_axes, 1, 0);
3655
+ if ( rc != CA_ITER_OK ) {
3656
+ rb_raise(rb_eRuntimeError,
3657
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3658
+ }
3659
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3660
+ slab_axes, 1, CA_KERNEL_WRITE);
3661
+ if ( rc != CA_ITER_OK ) {
3662
+ ca_iter_state_finish(&st_in);
3663
+ rb_raise(rb_eRuntimeError,
3664
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3665
+ }
3666
+
3667
+ char *pi, *po;
3668
+ boolean8_t *mi, *mo;
3669
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3670
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3671
+ CA_SLAB_SCAN_T(uint64_t, int64_t, st_in, pi, mi,
3672
+ st_out, po, 0, (void) v; r = ++acc);
3673
+ ca_iter_state_sync_slab(&st_out);
3674
+ }
3675
+ ca_iter_state_finish(&st_in);
3676
+ ca_iter_state_finish(&st_out);
3677
+ return vout;
3678
+ }
3679
+
3680
+ static VALUE
3681
+ cumcount_ki_native_f32 (VALUE self, CArray *ca, int axis)
3682
+ {
3683
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3684
+ INT2NUM(sizeof(int64_t)));
3685
+ CArray *co;
3686
+ GetCArray(vout, co);
3687
+
3688
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3689
+ iteration is one "fiber" along that axis with acc reset to
3690
+ INIT inside the macro. */
3691
+ int8_t slab_axes[CA_RANK_MAX];
3692
+ slab_axes[0] = (int8_t) axis;
3693
+ ca_iter_state st_in, st_out;
3694
+ int rc;
3695
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3696
+ slab_axes, 1, 0);
3697
+ if ( rc != CA_ITER_OK ) {
3698
+ rb_raise(rb_eRuntimeError,
3699
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3700
+ }
3701
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3702
+ slab_axes, 1, CA_KERNEL_WRITE);
3703
+ if ( rc != CA_ITER_OK ) {
3704
+ ca_iter_state_finish(&st_in);
3705
+ rb_raise(rb_eRuntimeError,
3706
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3707
+ }
3708
+
3709
+ char *pi, *po;
3710
+ boolean8_t *mi, *mo;
3711
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3712
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3713
+ CA_SLAB_SCAN_T(float, int64_t, st_in, pi, mi,
3714
+ st_out, po, 0, (void) v; r = ++acc);
3715
+ ca_iter_state_sync_slab(&st_out);
3716
+ }
3717
+ ca_iter_state_finish(&st_in);
3718
+ ca_iter_state_finish(&st_out);
3719
+ return vout;
3720
+ }
3721
+
3722
+ static VALUE
3723
+ cumcount_ki_native_f64 (VALUE self, CArray *ca, int axis)
3724
+ {
3725
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_INT64),
3726
+ INT2NUM(sizeof(int64_t)));
3727
+ CArray *co;
3728
+ GetCArray(vout, co);
3729
+
3730
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3731
+ iteration is one "fiber" along that axis with acc reset to
3732
+ INIT inside the macro. */
3733
+ int8_t slab_axes[CA_RANK_MAX];
3734
+ slab_axes[0] = (int8_t) axis;
3735
+ ca_iter_state st_in, st_out;
3736
+ int rc;
3737
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3738
+ slab_axes, 1, 0);
3739
+ if ( rc != CA_ITER_OK ) {
3740
+ rb_raise(rb_eRuntimeError,
3741
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3742
+ }
3743
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3744
+ slab_axes, 1, CA_KERNEL_WRITE);
3745
+ if ( rc != CA_ITER_OK ) {
3746
+ ca_iter_state_finish(&st_in);
3747
+ rb_raise(rb_eRuntimeError,
3748
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3749
+ }
3750
+
3751
+ char *pi, *po;
3752
+ boolean8_t *mi, *mo;
3753
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3754
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3755
+ CA_SLAB_SCAN_T(double, int64_t, st_in, pi, mi,
3756
+ st_out, po, 0, (void) v; r = ++acc);
3757
+ ca_iter_state_sync_slab(&st_out);
3758
+ }
3759
+ ca_iter_state_finish(&st_in);
3760
+ ca_iter_state_finish(&st_out);
3761
+ return vout;
3762
+ }
3763
+
3764
+ static VALUE
3765
+ rb_ca_cumcount_ki (int argc, VALUE *argv, VALUE self)
3766
+ {
3767
+ CArray *src;
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
+ }
3776
+ volatile VALUE ropt = rb_pop_options(&argc, &argv);
3777
+ volatile VALUE raxis = Qnil;
3778
+ rb_scan_options(ropt, "axis", &raxis);
3779
+ if ( argc > 0 ) {
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);
3781
+ }
3782
+ if ( NIL_P(raxis) ) {
3783
+ volatile VALUE vflat = rb_funcall(self, rb_intern("flatten"), 0);
3784
+ CArray *fsrc;
3785
+ GetCArray(vflat, fsrc);
3786
+ switch ( fsrc->data_type ) {
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);
3799
+ }
3800
+ }
3801
+ if ( TYPE(raxis) == T_ARRAY ) {
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());
3803
+ }
3804
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
3805
+ switch ( src->data_type ) {
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));
3818
+ }
3819
+ return Qnil; /* unreachable */
3820
+ }
3821
+
3822
+ /* ===== uniq_scan_ki ============================================ */
3823
+
3824
+ static VALUE
3825
+ uniq_scan_ki_native_i8 (VALUE self, CArray *ca, int axis)
3826
+ {
3827
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
3828
+ INT2NUM(sizeof(boolean8_t)));
3829
+ CArray *co;
3830
+ GetCArray(vout, co);
3831
+
3832
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3833
+ iteration is one "fiber" along that axis with acc reset to
3834
+ INIT inside the macro. */
3835
+ int8_t slab_axes[CA_RANK_MAX];
3836
+ slab_axes[0] = (int8_t) axis;
3837
+ ca_iter_state st_in, st_out;
3838
+ int rc;
3839
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3840
+ slab_axes, 1, 0);
3841
+ if ( rc != CA_ITER_OK ) {
3842
+ rb_raise(rb_eRuntimeError,
3843
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3844
+ }
3845
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3846
+ slab_axes, 1, CA_KERNEL_WRITE);
3847
+ if ( rc != CA_ITER_OK ) {
3848
+ ca_iter_state_finish(&st_in);
3849
+ rb_raise(rb_eRuntimeError,
3850
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3851
+ }
3852
+
3853
+ char *pi, *po;
3854
+ boolean8_t *mi, *mo;
3855
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3856
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3857
+ CA_SLAB_SCAN_TA(int8_t, boolean8_t, int8_t, st_in, pi, mi,
3858
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
3859
+ ca_iter_state_sync_slab(&st_out);
3860
+ }
3861
+ ca_iter_state_finish(&st_in);
3862
+ ca_iter_state_finish(&st_out);
3863
+ return vout;
3864
+ }
3865
+
3866
+ static VALUE
3867
+ uniq_scan_ki_native_u8 (VALUE self, CArray *ca, int axis)
3868
+ {
3869
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
3870
+ INT2NUM(sizeof(boolean8_t)));
3871
+ CArray *co;
3872
+ GetCArray(vout, co);
3873
+
3874
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3875
+ iteration is one "fiber" along that axis with acc reset to
3876
+ INIT inside the macro. */
3877
+ int8_t slab_axes[CA_RANK_MAX];
3878
+ slab_axes[0] = (int8_t) axis;
3879
+ ca_iter_state st_in, st_out;
3880
+ int rc;
3881
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3882
+ slab_axes, 1, 0);
3883
+ if ( rc != CA_ITER_OK ) {
3884
+ rb_raise(rb_eRuntimeError,
3885
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3886
+ }
3887
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3888
+ slab_axes, 1, CA_KERNEL_WRITE);
3889
+ if ( rc != CA_ITER_OK ) {
3890
+ ca_iter_state_finish(&st_in);
3891
+ rb_raise(rb_eRuntimeError,
3892
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3893
+ }
3894
+
3895
+ char *pi, *po;
3896
+ boolean8_t *mi, *mo;
3897
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3898
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3899
+ CA_SLAB_SCAN_TA(uint8_t, boolean8_t, uint8_t, st_in, pi, mi,
3900
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
3901
+ ca_iter_state_sync_slab(&st_out);
3902
+ }
3903
+ ca_iter_state_finish(&st_in);
3904
+ ca_iter_state_finish(&st_out);
3905
+ return vout;
3906
+ }
3907
+
3908
+ static VALUE
3909
+ uniq_scan_ki_native_i16 (VALUE self, CArray *ca, int axis)
3910
+ {
3911
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
3912
+ INT2NUM(sizeof(boolean8_t)));
3913
+ CArray *co;
3914
+ GetCArray(vout, co);
3915
+
3916
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3917
+ iteration is one "fiber" along that axis with acc reset to
3918
+ INIT inside the macro. */
3919
+ int8_t slab_axes[CA_RANK_MAX];
3920
+ slab_axes[0] = (int8_t) axis;
3921
+ ca_iter_state st_in, st_out;
3922
+ int rc;
3923
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3924
+ slab_axes, 1, 0);
3925
+ if ( rc != CA_ITER_OK ) {
3926
+ rb_raise(rb_eRuntimeError,
3927
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3928
+ }
3929
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3930
+ slab_axes, 1, CA_KERNEL_WRITE);
3931
+ if ( rc != CA_ITER_OK ) {
3932
+ ca_iter_state_finish(&st_in);
3933
+ rb_raise(rb_eRuntimeError,
3934
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3935
+ }
3936
+
3937
+ char *pi, *po;
3938
+ boolean8_t *mi, *mo;
3939
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3940
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3941
+ CA_SLAB_SCAN_TA(int16_t, boolean8_t, int16_t, st_in, pi, mi,
3942
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
3943
+ ca_iter_state_sync_slab(&st_out);
3944
+ }
3945
+ ca_iter_state_finish(&st_in);
3946
+ ca_iter_state_finish(&st_out);
3947
+ return vout;
3948
+ }
3949
+
3950
+ static VALUE
3951
+ uniq_scan_ki_native_u16 (VALUE self, CArray *ca, int axis)
3952
+ {
3953
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
3954
+ INT2NUM(sizeof(boolean8_t)));
3955
+ CArray *co;
3956
+ GetCArray(vout, co);
3957
+
3958
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
3959
+ iteration is one "fiber" along that axis with acc reset to
3960
+ INIT inside the macro. */
3961
+ int8_t slab_axes[CA_RANK_MAX];
3962
+ slab_axes[0] = (int8_t) axis;
3963
+ ca_iter_state st_in, st_out;
3964
+ int rc;
3965
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
3966
+ slab_axes, 1, 0);
3967
+ if ( rc != CA_ITER_OK ) {
3968
+ rb_raise(rb_eRuntimeError,
3969
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
3970
+ }
3971
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
3972
+ slab_axes, 1, CA_KERNEL_WRITE);
3973
+ if ( rc != CA_ITER_OK ) {
3974
+ ca_iter_state_finish(&st_in);
3975
+ rb_raise(rb_eRuntimeError,
3976
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
3977
+ }
3978
+
3979
+ char *pi, *po;
3980
+ boolean8_t *mi, *mo;
3981
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
3982
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
3983
+ CA_SLAB_SCAN_TA(uint16_t, boolean8_t, uint16_t, st_in, pi, mi,
3984
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
3985
+ ca_iter_state_sync_slab(&st_out);
3986
+ }
3987
+ ca_iter_state_finish(&st_in);
3988
+ ca_iter_state_finish(&st_out);
3989
+ return vout;
3990
+ }
3991
+
3992
+ static VALUE
3993
+ uniq_scan_ki_native_i32 (VALUE self, CArray *ca, int axis)
3994
+ {
3995
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
3996
+ INT2NUM(sizeof(boolean8_t)));
3997
+ CArray *co;
3998
+ GetCArray(vout, co);
3999
+
4000
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
4001
+ iteration is one "fiber" along that axis with acc reset to
4002
+ INIT inside the macro. */
4003
+ int8_t slab_axes[CA_RANK_MAX];
4004
+ slab_axes[0] = (int8_t) axis;
4005
+ ca_iter_state st_in, st_out;
4006
+ int rc;
4007
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
4008
+ slab_axes, 1, 0);
4009
+ if ( rc != CA_ITER_OK ) {
4010
+ rb_raise(rb_eRuntimeError,
4011
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
4012
+ }
4013
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
4014
+ slab_axes, 1, CA_KERNEL_WRITE);
4015
+ if ( rc != CA_ITER_OK ) {
4016
+ ca_iter_state_finish(&st_in);
4017
+ rb_raise(rb_eRuntimeError,
4018
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
4019
+ }
4020
+
4021
+ char *pi, *po;
4022
+ boolean8_t *mi, *mo;
4023
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
4024
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
4025
+ CA_SLAB_SCAN_TA(int32_t, boolean8_t, int32_t, st_in, pi, mi,
4026
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
4027
+ ca_iter_state_sync_slab(&st_out);
4028
+ }
4029
+ ca_iter_state_finish(&st_in);
4030
+ ca_iter_state_finish(&st_out);
4031
+ return vout;
4032
+ }
4033
+
4034
+ static VALUE
4035
+ uniq_scan_ki_native_u32 (VALUE self, CArray *ca, int axis)
4036
+ {
4037
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
4038
+ INT2NUM(sizeof(boolean8_t)));
4039
+ CArray *co;
4040
+ GetCArray(vout, co);
4041
+
4042
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
4043
+ iteration is one "fiber" along that axis with acc reset to
4044
+ INIT inside the macro. */
4045
+ int8_t slab_axes[CA_RANK_MAX];
4046
+ slab_axes[0] = (int8_t) axis;
4047
+ ca_iter_state st_in, st_out;
4048
+ int rc;
4049
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
4050
+ slab_axes, 1, 0);
4051
+ if ( rc != CA_ITER_OK ) {
4052
+ rb_raise(rb_eRuntimeError,
4053
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
4054
+ }
4055
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
4056
+ slab_axes, 1, CA_KERNEL_WRITE);
4057
+ if ( rc != CA_ITER_OK ) {
4058
+ ca_iter_state_finish(&st_in);
4059
+ rb_raise(rb_eRuntimeError,
4060
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
4061
+ }
4062
+
4063
+ char *pi, *po;
4064
+ boolean8_t *mi, *mo;
4065
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
4066
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
4067
+ CA_SLAB_SCAN_TA(uint32_t, boolean8_t, uint32_t, st_in, pi, mi,
4068
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
4069
+ ca_iter_state_sync_slab(&st_out);
4070
+ }
4071
+ ca_iter_state_finish(&st_in);
4072
+ ca_iter_state_finish(&st_out);
4073
+ return vout;
4074
+ }
4075
+
4076
+ static VALUE
4077
+ uniq_scan_ki_native_i64 (VALUE self, CArray *ca, int axis)
4078
+ {
4079
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
4080
+ INT2NUM(sizeof(boolean8_t)));
4081
+ CArray *co;
4082
+ GetCArray(vout, co);
4083
+
4084
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
4085
+ iteration is one "fiber" along that axis with acc reset to
4086
+ INIT inside the macro. */
4087
+ int8_t slab_axes[CA_RANK_MAX];
4088
+ slab_axes[0] = (int8_t) axis;
4089
+ ca_iter_state st_in, st_out;
4090
+ int rc;
4091
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
4092
+ slab_axes, 1, 0);
4093
+ if ( rc != CA_ITER_OK ) {
4094
+ rb_raise(rb_eRuntimeError,
4095
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
4096
+ }
4097
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
4098
+ slab_axes, 1, CA_KERNEL_WRITE);
4099
+ if ( rc != CA_ITER_OK ) {
4100
+ ca_iter_state_finish(&st_in);
4101
+ rb_raise(rb_eRuntimeError,
4102
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
4103
+ }
4104
+
4105
+ char *pi, *po;
4106
+ boolean8_t *mi, *mo;
4107
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
4108
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
4109
+ CA_SLAB_SCAN_TA(int64_t, boolean8_t, int64_t, st_in, pi, mi,
4110
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
4111
+ ca_iter_state_sync_slab(&st_out);
4112
+ }
4113
+ ca_iter_state_finish(&st_in);
4114
+ ca_iter_state_finish(&st_out);
4115
+ return vout;
4116
+ }
4117
+
4118
+ static VALUE
4119
+ uniq_scan_ki_native_u64 (VALUE self, CArray *ca, int axis)
4120
+ {
4121
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
4122
+ INT2NUM(sizeof(boolean8_t)));
4123
+ CArray *co;
4124
+ GetCArray(vout, co);
4125
+
4126
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
4127
+ iteration is one "fiber" along that axis with acc reset to
4128
+ INIT inside the macro. */
4129
+ int8_t slab_axes[CA_RANK_MAX];
4130
+ slab_axes[0] = (int8_t) axis;
4131
+ ca_iter_state st_in, st_out;
4132
+ int rc;
4133
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
4134
+ slab_axes, 1, 0);
4135
+ if ( rc != CA_ITER_OK ) {
4136
+ rb_raise(rb_eRuntimeError,
4137
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
4138
+ }
4139
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
4140
+ slab_axes, 1, CA_KERNEL_WRITE);
4141
+ if ( rc != CA_ITER_OK ) {
4142
+ ca_iter_state_finish(&st_in);
4143
+ rb_raise(rb_eRuntimeError,
4144
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
4145
+ }
4146
+
4147
+ char *pi, *po;
4148
+ boolean8_t *mi, *mo;
4149
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
4150
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
4151
+ CA_SLAB_SCAN_TA(uint64_t, boolean8_t, uint64_t, st_in, pi, mi,
4152
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
4153
+ ca_iter_state_sync_slab(&st_out);
4154
+ }
4155
+ ca_iter_state_finish(&st_in);
4156
+ ca_iter_state_finish(&st_out);
4157
+ return vout;
4158
+ }
4159
+
4160
+ static VALUE
4161
+ uniq_scan_ki_native_f32 (VALUE self, CArray *ca, int axis)
4162
+ {
4163
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
4164
+ INT2NUM(sizeof(boolean8_t)));
4165
+ CArray *co;
4166
+ GetCArray(vout, co);
4167
+
4168
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
4169
+ iteration is one "fiber" along that axis with acc reset to
4170
+ INIT inside the macro. */
4171
+ int8_t slab_axes[CA_RANK_MAX];
4172
+ slab_axes[0] = (int8_t) axis;
4173
+ ca_iter_state st_in, st_out;
4174
+ int rc;
4175
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
4176
+ slab_axes, 1, 0);
4177
+ if ( rc != CA_ITER_OK ) {
4178
+ rb_raise(rb_eRuntimeError,
4179
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
4180
+ }
4181
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
4182
+ slab_axes, 1, CA_KERNEL_WRITE);
4183
+ if ( rc != CA_ITER_OK ) {
4184
+ ca_iter_state_finish(&st_in);
4185
+ rb_raise(rb_eRuntimeError,
4186
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
4187
+ }
4188
+
4189
+ char *pi, *po;
4190
+ boolean8_t *mi, *mo;
4191
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
4192
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
4193
+ CA_SLAB_SCAN_TA(float, boolean8_t, float, st_in, pi, mi,
4194
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
4195
+ ca_iter_state_sync_slab(&st_out);
4196
+ }
4197
+ ca_iter_state_finish(&st_in);
4198
+ ca_iter_state_finish(&st_out);
4199
+ return vout;
4200
+ }
4201
+
4202
+ static VALUE
4203
+ uniq_scan_ki_native_f64 (VALUE self, CArray *ca, int axis)
4204
+ {
4205
+ VALUE vout = rb_ca_template_with_type(self, INT2NUM(CA_BOOLEAN),
4206
+ INT2NUM(sizeof(boolean8_t)));
4207
+ CArray *co;
4208
+ GetCArray(vout, co);
4209
+
4210
+ /* 1-axis scan: slab = the scan axis only. Each next_slab_axes
4211
+ iteration is one "fiber" along that axis with acc reset to
4212
+ INIT inside the macro. */
4213
+ int8_t slab_axes[CA_RANK_MAX];
4214
+ slab_axes[0] = (int8_t) axis;
4215
+ ca_iter_state st_in, st_out;
4216
+ int rc;
4217
+ rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES,
4218
+ slab_axes, 1, 0);
4219
+ if ( rc != CA_ITER_OK ) {
4220
+ rb_raise(rb_eRuntimeError,
4221
+ "%s: input init failed rc=%d", ca_calling_method_name(), rc);
4222
+ }
4223
+ rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
4224
+ slab_axes, 1, CA_KERNEL_WRITE);
4225
+ if ( rc != CA_ITER_OK ) {
4226
+ ca_iter_state_finish(&st_in);
4227
+ rb_raise(rb_eRuntimeError,
4228
+ "%s: output init failed rc=%d", ca_calling_method_name(), rc);
4229
+ }
4230
+
4231
+ char *pi, *po;
4232
+ boolean8_t *mi, *mo;
4233
+ while ( ca_iter_state_next_slab_axes(&st_in, &pi, &mi) &&
4234
+ ca_iter_state_next_slab_axes(&st_out, &po, &mo) ) {
4235
+ CA_SLAB_SCAN_TA(double, boolean8_t, double, st_in, pi, mi,
4236
+ st_out, po, 0, if (first) { acc = v; r = 0; } else if (v == acc) { r = 1; } else { acc = v; r = 0; });
4237
+ ca_iter_state_sync_slab(&st_out);
4238
+ }
4239
+ ca_iter_state_finish(&st_in);
4240
+ ca_iter_state_finish(&st_out);
4241
+ return vout;
4242
+ }
4243
+
4244
+ static VALUE
4245
+ rb_ca_uniq_scan_ki (int argc, VALUE *argv, VALUE self)
4246
+ {
4247
+ CArray *src;
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
+ }
4256
+ volatile VALUE ropt = rb_pop_options(&argc, &argv);
4257
+ volatile VALUE raxis = Qnil;
4258
+ rb_scan_options(ropt, "axis", &raxis);
4259
+ if ( argc > 0 ) {
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);
4261
+ }
4262
+ if ( NIL_P(raxis) ) {
4263
+ rb_raise(rb_eArgError, "%s: axis: is required (a single Integer; a scan over several axes is ambiguous)", ca_calling_method_name());
4264
+ }
4265
+ if ( TYPE(raxis) == T_ARRAY ) {
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());
4267
+ }
4268
+ int axis = ca_normalize_axis_arg(raxis, src->ndim, NULL);
4269
+ switch ( src->data_type ) {
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));
4280
+ default:
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]);
4283
+ }
4284
+ return Qnil; /* unreachable */
4285
+ }
4286
+
4287
+ void
4288
+ Init_carray_kernels_scan (void)
4289
+ {
4290
+ rb_define_method(rb_cCArray, "cumsum_ki", rb_ca_cumsum_ki, -1);
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);
4293
+ rb_define_method(rb_cCArray, "cumprod_ki", rb_ca_cumprod_ki, -1);
4294
+ rb_define_method(rb_cCArray, "cumprod", rb_ca_cumprod_ki, -1);
4295
+ rb_define_method(rb_cCArray, "cummax_ki", rb_ca_cummax_ki, -1);
4296
+ rb_define_method(rb_cCArray, "cummax", rb_ca_cummax_ki, -1);
4297
+ rb_define_method(rb_cCArray, "cummin_ki", rb_ca_cummin_ki, -1);
4298
+ rb_define_method(rb_cCArray, "cummin", rb_ca_cummin_ki, -1);
4299
+ rb_define_method(rb_cCArray, "cumcount_ki", rb_ca_cumcount_ki, -1);
4300
+ rb_define_method(rb_cCArray, "cumcount", rb_ca_cumcount_ki, -1);
4301
+ rb_define_method(rb_cCArray, "uniq_scan_ki", rb_ca_uniq_scan_ki, -1);
4302
+ }