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_shift.c CHANGED
@@ -1,59 +1,60 @@
1
1
  /* ---------------------------------------------------------------------------
2
2
 
3
- ca_obj_shift.c
4
-
5
- This file is part of Ruby/CArray extension library.
6
-
7
- Copyright (C) 2005-2020 Hiroki Motoyoshi
3
+ CAShift is a pure typedef of CAWindow (see carray.h). CAShift
4
+ construction maps (shift[], roll[], fill, fill_mask) onto CAWindow's
5
+ (start = -shift, count = parent->dim, bounds = roll ? PERIODIC :
6
+ (fill_mask ? MASK : FILL), fill) via ca_window_setup, then bumps
7
+ obj_type to CA_OBJ_SHIFT. Operations (attach / sync / copy_data /
8
+ sync_data / fill_data / ptr_at_* / fetch_index / store_index) are
9
+ shared with CAWindow's per-axis bounds engine via the `ca_shift_func`
10
+ table, which is built by copying `ca_window_func` and only overriding
11
+ free / clone / create_mask so that CAShift-typed instances are produced
12
+ on cloning and mask-projection.
13
+
14
+ User surface (CArray#shift) is documented in yard-stubs/ca_obj_shift.rb.
8
15
 
9
16
  ---------------------------------------------------------------------------- */
10
17
 
11
18
  #include "carray.h"
19
+ #include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE */
12
20
 
13
- /* yard:
14
- class CAShift < CAVirtual # :nodoc:
15
- end
16
- */
17
-
18
- typedef struct {
19
- int16_t obj_type;
20
- int8_t data_type;
21
- int8_t ndim;
22
- int32_t flags;
23
- ca_size_t bytes;
24
- ca_size_t elements;
25
- ca_size_t *dim;
26
- char *ptr;
27
- CArray *mask;
28
- CArray *parent;
29
- uint32_t attach;
30
- uint8_t nosync;
31
- /* -------------*/
32
- ca_size_t *shift;
33
- char *fill;
34
- int8_t *roll;
35
- int fill_mask;
36
- } CAShift;
21
+ /* External: CAWindow's operation table + setup are the basis for CAShift. */
22
+ extern ca_operation_function_t ca_window_func;
23
+ extern VALUE rb_cCAWindow;
24
+ extern int ca_window_setup (CAWindow *ca, CArray *parent,
25
+ ca_size_t *start, ca_size_t *count,
26
+ uint8_t *bounds, char *fill);
27
+
28
+ /* CAShift dsize: same formula as CAWindow (the structs share layout).
29
+ CAREFUL: forward-declared so the const rb_data_type_t initialisers
30
+ below can reference it. Patching dsize into the table in Init via a
31
+ (rb_data_type_t *) cast would write into .rodata and SIGBUS on macOS. */
32
+ static size_t ca_shift_dsize (const void *ap);
37
33
 
38
34
  const rb_data_type_t cashift_data_type = {
39
- .parent = &cavirtual_data_type,
35
+ .parent = &caview_data_type,
40
36
  .wrap_struct_name = "CAShift",
41
37
  .function = {
42
38
  .dmark = ca_mark,
43
39
  .dfree = ca_free,
44
- .dsize = NULL,
40
+ .dsize = ca_shift_dsize,
45
41
  .dcompact = NULL
46
42
  },
47
43
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
48
44
  };
49
45
 
46
+ /* CAREFUL: mask TypedData uses ca_free_nop. The mask CArray is owned
47
+ by the parent CAShift's `ca->mask` field and freed by free_ca_shift's
48
+ ca_free(ca->mask). If the wrapped Ruby VALUE (from the `ca.mask`
49
+ accessor / rb_ca_mask_array) also freed it, the result is a
50
+ double-free that explodes under GC stress. */
50
51
  const rb_data_type_t cashift_mask_data_type = {
51
52
  .parent = &cashift_data_type,
52
53
  .wrap_struct_name = "CAShiftMask",
53
54
  .function = {
54
55
  .dmark = ca_mark,
55
- .dfree = ca_free,
56
- .dsize = NULL,
56
+ .dfree = ca_free_nop,
57
+ .dsize = ca_shift_dsize,
57
58
  .dcompact = NULL
58
59
  },
59
60
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
@@ -64,809 +65,212 @@ static int8_t CA_OBJ_SHIFT;
64
65
  VALUE rb_cCAShift;
65
66
  VALUE rb_cCAShiftMask;
66
67
 
68
+ /* Custom op table for CAShift — populated in Init from ca_window_func. */
69
+ static ca_operation_function_t ca_shift_func;
70
+
71
+ /* CAShift dsize: same formula as CAWindow (same struct layout). */
72
+ static size_t
73
+ ca_shift_dsize (const void *ap)
74
+ {
75
+ const CAShift *ca = (const CAShift *) ap;
76
+ return sizeof(CAShift) + 3 * ca->ndim * sizeof(ca_size_t)
77
+ + ca->ndim * sizeof(uint8_t) + ca->bytes;
78
+ }
79
+
67
80
  /* ------------------------------------------------------------------- */
68
81
 
69
82
  int
70
83
  ca_shift_setup (CAShift *ca, CArray *parent,
71
- ca_size_t *shift, char *fill, int8_t *roll)
84
+ ca_size_t *shift, char *fill, int8_t *roll, int fill_mask)
72
85
  {
73
- int8_t data_type, ndim;
74
- ca_size_t elements, bytes;
75
-
76
- data_type = parent->data_type;
77
- bytes = parent->bytes;
78
- ndim = parent->ndim;
79
- elements = parent->elements;
80
-
81
-
82
- ca->obj_type = CA_OBJ_SHIFT;
83
- ca->data_type = data_type;
84
- ca->flags = 0;
85
- ca->ndim = ndim;
86
- ca->bytes = bytes;
87
- ca->elements = elements;
88
- ca->ptr = NULL;
89
- ca->mask = NULL;
90
- ca->dim = ALLOC_N(ca_size_t, ndim);
91
-
92
- ca->parent = parent;
93
- ca->attach = 0;
94
- ca->nosync = 0;
95
- ca->shift = ALLOC_N(ca_size_t, ndim);
96
- ca->fill = ALLOC_N(char, ca->bytes);
97
- ca->roll = ALLOC_N(int8_t, ndim);
98
-
99
- memcpy(ca->dim, parent->dim, ndim * sizeof(ca_size_t));
100
- memcpy(ca->shift, shift, ndim * sizeof(ca_size_t));
101
- memcpy(ca->roll, roll, ndim * sizeof(int8_t));
102
-
103
- if ( fill ) {
104
- ca->fill_mask = 0;
105
- memcpy(ca->fill, fill, ca->bytes);
106
- }
107
- else {
108
- ca->fill_mask = 1;
109
- memset(ca->fill, 0, ca->bytes);
110
- }
111
-
112
- if ( ca_has_mask(parent) ) {
113
- ca_create_mask(ca);
114
- }
86
+ ca_size_t start[CA_RANK_MAX];
87
+ ca_size_t count[CA_RANK_MAX];
88
+ uint8_t bounds[CA_RANK_MAX];
89
+ int8_t k, ndim;
90
+
91
+ ndim = parent->ndim;
92
+ CA_ASSUME(ndim >= 0 && ndim <= CA_RANK_MAX); /* bound loop over [CA_RANK_MAX] arrays */
93
+ for (k = 0; k < ndim; k++) {
94
+ start[k] = -shift[k];
95
+ count[k] = parent->dim[k];
96
+ if ( roll[k] ) {
97
+ bounds[k] = CA_BOUNDS_PERIODIC;
98
+ } else if ( fill_mask ) {
99
+ bounds[k] = CA_BOUNDS_MASK;
100
+ } else {
101
+ bounds[k] = CA_BOUNDS_FILL;
102
+ }
103
+ }
104
+
105
+ /* Delegate to CAWindow setup. */
106
+ ca_window_setup((CAWindow *) ca, parent, start, count, bounds, fill);
107
+
108
+ /* Override obj_type so dispatch (ca_func[obj_type]) lands on the
109
+ CAShift-specific table (which differs from CAWindow only in
110
+ free / clone / create_mask, all forwarding to a CAShift-typed
111
+ result). */
112
+ ca->obj_type = CA_OBJ_SHIFT;
115
113
 
116
114
  return 0;
117
115
  }
