carray 2.0.0 → 3.0.0

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 (339) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -25
  3. data/CHANGELOG.md +16 -0
  4. data/LICENSE +1 -1
  5. data/NEWS.md +3 -0
  6. data/README.md +128 -44
  7. data/carray.gemspec +22 -24
  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 +1208 -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 +125 -0
  15. data/ext/ca_binop_dispatch.h +159 -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 +241 -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 +4321 -0
  26. data/ext/ca_kernel_iterator.h +2603 -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 +809 -0
  33. data/ext/ca_obj_binop.c +892 -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 +965 -0
  39. data/ext/ca_obj_face.c +670 -0
  40. data/ext/ca_obj_face.h +247 -0
  41. data/ext/ca_obj_fake.c +228 -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 +306 -0
  45. data/ext/ca_obj_grid.c +858 -440
  46. data/ext/ca_obj_meld.c +1034 -0
  47. data/ext/ca_obj_moncmp.c +569 -0
  48. data/ext/ca_obj_monop.c +1111 -0
  49. data/ext/ca_obj_object.c +774 -298
  50. data/ext/ca_obj_record.c +468 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +569 -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 +616 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1296 -0
  58. data/ext/ca_obj_shift.c +230 -792
  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 +2501 -0
  62. data/ext/ca_obj_string.c +268 -0
  63. data/ext/ca_obj_tile.c +614 -0
  64. data/ext/ca_obj_time.c +546 -0
  65. data/ext/ca_obj_timedelta.c +435 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +746 -0
  68. data/ext/ca_obj_unbound_repeat.c +208 -241
  69. data/ext/ca_obj_window.c +1131 -563
  70. data/ext/ca_op_byte_swap.c +175 -0
  71. data/ext/ca_op_ipower.c +319 -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 +430 -0
  75. data/ext/ca_sweep_engine.h +157 -0
  76. data/ext/ca_transform_common.c +228 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +795 -402
  80. data/ext/carray_access.c +831 -711
  81. data/ext/carray_attribute.c +98 -330
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +283 -0
  84. data/ext/carray_call_cfunc.c +1360 -828
  85. data/ext/carray_call_cfunc.h +160 -0
  86. data/ext/carray_cast.c +1212 -301
  87. data/ext/carray_cast_func.rb +81 -40
  88. data/ext/carray_class.c +53 -63
  89. data/ext/carray_config.h +28 -0
  90. data/ext/carray_conversion.c +350 -346
  91. data/ext/carray_copy.c +156 -268
  92. data/ext/carray_core.c +1342 -199
  93. data/ext/carray_count.c +312 -0
  94. data/ext/carray_data_type.c +43 -19
  95. data/ext/carray_element.c +585 -213
  96. data/ext/carray_factorize.c +2542 -0
  97. data/ext/carray_generate.c +230 -559
  98. data/ext/carray_histogram.c +490 -0
  99. data/ext/carray_hold.c +228 -0
  100. data/ext/carray_index_classifier.c +1035 -0
  101. data/ext/carray_index_classifier.h +27 -0
  102. data/ext/carray_internal.h +120 -0
  103. data/ext/carray_kernels_bincmp.c +4445 -0
  104. data/ext/carray_kernels_binop.c +10979 -0
  105. data/ext/carray_kernels_init.c +36 -0
  106. data/ext/carray_kernels_map.c +3466 -0
  107. data/ext/carray_kernels_moncmp.c +2096 -0
  108. data/ext/carray_kernels_monop.c +18312 -0
  109. data/ext/carray_kernels_reduce_aggregate.c +25836 -0
  110. data/ext/carray_kernels_reduce_boolean.c +329 -0
  111. data/ext/carray_kernels_reduce_cumulative.c +14592 -0
  112. data/ext/carray_kernels_reduce_extreme.c +16947 -0
  113. data/ext/carray_kernels_reduce_variance.c +3909 -0
  114. data/ext/carray_kernels_scan.c +3692 -0
  115. data/ext/carray_kernels_search.c +32137 -0
  116. data/ext/carray_kernels_sort.c +10625 -0
  117. data/ext/carray_kernels_triop.c +1391 -0
  118. data/ext/carray_lazy.c +567 -0
  119. data/ext/carray_loop.c +88 -200
  120. data/ext/carray_mask.c +848 -154
  121. data/ext/carray_math_kernel.h +120 -0
  122. data/ext/carray_mathfunc.c +10 -241
  123. data/ext/carray_median_percentile.c +1257 -0
  124. data/ext/carray_memory_view.c +1625 -0
  125. data/ext/carray_operator.c +1526 -318
  126. data/ext/carray_order.c +664 -1394
  127. data/ext/carray_partition.c +416 -0
  128. data/ext/carray_random.c +518 -0
  129. data/ext/carray_scatter.c +357 -0
  130. data/ext/carray_slab.c +1219 -0
  131. data/ext/carray_slab.h +84 -0
  132. data/ext/carray_sort.c +829 -0
  133. data/ext/carray_sort_kernel.c +620 -0
  134. data/ext/carray_struct.c +695 -0
  135. data/ext/carray_test.c +343 -229
  136. data/ext/carray_undef.c +34 -17
  137. data/ext/carray_utils.c +175 -74
  138. data/ext/extconf.rb +216 -55
  139. data/ext/mk_call_cfunc.rb +480 -0
  140. data/ext/mkkernel.rb +8842 -0
  141. data/ext/ruby_carray.c +202 -101
  142. data/ext/version.h +4 -14
  143. data/ext/version.rb +5 -13
  144. data/lib/carray/arrow_tensor.rb +401 -0
  145. data/lib/carray/attribute.rb +166 -0
  146. data/lib/carray/autoload_carray.rb +220 -0
  147. data/lib/carray/autoload_method_extension.rb +44 -0
  148. data/lib/carray/axis_group.rb +711 -0
  149. data/lib/carray/basics.rb +481 -0
  150. data/lib/carray/bincount_nd.rb +358 -0
  151. data/lib/carray/block_iterator.rb +604 -0
  152. data/lib/carray/boolean_reduce.rb +109 -0
  153. data/lib/carray/categorical.rb +561 -0
  154. data/lib/carray/categorical_iterator.rb +1062 -0
  155. data/lib/carray/complex.rb +150 -0
  156. data/lib/carray/conditional.rb +216 -0
  157. data/lib/carray/const_string.rb +228 -0
  158. data/lib/carray/construct.rb +139 -328
  159. data/lib/carray/core_extensions.rb +240 -0
  160. data/lib/carray/data_type_extension.rb +233 -0
  161. data/lib/carray/fixlen_string.rb +95 -0
  162. data/lib/carray/frame/concat.rb +132 -0
  163. data/lib/carray/frame/convert.rb +95 -0
  164. data/lib/carray/frame/csv_parser.rb +211 -0
  165. data/lib/carray/frame/frame.rb +649 -0
  166. data/lib/carray/frame/group.rb +186 -0
  167. data/lib/carray/frame/io.rb +164 -0
  168. data/lib/carray/frame/join.rb +248 -0
  169. data/lib/carray/frame/records.rb +99 -0
  170. data/lib/carray/frame/sort.rb +113 -0
  171. data/lib/carray/frame/verbs.rb +299 -0
  172. data/lib/carray/frame.rb +16 -0
  173. data/lib/carray/histogram.rb +512 -0
  174. data/lib/carray/inspect.rb +37 -20
  175. data/lib/carray/iterator.rb +57 -349
  176. data/lib/carray/lazy.rb +889 -0
  177. data/lib/carray/mask_gap_fill.rb +200 -0
  178. data/lib/carray/math.rb +78 -342
  179. data/lib/carray/meld_reduce.rb +289 -0
  180. data/lib/carray/methods/align_addr.rb +116 -0
  181. data/lib/carray/methods/bin.rb +128 -0
  182. data/lib/carray/methods/bincount.rb +87 -0
  183. data/lib/carray/methods/bit_string.rb +92 -0
  184. data/lib/carray/methods/broadcast.rb +63 -0
  185. data/lib/carray/methods/choose.rb +39 -0
  186. data/lib/carray/methods/composition.rb +280 -0
  187. data/lib/carray/methods/gather_nd.rb +206 -0
  188. data/lib/carray/methods/index.rb +39 -0
  189. data/lib/carray/methods/insert_block.rb +99 -0
  190. data/lib/carray/methods/is_in.rb +141 -0
  191. data/lib/carray/methods/join.rb +90 -0
  192. data/lib/carray/methods/locate_addr.rb +47 -0
  193. data/lib/carray/methods/mask_duplicates.rb +41 -0
  194. data/lib/carray/methods/meshgrid.rb +91 -0
  195. data/lib/carray/methods/mode.rb +126 -0
  196. data/lib/carray/methods/nunique.rb +46 -0
  197. data/lib/carray/methods/resize.rb +56 -0
  198. data/lib/carray/methods/snap.rb +156 -0
  199. data/lib/carray/methods/string_format.rb +57 -0
  200. data/lib/carray/methods/unique.rb +47 -0
  201. data/lib/carray/methods/value_counts.rb +71 -0
  202. data/lib/carray/mkmf.rb +124 -101
  203. data/lib/carray/runtime.rb +108 -0
  204. data/lib/carray/serialize.rb +478 -167
  205. data/lib/carray/slab_iterator.rb +292 -0
  206. data/lib/carray/stack.rb +291 -0
  207. data/lib/carray/string.rb +56 -180
  208. data/lib/carray/string_operation_extension.rb +289 -0
  209. data/lib/carray/struct.rb +335 -323
  210. data/lib/carray/struct_builder.rb +697 -0
  211. data/lib/carray/table.rb +41 -2
  212. data/lib/carray/time.rb +2255 -38
  213. data/lib/carray/window_iterator.rb +655 -0
  214. data/lib/carray.rb +55 -57
  215. metadata +163 -130
  216. data/Rakefile +0 -51
  217. data/TODO.md +0 -18
  218. data/ext/ca_iter_block.c +0 -257
  219. data/ext/ca_iter_dimension.c +0 -299
  220. data/ext/ca_iter_window.c +0 -214
  221. data/ext/ca_obj_mapping.c +0 -644
  222. data/ext/carray_iterator.c +0 -641
  223. data/ext/carray_math.rb +0 -850
  224. data/ext/carray_numeric.c +0 -259
  225. data/ext/carray_sort_addr.c +0 -254
  226. data/ext/carray_stat.c +0 -2100
  227. data/ext/carray_stat_proc.rb +0 -1999
  228. data/ext/mkmath.rb +0 -741
  229. data/ext/ruby_ccomplex.c +0 -509
  230. data/ext/ruby_float_func.c +0 -86
  231. data/lib/carray/array.rb +0 -8
  232. data/lib/carray/autoload/autoload_base.rb +0 -19
  233. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  234. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  235. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  236. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  237. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  238. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  239. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  240. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  241. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  242. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  243. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  244. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  245. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  246. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  247. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  248. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  249. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  250. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  251. data/lib/carray/autoload.rb +0 -141
  252. data/lib/carray/basic.rb +0 -191
  253. data/lib/carray/broadcast.rb +0 -101
  254. data/lib/carray/compose.rb +0 -315
  255. data/lib/carray/convert.rb +0 -115
  256. data/lib/carray/info.rb +0 -110
  257. data/lib/carray/io/imagemagick.rb +0 -235
  258. data/lib/carray/mask.rb +0 -102
  259. data/lib/carray/math/histogram.rb +0 -177
  260. data/lib/carray/math/recurrence.rb +0 -93
  261. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  262. data/lib/carray/object/ca_obj_link.rb +0 -50
  263. data/lib/carray/object/ca_obj_pack.rb +0 -99
  264. data/lib/carray/obsolete.rb +0 -256
  265. data/lib/carray/ordering.rb +0 -181
  266. data/lib/carray/testing.rb +0 -51
  267. data/lib/carray/transform.rb +0 -109
  268. data/misc/Methods.ja.md +0 -182
  269. data/misc/NOTE +0 -51
  270. data/spec/Classes/CABitfield_spec.rb +0 -58
  271. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  272. data/spec/Classes/CABlock_spec.rb +0 -205
  273. data/spec/Classes/CAField_spec.rb +0 -39
  274. data/spec/Classes/CAGrid_spec.rb +0 -75
  275. data/spec/Classes/CAMap_spec.rb +0 -0
  276. data/spec/Classes/CAMapping_spec.rb +0 -105
  277. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  278. data/spec/Classes/CAObject_spec.rb +0 -33
  279. data/spec/Classes/CARefer_spec.rb +0 -93
  280. data/spec/Classes/CARepeat_spec.rb +0 -65
  281. data/spec/Classes/CASelect_spec.rb +0 -22
  282. data/spec/Classes/CAShift_spec.rb +0 -16
  283. data/spec/Classes/CAStruct_spec.rb +0 -71
  284. data/spec/Classes/CATranspose_spec.rb +0 -60
  285. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  286. data/spec/Classes/CAWindow_spec.rb +0 -54
  287. data/spec/Classes/CAWrap_spec.rb +0 -8
  288. data/spec/Classes/CArray_spec.rb +0 -184
  289. data/spec/Classes/CScalar_spec.rb +0 -55
  290. data/spec/Classes/ex1.rb +0 -46
  291. data/spec/Features/feature_130_spec.rb +0 -19
  292. data/spec/Features/feature_attributes_spec.rb +0 -280
  293. data/spec/Features/feature_boolean_spec.rb +0 -98
  294. data/spec/Features/feature_broadcast.rb +0 -116
  295. data/spec/Features/feature_cast_function.rb +0 -19
  296. data/spec/Features/feature_cast_spec.rb +0 -33
  297. data/spec/Features/feature_class_spec.rb +0 -84
  298. data/spec/Features/feature_complex_spec.rb +0 -42
  299. data/spec/Features/feature_composite_spec.rb +0 -124
  300. data/spec/Features/feature_convert_spec.rb +0 -46
  301. data/spec/Features/feature_copy_spec.rb +0 -123
  302. data/spec/Features/feature_creation_spec.rb +0 -84
  303. data/spec/Features/feature_element_spec.rb +0 -144
  304. data/spec/Features/feature_extream_spec.rb +0 -54
  305. data/spec/Features/feature_generate_spec.rb +0 -74
  306. data/spec/Features/feature_index_spec.rb +0 -69
  307. data/spec/Features/feature_mask_spec.rb +0 -580
  308. data/spec/Features/feature_math_spec.rb +0 -97
  309. data/spec/Features/feature_order_spec.rb +0 -146
  310. data/spec/Features/feature_ref_store_spec.rb +0 -209
  311. data/spec/Features/feature_serialization_spec.rb +0 -125
  312. data/spec/Features/feature_stat_spec.rb +0 -397
  313. data/spec/Features/feature_virtual_spec.rb +0 -48
  314. data/spec/Features/method_eq_spec.rb +0 -81
  315. data/spec/Features/method_is_nan_spec.rb +0 -12
  316. data/spec/Features/method_map_spec.rb +0 -54
  317. data/spec/Features/method_max_with.rb +0 -20
  318. data/spec/Features/method_min_with.rb +0 -19
  319. data/spec/Features/method_ne_spec.rb +0 -18
  320. data/spec/Features/method_project_spec.rb +0 -188
  321. data/spec/Features/method_ref_spec.rb +0 -27
  322. data/spec/Features/method_round_spec.rb +0 -11
  323. data/spec/Features/method_s_linspace_spec.rb +0 -48
  324. data/spec/Features/method_s_span_spec.rb +0 -14
  325. data/spec/Features/method_seq_spec.rb +0 -47
  326. data/spec/Features/method_sort_with.rb +0 -43
  327. data/spec/Features/method_sorted_with.rb +0 -29
  328. data/spec/Features/method_span_spec.rb +0 -42
  329. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  330. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  331. data/spec/spec_all.rb +0 -10
  332. data/utils/ca_ase.rb +0 -21
  333. data/utils/ca_methods.rb +0 -15
  334. data/utils/cast_checker.rb +0 -30
  335. data/utils/convert_test.rb +0 -73
  336. data/utils/extract_yard.rb +0 -22
  337. data/utils/guess_shape.rb +0 -76
  338. data/utils/monkey_patch_methods.rb +0 -62
  339. 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,319 @@
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
+ obj = rb_ca_rewrap_unbound_repeat(self, obj);
237
+
238
+ return obj;
239
+ }
240
+
241
+ static VALUE
242
+ rb_ca_ipower_bang (VALUE self, VALUE other)
243
+ {
244
+ CArray *ca;
245
+ int32_t ipow;
246
+ boolean8_t *m;
247
+
248
+ ipow = NUM2INT(other);
249
+
250
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
251
+
252
+ ca_attach(ca);
253
+
254
+ m = ( ca->mask ) ? (boolean8_t *)ca->mask->ptr : NULL;
255
+
256
+ switch ( ca->data_type ) {
257
+ case CA_FLOAT32:
258
+ ca_ipower_float32_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
259
+ case CA_FLOAT64:
260
+ ca_ipower_float64_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
261
+ case CA_CMPLX64:
262
+ ca_ipower_cmplx64_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
263
+ case CA_CMPLX128:
264
+ ca_ipower_cmplx128_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
265
+ default:
266
+ rb_raise(rb_eRuntimeError, "invalid data type for ipower");
267
+ }
268
+
269
+ ca_sync(ca);
270
+ ca_detach(ca);
271
+
272
+ return self;
273
+ }
274
+
275
+ /* CArray#pow(other) (alias `**`) — Float/Complex ** Integer takes the
276
+ * ipower fast path in this file; everything else falls through to the
277
+ * mkkernel-generated general pow/cpow (rb_ca_power in
278
+ * ext/carray_kernels.c). Non-bang variant preserves UnboundRepeat
279
+ * wrapping on the result. */
280
+ static VALUE rb_ca_pow (VALUE self, VALUE other)
281
+ {
282
+ volatile VALUE obj;
283
+ CArray *ca;
284
+
285
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
286
+ if ( ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) &&
287
+ rb_obj_is_kind_of(other, rb_cInteger) ) {
288
+ return rb_ca_ipower(self, other);
289
+ }
290
+ else {
291
+ obj = rb_ca_power(self, other);
292
+ obj = rb_ca_rewrap_unbound_repeat(self, obj);
293
+ return obj;
294
+ }
295
+ }
296
+
297
+ /* CArray#pow!(other) — in-place variant of #pow. Dispatch mirrors
298
+ * rb_ca_pow (fast path for Float/Complex ** Integer, otherwise
299
+ * general rb_ca_power_bang). */
300
+ static VALUE rb_ca_pow_bang (VALUE self, VALUE other)
301
+ {
302
+ CArray *ca;
303
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
304
+ if ( ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) &&
305
+ rb_obj_is_kind_of(other, rb_cInteger) ) {
306
+ return rb_ca_ipower_bang(self, other);
307
+ }
308
+ else {
309
+ return rb_ca_power_bang(self, other);
310
+ }
311
+ }
312
+
313
+ void
314
+ Init_ca_op_ipower (void)
315
+ {
316
+ rb_define_method(rb_cCArray, "pow", rb_ca_pow, 1);
317
+ rb_define_method(rb_cCArray, "pow!", rb_ca_pow_bang, 1);
318
+ rb_define_alias(rb_cCArray, "**", "pow");
319
+ }
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 */