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_refer.c CHANGED
@@ -1,22 +1,49 @@
1
1
  /* ---------------------------------------------------------------------------
2
2
 
3
- ca_obj_refer.c
3
+ CARefer view: strided reinterpretation of the parent (`#refer`)
4
+ plus the two shape-only rewrites `#reshape` and `#flatten`.
5
+ Byte-level reinterpret (a different `data_type` / `bytes`) that
6
+ CAStride cannot express is what makes CARefer distinct — plain
7
+ same-shape reshape usually rewrites to CAStride directly through
8
+ ca_reshape_try_strides.
4
9
 
5
- This file is part of Ruby/CArray extension library.
6
-
7
- Copyright (C) 2005-2025 Hiroki Motoyoshi
10
+ Sibling of ca_obj_stride.c (CARefer's operation table is
11
+ ca_stride_func with `free_object` / `clone` / `create_mask`
12
+ overridden for the byte-reinterpret mask paths).
8
13
 
9
14
  ---------------------------------------------------------------------------- */
10
15
 
11
16
  #include "carray.h"
17
+ #include "carray_internal.h" /* per-obj_type view constructors */
18
+ #include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE for CARecord parent */
19
+
20
+ extern ca_operation_function_t ca_stride_func;
21
+
22
+ VALUE rb_cCARefer;
23
+ VALUE rb_cCAReferMask;
24
+
25
+ /* CARefer ops: ca_stride_func + custom free + custom create_mask.
26
+ Filled in at Init time so the function pointers are valid before
27
+ carray_core's baseline registration is overridden. */
28
+ static ca_operation_function_t ca_refer_func;
12
29
 