118
116
 
119
117
  CAShift *
120
- ca_shift_new (CArray *parent, ca_size_t *shift, char *fill, int8_t *roll)
118
+ ca_shift_new (CArray *parent, ca_size_t *shift, char *fill, int8_t *roll,
119
+ int fill_mask)
121
120
  {
122
- CAShift *ca = ALLOC(CAShift);
123
- ca_shift_setup(ca, parent, shift, fill, roll);
121
+ CAShift *ca = (CAShift *) ca_array_alloc(CA_OBJ_SHIFT, parent->ndim);
122
+ ca_shift_setup(ca, parent, shift, fill, roll, fill_mask);
124
123
  return ca;
125
124
  }
126
125
 
126
+ /* Free: same fields as CAWindow (same struct). CAShift goes through
127
+ ca_window_setup, so the same seven ndim-sized fields live in ca->_pool
128
+ (fill stays separate). */
127
129
  static void
128
130
  free_ca_shift (void *ap)
129
131
  {
130
132
  CAShift *ca = (CAShift *) ap;
131
133
  if ( ca != NULL ) {
132
- xfree(ca->fill);
133
- xfree(ca->shift);
134
- xfree(ca->roll);
135
134
  ca_free(ca->mask);
136
- xfree(ca->dim);
137
- xfree(ca);
138
- }
139
- }
140
-
141
- static void ca_shift_attach (CAShift *ca);
142
- static void ca_shift_sync (CAShift *ca);
143
- static void ca_shift_fill (CAShift *ca, char *ptr);
144
-
145
- static ca_size_t
146
- ca_shift_normalized_roll_shift (CAShift *ca, ca_size_t i)
147
- {
148
- ca_size_t dim = ca->dim[i];
149
- ca_size_t shift = ca->shift[i];
150
- if ( shift >= 0 ) {
151
- return shift % dim;
152
- }
153
- else {
154
- return -((-shift) % dim);
155
- }
156
- }
157
-
158
- static ca_size_t
159
- ca_shift_rolled_index (CAShift *ca, ca_size_t i, ca_size_t k)
160
- {
161
- ca_size_t dim = ca->dim[i];
162
- ca_size_t shift = ca->shift[i];
163
- ca_size_t idx = k - shift;
164
- if ( idx >= 0 ) {
165
- return idx % dim;
166
- }
167
- else {
168
- idx = (-idx) % dim;
169
- return ( ! idx ) ? 0 : dim - idx;
170
- }
171
- }
172
-
173
- static ca_size_t
174
- ca_shift_shifted_index (CAShift *ca, ca_size_t i, ca_size_t k)
175
- {
176
- ca_size_t dim = ca->dim[i];
177
- ca_size_t shift = ca->shift[i];
178
- ca_size_t idx = k - shift;
179
- if ( idx < 0 || idx >= dim ) {
180
- return -1;
181
- }
182
- else {
183
- return idx;
184
- }
185
- }
186
-
187
- /* ------------------------------------------------------------------- */
188
-
189
- static void *
190
- ca_shift_func_clone (void *ap)
191
- {
192
- CAShift *ca = (CAShift *) ap;
193
- return ca_shift_new(ca->parent, ca->shift, ca->fill, ca->roll);
194
- }
195
-
196
- static char *
197
- ca_shift_func_ptr_at_addr (void *ap, ca_size_t addr)
198
- {
199
- CAShift *ca = (CAShift *) ap;
200
- if ( ! ca->ptr ) {
201
- ca_size_t idx[CA_RANK_MAX];
202
- ca_addr2index((CArray *)ca, addr, idx);
203
- return ca_ptr_at_index(ca, idx);
204
- }
205
- else {
206
- return ca->ptr + ca->bytes * addr;
207
- }
208
- }
209
-
210
- static char *
211
- ca_shift_func_ptr_at_index (void *ap, ca_size_t *idx)
212
- {
213
- CAShift *ca = (CAShift *) ap;
214
- if ( ! ca->ptr ) {
215
- ca_size_t *dim = ca->dim;
216
- int8_t *roll = ca->roll;
217
- int8_t i;
218
- ca_size_t k, n;
219
- n = 0;
220
- for (i=0; i<ca->ndim; i++) {
221
- k = idx[i];
222
- if ( roll[i] ) {
223
- k = ca_shift_rolled_index(ca, i, k);
224
- }
225
- else {
226
- k = ca_shift_shifted_index(ca, i, k);
227
- }
228
-
229
- if ( k < 0 ) {
230
- return ca->fill;
231
- }
232
- n = dim[i] * n + k;
233
- }
234
-
235
- if ( ca->parent->ptr == NULL ) {
236
- return ca_ptr_at_addr(ca->parent, n);
135
+ xfree(ca->fill); /* always separate (bytes-sized) */
136
+ if ( ca->_pool ) {
137
+ ca_array_free(ca);
237
138
  }
238
139
  else {
239
- return ca->parent->ptr + ca->bytes * n;
140
+ xfree(ca->bounds);
141
+ xfree(ca->start);
142
+ xfree(ca->count);
143
+ xfree(ca->size0);
144
+ xfree(ca->embed_parent_start);
145
+ xfree(ca->embed_count);
146
+ xfree(ca->embed_output_offset);
147
+ xfree(ca);
240
148
  }
241
149
  }
242
- else {
243
- return ca_func[CA_OBJ_ARRAY].ptr_at_index(ca, idx);
244
- }
245
150
  }
246
151
 
247
- static void
248
- ca_shift_func_fetch_index (void *ap, ca_size_t *idx, void *ptr)
152
+ /* Clone: produce a CAShift (not CAWindow) by rebuilding via setup.
153
+ Recover (shift[], roll[], fill_mask) from current (start[], bounds[]). */
154
+ static void *
155
+ ca_shift_func_clone (void *ap)
249
156
  {
250
157
  CAShift *ca = (CAShift *) ap;
251
- ca_size_t *dim = ca->dim;
252
- int8_t *roll = ca->roll;
253
- int8_t i;
254
- ca_size_t k, n;
255
- n = 0;
256
- for (i=0; i<ca->ndim; i++) {
257
- k = idx[i];
258
- if ( roll[i] ) {
259
- k = ca_shift_rolled_index(ca, i, k);
260
- }
261
- else {
262
- k = ca_shift_shifted_index(ca, i, k);
263
- }
158
+ ca_size_t shift[CA_RANK_MAX];
159
+ int8_t roll[CA_RANK_MAX];
160
+ int fill_mask = 0;
161
+ int8_t k;
264
162
 
265
- if ( k < 0 ) {
266
- memcpy(ptr, ca->fill, ca->bytes);
267
- return;
163
+ /* shift[k] = -start[k] (inverse of setup's start = -shift) */
164
+ for (k = 0; k < ca->ndim; k++) {
165
+ shift[k] = -ca->start[k];
166
+ if ( ca->bounds[k] == CA_BOUNDS_PERIODIC ) {
167
+ roll[k] = 1;
168
+ } else {
169
+ roll[k] = 0;
170
+ if ( ca->bounds[k] == CA_BOUNDS_MASK ) fill_mask = 1;
268
171
  }
269
- n = dim[i] * n + k;
270
172
  }
271
- ca_fetch_addr(ca->parent, n, ptr);
272
- }
273
173
 
274
- static void
275
- ca_shift_func_store_index (void *ap, ca_size_t *idx, void *ptr)
276
- {
277
- CAShift *ca = (CAShift *) ap;
278
- ca_size_t *dim = ca->dim;
279
- int8_t *roll = ca->roll;
280
- int8_t i;
281
- ca_size_t k, n;
282
- n = 0;
283
- for (i=0; i<ca->ndim; i++) {
284
- k = idx[i];
285
- if ( roll[i] ) {
286
- k = ca_shift_rolled_index(ca, i, k);
287
- }
288
- else {
289
- k = ca_shift_shifted_index(ca, i, k);
290
- }
291
-
292
- if ( k < 0 ) {
293
- return;
294
- }
295
- n = dim[i] * n + k;
296
- }
297
- ca_store_addr(ca->parent, n, ptr);
298
- }
299
-
300
- static void
301
- ca_shift_func_allocate (void *ap)
302
- {
303
- CAShift *ca = (CAShift *) ap;
304
- ca_attach(ca->parent);
305
- /* ca->ptr = ALLOC_N(char, ca_length(ca)); */
306
- ca->ptr = malloc_with_check(ca_length(ca));
307
- }
308
-
309
- static void
310
- ca_shift_func_attach (void *ap)
311
- {
312
- void ca_shift_attach (CAShift *cb);
313
-
314
- CAShift *ca = (CAShift *) ap;
315
- ca_attach(ca->parent);
316
- /* ca->ptr = ALLOC_N(char, ca_length(ca)); */
317
- ca->ptr = malloc_with_check(ca_length(ca));
318
- ca_shift_attach(ca);
319
- }
320
-
321
- static void
322
- ca_shift_func_sync (void *ap)
323
- {
324
- CAShift *ca = (CAShift *) ap;
325
- ca_shift_sync(ca);
326
- ca_sync(ca->parent);
327
- }
328
-
329
- static void
330
- ca_shift_func_detach (void *ap)
331
- {
332
- CAShift *ca = (CAShift *) ap;
333
- free(ca->ptr);
334
- ca->ptr = NULL;
335
- ca_detach(ca->parent);
336
- }
337
-
338
- static void
339
- ca_shift_func_copy_data (void *ap, void *ptr)
340
- {
341
- CAShift *ca = (CAShift *) ap;
342
- char *ptr0 = ca->ptr;
343
- ca_attach(ca->parent);
344
- ca->ptr = ptr;
345
- ca_shift_attach(ca);
346
- ca->ptr = ptr0;
347
- ca_detach(ca->parent);
348
- }
349
-
350
- static void
351
- ca_shift_func_sync_data (void *ap, void *ptr)
352
- {
353
- CAShift *ca = (CAShift *) ap;
354
- char *ptr0 = ca->ptr;
355
- ca_attach(ca->parent);
356
- ca->ptr = ptr;
357
- ca_shift_sync(ca);
358
- ca->ptr = ptr0;
359
- ca_sync(ca->parent);
360
- ca_detach(ca->parent);
361
- }
362
-
363
- static void
364
- ca_shift_func_fill_data (void *ap, void *ptr)
365
- {
366
- CAShift *ca = (CAShift *) ap;
367
- ca_attach(ca->parent);
368
- ca_shift_fill(ca, ptr);
369
- ca_sync(ca->parent);
370
- ca_detach(ca->parent);
174
+ return ca_shift_new(ca->parent, shift, ca->fill, roll, fill_mask);
371
175
  }
372
176
 
177
+ /* create_mask: produce a CAShift-typed mask (not CAWindow-typed).
178
+ Following the original ca_shift_func_create_mask semantics:
179
+ - Ensure parent has mask
180
+ - Build mask sub-view using same shift/roll, fill = 1 if fill_mask
181
+ else 0 (i.e. range-outside cells get masked when fill_mask was on,
182
+ unmasked otherwise) */
373
183
  static void
374
184
  ca_shift_func_create_mask (void *ap)
375
185
  {
376
186
  CAShift *ca = (CAShift *) ap;
377
- boolean8_t one = 1;
378
- boolean8_t zero = 0;
187
+ ca_size_t shift[CA_RANK_MAX];
188
+ int8_t roll[CA_RANK_MAX];
189
+ boolean8_t fill_val;
190
+ int fill_mask_was_on = 0;
191
+ int8_t k;
379
192
 
380
193
  ca_update_mask(ca->parent);
381
-
382
194
  if ( ! ca->parent->mask ) {
383
195
  ca_create_mask(ca->parent);
384
196
  }
385
197
 
386
- if ( ca->fill_mask ) {
387
- ca->mask = (CArray *) ca_shift_new(ca->parent->mask,
388
- ca->shift, (char *) &one, ca->roll);
389
- }
390
- else {
391
- ca->mask = (CArray *) ca_shift_new(ca->parent->mask,
392
- ca->shift, (char *) &zero, ca->roll);
393
- }
394
- }
395
-
396
- ca_operation_function_t ca_shift_func = {
397
- -1, /* CA_OBJ_SHIFT */
398
- CA_VIRTUAL_ARRAY,
399
- free_ca_shift,
400
- ca_shift_func_clone,
401
- ca_shift_func_ptr_at_addr,
402
- ca_shift_func_ptr_at_index,
403
- NULL,
404
- ca_shift_func_fetch_index,
405
- NULL,
406
- ca_shift_func_store_index,
407
- ca_shift_func_allocate,
408
- ca_shift_func_attach,
409
- ca_shift_func_sync,
410
- ca_shift_func_detach,
411
- ca_shift_func_copy_data,
412
- ca_shift_func_sync_data,
413
- ca_shift_func_fill_data,
414
- ca_shift_func_create_mask,
415
- };
416
-
417
- /* ------------------------------------------------------------------- */
418
-
419
- static void
420
- ca_shift_attach_loop (CAShift *ca, int16_t level, ca_size_t *idx, ca_size_t *idx0,
421
- int32_t fill)
422
- {
423
- ca_size_t dim = ca->dim[level];
424
- ca_size_t shift = ca->shift[level];
425
- int8_t roll = ca->roll[level];
426
- ca_size_t i;
427
-
428
- if ( level == ca->ndim - 1 ) {
429
- if ( fill ) {
430
- for (i=0; i<ca->dim[level]; i++) {
431
- idx[level] = i;
432
- memcpy(ca_ptr_at_index(ca, idx), ca->fill, ca->bytes);
433
- }
434
- }
435
- else if ( ! shift ) {
436
- idx[level] = 0;
437
- idx0[level] = 0;
438
- memcpy(ca_ptr_at_index(ca, idx), ca_ptr_at_index(ca->parent, idx0), dim * ca->bytes);
439
- }
440
- else if ( roll ) {
441
- shift = ca_shift_normalized_roll_shift(ca, level);
442
- if ( shift > 0 ) {
443
- idx[level] = 0;
444
- idx0[level] = dim-shift;
445
- memcpy(ca_ptr_at_index(ca,idx), ca_ptr_at_index(ca->parent,idx0), shift*ca->bytes);
446
- idx[level] = shift;
447
- idx0[level] = 0;
448
- memcpy(ca_ptr_at_index(ca,idx), ca_ptr_at_index(ca->parent,idx0), (dim-shift)*ca->bytes);
449
- }
450
- else {
451
- idx[level] = 0;
452
- idx0[level] = -shift;
453
- memcpy(ca_ptr_at_index(ca,idx), ca_ptr_at_index(ca->parent,idx0), (dim+shift)*ca->bytes);
454
- idx[level] = dim + shift;
455
- idx0[level] = 0;
456
- memcpy(ca_ptr_at_index(ca,idx), ca_ptr_at_index(ca->parent,idx0), (-shift)*ca->bytes);
457
- }
458
- }
459
- else {
460
- if ( shift > 0 ) {
461
- shift = ( shift >= dim ) ? dim : shift;
462
-
463
- for (i=0; i<shift; i++) {
464
- idx[level] = i;
465
- memcpy(ca_ptr_at_index(ca, idx), ca->fill, ca->bytes);
466
- }
467
-
468
- if ( shift < dim ) {
469
- idx[level] = shift;
470
- idx0[level] = 0;
471
- memcpy(ca_ptr_at_index(ca,idx), ca_ptr_at_index(ca->parent,idx0),(dim-shift)*ca->bytes);
472
- }
473
- }
474
- else {
475
- shift = ( -shift >= dim ) ? -dim : shift;
476
-
477
- if ( -shift < dim ) {
478
- idx[level] = 0;
479
- idx0[level] = -shift;
480
- memcpy(ca_ptr_at_index(ca,idx), ca_ptr_at_index(ca->parent,idx0),(dim+shift)*ca->bytes);
481
- }
482
-
483
- for (i=0; i<-shift; i++) {
484
- idx[level] = dim+shift+i;
485
- memcpy(ca_ptr_at_index(ca, idx), ca->fill, ca->bytes);
486
- }
487
- }
488
- }
489
- }
490
- else {
491
- if ( fill ) {
492
- for (i=0; i<dim; i++) {
493
- idx[level] = i;
494
- ca_shift_attach_loop(ca, level+1, idx, idx0, 1); /* fill */
495
- }
496
- }
497
- else if ( ! shift ) {
498
- for (i=0; i<dim; i++) {
499
- idx[level] = i;
500
- idx0[level] = i;
501
- ca_shift_attach_loop(ca, level+1, idx, idx0, 0);
502
- }
503
- }
504
- else if ( roll ) {
505
- shift = ca_shift_normalized_roll_shift(ca, level);
506
-
507
- if ( shift > 0 ) {
508
- for (i=0; i<shift; i++) {
509
- idx[level] = i;
510
- idx0[level] = dim-shift+i;
511
- ca_shift_attach_loop(ca, level+1, idx, idx0, 0);
512
- }
513
-
514
- for (i=0; i<dim-shift; i++) {
515
- idx[level] = shift+i;
516
- idx0[level] = i;
517
- ca_shift_attach_loop(ca, level+1, idx, idx0, 0);
518
- }
519
- }
520
- else {
521
- for (i=0; i<dim+shift; i++) {
522
- idx[level] = i;
523
- idx0[level] = -shift+i;
524
- ca_shift_attach_loop(ca, level+1, idx, idx0, 0);
525
- }
526
-
527
- for (i=0; i<-shift; i++) {
528
- idx[level] = dim + shift + i;
529
- idx0[level] = i;
530
- ca_shift_attach_loop(ca, level+1, idx, idx0, 0);
531
- }
532
- }
533
- }
534
- else {
535
- if ( shift > 0 ) {
536
- shift = ( shift >= dim ) ? dim : shift;
537
-
538
- for (i=0; i<shift; i++) {
539
- idx[level] = i;
540
- ca_shift_attach_loop(ca, level+1, idx, idx0, 1); /* fill */
541
- }
542
-
543
- if ( shift < dim ) {
544
- for (i=0; i<dim-shift; i++) {
545
- idx[level] = shift+i;
546
- idx0[level] = i;
547
- ca_shift_attach_loop(ca, level+1, idx, idx0, 0);
548
- }
549
- }
550
- }
551
- else {
552
- shift = ( -shift >= dim ) ? -dim : shift;
553
-
554
- if ( -shift < dim ) {
555
- for (i=0; i<dim+shift; i++) {
556
- idx[level] = i;
557
- idx0[level] = -shift+i;
558
- ca_shift_attach_loop(ca, level+1, idx, idx0, 0);
559
- }
560
- }
561
-
562
- for (i=0; i<-shift; i++) {
563
- idx[level] = dim+shift+i;
564
- ca_shift_attach_loop(ca, level+1, idx, idx0, 1); /* fill */
565
- }
566
- }
567
- }
568
- }
569
- }
570
-
571
- static void
572
- ca_shift_attach (CAShift *ca)
573
- {
574
- ca_size_t idx[CA_RANK_MAX];
575
- ca_size_t idx0[CA_RANK_MAX];
576
- ca_shift_attach_loop(ca, (int16_t) 0, idx, idx0, 0);
577
- }
578
-
579
- static void
580
- ca_shift_sync_loop (CAShift *ca, int16_t level, ca_size_t *idx, ca_size_t *idx0)
581
- {
582
- ca_size_t dim = ca->dim[level];
583
- ca_size_t shift = ca->shift[level];
584
- int8_t roll = ca->roll[level];
585
- ca_size_t i;
586
-
587
- if ( level == ca->ndim - 1 ) {
588
- if ( ! shift ) {
589
- idx[level] = 0;
590
- idx0[level] = 0;
591
- memcpy(ca_ptr_at_index(ca->parent, idx0), ca_ptr_at_index(ca, idx), dim * ca->bytes);
592
- }
593
- else if ( roll ) {
594
- shift = ca_shift_normalized_roll_shift(ca, level);
595
-
596
- if ( shift > 0 ) {
597
- idx[level] = 0;
598
- idx0[level] = dim-shift;
599
- memcpy(ca_ptr_at_index(ca->parent,idx0), ca_ptr_at_index(ca,idx), shift*ca->bytes);
600
- idx[level] = shift;
601
- idx0[level] = 0;
602
- memcpy(ca_ptr_at_index(ca->parent,idx0), ca_ptr_at_index(ca,idx), (dim-shift)*ca->bytes);
603
- }
604
- else {
605
- idx[level] = 0;
606
- idx0[level] = -shift;
607
- memcpy(ca_ptr_at_index(ca->parent,idx0), ca_ptr_at_index(ca,idx), (dim+shift)*ca->bytes);
608
- idx[level] = dim + shift;
609
- idx0[level] = 0;
610
- memcpy(ca_ptr_at_index(ca->parent,idx0), ca_ptr_at_index(ca,idx), (-shift)*ca->bytes);
611
- }
612
- }
613
- else {
614
- if ( shift > 0 ) {
615
- shift = ( shift >= dim ) ? dim : shift;
616
-
617
- for (i=0; i<shift; i++) {
618
- ; /* do nothing */
619
- }
620
-
621
- if ( shift < dim ) {
622
- idx[level] = shift;
623
- idx0[level] = 0;
624
- memcpy(ca_ptr_at_index(ca->parent,idx0), ca_ptr_at_index(ca,idx),(dim-shift)*ca->bytes);
625
- }
626
- }
627
- else {
628
- shift = ( -shift >= dim ) ? -dim : shift;
629
-
630
- if ( -shift < dim ) {
631
- idx[level] = 0;
632
- idx0[level] = -shift;
633
- memcpy(ca_ptr_at_index(ca->parent,idx0), ca_ptr_at_index(ca,idx),(dim+shift)*ca->bytes);
634
- }
635
-
636
- for (i=0; i<-shift; i++) {
637
- ; /* do nothing */
638
- }
639
- }
640
- }
641
- }
642
- else {
643
- if ( ! shift ) {
644
- for (i=0; i<dim; i++) {
645
- idx[level] = i;
646
- idx0[level] = i;
647
- ca_shift_sync_loop(ca, level+1, idx, idx0);
648
- }
649
- }
650
- else if ( roll ) {
651
- shift = ca_shift_normalized_roll_shift(ca, level);
652
- if ( shift > 0 ) {
653
- for (i=0; i<shift; i++) {
654
- idx[level] = i;
655
- idx0[level] = dim-shift+i;
656
- ca_shift_sync_loop(ca, level+1, idx, idx0);
657
- }
658
-
659
- for (i=0; i<dim-shift; i++) {
660
- idx[level] = shift+i;
661
- idx0[level] = i;
662
- ca_shift_sync_loop(ca, level+1, idx, idx0);
663
- }
664
- }
665
- else {
666
- for (i=0; i<dim+shift; i++) {
667
- idx[level] = i;
668
- idx0[level] = -shift+i;
669
- ca_shift_sync_loop(ca, level+1, idx, idx0);
670
- }
671
-
672
- for (i=0; i<-shift; i++) {
673
- idx[level] = dim + shift + i;
674
- idx0[level] = i;
675
- ca_shift_sync_loop(ca, level+1, idx, idx0);
676
- }
677
- }
678
- }
679
- else {
680
- if ( shift > 0 ) {
681
- shift = ( shift >= dim ) ? dim : shift;
682
-
683
- for (i=0; i<shift; i++) {
684
- ; /* do nothing */
685
- }
686
-
687
- if ( shift < dim ) {
688
- for (i=0; i<dim-shift; i++) {
689
- idx[level] = shift+i;
690
- idx0[level] = i;
691
- ca_shift_sync_loop(ca, level+1, idx, idx0);
692
- }
693
- }
694
- }
695
- else {
696
- shift = ( -shift >= dim ) ? -dim : shift;
697
-
698
- if ( -shift < dim ) {
699
- for (i=0; i<dim+shift; i++) {
700
- idx[level] = i;
701
- idx0[level] = -shift+i;
702
- ca_shift_sync_loop(ca, level+1, idx, idx0);
703
- }
704
- }
705
-
706
- for (i=0; i<-shift; i++) {
707
- ; /* do nothing */
708
- }
709
- }
710
- }
711
- }
712
- }
713
-
714
- static void
715
- ca_shift_sync (CAShift *ca)
716
- {
717
- ca_size_t idx[CA_RANK_MAX];
718
- ca_size_t idx0[CA_RANK_MAX];
719
- ca_shift_sync_loop(ca, (int16_t) 0, idx, idx0);
720
- }
721
-
722
- static void
723
- ca_shift_fill_loop (CAShift *ca, char *ptr,
724
- int16_t level, ca_size_t *idx0)
725
- {
726
- ca_size_t dim = ca->dim[level];
727
- ca_size_t shift = ca->shift[level];
728
- int8_t roll = ca->roll[level];
729
- ca_size_t i;
730
-
731
- if ( level == ca->ndim - 1 ) {
732
- if ( ( ! shift ) || roll ) {
733
- for (i=0; i<dim; i++) {
734
- idx0[level] = i;
735
- memcpy(ca_ptr_at_index(ca->parent, idx0), ptr, ca->bytes);
736
- }
737
- }
738
- else {
739
- if ( shift > 0 ) {
740
- shift = ( shift >= dim ) ? dim : shift;
741
-
742
- for (i=0; i<shift; i++) {
743
- ; /* do nothing */
744
- }
745
-
746
- if ( shift < dim ) {
747
- for (i=0; i<dim-shift; i++) {
748
- idx0[level] = i;
749
- memcpy(ca_ptr_at_index(ca->parent, idx0), ptr, ca->bytes);
750
- }
751
- }
752
- }
753
- else {
754
- shift = ( -shift >= dim ) ? -dim : shift;
755
-
756
- if ( -shift < dim ) {
757
- for (i=0; i<dim+shift; i++) {
758
- idx0[level] = -shift+i;
759
- memcpy(ca_ptr_at_index(ca->parent, idx0), ptr, ca->bytes);
760
- }
761
- }
762
-
763
- for (i=0; i<-shift; i++) {
764
- ; /* do nothing */
765
- }
766
- }
767
- }
768
- }
769
- else {
770
- if ( ( ! shift ) || roll ) {
771
- for (i=0; i<dim; i++) {
772
- idx0[level] = i;
773
- ca_shift_fill_loop(ca, ptr, level+1, idx0);
774
- }
775
- }
776
- else {
777
- if ( shift > 0 ) {
778
- shift = ( shift >= dim ) ? dim : shift;
779
-
780
- for (i=0; i<shift; i++) {
781
- ; /* do nothing */
782
- }
783
-
784
- if ( shift < dim ) {
785
- for (i=0; i<dim-shift; i++) {
786
- idx0[level] = i;
787
- ca_shift_fill_loop(ca, ptr, level+1, idx0);
788
- }
789
- }
790
- }
791
- else {
792
- shift = ( -shift >= dim ) ? -dim : shift;
793
-
794
- if ( -shift < dim ) {
795
- for (i=0; i<dim+shift; i++) {
796
- idx0[level] = -shift+i;
797
- ca_shift_fill_loop(ca, ptr, level+1, idx0);
798
- }
799
- }
800
-
801
- for (i=0; i<-shift; i++) {
802
- ; /* do nothing */
803
- }
804
- }
805
- }
806
- }
807
- }
808
-
809
- static void
810
- ca_shift_fill (CAShift *ca, char *ptr)
811
- {
812
- ca_size_t idx0[CA_RANK_MAX];
813
- ca_shift_fill_loop(ca, ptr, (int16_t) 0, idx0);
198
+ for (k = 0; k < ca->ndim; k++) {
199
+ shift[k] = -ca->start[k];
200
+ if ( ca->bounds[k] == CA_BOUNDS_PERIODIC ) {
201
+ roll[k] = 1;
202
+ } else {
203
+ roll[k] = 0;
204
+ if ( ca->bounds[k] == CA_BOUNDS_MASK ) fill_mask_was_on = 1;
205
+ }
206
+ }
207
+
208
+ /* If MASK policy was set, the mask sub-view should mark out-of-range
209
+ cells as "masked" (fill value = 1). Otherwise out-of-range cells
210
+ get the fill value (fill = 0) and aren't masked. */
211
+ fill_val = fill_mask_was_on ? 1 : 0;
212
+
213
+ /* Build the mask as CAShift with same shift/roll but using fill_mask=0
214
+ (the mask itself shouldn't recursively create a mask) and fill = 0/1
215
+ boolean. Bounds for mask: replace MASK→FILL so the mask values are
216
+ written, not the mask's mask. */
217
+ {
218
+ /* Construct mask via direct ca_window_new with adjusted bounds. */
219
+ uint8_t mbounds[CA_RANK_MAX];
220
+ ca_size_t mstart[CA_RANK_MAX];
221
+ ca_size_t mcount[CA_RANK_MAX];
222
+ CAShift *m;
223
+ CA_ASSUME(ca->ndim >= 0 && ca->ndim <= CA_RANK_MAX); /* bound loop over [CA_RANK_MAX] arrays */
224
+ for (k = 0; k < ca->ndim; k++) {
225
+ mstart[k] = ca->start[k];
226
+ mcount[k] = ca->count[k];
227
+ mbounds[k] = ( ca->bounds[k] == CA_BOUNDS_MASK )
228
+ ? CA_BOUNDS_FILL : ca->bounds[k];
229
+ }
230
+ /* CAShift-typed mask: allocate, setup as CAWindow with adjusted
231
+ bounds, bump obj_type. */
232
+ m = (CAShift *) ca_array_alloc(CA_OBJ_SHIFT, ca->ndim);
233
+ ca_window_setup((CAWindow *) m, ca->parent->mask,
234
+ mstart, mcount, mbounds, (char *) &fill_val);
235
+ m->obj_type = CA_OBJ_SHIFT;
236
+ ca->mask = (CArray *) m;
237
+ }
238
+ (void) shift; (void) roll; /* recovered above but unused in this block */
814
239
  }
815
240
 
816
241
  /* ------------------------------------------------------------------- */
817
242
 
818
- /*
819
- static VALUE
820
- rb_ca_shift_set_fill_value (VALUE self, VALUE rfval)
821
- {
822
- CAShift *ca;
823
- CArray *cs;
824
-
825
- TypedData_Get_Struct(self, CAShift, &cashift_data_type, ca);
826
-
827
- if ( NIL_P(rfval) ) {
828
- memset(ca->fill, 0, ca->bytes);
829
- }
830
- else {
831
- cs = ca_wrap_readonly(rfval, ca->data_type);
832
- memcpy(ca->fill, cs->ptr, ca->bytes);
833
- }
834
-
835
- return rfval;
836
- }
837
- */
838
-
839
243
  VALUE
840
- rb_ca_shift_new (VALUE cary, ca_size_t *shift, char *fill, int8_t *roll)
244
+ rb_ca_shift_new (VALUE cary, ca_size_t *shift, char *fill, int8_t *roll,
245
+ int fill_mask)
841
246
  {
842
247
  volatile VALUE obj;
843
248
  CArray *parent;
844
249
  CAShift *ca;
845
250
  rb_check_carray_object(cary);
846
251
  TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
847
- ca = ca_shift_new(parent, shift, fill, roll);
252
+ ca = ca_shift_new(parent, shift, fill, roll, fill_mask);
848
253
  obj = ca_wrap_struct(ca);
849
254
  rb_ca_set_parent(obj, cary);
850
- rb_ca_data_type_inherit(obj, cary);
851
255
  return obj;
852
256
  }
853
257
 
854
- /* yard:
855
- class CArray
856
- def shifted
857
- end
858
- end
859
- */
860
-
258
+ /* CArray#shift(*shifts, fill_value:) — returns a CAShift view translated
259
+ * by `shifts` along each axis (one shift per dimension).
260
+ *
261
+ * Out-of-range cells take fill_value (default 0); fill_value: UNDEF masks
262
+ * them instead. Raises ArgumentError on argument-count mismatch, on the
263
+ * removed :roll option, and on the removed block form. */
861
264
  VALUE
862
265
  rb_ca_shift (int argc, VALUE *argv, VALUE self)
863
266
  {
864
- volatile VALUE obj, ropt, rfval = CA_NIL, rroll = Qnil, rcs;
267
+ volatile VALUE obj, ropt, rfval = CA_UNSPECIFIED, rroll = Qnil, rcs;
865
268
  CArray *ca;
866
269
  CScalar *cs;
867
270
  ca_size_t shift[CA_RANK_MAX];
868
271
  int8_t roll[CA_RANK_MAX];
869
272
  char *fill = NULL;
273
+ int fill_mask = 0;
870
274
  int8_t i;
871
275
 
872
276
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
@@ -874,6 +278,15 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
874
278
  ropt = rb_pop_options(&argc, &argv);
875
279
  rb_scan_options(ropt, "roll,fill_value", &rroll, &rfval);
876
280
 
281
+ /* The :roll option was removed in 3.0. Cyclic shift is now CArray#roll
282
+ (returns a CARoll view, ca_obj_roll.c). Mixed per-axis roll is
283
+ expressed via chain: a.roll(1, 0) followed by .shift(...). */
284
+ if ( ! NIL_P(rroll) ) {
285
+ rb_raise(rb_eArgError,
286
+ "shift: :roll option removed in 3.0; "
287
+ "use CArray#roll(...) for cyclic shift (returns CARoll view)");
288
+ }
289
+
877
290
  if ( argc != ca->ndim ) {
878
291
  rb_raise(rb_eArgError, "# of arguments mismatch with ndim");
879
292
  }
@@ -882,16 +295,14 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
882
295
  shift[i] = NUM2SIZE(argv[i]);
883
296
  }
884
297
 
885
- if ( rfval == CA_NIL ) {
886
- if ( rb_block_given_p() ) {
887
- rfval = rb_yield(self);
888
- }
889
- }
890
- else {
891
- /* rb_warn(":fill_value option for CArray#shifted will be obsoleted."); */
298
+ if ( rb_block_given_p() ) {
299
+ rb_raise(rb_eArgError,
300
+ "shift: block form for fill value removed in 3.0; "
301
+ "use fill_value: kwarg (e.g. shift(1, fill_value: -2))");
892
302
  }
893
303
 
894
- if ( rfval == CA_NIL ) {
304
+ if ( rfval == CA_UNSPECIFIED ) {
305
+ /* Default fill value = 0 (or INT2NUM(0) for OBJECT type) */
895
306
  rcs = rb_cscalar_new(ca->data_type, ca->bytes, NULL);
896
307
  TypedData_Get_Struct(rcs, CScalar, &cscalar_data_type, cs);
897
308
  fill = cs->ptr;
@@ -900,10 +311,12 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
900
311
  }
901
312
  else {
902
313
  memset(fill, 0, cs->bytes);
903
- }
314
+ }
904
315
  }
905
316
  else if ( rfval == CA_UNDEF ) {
317
+ /* Range-outside cells should be masked, not value-filled. */
906
318
  fill = NULL;
319
+ fill_mask = 1;
907
320
  }
908
321
  else {
909
322
  rcs = rb_cscalar_new_with_value(ca->data_type, ca->bytes, rfval);
@@ -928,14 +341,9 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
928
341
  }
929
342
  }
930
343
 
931
- obj = rb_ca_shift_new(self, shift, fill, roll);
932
-
933
- if ( rfval == CA_UNDEF ) {
934
- CArray *co;
935
- TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
936
- ca_create_mask(co);
937
- }
344
+ obj = rb_ca_shift_new(self, shift, fill, roll, fill_mask);
938
345
 
346
+ CA_WRAPPER_LIFT(obj, self, ca);
939
347
  return obj;
940
348
  }
941
349
 
@@ -952,31 +360,61 @@ static VALUE
952
360
  rb_ca_shift_initialize_copy (VALUE self, VALUE other)
953
361
  {
954
362
  CAShift *ca, *cs;
363
+ ca_size_t shift[CA_RANK_MAX];
364
+ int8_t roll[CA_RANK_MAX];
365
+ int fill_mask = 0;
366
+ int8_t k;
955
367
 
956
368
  TypedData_Get_Struct(self, CAShift, &cashift_data_type, ca);
957
369
  TypedData_Get_Struct(other, CAShift, &cashift_data_type, cs);
958
370
 
959
- ca_shift_setup(ca, cs->parent, cs->shift, cs->fill, cs->roll);
371
+ /* Recover shift/roll/fill_mask from cs (same scheme as clone). */
372
+ for (k = 0; k < cs->ndim; k++) {
373
+ shift[k] = -cs->start[k];
374
+ if ( cs->bounds[k] == CA_BOUNDS_PERIODIC ) {
375
+ roll[k] = 1;
376
+ } else {
377
+ roll[k] = 0;
378
+ if ( cs->bounds[k] == CA_BOUNDS_MASK ) fill_mask = 1;
379
+ }
380
+ }
381
+ /* `self` came from rb_ca_shift_s_allocate (TypedData_Make_Struct,
382
+ _pool == NULL). Attach the pool before setup. */
383
+ if ( ca_func[CA_OBJ_SHIFT].pool_init ) {
384
+ ca_array_pool_alloc(ca, CA_OBJ_SHIFT, cs->ndim);
385
+ }
386
+ ca_shift_setup(ca, cs->parent, shift, cs->fill, roll, fill_mask);
960
387
 
961
388
  return self;
962
389
  }
963
390
 
391
+ /* `shift!` removed in 3.0; the canonical in-place idiom is
392
+ `ca[] = ca.shift(...)`.
393
+ [MOVED] roll -> ext/ca_obj_roll.c (CARoll view). */
394
+
964
395
  void
965
- Init_ca_obj_shift ()
396
+ Init_ca_obj_shift (void)
966
397
  {
967
- rb_cCAShift = rb_define_class("CAShift", rb_cCAVirtual);
398
+ /* Build the CAShift op table by copying CAWindow's and overriding
399
+ just the slots that need to produce CAShift-typed results. */
400
+ ca_shift_func = ca_window_func;
401
+ ca_shift_func.free_object = free_ca_shift;
402
+ ca_shift_func.clone = ca_shift_func_clone;
403
+ ca_shift_func.create_mask = ca_shift_func_create_mask;
404
+
405
+ rb_cCAShift = rb_define_class("CAShift", rb_cCAWindow);
968
406
  rb_cCAShiftMask = rb_define_class("CAShiftMask", rb_cCAShift);
969
407
 
970
- CA_OBJ_SHIFT = ca_install_obj_type(rb_cCAShift,
971
- &cashift_data_type,
972
- rb_cCAShiftMask,
973
- &cashift_mask_data_type, ca_shift_func);
408
+ CA_OBJ_SHIFT = ca_install_obj_type(rb_cCAShift,
409
+ &cashift_data_type,
410
+ rb_cCAShiftMask,
411
+ &cashift_mask_data_type, &ca_shift_func, sizeof(ca_shift_func));
974
412
  rb_define_const(rb_cObject, "CA_OBJ_SHIFT", INT2NUM(CA_OBJ_SHIFT));
975
413
 
976
- rb_define_method(rb_cCArray, "shifted", rb_ca_shift, -1);
414
+ rb_define_method(rb_cCArray, "shift", rb_ca_shift, -1);
415
+ /* "shift!" removed in 3.0; "roll" defined in Init_ca_obj_roll. */
977
416
 
978
417
  rb_define_alloc_func(rb_cCAShift, rb_ca_shift_s_allocate);
979
418
  rb_define_method(rb_cCAShift, "initialize_copy",
980
419
  rb_ca_shift_initialize_copy, 1);
981
420
  }
982
-