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,175 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Per-data_type kernel table for the CAMonOp `byte_swap` op
4
+ (`CA_MONOP_BYTE_SWAP`): reverses the byte order of each cell in place
5
+ after copying src to dst. byte_swap is data_type-preserving
6
+ (output.bytes == input.bytes).
7
+
8
+ Sibling of ca_monop_dispatch.c (looks up `ca_monop_byte_swap[in_dt]`)
9
+ and ca_obj_byte_swap.c (the eager CAByteSwap view + `ca_swap_bytes`
10
+ primitive that this file delegates to for the actual reversal).
11
+
12
+ Dispatch by data_type:
13
+ 1-byte cells (boolean / int8 / uint8) -> 1byte kernel (memcpy only)
14
+ fixed-width numeric (int16..float64) -> nbyte kernel (memcpy + reverse)
15
+ CA_CMPLX64 / CA_CMPLX128 -> cmplx kernel (half-independent)
16
+ CA_FIXLEN / CA_FLOAT128 / CA_CMPLX256 -> not_impl trampoline
17
+ CA_OBJECT -> not_impl trampoline
18
+
19
+ CMPLX cells are byte-swapped as two independent halves (real / imag),
20
+ not as one wide cell — this matches the eager `ca_byte_swap_buffer`
21
+ contract in ca_obj_byte_swap.c.
22
+
23
+ CA_FIXLEN is excluded here: bytes-per-cell is parent-specific and
24
+ data_class field-recursion requires a Ruby callback path; the CAByteSwap
25
+ view handles those. CA_OBJECT byte-swap on VALUE refs is meaningless.
26
+
27
+ ---------------------------------------------------------------------------- */
28
+
29
+ #include "carray.h"
30
+ #include "ca_monop_dispatch.h"
31
+ #include <string.h>
32
+
33
+ /* Reverses `bytes` bytes per cell across `elements` cells in place.
34
+ * Defined in ca_obj_byte_swap.c. */
35
+ extern void ca_swap_bytes (char *ptr, ca_size_t bytes, ca_size_t elements);
36
+
37
+ /* ------------------------------------------------------------------- */
38
+ /* per-data_type kernels */
39
+ /* ------------------------------------------------------------------- */
40
+
41
+ /* 1-byte cell: byte-swap is a no-op on a single byte. The kernel just
42
+ copies src to dst when they differ; included so boolean / int8 / uint8
43
+ share the dispatch shape with the wider kernels. */
44
+ #define DEFINE_BYTE_SWAP_1BYTE(name) \
45
+ static void \
46
+ name (ca_size_t n, boolean8_t *m, \
47
+ char *ptr1, ca_size_t i1, char *ptr2, ca_size_t i2) \
48
+ { \
49
+ ca_size_t k; \
50
+ if ( m ) { \
51
+ for (k = 0; k < n; k++) { \
52
+ if (!m[k]) { \
53
+ *(ptr2 + k*i2) = *(ptr1 + k*i1); \
54
+ } \
55
+ } \
56
+ } else { \
57
+ for (k = 0; k < n; k++) { \
58
+ *(ptr2 + k*i2) = *(ptr1 + k*i1); \
59
+ } \
60
+ } \
61
+ }
62
+
63
+ /* N-byte cell: copy src to dst (if different) then reverse the N
64
+ bytes within the cell. */
65
+ #define DEFINE_BYTE_SWAP_NBYTE(name, BYTES) \
66
+ static void \
67
+ name (ca_size_t n, boolean8_t *m, \
68
+ char *ptr1, ca_size_t i1, char *ptr2, ca_size_t i2) \
69
+ { \
70
+ ca_size_t k; \
71
+ if ( m ) { \
72
+ for (k = 0; k < n; k++) { \
73
+ if (!m[k]) { \
74
+ char *p1 = ptr1 + k*i1*(BYTES); \
75
+ char *p2 = ptr2 + k*i2*(BYTES); \
76
+ if (p2 != p1) memcpy(p2, p1, (BYTES)); \
77
+ ca_swap_bytes(p2, (BYTES), 1); \
78
+ } \
79
+ } \
80
+ } else { \
81
+ for (k = 0; k < n; k++) { \
82
+ char *p1 = ptr1 + k*i1*(BYTES); \
83
+ char *p2 = ptr2 + k*i2*(BYTES); \
84
+ if (p2 != p1) memcpy(p2, p1, (BYTES)); \
85
+ ca_swap_bytes(p2, (BYTES), 1); \
86
+ } \
87
+ } \
88
+ }
89
+
90
+ /* CMPLX cell (TOTAL bytes = 2 * HALF): swap the real half and the imag
91
+ half independently rather than reversing the whole TOTAL-byte cell. */
92
+ #define DEFINE_BYTE_SWAP_CMPLX(name, TOTAL, HALF) \
93
+ static void \
94
+ name (ca_size_t n, boolean8_t *m, \
95
+ char *ptr1, ca_size_t i1, char *ptr2, ca_size_t i2) \
96
+ { \
97
+ ca_size_t k; \
98
+ if ( m ) { \
99
+ for (k = 0; k < n; k++) { \
100
+ if (!m[k]) { \
101
+ char *p1 = ptr1 + k*i1*(TOTAL); \
102
+ char *p2 = ptr2 + k*i2*(TOTAL); \
103
+ if (p2 != p1) memcpy(p2, p1, (TOTAL)); \
104
+ ca_swap_bytes(p2, (HALF), 2); \
105
+ } \
106
+ } \
107
+ } else { \
108
+ for (k = 0; k < n; k++) { \
109
+ char *p1 = ptr1 + k*i1*(TOTAL); \
110
+ char *p2 = ptr2 + k*i2*(TOTAL); \
111
+ if (p2 != p1) memcpy(p2, p1, (TOTAL)); \
112
+ ca_swap_bytes(p2, (HALF), 2); \
113
+ } \
114
+ } \
115
+ }
116
+
117
+ DEFINE_BYTE_SWAP_1BYTE(ca_monop_byte_swap_boolean_t)
118
+ DEFINE_BYTE_SWAP_1BYTE(ca_monop_byte_swap_int8_t)
119
+ DEFINE_BYTE_SWAP_1BYTE(ca_monop_byte_swap_uint8_t)
120
+
121
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_int16_t, 2)
122
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_uint16_t, 2)
123
+
124
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_int32_t, 4)
125
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_uint32_t, 4)
126
+
127
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_int64_t, 8)
128
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_uint64_t, 8)
129
+
130
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_float32_t, 4)
131
+ DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_float64_t, 8)
132
+
133
+ DEFINE_BYTE_SWAP_CMPLX(ca_monop_byte_swap_cmplx64_t, 8, 4)
134
+ DEFINE_BYTE_SWAP_CMPLX(ca_monop_byte_swap_cmplx128_t, 16, 8)
135
+
136
+ /* Trampoline installed at unsupported data_type slots in the dispatch
137
+ table below. Raises rather than returning so the caller never sees
138
+ silent no-op behaviour on an out-of-scope data_type. */
139
+ NORETURN(static void ca_monop_byte_swap_not_impl (ca_size_t n, boolean8_t *m,
140
+ char *ptr1, ca_size_t i1,
141
+ char *ptr2, ca_size_t i2));
142
+ static void
143
+ ca_monop_byte_swap_not_impl (ca_size_t n, boolean8_t *m,
144
+ char *ptr1, ca_size_t i1,
145
+ char *ptr2, ca_size_t i2)
146
+ {
147
+ (void) n; (void) m; (void) ptr1; (void) i1; (void) ptr2; (void) i2;
148
+ rb_raise(rb_eRuntimeError,
149
+ "CAMonOp(byte_swap): not implemented for this data_type");
150
+ }
151
+
152
+ /* ------------------------------------------------------------------- */
153
+ /* dispatch table */
154
+ /* ------------------------------------------------------------------- */
155
+
156
+ ca_monop_func_t
157
+ ca_monop_byte_swap[CA_NTYPE] = {
158
+ /* CA_FIXLEN */ ca_monop_byte_swap_not_impl,
159
+ /* CA_BOOLEAN */ ca_monop_byte_swap_boolean_t,
160
+ /* CA_INT8 */ ca_monop_byte_swap_int8_t,
161
+ /* CA_UINT8 */ ca_monop_byte_swap_uint8_t,
162
+ /* CA_INT16 */ ca_monop_byte_swap_int16_t,
163
+ /* CA_UINT16 */ ca_monop_byte_swap_uint16_t,
164
+ /* CA_INT32 */ ca_monop_byte_swap_int32_t,
165
+ /* CA_UINT32 */ ca_monop_byte_swap_uint32_t,
166
+ /* CA_INT64 */ ca_monop_byte_swap_int64_t,
167
+ /* CA_UINT64 */ ca_monop_byte_swap_uint64_t,
168
+ /* CA_FLOAT32 */ ca_monop_byte_swap_float32_t,
169
+ /* CA_FLOAT64 */ ca_monop_byte_swap_float64_t,
170
+ /* CA_FLOAT128 */ ca_monop_byte_swap_not_impl, /* reserved hole */
171
+ /* CA_CMPLX64 */ ca_monop_byte_swap_cmplx64_t,
172
+ /* CA_CMPLX128 */ ca_monop_byte_swap_cmplx128_t,
173
+ /* CA_CMPLX256 */ ca_monop_byte_swap_not_impl, /* reserved hole */
174
+ /* CA_OBJECT */ ca_monop_byte_swap_not_impl,
175
+ };
@@ -0,0 +1,123 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ ca_op_cmplx64.h -- the cmplx64 products and quotients, computed in
4
+ double and rounded once
5
+
6
+ Used by:
7
+ - ext/carray_kernels_binop.c and ext/carray_kernels_monop.c
8
+ (generated from ext/mkkernel.rb): the `*`, `/`, `rcp` and
9
+ `rcp_mul` kernels for CA_CMPLX64.
10
+
11
+ Why these are not just `x * y` and `x / y`. Both the product and the
12
+ quotient of two complex numbers subtract two products of the parts, so
13
+ the result cancels whenever those two are close. Done at the operands'
14
+ own width there are no bits left underneath to absorb the cancellation.
15
+ Divide has a second cost: the compiler turns a `float _Complex` divide
16
+ into a call to `__divsc3`, which is Smith's algorithm (scale by the
17
+ larger component so the intermediate squares cannot overflow) plus the
18
+ C99 Annex G recovery for infinities -- branches and a call per cell.
19
+
20
+ For a cmplx64 the scaling is not needed at all: the operands are
21
+ floats, so a product of two parts reaches about 1.2e77 where a double
22
+ reaches 1.8e308. Computing the textbook formulas in double therefore
23
+ cannot overflow, and the double carries 29 extra mantissa bits, which
24
+ is what the cancellation needs. Measured against an exact rational
25
+ reference, the double route was correctly rounded on every sample
26
+ where the width-native route was off by up to 1806 ulp (divide) and
27
+ 1679 ulp (multiply).
28
+
29
+ The two are not the same trade. Divide gets faster as well, because
30
+ the call and the scaling both go away. Multiply gets slower, because
31
+ the compiler already inlines a naive float product and only calls
32
+ `__mulsc3` when a NaN appears -- so the wider arithmetic is pure cost
33
+ there, and is paid for the accuracy alone.
34
+
35
+ Annex G is preserved by falling back rather than by reimplementing it.
36
+ The fallback is chosen from the *result*, not from a classification of
37
+ the inputs: if the quick answer is not an ordinary number, hand the
38
+ pair to the compiler's helper and return whatever it says. Writing an
39
+ input classification here would mean transcribing the Annex G table,
40
+ and a transcription drifts from what the runtime actually does.
41
+
42
+ cmplx128 has no wider type to borrow (`long double` is a double on
43
+ Apple ARM64 and a slow 80-bit on x86-64), so it keeps `__mulsc3` /
44
+ `__divdc3`.
45
+
46
+ --------------------------------------------------------------------------- */
47
+
48
+ #ifndef CA_OP_CMPLX64_H
49
+ #define CA_OP_CMPLX64_H
50
+
51
+ #include "carray.h"
52
+ #include <math.h>
53
+
54
+ #ifdef HAVE_COMPLEX_H
55
+
56
+ /* CMPLXF is the float sibling of the CMPLX defined in carray.h, and is
57
+ here for the same reason: `re + I * im` evaluates `I * im` first, so an
58
+ im of +0.0 loses the sign of a -0.0 real part. CMPLXF is C11; provide
59
+ it when the toolchain predates that. */
60
+ #ifndef CMPLXF
61
+ # if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
62
+ # define CMPLXF(re, im) __builtin_complex((float)(re), (float)(im))
63
+ # else
64
+ # define CMPLXF(re, im) \
65
+ (((union { float _parts[2]; float complex _value; }) \
66
+ { { (float)(re), (float)(im) } })._value)
67
+ # endif
68
+ #endif
69
+
70
+ /* The real part is `xr*yr - xi*yi`, which cancels when the two products
71
+ are close; the double keeps the bits that cancellation eats. Only a
72
+ NaN can appear here that the naive form gets wrong, since a product of
73
+ two floats cannot overflow a double -- an infinite part in the answer
74
+ is the true answer. */
75
+ static inline cmplx64_t
76
+ op_cmul_cmplx64 (cmplx64_t x, cmplx64_t y)
77
+ {
78
+ double xr = crealf(x), xi = cimagf(x);
79
+ double yr = crealf(y), yi = cimagf(y);
80
+ float rr = (float) (xr * yr - xi * yi);
81
+ float ri = (float) (xr * yi + xi * yr);
82
+ if ( isnan(rr) || isnan(ri) ) {
83
+ return x * y; /* __mulsc3: an infinity met a zero (Annex G) */
84
+ }
85
+ return CMPLXF(rr, ri);
86
+ }
87
+
88
+ static inline cmplx64_t
89
+ op_cdiv_cmplx64 (cmplx64_t x, cmplx64_t y)
90
+ {
91
+ double yr = crealf(y), yi = cimagf(y);
92
+ double d = yr * yr + yi * yi;
93
+ if ( d > 0.0 && d < INFINITY ) {
94
+ double xr = crealf(x), xi = cimagf(x);
95
+ float rr = (float) ((xr * yr + xi * yi) / d);
96
+ float ri = (float) ((xi * yr - xr * yi) / d);
97
+ if ( isfinite(rr) && isfinite(ri) ) {
98
+ return CMPLXF(rr, ri);
99
+ }
100
+ }
101
+ return x / y; /* __divsc3: zero, infinite or NaN operands (Annex G) */
102
+ }
103
+
104
+ /* 1 / y. Same shape with the numerator's parts folded in, so that
105
+ `rcp` and `1 / z` keep giving the same answer. */
106
+ static inline cmplx64_t
107
+ op_crcp_cmplx64 (cmplx64_t y)
108
+ {
109
+ double yr = crealf(y), yi = cimagf(y);
110
+ double d = yr * yr + yi * yi;
111
+ if ( d > 0.0 && d < INFINITY ) {
112
+ float rr = (float) (yr / d);
113
+ float ri = (float) (-yi / d);
114
+ if ( isfinite(rr) && isfinite(ri) ) {
115
+ return CMPLXF(rr, ri);
116
+ }
117
+ }
118
+ return 1 / y;
119
+ }
120
+
121
+ #endif /* HAVE_COMPLEX_H */
122
+
123
+ #endif /* CA_OP_CMPLX64_H */
@@ -0,0 +1,316 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Float/Complex ** Integer integer-exponent fast path via
4
+ binary exponentiation (O(log p)).
5
+
6
+ Contents:
7
+ (1) LAZY kernel table `ca_binop_ipower[CA_NTYPE]` — CABinOp dispatch
8
+ entry taken when lazy `**` sees an Integer exponent on a
9
+ Float / Complex receiver. Called from ca_binop_dispatch.c.
10
+ (2) EAGER kernels + Ruby surface `pow` / `pow!` (alias `**`).
11
+ `rb_ca_pow{,_bang}` dispatch between ipower (Float/Complex **
12
+ Integer) and mkkernel-generated `rb_ca_power` (general pow).
13
+
14
+ Both paths share `op_powi_<type>` from ca_op_powi.h (= repeated
15
+ squaring, ~1-3 mul/cell for typical p).
16
+
17
+ ---------------------------------------------------------------------------- */
18
+
19
+ #include "carray.h"
20
+ #include "ca_binop_dispatch.h"
21
+ #include "ca_op_powi.h"
22
+
23
+ /* Defined in ext/carray_kernels.c (mkkernel-generated general pow /
24
+ cpow binop). Called by rb_ca_pow{,_bang} when the fast path does
25
+ not apply (rhs not Integer, or lhs not Float/Complex). */
26
+ extern VALUE rb_ca_power (VALUE self, VALUE other);
27
+ extern VALUE rb_ca_power_bang (VALUE self, VALUE other);
28
+
29
+ /* ========================================================================== */
30
+ /* (1) LAZY kernel table — CABinOp ipower dispatch */
31
+ /* ========================================================================== */
32
+
33
+ /* Kernel template: T = source/output data_type; right operand is
34
+ int64_t. Signature (n, m, ptr1, i1, ptr2, i2, ptr3, i3) mirrors
35
+ the mkkernel binop kernels so the CABinOp xfer_stride dispatcher
36
+ calls it uniformly.
37
+
38
+ Heterogeneous binop:
39
+ ptr1 = left (float32/float64/cmplx64/cmplx128, vector)
40
+ ptr2 = right (int64, scalar via i2=0)
41
+ ptr3 = dst (same data_type as left, vector)
42
+
43
+ Output data_type preserves the left data_type (= no cast-before
44
+ promotion). CAREFUL: cast-before / promo are overridden for
45
+ CA_BINOP_IPOWER in ca_binop_dispatch.c; changing this file's
46
+ dispatch table shape without matching that override leaks integer
47
+ promotion into the output.
48
+
49
+ Non-Float / non-Complex slots are NULL: lazy `**` routes only
50
+ Float / Complex parents through IPOWER; Integer parents stay on
51
+ the general CA_BINOP_POW path. */
52
+
53
+ #define DEFINE_LAZY_IPOWER_KERNEL(T) \
54
+ static void \
55
+ ca_binop_ipower_##T (ca_size_t n, boolean8_t *m, \
56
+ char *ptr1, ca_size_t i1, \
57
+ char *ptr2, ca_size_t i2, \
58
+ char *ptr3, ca_size_t i3) \
59
+ { \
60
+ T *q1 = (T *) ptr1, *q3 = (T *) ptr3; \
61
+ int64_t *q2 = (int64_t *) ptr2; \
62
+ T *p1, *p3; \
63
+ int64_t *p2; \
64
+ ca_size_t k; \
65
+ (void) i2; /* right is scalar broadcast (i2 == 0), q2 stays put */ \
66
+ if ( m ) { \
67
+ boolean8_t *pm; \
68
+ for (k = 0; k < n; k++) { \
69
+ pm = m + k; \
70
+ if ( ! *pm ) { \
71
+ p1 = q1 + k*i1; \
72
+ p2 = q2 + k*i2; \
73
+ p3 = q3 + k*i3; \
74
+ *p3 = op_powi_##T(*p1, *p2); \
75
+ } \
76
+ } \
77
+ } else { \
78
+ for (k = 0; k < n; k++) { \
79
+ p1 = q1 + k*i1; \
80
+ p2 = q2 + k*i2; \
81
+ p3 = q3 + k*i3; \
82
+ *p3 = op_powi_##T(*p1, *p2); \
83
+ } \
84
+ } \
85
+ }
86
+
87
+ DEFINE_LAZY_IPOWER_KERNEL(float32_t)
88
+ DEFINE_LAZY_IPOWER_KERNEL(float64_t)
89
+ DEFINE_LAZY_IPOWER_KERNEL(cmplx64_t)
90
+ DEFINE_LAZY_IPOWER_KERNEL(cmplx128_t)
91
+
92
+ #undef DEFINE_LAZY_IPOWER_KERNEL
93
+
94
+ /* Per-data_type dispatch table — NULL for slots not covered (= integer /
95
+ bool / object / fixlen / VL). Indexed by CA_FLOAT32 .. CA_CMPLX128. */
96
+ ca_binop_func_t ca_binop_ipower[CA_NTYPE] = {
97
+ [CA_FLOAT32] = ca_binop_ipower_float32_t,
98
+ [CA_FLOAT64] = ca_binop_ipower_float64_t,
99
+ [CA_CMPLX64] = ca_binop_ipower_cmplx64_t,
100
+ [CA_CMPLX128] = ca_binop_ipower_cmplx128_t,
101
+ };
102
+
103
+ /* ========================================================================== */
104
+ /* (2) EAGER kernels + Ruby surface */
105
+ /* ========================================================================== */
106
+
107
+ /* Per-data_type eager kernel: writes ipower(p1[k], ipow) → p2[k] for each
108
+ unmasked cell, using stride 1 on both input and output (= eager
109
+ driver materialises inputs to contig before calling). */
110
+
111
+ static void
112
+ ca_ipower_float32_t (ca_size_t n, boolean8_t *m,
113
+ char *ptr1, int32_t ipow, char *ptr2)
114
+ {
115
+ float32_t *p1 = (float32_t *) ptr1, *p2 = (float32_t *) ptr2;
116
+ if ( m ) {
117
+ while (n--) {
118
+ if ( ! *m++ ) { *p2 = op_powi_float32_t(*p1, ipow); }
119
+ p1++; p2++;
120
+ }
121
+ }
122
+ else
123
+ while (n--) { (*p2) = op_powi_float32_t(*p1, ipow); p1++; p2++; }
124
+ }
125
+
126
+ static void
127
+ ca_ipower_float64_t (ca_size_t n, boolean8_t *m,
128
+ char *ptr1, int32_t ipow, char *ptr2)
129
+ {
130
+ float64_t *p1 = (float64_t *) ptr1, *p2 = (float64_t *) ptr2;
131
+ if ( m ) {
132
+ while (n--) {
133
+ if ( ! *m++ ) { *p2 = op_powi_float64_t(*p1, ipow); }
134
+ p1++; p2++;
135
+ }
136
+ }
137
+ else
138
+ while (n--) { (*p2) = op_powi_float64_t(*p1, ipow); p1++; p2++; }
139
+ }
140
+
141
+ static void
142
+ ca_ipower_cmplx64_t (ca_size_t n, boolean8_t *m,
143
+ char *ptr1, int32_t ipow, char *ptr2)
144
+ {
145
+ cmplx64_t *p1 = (cmplx64_t *) ptr1, *p2 = (cmplx64_t *) ptr2;
146
+ if ( m ) {
147
+ while (n--) {
148
+ if ( ! *m++ ) { *p2 = op_powi_cmplx64_t(*p1, ipow); }
149
+ p1++; p2++;
150
+ }
151
+ }
152
+ else
153
+ while (n--) { (*p2) = op_powi_cmplx64_t(*p1, ipow); p1++; p2++; }
154
+ }
155
+
156
+ static void
157
+ ca_ipower_cmplx128_t (ca_size_t n, boolean8_t *m,
158
+ char *ptr1, int32_t ipow, char *ptr2)
159
+ {
160
+ cmplx128_t *p1 = (cmplx128_t *) ptr1, *p2 = (cmplx128_t *) ptr2;
161
+ if ( m ) {
162
+ while (n--) {
163
+ if ( ! *m++ ) { *p2 = op_powi_cmplx128_t(*p1, ipow); }
164
+ p1++; p2++;
165
+ }
166
+ }
167
+ else
168
+ while (n--) { (*p2) = op_powi_cmplx128_t(*p1, ipow); p1++; p2++; }
169
+ }
170
+
171
+ /* Eager Float/Complex ** Integer producing a fresh entity output.
172
+ * ca is input-only, co is the write target. Mirrors rb_ca_call_monop
173
+ * (see carray_math* / carray_kernels.c) so operand attach is elided:
174
+ * alias-cheap ca -> 1-shot ca_attach, use ca->ptr directly
175
+ * otherwise -> ALLOCV + ca_xfer_all(CA_XFER_GET) into a scratch
176
+ * buffer, no operand attach
177
+ * Mask goes through ca_mask_overlay_safe (also without an operand
178
+ * mask attach). Called by rb_ca_pow when the fast-path predicate
179
+ * matches. */
180
+ static VALUE
181
+ rb_ca_ipower (VALUE self, VALUE other)
182
+ {
183
+ volatile VALUE obj;
184
+ CArray *ca, *co;
185
+ int32_t ipow;
186
+ boolean8_t *m;
187
+
188
+ ipow = NUM2INT(other);
189
+
190
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
191
+
192
+ co = ca_has_mask(ca) ? ca_template_safe(ca) : ca_template(ca);
193
+ obj = ca_wrap_struct(co);
194
+
195
+ ca_mask_overlay_safe(co, 1, ca);
196
+ m = ( co->mask ) ? (boolean8_t *)co->mask->ptr : NULL;
197
+
198
+ if ( ca_attach_is_alias(ca) ) {
199
+ ca_attach(ca);
200
+ switch ( ca->data_type ) {
201
+ case CA_FLOAT32:
202
+ ca_ipower_float32_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
203
+ case CA_FLOAT64:
204
+ ca_ipower_float64_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
205
+ case CA_CMPLX64:
206
+ ca_ipower_cmplx64_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
207
+ case CA_CMPLX128:
208
+ ca_ipower_cmplx128_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
209
+ default:
210
+ rb_raise(rb_eCADataTypeError, "invalid data type for ipower");
211
+ }
212
+ ca_detach(ca);
213
+ }
214
+ else {
215
+ volatile VALUE h1 = Qnil;
216
+ char *p1;
217
+ (void) h1;
218
+ p1 = ALLOCV_N(char, h1, ca->elements * ca->bytes);
219
+ ca_xfer_all(ca, p1, CA_XFER_GET);
220
+ switch ( ca->data_type ) {
221
+ case CA_FLOAT32:
222
+ ca_ipower_float32_t(ca->elements, m, p1, ipow, co->ptr); break;
223
+ case CA_FLOAT64:
224
+ ca_ipower_float64_t(ca->elements, m, p1, ipow, co->ptr); break;
225
+ case CA_CMPLX64:
226
+ ca_ipower_cmplx64_t(ca->elements, m, p1, ipow, co->ptr); break;
227
+ case CA_CMPLX128:
228
+ ca_ipower_cmplx128_t(ca->elements, m, p1, ipow, co->ptr); break;
229
+ default:
230
+ ALLOCV_END(h1);
231
+ rb_raise(rb_eCADataTypeError, "invalid data type for ipower");
232
+ }
233
+ ALLOCV_END(h1);
234
+ }
235
+
236
+ return obj;
237
+ }
238
+
239
+ static VALUE
240
+ rb_ca_ipower_bang (VALUE self, VALUE other)
241
+ {
242
+ CArray *ca;
243
+ int32_t ipow;
244
+ boolean8_t *m;
245
+
246
+ ipow = NUM2INT(other);
247
+
248
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
249
+
250
+ ca_attach(ca);
251
+
252
+ m = ( ca->mask ) ? (boolean8_t *)ca->mask->ptr : NULL;
253
+
254
+ switch ( ca->data_type ) {
255
+ case CA_FLOAT32:
256
+ ca_ipower_float32_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
257
+ case CA_FLOAT64:
258
+ ca_ipower_float64_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
259
+ case CA_CMPLX64:
260
+ ca_ipower_cmplx64_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
261
+ case CA_CMPLX128:
262
+ ca_ipower_cmplx128_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
263
+ default:
264
+ rb_raise(rb_eRuntimeError, "invalid data type for ipower");
265
+ }
266
+
267
+ ca_sync(ca);
268
+ ca_detach(ca);
269
+
270
+ return self;
271
+ }
272
+
273
+ /* CArray#pow(other) (alias `**`) — Float/Complex ** Integer takes the
274
+ * ipower fast path in this file; everything else falls through to the
275
+ * mkkernel-generated general pow/cpow (rb_ca_power in
276
+ * ext/carray_kernels.c). Non-bang variant preserves UnboundRepeat
277
+ * wrapping on the result. */
278
+ static VALUE rb_ca_pow (VALUE self, VALUE other)
279
+ {
280
+ volatile VALUE obj;
281
+ CArray *ca;
282
+
283
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
284
+ if ( ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) &&
285
+ rb_obj_is_kind_of(other, rb_cInteger) ) {
286
+ return rb_ca_ipower(self, other);
287
+ }
288
+ else {
289
+ obj = rb_ca_power(self, other);
290
+ return obj;
291
+ }
292
+ }
293
+
294
+ /* CArray#pow!(other) — in-place variant of #pow. Dispatch mirrors
295
+ * rb_ca_pow (fast path for Float/Complex ** Integer, otherwise
296
+ * general rb_ca_power_bang). */
297
+ static VALUE rb_ca_pow_bang (VALUE self, VALUE other)
298
+ {
299
+ CArray *ca;
300
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
301
+ if ( ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) &&
302
+ rb_obj_is_kind_of(other, rb_cInteger) ) {
303
+ return rb_ca_ipower_bang(self, other);
304
+ }
305
+ else {
306
+ return rb_ca_power_bang(self, other);
307
+ }
308
+ }
309
+
310
+ void
311
+ Init_ca_op_ipower (void)
312
+ {
313
+ rb_define_method(rb_cCArray, "pow", rb_ca_pow, 1);
314
+ rb_define_method(rb_cCArray, "pow!", rb_ca_pow_bang, 1);
315
+ rb_define_alias(rb_cCArray, "**", "pow");
316
+ }
data/ext/ca_op_powi.h ADDED
@@ -0,0 +1,88 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ ca_op_powi.h -- shared `op_powi_<type>` integer-power helpers
4
+
5
+ Used by:
6
+ - ext/carray_kernels.c (generated from ext/mkkernel.rb)
7
+ the `power` binop kernel's integer variants call
8
+ `op_powi_<type>` to compute integer exponentiation by binary
9
+ exponentiation (O(log p) vs pow's general path).
10
+ - ext/carray_math.c (hand-written, P.5b.5)
11
+ the `ipower` family (rb_ca_ipower, rb_ca_ipower_bang) uses
12
+ `op_powi_<type>` for the Float**Integer / Complex**Integer
13
+ fast path when invoked via CArray#pow with an Integer rhs.
14
+
15
+ Both files include this header independently; each TU gets its own
16
+ `static inline` copy with no linker conflicts.
17
+
18
+ --------------------------------------------------------------------------- */
19
+
20
+ #ifndef CA_OP_POWI_H
21
+ #define CA_OP_POWI_H
22
+
23
+ #include "carray.h"
24
+ #include <stdint.h>
25
+
26
+ #define op_powi(type) \
27
+ static inline type \
28
+ op_powi_## type (type x, int64_t p) \
29
+ { \
30
+ type r=1; \
31
+ \
32
+ switch(p) { \
33
+ case 2: return x*x; \
34
+ case 3: return x*x*x; \
35
+ case 0: return 1; \
36
+ case 1: return x; \
37
+ } \
38
+ if (p<0) { \
39
+ type den = op_powi_## type(x, -p); \
40
+ if (den==0) ca_zerodiv(); \
41
+ return 1/den; \
42
+ }\
43
+ while (p) { \
44
+ if ( (p%2) == 1 ) r *= x; \
45
+ x *= x; \
46
+ p /= 2; \
47
+ } \
48
+ return r; \
49
+ }
50
+
51
+ #define op_powi_fc(type) \
52
+ static inline type \
53
+ op_powi_## type (type x, int64_t p) \
54
+ { \
55
+ type r=1; \
56
+ \
57
+ switch(p) { \
58
+ case 2: return x*x; \
59
+ case 3: return x*x*x; \
60
+ case 0: return 1; \
61
+ case 1: return x; \
62
+ } \
63
+ if (p<0) { \
64
+ type den = op_powi_## type(x, -p); \
65
+ return 1/den; \
66
+ }\
67
+ while (p) { \
68
+ if ( (p%2) == 1 ) r *= x; \
69
+ x *= x; \
70
+ p /= 2; \
71
+ } \
72
+ return r; \
73
+ }
74
+
75
+ op_powi(int8_t)
76
+ op_powi(uint8_t)
77
+ op_powi(int16_t)
78
+ op_powi(uint16_t)
79
+ op_powi(int32_t)
80
+ op_powi(uint32_t)
81
+ op_powi(int64_t)
82
+ op_powi(uint64_t)
83
+ op_powi_fc(float32_t)
84
+ op_powi_fc(float64_t)
85
+ op_powi_fc(cmplx64_t)
86
+ op_powi_fc(cmplx128_t)
87
+
88
+ #endif /* CA_OP_POWI_H */