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,839 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Lazy binadic element-wise comparison view: holds (left, right,
4
+ op_id, eps) and materialises a boolean result on attach. Carries
5
+ CA_FLAG_READ_ONLY; there is no bang path and `[]=` raises.
6
+
7
+ Sibling of ca_obj_binop.c (element-wise arithmetic) and
8
+ ca_obj_moncmp.c (unary comparisons); dispatched by
9
+ ca_bincmp_kernel_lookup from ca_bincmp_dispatch.h.
10
+
11
+ Dispatch by data_type:
12
+ numeric (i8..f64, +complex) -> ca_bincmp_<op>_<type> kernel
13
+ boolean / fixlen / object -> not implemented (raise)
14
+
15
+ CAREFUL: the binop in-place trick (= pull left into the output
16
+ buffer) is structurally unavailable here — the output is
17
+ boolean8_t (1 byte per cell) while operands live at the common
18
+ data_type (typically 8 bytes at f64), so a pull-into-output would
19
+ overflow. xfer_stride therefore holds two operand-typed scratch
20
+ slabs and writes the boolean result directly to `data`.
21
+
22
+ Comparison ops never trap, so the kernel is called with m=NULL
23
+ (SIMD fast path). The output mask is computed by create_mask as
24
+ `left.mask | right.mask` and propagated through the standard
25
+ CArray mask machinery.
26
+
27
+ ---------------------------------------------------------------------------- */
28
+
29
+ #include "carray.h"
30
+ #include "carray_internal.h" /* ca_lazy_arena_* */
31
+ #include "ca_bincmp_dispatch.h"
32
+ #include "ca_monop_dispatch.h" /* CA_MONOP_CAST_BASE */
33
+
34
+ extern VALUE ca_broadcast_view (VALUE src, int8_t ndim,
35
+ ca_size_t *target_dim);
36
+ extern VALUE ca_lazy_wrap_scalar (VALUE other, CArray *self_ca);
37
+ extern void *ca_lazy_arena_acquire (ca_size_t bytes);
38
+ extern void ca_lazy_arena_release (void *ptr);
39
+
40
+ int8_t CA_OBJ_BINCMP;
41
+ VALUE rb_cCABinCmp;
42
+
43
+ extern int8_t CA_OBJ_LAZY_MARKER;
44
+
45
+ /* ------------------------------------------------------------------- */
46
+ /* CABinCmp struct */
47
+ /* ------------------------------------------------------------------- */
48
+
49
+ typedef struct CABinCmp {
50
+ int16_t obj_type;
51
+ int8_t data_type; /* always CA_BOOLEAN */
52
+ int8_t ndim;
53
+ int32_t flags;
54
+ ca_size_t bytes; /* always 1 */
55
+ ca_size_t elements;
56
+ ca_size_t *dim;
57
+ char *ptr;
58
+ CArray *mask;
59
+ char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path). */
60
+ CArray *parent; /* = left */
61
+ uint32_t attach;
62
+ uint8_t nosync;
63
+ /* ---- CAMultiParent conformance (CA_FLAG_MULTI_PARENTS): n_parents and
64
+ parents[] sit immediately after the CAView header, as carray.h's
65
+ layout convention requires, so ca_has_mask can fold over both
66
+ operands and build the mask on demand instead of at setup. ---- */
67
+ int32_t n_parents; /* always 2 */
68
+ CArray **parents; /* = &operands[0]; no separate allocation */
69
+ /* CABinCmp-specific tail */
70
+ CArray *right;
71
+ uint16_t op_id;
72
+ uint8_t right_is_scalar;
73
+ int8_t common_dt; /* operand-data_type after promote (= cast
74
+ target of both left & right, also the
75
+ kernel lookup key) */
76
+ double eps; /* Runtime tolerance slot for IS_CLOSE /
77
+ IS_EQUIV; ignored for other ops. The
78
+ `eps` name is retained to keep the
79
+ `__eps__` Ruby accessor stable across
80
+ the dual purpose. */
81
+ CArray *operands[2]; /* {left, right}; what parents points at */
82
+ } CABinCmp;
83
+
84
+ static size_t
85
+ ca_bincmp_dsize (const void *ap)
86
+ {
87
+ const CABinCmp *ca = (const CABinCmp *) ap;
88
+ return sizeof(CABinCmp) + ca->ndim * sizeof(ca_size_t);
89
+ }
90
+
91
+ /* Pool framework hooks: single ndim-sized tail (dim) in the _pool
92
+ buffer. See ca_array_pool.c for the shared alloc/free discipline. */
93
+ static size_t
94
+ ca_bincmp_pool_bytes (int8_t ndim)
95
+ {
96
+ ca_size_t n = (ndim > 0) ? ndim : 1;
97
+ return (size_t) n * sizeof(ca_size_t);
98
+ }
99
+
100
+ static void
101
+ ca_bincmp_pool_init (void *ap, int8_t ndim)
102
+ {
103
+ CABinCmp *ca = (CABinCmp *) ap;
104
+ ca->dim = (ca_size_t *) ca->_pool;
105
+ }
106
+
107
+ const rb_data_type_t cabincmp_data_type = {
108
+ .parent = &caview_data_type,
109
+ .wrap_struct_name = "CABinCmp",
110
+ .function = {
111
+ .dmark = ca_mark,
112
+ .dfree = ca_free,
113
+ .dsize = ca_bincmp_dsize,
114
+ .dcompact = NULL
115
+ },
116
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
117
+ };
118
+
119
+ /* ------------------------------------------------------------------- */
120
+ /* setup / new / free */
121
+ /* ------------------------------------------------------------------- */
122
+
123
+ static int
124
+ ca_bincmp_setup (CABinCmp *ca, CArray *left, CArray *right, uint16_t op_id,
125
+ double eps)
126
+ {
127
+ ca->obj_type = CA_OBJ_BINCMP;
128
+ ca->data_type = CA_BOOLEAN; /* output is always boolean */
129
+ ca->flags = CA_FLAG_READ_ONLY | CA_FLAG_MULTI_PARENTS;
130
+ ca->ndim = left->ndim;
131
+ ca->bytes = 1; /* boolean8_t */
132
+ ca->elements = left->elements;
133
+ ca->ptr = NULL;
134
+ ca->mask = NULL;
135
+ if ( ! ca->_pool ) {
136
+ ca->dim = ALLOC_N(ca_size_t, left->ndim);
137
+ }
138
+ ca->parent = left;
139
+ ca->attach = 0;
140
+ ca->nosync = 0;
141
+ ca->right = right;
142
+ ca->op_id = op_id;
143
+ ca->right_is_scalar = ( right->elements == 1 && left->elements > 1 ) ? 1 : 0;
144
+ /* Builder has already cast both operands to common data_type. */
145
+ ca->common_dt = left->data_type;
146
+ ca->eps = eps;
147
+ ca->operands[0] = left;
148
+ ca->operands[1] = right;
149
+ ca->parents = ca->operands;
150
+ ca->n_parents = 2;
151
+
152
+ memcpy(ca->dim, left->dim, left->ndim * sizeof(ca_size_t));
153
+
154
+ /* The mask is NOT built here. ca_has_mask folds over parents[] for a
155
+ multi-parent view and creates it on demand, so an expression whose mask
156
+ nobody reads never allocates one. */
157
+
158
+ if ( ca_is_scalar(left) && ca_is_scalar(right) ) {
159
+ ca_set_flag(ca, CA_FLAG_SCALAR);
160
+ }
161
+
162
+ return 0;
163
+ }
164
+
165
+ CABinCmp *
166
+ ca_bincmp_new (CArray *left, CArray *right, uint16_t op_id, double eps)
167
+ {
168
+ CABinCmp *ca = (CABinCmp *) ca_array_alloc(CA_OBJ_BINCMP, left->ndim);
169
+ ca_bincmp_setup(ca, left, right, op_id, eps);
170
+ return ca;
171
+ }
172
+
173
+ static void
174
+ free_ca_bincmp (void *ap)
175
+ {
176
+ CABinCmp *ca = (CABinCmp *) ap;
177
+ if ( ca != NULL ) {
178
+ ca_free(ca->mask);
179
+ if ( ca->_pool ) {
180
+ ca_array_free(ca); /* dim lives in _pool */
181
+ }
182
+ else {
183
+ xfree(ca->dim);
184
+ xfree(ca);
185
+ }
186
+ }
187
+ }
188
+
189
+ /* ------------------------------------------------------------------- */
190
+ /* operation function table */
191
+ /* ------------------------------------------------------------------- */
192
+
193
+ static void ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts,
194
+ ca_size_t *counts,
195
+ ca_size_t *strides,
196
+ void *data, int dir);
197
+
198
+ static void *
199
+ ca_bincmp_func_clone (void *ap)
200
+ {
201
+ CABinCmp *ca = (CABinCmp *) ap;
202
+ return ca_bincmp_new(ca->parent, ca->right, ca->op_id, ca->eps);
203
+ }
204
+
205
+ static void
206
+ ca_bincmp_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
207
+ {
208
+ CABinCmp *ca = (CABinCmp *) ap;
209
+ ca_size_t starts[CA_RANK_MAX];
210
+ ca_size_t counts[CA_RANK_MAX];
211
+ ca_size_t strides[CA_RANK_MAX];
212
+ int8_t k;
213
+
214
+ if ( dir != CA_XFER_GET ) {
215
+ rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_index PUT)");
216
+ }
217
+
218
+ for ( k = ca->ndim - 1; k >= 0; k-- ) {
219
+ starts[k] = idx[k];
220
+ counts[k] = 1;
221
+ strides[k] = 1; /* boolean8_t */
222
+ }
223
+ ca_bincmp_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
224
+ }
225
+
226
+ static void
227
+ ca_bincmp_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
228
+ void *data, int dir)
229
+ {
230
+ CABinCmp *ca = (CABinCmp *) ap;
231
+ ca_size_t i;
232
+ char *out = (char *) data;
233
+
234
+ if ( dir != CA_XFER_GET ) {
235
+ rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_addrs PUT)");
236
+ }
237
+
238
+ for ( i = 0; i < n; i++ ) {
239
+ ca_size_t idx[CA_RANK_MAX];
240
+ ca_addr2index((CArray *)ca, addrs[i], idx);
241
+ ca_bincmp_func_xfer_index(ca, idx, out + i, CA_XFER_GET);
242
+ }
243
+ }
244
+
245
+ /* Test / observability counters — bumped from the xfer_stride hot
246
+ path so specs can assert scratch acquisition and leaf in-place
247
+ hit rates without materialising the view. */
248
+ ca_size_t ca_bincmp_scratch_acquire_count = 0;
249
+ ca_size_t ca_bincmp_materialise_call_count = 0;
250
+ ca_size_t ca_bincmp_leaf_inplace_count = 0;
251
+
252
+ /* Leaf-operand in-place read eligibility. When the operand has a
253
+ valid contiguous backing buffer at the common data_type, we can
254
+ use operand->ptr + byte_offset directly, skipping the arena
255
+ acquire and the ca_xfer_stride pull.
256
+ *
257
+ * Eligible cases:
258
+ * - entity (CA_OBJ_ARRAY / CA_OBJ_SCALAR / CA_OBJ_ARRAY_WRAP) at
259
+ * the common data_type
260
+ * - already-attached view at the common data_type with a
261
+ * contiguous ptr
262
+ *
263
+ * The request must be a row-major slab over the operand (what
264
+ * xfer_all sends, which is the dominant to_ca path). */
265
+ static int
266
+ ca_bincmp_try_leaf_inplace (CArray *op, int8_t common_dt,
267
+ ca_size_t *starts, ca_size_t *counts,
268
+ ca_size_t expected_inner_byte_stride,
269
+ char **out_ptr)
270
+ {
271
+ ca_size_t row_strides[CA_RANK_MAX];
272
+ ca_size_t s, byte_off;
273
+ int8_t k;
274
+
275
+ if ( op->data_type != common_dt ) return 0;
276
+ if ( op->ptr == NULL ) return 0;
277
+ if ( op->bytes != expected_inner_byte_stride ) return 0;
278
+
279
+ /* Compute row-major byte offset from starts[]. We rely on the
280
+ caller (ca_xfer_all) providing row-major counts == op->dim or a
281
+ contig sub-region. byte_off = sum(starts[k] * row_stride_k)
282
+ where row_stride_k = product of dim[k+1..ndim-1] * bytes. */
283
+ s = op->bytes;
284
+ for ( k = op->ndim - 1; k >= 0; k-- ) {
285
+ row_strides[k] = s;
286
+ s *= op->dim[k];
287
+ }
288
+ byte_off = 0;
289
+ for ( k = 0; k < op->ndim; k++ ) {
290
+ /* require sub-region fits within parent dim (= no OOB) */
291
+ if ( starts[k] < 0 || starts[k] + counts[k] > op->dim[k] ) return 0;
292
+ byte_off += starts[k] * row_strides[k];
293
+ }
294
+
295
+ *out_ptr = op->ptr + byte_off;
296
+ return 1;
297
+ }
298
+
299
+ static void
300
+ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
301
+ ca_size_t *strides, void *data, int dir)
302
+ {
303
+ CABinCmp *bc = (CABinCmp *) ap;
304
+ ca_size_t slab_n;
305
+ int8_t k;
306
+ void *left_scratch, *right_scratch;
307
+ ca_size_t operand_bytes;
308
+ ca_size_t operand_strides[CA_RANK_MAX];
309
+ ca_size_t right_step;
310
+ int is_contig;
311
+ int left_is_inplace = 0; /* skip release for leaf-opt path */
312
+ int right_is_inplace = 0;
313
+
314
+ if ( dir != CA_XFER_GET ) {
315
+ rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_stride PUT)");
316
+ }
317
+ ca_bincmp_materialise_call_count++;
318
+
319
+ slab_n = 1;
320
+ for ( k = 0; k < bc->ndim; k++ ) slab_n *= counts[k];
321
+
322
+ operand_bytes = ca_sizeof[bc->common_dt];
323
+
324
+ /* An operand cell is operand_bytes wide where this view's is one byte
325
+ (CA_BOOLEAN), so the caller's strides cannot be handed to the operand
326
+ pull the way a binop hands them on -- they have to be restated at the
327
+ operand's cell size. strides[k] / bytes is the index step, which is
328
+ what the two spaces share.
329
+
330
+ is_contig says the caller asked for the row-major slab that xfer_all
331
+ and attach send. Only then does an operand's own buffer hold the
332
+ wanted cells in the packed order the kernel reads them in, so it is
333
+ also the only case the leaf in-place path is good for. */
334
+ {
335
+ ca_size_t native = bc->bytes;
336
+ is_contig = 1;
337
+ for ( k = bc->ndim - 1; k >= 0; k-- ) {
338
+ operand_strides[k] = strides[k] / bc->bytes * operand_bytes;
339
+ if ( strides[k] != native ) {
340
+ is_contig = 0;
341
+ }
342
+ native *= bc->dim[k];
343
+ }
344
+ }
345
+
346
+ /* === 1. pull LEFT (leaf in-place read or arena scratch) === */
347
+ {
348
+ char *left_inplace = NULL;
349
+ if ( is_contig &&
350
+ ca_bincmp_try_leaf_inplace(bc->parent, bc->common_dt,
351
+ starts, counts, operand_bytes,
352
+ &left_inplace) ) {
353
+ /* Leaf-opt path: use parent->ptr + byte_offset directly. */
354
+ left_scratch = left_inplace;
355
+ left_is_inplace = 1;
356
+ ca_bincmp_leaf_inplace_count++;
357
+ }
358
+ else {
359
+ left_scratch = ( bc->common_dt == CA_OBJECT )
360
+ ? ca_lazy_arena_acquire_object(slab_n)
361
+ : ca_lazy_arena_acquire(slab_n * operand_bytes);
362
+ ca_bincmp_scratch_acquire_count++;
363
+ ca_xfer_stride(bc->parent, starts, counts, operand_strides, left_scratch,
364
+ CA_XFER_GET);
365
+ }
366
+ }
367
+
368
+ /* === 2. pull RIGHT (right_is_scalar + leaf-opt) === */
369
+ if ( bc->right_is_scalar ) {
370
+ /* CScalar right: pull the single value into a 1-cell scratch
371
+ and walk the kernel with right_step=0. Leaf-opt applies when
372
+ right is an entity-shaped CScalar at the common data_type;
373
+ the gain per call is small but the code path stays uniform
374
+ with the same-shape case. */
375
+ char *right_inplace = NULL;
376
+ ca_size_t one_starts[CA_RANK_MAX] = {0};
377
+ ca_size_t one_counts[CA_RANK_MAX];
378
+ for ( k = 0; k < bc->right->ndim; k++ ) one_counts[k] = 1;
379
+
380
+ if ( ca_bincmp_try_leaf_inplace(bc->right, bc->common_dt,
381
+ one_starts, one_counts, operand_bytes,
382
+ &right_inplace) ) {
383
+ right_scratch = right_inplace;
384
+ right_is_inplace = 1;
385
+ ca_bincmp_leaf_inplace_count++;
386
+ }
387
+ else {
388
+ ca_size_t one_strides[CA_RANK_MAX];
389
+ for ( k = 0; k < bc->right->ndim; k++ ) one_strides[k] = operand_bytes;
390
+ right_scratch = ( bc->common_dt == CA_OBJECT )
391
+ ? ca_lazy_arena_acquire_object(1)
392
+ : ca_lazy_arena_acquire(operand_bytes);
393
+ ca_bincmp_scratch_acquire_count++;
394
+ ca_xfer_stride(bc->right, one_starts, one_counts, one_strides,
395
+ right_scratch, CA_XFER_GET);
396
+ }
397
+ right_step = 0;
398
+ }
399
+ else {
400
+ /* Same-shape right: full slab pull or leaf-opt. */
401
+ char *right_inplace = NULL;
402
+ if ( is_contig &&
403
+ ca_bincmp_try_leaf_inplace(bc->right, bc->common_dt,
404
+ starts, counts, operand_bytes,
405
+ &right_inplace) ) {
406
+ right_scratch = right_inplace;
407
+ right_is_inplace = 1;
408
+ ca_bincmp_leaf_inplace_count++;
409
+ }
410
+ else {
411
+ right_scratch = ( bc->common_dt == CA_OBJECT )
412
+ ? ca_lazy_arena_acquire_object(slab_n)
413
+ : ca_lazy_arena_acquire(slab_n * operand_bytes);
414
+ ca_bincmp_scratch_acquire_count++;
415
+ ca_xfer_stride(bc->right, starts, counts, operand_strides, right_scratch,
416
+ CA_XFER_GET);
417
+ }
418
+ right_step = 1;
419
+ }
420
+
421
+ /* === 3. apply bincmp kernel ===
422
+ *
423
+ * Kernel signature (ext/carray.h):
424
+ * fn(n, m, ptr1, b1, i1, ptr2, b2, i2, ptr3, b3, i3)
425
+ *
426
+ * Per inspection of generated ca_bincmp_<op>_<data_type>, the `b*` args
427
+ * are declared but unused (kernel computes ptr + k*i*sizeof(T)). We
428
+ * pass 0 for the base arguments.
429
+ *
430
+ * Non-trapping: m=NULL (= SIMD fast path). Mask propagation handled
431
+ * by create_mask at view construction time.
432
+ */
433
+ {
434
+ ca_bincmp_func_t fn = ca_bincmp_kernel_lookup(bc->op_id, bc->common_dt);
435
+ if ( fn == NULL ) {
436
+ if ( ! right_is_inplace ) ca_lazy_arena_release(right_scratch);
437
+ if ( ! left_is_inplace ) ca_lazy_arena_release(left_scratch);
438
+ rb_raise(rb_eNotImpError,
439
+ "CABinCmp: kernel not implemented (op_id=%u data_type=%d)",
440
+ (unsigned) bc->op_id, (int) bc->common_dt);
441
+ }
442
+ fn(slab_n, NULL,
443
+ (char *) left_scratch, 0, 1,
444
+ (char *) right_scratch, 0, right_step,
445
+ (char *) data, 0, 1,
446
+ bc->eps); /* Runtime tolerance for IS_CLOSE / IS_EQUIV. */
447
+ }
448
+
449
+ if ( ! right_is_inplace ) ca_lazy_arena_release(right_scratch);
450
+ if ( ! left_is_inplace ) ca_lazy_arena_release(left_scratch);
451
+ }
452
+
453
+ static void
454
+ ca_bincmp_func_xfer_all (void *ap, void *data, int dir)
455
+ {
456
+ CABinCmp *ca = (CABinCmp *) ap;
457
+ ca_size_t starts[CA_RANK_MAX];
458
+ ca_size_t native[CA_RANK_MAX];
459
+ int8_t k;
460
+ ca_size_t s = 1; /* output stride = 1 byte */
461
+ for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
462
+ for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
463
+ ca_xfer_stride(ca, starts, ca->dim, native, data, dir);
464
+ }
465
+
466
+ static void
467
+ ca_bincmp_func_allocate (void *ap)
468
+ {
469
+ CABinCmp *ca = (CABinCmp *) ap;
470
+ ca->ptr = xmalloc(ca_length(ca));
471
+ }
472
+
473
+ static void
474
+ ca_bincmp_func_attach (void *ap)
475
+ {
476
+ /* CAREFUL: call the view-specific xfer_stride directly here,
477
+ not the public ca_xfer_stride dispatcher. The dispatcher's
478
+ self-memcpy fast path detects data == ca->ptr and returns
479
+ without materialising, so the freshly-allocated buffer would
480
+ still hold garbage. */
481
+ CABinCmp *ca = (CABinCmp *) ap;
482
+ ca_size_t starts[CA_RANK_MAX];
483
+ ca_size_t native[CA_RANK_MAX];
484
+ int8_t k;
485
+ ca_size_t s;
486
+
487
+ ca->ptr = xmalloc(ca_length(ca));
488
+
489
+ s = ca->bytes;
490
+ for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
491
+ for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
492
+ ca_bincmp_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
493
+ }
494
+
495
+ static void
496
+ ca_bincmp_func_sync (void *ap)
497
+ {
498
+ /* read-only */
499
+ }
500
+
501
+ static void
502
+ ca_bincmp_func_detach (void *ap)
503
+ {
504
+ CABinCmp *ca = (CABinCmp *) ap;
505
+ xfree(ca->ptr);
506
+ ca->ptr = NULL;
507
+ }
508
+
509
+ NORETURN(static void ca_bincmp_func_fill_data (void *ap, void *ptr));
510
+ static void
511
+ ca_bincmp_func_fill_data (void *ap, void *ptr)
512
+ {
513
+ rb_raise(rb_eRuntimeError, "CABinCmp is read-only (fill_data)");
514
+ }
515
+
516
+ /* mask = left.mask | right.mask, materialised as boolean8_t.
517
+ Mirrors CABinOp's create_mask policy. */
518
+ static void
519
+ ca_bincmp_func_create_mask (void *ap)
520
+ {
521
+ CABinCmp *bc = (CABinCmp *) ap;
522
+ CArray *l = bc->parent;
523
+ CArray *r = bc->right;
524
+ CArray *lm = NULL, *rm = NULL;
525
+ boolean8_t *dst;
526
+ ca_size_t i, n;
527
+ int has_l, has_r;
528
+
529
+ has_l = ca_has_mask(l);
530
+ has_r = ca_has_mask(r);
531
+ if ( ! has_l && ! has_r ) return;
532
+
533
+ if ( has_l ) lm = l->mask;
534
+ if ( has_r ) rm = r->mask;
535
+
536
+ bc->mask = (CArray *) carray_new(CA_BOOLEAN, bc->ndim, bc->dim, 0, NULL);
537
+ dst = (boolean8_t *) bc->mask->ptr;
538
+ n = bc->elements;
539
+
540
+ if ( has_l ) ca_attach(lm);
541
+ if ( has_r ) ca_attach(rm);
542
+
543
+ for ( i = 0; i < n; i++ ) {
544
+ boolean8_t a = has_l ? ((boolean8_t *) lm->ptr)[i] : 0;
545
+ boolean8_t b = 0;
546
+ if ( has_r ) {
547
+ ca_size_t ri = bc->right_is_scalar ? 0 : i;
548
+ b = ((boolean8_t *) rm->ptr)[ri];
549
+ }
550
+ dst[i] = (boolean8_t)( a | b );
551
+ }
552
+
553
+ if ( has_l ) ca_detach(lm);
554
+ if ( has_r ) ca_detach(rm);
555
+ }
556
+
557
+ ca_operation_function_t ca_bincmp_func = {
558
+ -1,
559
+ CA_VIEW_ARRAY,
560
+ free_ca_bincmp,
561
+ ca_bincmp_func_clone,
562
+ ca_bincmp_func_allocate,
563
+ ca_bincmp_func_attach,
564
+ ca_bincmp_func_sync,
565
+ ca_bincmp_func_detach,
566
+ ca_bincmp_func_fill_data,
567
+ ca_bincmp_func_create_mask,
568
+ ca_bincmp_func_xfer_index,
569
+ ca_bincmp_func_xfer_addrs,
570
+ NULL,
571
+ ca_bincmp_func_xfer_stride,
572
+ ca_bincmp_func_xfer_all,
573
+ };
574
+
575
+ /* ------------------------------------------------------------------- */
576
+ /* Public builder (= lib/carray/lazy.rb dispatch entry) */
577
+ /* ------------------------------------------------------------------- */
578
+
579
+ static VALUE
580
+ collapse_marker (VALUE cary)
581
+ {
582
+ CArray *ca;
583
+ if ( ! rb_obj_is_carray(cary) ) return cary;
584
+ TypedData_Get_Struct(cary, CArray, &carray_data_type, ca);
585
+ if ( ca->obj_type == CA_OBJ_LAZY_MARKER ) {
586
+ return rb_ca_parent(cary);
587
+ }
588
+ return cary;
589
+ }
590
+
591
+ static VALUE
592
+ rb_ca_bincmp_new (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
593
+ {
594
+ volatile VALUE obj;
595
+ CArray *l, *r;
596
+ CABinCmp *ca;
597
+ rb_check_carray_object(l_cary);
598
+ rb_check_carray_object(r_cary);
599
+ TypedData_Get_Struct(l_cary, CArray, &carray_data_type, l);
600
+ TypedData_Get_Struct(r_cary, CArray, &carray_data_type, r);
601
+ ca = ca_bincmp_new(l, r, op_id, eps);
602
+ obj = ca_wrap_struct(ca);
603
+ rb_ca_set_parent(obj, l_cary);
604
+ rb_ivar_set(obj, rb_intern("__bincmp_right__"), r_cary);
605
+ return obj;
606
+ }
607
+
608
+ VALUE
609
+ rb_ca_bincmp_build (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
610
+ {
611
+ CArray *l, *r;
612
+ int8_t l_in_dt, r_in_dt;
613
+ volatile VALUE l_resolved, r_resolved;
614
+
615
+ l_resolved = collapse_marker(l_cary);
616
+ r_resolved = collapse_marker(r_cary);
617
+
618
+ /* Scalar wrap — same policy as CABinOp. */
619
+ if ( ! rb_obj_is_carray(l_resolved) ) {
620
+ rb_check_carray_object(r_resolved);
621
+ TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
622
+ l_resolved = ca_lazy_wrap_scalar(l_resolved, r);
623
+ }
624
+ if ( ! rb_obj_is_carray(r_resolved) ) {
625
+ rb_check_carray_object(l_resolved);
626
+ TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
627
+ r_resolved = ca_lazy_wrap_scalar(r_resolved, l);
628
+ }
629
+
630
+ TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
631
+ TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
632
+
633
+ /* Cast both operands to the common data_type. */
634
+ ca_bincmp_kernel_input_data_types(op_id, l->data_type, r->data_type,
635
+ &l_in_dt, &r_in_dt);
636
+
637
+ if ( l_in_dt != l->data_type ) {
638
+ VALUE cast_op = INT2NUM(CA_MONOP_CAST_BASE + l_in_dt);
639
+ l_resolved = rb_funcall(rb_const_get(rb_cObject, rb_intern("CAMonOp")),
640
+ rb_intern("__build__"), 2,
641
+ l_resolved, cast_op);
642
+ TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
643
+ }
644
+ if ( r_in_dt != r->data_type ) {
645
+ VALUE cast_op = INT2NUM(CA_MONOP_CAST_BASE + r_in_dt);
646
+ r_resolved = rb_funcall(rb_const_get(rb_cObject, rb_intern("CAMonOp")),
647
+ rb_intern("__build__"), 2,
648
+ r_resolved, cast_op);
649
+ TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
650
+ }
651
+
652
+ /* Broadcast — same size-1-expansion logic as CABinOp. */
653
+ ca_broadcast_pair(&l_resolved, &r_resolved);
654
+ TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
655
+ TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
656
+
657
+ if ( l->elements != r->elements ) {
658
+ if ( r->elements == 1 && l->elements > 1 ) {
659
+ /* CScalar right: handled via right_is_scalar */
660
+ }
661
+ else if ( l->elements == 1 && r->elements > 1 ) {
662
+ /* Comparison ops commute under negation (LT/GT/LE/GE flip to
663
+ their counterpart, EQ/NE are commutative), but here we
664
+ broadcast the left scalar up instead of swapping, so op_id
665
+ does not need a flip table. */
666
+ ca_size_t count[CA_RANK_MAX];
667
+ int8_t k;
668
+ if ( r->ndim > l->ndim ) {
669
+ for ( k = 0; k < r->ndim - 1; k++ ) count[k] = 1;
670
+ count[r->ndim - 1] = 0;
671
+ l_resolved = rb_ca_repeat_new(l_resolved, r->ndim, count);
672
+ TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
673
+ }
674
+ l_resolved = ca_broadcast_view(l_resolved, r->ndim, r->dim);
675
+ TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
676
+ }
677
+ else {
678
+ /* Unreachable from Ruby; see the note in ca_obj_binop.c. */
679
+ rb_raise(rb_eArgError,
680
+ "CABinCmp: element count mismatch (%lld vs %lld)",
681
+ (long long) l->elements, (long long) r->elements);
682
+ }
683
+ }
684
+
685
+ return rb_ca_bincmp_new(l_resolved, r_resolved, op_id, eps);
686
+ }
687
+
688
+ static VALUE
689
+ rb_ca_bincmp_s_build (int argc, VALUE *argv, VALUE klass)
690
+ {
691
+ VALUE l_cary, r_cary, op_id_val, eps_val;
692
+ uint16_t op_id;
693
+ double eps = 0.0;
694
+ (void) klass;
695
+ rb_scan_args(argc, argv, "31", &l_cary, &r_cary, &op_id_val, &eps_val);
696
+ op_id = (uint16_t) NUM2UINT(op_id_val);
697
+ if ( argc >= 4 ) eps = NUM2DBL(eps_val);
698
+ return rb_ca_bincmp_build(l_cary, r_cary, op_id, eps);
699
+ }
700
+
701
+ static VALUE
702
+ rb_ca_bincmp_op_id (VALUE self)
703
+ {
704
+ CABinCmp *bc;
705
+ TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, bc);
706
+ return UINT2NUM(bc->op_id);
707
+ }
708
+
709
+ static VALUE
710
+ rb_ca_bincmp_right (VALUE self)
711
+ {
712
+ return rb_ivar_get(self, rb_intern("__bincmp_right__"));
713
+ }
714
+
715
+ static VALUE
716
+ rb_ca_bincmp_eps (VALUE self)
717
+ {
718
+ CABinCmp *bc;
719
+ TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, bc);
720
+ return rb_float_new(bc->eps);
721
+ }
722
+
723
+ static VALUE
724
+ rb_ca_bincmp_s_reset_scratch_counter (VALUE klass)
725
+ {
726
+ (void) klass;
727
+ ca_bincmp_scratch_acquire_count = 0;
728
+ return Qnil;
729
+ }
730
+
731
+ static VALUE
732
+ rb_ca_bincmp_s_scratch_count (VALUE klass)
733
+ {
734
+ (void) klass;
735
+ return SIZE2NUM(ca_bincmp_scratch_acquire_count);
736
+ }
737
+
738
+ static VALUE
739
+ rb_ca_bincmp_s_reset_materialise_counter (VALUE klass)
740
+ {
741
+ (void) klass;
742
+ ca_bincmp_materialise_call_count = 0;
743
+ return Qnil;
744
+ }
745
+
746
+ static VALUE
747
+ rb_ca_bincmp_s_materialise_count (VALUE klass)
748
+ {
749
+ (void) klass;
750
+ return SIZE2NUM(ca_bincmp_materialise_call_count);
751
+ }
752
+
753
+ static VALUE
754
+ rb_ca_bincmp_s_reset_leaf_inplace_counter (VALUE klass)
755
+ {
756
+ (void) klass;
757
+ ca_bincmp_leaf_inplace_count = 0;
758
+ return Qnil;
759
+ }
760
+
761
+ static VALUE
762
+ rb_ca_bincmp_s_leaf_inplace_count (VALUE klass)
763
+ {
764
+ (void) klass;
765
+ return SIZE2NUM(ca_bincmp_leaf_inplace_count);
766
+ }
767
+
768
+ static VALUE
769
+ rb_ca_bincmp_s_allocate (VALUE klass)
770
+ {
771
+ CABinCmp *ca;
772
+ return TypedData_Make_Struct(klass, CABinCmp, &cabincmp_data_type, ca);
773
+ }
774
+
775
+ static VALUE
776
+ rb_ca_bincmp_initialize_copy (VALUE self, VALUE other)
777
+ {
778
+ CABinCmp *ca, *cs;
779
+ TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, ca);
780
+ TypedData_Get_Struct(other, CABinCmp, &cabincmp_data_type, cs);
781
+ if ( ca_func[CA_OBJ_BINCMP].pool_init ) {
782
+ ca_array_pool_alloc(ca, CA_OBJ_BINCMP, cs->parent->ndim);
783
+ }
784
+ ca_bincmp_setup(ca, cs->parent, cs->right, cs->op_id, cs->eps);
785
+ return self;
786
+ }
787
+
788
+ void
789
+ Init_ca_obj_bincmp (void)
790
+ {
791
+ rb_cCABinCmp = rb_define_class("CABinCmp", rb_cCAView);
792
+
793
+ ca_bincmp_func.struct_size = sizeof(CABinCmp);
794
+ ca_bincmp_func.pool_bytes = ca_bincmp_pool_bytes;
795
+ ca_bincmp_func.pool_init = ca_bincmp_pool_init;
796
+
797
+ CA_OBJ_BINCMP = ca_install_obj_type(rb_cCABinCmp,
798
+ &cabincmp_data_type,
799
+ rb_cCArrayMask,
800
+ &carray_mask_data_type, &ca_bincmp_func, sizeof(ca_bincmp_func));
801
+ rb_define_const(rb_cObject, "CA_OBJ_BINCMP", INT2NUM(CA_OBJ_BINCMP));
802
+
803
+ /* op_id constants shared with lib/carray/lazy.rb. */
804
+ rb_define_const(rb_cCABinCmp, "OP_LT", INT2NUM(CA_BINCMP_LT));
805
+ rb_define_const(rb_cCABinCmp, "OP_GT", INT2NUM(CA_BINCMP_GT));
806
+ rb_define_const(rb_cCABinCmp, "OP_LE", INT2NUM(CA_BINCMP_LE));
807
+ rb_define_const(rb_cCABinCmp, "OP_GE", INT2NUM(CA_BINCMP_GE));
808
+ rb_define_const(rb_cCABinCmp, "OP_EQ", INT2NUM(CA_BINCMP_EQ));
809
+ rb_define_const(rb_cCABinCmp, "OP_NE", INT2NUM(CA_BINCMP_NE));
810
+ rb_define_const(rb_cCABinCmp, "OP_FEQ", INT2NUM(CA_BINCMP_FEQ));
811
+ rb_define_const(rb_cCABinCmp, "OP_IS_CLOSE", INT2NUM(CA_BINCMP_IS_CLOSE));
812
+ rb_define_const(rb_cCABinCmp, "OP_IS_EQUIV", INT2NUM(CA_BINCMP_IS_EQUIV));
813
+
814
+ rb_define_alloc_func(rb_cCABinCmp, rb_ca_bincmp_s_allocate);
815
+ rb_define_method(rb_cCABinCmp, "initialize_copy",
816
+ rb_ca_bincmp_initialize_copy, 1);
817
+
818
+ /* __build__(left, right, op_id [, eps]) */
819
+ rb_define_singleton_method(rb_cCABinCmp, "__build__",
820
+ rb_ca_bincmp_s_build, -1);
821
+
822
+ rb_define_method(rb_cCABinCmp, "__op_id__", rb_ca_bincmp_op_id, 0);
823
+ rb_define_method(rb_cCABinCmp, "__bincmp_right__",
824
+ rb_ca_bincmp_right, 0);
825
+ rb_define_method(rb_cCABinCmp, "__eps__", rb_ca_bincmp_eps, 0);
826
+
827
+ rb_define_singleton_method(rb_cCABinCmp, "__reset_scratch_counter__",
828
+ rb_ca_bincmp_s_reset_scratch_counter, 0);
829
+ rb_define_singleton_method(rb_cCABinCmp, "__scratch_count__",
830
+ rb_ca_bincmp_s_scratch_count, 0);
831
+ rb_define_singleton_method(rb_cCABinCmp, "__reset_materialise_counter__",
832
+ rb_ca_bincmp_s_reset_materialise_counter, 0);
833
+ rb_define_singleton_method(rb_cCABinCmp, "__materialise_count__",
834
+ rb_ca_bincmp_s_materialise_count, 0);
835
+ rb_define_singleton_method(rb_cCABinCmp, "__reset_leaf_inplace_counter__",
836
+ rb_ca_bincmp_s_reset_leaf_inplace_counter, 0);
837
+ rb_define_singleton_method(rb_cCABinCmp, "__leaf_inplace_count__",
838
+ rb_ca_bincmp_s_leaf_inplace_count, 0);
839
+ }