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
@@ -0,0 +1,306 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ ca_obj_fixlen_string.c
4
+
5
+ CAFixlenString — a String-array Face over CA_FIXLEN storage.
6
+
7
+ At the Face layer this is a plain fixlen -> fixlen identity Face: the
8
+ surface data_type equals the storage data_type (CA_FIXLEN), and no
9
+ reinterpretation happens. It is NOT a CARecord (which interprets the
10
+ fixlen bytes as a struct via the data_class encode/decode hooks); here
11
+ the bytes are the string, fetched and stored by the native fixlen path.
12
+
13
+ The Face's only job is to carry the CAFixlenString class across the view
14
+ chain and to organise the String method surface onto a dedicated class.
15
+ Because the storage is CA_FIXLEN (portable), the Face wrap can be carried
16
+ across multi-parent constructions (CAStack / Marshal / MemoryView).
17
+
18
+ Storage ops thin-forward to the parent via ca_face_* (ca_obj_face.h).
19
+ This is the sibling of CAString (identity Face over CA_OBJECT storage).
20
+
21
+ --------------------------------------------------------------------------- */
22
+
23
+ #include "carray.h"
24
+ #include "ca_obj_face.h"
25
+
26
+ typedef struct {
27
+ /* === CAView prefix === */
28
+ int16_t obj_type;
29
+ int8_t data_type; /* CA_FIXLEN (== storage) */
30
+ int8_t ndim;
31
+ int32_t flags; /* CA_FLAG_IS_FACE set */
32
+ ca_size_t bytes; /* K = parent->bytes */
33
+ ca_size_t elements;
34
+ ca_size_t *dim;
35
+ char *ptr;
36
+ CArray *mask;
37
+ char *_pool; /* framework-managed pool buffer */
38
+ CArray *parent;
39
+ uint32_t attach;
40
+ uint8_t nosync;
41
+ /* === Face tail === (none: CAFixlenString carries no per-instance state) */
42
+ } CAFixlenString;
43
+
44
+ static size_t
45
+ ca_fixlen_string_dsize (const void *ap)
46
+ {
47
+ const CAFixlenString *ca = (const CAFixlenString *) ap;
48
+ return sizeof(CAFixlenString) + ca->ndim * sizeof(ca_size_t);
49
+ }
50
+
51
+ /* Pool framework hooks: CAFixlenString owns a single ndim-sized tail (dim). */
52
+ static size_t
53
+ ca_fixlen_string_pool_bytes (int8_t ndim)
54
+ {
55
+ ca_size_t n = (ndim > 0) ? ndim : 1;
56
+ return (size_t) n * sizeof(ca_size_t);
57
+ }
58
+
59
+ static void
60
+ ca_fixlen_string_pool_init (void *ap, int8_t ndim)
61
+ {
62
+ CAFixlenString *ca = (CAFixlenString *) ap;
63
+ (void) ndim;
64
+ ca->dim = (ca_size_t *) ca->_pool;
65
+ }
66
+
67
+ const rb_data_type_t cafixlen_string_data_type = {
68
+ .parent = &caface_data_type,
69
+ .wrap_struct_name = "CAFixlenString",
70
+ .function = {
71
+ .dmark = ca_mark,
72
+ .dfree = ca_free,
73
+ .dsize = ca_fixlen_string_dsize,
74
+ .dcompact = NULL
75
+ },
76
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
77
+ };
78
+
79
+ static int8_t CA_OBJ_FIXLEN_STRING;
80
+ static VALUE rb_cCAFixlenString;
81
+
82
+ /* ------------------------------------------------------------------- */
83
+
84
+ int
85
+ ca_fixlen_string_setup (CAFixlenString *ca, CArray *parent)
86
+ {
87
+ if ( parent->data_type != CA_FIXLEN ) {
88
+ rb_raise(rb_eTypeError,
89
+ "CAFixlenString requires fixlen storage (parent.data_type != CA_FIXLEN)");
90
+ }
91
+
92
+ ca->obj_type = CA_OBJ_FIXLEN_STRING;
93
+ ca->data_type = CA_FIXLEN;
94
+ /* ORDERABLE + COMPARABLE, and both hold by construction: this Face's surface
95
+ IS its storage, byte for byte (a cell decodes to its own bytes, padding
96
+ included), so the descent is the identity map. memcmp order is therefore
97
+ String#<=> order for these cells, and byte equality is cell equality --
98
+ which is what the equality families need (docs/topics/CAFace.md §6.3).
99
+ Without the flags the sort family still worked (it exempts CA_FIXLEN
100
+ storage from the gate and orders by memcmp), but the value-hash family
101
+ handed its results back as a plain fixlen array, and search refused a
102
+ String query outright. */
103
+ ca->flags = CA_FLAG_IS_FACE
104
+ | CA_FLAG_FACE_ORDERABLE_STORAGE
105
+ | CA_FLAG_FACE_COMPARABLE_STORAGE;
106
+ ca->ndim = parent->ndim;
107
+ ca->bytes = parent->bytes;
108
+ ca->elements = parent->elements;
109
+ ca->ptr = NULL;
110
+ ca->mask = NULL;
111
+ if ( ! ca->_pool ) {
112
+ ca->dim = ALLOC_N(ca_size_t, parent->ndim);
113
+ }
114
+ memcpy(ca->dim, parent->dim, sizeof(ca_size_t) * parent->ndim);
115
+
116
+ ca->parent = parent;
117
+ ca->attach = 0;
118
+ ca->nosync = 0;
119
+
120
+ if ( ca_has_mask(parent) ) {
121
+ ca_create_mask((CArray *) ca);
122
+ }
123
+
124
+ if ( ca_is_scalar(parent) ) {
125
+ ca_set_flag(ca, CA_FLAG_SCALAR);
126
+ }
127
+
128
+ if ( ca_test_flag(parent, CA_FLAG_READ_ONLY) ) {
129
+ ca_set_flag(ca, CA_FLAG_READ_ONLY);
130
+ }
131
+
132
+ return 0;
133
+ }
134
+
135
+ CAFixlenString *
136
+ ca_fixlen_string_new (CArray *parent)
137
+ {
138
+ CAFixlenString *ca =
139
+ (CAFixlenString *) ca_array_alloc(CA_OBJ_FIXLEN_STRING, parent->ndim);
140
+ ca_fixlen_string_setup(ca, parent);
141
+ return ca;
142
+ }
143
+
144
+ static void
145
+ free_ca_fixlen_string (void *ap)
146
+ {
147
+ CAFixlenString *ca = (CAFixlenString *) ap;
148
+ if ( ca != NULL ) {
149
+ ca_free(ca->mask);
150
+ if ( ca->_pool ) {
151
+ ca_array_free(ca); /* dim lives in _pool */
152
+ }
153
+ else {
154
+ xfree(ca->dim);
155
+ xfree(ca);
156
+ }
157
+ }
158
+ }
159
+
160
+ /* ------------------------------------------------------------------- */
161
+
162
+ static void *
163
+ ca_fixlen_string_func_clone (void *ap)
164
+ {
165
+ CAFixlenString *ca = (CAFixlenString *) ap;
166
+ return ca_fixlen_string_new(ca->parent);
167
+ }
168
+
169
+ static void
170
+ ca_fixlen_string_func_allocate (void *ap)
171
+ {
172
+ CAFixlenString *ca = (CAFixlenString *) ap;
173
+ /* alias: parent attach + alias parent->ptr (Face has identical data) */
174
+ ca_attach(ca->parent);
175
+ ca->ptr = ca->parent->ptr;
176
+ }
177
+
178
+ static void
179
+ ca_fixlen_string_func_create_mask (void *ap)
180
+ {
181
+ CAFixlenString *ca = (CAFixlenString *) ap;
182
+ ca_update_mask(ca->parent);
183
+ if ( ! ca->parent->mask ) {
184
+ ca_create_mask(ca->parent);
185
+ }
186
+ ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
187
+ CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
188
+ }
189
+
190
+ ca_operation_function_t ca_fixlen_string_func = {
191
+ -1, /* CA_OBJ_FIXLEN_STRING — filled by ca_install_obj_type */
192
+ CA_VIEW_ARRAY,
193
+ free_ca_fixlen_string,
194
+ ca_fixlen_string_func_clone,
195
+ ca_fixlen_string_func_allocate,
196
+ ca_face_attach,
197
+ ca_face_sync,
198
+ ca_face_detach,
199
+ ca_face_fill_data,
200
+ ca_fixlen_string_func_create_mask,
201
+ ca_face_xfer_index,
202
+ ca_face_xfer_addrs,
203
+ NULL, /* fold_stride: identity Face is not foldable */
204
+ ca_face_xfer_stride,
205
+ ca_face_xfer_all
206
+ };
207
+
208
+ /* ------------------------------------------------------------------- */
209
+
210
+ /* CAFixlenString.wrap(fixlen_array) — zero-copy Face wrap */
211
+ VALUE
212
+ rb_ca_fixlen_string_wrap (VALUE parent_val)
213
+ {
214
+ volatile VALUE obj;
215
+ CArray *parent;
216
+ CAFixlenString *ca;
217
+
218
+ rb_check_carray_object(parent_val);
219
+ TypedData_Get_Struct(parent_val, CArray, &carray_data_type, parent);
220
+
221
+ ca = ca_fixlen_string_new(parent);
222
+ obj = ca_wrap_struct(ca);
223
+ rb_ca_set_parent(obj, parent_val);
224
+ return obj;
225
+ }
226
+
227
+ static VALUE
228
+ rb_ca_fixlen_string_wrap_method (VALUE klass, VALUE raw)
229
+ {
230
+ (void) klass;
231
+ return rb_ca_fixlen_string_wrap(raw);
232
+ }
233
+
234
+ /* Per-cell scalar decode: strip trailing NUL padding from the raw K-byte
235
+ fetch. A fixed-width slot pads short strings with NUL, which is padding,
236
+ not content (the same convention NumPy's 'S'/'U' dtypes use on readback).
237
+ Storage is unchanged -- only the surface scalar is stripped -- so sort /
238
+ search / MemoryView still see the raw padded bytes. Genuine trailing NULs
239
+ cannot survive here; use a raw CA_FIXLEN array for binary blobs. */
240
+ static VALUE
241
+ rb_ca_fixlen_string_storage_to_scalar (VALUE self, VALUE raw)
242
+ {
243
+ (void) self;
244
+ if ( TYPE(raw) == T_STRING ) {
245
+ const char *p = RSTRING_PTR(raw);
246
+ long n = RSTRING_LEN(raw);
247
+ while ( n > 0 && p[n - 1] == '\0' ) {
248
+ n--;
249
+ }
250
+ return rb_str_new(p, n);
251
+ }
252
+ return raw;
253
+ }
254
+
255
+ static VALUE
256
+ rb_ca_fixlen_string_s_allocate (VALUE klass)
257
+ {
258
+ CAFixlenString *ca;
259
+ return TypedData_Make_Struct(klass, CAFixlenString,
260
+ &cafixlen_string_data_type, ca);
261
+ }
262
+
263
+ static VALUE
264
+ rb_ca_fixlen_string_initialize_copy (VALUE self, VALUE other)
265
+ {
266
+ CAFixlenString *ca, *cs;
267
+ TypedData_Get_Struct(self, CAFixlenString, &cafixlen_string_data_type, ca);
268
+ TypedData_Get_Struct(other, CAFixlenString, &cafixlen_string_data_type, cs);
269
+ if ( ca_func[CA_OBJ_FIXLEN_STRING].pool_init ) {
270
+ ca_array_pool_alloc(ca, CA_OBJ_FIXLEN_STRING, cs->parent->ndim);
271
+ }
272
+ ca_fixlen_string_setup(ca, cs->parent);
273
+ return self;
274
+ }
275
+
276
+ void
277
+ Init_ca_obj_fixlen_string (void)
278
+ {
279
+ rb_cCAFixlenString = rb_define_class("CAFixlenString", rb_cCAFace);
280
+
281
+ ca_fixlen_string_func.struct_size = sizeof(CAFixlenString);
282
+ ca_fixlen_string_func.pool_bytes = ca_fixlen_string_pool_bytes;
283
+ ca_fixlen_string_func.pool_init = ca_fixlen_string_pool_init;
284
+
285
+ CA_OBJ_FIXLEN_STRING = ca_install_obj_type(rb_cCAFixlenString,
286
+ &cafixlen_string_data_type,
287
+ rb_cCArrayMask,
288
+ &carray_mask_data_type,
289
+ &ca_fixlen_string_func, sizeof(ca_fixlen_string_func));
290
+ rb_define_const(rb_cObject, "CA_OBJ_FIXLEN_STRING", INT2NUM(CA_OBJ_FIXLEN_STRING));
291
+
292
+ rb_define_alloc_func(rb_cCAFixlenString, rb_ca_fixlen_string_s_allocate);
293
+ rb_define_method(rb_cCAFixlenString, "initialize_copy",
294
+ rb_ca_fixlen_string_initialize_copy, 1);
295
+ rb_define_singleton_method(rb_cCAFixlenString, "wrap",
296
+ rb_ca_fixlen_string_wrap_method, 1);
297
+ rb_define_method(rb_cCAFixlenString, "storage_to_scalar",
298
+ rb_ca_fixlen_string_storage_to_scalar, 1);
299
+ ca_face_register_storage_to_scalar(CA_OBJ_FIXLEN_STRING,
300
+ rb_ca_fixlen_string_storage_to_scalar);
301
+
302
+ /* CA_FIXLEN is portable storage (fixed-width bytes, no per-process VALUE
303
+ or per-parent buffer), so the Face can be carried across multi-parent
304
+ constructions like CAStack / Marshal / MemoryView. */
305
+ ca_face_register_state_portable(CA_OBJ_FIXLEN_STRING, 1);
306
+ }