carray 2.0.1 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -25
  3. data/CHANGELOG.md +338 -0
  4. data/{NEWS.md → CHANGELOG.v1.md} +3 -0
  5. data/LICENSE +1 -1
  6. data/README.md +120 -36
  7. data/carray.gemspec +32 -30
  8. data/ext/ca_array_pool.c +91 -0
  9. data/ext/ca_axis_descriptor.h +186 -0
  10. data/ext/ca_axis_dispatch.c +924 -0
  11. data/ext/ca_axis_group.c +1244 -0
  12. data/ext/ca_bincmp_dispatch.c +76 -0
  13. data/ext/ca_bincmp_dispatch.h +85 -0
  14. data/ext/ca_binop_dispatch.c +124 -0
  15. data/ext/ca_binop_dispatch.h +152 -0
  16. data/ext/ca_categorical_iterator.c +1375 -0
  17. data/ext/ca_compare.c +94 -0
  18. data/ext/ca_compare.h +26 -0
  19. data/ext/ca_composite_dispatch.c +414 -0
  20. data/ext/ca_composite_dispatch.h +116 -0
  21. data/ext/ca_for_buffer.h +96 -0
  22. data/ext/ca_for_each_element.h +239 -0
  23. data/ext/ca_group_iter.c +304 -0
  24. data/ext/ca_iter_substrate.h +325 -0
  25. data/ext/ca_kernel_iterator.c +4367 -0
  26. data/ext/ca_kernel_iterator.h +2596 -0
  27. data/ext/ca_moncmp_dispatch.c +37 -0
  28. data/ext/ca_moncmp_dispatch.h +62 -0
  29. data/ext/ca_monop_dispatch.c +200 -0
  30. data/ext/ca_monop_dispatch.h +235 -0
  31. data/ext/ca_obj_array.c +355 -359
  32. data/ext/ca_obj_bincmp.c +839 -0
  33. data/ext/ca_obj_binop.c +948 -0
  34. data/ext/ca_obj_bitarray.c +369 -164
  35. data/ext/ca_obj_bitfield.c +294 -234
  36. data/ext/ca_obj_block.c +189 -711
  37. data/ext/ca_obj_byte_swap.c +766 -0
  38. data/ext/ca_obj_const_string.c +967 -0
  39. data/ext/ca_obj_face.c +750 -0
  40. data/ext/ca_obj_face.h +279 -0
  41. data/ext/ca_obj_fake.c +239 -100
  42. data/ext/ca_obj_farray.c +54 -441
  43. data/ext/ca_obj_field.c +82 -529
  44. data/ext/ca_obj_fixlen_string.c +308 -0
  45. data/ext/ca_obj_grid.c +866 -440
  46. data/ext/ca_obj_meld.c +1039 -0
  47. data/ext/ca_obj_moncmp.c +588 -0
  48. data/ext/ca_obj_monop.c +1123 -0
  49. data/ext/ca_obj_object.c +866 -296
  50. data/ext/ca_obj_record.c +470 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +593 -459
  53. data/ext/ca_obj_remap.c +475 -0
  54. data/ext/ca_obj_repeat.c +92 -477
  55. data/ext/ca_obj_roll.c +624 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1306 -0
  58. data/ext/ca_obj_shift.c +231 -793
  59. data/ext/ca_obj_source.c +78 -0
  60. data/ext/ca_obj_stack.c +1173 -0
  61. data/ext/ca_obj_stride.c +2584 -0
  62. data/ext/ca_obj_string.c +270 -0
  63. data/ext/ca_obj_tile.c +622 -0
  64. data/ext/ca_obj_time.c +548 -0
  65. data/ext/ca_obj_timedelta.c +437 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +785 -0
  68. data/ext/ca_obj_window.c +1202 -565
  69. data/ext/ca_op_byte_swap.c +175 -0
  70. data/ext/ca_op_cmplx64.h +123 -0
  71. data/ext/ca_op_ipower.c +316 -0
  72. data/ext/ca_op_powi.h +88 -0
  73. data/ext/ca_sort_kernels.h +132 -0
  74. data/ext/ca_sweep_engine.c +473 -0
  75. data/ext/ca_sweep_engine.h +166 -0
  76. data/ext/ca_transform_common.c +235 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +810 -420
  80. data/ext/carray_access.c +873 -731
  81. data/ext/carray_attribute.c +98 -329
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +376 -0
  84. data/ext/carray_build_flags.h +3 -0
  85. data/ext/carray_call_cfunc.c +2897 -874
  86. data/ext/carray_call_cfunc.h +313 -0
  87. data/ext/carray_cast.c +1264 -315
  88. data/ext/carray_cast_func.rb +81 -40
  89. data/ext/carray_class.c +53 -63
  90. data/ext/carray_config.h +28 -0
  91. data/ext/carray_conversion.c +350 -346
  92. data/ext/carray_copy.c +168 -270
  93. data/ext/carray_core.c +1396 -206
  94. data/ext/carray_count.c +312 -0
  95. data/ext/carray_data_type.c +43 -19
  96. data/ext/carray_element.c +585 -213
  97. data/ext/carray_factorize.c +2542 -0
  98. data/ext/carray_generate.c +230 -559
  99. data/ext/carray_histogram.c +490 -0
  100. data/ext/carray_hold.c +228 -0
  101. data/ext/carray_index_classifier.c +1021 -0
  102. data/ext/carray_index_classifier.h +27 -0
  103. data/ext/carray_internal.h +136 -0
  104. data/ext/carray_kernels_bincmp.c +4446 -0
  105. data/ext/carray_kernels_binop.c +11001 -0
  106. data/ext/carray_kernels_init.c +1131 -0
  107. data/ext/carray_kernels_map.c +3467 -0
  108. data/ext/carray_kernels_moncmp.c +2097 -0
  109. data/ext/carray_kernels_monop.c +18313 -0
  110. data/ext/carray_kernels_reduce_aggregate.c +25837 -0
  111. data/ext/carray_kernels_reduce_boolean.c +330 -0
  112. data/ext/carray_kernels_reduce_cumulative.c +14593 -0
  113. data/ext/carray_kernels_reduce_extreme.c +16948 -0
  114. data/ext/carray_kernels_reduce_variance.c +3910 -0
  115. data/ext/carray_kernels_scan.c +3693 -0
  116. data/ext/carray_kernels_search.c +32138 -0
  117. data/ext/carray_kernels_sort.c +10626 -0
  118. data/ext/carray_kernels_triop.c +1392 -0
  119. data/ext/carray_lazy.c +737 -0
  120. data/ext/carray_loop.c +88 -200
  121. data/ext/carray_mask.c +853 -158
  122. data/ext/carray_math_kernel.h +120 -0
  123. data/ext/carray_mathfunc.c +10 -241
  124. data/ext/carray_median_percentile.c +1257 -0
  125. data/ext/carray_memory_view.c +1650 -0
  126. data/ext/carray_operator.c +1525 -320
  127. data/ext/carray_order.c +664 -1394
  128. data/ext/carray_partition.c +416 -0
  129. data/ext/carray_random.c +518 -0
  130. data/ext/carray_scatter.c +357 -0
  131. data/ext/carray_slab.c +1219 -0
  132. data/ext/carray_slab.h +84 -0
  133. data/ext/carray_sort.c +829 -0
  134. data/ext/carray_sort_kernel.c +620 -0
  135. data/ext/carray_struct.c +695 -0
  136. data/ext/carray_test.c +343 -229
  137. data/ext/carray_undef.c +34 -17
  138. data/ext/carray_utils.c +175 -74
  139. data/ext/extconf.rb +234 -55
  140. data/ext/mk_call_cfunc.rb +671 -0
  141. data/ext/mkkernel.rb +9096 -0
  142. data/ext/ruby_carray.c +211 -108
  143. data/ext/version.h +4 -14
  144. data/ext/version.rb +5 -13
  145. data/lib/carray/arrow_tensor.rb +401 -0
  146. data/lib/carray/attribute.rb +166 -0
  147. data/lib/carray/autoload_carray.rb +239 -0
  148. data/lib/carray/autoload_method_extension.rb +45 -0
  149. data/lib/carray/axis_group.rb +711 -0
  150. data/lib/carray/basics.rb +481 -0
  151. data/lib/carray/bincount_nd.rb +358 -0
  152. data/lib/carray/block_iterator.rb +614 -0
  153. data/lib/carray/boolean_reduce.rb +109 -0
  154. data/lib/carray/categorical.rb +561 -0
  155. data/lib/carray/categorical_iterator.rb +1084 -0
  156. data/lib/carray/complex.rb +150 -0
  157. data/lib/carray/conditional.rb +216 -0
  158. data/lib/carray/const_string.rb +228 -0
  159. data/lib/carray/construct.rb +160 -328
  160. data/lib/carray/core_extensions.rb +297 -0
  161. data/lib/carray/data_type_extension.rb +250 -0
  162. data/lib/carray/fixlen_string.rb +95 -0
  163. data/lib/carray/frame/concat.rb +132 -0
  164. data/lib/carray/frame/convert.rb +95 -0
  165. data/lib/carray/frame/csv_parser.rb +211 -0
  166. data/lib/carray/frame/frame.rb +642 -0
  167. data/lib/carray/frame/group.rb +186 -0
  168. data/lib/carray/frame/io.rb +321 -0
  169. data/lib/carray/frame/join.rb +248 -0
  170. data/lib/carray/frame/records.rb +99 -0
  171. data/lib/carray/frame/sort.rb +113 -0
  172. data/lib/carray/frame/verbs.rb +316 -0
  173. data/lib/carray/frame.rb +16 -0
  174. data/lib/carray/fuse_source.rb +123 -0
  175. data/lib/carray/fusion.rb +218 -0
  176. data/lib/carray/histogram.rb +512 -0
  177. data/lib/carray/inspect.rb +37 -26
  178. data/lib/carray/iterator.rb +58 -349
  179. data/lib/carray/lazy.rb +941 -0
  180. data/lib/carray/mask_gap_fill.rb +200 -0
  181. data/lib/carray/math.rb +78 -342
  182. data/lib/carray/meld_reduce.rb +289 -0
  183. data/lib/carray/methods/align_addr.rb +116 -0
  184. data/lib/carray/methods/bin.rb +128 -0
  185. data/lib/carray/methods/bincount.rb +87 -0
  186. data/lib/carray/methods/bit_string.rb +92 -0
  187. data/lib/carray/methods/broadcast.rb +63 -0
  188. data/lib/carray/methods/choose.rb +39 -0
  189. data/lib/carray/methods/composition.rb +280 -0
  190. data/lib/carray/methods/gather_nd.rb +206 -0
  191. data/lib/carray/methods/index.rb +39 -0
  192. data/lib/carray/methods/insert_block.rb +99 -0
  193. data/lib/carray/methods/is_in.rb +141 -0
  194. data/lib/carray/methods/join.rb +90 -0
  195. data/lib/carray/methods/locate_addr.rb +52 -0
  196. data/lib/carray/methods/mask_duplicates.rb +41 -0
  197. data/lib/carray/methods/meshgrid.rb +90 -0
  198. data/lib/carray/methods/mode.rb +126 -0
  199. data/lib/carray/methods/nunique.rb +46 -0
  200. data/lib/carray/methods/resize.rb +56 -0
  201. data/lib/carray/methods/snap.rb +161 -0
  202. data/lib/carray/methods/string_format.rb +57 -0
  203. data/lib/carray/methods/unique.rb +47 -0
  204. data/lib/carray/methods/value_counts.rb +71 -0
  205. data/lib/carray/mkmf.rb +124 -101
  206. data/lib/carray/runtime.rb +89 -0
  207. data/lib/carray/serialize.rb +478 -167
  208. data/lib/carray/slab_iterator.rb +305 -0
  209. data/lib/carray/stack.rb +291 -0
  210. data/lib/carray/string.rb +56 -180
  211. data/lib/carray/string_operation_extension.rb +289 -0
  212. data/lib/carray/struct.rb +335 -323
  213. data/lib/carray/struct_builder.rb +697 -0
  214. data/lib/carray/table.rb +41 -2
  215. data/lib/carray/time.rb +2654 -38
  216. data/lib/carray/window_iterator.rb +927 -0
  217. data/lib/carray.rb +55 -57
  218. data/yard-stubs/ca_obj_array.rb +385 -0
  219. data/yard-stubs/ca_obj_bitarray.rb +38 -0
  220. data/yard-stubs/ca_obj_bitfield.rb +43 -0
  221. data/yard-stubs/ca_obj_block.rb +73 -0
  222. data/yard-stubs/ca_obj_byte_swap.rb +56 -0
  223. data/yard-stubs/ca_obj_fake.rb +31 -0
  224. data/yard-stubs/ca_obj_farray.rb +32 -0
  225. data/yard-stubs/ca_obj_field.rb +45 -0
  226. data/yard-stubs/ca_obj_grid.rb +35 -0
  227. data/yard-stubs/ca_obj_refer.rb +72 -0
  228. data/yard-stubs/ca_obj_roll.rb +45 -0
  229. data/yard-stubs/ca_obj_shift.rb +43 -0
  230. data/yard-stubs/ca_obj_stride.rb +181 -0
  231. data/yard-stubs/ca_obj_tile.rb +29 -0
  232. data/yard-stubs/ca_obj_transpose.rb +40 -0
  233. data/yard-stubs/ca_obj_window.rb +49 -0
  234. data/yard-stubs/carray_access.rb +131 -0
  235. data/yard-stubs/carray_attribute.rb +246 -0
  236. data/yard-stubs/carray_broadcast.rb +37 -0
  237. data/yard-stubs/carray_cast.rb +489 -0
  238. data/yard-stubs/carray_class.rb +65 -0
  239. data/yard-stubs/carray_conversion.rb +76 -0
  240. data/yard-stubs/carray_copy.rb +79 -0
  241. data/yard-stubs/carray_core.rb +114 -0
  242. data/yard-stubs/carray_count.rb +79 -0
  243. data/yard-stubs/carray_element.rb +108 -0
  244. data/yard-stubs/carray_generate.rb +66 -0
  245. data/yard-stubs/carray_lazy.rb +23 -0
  246. data/yard-stubs/carray_loop.rb +140 -0
  247. data/yard-stubs/carray_mask.rb +259 -0
  248. data/yard-stubs/carray_math.rb +132 -0
  249. data/yard-stubs/carray_mathfunc.rb +45 -0
  250. data/yard-stubs/carray_median_percentile.rb +89 -0
  251. data/yard-stubs/carray_memory_view.rb +163 -0
  252. data/yard-stubs/carray_order.rb +312 -0
  253. data/yard-stubs/carray_random.rb +89 -0
  254. data/yard-stubs/carray_scatter.rb +106 -0
  255. data/yard-stubs/carray_slab.rb +57 -0
  256. data/yard-stubs/carray_sort.rb +163 -0
  257. data/yard-stubs/carray_test.rb +85 -0
  258. data/yard-stubs/carray_undef.rb +64 -0
  259. data/yard-stubs/carray_utils.rb +97 -0
  260. data/yard-stubs/ruby_carray.rb +193 -0
  261. metadata +220 -138
  262. data/Rakefile +0 -51
  263. data/TODO.md +0 -18
  264. data/ext/ca_iter_block.c +0 -257
  265. data/ext/ca_iter_dimension.c +0 -299
  266. data/ext/ca_iter_window.c +0 -214
  267. data/ext/ca_obj_mapping.c +0 -644
  268. data/ext/ca_obj_unbound_repeat.c +0 -529
  269. data/ext/carray_iterator.c +0 -641
  270. data/ext/carray_math.rb +0 -850
  271. data/ext/carray_numeric.c +0 -259
  272. data/ext/carray_sort_addr.c +0 -254
  273. data/ext/carray_stat.c +0 -2100
  274. data/ext/carray_stat_proc.rb +0 -1999
  275. data/ext/mkmath.rb +0 -741
  276. data/ext/ruby_ccomplex.c +0 -509
  277. data/ext/ruby_float_func.c +0 -86
  278. data/lib/carray/array.rb +0 -8
  279. data/lib/carray/autoload/autoload_base.rb +0 -19
  280. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  281. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  282. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  283. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  284. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  285. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  286. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  287. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  288. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  289. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  290. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  291. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  292. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  293. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  294. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  295. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  296. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  297. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  298. data/lib/carray/autoload.rb +0 -141
  299. data/lib/carray/basic.rb +0 -191
  300. data/lib/carray/broadcast.rb +0 -101
  301. data/lib/carray/compose.rb +0 -315
  302. data/lib/carray/convert.rb +0 -115
  303. data/lib/carray/info.rb +0 -110
  304. data/lib/carray/io/imagemagick.rb +0 -235
  305. data/lib/carray/mask.rb +0 -102
  306. data/lib/carray/math/histogram.rb +0 -177
  307. data/lib/carray/math/recurrence.rb +0 -93
  308. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  309. data/lib/carray/object/ca_obj_link.rb +0 -50
  310. data/lib/carray/object/ca_obj_pack.rb +0 -99
  311. data/lib/carray/obsolete.rb +0 -256
  312. data/lib/carray/ordering.rb +0 -181
  313. data/lib/carray/testing.rb +0 -51
  314. data/lib/carray/transform.rb +0 -109
  315. data/mailmap +0 -1
  316. data/misc/Methods.ja.md +0 -182
  317. data/misc/NOTE +0 -51
  318. data/spec/Classes/CABitfield_spec.rb +0 -58
  319. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  320. data/spec/Classes/CABlock_spec.rb +0 -205
  321. data/spec/Classes/CAField_spec.rb +0 -39
  322. data/spec/Classes/CAGrid_spec.rb +0 -75
  323. data/spec/Classes/CAMap_spec.rb +0 -0
  324. data/spec/Classes/CAMapping_spec.rb +0 -105
  325. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  326. data/spec/Classes/CAObject_spec.rb +0 -33
  327. data/spec/Classes/CARefer_spec.rb +0 -93
  328. data/spec/Classes/CARepeat_spec.rb +0 -65
  329. data/spec/Classes/CASelect_spec.rb +0 -22
  330. data/spec/Classes/CAShift_spec.rb +0 -16
  331. data/spec/Classes/CAStruct_spec.rb +0 -71
  332. data/spec/Classes/CATranspose_spec.rb +0 -60
  333. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  334. data/spec/Classes/CAWindow_spec.rb +0 -54
  335. data/spec/Classes/CAWrap_spec.rb +0 -8
  336. data/spec/Classes/CArray_spec.rb +0 -184
  337. data/spec/Classes/CScalar_spec.rb +0 -55
  338. data/spec/Features/feature_130_spec.rb +0 -19
  339. data/spec/Features/feature_attributes_spec.rb +0 -280
  340. data/spec/Features/feature_boolean_spec.rb +0 -98
  341. data/spec/Features/feature_broadcast.rb +0 -116
  342. data/spec/Features/feature_cast_function.rb +0 -19
  343. data/spec/Features/feature_cast_spec.rb +0 -33
  344. data/spec/Features/feature_class_spec.rb +0 -84
  345. data/spec/Features/feature_complex_spec.rb +0 -42
  346. data/spec/Features/feature_composite_spec.rb +0 -124
  347. data/spec/Features/feature_convert_spec.rb +0 -46
  348. data/spec/Features/feature_copy_spec.rb +0 -123
  349. data/spec/Features/feature_creation_spec.rb +0 -84
  350. data/spec/Features/feature_element_spec.rb +0 -144
  351. data/spec/Features/feature_extream_spec.rb +0 -54
  352. data/spec/Features/feature_generate_spec.rb +0 -74
  353. data/spec/Features/feature_index_spec.rb +0 -69
  354. data/spec/Features/feature_mask_spec.rb +0 -580
  355. data/spec/Features/feature_math_spec.rb +0 -97
  356. data/spec/Features/feature_order_spec.rb +0 -146
  357. data/spec/Features/feature_ref_store_spec.rb +0 -209
  358. data/spec/Features/feature_serialization_spec.rb +0 -125
  359. data/spec/Features/feature_stat_spec.rb +0 -397
  360. data/spec/Features/feature_virtual_spec.rb +0 -48
  361. data/spec/Features/method_eq_spec.rb +0 -81
  362. data/spec/Features/method_is_nan_spec.rb +0 -12
  363. data/spec/Features/method_map_spec.rb +0 -54
  364. data/spec/Features/method_max_with.rb +0 -20
  365. data/spec/Features/method_min_with.rb +0 -19
  366. data/spec/Features/method_ne_spec.rb +0 -18
  367. data/spec/Features/method_project_spec.rb +0 -188
  368. data/spec/Features/method_ref_spec.rb +0 -27
  369. data/spec/Features/method_round_spec.rb +0 -11
  370. data/spec/Features/method_s_linspace_spec.rb +0 -48
  371. data/spec/Features/method_s_span_spec.rb +0 -14
  372. data/spec/Features/method_seq_spec.rb +0 -47
  373. data/spec/Features/method_sort_with.rb +0 -43
  374. data/spec/Features/method_sorted_with.rb +0 -29
  375. data/spec/Features/method_span_spec.rb +0 -42
  376. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  377. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  378. data/spec/spec_all.rb +0 -10
  379. data/utils/ca_ase.rb +0 -21
  380. data/utils/ca_methods.rb +0 -15
  381. data/utils/cast_checker.rb +0 -30
  382. data/utils/convert_test.rb +0 -73
  383. data/utils/extract_yard.rb +0 -22
  384. data/utils/guess_shape.rb +0 -76
  385. data/utils/monkey_patch_methods.rb +0 -62
  386. data/utils/remove_resource_fork.sh +0 -5
