carray 2.0.0 → 3.0.0

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 (339) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -25
  3. data/CHANGELOG.md +16 -0
  4. data/LICENSE +1 -1
  5. data/NEWS.md +3 -0
  6. data/README.md +128 -44
  7. data/carray.gemspec +22 -24
  8. data/ext/ca_array_pool.c +91 -0
  9. data/ext/ca_axis_descriptor.h +186 -0
  10. data/ext/ca_axis_dispatch.c +924 -0
  11. data/ext/ca_axis_group.c +1208 -0
  12. data/ext/ca_bincmp_dispatch.c +76 -0
  13. data/ext/ca_bincmp_dispatch.h +85 -0
  14. data/ext/ca_binop_dispatch.c +125 -0
  15. data/ext/ca_binop_dispatch.h +159 -0
  16. data/ext/ca_categorical_iterator.c +1375 -0
  17. data/ext/ca_compare.c +94 -0
  18. data/ext/ca_compare.h +26 -0
  19. data/ext/ca_composite_dispatch.c +414 -0
  20. data/ext/ca_composite_dispatch.h +116 -0
  21. data/ext/ca_for_buffer.h +96 -0
  22. data/ext/ca_for_each_element.h +241 -0
  23. data/ext/ca_group_iter.c +304 -0
  24. data/ext/ca_iter_substrate.h +325 -0
  25. data/ext/ca_kernel_iterator.c +4321 -0
  26. data/ext/ca_kernel_iterator.h +2603 -0
  27. data/ext/ca_moncmp_dispatch.c +37 -0
  28. data/ext/ca_moncmp_dispatch.h +62 -0
  29. data/ext/ca_monop_dispatch.c +200 -0
  30. data/ext/ca_monop_dispatch.h +235 -0
  31. data/ext/ca_obj_array.c +355 -359
  32. data/ext/ca_obj_bincmp.c +809 -0
  33. data/ext/ca_obj_binop.c +892 -0
  34. data/ext/ca_obj_bitarray.c +369 -164
  35. data/ext/ca_obj_bitfield.c +294 -234
  36. data/ext/ca_obj_block.c +189 -711
  37. data/ext/ca_obj_byte_swap.c +766 -0
  38. data/ext/ca_obj_const_string.c +965 -0
  39. data/ext/ca_obj_face.c +670 -0
  40. data/ext/ca_obj_face.h +247 -0
  41. data/ext/ca_obj_fake.c +228 -100
  42. data/ext/ca_obj_farray.c +54 -441
  43. data/ext/ca_obj_field.c +82 -529
  44. data/ext/ca_obj_fixlen_string.c +306 -0
  45. data/ext/ca_obj_grid.c +858 -440
  46. data/ext/ca_obj_meld.c +1034 -0
  47. data/ext/ca_obj_moncmp.c +569 -0
  48. data/ext/ca_obj_monop.c +1111 -0
  49. data/ext/ca_obj_object.c +774 -298
  50. data/ext/ca_obj_record.c +468 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +569 -459
  53. data/ext/ca_obj_remap.c +475 -0
  54. data/ext/ca_obj_repeat.c +92 -477
  55. data/ext/ca_obj_roll.c +616 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1296 -0
  58. data/ext/ca_obj_shift.c +230 -792
  59. data/ext/ca_obj_source.c +78 -0
  60. data/ext/ca_obj_stack.c +1173 -0
  61. data/ext/ca_obj_stride.c +2501 -0
  62. data/ext/ca_obj_string.c +268 -0
  63. data/ext/ca_obj_tile.c +614 -0
  64. data/ext/ca_obj_time.c +546 -0
  65. data/ext/ca_obj_timedelta.c +435 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +746 -0
  68. data/ext/ca_obj_unbound_repeat.c +208 -241
  69. data/ext/ca_obj_window.c +1131 -563
  70. data/ext/ca_op_byte_swap.c +175 -0
  71. data/ext/ca_op_ipower.c +319 -0
  72. data/ext/ca_op_powi.h +88 -0
  73. data/ext/ca_sort_kernels.h +132 -0
  74. data/ext/ca_sweep_engine.c +430 -0
  75. data/ext/ca_sweep_engine.h +157 -0
  76. data/ext/ca_transform_common.c +228 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +795 -402
  80. data/ext/carray_access.c +831 -711
  81. data/ext/carray_attribute.c +98 -330
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +283 -0
  84. data/ext/carray_call_cfunc.c +1360 -828
  85. data/ext/carray_call_cfunc.h +160 -0
  86. data/ext/carray_cast.c +1212 -301
  87. data/ext/carray_cast_func.rb +81 -40
  88. data/ext/carray_class.c +53 -63
  89. data/ext/carray_config.h +28 -0
  90. data/ext/carray_conversion.c +350 -346
  91. data/ext/carray_copy.c +156 -268
  92. data/ext/carray_core.c +1342 -199
  93. data/ext/carray_count.c +312 -0
  94. data/ext/carray_data_type.c +43 -19
  95. data/ext/carray_element.c +585 -213
  96. data/ext/carray_factorize.c +2542 -0
  97. data/ext/carray_generate.c +230 -559
  98. data/ext/carray_histogram.c +490 -0
  99. data/ext/carray_hold.c +228 -0
  100. data/ext/carray_index_classifier.c +1035 -0
  101. data/ext/carray_index_classifier.h +27 -0
  102. data/ext/carray_internal.h +120 -0
  103. data/ext/carray_kernels_bincmp.c +4445 -0
  104. data/ext/carray_kernels_binop.c +10979 -0
  105. data/ext/carray_kernels_init.c +36 -0
  106. data/ext/carray_kernels_map.c +3466 -0
  107. data/ext/carray_kernels_moncmp.c +2096 -0
  108. data/ext/carray_kernels_monop.c +18312 -0
  109. data/ext/carray_kernels_reduce_aggregate.c +25836 -0
  110. data/ext/carray_kernels_reduce_boolean.c +329 -0
  111. data/ext/carray_kernels_reduce_cumulative.c +14592 -0
  112. data/ext/carray_kernels_reduce_extreme.c +16947 -0
  113. data/ext/carray_kernels_reduce_variance.c +3909 -0
  114. data/ext/carray_kernels_scan.c +3692 -0
  115. data/ext/carray_kernels_search.c +32137 -0
  116. data/ext/carray_kernels_sort.c +10625 -0
  117. data/ext/carray_kernels_triop.c +1391 -0
  118. data/ext/carray_lazy.c +567 -0
  119. data/ext/carray_loop.c +88 -200
  120. data/ext/carray_mask.c +848 -154
  121. data/ext/carray_math_kernel.h +120 -0
  122. data/ext/carray_mathfunc.c +10 -241
  123. data/ext/carray_median_percentile.c +1257 -0
  124. data/ext/carray_memory_view.c +1625 -0
  125. data/ext/carray_operator.c +1526 -318
  126. data/ext/carray_order.c +664 -1394
  127. data/ext/carray_partition.c +416 -0
  128. data/ext/carray_random.c +518 -0
  129. data/ext/carray_scatter.c +357 -0
  130. data/ext/carray_slab.c +1219 -0
  131. data/ext/carray_slab.h +84 -0
  132. data/ext/carray_sort.c +829 -0
  133. data/ext/carray_sort_kernel.c +620 -0
  134. data/ext/carray_struct.c +695 -0
  135. data/ext/carray_test.c +343 -229
  136. data/ext/carray_undef.c +34 -17
  137. data/ext/carray_utils.c +175 -74
  138. data/ext/extconf.rb +216 -55
  139. data/ext/mk_call_cfunc.rb +480 -0
  140. data/ext/mkkernel.rb +8842 -0
  141. data/ext/ruby_carray.c +202 -101
  142. data/ext/version.h +4 -14
  143. data/ext/version.rb +5 -13
  144. data/lib/carray/arrow_tensor.rb +401 -0
  145. data/lib/carray/attribute.rb +166 -0
  146. data/lib/carray/autoload_carray.rb +220 -0
  147. data/lib/carray/autoload_method_extension.rb +44 -0
  148. data/lib/carray/axis_group.rb +711 -0
  149. data/lib/carray/basics.rb +481 -0
  150. data/lib/carray/bincount_nd.rb +358 -0
  151. data/lib/carray/block_iterator.rb +604 -0
  152. data/lib/carray/boolean_reduce.rb +109 -0
  153. data/lib/carray/categorical.rb +561 -0
  154. data/lib/carray/categorical_iterator.rb +1062 -0
  155. data/lib/carray/complex.rb +150 -0
  156. data/lib/carray/conditional.rb +216 -0
  157. data/lib/carray/const_string.rb +228 -0
  158. data/lib/carray/construct.rb +139 -328
  159. data/lib/carray/core_extensions.rb +240 -0
  160. data/lib/carray/data_type_extension.rb +233 -0
  161. data/lib/carray/fixlen_string.rb +95 -0
  162. data/lib/carray/frame/concat.rb +132 -0
  163. data/lib/carray/frame/convert.rb +95 -0
  164. data/lib/carray/frame/csv_parser.rb +211 -0
  165. data/lib/carray/frame/frame.rb +649 -0
  166. data/lib/carray/frame/group.rb +186 -0
  167. data/lib/carray/frame/io.rb +164 -0
  168. data/lib/carray/frame/join.rb +248 -0
  169. data/lib/carray/frame/records.rb +99 -0
  170. data/lib/carray/frame/sort.rb +113 -0
  171. data/lib/carray/frame/verbs.rb +299 -0
  172. data/lib/carray/frame.rb +16 -0
  173. data/lib/carray/histogram.rb +512 -0
  174. data/lib/carray/inspect.rb +37 -20
  175. data/lib/carray/iterator.rb +57 -349
  176. data/lib/carray/lazy.rb +889 -0
  177. data/lib/carray/mask_gap_fill.rb +200 -0
  178. data/lib/carray/math.rb +78 -342
  179. data/lib/carray/meld_reduce.rb +289 -0
  180. data/lib/carray/methods/align_addr.rb +116 -0
  181. data/lib/carray/methods/bin.rb +128 -0
  182. data/lib/carray/methods/bincount.rb +87 -0
  183. data/lib/carray/methods/bit_string.rb +92 -0
  184. data/lib/carray/methods/broadcast.rb +63 -0
  185. data/lib/carray/methods/choose.rb +39 -0
  186. data/lib/carray/methods/composition.rb +280 -0
  187. data/lib/carray/methods/gather_nd.rb +206 -0
  188. data/lib/carray/methods/index.rb +39 -0
  189. data/lib/carray/methods/insert_block.rb +99 -0
  190. data/lib/carray/methods/is_in.rb +141 -0
  191. data/lib/carray/methods/join.rb +90 -0
  192. data/lib/carray/methods/locate_addr.rb +47 -0
  193. data/lib/carray/methods/mask_duplicates.rb +41 -0
  194. data/lib/carray/methods/meshgrid.rb +91 -0
  195. data/lib/carray/methods/mode.rb +126 -0
  196. data/lib/carray/methods/nunique.rb +46 -0
  197. data/lib/carray/methods/resize.rb +56 -0
  198. data/lib/carray/methods/snap.rb +156 -0
  199. data/lib/carray/methods/string_format.rb +57 -0
  200. data/lib/carray/methods/unique.rb +47 -0
  201. data/lib/carray/methods/value_counts.rb +71 -0
  202. data/lib/carray/mkmf.rb +124 -101
  203. data/lib/carray/runtime.rb +108 -0
  204. data/lib/carray/serialize.rb +478 -167
  205. data/lib/carray/slab_iterator.rb +292 -0
  206. data/lib/carray/stack.rb +291 -0
  207. data/lib/carray/string.rb +56 -180
  208. data/lib/carray/string_operation_extension.rb +289 -0
  209. data/lib/carray/struct.rb +335 -323
  210. data/lib/carray/struct_builder.rb +697 -0
  211. data/lib/carray/table.rb +41 -2
  212. data/lib/carray/time.rb +2255 -38
  213. data/lib/carray/window_iterator.rb +655 -0
  214. data/lib/carray.rb +55 -57
  215. metadata +163 -130
  216. data/Rakefile +0 -51
  217. data/TODO.md +0 -18
  218. data/ext/ca_iter_block.c +0 -257
  219. data/ext/ca_iter_dimension.c +0 -299
  220. data/ext/ca_iter_window.c +0 -214
  221. data/ext/ca_obj_mapping.c +0 -644
  222. data/ext/carray_iterator.c +0 -641
  223. data/ext/carray_math.rb +0 -850
  224. data/ext/carray_numeric.c +0 -259
  225. data/ext/carray_sort_addr.c +0 -254
  226. data/ext/carray_stat.c +0 -2100
  227. data/ext/carray_stat_proc.rb +0 -1999
  228. data/ext/mkmath.rb +0 -741
  229. data/ext/ruby_ccomplex.c +0 -509
  230. data/ext/ruby_float_func.c +0 -86
  231. data/lib/carray/array.rb +0 -8
  232. data/lib/carray/autoload/autoload_base.rb +0 -19
  233. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  234. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  235. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  236. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  237. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  238. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  239. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  240. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  241. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  242. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  243. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  244. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  245. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  246. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  247. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  248. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  249. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  250. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  251. data/lib/carray/autoload.rb +0 -141
  252. data/lib/carray/basic.rb +0 -191
  253. data/lib/carray/broadcast.rb +0 -101
  254. data/lib/carray/compose.rb +0 -315
  255. data/lib/carray/convert.rb +0 -115
  256. data/lib/carray/info.rb +0 -110
  257. data/lib/carray/io/imagemagick.rb +0 -235
  258. data/lib/carray/mask.rb +0 -102
  259. data/lib/carray/math/histogram.rb +0 -177
  260. data/lib/carray/math/recurrence.rb +0 -93
  261. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  262. data/lib/carray/object/ca_obj_link.rb +0 -50
  263. data/lib/carray/object/ca_obj_pack.rb +0 -99
  264. data/lib/carray/obsolete.rb +0 -256
  265. data/lib/carray/ordering.rb +0 -181
  266. data/lib/carray/testing.rb +0 -51
  267. data/lib/carray/transform.rb +0 -109
  268. data/misc/Methods.ja.md +0 -182
  269. data/misc/NOTE +0 -51
  270. data/spec/Classes/CABitfield_spec.rb +0 -58
  271. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  272. data/spec/Classes/CABlock_spec.rb +0 -205
  273. data/spec/Classes/CAField_spec.rb +0 -39
  274. data/spec/Classes/CAGrid_spec.rb +0 -75
  275. data/spec/Classes/CAMap_spec.rb +0 -0
  276. data/spec/Classes/CAMapping_spec.rb +0 -105
  277. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  278. data/spec/Classes/CAObject_spec.rb +0 -33
  279. data/spec/Classes/CARefer_spec.rb +0 -93
  280. data/spec/Classes/CARepeat_spec.rb +0 -65
  281. data/spec/Classes/CASelect_spec.rb +0 -22
  282. data/spec/Classes/CAShift_spec.rb +0 -16
  283. data/spec/Classes/CAStruct_spec.rb +0 -71
  284. data/spec/Classes/CATranspose_spec.rb +0 -60
  285. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  286. data/spec/Classes/CAWindow_spec.rb +0 -54
  287. data/spec/Classes/CAWrap_spec.rb +0 -8
  288. data/spec/Classes/CArray_spec.rb +0 -184
  289. data/spec/Classes/CScalar_spec.rb +0 -55
  290. data/spec/Classes/ex1.rb +0 -46
  291. data/spec/Features/feature_130_spec.rb +0 -19
  292. data/spec/Features/feature_attributes_spec.rb +0 -280
  293. data/spec/Features/feature_boolean_spec.rb +0 -98
  294. data/spec/Features/feature_broadcast.rb +0 -116
  295. data/spec/Features/feature_cast_function.rb +0 -19
  296. data/spec/Features/feature_cast_spec.rb +0 -33
  297. data/spec/Features/feature_class_spec.rb +0 -84
  298. data/spec/Features/feature_complex_spec.rb +0 -42
  299. data/spec/Features/feature_composite_spec.rb +0 -124
  300. data/spec/Features/feature_convert_spec.rb +0 -46
  301. data/spec/Features/feature_copy_spec.rb +0 -123
  302. data/spec/Features/feature_creation_spec.rb +0 -84
  303. data/spec/Features/feature_element_spec.rb +0 -144
  304. data/spec/Features/feature_extream_spec.rb +0 -54
  305. data/spec/Features/feature_generate_spec.rb +0 -74
  306. data/spec/Features/feature_index_spec.rb +0 -69
  307. data/spec/Features/feature_mask_spec.rb +0 -580
  308. data/spec/Features/feature_math_spec.rb +0 -97
  309. data/spec/Features/feature_order_spec.rb +0 -146
  310. data/spec/Features/feature_ref_store_spec.rb +0 -209
  311. data/spec/Features/feature_serialization_spec.rb +0 -125
  312. data/spec/Features/feature_stat_spec.rb +0 -397
  313. data/spec/Features/feature_virtual_spec.rb +0 -48
  314. data/spec/Features/method_eq_spec.rb +0 -81
  315. data/spec/Features/method_is_nan_spec.rb +0 -12
  316. data/spec/Features/method_map_spec.rb +0 -54
  317. data/spec/Features/method_max_with.rb +0 -20
  318. data/spec/Features/method_min_with.rb +0 -19
  319. data/spec/Features/method_ne_spec.rb +0 -18
  320. data/spec/Features/method_project_spec.rb +0 -188
  321. data/spec/Features/method_ref_spec.rb +0 -27
  322. data/spec/Features/method_round_spec.rb +0 -11
  323. data/spec/Features/method_s_linspace_spec.rb +0 -48
  324. data/spec/Features/method_s_span_spec.rb +0 -14
  325. data/spec/Features/method_seq_spec.rb +0 -47
  326. data/spec/Features/method_sort_with.rb +0 -43
  327. data/spec/Features/method_sorted_with.rb +0 -29
  328. data/spec/Features/method_span_spec.rb +0 -42
  329. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  330. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  331. data/spec/spec_all.rb +0 -10
  332. data/utils/ca_ase.rb +0 -21
  333. data/utils/ca_methods.rb +0 -15
  334. data/utils/cast_checker.rb +0 -30
  335. data/utils/convert_test.rb +0 -73
  336. data/utils/extract_yard.rb +0 -22
  337. data/utils/guess_shape.rb +0 -76
  338. data/utils/monkey_patch_methods.rb +0 -62
  339. data/utils/remove_resource_fork.sh +0 -5
