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_select.c CHANGED
@@ -1,19 +1,22 @@
1
1
  /* ---------------------------------------------------------------------------
2
2
 
3
- ca_obj_select.c
4
-
5
- This file is part of Ruby/CArray extension library.
6
-
7
- Copyright (C) 2005-2020 Hiroki Motoyoshi
3
+ CASelect view: 1-D gather of the parent through a boolean selector.
4
+ The view snapshots the selector at construction time and pre-computes
5
+ `indices[]` (the flat parent positions where the selector is TRUE).
6
+
7
+ Sibling of ca_axis_dispatch.c (the per-axis descriptor engine).
8
+ attach / sync / xfer_all / xfer_stride / fill_data all dispatch
9
+ through `ca_axis_dispatch_*` with a single 1-D INDEX descriptor over
10
+ a flattened parent (parent_axis_dims = {parent->elements}). When
11
+ the TRUE positions form a constant-step run, the descriptor is
12
+ promoted to STRIDE kind so the engine's contig-memcpy fast path
13
+ becomes available.
8
14
 
9
15
  ---------------------------------------------------------------------------- */
10
16
 
11
17
  #include "carray.h"
12
-
13
- /* yard:
14
- class CASelect < CAVirtual # :nodoc:
15
- end
16
- */
18
+ #include "carray_internal.h" /* per-obj_type view constructors */
19
+ #include "ca_obj_face.h"
17
20
 
18
21
  typedef struct {
19
22
  int16_t obj_type;
@@ -25,21 +28,38 @@ typedef struct {
25
28
  ca_size_t *dim; /* point to _dim */
26
29
  char *ptr;
27
30
  CArray *mask;
31
+ char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path). */
28
32
  CArray *parent;
29
33
  uint32_t attach;
30
34
  uint8_t nosync;
31
35
  /* ---------- */
32
- CArray *select;
36
+ CArray *select; /* snapshot of selector (boolean array, owned) */
37
+ ca_size_t *indices; /* snapshot of TRUE positions in flat parent
38
+ (length = ca->elements; engine consumes this) */
39
+ /* Constant-step detection on indices[]. When TRUE positions form
40
+ an arithmetic progression (consecutive TRUE block, all-TRUE,
41
+ equally spaced), the descriptor is emitted as STRIDE kind
42
+ instead of INDEX to unlock the engine's contig-memcpy path. */
43
+ uint8_t stride_kind;
44
+ ca_size_t stride_start;
45
+ ca_size_t stride_step;
33
46
  ca_size_t _dim;
34
47
  } CASelect;
35
48
 
