carray 2.0.1 → 3.0.1

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 (386) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -25
  3. data/CHANGELOG.md +338 -0
  4. data/{NEWS.md → CHANGELOG.v1.md} +3 -0
  5. data/LICENSE +1 -1
  6. data/README.md +120 -36
  7. data/carray.gemspec +32 -30
  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 +1244 -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 +124 -0
  15. data/ext/ca_binop_dispatch.h +152 -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 +239 -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 +4367 -0
  26. data/ext/ca_kernel_iterator.h +2596 -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 +839 -0
  33. data/ext/ca_obj_binop.c +948 -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 +967 -0
  39. data/ext/ca_obj_face.c +750 -0
  40. data/ext/ca_obj_face.h +279 -0
  41. data/ext/ca_obj_fake.c +239 -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 +308 -0
  45. data/ext/ca_obj_grid.c +866 -440
  46. data/ext/ca_obj_meld.c +1039 -0
  47. data/ext/ca_obj_moncmp.c +588 -0
  48. data/ext/ca_obj_monop.c +1123 -0
  49. data/ext/ca_obj_object.c +866 -296
  50. data/ext/ca_obj_record.c +470 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +593 -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 +624 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1306 -0
  58. data/ext/ca_obj_shift.c +231 -793
  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 +2584 -0
  62. data/ext/ca_obj_string.c +270 -0
  63. data/ext/ca_obj_tile.c +622 -0
  64. data/ext/ca_obj_time.c +548 -0
  65. data/ext/ca_obj_timedelta.c +437 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +785 -0
  68. data/ext/ca_obj_window.c +1202 -565
  69. data/ext/ca_op_byte_swap.c +175 -0
  70. data/ext/ca_op_cmplx64.h +123 -0
  71. data/ext/ca_op_ipower.c +316 -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 +473 -0
  75. data/ext/ca_sweep_engine.h +166 -0
  76. data/ext/ca_transform_common.c +235 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +810 -420
  80. data/ext/carray_access.c +873 -731
  81. data/ext/carray_attribute.c +98 -329
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +376 -0
  84. data/ext/carray_build_flags.h +3 -0
  85. data/ext/carray_call_cfunc.c +2897 -874
  86. data/ext/carray_call_cfunc.h +313 -0
  87. data/ext/carray_cast.c +1264 -315
  88. data/ext/carray_cast_func.rb +81 -40
  89. data/ext/carray_class.c +53 -63
  90. data/ext/carray_config.h +28 -0
  91. data/ext/carray_conversion.c +350 -346
  92. data/ext/carray_copy.c +168 -270
  93. data/ext/carray_core.c +1396 -206
  94. data/ext/carray_count.c +312 -0
  95. data/ext/carray_data_type.c +43 -19
  96. data/ext/carray_element.c +585 -213
  97. data/ext/carray_factorize.c +2542 -0
  98. data/ext/carray_generate.c +230 -559
  99. data/ext/carray_histogram.c +490 -0
  100. data/ext/carray_hold.c +228 -0
  101. data/ext/carray_index_classifier.c +1021 -0
  102. data/ext/carray_index_classifier.h +27 -0
  103. data/ext/carray_internal.h +136 -0
  104. data/ext/carray_kernels_bincmp.c +4446 -0
  105. data/ext/carray_kernels_binop.c +11001 -0
  106. data/ext/carray_kernels_init.c +1131 -0
  107. data/ext/carray_kernels_map.c +3467 -0
  108. data/ext/carray_kernels_moncmp.c +2097 -0
  109. data/ext/carray_kernels_monop.c +18313 -0
  110. data/ext/carray_kernels_reduce_aggregate.c +25837 -0
  111. data/ext/carray_kernels_reduce_boolean.c +330 -0
  112. data/ext/carray_kernels_reduce_cumulative.c +14593 -0
  113. data/ext/carray_kernels_reduce_extreme.c +16948 -0
  114. data/ext/carray_kernels_reduce_variance.c +3910 -0
  115. data/ext/carray_kernels_scan.c +3693 -0
  116. data/ext/carray_kernels_search.c +32138 -0
  117. data/ext/carray_kernels_sort.c +10626 -0
  118. data/ext/carray_kernels_triop.c +1392 -0
  119. data/ext/carray_lazy.c +737 -0
  120. data/ext/carray_loop.c +88 -200
  121. data/ext/carray_mask.c +853 -158
  122. data/ext/carray_math_kernel.h +120 -0
  123. data/ext/carray_mathfunc.c +10 -241
  124. data/ext/carray_median_percentile.c +1257 -0
  125. data/ext/carray_memory_view.c +1650 -0
  126. data/ext/carray_operator.c +1525 -320
  127. data/ext/carray_order.c +664 -1394
  128. data/ext/carray_partition.c +416 -0
  129. data/ext/carray_random.c +518 -0
  130. data/ext/carray_scatter.c +357 -0
  131. data/ext/carray_slab.c +1219 -0
  132. data/ext/carray_slab.h +84 -0
  133. data/ext/carray_sort.c +829 -0
  134. data/ext/carray_sort_kernel.c +620 -0
  135. data/ext/carray_struct.c +695 -0
  136. data/ext/carray_test.c +343 -229
  137. data/ext/carray_undef.c +34 -17
  138. data/ext/carray_utils.c +175 -74
  139. data/ext/extconf.rb +234 -55
  140. data/ext/mk_call_cfunc.rb +671 -0
  141. data/ext/mkkernel.rb +9096 -0
  142. data/ext/ruby_carray.c +211 -108
  143. data/ext/version.h +4 -14
  144. data/ext/version.rb +5 -13
  145. data/lib/carray/arrow_tensor.rb +401 -0
  146. data/lib/carray/attribute.rb +166 -0
  147. data/lib/carray/autoload_carray.rb +239 -0
  148. data/lib/carray/autoload_method_extension.rb +45 -0
  149. data/lib/carray/axis_group.rb +711 -0
  150. data/lib/carray/basics.rb +481 -0
  151. data/lib/carray/bincount_nd.rb +358 -0
  152. data/lib/carray/block_iterator.rb +614 -0
  153. data/lib/carray/boolean_reduce.rb +109 -0
  154. data/lib/carray/categorical.rb +561 -0
  155. data/lib/carray/categorical_iterator.rb +1084 -0
  156. data/lib/carray/complex.rb +150 -0
  157. data/lib/carray/conditional.rb +216 -0
  158. data/lib/carray/const_string.rb +228 -0
  159. data/lib/carray/construct.rb +160 -328
  160. data/lib/carray/core_extensions.rb +297 -0
  161. data/lib/carray/data_type_extension.rb +250 -0
  162. data/lib/carray/fixlen_string.rb +95 -0
  163. data/lib/carray/frame/concat.rb +132 -0
  164. data/lib/carray/frame/convert.rb +95 -0
  165. data/lib/carray/frame/csv_parser.rb +211 -0
  166. data/lib/carray/frame/frame.rb +642 -0
  167. data/lib/carray/frame/group.rb +186 -0
  168. data/lib/carray/frame/io.rb +321 -0
  169. data/lib/carray/frame/join.rb +248 -0
  170. data/lib/carray/frame/records.rb +99 -0
  171. data/lib/carray/frame/sort.rb +113 -0
  172. data/lib/carray/frame/verbs.rb +316 -0
  173. data/lib/carray/frame.rb +16 -0
  174. data/lib/carray/fuse_source.rb +123 -0
  175. data/lib/carray/fusion.rb +218 -0
  176. data/lib/carray/histogram.rb +512 -0
  177. data/lib/carray/inspect.rb +37 -26
  178. data/lib/carray/iterator.rb +58 -349
  179. data/lib/carray/lazy.rb +941 -0
  180. data/lib/carray/mask_gap_fill.rb +200 -0
  181. data/lib/carray/math.rb +78 -342
  182. data/lib/carray/meld_reduce.rb +289 -0
  183. data/lib/carray/methods/align_addr.rb +116 -0
  184. data/lib/carray/methods/bin.rb +128 -0
  185. data/lib/carray/methods/bincount.rb +87 -0
  186. data/lib/carray/methods/bit_string.rb +92 -0
  187. data/lib/carray/methods/broadcast.rb +63 -0
  188. data/lib/carray/methods/choose.rb +39 -0
  189. data/lib/carray/methods/composition.rb +280 -0
  190. data/lib/carray/methods/gather_nd.rb +206 -0
  191. data/lib/carray/methods/index.rb +39 -0
  192. data/lib/carray/methods/insert_block.rb +99 -0
  193. data/lib/carray/methods/is_in.rb +141 -0
  194. data/lib/carray/methods/join.rb +90 -0
  195. data/lib/carray/methods/locate_addr.rb +52 -0
  196. data/lib/carray/methods/mask_duplicates.rb +41 -0
  197. data/lib/carray/methods/meshgrid.rb +90 -0
  198. data/lib/carray/methods/mode.rb +126 -0
  199. data/lib/carray/methods/nunique.rb +46 -0
  200. data/lib/carray/methods/resize.rb +56 -0
  201. data/lib/carray/methods/snap.rb +161 -0
  202. data/lib/carray/methods/string_format.rb +57 -0
  203. data/lib/carray/methods/unique.rb +47 -0
  204. data/lib/carray/methods/value_counts.rb +71 -0
  205. data/lib/carray/mkmf.rb +124 -101
  206. data/lib/carray/runtime.rb +89 -0
  207. data/lib/carray/serialize.rb +478 -167
  208. data/lib/carray/slab_iterator.rb +305 -0
  209. data/lib/carray/stack.rb +291 -0
  210. data/lib/carray/string.rb +56 -180
  211. data/lib/carray/string_operation_extension.rb +289 -0
  212. data/lib/carray/struct.rb +335 -323
  213. data/lib/carray/struct_builder.rb +697 -0
  214. data/lib/carray/table.rb +41 -2
  215. data/lib/carray/time.rb +2654 -38
  216. data/lib/carray/window_iterator.rb +927 -0
  217. data/lib/carray.rb +55 -57
  218. data/yard-stubs/ca_obj_array.rb +385 -0
  219. data/yard-stubs/ca_obj_bitarray.rb +38 -0
  220. data/yard-stubs/ca_obj_bitfield.rb +43 -0
  221. data/yard-stubs/ca_obj_block.rb +73 -0
  222. data/yard-stubs/ca_obj_byte_swap.rb +56 -0
  223. data/yard-stubs/ca_obj_fake.rb +31 -0
  224. data/yard-stubs/ca_obj_farray.rb +32 -0
  225. data/yard-stubs/ca_obj_field.rb +45 -0
  226. data/yard-stubs/ca_obj_grid.rb +35 -0
  227. data/yard-stubs/ca_obj_refer.rb +72 -0
  228. data/yard-stubs/ca_obj_roll.rb +45 -0
  229. data/yard-stubs/ca_obj_shift.rb +43 -0
  230. data/yard-stubs/ca_obj_stride.rb +181 -0
  231. data/yard-stubs/ca_obj_tile.rb +29 -0
  232. data/yard-stubs/ca_obj_transpose.rb +40 -0
  233. data/yard-stubs/ca_obj_window.rb +49 -0
  234. data/yard-stubs/carray_access.rb +131 -0
  235. data/yard-stubs/carray_attribute.rb +246 -0
  236. data/yard-stubs/carray_broadcast.rb +37 -0
  237. data/yard-stubs/carray_cast.rb +489 -0
  238. data/yard-stubs/carray_class.rb +65 -0
  239. data/yard-stubs/carray_conversion.rb +76 -0
  240. data/yard-stubs/carray_copy.rb +79 -0
  241. data/yard-stubs/carray_core.rb +114 -0
  242. data/yard-stubs/carray_count.rb +79 -0
  243. data/yard-stubs/carray_element.rb +108 -0
  244. data/yard-stubs/carray_generate.rb +66 -0
  245. data/yard-stubs/carray_lazy.rb +23 -0
  246. data/yard-stubs/carray_loop.rb +140 -0
  247. data/yard-stubs/carray_mask.rb +259 -0
  248. data/yard-stubs/carray_math.rb +132 -0
  249. data/yard-stubs/carray_mathfunc.rb +45 -0
  250. data/yard-stubs/carray_median_percentile.rb +89 -0
  251. data/yard-stubs/carray_memory_view.rb +163 -0
  252. data/yard-stubs/carray_order.rb +312 -0
  253. data/yard-stubs/carray_random.rb +89 -0
  254. data/yard-stubs/carray_scatter.rb +106 -0
  255. data/yard-stubs/carray_slab.rb +57 -0
  256. data/yard-stubs/carray_sort.rb +163 -0
  257. data/yard-stubs/carray_test.rb +85 -0
  258. data/yard-stubs/carray_undef.rb +64 -0
  259. data/yard-stubs/carray_utils.rb +97 -0
  260. data/yard-stubs/ruby_carray.rb +193 -0
  261. metadata +220 -138
  262. data/Rakefile +0 -51
  263. data/TODO.md +0 -18
  264. data/ext/ca_iter_block.c +0 -257
  265. data/ext/ca_iter_dimension.c +0 -299
  266. data/ext/ca_iter_window.c +0 -214
  267. data/ext/ca_obj_mapping.c +0 -644
  268. data/ext/ca_obj_unbound_repeat.c +0 -529
  269. data/ext/carray_iterator.c +0 -641
  270. data/ext/carray_math.rb +0 -850
  271. data/ext/carray_numeric.c +0 -259
  272. data/ext/carray_sort_addr.c +0 -254
  273. data/ext/carray_stat.c +0 -2100
  274. data/ext/carray_stat_proc.rb +0 -1999
  275. data/ext/mkmath.rb +0 -741
  276. data/ext/ruby_ccomplex.c +0 -509
  277. data/ext/ruby_float_func.c +0 -86
  278. data/lib/carray/array.rb +0 -8
  279. data/lib/carray/autoload/autoload_base.rb +0 -19
  280. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  281. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  282. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  283. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  284. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  285. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  286. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  287. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  288. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  289. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  290. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  291. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  292. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  293. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  294. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  295. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  296. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  297. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  298. data/lib/carray/autoload.rb +0 -141
  299. data/lib/carray/basic.rb +0 -191
  300. data/lib/carray/broadcast.rb +0 -101
  301. data/lib/carray/compose.rb +0 -315
  302. data/lib/carray/convert.rb +0 -115
  303. data/lib/carray/info.rb +0 -110
  304. data/lib/carray/io/imagemagick.rb +0 -235
  305. data/lib/carray/mask.rb +0 -102
  306. data/lib/carray/math/histogram.rb +0 -177
  307. data/lib/carray/math/recurrence.rb +0 -93
  308. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  309. data/lib/carray/object/ca_obj_link.rb +0 -50
  310. data/lib/carray/object/ca_obj_pack.rb +0 -99
  311. data/lib/carray/obsolete.rb +0 -256
  312. data/lib/carray/ordering.rb +0 -181
  313. data/lib/carray/testing.rb +0 -51
  314. data/lib/carray/transform.rb +0 -109
  315. data/mailmap +0 -1
  316. data/misc/Methods.ja.md +0 -182
  317. data/misc/NOTE +0 -51
  318. data/spec/Classes/CABitfield_spec.rb +0 -58
  319. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  320. data/spec/Classes/CABlock_spec.rb +0 -205
  321. data/spec/Classes/CAField_spec.rb +0 -39
  322. data/spec/Classes/CAGrid_spec.rb +0 -75
  323. data/spec/Classes/CAMap_spec.rb +0 -0
  324. data/spec/Classes/CAMapping_spec.rb +0 -105
  325. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  326. data/spec/Classes/CAObject_spec.rb +0 -33
  327. data/spec/Classes/CARefer_spec.rb +0 -93
  328. data/spec/Classes/CARepeat_spec.rb +0 -65
  329. data/spec/Classes/CASelect_spec.rb +0 -22
  330. data/spec/Classes/CAShift_spec.rb +0 -16
  331. data/spec/Classes/CAStruct_spec.rb +0 -71
  332. data/spec/Classes/CATranspose_spec.rb +0 -60
  333. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  334. data/spec/Classes/CAWindow_spec.rb +0 -54
  335. data/spec/Classes/CAWrap_spec.rb +0 -8
  336. data/spec/Classes/CArray_spec.rb +0 -184
  337. data/spec/Classes/CScalar_spec.rb +0 -55
  338. data/spec/Features/feature_130_spec.rb +0 -19
  339. data/spec/Features/feature_attributes_spec.rb +0 -280
  340. data/spec/Features/feature_boolean_spec.rb +0 -98
  341. data/spec/Features/feature_broadcast.rb +0 -116
  342. data/spec/Features/feature_cast_function.rb +0 -19
  343. data/spec/Features/feature_cast_spec.rb +0 -33
  344. data/spec/Features/feature_class_spec.rb +0 -84
  345. data/spec/Features/feature_complex_spec.rb +0 -42
  346. data/spec/Features/feature_composite_spec.rb +0 -124
  347. data/spec/Features/feature_convert_spec.rb +0 -46
  348. data/spec/Features/feature_copy_spec.rb +0 -123
  349. data/spec/Features/feature_creation_spec.rb +0 -84
  350. data/spec/Features/feature_element_spec.rb +0 -144
  351. data/spec/Features/feature_extream_spec.rb +0 -54
  352. data/spec/Features/feature_generate_spec.rb +0 -74
  353. data/spec/Features/feature_index_spec.rb +0 -69
  354. data/spec/Features/feature_mask_spec.rb +0 -580
  355. data/spec/Features/feature_math_spec.rb +0 -97
  356. data/spec/Features/feature_order_spec.rb +0 -146
  357. data/spec/Features/feature_ref_store_spec.rb +0 -209
  358. data/spec/Features/feature_serialization_spec.rb +0 -125
  359. data/spec/Features/feature_stat_spec.rb +0 -397
  360. data/spec/Features/feature_virtual_spec.rb +0 -48
  361. data/spec/Features/method_eq_spec.rb +0 -81
  362. data/spec/Features/method_is_nan_spec.rb +0 -12
  363. data/spec/Features/method_map_spec.rb +0 -54
  364. data/spec/Features/method_max_with.rb +0 -20
  365. data/spec/Features/method_min_with.rb +0 -19
  366. data/spec/Features/method_ne_spec.rb +0 -18
  367. data/spec/Features/method_project_spec.rb +0 -188
  368. data/spec/Features/method_ref_spec.rb +0 -27
  369. data/spec/Features/method_round_spec.rb +0 -11
  370. data/spec/Features/method_s_linspace_spec.rb +0 -48
  371. data/spec/Features/method_s_span_spec.rb +0 -14
  372. data/spec/Features/method_seq_spec.rb +0 -47
  373. data/spec/Features/method_sort_with.rb +0 -43
  374. data/spec/Features/method_sorted_with.rb +0 -29
  375. data/spec/Features/method_span_spec.rb +0 -42
  376. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  377. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  378. data/spec/spec_all.rb +0 -10
  379. data/utils/ca_ase.rb +0 -21
  380. data/utils/ca_methods.rb +0 -15
  381. data/utils/cast_checker.rb +0 -30
  382. data/utils/convert_test.rb +0 -73
  383. data/utils/extract_yard.rb +0 -22
  384. data/utils/guess_shape.rb +0 -76
  385. data/utils/monkey_patch_methods.rb +0 -62
  386. data/utils/remove_resource_fork.sh +0 -5
