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
@@ -1,10 +1,13 @@
1
1
  /* ---------------------------------------------------------------------------
2
2
 
3
- ca_obj_bitfield.c
3
+ CABitfield view: extract a contiguous bit field from each parent
4
+ cell, exposing it as an unsigned-integer (or boolean, when
5
+ bitlen == 1) CArray of the same shape as the parent.
4
6
 
5
- This file is part of Ruby/CArray extension library.
6
-
7
- Copyright (C) 2005-2020 Hiroki Motoyoshi
7
+ Byte-straddling fields are handled by loading up to 8 bytes from
8
+ the parent starting at `byte_offset`, masking with `bit_mask`, and
9
+ shifting by `bit_offset`. Big-endian hosts adjust byte_offset /
10
+ bit_offset so the field selection is invariant to host byte order.
8
11
 
9
12
  ---------------------------------------------------------------------------- */
10
13
 
@@ -20,6 +23,7 @@ typedef struct {
20
23
  ca_size_t *dim;
21
24
  char *ptr;
22
25
  CArray *mask;
26
+ char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path). */
23
27
  CArray *parent;
24
28
  uint32_t attach;
25
29
  uint8_t nosync;
@@ -27,15 +31,39 @@ typedef struct {
27
31
  ca_size_t byte_offset;
28
32
  ca_size_t bit_offset;
29
33
  uint64_t bit_mask;
34
+ ca_size_t bit_start; /* original offset before endian adjustment */
30
35
  } CABitfield;
31
36
 
