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,132 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ ca_sort_kernels.h
4
+
5
+ Portable textbook sort kernels (PROPOSAL_PORTABLE_TEXTBOOK_SORT).
6
+
7
+ P.1 / P.2 : quicksort + mergesort over the 10 numeric data types
8
+ (i8 / u8 / i16 / u16 / i32 / u32 / i64 / u64 / f32 / f64)
9
+ P.3 : NaN pre-partition for f32 / f64
10
+ P.4 : pair (value + index) variants for argsort kernels —
11
+ sort_index / sort_addr / partition_index family
12
+ P.9 : value-level quickselect for partition_copy
13
+
14
+ Status: ext-internal. Signatures may change across 3.x while the
15
+ textbook sort family evolves. Included from carray.h so internal
16
+ consumers (carray_sort_kernel.c, carray_order.c, carray_kernels.c,
17
+ mkkernel emit) reach it transparently via `#include "carray.h"`.
18
+
19
+ Depends on int8_t .. uint64_t / float32_t / double / ca_size_t
20
+ typedefs from carray.h — when this header is included from carray.h
21
+ mid-file, those typedefs are already in scope by the time we reach
22
+ the include site.
23
+
24
+ --------------------------------------------------------------------------- */
25
+
26
+ #ifndef CA_SORT_KERNELS_H
27
+ #define CA_SORT_KERNELS_H 1
28
+
29
+ /* Needs int8_t .. uint64_t / float32_t / double / ca_size_t. No longer
30
+ pulled mid-carray.h (PROPOSAL_CARRAY_H_REORG H.4.1), so include carray.h
31
+ directly to be self-sufficient when a consumer includes this header.
32
+ Guard-protected, so the re-entry is a no-op when carray.h is already in
33
+ flight. */
34
+ #include "carray.h"
35
+
36
+ /* P.1 / P.2: quicksort over 10 numeric data types. */
37
+ void ca_sort_quick_i8 (int8_t *a, ca_size_t n);
38
+ void ca_sort_quick_u8 (uint8_t *a, ca_size_t n);
39
+ void ca_sort_quick_i16 (int16_t *a, ca_size_t n);
40
+ void ca_sort_quick_u16 (uint16_t *a, ca_size_t n);
41
+ void ca_sort_quick_i32 (int32_t *a, ca_size_t n);
42
+ void ca_sort_quick_u32 (uint32_t *a, ca_size_t n);
43
+ void ca_sort_quick_i64 (int64_t *a, ca_size_t n);
44
+ void ca_sort_quick_u64 (uint64_t *a, ca_size_t n);
45
+ void ca_sort_quick_f32 (float32_t *a, ca_size_t n);
46
+ void ca_sort_quick_f64 (double *a, ca_size_t n);
47
+
48
+ /* P.1 / P.2: mergesort over 10 numeric data types (`aux` is caller-supplied
49
+ scratch buffer of the same length / data type as `a`). */
50
+ void ca_sort_merge_i8 (int8_t *a, int8_t *aux, ca_size_t n);
51
+ void ca_sort_merge_u8 (uint8_t *a, uint8_t *aux, ca_size_t n);
52
+ void ca_sort_merge_i16 (int16_t *a, int16_t *aux, ca_size_t n);
53
+ void ca_sort_merge_u16 (uint16_t *a, uint16_t *aux, ca_size_t n);
54
+ void ca_sort_merge_i32 (int32_t *a, int32_t *aux, ca_size_t n);
55
+ void ca_sort_merge_u32 (uint32_t *a, uint32_t *aux, ca_size_t n);
56
+ void ca_sort_merge_i64 (int64_t *a, int64_t *aux, ca_size_t n);
57
+ void ca_sort_merge_u64 (uint64_t *a, uint64_t *aux, ca_size_t n);
58
+ void ca_sort_merge_f32 (float32_t *a, float32_t *aux, ca_size_t n);
59
+ void ca_sort_merge_f64 (double *a, double *aux, ca_size_t n);
60
+
61
+ /* P.3: NaN pre-partition for float data types (Hoare 1-pass, returns finite count). */
62
+ ca_size_t ca_partition_nan_f32 (float32_t *a, ca_size_t n);
63
+ ca_size_t ca_partition_nan_f64 (double *a, ca_size_t n);
64
+
65
+ /* P.4: pair variant of NaN pre-partition for float argsort kernels. */
66
+ struct ca_pair_f32;
67
+ struct ca_pair_f64;
68
+ ca_size_t ca_partition_nan_pair_f32 (struct ca_pair_f32 *a, ca_size_t n);
69
+ ca_size_t ca_partition_nan_pair_f64 (struct ca_pair_f64 *a, ca_size_t n);
70
+
71
+ /* P.9: value-level quickselect for partition_copy.
72
+ Reorders a[0..n) so that a[kth] is exact + left/right regions
73
+ satisfy <= / >= contracts. Order within each region unspecified. */
74
+ void ca_partition_quick_i8 (int8_t *a, ca_size_t n, ca_size_t kth);
75
+ void ca_partition_quick_u8 (uint8_t *a, ca_size_t n, ca_size_t kth);
76
+ void ca_partition_quick_i16 (int16_t *a, ca_size_t n, ca_size_t kth);
77
+ void ca_partition_quick_u16 (uint16_t *a, ca_size_t n, ca_size_t kth);
78
+ void ca_partition_quick_i32 (int32_t *a, ca_size_t n, ca_size_t kth);
79
+ void ca_partition_quick_u32 (uint32_t *a, ca_size_t n, ca_size_t kth);
80
+ void ca_partition_quick_i64 (int64_t *a, ca_size_t n, ca_size_t kth);
81
+ void ca_partition_quick_u64 (uint64_t *a, ca_size_t n, ca_size_t kth);
82
+ void ca_partition_quick_f32 (float32_t *a, ca_size_t n, ca_size_t kth);
83
+ void ca_partition_quick_f64 (double *a, ca_size_t n, ca_size_t kth);
84
+
85
+ /* P.4: pair sort kernels (= argsort: sort_index / sort_addr). The pair
86
+ struct is opaque to mkkernel-emitted callers via void*; each kernel
87
+ has its own well-defined layout: { TYPE v; ca_size_t i; } with natural
88
+ alignment padding. */
89
+ struct ca_pair_i8 { int8_t v; ca_size_t i; };
90
+ struct ca_pair_u8 { uint8_t v; ca_size_t i; };
91
+ struct ca_pair_i16 { int16_t v; ca_size_t i; };
92
+ struct ca_pair_u16 { uint16_t v; ca_size_t i; };
93
+ struct ca_pair_i32 { int32_t v; ca_size_t i; };
94
+ struct ca_pair_u32 { uint32_t v; ca_size_t i; };
95
+ struct ca_pair_i64 { int64_t v; ca_size_t i; };
96
+ struct ca_pair_u64 { uint64_t v; ca_size_t i; };
97
+ struct ca_pair_f32 { float32_t v; ca_size_t i; };
98
+ struct ca_pair_f64 { double v; ca_size_t i; };
99
+ typedef struct ca_pair_i8 ca_pair_i8;
100
+ typedef struct ca_pair_u8 ca_pair_u8;
101
+ typedef struct ca_pair_i16 ca_pair_i16;
102
+ typedef struct ca_pair_u16 ca_pair_u16;
103
+ typedef struct ca_pair_i32 ca_pair_i32;
104
+ typedef struct ca_pair_u32 ca_pair_u32;
105
+ typedef struct ca_pair_i64 ca_pair_i64;
106
+ typedef struct ca_pair_u64 ca_pair_u64;
107
+ typedef struct ca_pair_f32 ca_pair_f32;
108
+ typedef struct ca_pair_f64 ca_pair_f64;
109
+
110
+ void ca_sort_quick_pair_i8 (ca_pair_i8 *a, ca_size_t n);
111
+ void ca_sort_quick_pair_u8 (ca_pair_u8 *a, ca_size_t n);
112
+ void ca_sort_quick_pair_i16 (ca_pair_i16 *a, ca_size_t n);
113
+ void ca_sort_quick_pair_u16 (ca_pair_u16 *a, ca_size_t n);
114
+ void ca_sort_quick_pair_i32 (ca_pair_i32 *a, ca_size_t n);
115
+ void ca_sort_quick_pair_u32 (ca_pair_u32 *a, ca_size_t n);
116
+ void ca_sort_quick_pair_i64 (ca_pair_i64 *a, ca_size_t n);
117
+ void ca_sort_quick_pair_u64 (ca_pair_u64 *a, ca_size_t n);
118
+ void ca_sort_quick_pair_f32 (ca_pair_f32 *a, ca_size_t n);
119
+ void ca_sort_quick_pair_f64 (ca_pair_f64 *a, ca_size_t n);
120
+
121
+ void ca_sort_merge_pair_i8 (ca_pair_i8 *a, ca_pair_i8 *aux, ca_size_t n);
122
+ void ca_sort_merge_pair_u8 (ca_pair_u8 *a, ca_pair_u8 *aux, ca_size_t n);
123
+ void ca_sort_merge_pair_i16 (ca_pair_i16 *a, ca_pair_i16 *aux, ca_size_t n);
124
+ void ca_sort_merge_pair_u16 (ca_pair_u16 *a, ca_pair_u16 *aux, ca_size_t n);
125
+ void ca_sort_merge_pair_i32 (ca_pair_i32 *a, ca_pair_i32 *aux, ca_size_t n);
126
+ void ca_sort_merge_pair_u32 (ca_pair_u32 *a, ca_pair_u32 *aux, ca_size_t n);
127
+ void ca_sort_merge_pair_i64 (ca_pair_i64 *a, ca_pair_i64 *aux, ca_size_t n);
128
+ void ca_sort_merge_pair_u64 (ca_pair_u64 *a, ca_pair_u64 *aux, ca_size_t n);
129
+ void ca_sort_merge_pair_f32 (ca_pair_f32 *a, ca_pair_f32 *aux, ca_size_t n);
130
+ void ca_sort_merge_pair_f64 (ca_pair_f64 *a, ca_pair_f64 *aux, ca_size_t n);
131
+
132
+ #endif /* CA_SORT_KERNELS_H */
@@ -0,0 +1,473 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Sweep (xfer_all) author-surface engine: shared acquire / release
4
+ bodies for the ca_call_cfunc trampolines generated by
5
+ mk_call_cfunc.rb. See ca_sweep_engine.h for the full lifecycle
6
+ template.
7
+
8
+ Two paths:
9
+ whole-buffer ca_sweep_acquire / _release — xmalloc scratch
10
+ chunked ca_sweep_acquire_chunked / _next_chunk / _release_chunked
11
+ — arena scratch
12
+
13
+ Both propagate INPUT masks to OUTPUT masks and honor the NO_MASK
14
+ form guard (masked INPUT + NO_MASK = raise, since a NO_MASK kernel
15
+ cannot observe masked cells).
16
+
17
+ ---------------------------------------------------------------------------- */
18
+
19
+ #include "carray.h"
20
+ #include "carray_internal.h" /* ca_lazy_arena_* */
21
+ #include "ca_sweep_engine.h"
22
+ #include "ca_for_buffer.h"
23
+ #include <string.h>
24
+
25
+ void
26
+ ca_sweep_acquire (ca_sweep_state_t *st)
27
+ {
28
+ int k_op;
29
+ int any_input_mask = 0;
30
+
31
+ if ((int) strlen(st->fsync) != st->n_ops) {
32
+ rb_raise(rb_eRuntimeError,
33
+ "[BUG] invalid length of fsync arg in %s (expected %d)",
34
+ st->src_label ? st->src_label : "ca_sweep_acquire",
35
+ st->n_ops);
36
+ }
37
+
38
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
39
+ st->base[k_op] = NULL;
40
+ st->owned_buf[k_op] = NULL;
41
+ st->attached[k_op] = 0;
42
+ }
43
+ st->m0 = NULL;
44
+ st->n_kernel = 1;
45
+ /* CAREFUL: do not reset st->no_mask here — caller sets it before
46
+ * acquire and the NO_MASK guard below consumes it. */
47
+
48
+ /* Per-operand acquire:
49
+ * OUTPUT (fsync == '1') -> ca_attach + base = ca->ptr
50
+ * INPUT alias -> ca_attach + base = ca->ptr
51
+ * INPUT non-alias non-scalar -> xmalloc scratch + ca_xfer_all
52
+ * INPUT non-alias never attaches the operand itself; the scratch
53
+ * copy carries the values into the kernel. */
54
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
55
+ CArray *ca = st->cx[k_op];
56
+ if (st->fsync[k_op] == '1') {
57
+ ca_attach(ca);
58
+ st->base[k_op] = (char *) ca->ptr;
59
+ st->attached[k_op] = 1;
60
+ } else if (ca_attach_is_alias(ca)) {
61
+ ca_attach(ca);
62
+ st->base[k_op] = (char *) ca->ptr;
63
+ st->attached[k_op] = 1;
64
+ } else {
65
+ ca_size_t bytes_total = ca->elements * ca->bytes;
66
+ st->owned_buf[k_op] = xmalloc(bytes_total);
67
+ st->base[k_op] = st->owned_buf[k_op];
68
+ ca_xfer_all(ca, st->base[k_op], CA_XFER_GET);
69
+ }
70
+ }
71
+
72
+ /* compute n_kernel (= broadcast shape) and per-cell strides */
73
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
74
+ CArray *ca = st->cx[k_op];
75
+ if (ca_is_scalar(ca)) {
76
+ st->stride[k_op] = 0;
77
+ } else {
78
+ st->stride[k_op] = ca->bytes;
79
+ if (st->n_kernel == 1) {
80
+ st->n_kernel = ca->elements;
81
+ } else if (ca->elements != st->n_kernel) {
82
+ rb_raise(rb_eRuntimeError, "data size mismatch in operation");
83
+ }
84
+ }
85
+ }
86
+
87
+ /* iter mask m0 = OR of INPUT operand masks, gathered via ca_xfer_all
88
+ so no operand mask attach happens. Stays NULL if no INPUT masks. */
89
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
90
+ if (st->fsync[k_op] == '0' && ca_has_mask(st->cx[k_op])) {
91
+ any_input_mask = 1;
92
+ break;
93
+ }
94
+ }
95
+ if (any_input_mask && st->no_mask) {
96
+ rb_raise(rb_eRuntimeError,
97
+ "%s: masked INPUT not allowed in NO_MASK form "
98
+ "(use the *_MASKED form to handle masked cells explicitly)",
99
+ st->src_label ? st->src_label : "ca_sweep_acquire");
100
+ }
101
+ if (any_input_mask) {
102
+ st->m0 = xmalloc(st->n_kernel);
103
+ memset(st->m0, 0, st->n_kernel);
104
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
105
+ CArray *ca = st->cx[k_op];
106
+ if (st->fsync[k_op] != '0') continue;
107
+ ca_update_mask(ca);
108
+ if (!ca->mask) continue;
109
+ if (ca_is_scalar(ca)) {
110
+ boolean8_t bit = 0;
111
+ ca_xfer_all(ca->mask, &bit, CA_XFER_GET);
112
+ if (bit) memset(st->m0, 1, st->n_kernel);
113
+ } else {
114
+ boolean8_t *ms = xmalloc(st->n_kernel);
115
+ ca_size_t j;
116
+ ca_xfer_all(ca->mask, ms, CA_XFER_GET);
117
+ for (j = 0; j < st->n_kernel; j++) st->m0[j] |= ms[j];
118
+ xfree(ms);
119
+ }
120
+ }
121
+ }
122
+
123
+ /* Overwrite each OUTPUT mask with the iter mask (creating the
124
+ OUTPUT mask if it did not exist). No-op when m0 is NULL. */
125
+ if (st->m0) {
126
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
127
+ CArray *ca = st->cx[k_op];
128
+ if (st->fsync[k_op] != '1') continue;
129
+ ca_update_mask(ca);
130
+ if (!ca->mask) ca_create_mask(ca);
131
+ memcpy(ca->mask->ptr, st->m0, st->n_kernel);
132
+ }
133
+ }
134
+ }
135
+
136
+ void
137
+ ca_sweep_release (ca_sweep_state_t *st)
138
+ {
139
+ int k_op;
140
+ /* sync OUTPUTs (reverse order) */
141
+ for (k_op = st->n_ops - 1; k_op >= 0; k_op--) {
142
+ if (st->fsync[k_op] == '1') ca_sync(st->cx[k_op]);
143
+ }
144
+ /* detach attached / xfree owned buffers (reverse order) */
145
+ for (k_op = st->n_ops - 1; k_op >= 0; k_op--) {
146
+ if (st->attached[k_op]) {
147
+ ca_detach(st->cx[k_op]);
148
+ } else if (st->owned_buf[k_op]) {
149
+ xfree(st->owned_buf[k_op]);
150
+ st->owned_buf[k_op] = NULL;
151
+ }
152
+ }
153
+ if (st->m0) {
154
+ xfree(st->m0);
155
+ st->m0 = NULL;
156
+ }
157
+ }
158
+
159
+ /* ===== Chunked path implementation ===== */
160
+
161
+ void
162
+ ca_sweep_acquire_chunked (ca_sweep_state_t *st)
163
+ {
164
+ int k_op;
165
+ int any_input_mask = 0;
166
+ CArray *shape_donor = NULL;
167
+
168
+ if ((int) strlen(st->fsync) != st->n_ops) {
169
+ rb_raise(rb_eRuntimeError,
170
+ "[BUG] invalid length of fsync arg in %s (expected %d)",
171
+ st->src_label ? st->src_label : "ca_sweep_acquire_chunked",
172
+ st->n_ops);
173
+ }
174
+
175
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
176
+ st->base[k_op] = NULL;
177
+ st->base_orig[k_op] = NULL;
178
+ st->owned_buf[k_op] = NULL;
179
+ st->attached[k_op] = 0;
180
+ }
181
+ st->m0 = NULL;
182
+ st->mask_scratch = NULL;
183
+ st->n_kernel = 1;
184
+ st->chunk_off = 0;
185
+ st->chunk_n = 0;
186
+ st->chunk_n_max = 0;
187
+ st->inner = 1;
188
+ st->chunked_state = 0;
189
+
190
+ /* compute broadcast shape (n_kernel + strides) from operand shapes.
191
+ * scalar operands collapse to stride 0; non-scalar operands must agree
192
+ * on element count. shape_donor is the first non-scalar operand and
193
+ * defines the chunking inner-axis size. */
194
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
195
+ CArray *ca = st->cx[k_op];
196
+ if (ca_is_scalar(ca)) {
197
+ st->stride[k_op] = 0;
198
+ } else {
199
+ st->stride[k_op] = ca->bytes;
200
+ if (st->n_kernel == 1) {
201
+ st->n_kernel = ca->elements;
202
+ shape_donor = ca;
203
+ } else if (ca->elements != st->n_kernel) {
204
+ rb_raise(rb_eRuntimeError, "data size mismatch in operation");
205
+ }
206
+ }
207
+ }
208
+
209
+ /* chunk-size policy: inner = donor's product of dims[1..]; chunk_n_max
210
+ * = compute_n on donor->bytes (= type-dependent 32KB target). */
211
+ if (shape_donor) {
212
+ st->inner = ca_chunk_inner_size(shape_donor);
213
+ st->chunk_n_max = ca_chunk_compute_n(st->n_kernel, st->inner,
214
+ shape_donor->bytes);
215
+ } else {
216
+ /* all-scalar: single 1-cell chunk */
217
+ st->inner = 1;
218
+ st->chunk_n_max = 1;
219
+ }
220
+
221
+ /* per-operand acquire:
222
+ * OUTPUT (fsync == '1') : ca_attach + base_orig = ca->ptr (legitimate)
223
+ * INPUT alias : ca_attach + base_orig = ca->ptr (zero-copy)
224
+ * INPUT non-alias non-scalar : arena chunk scratch of chunk_n_max bytes
225
+ * INPUT scalar : ca_attach + base_orig = ca->ptr (1 cell)
226
+ */
227
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
228
+ CArray *ca = st->cx[k_op];
229
+ if (st->fsync[k_op] == '1') {
230
+ ca_attach(ca);
231
+ st->base_orig[k_op] = (char *) ca->ptr;
232
+ st->attached[k_op] = 1;
233
+ } else if (ca_is_scalar(ca) || ca_attach_is_alias(ca)) {
234
+ ca_attach(ca);
235
+ st->base_orig[k_op] = (char *) ca->ptr;
236
+ st->attached[k_op] = 1;
237
+ } else {
238
+ /* non-alias non-scalar INPUT: arena scratch sized for chunk_n_max */
239
+ ca_size_t scratch_bytes = st->chunk_n_max * ca->bytes;
240
+ st->owned_buf[k_op] = (char *) ca_lazy_arena_acquire(scratch_bytes);
241
+ /* base_orig stays NULL -- per-chunk gather lands the data in
242
+ * owned_buf[k_op]; base[k_op] will be set to owned_buf[k_op] at
243
+ * each chunk boundary. */
244
+ }
245
+ }
246
+
247
+ /* iter mask = OR of INPUT operand masks, chunk-sized (chunk_n_max bytes)
248
+ * and re-gathered per chunk in ca_sweep_next_chunk. m0 is indexed by the
249
+ * offset within the chunk, m0[k] for k < chunk_n -- NOT by the flat cell
250
+ * index. Sizing it to n_kernel instead would leave one allocation still
251
+ * scaling with the operand, which is the thing this path exists to avoid:
252
+ * at 1 byte per cell it is an eighth of an f64 operand, but an eighth of
253
+ * unbounded is still unbounded. */
254
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
255
+ if (st->fsync[k_op] == '0' && ca_has_mask(st->cx[k_op])) {
256
+ any_input_mask = 1;
257
+ break;
258
+ }
259
+ }
260
+ if (any_input_mask && st->no_mask) {
261
+ rb_raise(rb_eRuntimeError,
262
+ "%s: masked INPUT not allowed in NO_MASK form "
263
+ "(use the *_MASKED form to handle masked cells explicitly)",
264
+ st->src_label ? st->src_label : "ca_sweep_acquire_chunked");
265
+ }
266
+ if (any_input_mask) {
267
+ st->m0 = (boolean8_t *) ca_lazy_arena_acquire(st->chunk_n_max);
268
+ st->mask_scratch = (boolean8_t *) ca_lazy_arena_acquire(st->chunk_n_max);
269
+ memset(st->m0, 0, st->chunk_n_max);
270
+ /* The OUTPUT masks have to exist before the walk starts, because each
271
+ * chunk's m0 is flushed into them as the walk passes -- there is no
272
+ * whole m0 left at release time to propagate in one go. */
273
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
274
+ CArray *ca = st->cx[k_op];
275
+ if (st->fsync[k_op] != '1') continue;
276
+ ca_update_mask(ca);
277
+ if (!ca->mask) ca_create_mask(ca);
278
+ }
279
+ }
280
+
281
+ /* CAREFUL: m0 -> OUTPUT mask propagation happens per chunk, at the point
282
+ * the chunk is finished (= the top of the next ca_sweep_next_chunk, and
283
+ * once more in release), never at acquire. Author per-cell m_out writes
284
+ * land in m0 during the chunk loop and must be captured after that loop
285
+ * has run, not before it. */
286
+ }
287
+
288
+ /* OR one INPUT operand's mask for the current chunk into m0. Gathered via
289
+ * ca_chunked_gather rather than attached, so no operand mask is ever
290
+ * attached -- the same invariant the whole-buffer path keeps with
291
+ * ca_xfer_all. */
292
+ static void
293
+ ca_sweep_gather_chunk_mask (ca_sweep_state_t *st, ca_size_t off, ca_size_t n)
294
+ {
295
+ int k_op;
296
+ ca_size_t j;
297
+
298
+ memset(st->m0, 0, n);
299
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
300
+ CArray *ca = st->cx[k_op];
301
+ if (st->fsync[k_op] != '0') continue;
302
+ ca_update_mask(ca);
303
+ if (!ca->mask) continue;
304
+ if (ca_is_scalar(ca)) {
305
+ /* one cell, broadcast across the chunk */
306
+ boolean8_t bit = 0;
307
+ ca_xfer_all(ca->mask, &bit, CA_XFER_GET);
308
+ if (bit) memset(st->m0, 1, n);
309
+ } else {
310
+ ca_chunked_gather(ca->mask, off, n, st->mask_scratch);
311
+ for (j = 0; j < n; j++) st->m0[j] |= st->mask_scratch[j];
312
+ }
313
+ }
314
+ }
315
+
316
+ /* Copy the chunk just finished out to every OUTPUT operand's mask. Runs
317
+ * after the author's loop over that chunk, so m_out writes into m0 are
318
+ * carried through. */
319
+ static void
320
+ ca_sweep_flush_chunk_mask (ca_sweep_state_t *st)
321
+ {
322
+ int k_op;
323
+ if (!st->m0 || st->chunked_state != 1 || st->chunk_n == 0) return;
324
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
325
+ CArray *ca = st->cx[k_op];
326
+ if (st->fsync[k_op] != '1') continue;
327
+ if (!ca->mask) continue;
328
+ memcpy((boolean8_t *) ca->mask->ptr + st->chunk_off, st->m0, st->chunk_n);
329
+ }
330
+ }
331
+
332
+ int
333
+ ca_sweep_next_chunk (ca_sweep_state_t *st)
334
+ {
335
+ int k_op;
336
+ ca_size_t off, n;
337
+
338
+ if (st->chunked_state == 0) {
339
+ /* first chunk */
340
+ st->chunk_off = 0;
341
+ st->chunked_state = 1;
342
+ } else {
343
+ /* the chunk that just finished is the author's last word on its mask */
344
+ ca_sweep_flush_chunk_mask(st);
345
+ /* advance */
346
+ st->chunk_off += st->chunk_n;
347
+ }
348
+
349
+ if (st->chunk_off >= st->n_kernel) {
350
+ st->chunked_state = 2;
351
+ return 0;
352
+ }
353
+
354
+ off = st->chunk_off;
355
+ n = st->chunk_n_max;
356
+ if (off + n > st->n_kernel) n = st->n_kernel - off;
357
+ st->chunk_n = n;
358
+
359
+ /* set up base[] for the upcoming chunk */
360
+ for (k_op = 0; k_op < st->n_ops; k_op++) {
361
+ CArray *ca = st->cx[k_op];
362
+ if (st->stride[k_op] == 0) {
363
+ /* scalar: stride 0, base is the single-cell ptr (base_orig) */
364
+ st->base[k_op] = st->base_orig[k_op];
365
+ } else if (st->base_orig[k_op]) {
366
+ /* alias INPUT or OUTPUT: walk through ca->ptr by chunk_off */
367
+ st->base[k_op] = st->base_orig[k_op] + off * st->stride[k_op];
368
+ } else {
369
+ /* non-alias INPUT: per-chunk gather into owned_buf (arena) */
370
+ ca_chunked_gather(ca, off, n, st->owned_buf[k_op]);
371
+ st->base[k_op] = st->owned_buf[k_op];
372
+ }
373
+ }
374
+
375
+ if (st->m0) ca_sweep_gather_chunk_mask(st, off, n);
376
+
377
+ return 1;
378
+ }
379
+
380
+ void
381
+ ca_sweep_release_chunked (ca_sweep_state_t *st)
382
+ {
383
+ int k_op;
384
+ /* The final chunk has no next_chunk call to flush it, so it is flushed
385
+ * here. For INOUT_MASKED forms this is what captures the author's
386
+ * per-cell m_out writes over that last chunk. */
387
+ ca_sweep_flush_chunk_mask(st);
388
+ /* sync OUTPUTs (reverse order, regardless of whether chunk loop ran) */
389
+ for (k_op = st->n_ops - 1; k_op >= 0; k_op--) {
390
+ if (st->fsync[k_op] == '1') ca_sync(st->cx[k_op]);
391
+ }
392
+ /* detach attached / release arena scratch buffers (reverse order) */
393
+ for (k_op = st->n_ops - 1; k_op >= 0; k_op--) {
394
+ if (st->attached[k_op]) {
395
+ ca_detach(st->cx[k_op]);
396
+ } else if (st->owned_buf[k_op]) {
397
+ ca_lazy_arena_release(st->owned_buf[k_op]);
398
+ st->owned_buf[k_op] = NULL;
399
+ }
400
+ }
401
+ if (st->m0) {
402
+ ca_lazy_arena_release(st->m0);
403
+ st->m0 = NULL;
404
+ }
405
+ if (st->mask_scratch) {
406
+ ca_lazy_arena_release(st->mask_scratch);
407
+ st->mask_scratch = NULL;
408
+ }
409
+ }
410
+
411
+ /* ===== WHOLE_BUFFER function form (rb_ensure-protected) ===== */
412
+
413
+ typedef struct {
414
+ CArray *ca;
415
+ int writable;
416
+ ca_with_buffer_body_fn body_fn;
417
+ void *user_data;
418
+ } ca_with_buffer_ctx_t;
419
+
420
+ static VALUE
421
+ ca_with_buffer_body_trampoline (VALUE ctx_val)
422
+ {
423
+ ca_with_buffer_ctx_t *ctx = (ca_with_buffer_ctx_t *) ctx_val;
424
+ ctx->body_fn(ctx->user_data, ctx->ca->ptr, ctx->ca->elements);
425
+ return Qnil;
426
+ }
427
+
428
+ static VALUE
429
+ ca_with_buffer_ensure_trampoline (VALUE ctx_val)
430
+ {
431
+ ca_with_buffer_ctx_t *ctx = (ca_with_buffer_ctx_t *) ctx_val;
432
+ if (ctx->writable) ca_sync(ctx->ca);
433
+ ca_detach(ctx->ca);
434
+ return Qnil;
435
+ }
436
+
437
+ void
438
+ rb_ca_call_with_buffer (VALUE r_ca, int writable,
439
+ ca_with_buffer_body_fn body, void *user_data)
440
+ {
441
+ ca_with_buffer_ctx_t ctx;
442
+ TypedData_Get_Struct(r_ca, CArray, &carray_data_type, ctx.ca);
443
+ /* CAREFUL: attach outside rb_ensure. If attach raises, we are not
444
+ * yet inside the ensure scope, so the ensure trampoline will not
445
+ * fire on a not-attached ca (which would try to detach and crash). */
446
+ ca_attach(ctx.ca);
447
+ ctx.writable = writable;
448
+ ctx.body_fn = body;
449
+ ctx.user_data = user_data;
450
+ rb_ensure(ca_with_buffer_body_trampoline, (VALUE) &ctx,
451
+ ca_with_buffer_ensure_trampoline, (VALUE) &ctx);
452
+ }
453
+
454
+ void
455
+ ca_sweep_check_same_shape (CArray *ca_in, CArray *ca_out, const char *src_label)
456
+ {
457
+ int k;
458
+ const char *lbl = src_label ? src_label : "ca_sweep_check_same_shape";
459
+ if (ca_in->ndim != ca_out->ndim) {
460
+ rb_raise(rb_eRuntimeError,
461
+ "%s: shape mismatch (ndim %d vs %d)",
462
+ lbl, ca_in->ndim, ca_out->ndim);
463
+ }
464
+ for (k = 0; k < ca_in->ndim; k++) {
465
+ if (ca_in->dim[k] != ca_out->dim[k]) {
466
+ rb_raise(rb_eRuntimeError,
467
+ "%s: shape mismatch at dim[%d] (%lld vs %lld)",
468
+ lbl, k,
469
+ (long long) ca_in->dim[k],
470
+ (long long) ca_out->dim[k]);
471
+ }
472
+ }
473
+ }