carray 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -25
  3. data/CHANGELOG.md +16 -0
  4. data/LICENSE +1 -1
  5. data/NEWS.md +3 -0
  6. data/README.md +128 -44
  7. data/carray.gemspec +22 -24
  8. data/ext/ca_array_pool.c +91 -0
  9. data/ext/ca_axis_descriptor.h +186 -0
  10. data/ext/ca_axis_dispatch.c +924 -0
  11. data/ext/ca_axis_group.c +1208 -0
  12. data/ext/ca_bincmp_dispatch.c +76 -0
  13. data/ext/ca_bincmp_dispatch.h +85 -0
  14. data/ext/ca_binop_dispatch.c +125 -0
  15. data/ext/ca_binop_dispatch.h +159 -0
  16. data/ext/ca_categorical_iterator.c +1375 -0
  17. data/ext/ca_compare.c +94 -0
  18. data/ext/ca_compare.h +26 -0
  19. data/ext/ca_composite_dispatch.c +414 -0
  20. data/ext/ca_composite_dispatch.h +116 -0
  21. data/ext/ca_for_buffer.h +96 -0
  22. data/ext/ca_for_each_element.h +241 -0
  23. data/ext/ca_group_iter.c +304 -0
  24. data/ext/ca_iter_substrate.h +325 -0
  25. data/ext/ca_kernel_iterator.c +4321 -0
  26. data/ext/ca_kernel_iterator.h +2603 -0
  27. data/ext/ca_moncmp_dispatch.c +37 -0
  28. data/ext/ca_moncmp_dispatch.h +62 -0
  29. data/ext/ca_monop_dispatch.c +200 -0
  30. data/ext/ca_monop_dispatch.h +235 -0
  31. data/ext/ca_obj_array.c +355 -359
  32. data/ext/ca_obj_bincmp.c +809 -0
  33. data/ext/ca_obj_binop.c +892 -0
  34. data/ext/ca_obj_bitarray.c +369 -164
  35. data/ext/ca_obj_bitfield.c +294 -234
  36. data/ext/ca_obj_block.c +189 -711
  37. data/ext/ca_obj_byte_swap.c +766 -0
  38. data/ext/ca_obj_const_string.c +965 -0
  39. data/ext/ca_obj_face.c +670 -0
  40. data/ext/ca_obj_face.h +247 -0
  41. data/ext/ca_obj_fake.c +228 -100
  42. data/ext/ca_obj_farray.c +54 -441
  43. data/ext/ca_obj_field.c +82 -529
  44. data/ext/ca_obj_fixlen_string.c +306 -0
  45. data/ext/ca_obj_grid.c +858 -440
  46. data/ext/ca_obj_meld.c +1034 -0
  47. data/ext/ca_obj_moncmp.c +569 -0
  48. data/ext/ca_obj_monop.c +1111 -0
  49. data/ext/ca_obj_object.c +774 -298
  50. data/ext/ca_obj_record.c +468 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +569 -459
  53. data/ext/ca_obj_remap.c +475 -0
  54. data/ext/ca_obj_repeat.c +92 -477
  55. data/ext/ca_obj_roll.c +616 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1296 -0
  58. data/ext/ca_obj_shift.c +230 -792
  59. data/ext/ca_obj_source.c +78 -0
  60. data/ext/ca_obj_stack.c +1173 -0
  61. data/ext/ca_obj_stride.c +2501 -0
  62. data/ext/ca_obj_string.c +268 -0
  63. data/ext/ca_obj_tile.c +614 -0
  64. data/ext/ca_obj_time.c +546 -0
  65. data/ext/ca_obj_timedelta.c +435 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +746 -0
  68. data/ext/ca_obj_unbound_repeat.c +208 -241
  69. data/ext/ca_obj_window.c +1131 -563
  70. data/ext/ca_op_byte_swap.c +175 -0
  71. data/ext/ca_op_ipower.c +319 -0
  72. data/ext/ca_op_powi.h +88 -0
  73. data/ext/ca_sort_kernels.h +132 -0
  74. data/ext/ca_sweep_engine.c +430 -0
  75. data/ext/ca_sweep_engine.h +157 -0
  76. data/ext/ca_transform_common.c +228 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +795 -402
  80. data/ext/carray_access.c +831 -711
  81. data/ext/carray_attribute.c +98 -330
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +283 -0
  84. data/ext/carray_call_cfunc.c +1360 -828
  85. data/ext/carray_call_cfunc.h +160 -0
  86. data/ext/carray_cast.c +1212 -301
  87. data/ext/carray_cast_func.rb +81 -40
  88. data/ext/carray_class.c +53 -63
  89. data/ext/carray_config.h +28 -0
  90. data/ext/carray_conversion.c +350 -346
  91. data/ext/carray_copy.c +156 -268
  92. data/ext/carray_core.c +1342 -199
  93. data/ext/carray_count.c +312 -0
  94. data/ext/carray_data_type.c +43 -19
  95. data/ext/carray_element.c +585 -213
  96. data/ext/carray_factorize.c +2542 -0
  97. data/ext/carray_generate.c +230 -559
  98. data/ext/carray_histogram.c +490 -0
  99. data/ext/carray_hold.c +228 -0
  100. data/ext/carray_index_classifier.c +1035 -0
  101. data/ext/carray_index_classifier.h +27 -0
  102. data/ext/carray_internal.h +120 -0
  103. data/ext/carray_kernels_bincmp.c +4445 -0
  104. data/ext/carray_kernels_binop.c +10979 -0
  105. data/ext/carray_kernels_init.c +36 -0
  106. data/ext/carray_kernels_map.c +3466 -0
  107. data/ext/carray_kernels_moncmp.c +2096 -0
  108. data/ext/carray_kernels_monop.c +18312 -0
  109. data/ext/carray_kernels_reduce_aggregate.c +25836 -0
  110. data/ext/carray_kernels_reduce_boolean.c +329 -0
  111. data/ext/carray_kernels_reduce_cumulative.c +14592 -0
  112. data/ext/carray_kernels_reduce_extreme.c +16947 -0
  113. data/ext/carray_kernels_reduce_variance.c +3909 -0
  114. data/ext/carray_kernels_scan.c +3692 -0
  115. data/ext/carray_kernels_search.c +32137 -0
  116. data/ext/carray_kernels_sort.c +10625 -0
  117. data/ext/carray_kernels_triop.c +1391 -0
  118. data/ext/carray_lazy.c +567 -0
  119. data/ext/carray_loop.c +88 -200
  120. data/ext/carray_mask.c +848 -154
  121. data/ext/carray_math_kernel.h +120 -0
  122. data/ext/carray_mathfunc.c +10 -241
  123. data/ext/carray_median_percentile.c +1257 -0
  124. data/ext/carray_memory_view.c +1625 -0
  125. data/ext/carray_operator.c +1526 -318
  126. data/ext/carray_order.c +664 -1394
  127. data/ext/carray_partition.c +416 -0
  128. data/ext/carray_random.c +518 -0
  129. data/ext/carray_scatter.c +357 -0
  130. data/ext/carray_slab.c +1219 -0
  131. data/ext/carray_slab.h +84 -0
  132. data/ext/carray_sort.c +829 -0
  133. data/ext/carray_sort_kernel.c +620 -0
  134. data/ext/carray_struct.c +695 -0
  135. data/ext/carray_test.c +343 -229
  136. data/ext/carray_undef.c +34 -17
  137. data/ext/carray_utils.c +175 -74
  138. data/ext/extconf.rb +216 -55
  139. data/ext/mk_call_cfunc.rb +480 -0
  140. data/ext/mkkernel.rb +8842 -0
  141. data/ext/ruby_carray.c +202 -101
  142. data/ext/version.h +4 -14
  143. data/ext/version.rb +5 -13
  144. data/lib/carray/arrow_tensor.rb +401 -0
  145. data/lib/carray/attribute.rb +166 -0
  146. data/lib/carray/autoload_carray.rb +220 -0
  147. data/lib/carray/autoload_method_extension.rb +44 -0
  148. data/lib/carray/axis_group.rb +711 -0
  149. data/lib/carray/basics.rb +481 -0
  150. data/lib/carray/bincount_nd.rb +358 -0
  151. data/lib/carray/block_iterator.rb +604 -0
  152. data/lib/carray/boolean_reduce.rb +109 -0
  153. data/lib/carray/categorical.rb +561 -0
  154. data/lib/carray/categorical_iterator.rb +1062 -0
  155. data/lib/carray/complex.rb +150 -0
  156. data/lib/carray/conditional.rb +216 -0
  157. data/lib/carray/const_string.rb +228 -0
  158. data/lib/carray/construct.rb +139 -328
  159. data/lib/carray/core_extensions.rb +240 -0
  160. data/lib/carray/data_type_extension.rb +233 -0
  161. data/lib/carray/fixlen_string.rb +95 -0
  162. data/lib/carray/frame/concat.rb +132 -0
  163. data/lib/carray/frame/convert.rb +95 -0
  164. data/lib/carray/frame/csv_parser.rb +211 -0
  165. data/lib/carray/frame/frame.rb +649 -0
  166. data/lib/carray/frame/group.rb +186 -0
  167. data/lib/carray/frame/io.rb +164 -0
  168. data/lib/carray/frame/join.rb +248 -0
  169. data/lib/carray/frame/records.rb +99 -0
  170. data/lib/carray/frame/sort.rb +113 -0
  171. data/lib/carray/frame/verbs.rb +299 -0
  172. data/lib/carray/frame.rb +16 -0
  173. data/lib/carray/histogram.rb +512 -0
  174. data/lib/carray/inspect.rb +37 -20
  175. data/lib/carray/iterator.rb +57 -349
  176. data/lib/carray/lazy.rb +889 -0
  177. data/lib/carray/mask_gap_fill.rb +200 -0
  178. data/lib/carray/math.rb +78 -342
  179. data/lib/carray/meld_reduce.rb +289 -0
  180. data/lib/carray/methods/align_addr.rb +116 -0
  181. data/lib/carray/methods/bin.rb +128 -0
  182. data/lib/carray/methods/bincount.rb +87 -0
  183. data/lib/carray/methods/bit_string.rb +92 -0
  184. data/lib/carray/methods/broadcast.rb +63 -0
  185. data/lib/carray/methods/choose.rb +39 -0
  186. data/lib/carray/methods/composition.rb +280 -0
  187. data/lib/carray/methods/gather_nd.rb +206 -0
  188. data/lib/carray/methods/index.rb +39 -0
  189. data/lib/carray/methods/insert_block.rb +99 -0
  190. data/lib/carray/methods/is_in.rb +141 -0
  191. data/lib/carray/methods/join.rb +90 -0
  192. data/lib/carray/methods/locate_addr.rb +47 -0
  193. data/lib/carray/methods/mask_duplicates.rb +41 -0
  194. data/lib/carray/methods/meshgrid.rb +91 -0
  195. data/lib/carray/methods/mode.rb +126 -0
  196. data/lib/carray/methods/nunique.rb +46 -0
  197. data/lib/carray/methods/resize.rb +56 -0
  198. data/lib/carray/methods/snap.rb +156 -0
  199. data/lib/carray/methods/string_format.rb +57 -0
  200. data/lib/carray/methods/unique.rb +47 -0
  201. data/lib/carray/methods/value_counts.rb +71 -0
  202. data/lib/carray/mkmf.rb +124 -101
  203. data/lib/carray/runtime.rb +108 -0
  204. data/lib/carray/serialize.rb +478 -167
  205. data/lib/carray/slab_iterator.rb +292 -0
  206. data/lib/carray/stack.rb +291 -0
  207. data/lib/carray/string.rb +56 -180
  208. data/lib/carray/string_operation_extension.rb +289 -0
  209. data/lib/carray/struct.rb +335 -323
  210. data/lib/carray/struct_builder.rb +697 -0
  211. data/lib/carray/table.rb +41 -2
  212. data/lib/carray/time.rb +2255 -38
  213. data/lib/carray/window_iterator.rb +655 -0
  214. data/lib/carray.rb +55 -57
  215. metadata +163 -130
  216. data/Rakefile +0 -51
  217. data/TODO.md +0 -18
  218. data/ext/ca_iter_block.c +0 -257
  219. data/ext/ca_iter_dimension.c +0 -299
  220. data/ext/ca_iter_window.c +0 -214
  221. data/ext/ca_obj_mapping.c +0 -644
  222. data/ext/carray_iterator.c +0 -641
  223. data/ext/carray_math.rb +0 -850
  224. data/ext/carray_numeric.c +0 -259
  225. data/ext/carray_sort_addr.c +0 -254
  226. data/ext/carray_stat.c +0 -2100
  227. data/ext/carray_stat_proc.rb +0 -1999
  228. data/ext/mkmath.rb +0 -741
  229. data/ext/ruby_ccomplex.c +0 -509
  230. data/ext/ruby_float_func.c +0 -86
  231. data/lib/carray/array.rb +0 -8
  232. data/lib/carray/autoload/autoload_base.rb +0 -19
  233. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  234. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  235. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  236. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  237. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  238. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  239. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  240. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  241. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  242. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  243. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  244. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  245. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  246. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  247. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  248. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  249. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  250. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  251. data/lib/carray/autoload.rb +0 -141
  252. data/lib/carray/basic.rb +0 -191
  253. data/lib/carray/broadcast.rb +0 -101
  254. data/lib/carray/compose.rb +0 -315
  255. data/lib/carray/convert.rb +0 -115
  256. data/lib/carray/info.rb +0 -110
  257. data/lib/carray/io/imagemagick.rb +0 -235
  258. data/lib/carray/mask.rb +0 -102
  259. data/lib/carray/math/histogram.rb +0 -177
  260. data/lib/carray/math/recurrence.rb +0 -93
  261. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  262. data/lib/carray/object/ca_obj_link.rb +0 -50
  263. data/lib/carray/object/ca_obj_pack.rb +0 -99
  264. data/lib/carray/obsolete.rb +0 -256
  265. data/lib/carray/ordering.rb +0 -181
  266. data/lib/carray/testing.rb +0 -51
  267. data/lib/carray/transform.rb +0 -109
  268. data/misc/Methods.ja.md +0 -182
  269. data/misc/NOTE +0 -51
  270. data/spec/Classes/CABitfield_spec.rb +0 -58
  271. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  272. data/spec/Classes/CABlock_spec.rb +0 -205
  273. data/spec/Classes/CAField_spec.rb +0 -39
  274. data/spec/Classes/CAGrid_spec.rb +0 -75
  275. data/spec/Classes/CAMap_spec.rb +0 -0
  276. data/spec/Classes/CAMapping_spec.rb +0 -105
  277. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  278. data/spec/Classes/CAObject_spec.rb +0 -33
  279. data/spec/Classes/CARefer_spec.rb +0 -93
  280. data/spec/Classes/CARepeat_spec.rb +0 -65
  281. data/spec/Classes/CASelect_spec.rb +0 -22
  282. data/spec/Classes/CAShift_spec.rb +0 -16
  283. data/spec/Classes/CAStruct_spec.rb +0 -71
  284. data/spec/Classes/CATranspose_spec.rb +0 -60
  285. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  286. data/spec/Classes/CAWindow_spec.rb +0 -54
  287. data/spec/Classes/CAWrap_spec.rb +0 -8
  288. data/spec/Classes/CArray_spec.rb +0 -184
  289. data/spec/Classes/CScalar_spec.rb +0 -55
  290. data/spec/Classes/ex1.rb +0 -46
  291. data/spec/Features/feature_130_spec.rb +0 -19
  292. data/spec/Features/feature_attributes_spec.rb +0 -280
  293. data/spec/Features/feature_boolean_spec.rb +0 -98
  294. data/spec/Features/feature_broadcast.rb +0 -116
  295. data/spec/Features/feature_cast_function.rb +0 -19
  296. data/spec/Features/feature_cast_spec.rb +0 -33
  297. data/spec/Features/feature_class_spec.rb +0 -84
  298. data/spec/Features/feature_complex_spec.rb +0 -42
  299. data/spec/Features/feature_composite_spec.rb +0 -124
  300. data/spec/Features/feature_convert_spec.rb +0 -46
  301. data/spec/Features/feature_copy_spec.rb +0 -123
  302. data/spec/Features/feature_creation_spec.rb +0 -84
  303. data/spec/Features/feature_element_spec.rb +0 -144
  304. data/spec/Features/feature_extream_spec.rb +0 -54
  305. data/spec/Features/feature_generate_spec.rb +0 -74
  306. data/spec/Features/feature_index_spec.rb +0 -69
  307. data/spec/Features/feature_mask_spec.rb +0 -580
  308. data/spec/Features/feature_math_spec.rb +0 -97
  309. data/spec/Features/feature_order_spec.rb +0 -146
  310. data/spec/Features/feature_ref_store_spec.rb +0 -209
  311. data/spec/Features/feature_serialization_spec.rb +0 -125
  312. data/spec/Features/feature_stat_spec.rb +0 -397
  313. data/spec/Features/feature_virtual_spec.rb +0 -48
  314. data/spec/Features/method_eq_spec.rb +0 -81
  315. data/spec/Features/method_is_nan_spec.rb +0 -12
  316. data/spec/Features/method_map_spec.rb +0 -54
  317. data/spec/Features/method_max_with.rb +0 -20
  318. data/spec/Features/method_min_with.rb +0 -19
  319. data/spec/Features/method_ne_spec.rb +0 -18
  320. data/spec/Features/method_project_spec.rb +0 -188
  321. data/spec/Features/method_ref_spec.rb +0 -27
  322. data/spec/Features/method_round_spec.rb +0 -11
  323. data/spec/Features/method_s_linspace_spec.rb +0 -48
  324. data/spec/Features/method_s_span_spec.rb +0 -14
  325. data/spec/Features/method_seq_spec.rb +0 -47
  326. data/spec/Features/method_sort_with.rb +0 -43
  327. data/spec/Features/method_sorted_with.rb +0 -29
  328. data/spec/Features/method_span_spec.rb +0 -42
  329. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  330. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  331. data/spec/spec_all.rb +0 -10
  332. data/utils/ca_ase.rb +0 -21
  333. data/utils/ca_methods.rb +0 -15
  334. data/utils/cast_checker.rb +0 -30
  335. data/utils/convert_test.rb +0 -73
  336. data/utils/extract_yard.rb +0 -22
  337. data/utils/guess_shape.rb +0 -76
  338. data/utils/monkey_patch_methods.rb +0 -62
  339. data/utils/remove_resource_fork.sh +0 -5
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
- .wrap_struct_name = "CAShift",
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,800 +65,202 @@ 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);
237
- }
238
- else {
239
- return ca->parent->ptr + ca->bytes * n;
240
- }
241
- }
242
- else {
243
- return ca_func[CA_OBJ_ARRAY].ptr_at_index(ca, idx);
244
- }
245
- }
246
-
247
- static void
248
- ca_shift_func_fetch_index (void *ap, ca_size_t *idx, void *ptr)
249
- {
250
- 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);
135
+ xfree(ca->fill); /* always separate (bytes-sized) */
136
+ if ( ca->_pool ) {
137
+ ca_array_free(ca);
260
138
  }
261
139
  else {
262
- k = ca_shift_shifted_index(ca, i, k);
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);
263
148
  }
264
-
265
- if ( k < 0 ) {
266
- memcpy(ptr, ca->fill, ca->bytes);
267
- return;
268
- }
269
- n = dim[i] * n + k;
270
149
  }
271
- ca_fetch_addr(ca->parent, n, ptr);
272
150
  }
273
151
 
274
- static void
275
- ca_shift_func_store_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)
276
156
  {
277
157
  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
- }
158
+ ca_size_t shift[CA_RANK_MAX];
159
+ int8_t roll[CA_RANK_MAX];
160
+ int fill_mask = 0;
161
+ int8_t k;
291
162
 
292
- if ( k < 0 ) {
293
- 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;
294
171
  }
295
- n = dim[i] * n + k;
296
172
  }
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
173
 
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
- }
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 */
394
239
  }
395
240
 
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
241
  /* ------------------------------------------------------------------- */
418
242
 
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);
814
- }
815
-
816
- /* ------------------------------------------------------------------- */
817
-
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
  {
@@ -867,6 +270,7 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
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
304
  if ( rfval == CA_NIL ) {
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_FACE_LIFT_IF_FACE(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
-