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,357 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ scatter_*! family (per-position mutation primitives): scatter_add /
4
+ sub / mul / min / max in-place, docs in yard-stubs/carray_scatter.rb.
5
+
6
+ Shared contract (load-bearing across all five methods):
7
+ addrs CArray or Ruby Array; coerced to ca_size_t, OOB raises IndexError
8
+ vals CArray of length(addrs) OR Numeric scalar (broadcast)
9
+ duplicates unbuffered (sequential) — collisions accumulate
10
+ mask pair skipped when any of addrs[i] / vals[i] / self[addrs[i]] is masked
11
+ cast vals silently cast to self.data_type
12
+ data type arithmetic (add / sub / mul / min / max): numeric only
13
+ (boolean / object / fixlen → CADataTypeError; the bang
14
+ cannot widen self, same rationale as fma! / fms!)
15
+ replace: numeric or boolean (assignment, no widening)
16
+
17
+ --------------------------------------------------------------------------- */
18
+
19
+ #include "carray.h"
20
+
21
+ /* ---------- common kernel macros ----------
22
+
23
+ Scalar broadcast path: `vs` already cast to T at entry.
24
+ Vector path: `r[i]` already in self.data_type (silent cast via wrap).
25
+
26
+ APPLY(qp, v) := one of:
27
+ OP_ADD *(qp) += (v)
28
+ OP_SUB *(qp) -= (v)
29
+ OP_MIN_FLT if ((v) < *(qp) || *(qp) != *(qp)) *(qp) = (v) (fmin policy)
30
+ OP_MAX_FLT if ((v) > *(qp) || *(qp) != *(qp)) *(qp) = (v)
31
+ OP_MIN_INT if ((v) < *(qp)) *(qp) = (v)
32
+ OP_MAX_INT if ((v) > *(qp)) *(qp) = (v)
33
+ */
34
+
35
+ #define OP_ADD(qp, v) (*(qp) += (v))
36
+ #define OP_SUB(qp, v) (*(qp) -= (v))
37
+ #define OP_MUL(qp, v) (*(qp) *= (v))
38
+ #define OP_REPLACE(qp, v) (*(qp) = (v))
39
+ #define OP_MIN_FLT(qp, v) do { if ((v) < *(qp) || *(qp) != *(qp)) *(qp) = (v); } while (0)
40
+ #define OP_MAX_FLT(qp, v) do { if ((v) > *(qp) || *(qp) != *(qp)) *(qp) = (v); } while (0)
41
+ #define OP_MIN_INT(qp, v) do { if ((v) < *(qp)) *(qp) = (v); } while (0)
42
+ #define OP_MAX_INT(qp, v) do { if ((v) > *(qp)) *(qp) = (v); } while (0)
43
+
44
+ #define LOOP_SCALAR(T, APPLY) do { \
45
+ T *q = (T *) ca->ptr; \
46
+ T vs = (T) (v_is_float ? (double)vd : (double)vl); \
47
+ if ( mself ) { \
48
+ for (i = 0; i < n; i++) { \
49
+ if ( maddrs && maddrs[i] ) continue; \
50
+ addr = p[i]; \
51
+ CA_CHECK_INDEX(addr, elements); \
52
+ if ( mself[addr] ) continue; \
53
+ APPLY(q + addr, vs); \
54
+ } \
55
+ } \
56
+ else { \
57
+ for (i = 0; i < n; i++) { \
58
+ if ( maddrs && maddrs[i] ) continue; \
59
+ addr = p[i]; \
60
+ CA_CHECK_INDEX(addr, elements); \
61
+ APPLY(q + addr, vs); \
62
+ } \
63
+ } \
64
+ } while (0)
65
+
66
+ #define LOOP_VEC(T, APPLY) do { \
67
+ T *q = (T *) ca->ptr; \
68
+ T *r = (T *) cv->ptr; \
69
+ if ( mself ) { \
70
+ for (i = 0; i < n; i++) { \
71
+ if ( maddrs && maddrs[i] ) continue; \
72
+ if ( mvals && mvals[i] ) continue; \
73
+ addr = p[i]; \
74
+ CA_CHECK_INDEX(addr, elements); \
75
+ if ( mself[addr] ) continue; \
76
+ APPLY(q + addr, r[i]); \
77
+ } \
78
+ } \
79
+ else { \
80
+ for (i = 0; i < n; i++) { \
81
+ if ( maddrs && maddrs[i] ) continue; \
82
+ if ( mvals && mvals[i] ) continue; \
83
+ addr = p[i]; \
84
+ CA_CHECK_INDEX(addr, elements); \
85
+ APPLY(q + addr, r[i]); \
86
+ } \
87
+ } \
88
+ } while (0)
89
+
90
+ /* REPLACE variant: last-write semantics. Differs from the accumulate
91
+ family on mask handling:
92
+ - target's prior mask is NOT a skip signal; the write overwrites
93
+ both value and mask (indexer contract, `self[addrs] = vals`).
94
+ - masked vals[i] flips target to masked (writes UNDEF); valid
95
+ vals[i] writes value and clears the target's mask bit.
96
+ Scalar vals is always valid (Fixnum / Float), so scalar path just
97
+ writes and clears target mask. */
98
+
99
+ #define LOOP_SCALAR_REPLACE(T) do { \
100
+ T *q = (T *) ca->ptr; \
101
+ T vs = (T) (v_is_float ? (double)vd : (double)vl); \
102
+ for (i = 0; i < n; i++) { \
103
+ if ( maddrs && maddrs[i] ) continue; \
104
+ addr = p[i]; \
105
+ CA_CHECK_INDEX(addr, elements); \
106
+ q[addr] = vs; \
107
+ if ( mself ) mself[addr] = 0; \
108
+ } \
109
+ } while (0)
110
+
111
+ #define LOOP_VEC_REPLACE(T) do { \
112
+ T *q = (T *) ca->ptr; \
113
+ T *r = (T *) cv->ptr; \
114
+ for (i = 0; i < n; i++) { \
115
+ if ( maddrs && maddrs[i] ) continue; \
116
+ addr = p[i]; \
117
+ CA_CHECK_INDEX(addr, elements); \
118
+ if ( mvals && mvals[i] ) { \
119
+ if ( mself ) mself[addr] = 1; \
120
+ } else { \
121
+ q[addr] = r[i]; \
122
+ if ( mself ) mself[addr] = 0; \
123
+ } \
124
+ } \
125
+ } while (0)
126
+
127
+ #define DISPATCH_NUMERIC_REPLACE() do { \
128
+ switch ( ca->data_type ) { \
129
+ case CA_BOOLEAN: if (vals_scalar) LOOP_SCALAR_REPLACE(uint8_t); else LOOP_VEC_REPLACE(uint8_t); break; \
130
+ case CA_FLOAT64: if (vals_scalar) LOOP_SCALAR_REPLACE(double); else LOOP_VEC_REPLACE(double); break; \
131
+ case CA_FLOAT32: if (vals_scalar) LOOP_SCALAR_REPLACE(float); else LOOP_VEC_REPLACE(float); break; \
132
+ case CA_INT64: if (vals_scalar) LOOP_SCALAR_REPLACE(int64_t); else LOOP_VEC_REPLACE(int64_t); break; \
133
+ case CA_INT32: if (vals_scalar) LOOP_SCALAR_REPLACE(int32_t); else LOOP_VEC_REPLACE(int32_t); break; \
134
+ case CA_INT16: if (vals_scalar) LOOP_SCALAR_REPLACE(int16_t); else LOOP_VEC_REPLACE(int16_t); break; \
135
+ case CA_INT8: if (vals_scalar) LOOP_SCALAR_REPLACE(int8_t); else LOOP_VEC_REPLACE(int8_t); break; \
136
+ case CA_UINT64: if (vals_scalar) LOOP_SCALAR_REPLACE(uint64_t); else LOOP_VEC_REPLACE(uint64_t); break; \
137
+ case CA_UINT32: if (vals_scalar) LOOP_SCALAR_REPLACE(uint32_t); else LOOP_VEC_REPLACE(uint32_t); break; \
138
+ case CA_UINT16: if (vals_scalar) LOOP_SCALAR_REPLACE(uint16_t); else LOOP_VEC_REPLACE(uint16_t); break; \
139
+ case CA_UINT8: if (vals_scalar) LOOP_SCALAR_REPLACE(uint8_t); else LOOP_VEC_REPLACE(uint8_t); break; \
140
+ default: \
141
+ rb_bug("carray_scatter: unsupported data_type %d after numeric check", ca->data_type); \
142
+ } \
143
+ } while (0)
144
+
145
+ #define DISPATCH_NUMERIC(APPLY_INT, APPLY_FLT) do { \
146
+ switch ( ca->data_type ) { \
147
+ case CA_FLOAT64: if (vals_scalar) LOOP_SCALAR(double, APPLY_FLT); else LOOP_VEC(double, APPLY_FLT); break; \
148
+ case CA_FLOAT32: if (vals_scalar) LOOP_SCALAR(float, APPLY_FLT); else LOOP_VEC(float, APPLY_FLT); break; \
149
+ case CA_INT64: if (vals_scalar) LOOP_SCALAR(int64_t, APPLY_INT); else LOOP_VEC(int64_t, APPLY_INT); break; \
150
+ case CA_INT32: if (vals_scalar) LOOP_SCALAR(int32_t, APPLY_INT); else LOOP_VEC(int32_t, APPLY_INT); break; \
151
+ case CA_INT16: if (vals_scalar) LOOP_SCALAR(int16_t, APPLY_INT); else LOOP_VEC(int16_t, APPLY_INT); break; \
152
+ case CA_INT8: if (vals_scalar) LOOP_SCALAR(int8_t, APPLY_INT); else LOOP_VEC(int8_t, APPLY_INT); break; \
153
+ case CA_UINT64: if (vals_scalar) LOOP_SCALAR(uint64_t, APPLY_INT); else LOOP_VEC(uint64_t, APPLY_INT); break; \
154
+ case CA_UINT32: if (vals_scalar) LOOP_SCALAR(uint32_t, APPLY_INT); else LOOP_VEC(uint32_t, APPLY_INT); break; \
155
+ case CA_UINT16: if (vals_scalar) LOOP_SCALAR(uint16_t, APPLY_INT); else LOOP_VEC(uint16_t, APPLY_INT); break; \
156
+ case CA_UINT8: if (vals_scalar) LOOP_SCALAR(uint8_t, APPLY_INT); else LOOP_VEC(uint8_t, APPLY_INT); break; \
157
+ default: \
158
+ /* numeric check passed before dispatch; complex types fall through to bug */ \
159
+ rb_bug("carray_scatter: unsupported data_type %d after numeric check", ca->data_type); \
160
+ } \
161
+ } while (0)
162
+
163
+ /* Setup boilerplate: parse args, wrap addrs/vals, attach.
164
+
165
+ Outputs into caller's locals:
166
+ ca, ci, cv (CArray*), n, elements (ca_size_t),
167
+ p, maddrs, mvals, mself (pointers),
168
+ vals_scalar (int), v_is_float (int), vd (double), vl (long).
169
+
170
+ Caller must `ca_sync(ca); ca_detach_n(...);` after kernel.
171
+ */
172
+ /* Body shared by arithmetic and replace setups. Caller precondition:
173
+ the data_type gate has already run (arithmetic = numeric only, replace
174
+ = numeric or boolean). For the replace variant, `true` / `false`
175
+ scalars are accepted as vals (bridged as vl = 1 / 0). */
176
+ #define AT_SETUP_BODY(name, allow_bool_scalar) \
177
+ raddrs = rb_ca_wrap_readonly(raddrs, INT2NUM(CA_SIZE)); \
178
+ TypedData_Get_Struct(raddrs, CArray, &carray_data_type, ci); \
179
+ n = ci->elements; \
180
+ if ( n == 0 ) return self; \
181
+ vals_scalar = (RB_FLOAT_TYPE_P(rvals) || FIXNUM_P(rvals) \
182
+ || ((allow_bool_scalar) && (rvals == Qtrue || rvals == Qfalse))); \
183
+ if ( vals_scalar ) { \
184
+ if ( RB_FLOAT_TYPE_P(rvals) ) { vd = RFLOAT_VALUE(rvals); v_is_float = 1; } \
185
+ else if ( FIXNUM_P(rvals) ) { vl = FIX2LONG(rvals); v_is_float = 0; } \
186
+ else { vl = (rvals == Qtrue) ? 1 : 0; v_is_float = 0; } \
187
+ } \
188
+ else { \
189
+ rvals = rb_ca_wrap_readonly(rvals, INT2NUM(ca->data_type)); \
190
+ TypedData_Get_Struct(rvals, CArray, &carray_data_type, cv); \
191
+ if ( cv->elements != n ) { \
192
+ rb_raise(rb_eArgError, \
193
+ name ": vals length (%lld) doesn't match addrs length (%lld)", \
194
+ (long long)cv->elements, (long long)n); \
195
+ } \
196
+ } \
197
+ if ( vals_scalar ) ca_attach_n(2, ca, ci); \
198
+ else ca_attach_n(3, ca, ci, cv); \
199
+ p = (ca_size_t *) ci->ptr; \
200
+ maddrs = ci->mask ? (boolean8_t *) ci->mask->ptr : NULL; \
201
+ mvals = (cv && cv->mask) ? (boolean8_t *) cv->mask->ptr : NULL; \
202
+ mself = ca->mask ? (boolean8_t *) ca->mask->ptr : NULL; \
203
+ elements = ca->elements;
204
+
205
+ #define AT_SETUP_OR_RETURN(name) \
206
+ CArray *ca, *ci, *cv = NULL; \
207
+ ca_size_t i, n, addr, elements; \
208
+ ca_size_t *p; \
209
+ boolean8_t *maddrs, *mvals = NULL, *mself; \
210
+ int vals_scalar, v_is_float = 0; \
211
+ double vd = 0.0; long vl = 0; \
212
+ rb_ca_modify(self); \
213
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca); \
214
+ if ( ! ca_is_numeric_type(ca) ) { \
215
+ rb_raise(rb_eCADataTypeError, name " requires a numeric array"); \
216
+ } \
217
+ AT_SETUP_BODY(name, 0)
218
+
219
+ /* replace variant: accepts boolean self (assignment, no widening) and
220
+ Ruby true / false as scalar vals. */
221
+ #define AT_SETUP_OR_RETURN_REPLACE(name) \
222
+ CArray *ca, *ci, *cv = NULL; \
223
+ ca_size_t i, n, addr, elements; \
224
+ ca_size_t *p; \
225
+ boolean8_t *maddrs, *mvals = NULL, *mself; \
226
+ int vals_scalar, v_is_float = 0; \
227
+ double vd = 0.0; long vl = 0; \
228
+ rb_ca_modify(self); \
229
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca); \
230
+ if ( ! ca_is_numeric_type(ca) && ca->data_type != CA_BOOLEAN ) { \
231
+ rb_raise(rb_eCADataTypeError, \
232
+ name " requires a numeric or boolean array"); \
233
+ } \
234
+ AT_SETUP_BODY(name, 1)
235
+
236
+ #define AT_TEARDOWN() do { \
237
+ ca_sync(ca); \
238
+ if ( vals_scalar ) ca_detach_n(2, ca, ci); \
239
+ else ca_detach_n(3, ca, ci, cv); \
240
+ } while (0)
241
+
242
+ /* --------------------------------------------------------------- */
243
+
244
+ /* CArray#scatter_add!(addrs, vals) — for each i, self[addrs[i]] +=
245
+ * vals[i] (or += vals when scalar). Duplicate addrs accumulate
246
+ * (unbuffered), unlike self[addrs] += vals which is last-wins. */
247
+ static VALUE
248
+ rb_ca_scatter_add_bang (VALUE self, VALUE raddrs, VALUE rvals)
249
+ {
250
+ AT_SETUP_OR_RETURN("scatter_add!");
251
+ DISPATCH_NUMERIC(OP_ADD, OP_ADD);
252
+ AT_TEARDOWN();
253
+ return self;
254
+ }
255
+
256
+ /* --------------------------------------------------------------- */
257
+
258
+ /* CArray#scatter_sub!(addrs, vals) — for each i, self[addrs[i]] -=
259
+ * vals[i]. Same mask/cast/bounds policy as scatter_add!. */
260
+ static VALUE
261
+ rb_ca_scatter_sub_bang (VALUE self, VALUE raddrs, VALUE rvals)
262
+ {
263
+ AT_SETUP_OR_RETURN("scatter_sub!");
264
+ DISPATCH_NUMERIC(OP_SUB, OP_SUB);
265
+ AT_TEARDOWN();
266
+ return self;
267
+ }
268
+
269
+ /* --------------------------------------------------------------- */
270
+
271
+ /* CArray#scatter_mul!(addrs, vals) — for each i, self[addrs[i]] *=
272
+ * vals[i]. NaN/inf follow standard C arithmetic (no fmin-style
273
+ * missing-value rule); integer overflow wraps. Otherwise identical
274
+ * to scatter_add! (mask / cast / bounds). */
275
+ static VALUE
276
+ rb_ca_scatter_mul_bang (VALUE self, VALUE raddrs, VALUE rvals)
277
+ {
278
+ AT_SETUP_OR_RETURN("scatter_mul!");
279
+ DISPATCH_NUMERIC(OP_MUL, OP_MUL);
280
+ AT_TEARDOWN();
281
+ return self;
282
+ }
283
+
284
+ /* --------------------------------------------------------------- */
285
+
286
+ /* CArray#scatter_min!(addrs, vals) — for each i, self[addrs[i]] =
287
+ * min(self[addrs[i]], vals[i]). Float types follow the fmin rule
288
+ * (NaN is treated as missing). Same mask/cast/bounds policy as
289
+ * scatter_add!. */
290
+ static VALUE
291
+ rb_ca_scatter_min_bang (VALUE self, VALUE raddrs, VALUE rvals)
292
+ {
293
+ AT_SETUP_OR_RETURN("scatter_min!");
294
+ DISPATCH_NUMERIC(OP_MIN_INT, OP_MIN_FLT);
295
+ AT_TEARDOWN();
296
+ return self;
297
+ }
298
+
299
+ /* --------------------------------------------------------------- */
300
+
301
+ /* CArray#scatter_max!(addrs, vals) — for each i, self[addrs[i]] =
302
+ * max(self[addrs[i]], vals[i]). Float types follow the fmax rule.
303
+ * Otherwise identical to scatter_add!. */
304
+ static VALUE
305
+ rb_ca_scatter_max_bang (VALUE self, VALUE raddrs, VALUE rvals)
306
+ {
307
+ AT_SETUP_OR_RETURN("scatter_max!");
308
+ DISPATCH_NUMERIC(OP_MAX_INT, OP_MAX_FLT);
309
+ AT_TEARDOWN();
310
+ return self;
311
+ }
312
+
313
+ /* --------------------------------------------------------------- */
314
+
315
+ /* CArray#scatter_replace!(addrs, vals) — for each i, self[addrs[i]] =
316
+ * vals[i] (or = vals when scalar). Semantically equivalent to
317
+ * self[addrs] = vals (last-write-wins on duplicate addrs) but bypasses
318
+ * the CAGrid view chain (snapshot copy of addrs + view alloc + store_all
319
+ * dispatch). Mask policy follows the indexer contract: target's prior
320
+ * mask is overwritten (masked vals[i] flips target to masked, valid
321
+ * vals[i] clears target's mask). */
322
+ static VALUE
323
+ rb_ca_scatter_replace_bang (VALUE self, VALUE raddrs, VALUE rvals)
324
+ {
325
+ /* Pre-scan: if vals is a masked CArray and self isn't yet masked,
326
+ promote self so the kernel can flip target cells to masked (indexer
327
+ `self[addrs] = vals` establishes self.mask lazily the same way). */
328
+ if ( ! (RB_FLOAT_TYPE_P(rvals) || FIXNUM_P(rvals))
329
+ && rb_obj_is_carray(rvals) ) {
330
+ CArray *cv_pre;
331
+ TypedData_Get_Struct(rvals, CArray, &carray_data_type, cv_pre);
332
+ if ( ca_has_mask(cv_pre) ) {
333
+ CArray *ca_pre;
334
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca_pre);
335
+ if ( ! ca_has_mask(ca_pre) ) {
336
+ ca_create_mask(ca_pre);
337
+ }
338
+ }
339
+ }
340
+ AT_SETUP_OR_RETURN_REPLACE("scatter_replace!");
341
+ DISPATCH_NUMERIC_REPLACE();
342
+ AT_TEARDOWN();
343
+ return self;
344
+ }
345
+
346
+ /* --------------------------------------------------------------- */
347
+
348
+ void
349
+ Init_carray_scatter (void)
350
+ {
351
+ rb_define_method(rb_cCArray, "scatter_add!", rb_ca_scatter_add_bang, 2);
352
+ rb_define_method(rb_cCArray, "scatter_sub!", rb_ca_scatter_sub_bang, 2);
353
+ rb_define_method(rb_cCArray, "scatter_mul!", rb_ca_scatter_mul_bang, 2);
354
+ rb_define_method(rb_cCArray, "scatter_min!", rb_ca_scatter_min_bang, 2);
355
+ rb_define_method(rb_cCArray, "scatter_max!", rb_ca_scatter_max_bang, 2);
356
+ rb_define_method(rb_cCArray, "scatter_replace!", rb_ca_scatter_replace_bang, 2);
357
+ }