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
data/ext/ca_obj_roll.c ADDED
@@ -0,0 +1,624 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ CARoll view: same-shape cyclic shift of the parent. Per-axis shift
4
+ is passed as multi-arg to `CArray#roll`.
5
+
6
+ Sibling of ca_obj_tile.c (CARoll is a `typedef CATile CARoll`; the
7
+ operation table is built by copying ca_tile_func and overriding the
8
+ slots that need shift-specific behavior).
9
+
10
+ Storage reuse: CATile's `reps[]` field is reinterpreted in CARoll as
11
+ `shift[]` (= normalised to `[0, parent.dim[k])`).
12
+
13
+ Region enumeration: each shifted axis contributes 2 stripes, so the
14
+ cartesian product yields 2^K regions where K counts non-zero shift
15
+ axes. Non-shifted axes give a single full-parent stripe.
16
+
17
+ ---------------------------------------------------------------------------- */
18
+
19
+ #include "carray.h"
20
+ #include "ca_composite_dispatch.h"
21
+ #include "ca_obj_face.h"
22
+
23
+ /* ------------------------------------------------------------------- */
24
+ /* External: CATile's data type + base operation table (typedef shared). */
25
+ /* ------------------------------------------------------------------- */
26
+
27
+ extern const rb_data_type_t catile_data_type;
28
+ extern ca_operation_function_t ca_tile_func;
29
+ extern VALUE rb_cCATile;
30
+
31
+ /* ------------------------------------------------------------------- */
32
+ /* TypedData */
33
+ /* ------------------------------------------------------------------- */
34
+
35
+ static size_t
36
+ ca_roll_dsize (const void *ap)
37
+ {
38
+ const CARoll *ca = (const CARoll *) ap;
39
+ /* Layout inherited from CATile: dim + reps, each ALLOC_N(ndim). */
40
+ return sizeof(CARoll) + 2 * ca->ndim * sizeof(ca_size_t);
41
+ }
42
+
43
+ const rb_data_type_t caroll_data_type = {
44
+ .parent = &catile_data_type,
45
+ .wrap_struct_name = "CARoll",
46
+ .function = {
47
+ .dmark = ca_mark,
48
+ .dfree = ca_free,
49
+ .dsize = ca_roll_dsize,
50
+ .dcompact = NULL
51
+ },
52
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
53
+ };
54
+
55
+ const rb_data_type_t caroll_mask_data_type = {
56
+ .parent = &caroll_data_type,
57
+ .wrap_struct_name = "CARollMask",
58
+ .function = {
59
+ .dmark = ca_mark,
60
+ .dfree = ca_free_nop,
61
+ .dsize = ca_roll_dsize,
62
+ .dcompact = NULL
63
+ },
64
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
65
+ };
66
+
67
+ int8_t CA_OBJ_ROLL;
68
+
69
+ VALUE rb_cCARoll;
70
+ VALUE rb_cCARollMask;
71
+
72
+ ca_operation_function_t ca_roll_func;
73
+
74
+ /* ------------------------------------------------------------------- */
75
+ /* setup / new / free / clone */
76
+ /* ------------------------------------------------------------------- */
77
+
78
+ /* shift[] semantics:
79
+ shift[k] > 0 : shift right (last shift[k] elements wrap to front)
80
+ shift[k] < 0 : shift left
81
+ shift[k] is normalised into [0, parent.dim[k]) modulo dim[k].
82
+ Missing axes (argc < ndim from Ruby): treated as shift = 0. */
83
+ int
84
+ ca_roll_setup (CARoll *ca, CArray *parent, ca_size_t *shift)
85
+ {
86
+ int8_t ndim = parent->ndim;
87
+ ca_size_t bytes = parent->bytes;
88
+ ca_size_t elements;
89
+ int8_t i;
90
+
91
+ elements = 1;
92
+ for (i = 0; i < ndim; i++) {
93
+ if ( parent->dim[i] <= 0 ) {
94
+ rb_raise(rb_eIndexError, "invalid parent dim for %d-th dimension", i);
95
+ }
96
+ elements *= parent->dim[i];
97
+ }
98
+
99
+ ca->obj_type = CA_OBJ_ROLL;
100
+ ca->data_type = parent->data_type;
101
+ ca->flags = 0;
102
+ ca->ndim = ndim;
103
+ ca->bytes = bytes;
104
+ ca->elements = elements;
105
+ ca->ptr = NULL;
106
+ ca->mask = NULL;
107
+
108
+ ca->parent = parent;
109
+ ca->attach = 0;
110
+ ca->nosync = 0;
111
+ ca->reps = ALLOC_N(ca_size_t, ndim); /* repurposed as shift[] */
112
+ ca->dim = ALLOC_N(ca_size_t, ndim);
113
+
114
+ for (i = 0; i < ndim; i++) {
115
+ ca->dim[i] = parent->dim[i];
116
+ /* Normalise: ((shift[i] % dim[i]) + dim[i]) % dim[i] ∈ [0, dim[i]). */
117
+ ca_size_t s = shift[i] % parent->dim[i];
118
+ if ( s < 0 ) s += parent->dim[i];
119
+ ca->reps[i] = s;
120
+ }
121
+
122
+ if ( ca_has_mask(parent) ) {
123
+ ca_create_mask(ca);
124
+ }
125
+
126
+ return 0;
127
+ }
128
+
129
+ CARoll *
130
+ ca_roll_new (CArray *parent, ca_size_t *shift)
131
+ {
132
+ CARoll *ca = ALLOC(CARoll);
133
+ ca_roll_setup(ca, parent, shift);
134
+ return ca;
135
+ }
136
+
137
+ static void
138
+ free_ca_roll (void *ap)
139
+ {
140
+ CARoll *ca = (CARoll *) ap;
141
+ if ( ca != NULL ) {
142
+ ca_free(ca->mask);
143
+ xfree(ca->reps);
144
+ xfree(ca->dim);
145
+ xfree(ca);
146
+ }
147
+ }
148
+
149
+ static void *
150
+ ca_roll_func_clone (void *ap)
151
+ {
152
+ CARoll *ca = (CARoll *) ap;
153
+ return ca_roll_new(ca->parent, ca->reps); /* reps[] is already normalised shift[] */
154
+ }
155
+
156
+ /* ------------------------------------------------------------------- */
157
+ /* xfer_index / xfer_addrs / xfer_stride — periodic index map */
158
+ /* */
159
+ /* view[i_0, i_1, ...] = parent[(i_0 - shift_0 + dim_0) % dim_0, ...] */
160
+ /* */
161
+ /* CARoll inherits ca_tile_func by copy, so every xfer slot below must */
162
+ /* be re-registered in Init_ca_obj_roll to override the CATile version. */
163
+ /* ------------------------------------------------------------------- */
164
+
165
+ static void
166
+ ca_roll_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
167
+ {
168
+ CARoll *ca = (CARoll *) ap;
169
+ ca_size_t pidx[CA_RANK_MAX];
170
+ int8_t i;
171
+ for (i = 0; i < ca->ndim; i++) {
172
+ /* output[idx] = parent[(idx - shift + dim) % dim]. */
173
+ ca_size_t k = idx[i] - ca->reps[i];
174
+ if ( k < 0 ) k += ca->parent->dim[i];
175
+ pidx[i] = k;
176
+ }
177
+ ca_xfer_index(ca->parent, pidx, data, dir);
178
+ }
179
+
180
+ /* Batched address gather/scatter. The periodic shift is 1:1 and
181
+ always in-bounds, so all addrs collapse to a single parent
182
+ ca_xfer_addrs call. */
183
+ static void
184
+ ca_roll_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
185
+ void *data, int dir)
186
+ {
187
+ CARoll *ca = (CARoll *) ap;
188
+ ca_size_t *paddrs;
189
+ ca_size_t i;
190
+ int8_t k;
191
+ volatile VALUE holder;
192
+ paddrs = ALLOCV_N(ca_size_t, holder, n);
193
+ for (i = 0; i < n; i++) {
194
+ ca_size_t vidx[CA_RANK_MAX], pidx[CA_RANK_MAX];
195
+ ca_addr2index((CArray *) ca, addrs[i], vidx);
196
+ for (k = 0; k < ca->ndim; k++) {
197
+ ca_size_t j = vidx[k] - ca->reps[k];
198
+ if ( j < 0 ) j += ca->parent->dim[k];
199
+ pidx[k] = j;
200
+ }
201
+ paddrs[i] = ca_index2addr(ca->parent, pidx);
202
+ }
203
+ ca_xfer_addrs(ca->parent, n, paddrs, data, dir);
204
+ ALLOCV_END(holder);
205
+ }
206
+
207
+ /* Structural region delivery for CARoll. The parent position along
208
+ each axis is `(view_pos - shift) mod parent.dim[k]`. view.dim ==
209
+ parent.dim, so a contiguous inner run wraps at most once and the
210
+ per-segment loop handles the wrap. Structural path requires
211
+ axis-aligned unit src step along the inner axis; otherwise falls
212
+ back to per-cell xfer_index. */
213
+ static void
214
+ ca_roll_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
215
+ ca_size_t *strides, void *data, int dir)
216
+ {
217
+ CARoll *ca = (CARoll *) ap;
218
+ CArray *parent = ca->parent;
219
+ int8_t ndim = ca->ndim;
220
+ int8_t inner = ndim - 1;
221
+ ca_size_t pnative[CA_RANK_MAX], rnative[CA_RANK_MAX], dstride[CA_RANK_MAX];
222
+ ca_size_t o[CA_RANK_MAX];
223
+ ca_size_t s;
224
+ int8_t k;
225
+ int structural = 1;
226
+ char *d = (char *) data;
227
+
228
+ s = parent->bytes;
229
+ for (k = ndim - 1; k >= 0; k--) { pnative[k] = s; s *= parent->dim[k]; }
230
+ s = ca->bytes;
231
+ for (k = ndim - 1; k >= 0; k--) { rnative[k] = s; s *= ca->dim[k]; }
232
+ s = ca->bytes;
233
+ for (k = ndim - 1; k >= 0; k--) { dstride[k] = s; s *= counts[k]; }
234
+
235
+ /* The request is over the view's addresses, so a transposed / flat request
236
+ is legal and must not be composed axis-by-axis; see
237
+ ca_xfer_stride_request_is_axis_box (carray.h). */
238
+ if ( ! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
239
+ structural = 0;
240
+ }
241
+ else {
242
+ for (k = 0; k < ndim; k++) {
243
+ if (strides[k] % rnative[k] != 0 || strides[k] / rnative[k] != 1) {
244
+ structural = 0;
245
+ break;
246
+ }
247
+ }
248
+ }
249
+
250
+ if (!structural) {
251
+ ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
252
+ for (k = 0; k < ndim; k++) base += starts[k] * rnative[k];
253
+ for (k = 0; k < ndim; k++) idx[k] = 0;
254
+ while (1) {
255
+ ca_size_t roff = base, ridx[CA_RANK_MAX];
256
+ for (k = 0; k < ndim; k++) roff += idx[k] * strides[k];
257
+ ca_addr2index((CArray *) ca, roff / ca->bytes, ridx);
258
+ ca_roll_func_xfer_index(ca, ridx, d + doff, dir);
259
+ doff += ca->bytes;
260
+ k = ndim - 1;
261
+ while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
262
+ if (k < 0) break;
263
+ }
264
+ return;
265
+ }
266
+
267
+ for (k = 0; k < ndim; k++) o[k] = 0;
268
+ while (1) {
269
+ ca_size_t pbase = 0, doff = 0, i;
270
+ for (k = 0; k < inner; k++) {
271
+ ca_size_t j = (starts[k] + o[k]) - ca->reps[k];
272
+ if (j < 0) j += parent->dim[k];
273
+ pbase += j * pnative[k];
274
+ doff += o[k] * dstride[k];
275
+ }
276
+ i = 0;
277
+ while (i < counts[inner]) {
278
+ ca_size_t ppos = (starts[inner] + i) - ca->reps[inner];
279
+ if (ppos < 0) ppos += parent->dim[inner];
280
+ ca_size_t seg = parent->dim[inner] - ppos;
281
+ ca_size_t pstarts[CA_RANK_MAX], pcounts[CA_RANK_MAX], pstrides[CA_RANK_MAX];
282
+ if (seg > counts[inner] - i) seg = counts[inner] - i;
283
+ ca_addr2index((CArray *) parent, (pbase + ppos * pnative[inner]) / parent->bytes, pstarts);
284
+ for (k = 0; k < ndim; k++) { pcounts[k] = 1; pstrides[k] = 0; }
285
+ pcounts[inner] = seg;
286
+ pstrides[inner] = pnative[inner];
287
+ ca_xfer_stride(parent, pstarts, pcounts, pstrides, d + doff + i * dstride[inner], dir);
288
+ i += seg;
289
+ }
290
+ k = inner - 1;
291
+ while (k >= 0) { if (++o[k] < counts[k]) break; o[k] = 0; k--; }
292
+ if (k < 0) break;
293
+ }
294
+ }
295
+
296
+ /* ------------------------------------------------------------------- */
297
+ /* attach / sync — enumerate 2^K stripe regions */
298
+ /* */
299
+ /* Per axis k: */
300
+ /* shift[k] == 0 : */
301
+ /* one full-axis stripe (parent_start=0, count=dim, off=0) */
302
+ /* shift[k] > 0 : */
303
+ /* stripe A (last shift[k] parent cells wrap to output front): */
304
+ /* parent_start[k] = dim[k] - shift[k] */
305
+ /* count[k] = shift[k] */
306
+ /* output_offset[k]= 0 */
307
+ /* stripe B (remaining cells): */
308
+ /* parent_start[k] = 0 */
309
+ /* count[k] = dim[k] - shift[k] */
310
+ /* output_offset[k]= shift[k] */
311
+ /* */
312
+ /* Total regions = 2^K where K = number of axes with shift != 0. */
313
+ /* ------------------------------------------------------------------- */
314
+
315
+ static void
316
+ ca_roll_compute_strides (CARoll *ca,
317
+ ca_size_t *parent_strides,
318
+ ca_size_t *output_strides)
319
+ {
320
+ ca_size_t s;
321
+ int8_t k;
322
+ s = ca->bytes;
323
+ for ( k = ca->ndim - 1; k >= 0; k-- ) {
324
+ parent_strides[k] = s;
325
+ s *= ca->parent->dim[k];
326
+ }
327
+ s = ca->bytes;
328
+ for ( k = ca->ndim - 1; k >= 0; k-- ) {
329
+ output_strides[k] = s;
330
+ s *= ca->dim[k];
331
+ }
332
+ }
333
+
334
+ /* Walk regions via a bitmap over the K shifted axes. For each region
335
+ (bitmap value 0..2^K-1), build parent_start[] / count[] /
336
+ output_offset[] and call ca_composite_region_gather (attach) or
337
+ ca_composite_region_scatter (sync). */
338
+ static void
339
+ ca_roll_iterate_regions (CARoll *ca, char *out_ptr, int direction)
340
+ {
341
+ ca_size_t parent_strides[CA_RANK_MAX];
342
+ ca_size_t output_strides[CA_RANK_MAX];
343
+ ca_size_t parent_start[CA_RANK_MAX];
344
+ ca_size_t output_offset[CA_RANK_MAX];
345
+ ca_size_t count[CA_RANK_MAX];
346
+ int8_t shifted_axes[CA_RANK_MAX];
347
+ int8_t n_shifted = 0;
348
+ int8_t k;
349
+ ca_size_t bytes = ca->bytes;
350
+ int8_t ndim = ca->ndim;
351
+ int region, total_regions;
352
+
353
+ ca_roll_compute_strides(ca, parent_strides, output_strides);
354
+
355
+ /* Identify shifted axes; set baseline (= stripe B for shifted, full for non-shifted). */
356
+ for ( k = 0; k < ndim; k++ ) {
357
+ if ( ca->reps[k] != 0 ) {
358
+ shifted_axes[n_shifted++] = k;
359
+ }
360
+ }
361
+
362
+ total_regions = 1 << n_shifted;
363
+
364
+ for ( region = 0; region < total_regions; region++ ) {
365
+ /* Initialise: non-shifted axes = full. */
366
+ for ( k = 0; k < ndim; k++ ) {
367
+ if ( ca->reps[k] == 0 ) {
368
+ parent_start[k] = 0;
369
+ count[k] = ca->parent->dim[k];
370
+ output_offset[k] = 0;
371
+ }
372
+ }
373
+ /* For each shifted axis, pick stripe based on region bit. */
374
+ for ( int b = 0; b < n_shifted; b++ ) {
375
+ int8_t ax = shifted_axes[b];
376
+ ca_size_t shift = ca->reps[ax];
377
+ ca_size_t pdim = ca->parent->dim[ax];
378
+ if ( (region >> b) & 1 ) {
379
+ /* Stripe B: remaining elements after the wrapped tail. */
380
+ parent_start[ax] = 0;
381
+ count[ax] = pdim - shift;
382
+ output_offset[ax] = shift;
383
+ } else {
384
+ /* Stripe A: last `shift` elements wrap to front. */
385
+ parent_start[ax] = pdim - shift;
386
+ count[ax] = shift;
387
+ output_offset[ax] = 0;
388
+ }
389
+ }
390
+
391
+ if ( direction == 0 ) {
392
+ ca_composite_region_gather(ca->parent->ptr, parent_strides,
393
+ parent_start,
394
+ out_ptr, output_strides, output_offset,
395
+ count, ndim, bytes);
396
+ } else {
397
+ ca_composite_region_scatter(ca->parent->ptr, parent_strides,
398
+ parent_start,
399
+ out_ptr, output_strides, output_offset,
400
+ count, ndim, bytes);
401
+ }
402
+ }
403
+ }
404
+
405
+ static void
406
+ ca_roll_func_allocate (void *ap)
407
+ {
408
+ CARoll *ca = (CARoll *) ap;
409
+ ca_attach(ca->parent);
410
+ ca->ptr = xmalloc(ca_length(ca));
411
+ }
412
+
413
+ static void
414
+ ca_roll_func_attach (void *ap)
415
+ {
416
+ CARoll *ca = (CARoll *) ap;
417
+ ca_attach(ca->parent);
418
+ ca->ptr = xmalloc(ca_length(ca));
419
+ ca_roll_iterate_regions(ca, ca->ptr, 0);
420
+ }
421
+
422
+ static void
423
+ ca_roll_func_sync (void *ap)
424
+ {
425
+ CARoll *ca = (CARoll *) ap;
426
+ ca_roll_iterate_regions(ca, ca->ptr, 1);
427
+ ca_sync(ca->parent);
428
+ }
429
+
430
+ static void
431
+ ca_roll_func_detach (void *ap)
432
+ {
433
+ CARoll *ca = (CARoll *) ap;
434
+ xfree(ca->ptr);
435
+ ca->ptr = NULL;
436
+ ca_detach(ca->parent);
437
+ }
438
+
439
+ /* Fast path (hot parent): drive the region walk directly against
440
+ parent->ptr. Cold parent: fall back to a scratch 2-pass (gather
441
+ parent into scratch, walk regions against the scratch, scatter
442
+ back on PUT). Deliberately does not call ca_attach(parent) — that
443
+ would re-introduce the silent transitive attach the fast path was
444
+ built to avoid. */
445
+ static void
446
+ ca_roll_func_xfer_all (void *ap, void *data, int dir)
447
+ {
448
+ CARoll *ca = (CARoll *) ap;
449
+ if ( ca->parent->ptr ) {
450
+ ca_roll_iterate_regions(ca, (char *) data, dir == CA_XFER_PUT);
451
+ return;
452
+ }
453
+ {
454
+ volatile VALUE holder;
455
+ CArray *parent = ca->parent;
456
+ ca_size_t plen = parent->elements * parent->bytes;
457
+ char *parent_scratch = ALLOCV_N(char, holder, plen);
458
+ char *parent_ptr_saved = parent->ptr;
459
+ ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
460
+ parent->ptr = parent_scratch;
461
+ ca_roll_iterate_regions(ca, (char *) data, dir == CA_XFER_PUT);
462
+ if ( dir == CA_XFER_PUT ) {
463
+ ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
464
+ }
465
+ parent->ptr = parent_ptr_saved;
466
+ ALLOCV_END(holder);
467
+ }
468
+ }
469
+
470
+ static void
471
+ ca_roll_func_fill_data (void *ap, void *ptr)
472
+ {
473
+ CARoll *ca = (CARoll *) ap;
474
+ /* Each parent cell appears exactly once in the view, so a broadcast
475
+ fill is equivalent to filling the parent once. */
476
+ ca_fill(ca->parent, ptr);
477
+ }
478
+
479
+ static void
480
+ ca_roll_func_create_mask (void *ap)
481
+ {
482
+ CARoll *ca = (CARoll *) ap;
483
+ ca_update_mask(ca->parent);
484
+ if ( ! ca->parent->mask ) {
485
+ ca_create_mask(ca->parent);
486
+ }
487
+ ca->mask = (CArray *) ca_roll_new(ca->parent->mask, ca->reps);
488
+ }
489
+
490
+ /* ------------------------------------------------------------------- */
491
+ /* Ruby surface */
492
+ /* ------------------------------------------------------------------- */
493
+
494
+ VALUE
495
+ rb_ca_roll_new (VALUE cary, ca_size_t *shift)
496
+ {
497
+ volatile VALUE obj;
498
+ CArray *parent;
499
+ CARoll *ca;
500
+ rb_check_carray_object(cary);
501
+ TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
502
+ ca = ca_roll_new(parent, shift);
503
+ obj = ca_wrap_struct(ca);
504
+ rb_ca_set_parent(obj, cary);
505
+ return obj;
506
+ }
507
+
508
+ /* CArray#roll(*shifts) — cyclic shift along each axis.
509
+ argc < ndim : missing axes take shift = 0.
510
+ argc > ndim : ArgumentError. */
511
+ static VALUE
512
+ rb_ca_roll (int argc, VALUE *argv, VALUE self)
513
+ {
514
+ CArray *ca;
515
+ volatile VALUE ropt;
516
+ ca_size_t shift[CA_RANK_MAX];
517
+ int8_t i;
518
+
519
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
520
+
521
+ /* Shifts are positional only. A trailing Hash is a keyword argument
522
+ that would otherwise reach NUM2SIZE and surface as a TypeError. */
523
+ ropt = rb_pop_options(&argc, &argv);
524
+ rb_reject_options(ropt);
525
+
526
+ if ( argc > ca->ndim ) {
527
+ rb_raise(rb_eArgError,
528
+ "roll: too many args (%d), expected at most %d (= ndim)",
529
+ argc, ca->ndim);
530
+ }
531
+ for ( i = 0; i < ca->ndim; i++ ) {
532
+ if ( i < argc ) {
533
+ shift[i] = NUM2SIZE(argv[i]);
534
+ } else {
535
+ shift[i] = 0;
536
+ }
537
+ }
538
+ {
539
+ VALUE obj = rb_ca_roll_new(self, shift);
540
+ CA_WRAPPER_LIFT(obj, self, ca);
541
+ return obj;
542
+ }
543
+ }
544
+
545
+ /* `roll!` intentionally absent. Canonical in-place idiom is
546
+ `ca[] = ca.roll(...)`. */
547
+
548
+ static VALUE
549
+ rb_ca_roll_s_allocate (VALUE klass)
550
+ {
551
+ CARoll *ca;
552
+ return TypedData_Make_Struct(klass, CARoll, &caroll_data_type, ca);
553
+ }
554
+
555
+ static VALUE
556
+ rb_ca_roll_initialize_copy (VALUE self, VALUE other)
557
+ {
558
+ CARoll *ca, *cs;
559
+ TypedData_Get_Struct(self, CARoll, &caroll_data_type, ca);
560
+ TypedData_Get_Struct(other, CARoll, &caroll_data_type, cs);
561
+ ca_roll_setup(ca, cs->parent, cs->reps);
562
+ return self;
563
+ }
564
+
565
+ /* Debug-only accessor returning the roll descriptor as a Hash
566
+ (`shifts`, `n_regions`, `ndim`). Not part of the public surface. */
567
+ static VALUE
568
+ rb_ca_roll_descriptor (VALUE self)
569
+ {
570
+ CARoll *ca = (CARoll *) DATA_PTR(self);
571
+ VALUE hash, shifts_ary;
572
+ int8_t k;
573
+ int n_shifted = 0;
574
+
575
+ shifts_ary = rb_ary_new_capa(ca->ndim);
576
+ for ( k = 0; k < ca->ndim; k++ ) {
577
+ rb_ary_push(shifts_ary, SIZE2NUM(ca->reps[k]));
578
+ if ( ca->reps[k] != 0 ) n_shifted++;
579
+ }
580
+ hash = rb_hash_new();
581
+ rb_hash_aset(hash, ID2SYM(rb_intern("shifts")), shifts_ary);
582
+ rb_hash_aset(hash, ID2SYM(rb_intern("n_regions")), INT2NUM(1 << n_shifted));
583
+ rb_hash_aset(hash, ID2SYM(rb_intern("ndim")), INT2NUM(ca->ndim));
584
+ return hash;
585
+ }
586
+
587
+ void
588
+ Init_ca_obj_roll (void)
589
+ {
590
+ /* Build ca_roll_func by copying ca_tile_func and overriding the
591
+ slots that need CARoll-specific behavior. */
592
+ ca_roll_func = ca_tile_func;
593
+ ca_roll_func.free_object = free_ca_roll;
594
+ ca_roll_func.clone = ca_roll_func_clone;
595
+ ca_roll_func.allocate = ca_roll_func_allocate;
596
+ ca_roll_func.attach = ca_roll_func_attach;
597
+ ca_roll_func.sync = ca_roll_func_sync;
598
+ ca_roll_func.detach = ca_roll_func_detach;
599
+ ca_roll_func.fill_data = ca_roll_func_fill_data;
600
+ ca_roll_func.create_mask = ca_roll_func_create_mask;
601
+ ca_roll_func.xfer_index = ca_roll_func_xfer_index;
602
+ ca_roll_func.xfer_addrs = ca_roll_func_xfer_addrs;
603
+ ca_roll_func.xfer_stride = ca_roll_func_xfer_stride;
604
+ ca_roll_func.xfer_all = ca_roll_func_xfer_all;
605
+
606
+ rb_cCARoll = rb_define_class("CARoll", rb_cCATile);
607
+ rb_cCARollMask = rb_define_class("CARollMask", rb_cCARoll);
608
+
609
+ CA_OBJ_ROLL = ca_install_obj_type(rb_cCARoll,
610
+ &caroll_data_type,
611
+ rb_cCARollMask,
612
+ &caroll_mask_data_type, &ca_roll_func, sizeof(ca_roll_func));
613
+ rb_define_const(rb_cObject, "CA_OBJ_ROLL", INT2NUM(CA_OBJ_ROLL));
614
+
615
+ rb_define_method(rb_cCArray, "roll", rb_ca_roll, -1);
616
+
617
+ rb_define_alloc_func(rb_cCARoll, rb_ca_roll_s_allocate);
618
+ rb_define_method(rb_cCARoll, "initialize_copy",
619
+ rb_ca_roll_initialize_copy, 1);
620
+
621
+ /* Debug accessor, not part of the public surface. */
622
+ rb_define_method(rb_cCARoll, "_roll_descriptor",
623
+ rb_ca_roll_descriptor, 0);
624
+ }