37
+ static size_t
38
+ ca_bitfield_dsize (const void *ap)
39
+ {
40
+ const CABitfield *ca = (const CABitfield *) ap;
41
+ return sizeof(CABitfield) + ca->ndim * sizeof(ca_size_t);
42
+ }
43
+
44
+ /* Pool framework hooks: single ndim-sized tail (dim) in the _pool
45
+ buffer. See ca_array_pool.c for the shared alloc/free discipline. */
46
+ static size_t
47
+ ca_bitfield_pool_bytes (int8_t ndim)
48
+ {
49
+ ca_size_t n = (ndim > 0) ? ndim : 1;
50
+ return (size_t) n * sizeof(ca_size_t);
51
+ }
52
+
53
+ static void
54
+ ca_bitfield_pool_init (void *ap, int8_t ndim)
55
+ {
56
+ CABitfield *ca = (CABitfield *) ap;
57
+ ca->dim = (ca_size_t *) ca->_pool;
58
+ }
59
+
32
60
  const rb_data_type_t cabitfield_data_type = {
33
- .parent = &cavirtual_data_type,
61
+ .parent = &caview_data_type,
34
62
  .wrap_struct_name = "CABitfield",
35
63
  .function = {
36
64
  .dmark = ca_mark,
37
65
  .dfree = ca_free,
38
- .dsize = NULL,
66
+ .dsize = ca_bitfield_dsize,
39
67
  .dcompact = NULL
40
68
  },
41
69
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
@@ -45,11 +73,6 @@ static int8_t CA_OBJ_BITFIELD;
45
73
 
46
74
  static VALUE rb_cCABitfield;
47
75
 
48
- /* yard:
49
- class CABitField < CAVirtual # :nodoc:
50
- end
51
- */
52
-
53
76
  static ca_size_t
54
77
  bitfield_bitlen (uint64_t bit_mask, ca_size_t bytes)
55
78
  {
@@ -64,153 +87,55 @@ bitfield_bitlen (uint64_t bit_mask, ca_size_t bytes)
64
87
  return count;
65
88
  }
66
89
 
90
+ /* Generic per-cell fetch: load up to 8 bytes from src starting at
91
+ byte_offset, mask with bit_mask, shift down by bit_offset, and
92
+ write the low `dwrite` bytes of the result to dst.
93
+ *
94
+ * CAREFUL: the read goes through a uint64 with dynamic `span` /
95
+ * `dwrite` deliberately, so that a byte-straddling field (e.g. an
96
+ * 8-bit field starting at bit 4 of a 2-byte parent) sees the full
97
+ * bit_mask. A dbytes-typed cast would silently truncate bit_mask
98
+ * to `1 << (dbytes * 8)`, dropping the upper bits of the field. */
67
99
  static void
68
- bitfield_fetch(char *dst, ca_size_t dbytes,
100
+ bitfield_fetch(char *dst, ca_size_t dbytes,
69
101
  char *src, ca_size_t sbytes,
70
102
  ca_size_t byte_offset, ca_size_t bit_offset, uint64_t bit_mask,
71
103
  ca_size_t elements)
72
104
  {
73
105
  ca_size_t k;
74
- switch ( dbytes ) {
75
- case 1: {
76
- char *p;
77
- uint8_t *q, *r;
78
- uint8_t mask = (uint8_t) bit_mask;
79
- p = src + byte_offset;
80
- q = (uint8_t *) dst;
81
- #ifdef _OPENMP
82
- #pragma omp parallel for private(r)
83
- #endif
84
- for (k=0; k<elements; k++) {
85
- r = (uint8_t *) (p+k*sbytes);
86
- *(q+k) = (( *r & mask ) >> bit_offset);
87
- }
88
- break;
89
- }
90
- case 2: {
91
- char *p;
92
- uint16_t *q, *r;
93
- uint16_t mask = (uint16_t) bit_mask;
94
- p = src + byte_offset;
95
- q = (uint16_t *) dst;
96
- #ifdef _OPENMP
97
- #pragma omp parallel for private(r)
98
- #endif
99
- for (k=0; k<elements; k++) {
100
- r = (uint16_t *) (p+k*sbytes);
101
- *(q+k) = (( *r & mask ) >> bit_offset);
102
- }
103
- break;
104
- }
105
- case 4: {
106
- char *p;
107
- uint32_t *q, *r;
108
- uint32_t mask = (uint32_t) bit_mask;
109
- p = src + byte_offset;
110
- q = (uint32_t *) dst;
111
- #ifdef _OPENMP
112
- #pragma omp parallel for private(r)
113
- #endif
114
- for (k=0; k<elements; k++) {
115
- r = (uint32_t *) (p+k*sbytes);
116
- *(q+k) = (( *r & mask ) >> bit_offset);
117
- }
118
- break;
119
- }
120
- case 8: {
121
- char *p;
122
- uint64_t *q, *r;
123
- uint64_t mask = (uint64_t) bit_mask;
124
- p = src + byte_offset;
125
- q = (uint64_t *) dst;
126
- #ifdef _OPENMP
127
- #pragma omp parallel for private(r)
128
- #endif
129
- for (k=0; k<elements; k++) {
130
- r = (uint64_t *) (p+k*sbytes);
131
- *(q+k) = (( *r & mask ) >> bit_offset);
132
- }
133
- break;
134
- }
135
- default:
136
- rb_raise(rb_eRuntimeError, "[BUG]");
106
+ ca_size_t span = sbytes - byte_offset;
107
+ if (span > 8) span = 8;
108
+ ca_size_t dwrite = (dbytes > 8) ? 8 : dbytes;
109
+ for (k = 0; k < elements; k++) {
110
+ uint64_t tmp = 0;
111
+ memcpy(&tmp, src + k * sbytes + byte_offset, (size_t) span);
112
+ uint64_t result = (tmp & bit_mask) >> bit_offset;
113
+ memcpy(dst + k * dbytes, &result, (size_t) dwrite);
137
114
  }
138
115
  }
139
116
 
140
117
  static void
141
118
  bitfield_store(char *src, ca_size_t sbytes,
142
- char *dst, ca_size_t dbytes,
119
+ char *dst, ca_size_t dbytes,
143
120
  ca_size_t byte_offset, ca_size_t bit_offset, uint64_t bit_mask,
144
121
  ca_size_t elements)
145
122
  {
123
+ /* Mirror of bitfield_fetch with scatter direction: reads sbytes
124
+ from src, reads dbytes of dst starting at byte_offset, masks
125
+ the field bits in, writes back. The uint64 read/write span
126
+ preserves bit_mask for byte-straddling fields (see
127
+ bitfield_fetch CAREFUL). */
146
128
  ca_size_t k;
147
- switch ( dbytes ) {
148
- case 1: {
149
- char *q;
150
- uint8_t *p, *r;
151
- uint8_t mask = (uint8_t) bit_mask;
152
- p = (uint8_t *) src;
153
- q = dst + byte_offset;
154
- #ifdef _OPENMP
155
- #pragma omp parallel for private(r)
156
- #endif
157
- for (k=0; k<elements; k++) {
158
- r = p + k;
159
- *(uint8_t*)(q+k*dbytes) =
160
- ( ((*(uint8_t*)(q+k*dbytes)) & ~mask) | ((*r << bit_offset) & mask) );
161
- }
162
- break;
163
- }
164
- case 2: {
165
- char *q;
166
- uint16_t *p, *r;
167
- uint16_t mask = (uint16_t) bit_mask;
168
- p = (uint16_t *) src;
169
- q = dst + byte_offset;
170
- #ifdef _OPENMP
171
- #pragma omp parallel for private(r)
172
- #endif
173
- for (k=0; k<elements; k++) {
174
- r = p + k;
175
- *(uint16_t*)(q+k*dbytes) =
176
- ( ((*(uint16_t*)(q+k*dbytes)) & ~mask) | ((*r << bit_offset) & mask) );
177
- }
178
- break;
179
- }
180
- case 4: {
181
- char *q;
182
- uint32_t *p, *r;
183
- uint32_t mask = (uint32_t) bit_mask;
184
- p = (uint32_t *) src;
185
- q = dst + byte_offset;
186
- #ifdef _OPENMP
187
- #pragma omp parallel for private(r)
188
- #endif
189
- for (k=0; k<elements; k++) {
190
- r = p + k;
191
- *(uint32_t*)(q+k*dbytes) =
192
- ( ((*(uint32_t*)(q+k*dbytes)) & ~mask) | ((*r << bit_offset) & mask) );
193
- }
194
- break;
195
- }
196
- case 8: {
197
- char *q;
198
- uint64_t *p, *r;
199
- uint64_t mask = (uint64_t) bit_mask;
200
- p = (uint64_t *) src;
201
- q = dst + byte_offset;
202
- #ifdef _OPENMP
203
- #pragma omp parallel for private(r)
204
- #endif
205
- for (k=0; k<elements; k++) {
206
- r = p + k;
207
- *(uint64_t*)(q+k*dbytes) =
208
- ( ((*(uint64_t*)(q+k*dbytes)) & ~mask) | ((*r << bit_offset) & mask) );
209
- }
210
- break;
211
- }
212
- default:
213
- rb_raise(rb_eRuntimeError, "[BUG]");
129
+ ca_size_t span = dbytes - byte_offset;
130
+ if (span > 8) span = 8;
131
+ ca_size_t sread = (sbytes > 8) ? 8 : sbytes;
132
+ for (k = 0; k < elements; k++) {
133
+ uint64_t srcv = 0;
134
+ memcpy(&srcv, src + k * sbytes, (size_t) sread);
135
+ uint64_t tmp = 0;
136
+ memcpy(&tmp, dst + k * dbytes + byte_offset, (size_t) span);
137
+ tmp = (tmp & ~bit_mask) | ((srcv << bit_offset) & bit_mask);
138
+ memcpy(dst + k * dbytes + byte_offset, &tmp, (size_t) span);
214
139
  }
215
140
  }
216
141
 
@@ -230,14 +155,6 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
230
155
  uint64_t bit_mask;
231
156
  ca_size_t i;
232
157
 
233
- /* check arguments */
234
-
235
- /*
236
- if ( ! ca_is_integer_type(parent) && ! ca_is_float_type(ca) ) {
237
- rb_raise(rb_eCADataTypeError, "invalid data_type for bitfield");
238
- }
239
- */
240
-
241
158
  ndim = parent->ndim;
242
159
  bitsize = parent->bytes * 8;
243
160
  elements = parent->elements;
@@ -281,7 +198,7 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
281
198
  bit_offset = offset % 8;
282
199
  bit_mask = 0;
283
200
  for (i=0; i<bitlen; i++) {
284
- bit_mask += 1 << ( bit_offset + i );
201
+ bit_mask += 1ULL << ( bit_offset + i );
285
202
  }
286
203
  if ( byte_offset < 0 ) {
287
204
  for (i=0; i<-byte_offset; i++) {
@@ -296,7 +213,7 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
296
213
  bit_offset = offset % 8;
297
214
  bit_mask = 0;
298
215
  for (i=0; i<bitlen; i++) {
299
- bit_mask += 1 << ( bit_offset + i );
216
+ bit_mask += 1ULL << ( bit_offset + i );
300
217
  }
301
218
  }
302
219
 
@@ -308,7 +225,9 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
308
225
  ca->elements = elements;
309
226
  ca->ptr = NULL;
310
227
  ca->mask = NULL;
311
- ca->dim = ALLOC_N(ca_size_t, ndim);
228
+ if ( ! ca->_pool ) {
229
+ ca->dim = ALLOC_N(ca_size_t, ndim);
230
+ }
312
231
 
313
232
  ca->parent = parent;
314
233
  ca->attach = 0;
@@ -317,6 +236,7 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
317
236
  ca->byte_offset = byte_offset;
318
237
  ca->bit_offset = bit_offset;
319
238
  ca->bit_mask = bit_mask;
239
+ ca->bit_start = offset; /* preserve original offset for clone/copy */
320
240
 
321
241
  memcpy(ca->dim, parent->dim, ndim * sizeof(ca_size_t));
322
242
 
@@ -330,7 +250,7 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
330
250
  CABitfield *
331
251
  ca_bitfield_new (CArray *parent, ca_size_t offset, ca_size_t bitlen)
332
252
  {
333
- CABitfield *ca = ALLOC(CABitfield);
253
+ CABitfield *ca = (CABitfield *) ca_array_alloc(CA_OBJ_BITFIELD, parent->ndim);
334
254
  ca_bitfield_setup(ca, parent, offset, bitlen);
335
255
  return ca;
336
256
  }
@@ -341,8 +261,13 @@ free_ca_bitfield (void *ap)
341
261
  CABitfield *ca = (CABitfield *) ap;
342
262
  if ( ca != NULL ) {
343
263
  ca_free(ca->mask);
344
- xfree(ca->dim);
345
- xfree(ca);
264
+ if ( ca->_pool ) {
265
+ ca_array_free(ca); /* dim lives in _pool */
266
+ }
267
+ else {
268
+ xfree(ca->dim);
269
+ xfree(ca);
270
+ }
346
271
  }
347
272
  }
348
273
 
@@ -356,59 +281,130 @@ static void *
356
281
  ca_bitfield_func_clone (void *ap)
357
282
  {
358
283
  CABitfield *ca = (CABitfield *) ap;
359
- return ca_bitfield_new(ca->parent,
360
- 8 * ca->byte_offset + ca->bit_offset,
284
+ return ca_bitfield_new(ca->parent,
285
+ ca->bit_start,
361
286
  bitfield_bitlen(ca->bit_mask, ca->bytes));
362
287
  }
363
288
 
364
- static char *
365
- ca_bitfield_func_ptr_at_addr (void *ap, ca_size_t addr)
289
+ /* Per-cell get/put: fetch the parent cell into a scratch buffer,
290
+ then extract or splice the bit field with bitfield_fetch /
291
+ bitfield_store on a single element. */
292
+ static void
293
+ ca_bitfield_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
366
294
  {
367
295
  CABitfield *ca = (CABitfield *) ap;
368
- if ( ! ca->ptr ) {
369
- rb_raise(rb_eRuntimeError, "[BUG]");
370
- return NULL;
296
+ char *v = xmalloc(ca->parent->bytes);
297
+ ca_fetch_index(ca->parent, idx, v);
298
+ if ( dir == CA_XFER_GET ) {
299
+ memset(data, 0, ca->bytes);
300
+ bitfield_fetch(data, ca->bytes, v, ca->parent->bytes,
301
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
371
302
  }
372
303
  else {
373
- return ca->ptr + ca->bytes * addr;
304
+ bitfield_store(data, ca->bytes, v, ca->parent->bytes,
305
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
306
+ ca_store_index(ca->parent, idx, v);
374
307
  }
308
+ xfree(v);
375
309
  }
376
310
 
377
- static char *
378
- ca_bitfield_func_ptr_at_index (void *ap, ca_size_t *idx)
311
+ /* Batched gather / scatter. CABitfield is a 1:1 view (each parent
312
+ cell carries exactly one field position) so the incoming view
313
+ addresses are also parent addresses. GET gathers parent cells in
314
+ one call then extracts bits; PUT reads, splices field bits, then
315
+ writes back. Each cell touches its own bits, so there is no
316
+ shared-cell hazard between concurrent scatters.
317
+
318
+ Fast path: when `addrs` covers the whole view sequentially and
319
+ the effective attached parent (via identity compose-fold) is
320
+ live, drive bitfield_fetch / bitfield_store directly against
321
+ parent->ptr — no scratch, no double xfer_addrs round-trip. */
322
+ static void
323
+ ca_bitfield_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
324
+ void *data, int dir)
379
325
  {
380
326
  CABitfield *ca = (CABitfield *) ap;
381
- if ( ! ca->ptr ) {
382
- rb_raise(rb_eRuntimeError, "[BUG]");
383
- return NULL;
327
+ CArray *parent = ca->parent;
328
+ char *d = (char *) data;
329
+ ca_size_t pbytes = parent->bytes;
330
+ ca_size_t i, base;
331
+ char *v;
332
+ volatile VALUE holder;
333
+
334
+ if ( n == ca->elements
335
+ && ca_xfer_addrs_is_sequential_run(n, addrs, &base) && base == 0 ) {
336
+ CArray *eff_parent = ca_resolve_attached_root_via_identity(parent);
337
+ if ( eff_parent->ptr
338
+ && eff_parent->elements == parent->elements
339
+ && eff_parent->bytes == parent->bytes ) {
340
+ if ( dir == CA_XFER_GET ) {
341
+ /* Zero the output buffer, then bulk-extract n field values
342
+ directly from the attached parent. */
343
+ memset(d, 0, n * ca->bytes);
344
+ bitfield_fetch(d, ca->bytes, eff_parent->ptr, pbytes,
345
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
346
+ } else {
347
+ /* Bulk RMW directly against parent memory (bitfield_store
348
+ preserves non-field bits). */
349
+ bitfield_store(d, ca->bytes, eff_parent->ptr, pbytes,
350
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
351
+ }
352
+ return;
353
+ }
354
+ }
355
+
356
+ v = ALLOCV_N(char, holder, n * pbytes);
357
+ if ( dir == CA_XFER_GET ) {
358
+ ca_xfer_addrs(parent, n, addrs, v, CA_XFER_GET);
359
+ for (i = 0; i < n; i++) {
360
+ memset(d + i * ca->bytes, 0, ca->bytes);
361
+ bitfield_fetch(d + i * ca->bytes, ca->bytes, v + i * pbytes, pbytes,
362
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
363
+ }
384
364
  }
385
365
  else {
386
- return ca_func[CA_OBJ_ARRAY].ptr_at_index(ca, idx);
366
+ ca_xfer_addrs(parent, n, addrs, v, CA_XFER_GET); /* RMW: read first */
367
+ for (i = 0; i < n; i++) {
368
+ bitfield_store(d + i * ca->bytes, ca->bytes, v + i * pbytes, pbytes,
369
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
370
+ }
371
+ ca_xfer_addrs(parent, n, addrs, v, CA_XFER_PUT);
387
372
  }
373
+ ALLOCV_END(holder);
388
374
  }
389
375
 
376
+ /* CABitfield is a per-cell bit transform with no axis structure to
377
+ preserve, so the incoming region reduces to a flat address list
378
+ over the view. We materialise that list from starts / counts /
379
+ strides and delegate to the view's own xfer_addrs, which handles
380
+ the gather + bit RMW + batched parent delivery. */
390
381
  static void
391
- ca_bitfield_func_fetch_index (void *ap, ca_size_t *idx, void *ptr)
382
+ ca_bitfield_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
383
+ ca_size_t *strides, void *data, int dir)
392
384
  {
393
385
  CABitfield *ca = (CABitfield *) ap;
394
- char *v = xmalloc(ca->parent->bytes);
395
- ca_fetch_index(ca->parent, idx, v);
396
- memset(ptr, 0, ca->bytes);
397
- bitfield_fetch(ptr, ca->bytes, v, ca->parent->bytes,
398
- ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
399
- xfree(v);
400
- }
401
-
402
- static void
403
- ca_bitfield_func_store_index (void *ap, ca_size_t *idx, void *ptr)
404
- {
405
- CABitfield *ca = (CABitfield *) ap;
406
- char *v = xmalloc(ca->parent->bytes);
407
- ca_fetch_index(ca->parent, idx, v);
408
- bitfield_store(ptr, ca->bytes, v, ca->parent->bytes,
409
- ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
410
- ca_store_index(ca->parent, idx, v);
411
- xfree(v);
386
+ int8_t ndim = ca->ndim;
387
+ ca_size_t native[CA_RANK_MAX], idx[CA_RANK_MAX];
388
+ ca_size_t *vaddrs;
389
+ ca_size_t base = 0, n = 1, i, s;
390
+ int8_t k;
391
+ volatile VALUE holder;
392
+
393
+ s = ca->bytes;
394
+ for (k = ndim - 1; k >= 0; k--) { native[k] = s; s *= ca->dim[k]; }
395
+ for (k = 0; k < ndim; k++) { base += starts[k] * native[k]; n *= counts[k]; }
396
+
397
+ vaddrs = ALLOCV_N(ca_size_t, holder, n);
398
+ for (k = 0; k < ndim; k++) idx[k] = 0;
399
+ for (i = 0; i < n; i++) {
400
+ ca_size_t off = base;
401
+ for (k = 0; k < ndim; k++) off += idx[k] * strides[k];
402
+ vaddrs[i] = off / ca->bytes;
403
+ k = ndim - 1;
404
+ while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
405
+ }
406
+ ca_xfer_addrs(ca, n, vaddrs, data, dir);
407
+ ALLOCV_END(holder);
412
408
  }
413
409
 
414
410
  static void
@@ -416,18 +412,15 @@ ca_bitfield_func_allocate (void *ap)
416
412
  {
417
413
  CABitfield *ca = (CABitfield *) ap;
418
414
  ca_attach(ca->parent);
419
- /* ca->ptr = ALLOC_N(char, ca_length(ca)); */
420
- ca->ptr = malloc_with_check(ca_length(ca));
415
+ ca->ptr = xmalloc(ca_length(ca));
421
416
  }
422
417
 
423
418
  static void
424
419
  ca_bitfield_func_attach (void *ap)
425
420
  {
426
- void ca_bitfield_attach (CABitfield *cb);
427
421
  CABitfield *ca = (CABitfield *) ap;
428
422
  ca_attach(ca->parent);
429
- /* ca->ptr = ALLOC_N(char, ca_length(ca)); */
430
- ca->ptr = malloc_with_check(ca_length(ca));
423
+ ca->ptr = xmalloc(ca_length(ca));
431
424
  ca_bitfield_attach(ca);
432
425
  }
433
426
 
@@ -443,44 +436,110 @@ static void
443
436
  ca_bitfield_func_detach (void *ap)
444
437
  {
445
438
  CABitfield *ca = (CABitfield *) ap;
446
- free(ca->ptr);
439
+ xfree(ca->ptr);
447
440
  ca->ptr = NULL;
448
441
  ca_detach(ca->parent);
449
442
  }
450
443
 
444
+ /* Whole-view transfer. Fast path: drive bitfield_fetch /
445
+ bitfield_store directly against the effective attached parent
446
+ (via identity compose-fold), bypassing the addrs[] allocation
447
+ and sequential-run scan that xfer_addrs would perform.
448
+
449
+ Cold parent falls back to a scratch 2-pass (gather parent into a
450
+ local buffer via xfer_stride, apply the bitfield primitive, and
451
+ for PUT scatter the buffer back). Deliberately does not call
452
+ ca_attach(parent) — that would re-introduce the silent transitive
453
+ attach the fast path exists to avoid. */
451
454
  static void
452
- ca_bitfield_func_copy_data (void *ap, void *ptr)
455
+ ca_bitfield_func_xfer_all (void *ap, void *data, int dir)
453
456
  {
454
457
  CABitfield *ca = (CABitfield *) ap;
455
- char *ptr0 = ca->ptr;
456
- ca_attach(ca->parent);
457
- ca->ptr = ptr;
458
- ca_bitfield_attach(ca);
459
- ca->ptr = ptr0;
460
- ca_detach(ca->parent);
458
+ CArray *parent = ca->parent;
459
+ ca_size_t pbytes = parent->bytes;
460
+ ca_size_t n = ca->elements;
461
+ char *d = (char *) data;
462
+ CArray *eff_parent = ca_resolve_attached_root_via_identity(parent);
463
+
464
+ if ( eff_parent->ptr
465
+ && eff_parent->elements == parent->elements
466
+ && eff_parent->bytes == parent->bytes ) {
467
+ if ( dir == CA_XFER_GET ) {
468
+ memset(d, 0, n * ca->bytes);
469
+ bitfield_fetch(d, ca->bytes, eff_parent->ptr, pbytes,
470
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
471
+ } else {
472
+ bitfield_store(d, ca->bytes, eff_parent->ptr, pbytes,
473
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
474
+ }
475
+ return;
476
+ }
477
+
478
+ /* Cold-parent fallback: materialise into scratch via xfer_stride
479
+ (no ca_attach(parent)), apply the bitfield primitive, and for
480
+ PUT scatter back. */
481
+ {
482
+ volatile VALUE holder;
483
+ char *scratch = ALLOCV_N(char, holder, parent->elements * pbytes);
484
+ ca_size_t pstarts[CA_RANK_MAX];
485
+ ca_size_t pnative[CA_RANK_MAX];
486
+ ca_size_t s = pbytes;
487
+ int8_t k;
488
+ for ( k = parent->ndim - 1; k >= 0; k-- ) { pnative[k] = s; s *= parent->dim[k]; }
489
+ for ( k = 0; k < parent->ndim; k++ ) pstarts[k] = 0;
490
+ if ( dir == CA_XFER_GET ) {
491
+ ca_xfer_stride(parent, pstarts, parent->dim, pnative, scratch, CA_XFER_GET);
492
+ memset(d, 0, n * ca->bytes);
493
+ bitfield_fetch(d, ca->bytes, scratch, pbytes,
494
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
495
+ } else {
496
+ /* CAREFUL: gather parent into scratch before splicing so the
497
+ non-field bits are preserved across the RMW. */
498
+ ca_xfer_stride(parent, pstarts, parent->dim, pnative, scratch, CA_XFER_GET);
499
+ bitfield_store(d, ca->bytes, scratch, pbytes,
500
+ ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
501
+ ca_xfer_stride(parent, pstarts, parent->dim, pnative, scratch, CA_XFER_PUT);
502
+ }
503
+ ALLOCV_END(holder);
504
+ }
461
505
  }
462
506
 
463
507
  static void
464
- ca_bitfield_func_sync_data (void *ap, void *ptr)
508
+ ca_bitfield_func_fill_data (void *ap, void *ptr)
465
509
  {
466
510
  CABitfield *ca = (CABitfield *) ap;
467
- char *ptr0 = ca->ptr;
468
511
  ca_attach(ca->parent);
469
- ca->ptr = ptr;
470
- ca_bitfield_sync(ca);
471
- ca->ptr = ptr0;
512
+ ca_bitfield_fill(ca, ptr);
472
513
  ca_sync(ca->parent);
473
514
  ca_detach(ca->parent);
474
515
  }
475
516
 
517
+
518
+ /* A fill here is a read-modify-write: the cell also carries bits this view
519
+ does not own, so there is nothing to hand down as a region. The batched
520
+ address slot already reads and writes a run in one call each; broadcasting
521
+ the value into it is all that is left, and it saves the descent that a
522
+ per-cell walk would pay for every cell. */
476
523
  static void
477
- ca_bitfield_func_fill_data (void *ap, void *ptr)
524
+ ca_bitfield_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
478
525
  {
479
526
  CABitfield *ca = (CABitfield *) ap;
480
- ca_attach(ca->parent);
481
- ca_bitfield_fill(ca, ptr);
482
- ca_sync(ca->parent);
483
- ca_detach(ca->parent);
527
+ volatile VALUE holder;
528
+ char *buf = ALLOCV_N(char, holder, (size_t) n * ca->bytes);
529
+ ca_size_t i;
530
+
531
+ for ( i = 0; i < n; i++ ) {
532
+ memcpy(buf + i * ca->bytes, ptr, ca->bytes);
533
+ }
534
+ ca_bitfield_func_xfer_addrs(ca, n, addrs, buf, CA_XFER_PUT);
535
+ ALLOCV_END(holder);
536
+ }
537
+
538
+ static void
539
+ ca_bitfield_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
540
+ ca_size_t *counts, ca_size_t *steps, void *ptr)
541
+ {
542
+ ca_fill_stride_via_addrs(ap, base, ndim, counts, steps, ptr);
484
543
  }
485
544
 
486
545
  static void
@@ -499,23 +558,22 @@ ca_bitfield_func_create_mask (void *ap)
499
558
 
500
559
  ca_operation_function_t ca_bitfield_func = {
501
560
  -1, /* CA_OBJ_BITFIELD */
502
- CA_VIRTUAL_ARRAY,
561
+ CA_VIEW_ARRAY,
503
562
  free_ca_bitfield,
504
563
  ca_bitfield_func_clone,
505
- ca_bitfield_func_ptr_at_addr,
506
- ca_bitfield_func_ptr_at_index,
507
- NULL,
508
- ca_bitfield_func_fetch_index,
509
- NULL,
510
- ca_bitfield_func_store_index,
511
564
  ca_bitfield_func_allocate,
512
565
  ca_bitfield_func_attach,
513
566
  ca_bitfield_func_sync,
514
567
  ca_bitfield_func_detach,
515
- ca_bitfield_func_copy_data,
516
- ca_bitfield_func_sync_data,
517
568
  ca_bitfield_func_fill_data,
518
569
  ca_bitfield_func_create_mask,
570
+ ca_bitfield_func_xfer_index,
571
+ ca_bitfield_func_xfer_addrs,
572
+ NULL, /* fold_stride: never fold — per-cell bit transform */
573
+ ca_bitfield_func_xfer_stride,
574
+ ca_bitfield_func_xfer_all,
575
+ .fill_addrs = ca_bitfield_func_fill_addrs,
576
+ .fill_stride = ca_bitfield_func_fill_stride,
519
577
  };
520
578
 
521
579
  /* ------------------------------------------------------------------- */
@@ -569,11 +627,6 @@ rb_ca_bitfield_new (VALUE cary, ca_size_t offset, ca_size_t bitlen)
569
627
  return obj;
570
628
  }
571
629
 
572
- /* @overload bitfield (range, type)
573
-
574
- [TBD]
575
- */
576
-
577
630
  VALUE
578
631
  rb_ca_bitfield (int argc, VALUE *argv, VALUE self)
579
632
  {
@@ -616,22 +669,29 @@ rb_ca_bitfield_initialize_copy (VALUE self, VALUE other)
616
669
  TypedData_Get_Struct(self, CABitfield, &cabitfield_data_type, ca);
617
670
  TypedData_Get_Struct(other, CABitfield, &cabitfield_data_type, cs);
618
671
 
619
- ca_bitfield_setup(ca, cs->parent,
620
- 8 * cs->byte_offset + cs->bit_offset,
672
+ if ( ca_func[CA_OBJ_BITFIELD].pool_init ) {
673
+ ca_array_pool_alloc(ca, CA_OBJ_BITFIELD, cs->parent->ndim);
674
+ }
675
+ ca_bitfield_setup(ca, cs->parent,
676
+ cs->bit_start,
621
677
  bitfield_bitlen(cs->bit_mask, cs->bytes));
622
678
 
623
679
  return self;
624
680
  }
625
681
 
626
682
  void
627
- Init_ca_obj_bitfield ()
683
+ Init_ca_obj_bitfield (void)
628
684
  {
629
- rb_cCABitfield = rb_define_class("CABitfield", rb_cCAVirtual);
685
+ rb_cCABitfield = rb_define_class("CABitfield", rb_cCAView);
686
+
687
+ ca_bitfield_func.struct_size = sizeof(CABitfield);
688
+ ca_bitfield_func.pool_bytes = ca_bitfield_pool_bytes;
689
+ ca_bitfield_func.pool_init = ca_bitfield_pool_init;
630
690
 
631
- CA_OBJ_BITFIELD = ca_install_obj_type(rb_cCABitfield,
632
- &cabitfield_data_type,
691
+ CA_OBJ_BITFIELD = ca_install_obj_type(rb_cCABitfield,
692
+ &cabitfield_data_type,
633
693
  rb_cCArrayMask,
634
- &carray_data_type, ca_bitfield_func);
694
+ &carray_mask_data_type, &ca_bitfield_func, sizeof(ca_bitfield_func));
635
695
  rb_define_const(rb_cObject, "CA_OBJ_BITFIELD", INT2NUM(CA_OBJ_BITFIELD));
636
696
 
637
697
  rb_define_method(rb_cCArray, "bitfield", rb_ca_bitfield, -1);