@@ -0,0 +1,166 @@
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
+ boolean8_t *mask_scratch; /* chunk-sized staging for the per-chunk
89
+ mask OR; NULL when no INPUT is masked */
90
+ } ca_sweep_state_t;
91
+
92
+ /* Validate fsync length, acquire per-op buffers, compute broadcast shape +
93
+ * strides, build mask m0, propagate mask to OUTPUTs. May raise (fsync
94
+ * length mismatch, shape mismatch). */
95
+ void ca_sweep_acquire (ca_sweep_state_t *st);
96
+
97
+ /* Reverse-order release: sync OUTPUTs, detach attached / xfree owned_buf,
98
+ * xfree m0. State is single-use; do not call acquire again on the same
99
+ * state without re-initializing the caller-owned arrays. */
100
+ void ca_sweep_release (ca_sweep_state_t *st);
101
+
102
+ /* Strict full-shape equality check used by INOUT macros (AC5: silent-
103
+ * corruption seam prevention). Raises if ndim differs or any dim[k]
104
+ * differs. Returns void; raises on mismatch. */
105
+ void ca_sweep_check_same_shape (CArray *ca_in, CArray *ca_out,
106
+ const char *src_label);
107
+
108
+ /* ===== Chunked path API (sweep ELEMENT macro family, L0.1 chunk) =====
109
+ *
110
+ * Unlike ca_sweep_acquire / ca_sweep_release (= whole-buffer materialise used
111
+ * by cfunc), the chunked path keeps INPUT memory peak bounded to chunk
112
+ * size (~32KB at f64 by default). AC2 ancestor cascade prevention plus
113
+ * memory peak guarantee: shrinking views materialise into chunk scratch
114
+ * sized to inner-axis multiples, not full operand size.
115
+ *
116
+ * Usage shape (inside a macro):
117
+ * ca_sweep_acquire_chunked(&st);
118
+ * while (ca_sweep_next_chunk(&st)) {
119
+ * for (k = 0; k < st.chunk_n; k++) {
120
+ * T x = *(T*)(st.base[0] + k * st.stride[0]);
121
+ * ...
122
+ * }
123
+ * }
124
+ * ca_sweep_release_chunked(&st);
125
+ *
126
+ * OUTPUT operand semantics:
127
+ * OUTPUT is ca_attach'd whole (= self IS write target, legitimate per
128
+ * E.7 invariant), and base[k] is rewritten per chunk as base_orig[k] +
129
+ * chunk_off * stride[k] so author writes land in the correct region.
130
+ * Final ca_sync runs in release_chunked. Output memory peak = entity
131
+ * size (= unavoidable; output buffer must exist).
132
+ *
133
+ * INPUT operand semantics:
134
+ * alias INPUT: base[k] = ca->ptr + chunk_off * stride[k], no gather.
135
+ * non-alias INPUT: arena scratch of size chunk_n_max * bytes is held
136
+ * for the entire walk; ca_chunked_gather rewrites it per chunk.
137
+ *
138
+ * Mask handling (m0):
139
+ * Chunk-sized (= chunk_n_max bytes), re-gathered per chunk in
140
+ * ca_sweep_next_chunk. Read it at m0[k] for k < chunk_n -- it is
141
+ * indexed within the chunk, NOT by the flat cell index. (This differs
142
+ * from the whole-buffer path, where m0 spans n_kernel.)
143
+ *
144
+ * An author may WRITE m0[k] during the chunk loop (= the INOUT_MASKED
145
+ * forms' m_out). Those writes are flushed into the OUTPUT operands'
146
+ * masks when the chunk finishes -- at the top of the following
147
+ * ca_sweep_next_chunk, and once more in ca_sweep_release_chunked for
148
+ * the last chunk -- so the OUTPUT masks are created up front in
149
+ * acquire_chunked rather than propagated in one go at release.
150
+ */
151
+ void ca_sweep_acquire_chunked (ca_sweep_state_t *st);
152
+ int ca_sweep_next_chunk (ca_sweep_state_t *st); /* 1 = chunk ready, 0 = done */
153
+ void ca_sweep_release_chunked (ca_sweep_state_t *st);
154
+
155
+ /* ===== Chunking helpers (extern-ified from carray_operator.c) ===== */
156
+ ca_size_t ca_chunk_inner_size (CArray *ca);
157
+ ca_size_t ca_chunk_compute_n (ca_size_t total, ca_size_t inner,
158
+ ca_size_t bytes_per_cell);
159
+ void ca_chunked_gather (CArray *ca, ca_size_t off, ca_size_t n,
160
+ void *dest);
161
+
162
+ /* Arena pool (extern-ified earlier by lazy substrate; reused here). */
163
+ extern void *ca_lazy_arena_acquire (ca_size_t bytes);
164
+ extern void ca_lazy_arena_release (void *ptr);
165
+
166
+ #endif /* CA_SWEEP_ENGINE_H */
@@ -0,0 +1,235 @@
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
+ /* Per-axis composition below is only meaningful for a request that walks
116
+ our own axes; a transposed / flat request over the view's addresses
117
+ (legal -- see ca_xfer_stride_request_is_axis_box in carray.h) declines
118
+ to the caller's per-cell path. */
119
+ if ( ! ca_xfer_stride_request_is_axis_box(view, starts, counts, strides) ) {
120
+ return 0;
121
+ }
122
+
123
+ for ( k = 0; k < ndim; k++ ) {
124
+ if ( view_native[k] == 0 ) return 0;
125
+ if ( strides[k] % view_native[k] != 0 ) return 0; /* non-natural */
126
+ ca_size_t req_step = strides[k] / view_native[k];
127
+ composed_base += starts[k] * composed_strides[k];
128
+ eff_root_step[k] = req_step * composed_strides[k];
129
+ }
130
+ } else if ( parent->ptr ) {
131
+ /* (B) Non-CAStride parent with live ptr (= entity / attached view).
132
+ Parent has linear row-major byte layout: bytes scale uniformly with
133
+ cells via parent_bytes/view_bytes ratio (CAFake is 1:1 shape
134
+ preserving). Use the universal "OLD CAFake" formula:
135
+ root byte step per axis-k iter = strides[k] * parent_bytes / view_bytes
136
+ root base contribution = starts[k] * parent_native[k]
137
+ This naturally handles transposed/sub-sampled caller strides. */
138
+ root = parent;
139
+ composed_base = 0;
140
+ if ( view_bytes == 0 ) return 0;
141
+ if ( parent_bytes % view_bytes != 0 && view_bytes % parent_bytes != 0 ) return 0;
142
+
143
+ ca_size_t parent_native[CA_RANK_MAX];
144
+ {
145
+ ca_size_t s = parent_bytes;
146
+ for ( k = parent->ndim - 1; k >= 0; k-- ) {
147
+ parent_native[k] = s;
148
+ s *= parent->dim[k];
149
+ }
150
+ }
151
+ for ( k = 0; k < ndim; k++ ) {
152
+ composed_base += starts[k] * parent_native[k];
153
+ eff_root_step[k] = strides[k] * parent_bytes / view_bytes;
154
+ }
155
+ } else {
156
+ /* Cold non-CAStride boundary (= CASelect etc. without ptr) -- fallback. */
157
+ return 0;
158
+ }
159
+
160
+ inner_stride = eff_root_step[ndim - 1];
161
+
162
+ /* When the inner row is contig in root (= inner_stride == parent_bytes),
163
+ the scratch gather/scatter is redundant -- xform_get/_put can read or
164
+ write root->ptr+soff directly, saving the row_buf allocation and one
165
+ of the two memory passes per outer row. Transposed access through
166
+ CATranspose-of-CAFake has inner_stride != parent_bytes and falls
167
+ through to the scratch+gather path. See
168
+ PROPOSAL_XFER_STRIDE_PER_REGION_GAPS.md. */
169
+ int inner_contig = (inner_stride == parent_bytes);
170
+
171
+ /* A 2D tile-cache + bulk-cast variant of this loop was explored and
172
+ reverted: the existing per-row walker already streams source through
173
+ L2/L3, and the tile path loses to per-call cast dispatch overhead
174
+ and an extra untranspose pass. See
175
+ PROPOSAL_TRANSFORM_FUSED_XFER.md for the rejected-direction record.
176
+ A typed (src,dst)-specialised inner loop is the next candidate. */
177
+
178
+ /* ---- Row scratch (parent data_type, inner_count cells) ----
179
+ Skipped when inner_contig is true (= every outer iter uses the
180
+ direct fast path below). */
181
+ row_bytes = inner_count * parent_bytes;
182
+ row_buf = NULL;
183
+ if ( !inner_contig ) {
184
+ if ( row_bytes <= (ca_size_t)CA_TRANSFORM_ROW_STACK_BYTES ) {
185
+ row_buf = row_stack;
186
+ } else {
187
+ row_buf = ALLOCV_N(char, holder, row_bytes);
188
+ }
189
+ }
190
+
191
+ /* ---- Walk outer (ndim-1) axes on odometer ---- */
192
+ outer_total = 1;
193
+ for ( k = 0; k < ndim - 1; k++ ) outer_total *= counts[k];
194
+ for ( k = 0; k < ndim - 1; k++ ) idx[k] = 0;
195
+ doff = 0;
196
+
197
+ for ( n = 0; n < outer_total; n++ ) {
198
+ /* Outer offset into root for this inner row. */
199
+ ca_size_t soff = composed_base;
200
+ for ( k = 0; k < ndim - 1; k++ ) soff += idx[k] * eff_root_step[k];
201
+
202
+ if ( inner_contig ) {
203
+ /* Inner-row contig in root; no scratch needed. */
204
+ if ( dir == CA_XFER_GET ) {
205
+ xform_get(inner_count, parent, root->ptr + soff,
206
+ view, data + doff);
207
+ } else {
208
+ xform_put(inner_count, view, data + doff,
209
+ parent, root->ptr + soff);
210
+ }
211
+ } else if ( dir == CA_XFER_GET ) {
212
+ /* root.ptr+soff strided -> row_buf contig (parent data_type). */
213
+ ca_stride_gather_run(row_buf, root->ptr + soff,
214
+ parent_bytes, inner_count, inner_stride);
215
+ /* row_buf (parent data_type) -> data+doff (view data_type). */
216
+ xform_get(inner_count, parent, row_buf, view, data + doff);
217
+ } else {
218
+ /* data+doff (view data_type) -> row_buf contig (parent data_type). */
219
+ xform_put(inner_count, view, data + doff, parent, row_buf);
220
+ /* row_buf contig -> root.ptr+soff strided (parent data_type). */
221
+ ca_stride_scatter_run(root->ptr + soff, row_buf,
222
+ parent_bytes, inner_count, inner_stride);
223
+ }
224
+ doff += inner_count * view_bytes;
225
+
226
+ /* Odometer advance over the outer (ndim-1) axes. */
227
+ if ( ndim < 2 ) break;
228
+ k = ndim - 2;
229
+ while ( k >= 0 ) { if ( ++idx[k] < counts[k] ) break; idx[k] = 0; k--; }
230
+ if ( k < 0 ) break;
231
+ }
232
+
233
+ if ( holder != Qnil ) ALLOCV_END(holder);
234
+ return 1;
235
+ }
@@ -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 */