30
+ static size_t
31
+ ca_refer_dsize (const void *ap)
32
+ {
33
+ const CARefer *ca = (const CARefer *) ap;
34
+ return sizeof(CARefer) + 2 * ca->ndim * sizeof(ca_size_t);
35
+ }
36
+
37
+ /* TypedData parent chain: carefer -> castride -> caview -> carray.
38
+ Inheriting from castride_data_type lets CAStride accessor methods
39
+ (#strides, #byte_offset) accept CARefer instances. */
13
40
  const rb_data_type_t carefer_data_type = {
14
- .parent = &cavirtual_data_type,
41
+ .parent = &castride_data_type,
15
42
  .wrap_struct_name = "CARefer",
16
43
  .function = {
17
44
  .dmark = ca_mark,
18
45
  .dfree = ca_free,
19
- .dsize = NULL,
46
+ .dsize = ca_refer_dsize,
20
47
  .dcompact = NULL
21
48
  },
22
49
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
@@ -28,104 +55,77 @@ const rb_data_type_t carefer_mask_data_type = {
28
55
  .function = {
29
56
  .dmark = NULL,
30
57
  .dfree = ca_free_nop,
31
- .dsize = NULL,
58
+ .dsize = ca_refer_dsize,
32
59
  .dcompact = NULL
33
60
  },
34
61
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
35
62
  };
36
63
 
37
- VALUE rb_cCARefer;
38
- VALUE rb_cCAReferMask;
39
-
40
- /* yard:
41
- class CARefer < CAVirtual # :nodoc:
42
- end
43
- */
64
+ /* ------------------------------------------------------------------- */
44
65
 
45
- static int
66
+ int
46
67
  ca_refer_setup (CARefer *ca, CArray *parent,
47
68
  int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
48
69
  ca_size_t offset)
49
70
  {
50
- ca_size_t elements, ratio;
71
+ ca_size_t elements, strides[CA_RANK_MAX];
72
+ ca_size_t parent_bytes = parent->bytes;
73
+ ca_size_t base_offset;
74
+ ca_size_t s;
51
75
  int8_t i;
52
- int is_deformed;
53
76
 
54
77
  CA_CHECK_DATA_TYPE(data_type);
55
78
  CA_CHECK_RANK(ndim);
56
79
  CA_CHECK_DIM(ndim, dim);
57
80
  CA_CHECK_BYTES(data_type, bytes);
58
81
 
59
- if ( ca_is_object_type(parent) && data_type != CA_OBJECT ) {
60
- rb_raise(rb_eRuntimeError, "object array can't be referred by other data type");
82
+ if (ca_is_object_type(parent) && data_type != CA_OBJECT) {
83
+ rb_raise(rb_eRuntimeError,
84
+ "object array can't be referred by other data type");
61
85
  }
62
-
63
- if ( parent->elements && bytes > parent->bytes * parent->elements ) {
86
+ if (parent->elements && bytes > parent_bytes * parent->elements) {
64
87
  rb_raise(rb_eRuntimeError, "bytes exceeds the data size of referent");
65
88
  }
66
-
67
- /* calc datanum and check deformation */
68
- is_deformed = ( ndim == parent->ndim ) ? 0 : 1;
69
- ratio = 1;
70
- elements = 1;
71
- for (i=0; i<ndim; i++) {
72
- elements *= dim[i];
73
- if ( dim[i] != parent->dim[i] ) {
74
- is_deformed |= 1;
75
- }
76
- }
77
- if ( bytes < parent->bytes ) {
78
- if ( parent->bytes % bytes != 0 ) {
79
- rb_raise(rb_eRuntimeError, "bytes of reference array must be a multiple of that of referent");
80
- }
81
- is_deformed = -2;
82
- ratio = parent->bytes / bytes;
89
+ if (bytes < parent_bytes && parent_bytes % bytes != 0) {
90
+ rb_raise(rb_eRuntimeError,
91
+ "bytes of reference array must be a multiple of that of referent");
83
92
  }
84
- else if ( bytes > parent->bytes ) {
85
- if ( bytes % parent->bytes != 0 ) {
86
- rb_raise(rb_eRuntimeError, "bytes of reference array must be a multiple of that of referent");
87
- }
88
- is_deformed = 2;
89
- ratio = bytes / parent->bytes;
93
+ if (bytes > parent_bytes && bytes % parent_bytes != 0) {
94
+ rb_raise(rb_eRuntimeError,
95
+ "bytes of reference array must be a multiple of that of referent");
90
96
  }
91
- if ( offset < 0 ) {
97
+ if (offset < 0) {
92
98
  rb_raise(rb_eRuntimeError, "negative offset is not permitted for CARefer");
93
99
  }
94
-
95
- if ( ( bytes * elements + parent->bytes * offset ) >
96
- ( parent->bytes * parent->elements ) ) {
97
- rb_raise(rb_eRuntimeError, "data size of reference array must not exceed that of referent");
100
+ elements = 1;
101
+ for (i = 0; i < ndim; i++) elements *= dim[i];
102
+ if ((bytes * elements + parent_bytes * offset) >
103
+ (parent_bytes * parent->elements)) {
104
+ rb_raise(rb_eRuntimeError,
105
+ "data size of reference array must not exceed that of referent");
98
106
  }
99
107
 
100
- ca->obj_type = CA_OBJ_REFER;
101
- ca->data_type = data_type;
102
- ca->flags = 0;
103
- ca->ndim = ndim;
104
- ca->bytes = bytes;
105
- ca->elements = elements;
106
- ca->dim = ALLOC_N(ca_size_t, ndim);
107
- ca->ptr = NULL;
108
- ca->mask = NULL;
109
- ca->mask0 = NULL;
110
-
111
- ca->parent = parent;
112
- ca->attach = 0;
113
- ca->nosync = 0;
114
-
115
- ca->is_deformed = (int8_t) is_deformed;
116
- ca->ratio = ratio;
117
- ca->offset = offset;
118
-
119
- if ( ca->offset > 0 && ca->is_deformed == 0 ) {
120
- ca->is_deformed = 1;
108
+ /* strides: row-major contiguous over the view's own dim, in view bytes */
109
+ s = bytes;
110
+ for (i = ndim - 1; i >= 0; i--) {
111
+ strides[i] = s;
112
+ s *= dim[i];
121
113
  }
114
+ /* base_offset is in bytes: `offset` is in parent-element units. */
115
+ base_offset = offset * parent_bytes;
116
+
117
+ /* CAREFUL: initialise mask0 before ca_stride_setup — the setup
118
+ may dispatch to ca_refer_func_create_mask, which writes to
119
+ mask0. Leaving it uninitialised risks freeing a garbage
120
+ pointer during error unwind. */
121
+ ca->mask0 = NULL;
122
122
 
123
- memcpy(ca->dim, dim, ndim * sizeof(ca_size_t));
123
+ ca_stride_setup((CAStride *) ca, CA_OBJ_REFER, parent,
124
+ data_type, bytes, ndim, dim, strides, base_offset);
124
125
 
125
- if ( ca_is_scalar(parent) ) {
126
+ if (ca_is_scalar(parent)) {
126
127
  ca_set_flag(ca, CA_FLAG_SCALAR);
127
128
  }
128
-
129
129
  return 0;
130
130
  }
131
131
 
@@ -134,7 +134,7 @@ ca_refer_new (CArray *parent,
134
134
  int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
135
135
  ca_size_t offset)
136
136
  {
137
- CARefer *ca = ALLOC(CARefer);
137
+ CARefer *ca = (CARefer *) ca_array_alloc(CA_OBJ_REFER, ndim);
138
138
  ca_refer_setup(ca, parent, data_type, ndim, dim, bytes, offset);
139
139
  return ca;
140
140
  }
@@ -143,351 +143,81 @@ static void
143
143
  free_ca_refer (void *ap)
144
144
  {
145
145
  CARefer *ca = (CARefer *) ap;
146
- if ( ca != NULL ) {
146
+ if (ca == NULL) return;
147
+ /* Free the byte-reinterpret intermediate mask, if any. */
148
+ ca_free(ca->mask0);
149
+ /* The rest mirrors free_ca_stride. */
150
+ ca_free(ca->mask);
151
+ if (ca->_pool) {
152
+ ca_array_free(ca);
153
+ } else {
154
+ xfree(ca->strides);
147
155
  xfree(ca->dim);
148
- ca_free(ca->mask);
149
- ca_free(ca->mask0);
150
156
  xfree(ca);
151
157
  }
152
158
  }
153
159
 
154
- /* ------------------------------------------------------------------- */
155
-
156
160
  static void *
157
161
  ca_refer_func_clone (void *ap)
158
162
  {
159
163
  CARefer *ca = (CARefer *) ap;
160
- return ca_refer_new(ca->parent,
161
- ca->data_type, ca->ndim, ca->dim, ca->bytes, ca->offset);
162
- }
163
-
164
- static char *
165
- ca_refer_func_ptr_at_addr (void *ap, ca_size_t addr)
166
- {
167
- CARefer *ca = (CARefer *) ap;
168
- ca_size_t minor;
169
- switch ( ca->is_deformed ) {
170
- case 0:
171
- case 1:
172
- return ca->ptr + ca->bytes * addr;
173
- case -2:
174
- minor = (addr * ca->bytes) % ca->parent->bytes;
175
- return ca->ptr + ca->bytes * addr + minor;
176
- case 2:
177
- return ca->ptr + ca->bytes * (addr * ca->ratio);
178
- default:
179
- rb_raise(rb_eRuntimeError, "[BUG]");
180
- }
181
- }
182
-
183
- static char *
184
- ca_refer_func_ptr_at_index (void *ap, ca_size_t *idx)
185
- {
186
- CARefer *ca = (CARefer*) ap;
187
- ca_size_t *dim = ca->dim;
188
- int8_t i;
189
- ca_size_t n;
190
- n = idx[0]; /* n = idx[0]*dim[1]*dim[2]*...*dim[ndim-1] */
191
- for (i=1; i<ca->ndim; i++) { /* + idx[1]*dim[1]*dim[2]*...*dim[ndim-1] */
192
- n = dim[i]*n+idx[i]; /* ... + idx[ndim-2]*dim[1] + idx[ndim-1] */
193
- }
194
- return ca->ptr + ca->bytes * n;
195
- }
196
-
197
- static void
198
- ca_refer_func_fetch_addr (void *ap, ca_size_t addr, void *ptr)
199
- {
200
- CARefer *ca = (CARefer *) ap;
201
- ca_size_t major, minor;
202
- switch ( ca->is_deformed ) {
203
- case 0:
204
- ca_fetch_addr(ca->parent, addr, ptr);
205
- case 1:
206
- ca_fetch_addr(ca->parent, addr + ca->offset, ptr);
207
- break;
208
- case -2: {
209
- major = (addr * ca->bytes) / ca->parent->bytes;
210
- minor = (addr * ca->bytes) % ca->parent->bytes;
211
- if ( ca->parent->bytes <= 256 ) {
212
- char val[256];
213
- ca_fetch_addr(ca->parent, major + ca->offset, val);
214
- memcpy(ptr, val+minor, ca->bytes);
215
- }
216
- else {
217
- char *val = malloc_with_check(ca->parent->bytes);
218
- ca_fetch_addr(ca->parent, major + ca->offset, val);
219
- memcpy(ptr, val+minor, ca->bytes);
220
- free(val);
221
- }
222
- break;
223
- }
224
- case 2: {
225
- int i;
226
- for (i=0; i<ca->ratio; i++) {
227
- ca_fetch_addr(ca->parent,
228
- addr * ca->ratio + i + ca->offset,
229
- (char *) ptr + i * ca->parent->bytes);
230
- }
231
- break;
232
- }
233
- }
234
- }
235
-
236
- static void
237
- ca_refer_func_fetch_index (void *ap, ca_size_t *idx, void *ptr)
238
- {
239
- CARefer *ca = (CARefer *) ap;
240
- if ( ca->is_deformed ) {
241
- ca_size_t *dim = ca->dim;
242
- int8_t i;
243
- ca_size_t n;
244
- n = idx[0];
245
- for (i=1; i<ca->ndim; i++) {
246
- n = dim[i]*n+idx[i];
247
- }
248
- ca_refer_func_fetch_addr(ca, n, ptr);
249
- }
250
- else {
251
- ca_fetch_index(ca->parent, idx, ptr);
252
- }
253
- }
254
-
255
- static void
256
- ca_refer_func_store_addr (void *ap, ca_size_t addr, void *ptr)
257
- {
258
- CARefer *ca = (CARefer *) ap;
259
- ca_size_t major, minor;
260
- switch ( ca->is_deformed ) {
261
- case 0:
262
- ca_store_addr(ca->parent, addr, ptr);
263
- break;
264
- case 1:
265
- ca_store_addr(ca->parent, addr + ca->offset, ptr);
266
- break;
267
- case -2: {
268
- major = (addr * ca->bytes) / ca->parent->bytes;
269
- minor = (addr * ca->bytes) % ca->parent->bytes;
270
- if ( ca->parent->bytes <= 256 ) {
271
- char val[256];
272
- ca_fetch_addr(ca->parent, major + ca->offset, val);
273
- memcpy(val+minor, ptr, ca->bytes);
274
- ca_store_addr(ca->parent, major + ca->offset, val);
275
- }
276
- else {
277
- char *val = malloc_with_check(ca->parent->bytes);
278
- ca_fetch_addr(ca->parent, major + ca->offset, val);
279
- memcpy(val+minor, ptr, ca->bytes);
280
- ca_store_addr(ca->parent, major + ca->offset, val);
281
- free(val);
282
- }
283
- break;
284
- }
285
- case 2: {
286
- int i;
287
- for (i=0; i<ca->ratio; i++) {
288
- ca_store_addr(ca->parent,
289
- addr * ca->ratio + i + ca->offset,
290
- (char *) ptr + i * ca->parent->bytes);
291
- }
292
- break;
293
- }
294
- }
295
- }
296
-
297
- static void
298
- ca_refer_func_store_index (void *ap, ca_size_t *idx, void *ptr)
299
- {
300
- CARefer *ca = (CARefer *) ap;
301
- if ( ca->is_deformed ) {
302
- ca_size_t *dim = ca->dim;
303
- int8_t i;
304
- ca_size_t n;
305
- n = idx[0];
306
- for (i=1; i<ca->ndim; i++) {
307
- n = dim[i]*n+idx[i];
308
- }
309
- ca_refer_func_store_addr(ca, n, ptr);
310
- }
311
- else {
312
- ca_store_index(ca->parent, idx, ptr);
313
- }
314
- }
315
-
316
- static void
317
- ca_refer_func_allocate (void *ap)
318
- {
319
- CARefer *ca = (CARefer *) ap;
320
- ca_allocate(ca->parent);
321
- ca->ptr = ca->parent->ptr + ca->parent->bytes * ca->offset;
322
- return;
323
- }
324
-
325
- static void
326
- ca_refer_func_attach (void *ap)
327
- {
328
- CARefer *ca = (CARefer *) ap;
329
- ca_attach(ca->parent);
330
- ca->ptr = ca->parent->ptr + ca->parent->bytes * ca->offset;
331
- return;
332
- }
333
-
334
- static void
335
- ca_refer_func_sync (void *ap)
336
- {
337
- CARefer *ca = (CARefer *) ap;
338
- ca_sync(ca->parent);
339
- return;
340
- }
341
-
342
- static void
343
- ca_refer_func_detach (void *ap)
344
- {
345
- CARefer *ca = (CARefer *) ap;
346
- ca->ptr = NULL;
347
- ca_detach(ca->parent);
348
- return;
349
- }
350
-
351
- static void
352
- ca_refer_func_copy_data (void *ap, void *ptr)
353
- {
354
- CARefer *ca = (CARefer *) ap;
355
- if ( ptr != ca->ptr ) {
356
- ca_attach(ca->parent);
357
- memmove(ptr,
358
- ca->parent->ptr + ca->parent->bytes * ca->offset,
359
- ca_length(ca));
360
- ca_detach(ca->parent);
361
- }
362
- }
363
-
364
- static void
365
- ca_refer_func_sync_data (void *ap, void *ptr)
366
- {
367
- CARefer *ca = (CARefer *) ap;
368
- if ( ptr != ca->ptr ) {
369
- ca_allocate(ca->parent);
370
- memmove(ca->parent->ptr + ca->parent->bytes * ca->offset,
371
- ptr,
372
- ca_length(ca));
373
- ca_sync(ca->parent);
374
- ca_detach(ca->parent);
375
- }
376
- }
377
-
378
- #define proc_fill_bang_fixlen() \
379
- { \
380
- ca_size_t i; \
381
- ca_size_t bytes = ca->bytes; \
382
- char *p = ca->parent->ptr + ca->parent->bytes * ca->offset; \
383
- for (i=ca->elements; i; i--, p+=bytes) { \
384
- memcpy(p, val, bytes); \
385
- } \
386
- }
387
-
388
- #define proc_fill_bang(type) \
389
- { \
390
- ca_size_t i; \
391
- type *p = (type *)(ca->parent->ptr + ca->parent->bytes * ca->offset); \
392
- type v = *(type *)val; \
393
- for (i=ca->elements; i; i--, p++) { \
394
- *p = v; \
395
- } \
396
- }
397
-
398
- static void
399
- ca_refer_func_fill_data (void *ap, void *val)
400
- {
401
- CARefer *ca = (CARefer *) ap;
402
-
403
- ca_allocate(ca->parent);
404
-
405
- switch ( ca->data_type ) {
406
- case CA_FIXLEN: proc_fill_bang_fixlen(); break;
407
- case CA_BOOLEAN:
408
- case CA_INT8:
409
- case CA_UINT8: proc_fill_bang(int8_t); break;
410
- case CA_INT16:
411
- case CA_UINT16: proc_fill_bang(int16_t); break;
412
- case CA_INT32:
413
- case CA_UINT32:
414
- case CA_FLOAT32: proc_fill_bang(int32_t); break;
415
- case CA_INT64:
416
- case CA_UINT64:
417
- case CA_FLOAT64: proc_fill_bang(float64_t); break;
418
- case CA_FLOAT128: proc_fill_bang(float128_t); break;
419
- #ifdef HAVE_COMPLEX_H
420
- case CA_CMPLX64: proc_fill_bang(cmplx64_t); break;
421
- case CA_CMPLX128: proc_fill_bang(cmplx128_t); break;
422
- case CA_CMPLX256: proc_fill_bang(cmplx256_t); break;
423
- #endif
424
- case CA_OBJECT: proc_fill_bang(VALUE); break;
425
- default: rb_bug("array has an unknown data type");
426
- }
427
- ca_sync(ca->parent);
428
- ca_detach(ca->parent);
164
+ return ca_refer_new(ca->parent, ca->data_type, ca->ndim, ca->dim,
165
+ ca->bytes, ca->base_offset / ca->parent->bytes);
429
166
  }
430
167
 
431
168
  static void
432
169
  ca_refer_func_create_mask (void *ap)
433
170
  {
434
171
  CARefer *ca = (CARefer *) ap;
172
+ ca_size_t parent_bytes = ca->parent->bytes;
173
+ ca_size_t parent_offset;
435
174
 
436
175
  ca_update_mask(ca->parent);
437
- if ( ! ca->parent->mask ) {
176
+ if (! ca->parent->mask) {
438
177
  ca_create_mask(ca->parent);
439
178
  }
440
179
 
441
- if ( ca->bytes == ca->parent->bytes ) {
180
+ parent_offset = ca->base_offset / parent_bytes;
181
+
182
+ if (ca->bytes == parent_bytes) {
183
+ /* Same-width reinterpret / reshape. Mask is a CARefer over
184
+ the parent's mask with the same logical shape and offset. */
442
185
  ca->mask =
443
186
  (CArray *) ca_refer_new(ca->parent->mask,
444
- CA_BOOLEAN, ca->ndim, ca->dim, 0, ca->offset);
445
- }
446
- else if ( ca->is_deformed == -2 ) {
187
+ CA_BOOLEAN, ca->ndim, ca->dim, 0, parent_offset);
188
+ }
189
+ else if (ca->bytes < parent_bytes) {
190
+ /* Divided reinterpret: one parent element splits into
191
+ ratio = parent_bytes / bytes view elements. Build a
192
+ CARepeat that broadcasts each parent mask bit across the
193
+ ratio sub-positions, then refer-reshape it to the view's
194
+ actual shape. */
195
+ ca_size_t ratio = parent_bytes / ca->bytes;
447
196
  ca_size_t count[CA_RANK_MAX];
448
- int i;
449
- for (i=0; i<ca->parent->ndim; i++) {
450
- count[i] = 0;
451
- }
452
- count[ca->parent->ndim] = ca->ratio;
453
- ca->mask0 =
454
- (CArray *) ca_repeat_new(ca->parent->mask, ca->parent->ndim+1, count);
197
+ int8_t i;
198
+ for (i = 0; i < ca->parent->ndim; i++) count[i] = 0;
199
+ count[ca->parent->ndim] = ratio;
200
+ ca->mask0 =
201
+ (CArray *) ca_repeat_new(ca->parent->mask, ca->parent->ndim + 1, count);
455
202
  ca_unset_flag(ca->mask0, CA_FLAG_READ_ONLY);
456
-
457
- ca->mask =
458
- (CArray *) ca_refer_new(ca->mask0,
459
- CA_BOOLEAN, ca->ndim, ca->dim, 0, ca->offset);
203
+ ca->mask =
204
+ (CArray *) ca_refer_new(ca->mask0,
205
+ CA_BOOLEAN, ca->ndim, ca->dim, 0, parent_offset);
460
206
  }
461
- else if ( ca->is_deformed == 2 ) {
462
- /* TODO */
463
- ca->mask0 =
464
- (CArray *) ca_reduce_new(ca->parent->mask, ca->ratio, ca->offset);
465
- ca->mask =
466
- (CArray *) ca_refer_new(ca->mask0, CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
207
+ else {
208
+ /* Spanned reinterpret: ratio = bytes / parent_bytes parent
209
+ elements fold into one view element. Build a CAReduce that
210
+ OR-reduces the ratio adjacent parent mask bits into one
211
+ mask bit, then refer-reshape to the view's shape. */
212
+ ca_size_t ratio = ca->bytes / parent_bytes;
213
+ ca->mask0 =
214
+ (CArray *) ca_reduce_new(ca->parent->mask, ratio, parent_offset);
215
+ ca->mask =
216
+ (CArray *) ca_refer_new(ca->mask0,
217
+ CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
467
218
  }
468
219
  }
469
220
 
470
- ca_operation_function_t ca_refer_func = {
471
- CA_OBJ_REFER,
472
- CA_VIRTUAL_ARRAY,
473
- free_ca_refer,
474
- ca_refer_func_clone,
475
- ca_refer_func_ptr_at_addr,
476
- ca_refer_func_ptr_at_index,
477
- ca_refer_func_fetch_addr,
478
- ca_refer_func_fetch_index,
479
- ca_refer_func_store_addr,
480
- ca_refer_func_store_index,
481
- ca_refer_func_allocate,
482
- ca_refer_func_attach,
483
- ca_refer_func_sync,
484
- ca_refer_func_detach,
485
- ca_refer_func_copy_data,
486
- ca_refer_func_sync_data,
487
- ca_refer_func_fill_data,
488
- ca_refer_func_create_mask,
489
- };
490
-
491
221
  /* ------------------------------------------------------------------- */
492
222
 
493
223
  static VALUE
@@ -501,31 +231,175 @@ static VALUE
501
231
  rb_ca_refer_initialize_copy (VALUE self, VALUE other)
502
232
  {
503
233
  CARefer *ca, *cs;
504
-
505
234
  TypedData_Get_Struct(self, CARefer, &carefer_data_type, ca);
506
235
  TypedData_Get_Struct(other, CARefer, &carefer_data_type, cs);
507
-
236
+ if ( ca_func[CA_OBJ_REFER].pool_init ) {
237
+ ca_array_pool_alloc(ca, CA_OBJ_REFER, cs->ndim);
238
+ }
239
+ /* CAREFUL: rebuild through ca_refer_setup's (data_type, ndim,
240
+ dim, bytes, offset) form. The CAStride (strides, base_offset)
241
+ form would lose the parent-element offset semantics on
242
+ unusual mod-bytes alignments. */
508
243
  ca_refer_setup(ca, cs->parent, cs->data_type, cs->ndim, cs->dim,
509
- cs->bytes, cs->offset);
510
-
244
+ cs->bytes, cs->base_offset / cs->parent->bytes);
511
245
  return self;
512
246
  }
513
247
 
514
- /* yard:
515
- class CArray
516
- # call-seq:
517
- # CArray.refer()
518
- # CArray.refer(data_type, dim[, :bytes=>bytes, :offset=>offset])
519
- # CArray.refer(data_class, dim)
520
- #
521
- # Returns CARefer object which refers self.
522
- # In second form, `data_type` can be different data_type of self,
523
- # as long as the total byte length of new array is smaller than
524
- # that of self.
525
- def refer (*argv)
526
- end
527
- end
528
- */
248
+ /* Reshape-stride rewrite.
249
+ *
250
+ * Try to express `parent` reshaped to `new_dim` as a CAStride over
251
+ * the deepest non-CAStride ancestor (returned in *out_root) with
252
+ * explicit strides + base_offset in that root's byte coord. Used
253
+ * by rb_ca_reshape and rb_ca_flatten before falling back to
254
+ * ca_refer_new.
255
+ *
256
+ * Pre-conditions (contract from the callers):
257
+ * - product of new_dim == parent->elements
258
+ * - bytes (== parent->bytes) and data_type (== parent->data_type)
259
+ * unchanged, offset == 0 implicit
260
+ *
261
+ * Returns 1 on success with *out_root, out_strides[0..new_ndim-1]
262
+ * and *out_base filled. The caller then constructs
263
+ * ca_stride_new(CA_OBJ_STRIDE, *out_root, ..., out_strides, *out_base);
264
+ * the CAStride's parent is *out_root (not the immediate caller
265
+ * parent), which lets compose-fold treat the whole reshape as a
266
+ * single-step gather from the entity.
267
+ *
268
+ * Returns 0 on failure: the caller must fall back to ca_refer_new.
269
+ *
270
+ * Algorithm:
271
+ * 1. Resolve parent into (root, root_strides, root_base) via
272
+ * ca_stride_compose_to_root for the CAStride family, or
273
+ * row-major derivation for a plain CArray entity. Other
274
+ * obj_types fail immediately.
275
+ * 2. Match ranges of parent axes to new axes so element products
276
+ * agree. Inside each matched range, root_strides must be
277
+ * inter-axis contiguous. */
278
+ static int
279
+ ca_reshape_try_strides (CArray *parent,
280
+ const ca_size_t *new_dim,
281
+ int8_t new_ndim,
282
+ CArray **out_root,
283
+ ca_size_t *out_strides,
284
+ ca_size_t *out_base)
285
+ {
286
+ ca_size_t pstrides_buf[CA_RANK_MAX];
287
+ ca_size_t pstrides_composed[CA_RANK_MAX];
288
+ const ca_size_t *pstrides;
289
+ ca_size_t pbase;
290
+ ca_size_t bytes = parent->bytes;
291
+ int8_t pndim = parent->ndim;
292
+ int8_t k;
293
+ CArray *root;
294
+
295
+ /* Resolve parent into (root, pstrides, pbase) in root's byte coord. */
296
+ if (ca_func[parent->obj_type].attach == ca_stride_func.attach) {
297
+ /* CAStride family: fold the parent's own view through its
298
+ ancestor chain, producing strides + base in the deepest
299
+ non-CAStride ancestor's coord. */
300
+ ca_stride_compose_to_root((CAStride *) parent,
301
+ &root, pstrides_composed, &pbase);
302
+ pstrides = pstrides_composed;
303
+ } else if (parent->obj_type == CA_OBJ_ARRAY
304
+ || parent->obj_type == CA_OBJ_ARRAY_WRAP
305
+ || parent->obj_type == CA_OBJ_SCALAR) {
306
+ /* Plain CArray entity: row-major contig, base 0. */
307
+ ca_size_t s = bytes;
308
+ for (k = pndim - 1; k >= 0; k--) {
309
+ pstrides_buf[k] = s;
310
+ s *= parent->dim[k];
311
+ }
312
+ pstrides = pstrides_buf;
313
+ pbase = 0;
314
+ root = parent;
315
+ (void) pstrides_composed;
316
+ } else {
317
+ /* CASelect / CAReduce / CAGrid / CAObject / CAField etc. — no usable
318
+ strides representation for reshape rewrite. */
319
+ return 0;
320
+ }
321
+
322
+ *out_root = root;
323
+
324
+ /* Zero-element corner case: nothing to gather; trivial reshape. */
325
+ if (parent->elements == 0) {
326
+ for (k = 0; k < new_ndim; k++) out_strides[k] = 0;
327
+ *out_base = pbase;
328
+ return 1;
329
+ }
330
+
331
+ /* Scalar reshape (new_ndim == 0) only valid if elements == 1 — but
332
+ CArray's reshape rejects argc==0 earlier; defensive return for safety. */
333
+ if (new_ndim == 0) {
334
+ *out_base = pbase;
335
+ return parent->elements == 1 ? 1 : 0;
336
+ }
337
+
338
+ /* Match ranges outer-to-inner. Skip dim==1 axes on either side
339
+ (they contribute no displacement; we'll assign stride 0 to dim==1
340
+ new axes after matching). */
341
+ int8_t oi = 0, ni = 0;
342
+
343
+ while (oi < pndim && ni < new_ndim) {
344
+ /* Skip leading dim==1 new axes (no parent axis consumed) */
345
+ if (new_dim[ni] == 1) {
346
+ out_strides[ni] = 0;
347
+ ni++;
348
+ continue;
349
+ }
350
+ /* Skip leading dim==1 parent axes (no contribution) */
351
+ if (parent->dim[oi] == 1) {
352
+ oi++;
353
+ continue;
354
+ }
355
+
356
+ int8_t oj = oi + 1;
357
+ int8_t nj = ni + 1;
358
+ ca_size_t old_prod = parent->dim[oi];
359
+ ca_size_t new_prod = new_dim[ni];
360
+
361
+ while (old_prod != new_prod) {
362
+ if (old_prod < new_prod) {
363
+ /* Need to extend old range; require inter-axis contig */
364
+ if (oj >= pndim) return 0;
365
+ if (parent->dim[oj] == 0) return 0; /* shouldn't happen */
366
+ if (pstrides[oj - 1] != pstrides[oj] * parent->dim[oj]) return 0;
367
+ old_prod *= parent->dim[oj];
368
+ oj++;
369
+ } else {
370
+ if (nj >= new_ndim) return 0;
371
+ if (new_dim[nj] == 0) return 0;
372
+ new_prod *= new_dim[nj];
373
+ nj++;
374
+ }
375
+ }
376
+
377
+ /* Range matched: assign strides to new axes [ni..nj).
378
+ Innermost gets parent's innermost stride in the matched old range.
379
+ Outer new axes scale by following new_dim. */
380
+ out_strides[nj - 1] = pstrides[oj - 1];
381
+ for (k = nj - 2; k >= ni; k--) {
382
+ out_strides[k] = out_strides[k + 1] * new_dim[k + 1];
383
+ }
384
+
385
+ oi = oj;
386
+ ni = nj;
387
+ }
388
+
389
+ /* Trailing dim==1 axes in either side */
390
+ while (ni < new_ndim) {
391
+ if (new_dim[ni] != 1) return 0;
392
+ out_strides[ni] = 0;
393
+ ni++;
394
+ }
395
+ while (oi < pndim) {
396
+ if (parent->dim[oi] != 1) return 0;
397
+ oi++;
398
+ }
399
+
400
+ *out_base = pbase;
401
+ return 1;
402
+ }
529
403
 
530
404
  static VALUE
531
405
  rb_ca_refer (int argc, VALUE *argv, VALUE self)
@@ -541,85 +415,66 @@ rb_ca_refer (int argc, VALUE *argv, VALUE self)
541
415
 
542
416
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
543
417
 
544
- if ( argc == 0 ) { /* CArray#refer() */
418
+ if (argc == 0) {
545
419
  data_type = ca->data_type;
546
420
  bytes = ca->bytes;
547
421
  ndim = ca->ndim;
548
- for (i=0; i<ndim; i++) {
549
- dim[i] = ca->dim[i];
550
- }
551
- cr = ca_refer_new((CArray*)ca, data_type, ndim, dim, bytes, offset);
422
+ for (i = 0; i < ndim; i++) dim[i] = ca->dim[i];
423
+ cr = ca_refer_new((CArray *) ca, data_type, ndim, dim, bytes, offset);
552
424
  obj = ca_wrap_struct(cr);
553
425
  rb_ca_set_parent(obj, self);
554
- rb_ca_data_type_inherit(obj, self);
555
426
  }
556
427
  else {
557
428
  volatile VALUE rtype, rdim, ropt, rbytes = Qnil, roffset = Qnil;
558
-
559
429
  ropt = rb_pop_options(&argc, &argv);
560
430
  rb_scan_args(argc, argv, "11", (VALUE *) &rtype, (VALUE *) &rdim);
561
431
  rb_scan_options(ropt, "bytes,offset", &rbytes, &roffset);
562
-
563
- if ( NIL_P(rbytes) ) {
564
- rbytes = rb_ca_bytes(self);
565
- }
566
-
432
+ if (NIL_P(rbytes)) rbytes = rb_ca_bytes(self);
567
433
  rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
568
-
569
- if ( NIL_P(rdim) ) {
570
- if ( ca->bytes != bytes ) {
571
- rb_raise(rb_eRuntimeError,
434
+ if (NIL_P(rdim)) {
435
+ if (ca->bytes != bytes) {
436
+ rb_raise(rb_eRuntimeError,
572
437
  "specify dimension shape for different byte size");
573
- }
574
- else {
438
+ } else {
575
439
  rdim = rb_ca_dim(self);
576
440
  }
577
441
  }
578
-
579
442
  Check_Type(rdim, T_ARRAY);
580
443
  ndim = RARRAY_LEN(rdim);
581
-
582
- for (i=0; i<ndim; i++) {
583
- dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
584
- }
585
-
586
- if ( ! NIL_P(roffset) ) {
587
- offset = NUM2SIZE(roffset);
588
- }
589
-
590
- cr = ca_refer_new((CArray*)ca, data_type, ndim, dim, bytes, offset);
444
+ for (i = 0; i < ndim; i++) dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
445
+ if (! NIL_P(roffset)) offset = NUM2SIZE(roffset);
446
+ cr = ca_refer_new((CArray *) ca, data_type, ndim, dim, bytes, offset);
591
447
  obj = ca_wrap_struct(cr);
592
448
  rb_ca_set_parent(obj, self);
593
- rb_ca_data_type_import(obj, rtype);
449
+ /* When rtype is a data_class, wrap the result in CARecord so
450
+ the data_class is carried even if self is not itself a Face. */
451
+ if ( rb_obj_is_data_class(rtype) ) {
452
+ obj = rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
453
+ rb_intern("wrap"), 2, obj, rtype);
454
+ return obj;
455
+ }
594
456
  }
595
-
457
+ CA_WRAPPER_LIFT(obj, self, ca);
596
458
  return obj;
597
459
  }
598
460
 
599
- /* api: rb_ca_refer_new
600
- */
601
-
602
461
  VALUE
603
462
  rb_ca_refer_new (VALUE self,
604
463
  int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
605
464
  ca_size_t offset)
606
465
  {
607
466
  volatile VALUE list, rdim, ropt;
608
- CArray *ca;
609
467
  int8_t i;
610
468
 
611
- TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
612
-
613
469
  rdim = rb_ary_new2(ndim);
614
- for (i=0; i<ndim; i++) {
470
+ for (i = 0; i < ndim; i++) {
615
471
  rb_ary_store(rdim, i, SIZE2NUM(dim[i]));
616
472
  }
617
473
 
618
474
  list = rb_ary_new2(3);
619
- if ( data_type == CA_FIXLEN && rb_ca_has_data_class(self) ) {
475
+ if (data_type == CA_FIXLEN && rb_ca_has_data_class(self)) {
620
476
  rb_ary_store(list, 0, rb_ca_data_class(self));
621
- }
622
- else {
477
+ } else {
623
478
  rb_ary_store(list, 0, INT2NUM(data_type));
624
479
  }
625
480
  rb_ary_store(list, 1, rdim);
@@ -627,21 +482,300 @@ rb_ca_refer_new (VALUE self,
627
482
  rb_set_options(ropt, "bytes,offset", SIZE2NUM(bytes), SIZE2NUM(offset));
628
483
  rb_ary_store(list, 2, ropt);
629
484
 
630
- return rb_ca_refer(3, RARRAY_PTR(list), self);
485
+ {
486
+ volatile VALUE obj = rb_ca_refer(3, (VALUE *) RARRAY_CONST_PTR(list), self);
487
+ CArray *co;
488
+
489
+ /* CAREFUL: this is the internal builder -- some fifteen call sites want
490
+ the refer itself, not a wrapper on top of it. The public `refer` it
491
+ delegates to lifts a CALazyMarker, so strip that here.
492
+
493
+ Two things go wrong otherwise. rb_ca_value_array strips the mask off
494
+ what it gets back and marks the level it is handed; with a marker in
495
+ the way the refer underneath keeps its mask and never gets
496
+ CA_FLAG_VALUE_ARRAY, so the values read back as UNDEF. And builders
497
+ that stack further views on the result -- fancy indexing goes refer,
498
+ grid, refer -- end up with a marker buried in the middle of the
499
+ chain, which is the redundant-middle-wrapper that CAFace.md section
500
+ 8.3 exists to prevent.
501
+
502
+ Faces stay lifted: rb_ca_value_array depends on that and says so
503
+ where it marks the storage level. */
504
+ TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
505
+ if ( ca_is_lazy_marker(co) ) {
506
+ obj = rb_ca_parent(obj);
507
+ }
508
+ return obj;
509
+ }
631
510
  }
632
511
 
512
+ /* CArray#reshape(*newdim) — returns a view of self with the new
513
+ shape (a CAStride when ca_reshape_try_strides succeeds, otherwise
514
+ a CARefer). Each element of `newdim` is either:
515
+ - Integer : the new size for that axis
516
+ - nil : copy from the source. Axes left of the auto-infer
517
+ placeholder use ca->dim[i] in position order; axes
518
+ to its right use ca->dim[ca->ndim - (argc - i)] so
519
+ trailing nils mirror trailing source axes.
520
+ - -1 / `:~` : one axis inferred from elements / (product of the
521
+ others). At most one placeholder is allowed.
522
+
523
+ Also exported (declared in carray.h) so downstream C extensions
524
+ can build a reshape view directly:
525
+
526
+ VALUE args[] = {INT2NUM(3), INT2NUM(2)};
527
+ VALUE view = rb_ca_reshape(2, args, ca);
528
+
529
+ For typed-dim usage (bypassing the placeholder vocabulary) call
530
+ rb_ca_refer_new(self, ca->data_type, ndim, dim, ca->bytes, 0). */
531
+ VALUE
532
+ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
533
+ {
534
+ CArray *ca;
535
+ CARefer *cr;
536
+ ca_size_t new_dim[CA_RANK_MAX];
537
+ ca_size_t prod = 1;
538
+ int placeholder_idx = -1; /* axis with `-1` or `:~` infer placeholder */
539
+ int i;
540
+ volatile VALUE obj;
541
+ VALUE sym_tilde = ID2SYM(rb_intern("~")); /* :~ = infer-placeholder alias for -1 */
633
542
 
634
- void
635
- Init_ca_obj_refer ()
543
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
544
+
545
+ if (argc < 0 || argc > CA_RANK_MAX) {
546
+ rb_raise(rb_eArgError, "reshape: invalid number of dims (%d)", argc);
547
+ }
548
+
549
+ /* Locate the (at most one) auto-infer placeholder. `-1` is the
550
+ conventional spelling; `:~` is the unified auto-fill sigil
551
+ (same meaning). */
552
+ for (i = 0; i < argc; i++) {
553
+ if ( (FIXNUM_P(argv[i]) && FIX2LONG(argv[i]) == -1)
554
+ || argv[i] == sym_tilde ) {
555
+ if (placeholder_idx >= 0) {
556
+ rb_raise(rb_eRuntimeError,
557
+ "reshape: only one auto-infer placeholder (-1 / :~) allowed");
558
+ }
559
+ placeholder_idx = i;
560
+ }
561
+ }
562
+
563
+ /* Resolve every non-placeholder axis. */
564
+ for (i = 0; i < argc; i++) {
565
+ if (i == placeholder_idx) continue;
566
+ if (NIL_P(argv[i])) {
567
+ /* Two-sweep nil resolution:
568
+ - With a placeholder: forward-map before it, mirror from
569
+ the end after.
570
+ - Without a placeholder: forward-map while in range,
571
+ otherwise mirror from the end so trailing nils pick up
572
+ the tail source axes (e.g. b.ndim=1, b.reshape(1, nil)
573
+ -> (1, 3)). */
574
+ int src;
575
+ if (placeholder_idx >= 0) {
576
+ src = (i < placeholder_idx) ? i : ca->ndim - (argc - i);
577
+ } else {
578
+ src = (i < ca->ndim) ? i : ca->ndim - (argc - i);
579
+ }
580
+ if (src < 0 || src >= ca->ndim) {
581
+ rb_raise(rb_eRuntimeError,
582
+ "reshape: nil at axis %d has no source dim", i);
583
+ }
584
+ new_dim[i] = ca->dim[src];
585
+ }
586
+ else {
587
+ new_dim[i] = NUM2SIZE(argv[i]);
588
+ }
589
+ prod *= new_dim[i];
590
+ }
591
+
592
+ /* Resolve placeholder dim from the leftover total. */
593
+ if (placeholder_idx >= 0) {
594
+ if (prod == 0 || ca->elements % prod != 0) {
595
+ rb_raise(rb_eRuntimeError,
596
+ "reshape: cannot infer dim for `-1` placeholder");
597
+ }
598
+ new_dim[placeholder_idx] = ca->elements / prod;
599
+ }
600
+ else {
601
+ /* CAREFUL: strict element conservation. Without a placeholder
602
+ the resolved product must equal the source element count.
603
+ A smaller shape would silently truncate data (a CARefer over
604
+ a subset), and on non-contiguous parents the compose-fold
605
+ path corrupts data outright — hence the raise. */
606
+ if (prod != ca->elements) {
607
+ rb_raise(rb_eRuntimeError,
608
+ "reshape: cannot reshape array of %lld elements into a shape "
609
+ "of %lld elements (use -1 / :~ to infer a dim)",
610
+ (long long) ca->elements, (long long) prod);
611
+ }
612
+ }
613
+
614
+ /* Try the stride rewrite first. On success, construct a
615
+ CAStride directly over the deepest non-CAStride ancestor
616
+ (out_root) with composed strides + base in that root's byte
617
+ coord. The Ruby-level parent ref is still `self`, so the
618
+ immediate parent stays alive through GC. On failure, fall
619
+ through to the CARefer path. */
620
+ {
621
+ CArray *out_root;
622
+ ca_size_t out_strides[CA_RANK_MAX];
623
+ ca_size_t out_base;
624
+ if (ca_reshape_try_strides(ca, new_dim, (int8_t) argc,
625
+ &out_root, out_strides, &out_base)) {
626
+ CAStride *cs = ca_stride_new(CA_OBJ_STRIDE, out_root,
627
+ ca->data_type, ca->bytes,
628
+ (int8_t) argc, new_dim,
629
+ out_strides, out_base);
630
+ obj = ca_wrap_struct(cs);
631
+ rb_ca_set_parent(obj, self);
632
+ CA_WRAPPER_LIFT(obj, self, ca);
633
+ return obj;
634
+ }
635
+ }
636
+
637
+ cr = ca_refer_new(ca, ca->data_type, (int8_t) argc,
638
+ new_dim, ca->bytes, 0);
639
+ obj = ca_wrap_struct(cr);
640
+ rb_ca_set_parent(obj, self);
641
+ CA_WRAPPER_LIFT(obj, self, ca);
642
+ return obj;
643
+ }
644
+
645
+ /* CArray#flatten — a 1-D view of all elements in row-major order
646
+ (a CAStride when ca_reshape_try_strides succeeds, otherwise a
647
+ CARefer). Also exported (declared in carray.h). */
648
+ VALUE
649
+ rb_ca_flatten (VALUE self)
636
650
  {
637
- /* rb_cCARefer, CA_OBJ_REFER are defined in ruby_carray.c */
651
+ CArray *ca;
652
+ CARefer *cr;
653
+ ca_size_t dim[1];
654
+ volatile VALUE obj;
638
655
 
639
- rb_define_const(rb_cObject, "CA_OBJ_REFER", INT2NUM(CA_OBJ_REFER));
656
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
657
+ dim[0] = ca->elements;
658
+
659
+ {
660
+ CArray *out_root;
661
+ ca_size_t out_strides[1];
662
+ ca_size_t out_base;
663
+ if (ca_reshape_try_strides(ca, dim, 1, &out_root, out_strides, &out_base)) {
664
+ CAStride *cs = ca_stride_new(CA_OBJ_STRIDE, out_root,
665
+ ca->data_type, ca->bytes,
666
+ 1, dim, out_strides, out_base);
667
+ obj = ca_wrap_struct(cs);
668
+ rb_ca_set_parent(obj, self);
669
+ CA_WRAPPER_LIFT(obj, self, ca);
670
+ return obj;
671
+ }
672
+ }
640
673
 
641
- rb_define_method(rb_cCArray, "refer", rb_ca_refer, -1);
674
+ cr = ca_refer_new(ca, ca->data_type, 1, dim, ca->bytes, 0);
675
+ obj = ca_wrap_struct(cr);
676
+ rb_ca_set_parent(obj, self);
677
+ CA_WRAPPER_LIFT(obj, self, ca);
678
+ return obj;
679
+ }
642
680
 
681
+ /* The bare size-1 insertion primitive, in the SOURCE frame: each position
682
+ names the existing axis the new axis goes *before* (ndim = append at the
683
+ end; negatives count from the end gap). A position given more than once
684
+ stacks several length-1 axes before that source axis. Positions do not
685
+ shift as other axes are inserted.
686
+
687
+ a = CArray.int32(2, 3) # shape [2, 3]
688
+ insert before axis 0 -> [1, 2, 3]
689
+ insert before axis 2 (= -1, end) -> [2, 3, 1]
690
+ before axis 0 and the end -> [1, 2, 3, 1]
691
+ before axis 0 twice -> [1, 1, 2, 3]
692
+
693
+ Returns a CARefer view (zero-copy alias to +self+'s data, via reshape).
694
+ Bound to the internal name __insert_axis_size1__; the user-facing
695
+ insert_axis (with the repeat: keyword) is the Ruby method in
696
+ lib/carray/basics.rb, which builds on this primitive.
697
+
698
+ Non-static so external CIFY consumers (= carray_order.c,
699
+ carray_median_percentile.c) can call directly; they pass a single axis,
700
+ for which the source and output frames coincide. */
701
+ VALUE
702
+ rb_ca_insert_axis (int argc, VALUE *argv, VALUE self)
703
+ {
704
+ CArray *ca;
705
+ VALUE new_argv[CA_RANK_MAX];
706
+ int gap_count[CA_RANK_MAX + 1];
707
+ int ndim, new_ndim, ngap;
708
+ int i, c, k;
709
+
710
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
711
+
712
+ ndim = (int) ca->ndim;
713
+ new_ndim = ndim + argc;
714
+ if (new_ndim > CA_RANK_MAX) {
715
+ rb_raise(rb_eArgError,
716
+ "insert_axis: resulting ndim %d exceeds CA_RANK_MAX %d",
717
+ new_ndim, CA_RANK_MAX);
718
+ }
719
+
720
+ ngap = ndim + 1; /* gaps live in [0, ndim] (ndim = the end gap) */
721
+
722
+ /* Tally how many new axes go before each source axis (gap). Negative
723
+ positions count from the end gap; duplicates are allowed (stacking). */
724
+ for (i = 0; i <= ndim; i++) {
725
+ gap_count[i] = 0;
726
+ }
727
+ for (i = 0; i < argc; i++) {
728
+ int raw = NUM2INT(argv[i]);
729
+ int g = (raw < 0) ? raw + ngap : raw;
730
+ if (g < 0 || g >= ngap) {
731
+ rb_raise(rb_eArgError,
732
+ "insert_axis: axis %d out of range for ndim %d", raw, ndim);
733
+ }
734
+ gap_count[g]++;
735
+ }
736
+
737
+ /* Build the output dim list: before each source axis emit its tally of
738
+ length-1 axes, then the source dim; finally the end-gap tally. */
739
+ k = 0;
740
+ for (i = 0; i < ndim; i++) {
741
+ for (c = 0; c < gap_count[i]; c++) {
742
+ new_argv[k++] = INT2NUM(1);
743
+ }
744
+ new_argv[k++] = SIZE2NUM(ca->dim[i]);
745
+ }
746
+ for (c = 0; c < gap_count[ndim]; c++) {
747
+ new_argv[k++] = INT2NUM(1);
748
+ }
749
+
750
+ return rb_ca_reshape(new_ndim, new_argv, self);
751
+ }
752
+
753
+ void
754
+ Init_ca_obj_refer (void)
755
+ {
756
+ /* rb_cCARefer, CA_OBJ_REFER are defined in ruby_carray.c /
757
+ carray_core.c. Build the custom op table and override the
758
+ baseline registration installed by Init_carray_core. */
759
+ ca_refer_func = ca_stride_func;
760
+ ca_refer_func.free_object = free_ca_refer;
761
+ ca_refer_func.clone = ca_refer_func_clone;
762
+ ca_refer_func.create_mask = ca_refer_func_create_mask;
763
+ /* CARefer's struct is larger than CAStride (adds mask0); inherit
764
+ CAStride's pool_bytes / pool_init (dim + strides) but override
765
+ struct_size so ca_array_alloc reserves the right amount. */
766
+ ca_refer_func.struct_size = sizeof(CARefer);
767
+ ca_func[CA_OBJ_REFER] = ca_refer_func;
768
+
769
+ rb_define_const(rb_cObject, "CA_OBJ_REFER", INT2NUM(CA_OBJ_REFER));
770
+
771
+ rb_define_method(rb_cCArray, "refer", rb_ca_refer, -1);
772
+ rb_define_method(rb_cCArray, "reshape", rb_ca_reshape, -1);
773
+ rb_define_method(rb_cCArray, "flatten", rb_ca_flatten, 0);
774
+ /* The bare size-1 primitive. The user-facing `insert_axis` (with its
775
+ `repeat:` keyword) is the Ruby method in lib/carray/basics.rb, which
776
+ owns the name and calls this primitive. */
777
+ rb_define_method(rb_cCArray, "__insert_axis_size1__", rb_ca_insert_axis, -1);
643
778
  rb_define_alloc_func(rb_cCARefer, rb_ca_refer_s_allocate);
644
779
  rb_define_method(rb_cCARefer, "initialize_copy",
645
- rb_ca_refer_initialize_copy, 1);
780
+ rb_ca_refer_initialize_copy, 1);
646
781
  }
647
-