49
+ static size_t
50
+ ca_select_dsize (const void *ap)
51
+ {
52
+ /* CASelect: dim points to _dim inside struct, no separate allocation */
53
+ return sizeof(CASelect);
54
+ }
55
+
36
56
  const rb_data_type_t caselect_data_type = {
37
- .parent = &cavirtual_data_type,
57
+ .parent = &caview_data_type,
38
58
  .wrap_struct_name = "CASelect",
39
59
  .function = {
40
60
  .dmark = ca_mark,
41
61
  .dfree = ca_free,
42
- .dsize = NULL,
62
+ .dsize = ca_select_dsize,
43
63
  .dcompact = NULL
44
64
  },
45
65
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
@@ -51,7 +71,7 @@ const rb_data_type_t caselect_mask_data_type = {
51
71
  .function = {
52
72
  .dmark = NULL,
53
73
  .dfree = ca_free_nop,
54
- .dsize = NULL,
74
+ .dsize = ca_select_dsize,
55
75
  .dcompact = NULL
56
76
  },
57
77
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
@@ -63,12 +83,16 @@ VALUE rb_cCASelectMask;
63
83
 
64
84
  /* ------------------------------------------------------------------- */
65
85
 
86
+ /* Snapshot the selector into ca->select (always a copy) and pre-compute
87
+ ca->indices (TRUE positions in flat parent order). Masked selector
88
+ cells become false in the snapshot. After construction, mutating
89
+ the caller's live selector does not affect the view. */
66
90
  static int
67
91
  ca_select_setup (CASelect *ca, CArray *parent, CArray *select, int share)
68
92
  {
69
93
  int8_t data_type;
70
94
  ca_size_t bytes;
71
- int i;
95
+ ca_size_t i;
72
96
 
73
97
  if ( ! ca_is_boolean_type(select) ) {
74
98
  rb_raise(rb_eRuntimeError,
@@ -84,51 +108,79 @@ ca_select_setup (CASelect *ca, CArray *parent, CArray *select, int share)
84
108
  ca->flags = 0;
85
109
  ca->ndim = 1;
86
110
  ca->bytes = bytes;
87
-
88
- if ( share && ca_is_entity(select) ) {
89
- ca_set_flag(ca, CA_FLAG_SHARE_INDEX);
90
- ca->select = select;
91
- }
92
- else {
93
- if ( ca_has_mask(select) ) {
94
- boolean8_t *p, *q, *m;
95
- ca->select = ca_template(select);
96
- ca_attach(select);
97
- q = (boolean8_t *) ca->select->ptr;
98
- p = (boolean8_t *) select->ptr;
99
- m = (boolean8_t *) select->mask->ptr;
100
- for (i=0; i<select->elements; i++) {
101
- *q = ( *m ) ? 0 : *p;
102
- q++; p++; m++;
103
- }
104
- ca_detach(select);
105
- }
106
- else {
107
- ca->select = ca_copy(select);
111
+ ca->ptr = NULL;
112
+ ca->mask = NULL;
113
+ ca->parent = parent;
114
+ ca->attach = 0;
115
+ ca->nosync = 0;
116
+ ca->indices = NULL;
117
+
118
+ /* The `share` argument is preserved for source compatibility but
119
+ no longer toggles a live-reference path; both paths copy.
120
+ Masked selector cells become false in the snapshot. */
121
+ (void) share;
122
+ if ( ca_has_mask(select) ) {
123
+ boolean8_t *p, *q, *m;
124
+ ca->select = ca_template(select);
125
+ ca_attach(select);
126
+ q = (boolean8_t *) ca->select->ptr;
127
+ p = (boolean8_t *) select->ptr;
128
+ m = (boolean8_t *) select->mask->ptr;
129
+ for (i = 0; i < select->elements; i++) {
130
+ *q = ( *m ) ? 0 : *p;
131
+ q++; p++; m++;
108
132
  }
133
+ ca_detach(select);
134
+ } else {
135
+ ca->select = ca_copy(select);
109
136
  }
110
137
 
138
+ /* Count TRUE positions and snapshot them into ca->indices. */
111
139
  {
112
- int count = 0;
113
140
  boolean8_t *s = (boolean8_t *) ca->select->ptr;
114
- for (i=0; i<ca->select->elements; i++) {
115
- if ( *s ) {
116
- count++;
141
+ ca_size_t count = 0;
142
+ for (i = 0; i < ca->select->elements; i++) {
143
+ if ( s[i] ) count++;
144
+ }
145
+ ca->elements = count;
146
+ /* Placeholder 1-element allocation when count == 0 to avoid
147
+ malloc(0) implementation variance; the engine treats
148
+ elements==0 as a no-op so the contents are irrelevant. */
149
+ ca->indices = (ca_size_t *) xmalloc(
150
+ sizeof(ca_size_t) * (count > 0 ? count : 1));
151
+ {
152
+ ca_size_t j = 0;
153
+ for (i = 0; i < ca->select->elements; i++) {
154
+ if ( s[i] ) ca->indices[j++] = i;
117
155
  }
118
- s++;
119
156
  }
120
- ca->elements = count;
157
+ /* Constant-step detection: promotes to STRIDE descriptor kind
158
+ when TRUE positions form an arithmetic progression. */
159
+ ca->stride_kind = 0;
160
+ ca->stride_start = 0;
161
+ ca->stride_step = 1;
162
+ if ( count >= 2 ) {
163
+ ca_size_t step = ca->indices[1] - ca->indices[0];
164
+ ca_size_t k;
165
+ int is_const = 1;
166
+ for ( k = 2; k < count; k++ ) {
167
+ if ( ca->indices[k] - ca->indices[k-1] != step ) { is_const = 0; break; }
168
+ }
169
+ if ( is_const ) {
170
+ ca->stride_kind = 1;
171
+ ca->stride_start = ca->indices[0];
172
+ ca->stride_step = step;
173
+ }
174
+ } else if ( count == 1 ) {
175
+ ca->stride_kind = 1;
176
+ ca->stride_start = ca->indices[0];
177
+ ca->stride_step = 1;
178
+ }
121
179
  }
122
180
 
123
- ca->ptr = NULL;
124
- ca->mask = NULL;
125
181
  ca->dim = &(ca->_dim);
126
182
  ca->dim[0] = ca->elements;
127
183
 
128
- ca->parent = parent;
129
- ca->attach = 0;
130
- ca->nosync = 0;
131
-
132
184
  if ( ca_is_scalar(select) ) {
133
185
  ca_set_flag(ca, CA_FLAG_SCALAR);
134
186
  }
@@ -144,6 +196,9 @@ ca_select_new (CArray *parent, CArray *select)
144
196
  return (CArray*) ca;
145
197
  }
146
198
 
199
+ /* Alias for source compatibility. Both constructors produce a
200
+ snapshot view; the `share` name is retained because a handful of
201
+ internal call sites still pass a `share` flag. */
147
202
  CArray *
148
203
  ca_select_new_share (CArray *parent, CArray *select)
149
204
  {
@@ -158,18 +213,40 @@ free_ca_select (void *ap)
158
213
  CASelect *ca = (CASelect *) ap;
159
214
  if ( ca != NULL ) {
160
215
  ca_free(ca->mask);
161
- if ( ! (ca->flags & CA_FLAG_SHARE_INDEX) ) {
162
- ca_free(ca->select);
163
- }
216
+ ca_free(ca->select); /* the snapshot is always owned */
217
+ if ( ca->indices ) xfree(ca->indices);
164
218
  xfree(ca);
165
219
  }
166
220
  }
167
221
 
168
- void ca_select_to_ptr (CArray *ca, CArray *select, char *ptr);
169
- void ca_select_from_ptr (CArray *ca, CArray *select, char *ptr);
170
- void ca_select_fill (CArray *ca, CArray *select, char *valp);
171
- void ca_select_to_carray (CArray *ca, CArray *select, CArray *cs);
172
- void ca_select_from_carray (CArray *ca, CArray *select, CArray *cs);
222
+ /* ------------------------------------------------------------------- */
223
+ /* Producer for the per-axis descriptor engine: emit a single 1-D axis.
224
+ Writes 1 entry into `out` and `out_parent_dims`. parent_axis_dims[0]
225
+ is the flattened parent length, so the engine treats the parent as
226
+ 1-D regardless of its original shape. */
227
+
228
+ void
229
+ ca_select_describe_axes (void *ap, ca_axis_desc_t *out,
230
+ ca_size_t *out_parent_dims)
231
+ {
232
+ CASelect *ca = (CASelect *) ap;
233
+ out_parent_dims[0] = ca->parent->elements;
234
+ if ( ca->stride_kind ) {
235
+ /* Constant-step run: emit STRIDE so the engine's contig-memcpy
236
+ fast path is available (all-TRUE, block-TRUE, equally-spaced). */
237
+ out[0].kind = CA_AXIS_KIND_STRIDE;
238
+ out[0].count = ca->elements;
239
+ out[0].start = ca->stride_start;
240
+ out[0].step = ca->stride_step;
241
+ out[0].indices = NULL;
242
+ } else {
243
+ out[0].kind = CA_AXIS_KIND_INDEX;
244
+ out[0].count = ca->elements;
245
+ out[0].start = 0;
246
+ out[0].step = 0;
247
+ out[0].indices = ca->indices;
248
+ }
249
+ }
173
250
 
174
251
  /* ------------------------------------------------------------------- */
175
252
 
@@ -180,107 +257,146 @@ ca_select_func_clone (void *ap)
180
257
  return ca_select_new_share(ca->parent, ca->select);
181
258
  }
182
259
 
183
- static char *
184
- ca_select_func_ptr_at_addr (void *ap, ca_size_t addr)
185
- {
186
- CASelect *ca = (CASelect *) ap;
187
-
188
- if ( ca->ptr ) {
189
- return ca->ptr + ca->bytes * addr;
190
- }
191
- else {
192
- ca_size_t n, i, a;
193
- ca_size_t elements = ca->select->elements;
194
- boolean8_t s;
195
-
196
- n = 0;
197
- a = 0;
198
-
199
- for (i=0; i<elements; i++) {
200
- ca_fetch_addr(ca->select, i, &s);
201
- if ( s ) {
202
- if ( addr == a++ ) {
203
- n = i;
204
- break;
205
- }
206
- }
207
- }
208
-
209
- if ( ca_is_attached(ca->parent) ) {
210
- return ca->parent->ptr + ca->bytes * n;
211
- }
212
- else {
213
- return ca_ptr_at_addr(ca->parent, n);
214
- }
215
- }
216
- }
260
+ static void ca_select_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data, int dir);
217
261
 
218
- static char *
219
- ca_select_func_ptr_at_index (void *ap, ca_size_t *idx)
262
+ static void
263
+ ca_select_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
220
264
  {
221
- CASelect *ca = (CASelect *) ap;
222
- ca_size_t addr = idx[0];
223
-
224
- if ( ca->ptr ) {
225
- return ca->ptr + ca->bytes * addr;
226
- }
227
- else {
228
- return ca_select_func_ptr_at_addr(ca, idx[0]);
229
- }
265
+ ca_select_func_xfer_addrs(ap, 1, &idx[0], data, dir);
230
266
  }
231
267
 
268
+ /* Translate the incoming address list through ca->indices and deliver
269
+ to the parent in one call.
270
+
271
+ Fast path: when `addrs` covers the whole view sequentially and the
272
+ parent is attached, the pre-built ca->indices is handed straight to
273
+ the descriptor engine (zero copy, no ALLOCV). This is the same
274
+ 1-D-INDEX-over-flat-parent dispatch attach / sync use, so a chain
275
+ like `a[idx_2d]` (which reshape/CAGrid folds down to whole-view
276
+ sequential addrs on CASelect) also lands on the fast path. */
232
277
  static void
233
- ca_select_func_fetch_addr (void *ap, ca_size_t addr, void *ptr)
278
+ ca_select_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
279
+ void *data, int dir)
234
280
  {
235
- CASelect *ca = (CASelect *) ap;
236
- ca_size_t n, i, a;
237
- ca_size_t elements = ca->select->elements;
238
- boolean8_t s;
239
- n = 0;
240
- a = 0;
241
- for (i=0; i<elements; i++) {
242
- ca_fetch_addr(ca->select, i, &s);
243
- if ( s ) {
244
- if ( addr == a++ ) {
245
- n = i;
246
- break;
281
+ CASelect *ca = (CASelect *) ap;
282
+ CArray *parent = ca->parent;
283
+ ca_size_t *paddrs;
284
+ ca_size_t i, base;
285
+ volatile VALUE holder;
286
+
287
+ if ( n == ca->elements
288
+ && ca_xfer_addrs_is_sequential_run(n, addrs, &base) && base == 0 ) {
289
+ CArray *eff_parent = ca_resolve_attached_root_via_identity(parent);
290
+ if ( eff_parent->ptr ) {
291
+ ca_axis_desc_t sub_axes[1];
292
+ ca_size_t parent_axis_dims[1];
293
+ parent_axis_dims[0] = parent->elements;
294
+ if ( ca->stride_kind ) {
295
+ sub_axes[0].kind = CA_AXIS_KIND_STRIDE;
296
+ sub_axes[0].count = ca->elements;
297
+ sub_axes[0].start = ca->stride_start;
298
+ sub_axes[0].step = ca->stride_step;
299
+ sub_axes[0].indices = NULL;
300
+ } else {
301
+ sub_axes[0].kind = CA_AXIS_KIND_INDEX;
302
+ sub_axes[0].count = ca->elements;
303
+ sub_axes[0].start = 0;
304
+ sub_axes[0].step = 0;
305
+ sub_axes[0].indices = ca->indices;
306
+ }
307
+ if ( dir == CA_XFER_GET ) {
308
+ ca_axis_dispatch_gather(eff_parent, parent_axis_dims, sub_axes, 1,
309
+ ca->bytes, ca->elements, NULL, (char *) data);
310
+ } else {
311
+ ca_axis_dispatch_scatter(eff_parent, parent_axis_dims, sub_axes, 1,
312
+ ca->bytes, ca->elements, (char *) data);
247
313
  }
314
+ return;
248
315
  }
249
316
  }
250
- ca_fetch_addr(ca->parent, n, ptr);
251
- }
252
317
 
253
- static void
254
- ca_select_func_fetch_index (void *ap, ca_size_t *idx, void *ptr)
255
- {
256
- ca_select_func_fetch_addr(ap, idx[0], ptr);
318
+ /* Per-cell remap fallback (arbitrary addrs or unattached parent). */
319
+ paddrs = ALLOCV_N(ca_size_t, holder, n);
320
+ for ( i = 0; i < n; i++ ) {
321
+ paddrs[i] = ca->indices[addrs[i]];
322
+ }
323
+ ca_xfer_addrs(ca->parent, n, paddrs, data, dir);
324
+ ALLOCV_END(holder);
257
325
  }
258
326
 
327
+ /* CASelect is the never-fold gather boundary: the incoming strided
328
+ region request describes a 1-D access into the selection, which
329
+ the view translates to a parent address list and delegates in one
330
+ call. `data` is contiguous (row-major over counts).
331
+
332
+ Access into the selection is
333
+ position = starts[0] + i * (strides[0] / bytes)
334
+ and ca->indices[position] is the parent address. ca->indices is a
335
+ construction-time snapshot, so no attach is required. */
259
336
  static void
260
- ca_select_func_store_addr (void *ap, ca_size_t addr, void *ptr)
337
+ ca_select_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
338
+ ca_size_t *strides, void *data, int dir)
261
339
  {
262
- CASelect *ca = (CASelect *) ap;
263
- ca_size_t n, i, a;
264
- ca_size_t elements = ca->select->elements;
265
- boolean8_t s;
266
- n = 0;
267
- a = 0;
268
- for (i=0; i<elements; i++) {
269
- ca_fetch_addr(ca->select, i, &s);
270
- if ( s ) {
271
- if ( addr == a++ ) {
272
- n = i;
273
- break;
340
+ CASelect *ca = (CASelect *) ap;
341
+ CArray *parent = ca->parent;
342
+ ca_size_t n = counts[0];
343
+ ca_size_t step = strides[0] / ca->bytes; /* element step (may be negative) */
344
+ ca_size_t start = starts[0];
345
+
346
+ /* Attached-parent fast path: translate the sub-region request
347
+ (start / n / step over the 1-D INDEX view) into a transient
348
+ ca_axis_desc_t[1] and dispatch through the engine directly,
349
+ without calling ca_attach(parent). Collapses the per-cell
350
+ ca_xfer_addrs loop into a single batched engine call. */
351
+ if ( parent->ptr ) {
352
+ ca_axis_desc_t sub_axes[1];
353
+ ca_size_t parent_axis_dims[1];
354
+ ca_size_t *index_buf = NULL;
355
+ volatile VALUE index_holder = Qnil;
356
+
357
+ parent_axis_dims[0] = parent->elements; /* parent flattened */
358
+ sub_axes[0].kind = CA_AXIS_KIND_INDEX;
359
+ sub_axes[0].count = n;
360
+ sub_axes[0].start = 0;
361
+ sub_axes[0].step = 0;
362
+
363
+ if ( step == 1 ) {
364
+ /* zero-copy pointer offset into precomputed indices[] */
365
+ sub_axes[0].indices = ca->indices + start;
366
+ } else {
367
+ /* sub-sampled or reversed: materialise sub-indices */
368
+ ca_size_t i;
369
+ index_buf = ALLOCV_N(ca_size_t, index_holder, n);
370
+ for ( i = 0; i < n; i++ ) {
371
+ index_buf[i] = ca->indices[start + i * step];
274
372
  }
373
+ sub_axes[0].indices = index_buf;
374
+ }
375
+
376
+ if ( dir == CA_XFER_GET ) {
377
+ ca_axis_dispatch_gather(parent, parent_axis_dims, sub_axes, 1,
378
+ ca->bytes, n, NULL, (char *)data);
379
+ } else {
380
+ ca_axis_dispatch_scatter(parent, parent_axis_dims, sub_axes, 1,
381
+ ca->bytes, n, (char *)data);
275
382
  }
383
+
384
+ if ( index_buf != NULL ) ALLOCV_END(index_holder);
385
+ return;
276
386
  }
277
- ca_store_addr(ca->parent, n, ptr);
278
- }
279
387
 
280
- static void
281
- ca_select_func_store_index (void *ap, ca_size_t *idx, void *ptr)
282
- {
283
- ca_select_func_store_addr(ap, idx[0], ptr);
388
+ /* Fallback for unattached parent: per-cell ca_xfer_addrs. */
389
+ {
390
+ ca_size_t *paddrs;
391
+ ca_size_t i;
392
+ volatile VALUE holder;
393
+ paddrs = ALLOCV_N(ca_size_t, holder, n);
394
+ for ( i = 0; i < n; i++ ) {
395
+ paddrs[i] = ca->indices[start + i * step];
396
+ }
397
+ ca_xfer_addrs(parent, n, paddrs, data, dir);
398
+ ALLOCV_END(holder);
399
+ }
284
400
  }
285
401
 
286
402
  static void
@@ -288,25 +404,34 @@ ca_select_func_allocate (void *ap)
288
404
  {
289
405
  CASelect *ca = (CASelect *) ap;
290
406
  ca_attach(ca->parent);
291
- /* ca->ptr = ALLOC_N(char, ca_length(ca)); */
292
- ca->ptr = malloc_with_check(ca_length(ca));
407
+ ca->ptr = xmalloc(ca_length(ca));
293
408
  }
294
409
 
410
+ /* Every attach / sync / xfer_all / xfer_stride / fill_data path
411
+ dispatches through the descriptor engine with the same shape
412
+ CASelectAxis uses: one axis over a flattened parent. */
413
+
295
414
  static void
296
415
  ca_select_func_attach (void *ap)
297
416
  {
298
417
  CASelect *ca = (CASelect *) ap;
418
+ ca_axis_desc_t desc[CA_RANK_MAX];
419
+ ca_size_t pdims[CA_RANK_MAX];
299
420
  ca_attach(ca->parent);
300
- /* ca->ptr = ALLOC_N(char, ca_length(ca)); */
301
- ca->ptr = malloc_with_check(ca_length(ca));
302
- ca_select_to_ptr(ca->parent, ca->select, ca->ptr);
421
+ ca_select_describe_axes(ca, desc, pdims);
422
+ ca->ptr = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim,
423
+ ca->bytes, ca->elements, NULL);
303
424
  }
304
425
 
305
426
  static void
306
427
  ca_select_func_sync (void *ap)
307
428
  {
308
429
  CASelect *ca = (CASelect *) ap;
309
- ca_select_from_ptr(ca->parent, ca->select, ca->ptr);
430
+ ca_axis_desc_t desc[CA_RANK_MAX];
431
+ ca_size_t pdims[CA_RANK_MAX];
432
+ ca_select_describe_axes(ca, desc, pdims);
433
+ ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
434
+ ca->elements, ca->ptr);
310
435
  ca_sync(ca->parent);
311
436
  }
312
437
 
@@ -314,37 +439,83 @@ static void
314
439
  ca_select_func_detach (void *ap)
315
440
  {
316
441
  CASelect *ca = (CASelect *) ap;
317
- free(ca->ptr);
442
+ xfree(ca->ptr);
318
443
  ca->ptr = NULL;
319
444
  ca_detach(ca->parent);
320
445
  }
321
446
 
447
+ /* Fast-path core used by xfer_all's attached-parent branch and the
448
+ cold-parent 2-pass scratch branch below. */
322
449
  static void
323
- ca_select_func_copy_data (void *ap, void *ptr)
450
+ ca_select_func_run_fast_path (CASelect *ca, char *data, int dir)
324
451
  {
325
- CASelect *ca = (CASelect *) ap;
326
- ca_attach(ca->parent);
327
- ca_select_to_ptr(ca->parent, ca->select, ptr);
328
- ca_detach(ca->parent);
452
+ ca_axis_desc_t desc[CA_RANK_MAX];
453
+ ca_size_t pdims[CA_RANK_MAX];
454
+ ca_select_describe_axes(ca, desc, pdims);
455
+ if ( dir == CA_XFER_GET ) {
456
+ ca_axis_dispatch_gather(ca->parent, pdims, desc, ca->ndim, ca->bytes,
457
+ ca->elements, NULL, data);
458
+ } else {
459
+ ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
460
+ ca->elements, data);
461
+ }
329
462
  }
330
463
 
464
+ /* Cold parent is served by a 2-pass scratch (gather parent into a
465
+ local buffer, dispatch through the fast path against the buffer,
466
+ scatter back on PUT). Deliberately avoids ca_attach(parent) so
467
+ that a silent transitive attach cannot re-enter through here. */
331
468
  static void
332
- ca_select_func_sync_data (void *ap, void *ptr)
469
+ ca_select_func_xfer_all (void *ap, void *data, int dir)
333
470
  {
334
471
  CASelect *ca = (CASelect *) ap;
335
- ca_attach(ca->parent);
336
- ca_select_from_ptr(ca->parent, ca->select, ptr);
337
- ca_sync(ca->parent);
338
- ca_detach(ca->parent);
472
+ if ( ca->parent->ptr ) {
473
+ ca_select_func_run_fast_path(ca, (char *) data, dir);
474
+ return;
475
+ }
476
+ {
477
+ volatile VALUE holder;
478
+ CArray *parent = ca->parent;
479
+ ca_size_t plen = parent->elements * parent->bytes;
480
+ char *parent_scratch = ALLOCV_N(char, holder, plen);
481
+ char *parent_ptr_saved = parent->ptr;
482
+ ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
483
+ parent->ptr = parent_scratch;
484
+ ca_select_func_run_fast_path(ca, (char *) data, dir);
485
+ if ( dir == CA_XFER_PUT ) {
486
+ ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
487
+ }
488
+ parent->ptr = parent_ptr_saved;
489
+ ALLOCV_END(holder);
490
+ }
339
491
  }
340
492
 
341
-
342
493
  static void
343
494
  ca_select_func_fill_data (void *ap, void *ptr)
344
495
  {
345
496
  CASelect *ca = (CASelect *) ap;
497
+ ca_axis_desc_t desc[CA_RANK_MAX];
498
+ ca_size_t pdims[CA_RANK_MAX];
499
+
500
+ /* Writing only the selected cells still went through a whole-parent
501
+ attach and sync. Where that attach is a gather rather than an alias,
502
+ the unselected cells make the round trip for nothing -- and through a
503
+ lossy transform layer they do not come back the same. Descend per cell
504
+ instead; the cost then follows the selection. Kept in step with the
505
+ CAStride form, so both spellings of a partial fill behave alike.
506
+ (PROPOSAL_PARTIAL_FILL_WHOLE_ROOT_WRITEBACK.md sections 3.3 / 6.2) */
507
+ if ( !ca_is_attached(ca->parent) && !ca_attach_is_alias(ca->parent) ) {
508
+ /* indices[] are already the selected positions in the parent's flat
509
+ space, so the selection passes down as it stands -- one hop, no
510
+ attach, and the unselected cells are never named. */
511
+ ca_fill_addrs(ca->parent, ca->elements, ca->indices, ptr);
512
+ return;
513
+ }
514
+
346
515
  ca_attach(ca->parent);
347
- ca_select_fill(ca->parent, ca->select, ptr);
516
+ ca_select_describe_axes(ca, desc, pdims);
517
+ ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
518
+ ca->elements, ptr);
348
519
  ca_sync(ca->parent);
349
520
  ca_detach(ca->parent);
350
521
  }
@@ -362,23 +533,20 @@ ca_select_func_create_mask (void *ap)
362
533
 
363
534
  ca_operation_function_t ca_select_func = {
364
535
  CA_OBJ_SELECT,
365
- CA_VIRTUAL_ARRAY,
536
+ CA_VIEW_ARRAY,
366
537
  free_ca_select,
367
538
  ca_select_func_clone,
368
- ca_select_func_ptr_at_addr,
369
- ca_select_func_ptr_at_index,
370
- ca_select_func_fetch_addr,
371
- ca_select_func_fetch_index,
372
- ca_select_func_store_addr,
373
- ca_select_func_store_index,
374
539
  ca_select_func_allocate,
375
540
  ca_select_func_attach,
376
541
  ca_select_func_sync,
377
542
  ca_select_func_detach,
378
- ca_select_func_copy_data,
379
- ca_select_func_sync_data,
380
543
  ca_select_func_fill_data,
381
544
  ca_select_func_create_mask,
545
+ ca_select_func_xfer_index,
546
+ ca_select_func_xfer_addrs,
547
+ NULL, /* fold_stride: never fold — gather boundary */
548
+ ca_select_func_xfer_stride,
549
+ ca_select_func_xfer_all,
382
550
  };
383
551
 
384
552
  /* ------------------------------------------------------------------- */
@@ -399,13 +567,16 @@ rb_ca_select_new (VALUE cary, VALUE select)
399
567
  }
400
568
  obj = ca_wrap_struct(ca);
401
569
  rb_ca_set_parent(obj, cary);
402
- rb_ca_data_type_inherit(obj, cary);
570
+ CA_FACE_LIFT_IF_FACE(obj, cary, parent);
403
571
  return obj;
404
572
  }
405
573
 
406
574
  VALUE
407
575
  rb_ca_select_new_share (VALUE cary, VALUE select)
408
576
  {
577
+ /* Alias of the snapshot constructor. The `referred_index` ivar is
578
+ set so consumers that expect the original selector to be
579
+ reachable from the view object continue to find it. */
409
580
  volatile VALUE obj;
410
581
  CArray *parent, *cselect;
411
582
  CASelect *ca;
@@ -419,136 +590,12 @@ rb_ca_select_new_share (VALUE cary, VALUE select)
419
590
  }
420
591
  obj = ca_wrap_struct(ca);
421
592
  rb_ca_set_parent(obj, cary);
422
- rb_ca_data_type_inherit(obj, cary);
423
593
  rb_ivar_set(obj, rb_intern("referred_index"), select);
424
594
  return obj;
425
595
  }
426
596
 
427
597
  /* -------------------------------------------------------------------- */
428
598
 
429
- #define proc_select_to_ptr(type) \
430
- { \
431
- type *p = (type *) ptr; \
432
- type *q = (type *) ca->ptr; \
433
- for (i=ca->elements; i; i--) { \
434
- if ( *s ) { \
435
- *p++ = *q; \
436
- } \
437
- q++; s++; \
438
- } \
439
- }
440
-
441
- void
442
- ca_select_to_ptr (CArray *ca, CArray *select, char *ptr)
443
- {
444
- boolean8_t *s = (boolean8_t*) select->ptr;
445
- ca_size_t i;
446
-
447
- switch ( ca->bytes ) {
448
- case 1: proc_select_to_ptr(int8_t); break;
449
- case 2: proc_select_to_ptr(int16_t); break;
450
- case 4: proc_select_to_ptr(int32_t); break;
451
- case 8: proc_select_to_ptr(float64_t); break;
452
- default: {
453
- char *p = ptr, *q = ca->ptr;
454
- ca_size_t bytes = ca->bytes;
455
- for (i=ca->elements; i; i--) {
456
- if ( *s ) {
457
- memcpy(q, p, bytes);
458
- p+=bytes;
459
- }
460
- q+=bytes; s++;
461
- }
462
- break;
463
- }
464
- }
465
-
466
- }
467
-
468
- /* ------------------------------------------------------------------- */
469
-
470
- #define proc_select_from_ptr(type) \
471
- { \
472
- type *p = (type *) ptr; \
473
- type *q = (type *) ca->ptr; \
474
- for (i=ca->elements; i; i--) { \
475
- if ( *s ) { \
476
- *q = *p++; \
477
- } \
478
- q++; s++; \
479
- } \
480
- }
481
-
482
- void
483
- ca_select_from_ptr (CArray *ca, CArray *select, char *ptr)
484
- {
485
- boolean8_t *s = (boolean8_t *) select->ptr;
486
- ca_size_t i;
487
-
488
- switch ( ca->bytes ) {
489
- case 1: proc_select_from_ptr(int8_t); break;
490
- case 2: proc_select_from_ptr(int16_t); break;
491
- case 4: proc_select_from_ptr(int32_t); break;
492
- case 8: proc_select_from_ptr(float64_t); break;
493
- default: {
494
- char *p = ptr;
495
- char *q = ca->ptr;
496
- ca_size_t bytes = ca->bytes;
497
- for (i=ca->elements; i; i--) {
498
- if ( *s ) {
499
- memcpy(q, p, bytes);
500
- p+=bytes;
501
- }
502
- q+=bytes; s++;
503
- }
504
- break;
505
- }
506
- }
507
-
508
- }
509
-
510
- /* ------------------------------------------------------------------- */
511
-
512
- #define proc_select_fill(type) \
513
- { \
514
- type *q = (type *) ca->ptr; \
515
- type v = *(type *) valp; \
516
- for (i=ca->elements; i; i--) { \
517
- if ( *s ) { \
518
- *q = v; \
519
- } \
520
- q++; s++; \
521
- } \
522
- }
523
-
524
- void
525
- ca_select_fill (CArray *ca, CArray *select, char *valp)
526
- {
527
- boolean8_t *s = (boolean8_t *) select->ptr;
528
- ca_size_t i;
529
-
530
- switch ( ca->bytes ) {
531
- case 1: proc_select_fill(int8_t); break;
532
- case 2: proc_select_fill(int16_t); break;
533
- case 4: proc_select_fill(int32_t); break;
534
- case 8: proc_select_fill(float64_t); break;
535
- default: {
536
- char *q = ca->ptr;
537
- ca_size_t bytes = ca->bytes;
538
- for (i=ca->elements; i; i--) {
539
- if ( *s ) {
540
- memcpy(q, valp, bytes);
541
- }
542
- q+=bytes; s++;
543
- }
544
- break;
545
- }
546
- }
547
-
548
- }
549
-
550
- /* ------------------------------------------------------------------- */
551
-
552
599
  static VALUE
553
600
  rb_cm_s_allocate (VALUE klass)
554
601
  {
@@ -564,19 +611,20 @@ rb_cm_initialize_copy (VALUE self, VALUE other)
564
611
  TypedData_Get_Struct(self, CASelect, &caselect_data_type, ca);
565
612
  TypedData_Get_Struct(other, CASelect, &caselect_data_type, cs);
566
613
 
567
- /* share select info */
614
+ /* Re-snapshot from the source's selector copy so the two views
615
+ end up with independent indices buffers. */
568
616
  ca_select_setup(ca, cs->parent, cs->select, 1);
569
617
 
570
618
  return self;
571
619
  }
572
620
 
573
621
  void
574
- Init_ca_obj_select ()
622
+ Init_ca_obj_select (void)
575
623
  {
576
- /* rb_cCASelect, CA_OBJ_SELECT are defined in rb_carray.c */
624
+ /* rb_cCASelect and CA_OBJ_SELECT are defined in ruby_carray.c;
625
+ this file only registers the constant + allocator. */
577
626
  rb_define_const(rb_cObject, "CA_OBJ_SELECT", INT2NUM(CA_OBJ_SELECT));
578
627
 
579
628
  rb_define_alloc_func(rb_cCASelect, rb_cm_s_allocate);
580
629
  rb_define_method(rb_cCASelect, "initialize_copy", rb_cm_initialize_copy, 1);
581
630
  }
582
-