@@ -0,0 +1,297 @@
1
+ # ----------------------------------------------------------------------------
2
+ #
3
+ # carray/core_extensions.rb
4
+ #
5
+ # Refinement that restores the carray-flavoured monkey patches on
6
+ # Float / Integer / Rational / Numeric / TrueClass / FalseClass
7
+ # for files that opt in with `using CArray::CoreExtensions`.
8
+ #
9
+ # Provides:
10
+ # - Postfix math on Float/Integer/Rational (sqrt, exp, log, sin, ...)
11
+ # enabling scalar/CArray polymorphism: the same expression
12
+ # `(0.0415*(t-218.8)).tanh` works whether t is a Float or a CArray.
13
+ # - The same postfix math on Complex, so an expression written for a
14
+ # complex CArray still reads for a single cell taken out of it.
15
+ # - Angle normalisation on Numeric (deg_360 / deg_180 / rad_2pi / rad_pi).
16
+ # - Comparison helpers on Numeric (#eq / #ne) for symmetric usage:
17
+ # `5.eq(ca)` dispatches to `ca.eq(5)`.
18
+ # - Symmetric bitwise operators on Integer / TrueClass / FalseClass
19
+ # so that `5 | bool_ca`, `0xff & flag_ca`, `1 << position_ca` work
20
+ # without writing CA_INT(5) on the left.
21
+ #
22
+ # None of these are loaded by default `require "carray"`. Each file
23
+ # that wants any of them must opt in:
24
+ #
25
+ # using CArray::CoreExtensions
26
+ #
27
+ # Refinements are lexically scoped to the file (or class/module body)
28
+ # where `using` is written. Methods defined in that scope resolve
29
+ # the refined methods at call time regardless of who is calling.
30
+ #
31
+ # This file is auto-loaded on first reference to CArray::CoreExtensions.
32
+ #
33
+ # ----------------------------------------------------------------------------
34
+
35
+ class CArray
36
+ # Refinement carrying the carray-flavoured additions to Float / Integer /
37
+ # Rational / Numeric / TrueClass / FalseClass, for files that opt in with
38
+ # `using CArray::CoreExtensions`.
39
+ #
40
+ # It provides postfix math on scalars (so `(0.0415*(t-218.8)).tanh` reads
41
+ # the same whether `t` is a Float, a Complex or a CArray), angle
42
+ # normalisation, and comparison helpers. Being a refinement, it is
43
+ # lexically scoped: nothing changes for code that does not opt in.
44
+ module CoreExtensions
45
+
46
+ # @!visibility private
47
+ MATH_METHODS = %i[
48
+ sqrt exp log log10
49
+ sin cos tan sinh cosh tanh
50
+ asin acos atan asinh acosh atanh
51
+ ].freeze
52
+
53
+ [Float, Integer, Rational].each do |klass|
54
+ refine(klass) do
55
+ MATH_METHODS.each do |m|
56
+ module_eval <<~RUBY, __FILE__, __LINE__ + 1
57
+ def #{m}
58
+ Math.#{m}(self)
59
+ end
60
+ RUBY
61
+ end
62
+ def rad
63
+ self.to_f * Math::PI / 180.0
64
+ end
65
+ def deg
66
+ self.to_f * 180.0 / Math::PI
67
+ end
68
+ def distance(other)
69
+ (self.to_f - other.to_f).abs
70
+ end
71
+ # M.1 (PyTorch alignment) scalar polymorphism additions.
72
+ # `trunc` is left to Ruby's built-in semantics (Float#truncate
73
+ # returns Integer when arg=0) — its CArray counterpart preserves
74
+ # data type, so scalar-side use should call .to_f.trunc explicitly.
75
+ # Math.expm1 / Math.log1p don't exist in stdlib; hand-roll.
76
+ def expm1
77
+ Math.exp(self) - 1.0
78
+ end
79
+ def log1p
80
+ Math.log(1.0 + self)
81
+ end
82
+ def rsqrt
83
+ 1.0 / Math.sqrt(self)
84
+ end
85
+ def square
86
+ self * self
87
+ end
88
+ def signbit
89
+ self.negative?
90
+ end
91
+ end
92
+ end
93
+
94
+ # The subset of MATH_METHODS that CArray's complex kernels implement,
95
+ # plus the two elementwise helpers that also accept complex input.
96
+ #
97
+ # Absent, because a complex CArray raises CArray::DataTypeError for
98
+ # them: log10 (C99 has no clog10) and expm1 / log1p (no complex form
99
+ # in C99 either). Leaving them undefined on Complex keeps the scalar
100
+ # side failing wherever the array side fails. rad / deg / distance /
101
+ # signbit are absent for the same reason from the other direction:
102
+ # they go through #to_f, which Complex does not have.
103
+ #
104
+ # @!visibility private
105
+ COMPLEX_MATH_METHODS = %i[
106
+ sqrt exp log
107
+ sin cos tan sinh cosh tanh
108
+ asin acos atan asinh acosh atanh
109
+ square rsqrt
110
+ ].freeze
111
+
112
+ # Complex is not handled the way Float / Integer / Rational are.
113
+ # Math.tanh(Complex(1,2)) raises RangeError -- of the stdlib Math
114
+ # methods only Math.sqrt accepts a Complex -- so the complex forms
115
+ # need their own implementation.
116
+ #
117
+ # Each one runs the value through a one-element cmplx128 CScalar, so
118
+ # the answer comes from the very kernel the array form would have
119
+ # used. That is the point: the branch cuts of csqrt / clog / casin /
120
+ # cacosh / catanh, and the sign of a zero on either side of them, are
121
+ # whatever the platform's C99 complex.h says they are, and they are
122
+ # not the same everywhere. On this machine, for instance,
123
+ # catanh(-1+0i) yields -Infinity+(pi/4)i where C99 Annex G describes
124
+ # -Infinity+0i. A hand-written Complex implementation would have to
125
+ # reproduce each such quirk to agree with the array form, and would
126
+ # stop agreeing on the next platform; delegating agrees by
127
+ # construction on all of them. The cost is one CScalar per call
128
+ # (~0.4 microseconds), which is the right trade for a scalar
129
+ # convenience whose whole purpose is to read the same as the array.
130
+ #
131
+ # `square` is delegated rather than written as `self * self`: Ruby's
132
+ # Complex multiplication and C's `double _Complex` multiplication part
133
+ # ways on infinities (Complex(1, Inf) squared gives -Inf+Inf*i in Ruby
134
+ # and -Inf+NaN*i in C).
135
+ refine Complex do
136
+ COMPLEX_MATH_METHODS.each do |m|
137
+ module_eval <<~RUBY, __FILE__, __LINE__ + 1
138
+ def #{m}
139
+ CA_CMPLX128(self).#{m}[0]
140
+ end
141
+ RUBY
142
+ end
143
+ end
144
+
145
+ refine Numeric do
146
+ def deg_360
147
+ a = self.to_f
148
+ fa = a / 360.0
149
+ if a >= 0
150
+ (fa - fa.floor) * 360.0
151
+ else
152
+ (fa - fa.ceil + 1) * 360.0
153
+ end
154
+ end
155
+
156
+ def deg_180
157
+ a = self.to_f
158
+ fa = (a + 180.0) / 360.0
159
+ b = if a >= 0
160
+ (fa - fa.floor) * 360.0 - 180.0
161
+ else
162
+ (fa - fa.ceil) * 360.0 - 180.0
163
+ end
164
+ b += 360.0 if b <= -180.0
165
+ b
166
+ end
167
+
168
+ def rad_2pi
169
+ a = self.to_f
170
+ two_pi = 2 * Math::PI
171
+ fa = a / two_pi
172
+ if a >= 0
173
+ (fa - fa.floor) * two_pi
174
+ else
175
+ (fa - fa.ceil + 1) * two_pi
176
+ end
177
+ end
178
+
179
+ def rad_pi
180
+ a = self.to_f
181
+ two_pi = 2 * Math::PI
182
+ fa = (a + Math::PI) / two_pi
183
+ b = if a >= 0
184
+ (fa - fa.floor) * two_pi - Math::PI
185
+ else
186
+ (fa - fa.ceil) * two_pi - Math::PI
187
+ end
188
+ b += two_pi if b <= -Math::PI
189
+ b
190
+ end
191
+
192
+ def eq(other)
193
+ if CArray === other
194
+ other.eq(self)
195
+ else
196
+ self == other
197
+ end
198
+ end
199
+
200
+ def ne(other)
201
+ if CArray === other
202
+ other.ne(self)
203
+ else
204
+ self != other
205
+ end
206
+ end
207
+ end
208
+
209
+ refine Integer do
210
+ def |(other)
211
+ if CArray === other
212
+ if other.boolean?
213
+ other.bit_or(self)
214
+ else
215
+ l, r = other.coerce(self)
216
+ l | r
217
+ end
218
+ else
219
+ super
220
+ end
221
+ end
222
+
223
+ def &(other)
224
+ if CArray === other
225
+ if other.boolean?
226
+ other.bit_and(self)
227
+ else
228
+ l, r = other.coerce(self)
229
+ l & r
230
+ end
231
+ else
232
+ super
233
+ end
234
+ end
235
+
236
+ def ^(other)
237
+ if CArray === other
238
+ if other.boolean?
239
+ other.bit_xor(self)
240
+ else
241
+ l, r = other.coerce(self)
242
+ l ^ r
243
+ end
244
+ else
245
+ super
246
+ end
247
+ end
248
+
249
+ def <<(other)
250
+ if CArray === other
251
+ l, r = other.coerce(self)
252
+ l << r
253
+ else
254
+ super
255
+ end
256
+ end
257
+
258
+ def >>(other)
259
+ if CArray === other
260
+ l, r = other.coerce(self)
261
+ l >> r
262
+ else
263
+ super
264
+ end
265
+ end
266
+ end
267
+
268
+ [TrueClass, FalseClass].each do |klass|
269
+ refine(klass) do
270
+ def |(other)
271
+ if CArray === other && other.boolean?
272
+ other.bit_or(self)
273
+ else
274
+ super
275
+ end
276
+ end
277
+
278
+ def &(other)
279
+ if CArray === other && other.boolean?
280
+ other.bit_and(self)
281
+ else
282
+ super
283
+ end
284
+ end
285
+
286
+ def ^(other)
287
+ if CArray === other && other.boolean?
288
+ other.bit_xor(self)
289
+ else
290
+ super
291
+ end
292
+ end
293
+ end
294
+ end
295
+
296
+ end # module CoreExtensions
297
+ end # class CArray
@@ -0,0 +1,250 @@
1
+ # Numo / NumPy-style factory class methods, gathered here as a
2
+ # best-effort soft compatibility layer.
3
+ #
4
+ # Rationale (the apology this file owes the rest of carray):
5
+ #
6
+ # carray's native idiom for building arrays is the typed
7
+ # constructor (CArray.float64(3, 3) { 0 }, CA_INT([1, 2, 3]), and
8
+ # friends). The methods below -- zeros / ones / eye / identity /
9
+ # linspace / arange / full / meshgrid -- duplicate that
10
+ # functionality with NumPy / Numo-flavoured names. They exist
11
+ # for one specific reason: when a user is porting a NumPy or Numo
12
+ # example program over to carray, the first thing they hit is
13
+ # the array-creation entry point, and "I have to learn a whole
14
+ # different API just to call zeros" is the worst place to lose
15
+ # someone. Having these helpers means a paste from
16
+ #
17
+ # np.zeros((3, 3)) -> CArray.zeros([3, 3])
18
+ # np.full((3, 3), 7) -> CArray.full([3, 3], 7)
19
+ # np.linspace(0.0, 1.0, 5) -> CArray.linspace(0.0, 1.0, 5)
20
+ # Numo::DFloat.zeros(3, 3) -> CArray::Float64.zeros(3, 3)
21
+ #
22
+ # works with minimal rewriting. Both the splat-shape carray-ish
23
+ # form (CArray.zeros(3, 3)) and the array-shape NumPy-ish form
24
+ # (CArray.zeros([3, 3])) are accepted by the shape-taking
25
+ # factories.
26
+ #
27
+ # The methods land on CArray itself and on every typed class
28
+ # (CArray::Int32, CArray::Float64, etc.) via the
29
+ # DataTypeExtension module declared (empty) in
30
+ # lib/carray/construct.rb. Required AFTER construct.rb in
31
+ # lib/carray.rb so the module exists -- the extends in construct
32
+ # see this file's method additions transparently.
33
+ #
34
+ # meshgrid was previously in this file; it is now in
35
+ # lib/carray/methods/meshgrid.rb (autoloaded on first call).
36
+ #
37
+ # These helpers are not the "main" carray API. When writing new
38
+ # carray-flavoured code, prefer the typed constructors. Use
39
+ # these when porting external code or when a NumPy / Numo
40
+ # spelling reads more naturally to the audience.
41
+
42
+ class CArray
43
+
44
+ module DataTypeExtension
45
+
46
+ def guess_data_type_from_values (*values)
47
+ if values.all? {|v| v == true || v == false }
48
+ CA_BOOLEAN
49
+ elsif values.all? { |v| v.is_a?(Integer) }
50
+ CA_INT64
51
+ elsif values.all? { |v| v.is_a?(Float) }
52
+ CA_FLOAT64
53
+ elsif values.all? { |v| v.is_a?(Complex) }
54
+ CA_CMPLX128
55
+ else
56
+ CA_OBJECT
57
+ end
58
+ end
59
+
60
+ private :guess_data_type_from_values
61
+
62
+ # Normalize a shape argument list: accept both
63
+ #
64
+ # foo(3, 4) # splat (carray-style)
65
+ # foo([3, 4]) # Array (NumPy-style: foo((3, 4)))
66
+ #
67
+ # so users can paste NumPy / Numo example code with minimal
68
+ # rewriting.
69
+ def normalize_shape (args)
70
+ if args.size == 1 && args.first.is_a?(Array)
71
+ args.first
72
+ else
73
+ args
74
+ end
75
+ end
76
+
77
+ private :normalize_shape
78
+
79
+ # @overload zeros(*shape)
80
+ # Returns a new CArray of the given shape filled with zeros.
81
+ # Shape accepts both splat Integers and a single Array. When
82
+ # called on a typed class the `data_type` is taken from the
83
+ # class; otherwise it defaults to `CA_FLOAT64`.
84
+ # @param shape [Array<Integer>, Array<Array<Integer>>] shape
85
+ # of the result.
86
+ # @return [CArray]
87
+ def zeros (*args)
88
+ CArray.new(self::DataType || CA_FLOAT64, normalize_shape(args)).zero
89
+ end
90
+
91
+ # @overload ones(*shape)
92
+ # Returns a new CArray of the given shape filled with ones.
93
+ # Same shape and `data_type` rules as {#zeros}.
94
+ # @param shape [Array<Integer>, Array<Array<Integer>>]
95
+ # @return [CArray]
96
+ def ones (*args)
97
+ CArray.new(self::DataType || CA_FLOAT64, normalize_shape(args)).one
98
+ end
99
+
100
+ # @overload eye(n, m = n, k = 0)
101
+ # Returns a 2-D CArray with ones on the `k`-th diagonal and
102
+ # zeros elsewhere.
103
+ # @param n [Integer] number of rows.
104
+ # @param m [Integer] number of columns; defaults to `n`.
105
+ # @param k [Integer] diagonal offset (positive above the main
106
+ # diagonal, negative below).
107
+ # @return [CArray] shape `(n, m)`.
108
+ def eye (n, m = nil, k = 0)
109
+ m ||= n
110
+ mat = CArray.new(self::DataType || CA_FLOAT64, [n, m])
111
+ if k >= 0
112
+ count = [n, m - k].min
113
+ start = k
114
+ else
115
+ count = [n + k, m].min
116
+ start = (-k) * m
117
+ end
118
+ if count > 0
119
+ mat[[start, count, m+1]] = 1
120
+ end
121
+ mat
122
+ end
123
+
124
+ # @overload identity(n)
125
+ # Returns the `n` by `n` identity matrix.
126
+ # @param n [Integer] matrix size.
127
+ # @return [CArray] shape `(n, n)`.
128
+ def identity (n)
129
+ mat = CArray.new(self::DataType || CA_FLOAT64, [n, n])
130
+ mat[[nil,n+1]] = 1
131
+ mat
132
+ end
133
+
134
+ # @overload linspace(x1, x2, n = 100)
135
+ # Returns a 1-D CArray of `n` values evenly spaced from `x1`
136
+ # to `x2` inclusive, matching NumPy's `linspace`. For an integer
137
+ # target `data_type`, values are computed in float64 with the
138
+ # linspace step `(x2 - x1) / (n - 1)`, then floored to the target
139
+ # type — the rule `np.linspace(x1, x2, n, dtype=int)` uses (round
140
+ # toward -infinity, not toward zero). Both endpoints are hit
141
+ # exactly for integer output when `x1` and `x2` are
142
+ # integer-valued.
143
+ #
144
+ # Called on `CArray` itself (module method) integer inputs promote
145
+ # to `CA_FLOAT64` and the result is a float array. Called via an
146
+ # integer subclass (`CArray::Int32.linspace(...)`), the result is
147
+ # an integer array with floor semantics.
148
+ #
149
+ # @param x1 [Numeric] first value.
150
+ # @param x2 [Numeric] last value.
151
+ # @param n [Integer] number of samples.
152
+ # @return [CArray]
153
+ def linspace (x1, x2, n = 100)
154
+ data_type = self::DataType
155
+ unless data_type
156
+ guess = guess_data_type_from_values(x1, x2)
157
+ guess = CA_FLOAT64 if guess == CA_INT64
158
+ data_type = guess
159
+ end
160
+ # span is float-only ("N evenly-spaced integers" is ambiguous —
161
+ # see basics.rb). Route non-float targets through a float64
162
+ # span, then floor + cast; this matches np.linspace(dtype=int)
163
+ # bit for bit (floor rounds toward -infinity so negative
164
+ # midpoints go the same way as numpy's integer linspace).
165
+ float_out = CArray.new(CA_FLOAT64, [n]).span(x1.to_f..x2.to_f)
166
+ return float_out if data_type == CA_FLOAT64
167
+ float_out.floor.to_type(data_type)
168
+ end
169
+
170
+ # @overload arange(stop)
171
+ # Returns a 1-D CArray with values `0, 1, ..., stop - 1`.
172
+ # @param stop [Numeric] exclusive upper bound.
173
+ # @return [CArray]
174
+ # @overload arange(start, stop)
175
+ # Returns `start, start + 1, ..., stop - 1`.
176
+ # @param start [Numeric] inclusive lower bound.
177
+ # @param stop [Numeric] exclusive upper bound.
178
+ # @return [CArray]
179
+ # @overload arange(start, stop, step)
180
+ # Returns values from `start` to `stop` (exclusive) stepping
181
+ # by `step`.
182
+ # @param start [Numeric] inclusive lower bound.
183
+ # @param stop [Numeric] exclusive upper bound.
184
+ # @param step [Numeric] spacing.
185
+ # @return [CArray]
186
+ def arange (*args)
187
+ case args.size
188
+ when 3
189
+ start, stop, step = *args
190
+ when 2
191
+ start, stop = *args
192
+ step = 1
193
+ when 1
194
+ start = 0
195
+ stop, = *args
196
+ step = 1
197
+ else
198
+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1..3)"
199
+ end
200
+ raise ArgumentError, "step must not be 0" if step == 0
201
+ data_type = self::DataType
202
+ data_type ||= guess_data_type_from_values(start, stop, step)
203
+ # Element count comes from the arguments as given, not from the
204
+ # target data type: CArray::Int32.arange(0, 1, 0.25) counts four
205
+ # elements from the float step and truncates them on store.
206
+ # Integer arguments count exactly (divmod) so that a step dividing
207
+ # the span evenly does not gain a spurious element through float
208
+ # rounding.
209
+ span = stop - start
210
+ if span.is_a?(Integer) && step.is_a?(Integer)
211
+ q, r = span.divmod(step)
212
+ n = r.zero? ? q : q + 1
213
+ else
214
+ n = (span.to_f / step).ceil
215
+ end
216
+ n = 0 if n < 0
217
+ CArray.new(data_type, [n]).seq(start, step)
218
+ end
219
+
220
+ # @overload full(shape, fill_value)
221
+ # Returns a new CArray of the given shape filled with
222
+ # `fill_value`. `shape` accepts an Integer or an Array of
223
+ # Integers. The `data_type` is inferred from `fill_value`
224
+ # when the receiver is not a typed class.
225
+ # @param shape [Integer, Array<Integer>]
226
+ # @param fill_value [Object] value used to fill the array.
227
+ # @return [CArray]
228
+ def full (shape, fill_value)
229
+ data_type = self::DataType
230
+ data_type ||= guess_data_type_from_values(fill_value)
231
+ shape = [shape] unless shape.is_a?(Array)
232
+ CArray.new(data_type, shape).fill(fill_value)
233
+ end
234
+
235
+ # @overload empty(*shape)
236
+ # Returns a new CArray of the given shape whose contents are
237
+ # **uninitialised**. The caller must overwrite the array
238
+ # before reading from it. `CA_OBJECT` silently falls back to
239
+ # a zero-VALUE init required for GC safety.
240
+ # @param shape [Array<Integer>, Array<Array<Integer>>]
241
+ # @return [CArray]
242
+ def empty (*args)
243
+ CArray.__alloc_uninit__(self::DataType || CA_FLOAT64,
244
+ normalize_shape(args))
245
+ end
246
+
247
+ end
248
+
249
+ end
250
+
@@ -0,0 +1,95 @@
1
+ # ----------------------------------------------------------------------------
2
+ #
3
+ # CAFixlenString high-level construction surface.
4
+ #
5
+ # CAFixlenString itself (the string interpretation of CA_FIXLEN storage) lives
6
+ # in ext/ca_obj_string.c. This file provides the ergonomic builder that packs
7
+ # Ruby Strings into a fixed-width CA_FIXLEN entity and wraps it via
8
+ # CAFixlenString.wrap.
9
+ #
10
+ # ----------------------------------------------------------------------------
11
+
12
+ class CArray
13
+
14
+ # Build a CAFixlenString (fixed-width String array over CA_FIXLEN storage).
15
+ #
16
+ # CArray.fixlen_string(["ab", "cde"], bytes: 4) # explicit slot width
17
+ # CArray.fixlen_string(["ab", "cde"]) # width = max bytesize
18
+ # CArray.fixlen_string([a, nil, b], bytes: 8) # nil → masked element
19
+ #
20
+ # The bounded slot width is the storage seam CAFixlenString exposes.
21
+ # `truncate:` controls what happens when
22
+ # a value exceeds `bytes` (only reachable when `bytes` is given explicitly;
23
+ # the auto width can never overflow):
24
+ #
25
+ # :error (default) raise ArgumentError on overflow — loud data loss
26
+ # :silent let the native fixlen store keep the leading `bytes` bytes
27
+ #
28
+ # The overflow policy lives at this construction surface, not at per-cell
29
+ # `fix[i] = v` (which always truncates silently via the native fixlen store).
30
+ # A CArray source is normalised through a String Face
31
+ # ({CArray.string_face_of}): a raw CA_FIXLEN of matching width wraps
32
+ # zero-copy, other string-bearing arrays materialise, numeric is rejected.
33
+ # @overload fixlen_string(values, bytes: nil, truncate: :error)
34
+ # @param values [Array<String, nil>] source values.
35
+ # @param bytes [Integer, nil] slot width; defaults to the max bytesize.
36
+ # @param truncate [Symbol] `:error` or `:silent`.
37
+ # @return [CAFixlenString]
38
+ # @overload fixlen_string(ca, bytes: nil, truncate: :error)
39
+ # @param ca [CArray] a String Face, CA_OBJECT, or raw CA_FIXLEN array.
40
+ # @return [CAFixlenString]
41
+ # @raise [CArray::DataTypeError] if `ca` is numeric / boolean.
42
+ # @overload fixlen_string(n, bytes: nil, truncate: :error) { |i| ... }
43
+ # @param n [Integer] element count.
44
+ # @param bytes [Integer, nil] slot width; defaults to the max bytesize.
45
+ # @param truncate [Symbol] `:error` or `:silent`.
46
+ # @return [CAFixlenString]
47
+ def self.fixlen_string (arg, bytes: nil, truncate: :error, &block)
48
+ if arg.is_a?(CArray)
49
+ return string_face_of(arg).to_fixlen_string(bytes: bytes, truncate: truncate)
50
+ end
51
+ unless [:error, :silent].include?(truncate)
52
+ raise ArgumentError, "truncate: must be :error or :silent (got #{truncate.inspect})"
53
+ end
54
+ if block
55
+ n = Integer(arg)
56
+ if block.arity == 0
57
+ v = block.call
58
+ values = Array.new(n) { v }
59
+ else
60
+ values = Array.new(n) { |i| block.call(i) }
61
+ end
62
+ else
63
+ values = arg.to_a
64
+ end
65
+
66
+ width = bytes || values.compact.map { |s| s.to_s.bytesize }.max || 1
67
+ width = 1 if width < 1
68
+
69
+ if truncate == :error
70
+ values.each_with_index do |s, i|
71
+ next if s.nil?
72
+ b = s.to_s.bytesize
73
+ if b > width
74
+ raise ArgumentError,
75
+ "CArray.fixlen_string: value at #{i} is #{b} bytes, exceeds slot width #{width} " \
76
+ "(use truncate: :silent to keep the leading bytes)"
77
+ end
78
+ end
79
+ end
80
+
81
+ entity = CArray.new(CA_FIXLEN, [values.size], :bytes => width)
82
+ values.each_with_index do |s, i|
83
+ entity[i] = s.nil? ? UNDEF : s.to_s
84
+ end
85
+ CAFixlenString.wrap(entity)
86
+ end
87
+
88
+ end
89
+
90
+ # Mutable fixed-width String Face: L1 ops + in-place variants. In-place
91
+ # transforms re-store through the native fixlen path (silent truncate).
92
+ class CAFixlenString
93
+ include CArray::StringOperationMixin
94
+ include CArray::StringOperationMixin::Mutable
95
+ end