@@ -0,0 +1,157 @@
1
+ /* ---------------------------------------------------------------------------
2
+ *
3
+ * ca_sweep_engine.h -- sweep (xfer_all) author surface engine, shared helper
4
+ *
5
+ * Established in PROPOSAL_L0_AUTHOR_SURFACE L0.1 (2026-06-11). Extracts
6
+ * the xfer_all-aware lifecycle template previously duplicated 7-times in
7
+ * ext/carray_call_cfunc.c (= one body per arity 1..7) into a single shared
8
+ * helper. Same helper will back the forthcoming CA_FOR_EACH_ELEMENT macro
9
+ * family (L0.2a) and the WHOLE_BUFFER family (L0.2c).
10
+ *
11
+ * Lifecycle template:
12
+ * (1) per-operand acquire
13
+ * OUTPUT (fsync=='1') -> ca_attach + use ca->ptr (sync on release)
14
+ * INPUT (fsync=='0') alias-able -> ca_attach + use ca->ptr
15
+ * INPUT (fsync=='0') non-alias -> xmalloc + ca_xfer_all(GET)
16
+ * (2) broadcast shape check (scalar collapse + n_kernel agreement)
17
+ * (3) mask OR across INPUT operands -> m0 (xmalloc, NULL if none)
18
+ * (4) mask propagate to OUTPUT operands (overwrite output->mask)
19
+ * (5) caller runs the per-cell loop using base[] + stride[]
20
+ * (6) per-operand release (reverse order):
21
+ * sync OUTPUTs, detach attached or xfree owned_buf, xfree m0
22
+ *
23
+ * Why xmalloc instead of ALLOCV_N:
24
+ * ALLOCV_N uses alloca() for sizes < RUBY_ALLOCV_LIMIT (1024 B); the
25
+ * allocation is bound to the calling C frame. When the engine is
26
+ * extracted to a helper function, the alloca'd region would die on
27
+ * helper return. xmalloc/xfree is frame-independent and safe to
28
+ * carry across the helper boundary. Cost: one heap call per non-alias
29
+ * INPUT. For arrays that warrant a kernel loop the cost is negligible.
30
+ *
31
+ * --------------------------------------------------------------------------- */
32
+
33
+ #ifndef CA_SWEEP_ENGINE_H
34
+ #define CA_SWEEP_ENGINE_H
35
+
36
+ #include "carray.h"
37
+
38
+ /* Caller-allocated arrays of length n_ops:
39
+ * - cx[] IN: CArray pointers (caller fills before ca_sweep_acquire)
40
+ * - base[] OUT: per-op base ptr for the per-cell loop
41
+ * - stride[] OUT: per-cell stride in bytes (0 for scalar broadcast)
42
+ * - owned_buf[] OUT: xmalloc'd buffer (NULL if alias or OUTPUT path)
43
+ * - attached[] OUT: 1 if ca_attach was called (= release must ca_detach)
44
+ *
45
+ * Engine-allocated:
46
+ * - m0 OUT: xmalloc'd mask byte array, NULL if no INPUT has mask
47
+ * - n_kernel OUT: broadcast element count
48
+ *
49
+ * fsync: per-op '0'/'1' string of length n_ops. Lifetime must cover both
50
+ * ca_sweep_acquire and ca_sweep_release (caller-owned, typically a string
51
+ * literal or stack-stored).
52
+ *
53
+ * src_label: optional, included in [BUG] error message if fsync length
54
+ * mismatches; NULL falls back to "ca_sweep_acquire".
55
+ */
56
+ typedef struct ca_sweep_state {
57
+ int n_ops;
58
+ const char *fsync;
59
+ CArray **cx;
60
+ char **base;
61
+ ca_size_t *stride;
62
+ char **owned_buf;
63
+ int *attached;
64
+ boolean8_t *m0;
65
+ ca_size_t n_kernel;
66
+ const char *src_label;
67
+ /* no_mask: if non-zero, ca_sweep_acquire raises when any INPUT operand has
68
+ * a mask. Used by the NO_MASK macro forms (CA_FOR_EACH_ELEMENT etc.) to
69
+ * implement Q3=(ii) runtime error policy. Default 0 (= masked INPUT OK,
70
+ * m0 built as usual). Caller sets before calling ca_sweep_acquire. */
71
+ int no_mask;
72
+
73
+ /* === chunked path fields (L0.1 chunk, PROPOSAL_L0_AUTHOR_SURFACE) === */
74
+ /* Used by ca_sweep_acquire_chunked / ca_sweep_next_chunk / ca_sweep_release_chunked
75
+ * (= the sweep ELEMENT macro family). Unused by the whole-materialise path
76
+ * (ca_sweep_acquire / ca_sweep_release) — cfunc and other whole-buffer callers
77
+ * leave these zero. */
78
+ char **base_orig; /* per-op original ptr (= ca->ptr for
79
+ alias/output; NULL for non-alias INPUT
80
+ that uses an arena chunk scratch).
81
+ Caller-allocated, length n_ops. */
82
+ ca_size_t chunk_n; /* current chunk element count */
83
+ ca_size_t chunk_off; /* current chunk start in flat addr */
84
+ ca_size_t chunk_n_max; /* max chunk size from ca_chunk_compute_n */
85
+ ca_size_t inner; /* product of dims except outermost (= row
86
+ size in elements for outer-axis chunking) */
87
+ int chunked_state; /* 0=pre-init, 1=active, 2=done */
88
+ } ca_sweep_state_t;
89
+
90
+ /* Validate fsync length, acquire per-op buffers, compute broadcast shape +
91
+ * strides, build mask m0, propagate mask to OUTPUTs. May raise (fsync
92
+ * length mismatch, shape mismatch). */
93
+ void ca_sweep_acquire (ca_sweep_state_t *st);
94
+
95
+ /* Reverse-order release: sync OUTPUTs, detach attached / xfree owned_buf,
96
+ * xfree m0. State is single-use; do not call acquire again on the same
97
+ * state without re-initializing the caller-owned arrays. */
98
+ void ca_sweep_release (ca_sweep_state_t *st);
99
+
100
+ /* Strict full-shape equality check used by INOUT macros (AC5: silent-
101
+ * corruption seam prevention). Raises if ndim differs or any dim[k]
102
+ * differs. Returns void; raises on mismatch. */
103
+ void ca_sweep_check_same_shape (CArray *ca_in, CArray *ca_out,
104
+ const char *src_label);
105
+
106
+ /* ===== Chunked path API (sweep ELEMENT macro family, L0.1 chunk) =====
107
+ *
108
+ * Unlike ca_sweep_acquire / ca_sweep_release (= whole-buffer materialise used
109
+ * by cfunc), the chunked path keeps INPUT memory peak bounded to chunk
110
+ * size (~32KB at f64 by default). AC2 ancestor cascade prevention plus
111
+ * memory peak guarantee: shrinking views materialise into chunk scratch
112
+ * sized to inner-axis multiples, not full operand size.
113
+ *
114
+ * Usage shape (inside a macro):
115
+ * ca_sweep_acquire_chunked(&st);
116
+ * while (ca_sweep_next_chunk(&st)) {
117
+ * for (k = 0; k < st.chunk_n; k++) {
118
+ * T x = *(T*)(st.base[0] + k * st.stride[0]);
119
+ * ...
120
+ * }
121
+ * }
122
+ * ca_sweep_release_chunked(&st);
123
+ *
124
+ * OUTPUT operand semantics:
125
+ * OUTPUT is ca_attach'd whole (= self IS write target, legitimate per
126
+ * E.7 invariant), and base[k] is rewritten per chunk as base_orig[k] +
127
+ * chunk_off * stride[k] so author writes land in the correct region.
128
+ * Final ca_sync runs in release_chunked. Output memory peak = entity
129
+ * size (= unavoidable; output buffer must exist).
130
+ *
131
+ * INPUT operand semantics:
132
+ * alias INPUT: base[k] = ca->ptr + chunk_off * stride[k], no gather.
133
+ * non-alias INPUT: arena scratch of size chunk_n_max * bytes is held
134
+ * for the entire walk; ca_chunked_gather rewrites it per chunk.
135
+ *
136
+ * Mask handling (m0):
137
+ * Built once in acquire_chunked at full size (= n_kernel bytes).
138
+ * Macros that want per-cell mask read at m0[chunk_off + k].
139
+ * Full-size m0 mirrors the whole path; per-chunk mask gather is a
140
+ * future optim.
141
+ */
142
+ void ca_sweep_acquire_chunked (ca_sweep_state_t *st);
143
+ int ca_sweep_next_chunk (ca_sweep_state_t *st); /* 1 = chunk ready, 0 = done */
144
+ void ca_sweep_release_chunked (ca_sweep_state_t *st);
145
+
146
+ /* ===== Chunking helpers (extern-ified from carray_operator.c) ===== */
147
+ ca_size_t ca_chunk_inner_size (CArray *ca);
148
+ ca_size_t ca_chunk_compute_n (ca_size_t total, ca_size_t inner,
149
+ ca_size_t bytes_per_cell);
150
+ void ca_chunked_gather (CArray *ca, ca_size_t off, ca_size_t n,
151
+ void *dest);
152
+
153
+ /* Arena pool (extern-ified earlier by lazy substrate; reused here). */
154
+ extern void *ca_lazy_arena_acquire (ca_size_t bytes);
155
+ extern void ca_lazy_arena_release (void *ptr);
156
+
157
+ #endif /* CA_SWEEP_ENGINE_H */
@@ -0,0 +1,228 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Shared substrate for byte-level 1:1 value-transform views (CAFake /
4
+ CAByteSwap). Implements the "compose to root + walk + transform in
5
+ flight" fast path used by xfer_stride (and indirectly by xfer_all via
6
+ thin-wrapper delegation).
7
+
8
+ Design and rationale: devel/PROPOSAL_TRANSFORM_FUSED_XFER.md.
9
+
10
+ ---------------------------------------------------------------------------- */
11
+
12
+ #include "carray.h"
13
+ #include "ca_iter_substrate.h"
14
+ #include <string.h>
15
+
16
+ /* CAStride compose helper (ca_obj_stride.c). */
17
+ extern void ca_stride_compose_to_root (CAStride *leaf, CArray **out_root,
18
+ ca_size_t *out_strides,
19
+ ca_size_t *out_base);
20
+ extern ca_operation_function_t ca_stride_func;
21
+
22
+ /* ---------------------------------------------------------------------------
23
+ ca_xfer_stride_transform_fused
24
+
25
+ Walk parent's CAStride chain to its root (an entity with live ptr), then
26
+ for each inner row gather one strided run from root.ptr into a row scratch
27
+ in parent data_type and apply the per-view transform callback to write that
28
+ row to dst in view data_type. No whole-view scratch, no ca_attach -- a true
29
+ 1-pass fused walk for both GET and PUT.
30
+
31
+ PUT is symmetric to GET: cast dst (view data_type) into row scratch (parent
32
+ data_type) via xform_put, then scatter row scratch into root.ptr strided.
33
+
34
+ Eligibility (returns 0 = fail, caller falls back to its existing path):
35
+ - parent is in the CAStride family (= ca_func[].attach matches)
36
+ - ndim >= 1
37
+ - compose_to_root yields a root with live ptr (= entity / attached)
38
+
39
+ Mask: not consulted. Post-xfer-reform data paths are mask-blind by
40
+ design; mask is propagated on a separate channel. See
41
+ PROPOSAL_TRANSFORM_FUSED_XFER.md for the audit.
42
+
43
+ row scratch sizing: stack 16 KB first, ALLOCV (alloca-like) for larger.
44
+
45
+ Callers (= the two transform views that wire xform_get/_put):
46
+ - ext/ca_obj_fake.c (CAFake; xform = type cast)
47
+ - ext/ca_obj_byte_swap.c (CAByteSwap; xform = endian swap)
48
+ The ca_transform_row_fn callback contract is declared in
49
+ ext/ca_iter_substrate.h.
50
+ --------------------------------------------------------------------------- */
51
+
52
+ #define CA_TRANSFORM_ROW_STACK_BYTES 16384
53
+
54
+ int
55
+ ca_xfer_stride_transform_fused (CArray *view,
56
+ CArray *parent,
57
+ ca_size_t *starts,
58
+ ca_size_t *counts,
59
+ ca_size_t *strides,
60
+ char *data,
61
+ int dir,
62
+ ca_transform_row_fn xform_get,
63
+ ca_transform_row_fn xform_put)
64
+ {
65
+ CArray *root;
66
+ ca_size_t composed_strides[CA_RANK_MAX];
67
+ ca_size_t composed_base;
68
+ ca_size_t parent_bytes, view_bytes;
69
+ int8_t ndim, k;
70
+ ca_size_t inner_count, inner_stride;
71
+ ca_size_t row_bytes;
72
+ char *row_buf;
73
+ char row_stack[CA_TRANSFORM_ROW_STACK_BYTES];
74
+ volatile VALUE holder = Qnil;
75
+ ca_size_t idx[CA_RANK_MAX];
76
+ ca_size_t outer_total, n, doff;
77
+
78
+ /* ---- Eligibility ---- */
79
+ if ( view->ndim < 1 ) return 0;
80
+ if ( dir != CA_XFER_GET && dir != CA_XFER_PUT ) return 0;
81
+
82
+ parent_bytes = parent->bytes;
83
+ view_bytes = view->bytes;
84
+ ndim = view->ndim;
85
+ /* CAREFUL: must use counts[ndim-1] (the sub-region width), not
86
+ view->dim[ndim-1] (the full view width). Caller's data buffer is
87
+ sized for counts[], so a sub-region PUT through a CATranspose-of-
88
+ CAFake chain overflows the buffer if the full view dim is used. */
89
+ inner_count = counts[ndim - 1];
90
+ if ( inner_count == 0 ) return 1; /* trivially complete */
91
+
92
+ /* Compute view's natural row-major byte strides in view byte space. */
93
+ ca_size_t view_native[CA_RANK_MAX];
94
+ {
95
+ ca_size_t s = view_bytes;
96
+ for ( k = ndim - 1; k >= 0; k-- ) {
97
+ view_native[k] = s;
98
+ s *= view->dim[k];
99
+ }
100
+ }
101
+
102
+ ca_size_t eff_root_step[CA_RANK_MAX];
103
+
104
+ /* ---- Resolve parent's data source: two cases ---- */
105
+ if ( ca_func[parent->obj_type].attach == ca_stride_func.attach ) {
106
+ /* (A) CAStride family parent: compose stride chain down to root.
107
+ composed_strides[k] = root bytes per ONE view cell on axis k
108
+ (already accounts for parent's possibly-permuted layout).
109
+ Requires caller's strides to be natural multiples of view_native[]
110
+ so req_step is integer; otherwise fallback. */
111
+ ca_stride_compose_to_root((CAStride *)parent, &root,
112
+ composed_strides, &composed_base);
113
+ if ( !root->ptr ) return 0;
114
+ if ( parent->bytes != root->bytes ) return 0;
115
+
116
+ for ( k = 0; k < ndim; k++ ) {
117
+ if ( view_native[k] == 0 ) return 0;
118
+ if ( strides[k] % view_native[k] != 0 ) return 0; /* non-natural */
119
+ ca_size_t req_step = strides[k] / view_native[k];
120
+ composed_base += starts[k] * composed_strides[k];
121
+ eff_root_step[k] = req_step * composed_strides[k];
122
+ }
123
+ } else if ( parent->ptr ) {
124
+ /* (B) Non-CAStride parent with live ptr (= entity / attached view).
125
+ Parent has linear row-major byte layout: bytes scale uniformly with
126
+ cells via parent_bytes/view_bytes ratio (CAFake is 1:1 shape
127
+ preserving). Use the universal "OLD CAFake" formula:
128
+ root byte step per axis-k iter = strides[k] * parent_bytes / view_bytes
129
+ root base contribution = starts[k] * parent_native[k]
130
+ This naturally handles transposed/sub-sampled caller strides. */
131
+ root = parent;
132
+ composed_base = 0;
133
+ if ( view_bytes == 0 ) return 0;
134
+ if ( parent_bytes % view_bytes != 0 && view_bytes % parent_bytes != 0 ) return 0;
135
+
136
+ ca_size_t parent_native[CA_RANK_MAX];
137
+ {
138
+ ca_size_t s = parent_bytes;
139
+ for ( k = parent->ndim - 1; k >= 0; k-- ) {
140
+ parent_native[k] = s;
141
+ s *= parent->dim[k];
142
+ }
143
+ }
144
+ for ( k = 0; k < ndim; k++ ) {
145
+ composed_base += starts[k] * parent_native[k];
146
+ eff_root_step[k] = strides[k] * parent_bytes / view_bytes;
147
+ }
148
+ } else {
149
+ /* Cold non-CAStride boundary (= CASelect etc. without ptr) -- fallback. */
150
+ return 0;
151
+ }
152
+
153
+ inner_stride = eff_root_step[ndim - 1];
154
+
155
+ /* When the inner row is contig in root (= inner_stride == parent_bytes),
156
+ the scratch gather/scatter is redundant -- xform_get/_put can read or
157
+ write root->ptr+soff directly, saving the row_buf allocation and one
158
+ of the two memory passes per outer row. Transposed access through
159
+ CATranspose-of-CAFake has inner_stride != parent_bytes and falls
160
+ through to the scratch+gather path. See
161
+ PROPOSAL_XFER_STRIDE_PER_REGION_GAPS.md. */
162
+ int inner_contig = (inner_stride == parent_bytes);
163
+
164
+ /* A 2D tile-cache + bulk-cast variant of this loop was explored and
165
+ reverted: the existing per-row walker already streams source through
166
+ L2/L3, and the tile path loses to per-call cast dispatch overhead
167
+ and an extra untranspose pass. See
168
+ PROPOSAL_TRANSFORM_FUSED_XFER.md for the rejected-direction record.
169
+ A typed (src,dst)-specialised inner loop is the next candidate. */
170
+
171
+ /* ---- Row scratch (parent data_type, inner_count cells) ----
172
+ Skipped when inner_contig is true (= every outer iter uses the
173
+ direct fast path below). */
174
+ row_bytes = inner_count * parent_bytes;
175
+ row_buf = NULL;
176
+ if ( !inner_contig ) {
177
+ if ( row_bytes <= (ca_size_t)CA_TRANSFORM_ROW_STACK_BYTES ) {
178
+ row_buf = row_stack;
179
+ } else {
180
+ row_buf = ALLOCV_N(char, holder, row_bytes);
181
+ }
182
+ }
183
+
184
+ /* ---- Walk outer (ndim-1) axes on odometer ---- */
185
+ outer_total = 1;
186
+ for ( k = 0; k < ndim - 1; k++ ) outer_total *= counts[k];
187
+ for ( k = 0; k < ndim - 1; k++ ) idx[k] = 0;
188
+ doff = 0;
189
+
190
+ for ( n = 0; n < outer_total; n++ ) {
191
+ /* Outer offset into root for this inner row. */
192
+ ca_size_t soff = composed_base;
193
+ for ( k = 0; k < ndim - 1; k++ ) soff += idx[k] * eff_root_step[k];
194
+
195
+ if ( inner_contig ) {
196
+ /* Inner-row contig in root; no scratch needed. */
197
+ if ( dir == CA_XFER_GET ) {
198
+ xform_get(inner_count, parent, root->ptr + soff,
199
+ view, data + doff);
200
+ } else {
201
+ xform_put(inner_count, view, data + doff,
202
+ parent, root->ptr + soff);
203
+ }
204
+ } else if ( dir == CA_XFER_GET ) {
205
+ /* root.ptr+soff strided -> row_buf contig (parent data_type). */
206
+ ca_stride_gather_run(row_buf, root->ptr + soff,
207
+ parent_bytes, inner_count, inner_stride);
208
+ /* row_buf (parent data_type) -> data+doff (view data_type). */
209
+ xform_get(inner_count, parent, row_buf, view, data + doff);
210
+ } else {
211
+ /* data+doff (view data_type) -> row_buf contig (parent data_type). */
212
+ xform_put(inner_count, view, data + doff, parent, row_buf);
213
+ /* row_buf contig -> root.ptr+soff strided (parent data_type). */
214
+ ca_stride_scatter_run(root->ptr + soff, row_buf,
215
+ parent_bytes, inner_count, inner_stride);
216
+ }
217
+ doff += inner_count * view_bytes;
218
+
219
+ /* Odometer advance over the outer (ndim-1) axes. */
220
+ if ( ndim < 2 ) break;
221
+ k = ndim - 2;
222
+ while ( k >= 0 ) { if ( ++idx[k] < counts[k] ) break; idx[k] = 0; k--; }
223
+ if ( k < 0 ) break;
224
+ }
225
+
226
+ if ( holder != Qnil ) ALLOCV_END(holder);
227
+ return 1;
228
+ }
@@ -0,0 +1,55 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ CATriOp dispatch: routes a triop op id (`CA_TRIOP_*`) to the per-
4
+ data_type kernel and computes the 3-way promotion.
5
+
6
+ Sibling of ca_binop_dispatch.c (binary counterpart) and
7
+ ca_obj_triop.c (the CATriOp view). Per-data_type kernel tables
8
+ are declared in ca_triop_dispatch.h.
9
+
10
+ All 3 operands are cast to the common promoted data_type before the
11
+ kernel runs (cast-before invariant, same as CABinOp). Output data_type
12
+ is the common promoted data_type.
13
+
14
+ ---------------------------------------------------------------------------- */
15
+
16
+ #include "carray.h"
17
+ #include "ca_triop_dispatch.h"
18
+
19
+ /* ------------------------------------------------------------------- */
20
+ /* vvv kernel lookup */
21
+ /* ------------------------------------------------------------------- */
22
+
23
+ ca_triop_func_t
24
+ ca_triop_kernel_lookup_vvv (uint16_t op_id, int8_t common_dt)
25
+ {
26
+ switch (op_id) {
27
+ case CA_TRIOP_FMA: return ca_triop_fma [common_dt];
28
+ case CA_TRIOP_FMS: return ca_triop_fms [common_dt];
29
+ case CA_TRIOP_CLIP: return ca_triop_clip [common_dt];
30
+ default: return NULL;
31
+ }
32
+ }
33
+
34
+ /* ------------------------------------------------------------------- */
35
+ /* 3-way promotion */
36
+ /* ------------------------------------------------------------------- */
37
+
38
+ int8_t
39
+ ca_lazy_promote_triop (uint16_t op_id, int8_t dt1, int8_t dt2, int8_t dt3)
40
+ {
41
+ (void) op_id; /* uniform 3-way promote across all currently-defined triops */
42
+ return (int8_t) ca_promote_type(ca_promote_type(dt1, dt2), dt3);
43
+ }
44
+
45
+ void
46
+ ca_triop_kernel_input_data_types (uint16_t op_id,
47
+ int8_t dt1, int8_t dt2, int8_t dt3,
48
+ int8_t *out_dt1, int8_t *out_dt2,
49
+ int8_t *out_dt3)
50
+ {
51
+ int8_t common = ca_lazy_promote_triop(op_id, dt1, dt2, dt3);
52
+ if ( out_dt1 ) *out_dt1 = common;
53
+ if ( out_dt2 ) *out_dt2 = common;
54
+ if ( out_dt3 ) *out_dt3 = common;
55
+ }
@@ -0,0 +1,62 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ ca_triop_dispatch.h
4
+
5
+ CATriOp dispatch API — sibling of ca_binop_dispatch.h. Routes a
6
+ triop op id (`CA_TRIOP_*`) to the per-data_type kernel and computes
7
+ the 3-way input promotion.
8
+
9
+ Kernel signature: fn(n, mask, src1, i1, src2, i2, src3, i3, dst, i4)
10
+ All 3 operands are cast to the common data_type before the kernel
11
+ runs (cast-before invariant, mirrors CABinOp). Output data_type is
12
+ always the common data_type (preserve).
13
+
14
+ Scope: fma / fms / clip (see ext/mkkernel.rb :fma / :fms / :clip).
15
+ None of the currently-defined triops trap on integer zero divisor.
16
+
17
+ ---------------------------------------------------------------------------- */
18
+
19
+ #ifndef CA_TRIOP_DISPATCH_H
20
+ #define CA_TRIOP_DISPATCH_H
21
+
22
+ #include "carray.h"
23
+
24
+ /* ------------------------------------------------------------------- */
25
+ /* op_id enum */
26
+ /* ------------------------------------------------------------------- */
27
+
28
+ enum {
29
+ CA_TRIOP_FMA = 0, /* a * b + c (single-rounding on float) */
30
+ CA_TRIOP_FMS = 1, /* a * b - c (single-rounding on float) */
31
+ CA_TRIOP_CLIP = 2, /* min(max(a, lo), hi), NaN-preserving */
32
+
33
+ CA_TRIOP_COUNT
34
+ };
35
+
36
+ /* ------------------------------------------------------------------- */
37
+ /* Kernel dispatch tables (per-data_type) */
38
+ /* ------------------------------------------------------------------- */
39
+
40
+ extern ca_triop_func_t ca_triop_fma [CA_NTYPE];
41
+ extern ca_triop_func_t ca_triop_fms [CA_NTYPE];
42
+ extern ca_triop_func_t ca_triop_clip [CA_NTYPE];
43
+
44
+ /* ------------------------------------------------------------------- */
45
+ /* Dispatch API */
46
+ /* ------------------------------------------------------------------- */
47
+
48
+ /* Look up the triop kernel for (op_id, common_dt). Returns NULL if
49
+ not implemented at the requested data_type. */
50
+ ca_triop_func_t ca_triop_kernel_lookup_vvv (uint16_t op_id, int8_t common_dt);
51
+
52
+ /* 3-way promotion: common data_type of (dt1, dt2, dt3). */
53
+ int8_t ca_lazy_promote_triop (uint16_t op_id, int8_t dt1, int8_t dt2, int8_t dt3);
54
+
55
+ /* Each operand's cast-target data_type (= common data_type for all three,
56
+ the cast-before invariant). */
57
+ void ca_triop_kernel_input_data_types (uint16_t op_id,
58
+ int8_t dt1, int8_t dt2, int8_t dt3,
59
+ int8_t *out_dt1, int8_t *out_dt2,
60
+ int8_t *out_dt3);
61
+
62
+ #endif /* CA_TRIOP_DISPATCH_H */