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,46 @@
1
+ class CArray
2
+
3
+ # @overload nunique(axis: nil, keep_axis: false)
4
+ # Counts the distinct values of `self`. This is the scalar-reduction
5
+ # member of the value-hash discovery family ({#unique},
6
+ # {#mask_duplicates}, {#value_counts}): where {#unique} compresses
7
+ # and {#value_counts} tabulates, `nunique` just counts.
8
+ #
9
+ # With `axis: nil` (default) it counts distinct values across the
10
+ # whole array and returns an Integer. With `axis: k` it counts per
11
+ # fiber along axis `k`, returning a reduced `CA_INT64` CArray
12
+ # (shape = self.shape with axis `k` removed; `keep_axis: true` keeps
13
+ # it as a length-1 axis). The shape rule matches other per-axis
14
+ # reductions such as `sum(axis:)`.
15
+ #
16
+ # The distinct count has identity 0: an empty array, an all-masked
17
+ # fiber, or a zero-length axis counts 0 (not UNDEF) — an empty set
18
+ # has zero distinct values. Masked cells do not participate.
19
+ #
20
+ # Numeric distinctness follows `==` with the family's two float
21
+ # special cases: all NaN collapse to a single value and
22
+ # -0.0 / +0.0 are the same value. For `CA_OBJECT` / `CA_FIXLEN`
23
+ # distinctness follows Ruby `eql?` / `hash` (which, unlike numeric,
24
+ # does not collapse distinct NaN objects).
25
+ #
26
+ # @param axis [Integer, nil] axis to count along; `nil` counts over
27
+ # the whole array.
28
+ # @param keep_axis [Boolean] when `axis` is given, keep the reduced
29
+ # axis as a length-1 axis instead of dropping it.
30
+ # @return [Integer, CArray] Integer for `axis: nil`, otherwise a
31
+ # reduced `CA_INT64` CArray.
32
+ def nunique (axis: nil, keep_axis: false)
33
+ # Per-fiber single-pass seen-set hash (C __nunique__), one lane per data type
34
+ # family (numeric widen / NaN collapse, object rb_hash + rb_eql, fixlen
35
+ # byte-hash + memcmp). Masked cells are skipped; the accumulator is a no-op
36
+ # (the distinct count is the interned-key count).
37
+ if axis.nil?
38
+ # Whole-array distinct count: flatten to 1-D and reduce its only axis,
39
+ # then read the single reduced cell as an Integer.
40
+ flatten.send(:__nunique__, 0, false)[0]
41
+ else
42
+ __nunique__(normalize_axis(axis, "nunique"), keep_axis)
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,56 @@
1
+ class CArray
2
+
3
+ # @overload resize(*newdim, fill_value: 0)
4
+ # Returns `self` resized to `newdim`. The original data is
5
+ # placed at offset 0 (positive size) or right-aligned (negative
6
+ # size); the new area outside the original region is filled
7
+ # with `fill_value`, or -- for fixlen storage -- left as zero
8
+ # bytes. Pass `UNDEF` to mask the new area.
9
+ #
10
+ # Each entry of `newdim` is: `nil` to keep the current
11
+ # `shape[i]`, a positive Integer for a new size with the
12
+ # original left-aligned at offset 0, or a negative Integer
13
+ # `d` for a new size `|d|` with the original right-aligned.
14
+ #
15
+ # Works on Face arrays (CARecord / CATime / ...) and
16
+ # plain fixlen: the resize is done on the storage layout
17
+ # (preserving bytes) and re-wrapped as the same Face.
18
+ #
19
+ # @param newdim [Array<Integer, nil>] new shape spec, one entry
20
+ # per axis.
21
+ # @param fill_value [Object] value for the extended area.
22
+ # @return [CArray] resized copy.
23
+ def resize (*newdim, fill_value: 0)
24
+ raise "ndim mismatch" if newdim.size != ndim
25
+ offset = Array.new(ndim, 0)
26
+ newdim = newdim.each_with_index.map do |d, i|
27
+ case d
28
+ when nil
29
+ shape[i]
30
+ when Integer
31
+ size = d.abs
32
+ offset[i] = size - shape[i] if d < 0
33
+ size
34
+ else
35
+ raise "invalid dimension size"
36
+ end
37
+ end
38
+ face_parent = self.face? ? self : nil
39
+ src = self
40
+ src = src.parent while src.face?
41
+ dt = src.data_type
42
+ bytes = (dt == :fixlen) ? src.bytes : nil
43
+ out = CArray.new(dt, newdim, bytes: bytes)
44
+ # Fill the new area: numeric storage takes fill_value as-is; fixlen
45
+ # storage cannot hold a numeric 0, so leave zero bytes and honor only
46
+ # UNDEF (mask) or an explicit String fill.
47
+ if dt != :fixlen || fill_value.equal?(UNDEF) || fill_value.is_a?(String)
48
+ out[] = fill_value
49
+ end
50
+ out.mask.paste(offset, src.false) if out.has_mask?
51
+ out.paste(offset, src)
52
+ out = out.face_lift(face_parent) if face_parent
53
+ out
54
+ end
55
+
56
+ end
@@ -0,0 +1,161 @@
1
+ class CArray
2
+
3
+ # @overload snap(step, offset: 0.0, direction: :round)
4
+ # Returns each element snapped to a point on the uniform grid
5
+ # `..., -step + offset, offset, step + offset, 2*step + offset, ...`.
6
+ # The rounding rule follows `direction:` (default `:round`,
7
+ # matching `CArray#round`; `:floor` snaps toward `-inf`, `:ceil`
8
+ # toward `+inf`).
9
+ #
10
+ # The output has the same data type as `self` (integer input is coerced
11
+ # to float internally when `step` / `offset` are floats, following
12
+ # normal arithmetic promotion). NaN / Inf are preserved as a mask
13
+ # on the output; the rounding kernels map NaN to 0.0, which would
14
+ # silently land NaN cells on the grid, so NaN is detected
15
+ # explicitly on the scaled chain.
16
+ #
17
+ # Use `snap_to(list)` when the target grid is non-uniform; use
18
+ # `bin(vmin, vmax, step)` when the desired output is a bin index.
19
+ #
20
+ # @param step [Numeric] positive grid spacing.
21
+ # @param offset [Numeric] phase / origin of the grid; the grid
22
+ # always passes through `offset`.
23
+ # @param direction [:round, :floor, :ceil] rounding rule; `:round`
24
+ # picks the nearest grid point (ties half-away-from-zero),
25
+ # `:floor` picks the grid point at or below the value, `:ceil`
26
+ # picks the grid point at or above.
27
+ # @return [CArray] snapped values, same shape as `self`.
28
+ # @raise [ArgumentError] when `step <= 0` or `direction` is not one
29
+ # of the accepted symbols.
30
+ # @example
31
+ # temp.snap(0.5) # nearest 0.5 K grid point
32
+ # temp.snap(0.5, offset: 0.25) # to 0.25, 0.75, 1.25, ... (bin centers)
33
+ # temp.snap(0.5, direction: :floor) # bin lower edge
34
+ # temp.snap(0.5, direction: :ceil) # bin upper edge
35
+ def snap(step, offset: 0.0, direction: :round)
36
+ raise ArgumentError, "snap: step must be > 0" unless step > 0
37
+ unless [:round, :floor, :ceil].include?(direction)
38
+ raise ArgumentError,
39
+ "snap: direction must be :round / :floor / :ceil " \
40
+ "(got #{direction.inspect})"
41
+ end
42
+
43
+ scaled = (self - offset) / step
44
+
45
+ # Detect NaN / Inf before rounding (which maps NaN -> 0.0 silently).
46
+ invalid_mask = scaled.float? ? scaled.is_invalid : nil
47
+
48
+ snapped = case direction
49
+ when :round then scaled.round
50
+ when :floor then scaled.floor
51
+ when :ceil then scaled.ceil
52
+ end
53
+ out = snapped * step + offset
54
+
55
+ if invalid_mask && invalid_mask.count(true) > 0
56
+ out.mask = out.has_mask? ? (out.mask | invalid_mask) : invalid_mask
57
+ end
58
+
59
+ out
60
+ end
61
+
62
+ # @overload snap_to(list, lfill: :clamp, ufill: :clamp, direction: :round)
63
+ # Returns each element snapped to a value in `list` (non-uniform
64
+ # grid). The rounding rule follows `direction:` (default `:round`
65
+ # for nearest neighbour; `:floor` picks the list value at or below
66
+ # the sample, `:ceil` at or above), and delegates to
67
+ # `locate_nearest_addr(direction:)`.
68
+ #
69
+ # `list` must be a 1-D ascending numeric CArray (or convertible via
70
+ # `CArray.wrap_readonly`). Out-of-range and NaN handling follows the
71
+ # same pattern as `bin_to`, but with an additional `:clamp`
72
+ # sentinel that snaps out-of-range cells to the nearest list end.
73
+ #
74
+ # - `:clamp` (default) — below-range cells become `list[0]`,
75
+ # above-range cells become `list[-1]`.
76
+ # - `nil` — the side is masked in the output.
77
+ # - any other value — the side is filled with that value.
78
+ #
79
+ # NaN / masked input cells are always masked in the output,
80
+ # regardless of `lfill` / `ufill`.
81
+ #
82
+ # Use `snap(step, offset:)` when the target grid is uniform; use
83
+ # `bin_to(edges)` when the output is a bin index against half-open
84
+ # intervals rather than a nearest-value snap.
85
+ #
86
+ # @param list [CArray, Array<Numeric>] 1-D ascending grid, at least
87
+ # one value.
88
+ # @param lfill [:clamp, nil, Numeric] handling for below-`list[0]`
89
+ # cells.
90
+ # @param ufill [:clamp, nil, Numeric] handling for above-`list[-1]`
91
+ # cells.
92
+ # @param direction [:round, :floor, :ceil] rounding rule; forwarded
93
+ # to `locate_nearest_addr`.
94
+ # @return [CArray] snapped values with `list`'s data_type, same
95
+ # shape as `self`.
96
+ # @raise [ArgumentError] when `list` is not 1-D or is empty, or
97
+ # `direction` is not one of the accepted symbols.
98
+ # @example
99
+ # temp.snap_to([270.0, 280.0, 290.0, 300.0]) # clamp OOB
100
+ # temp.snap_to(grid, lfill: nil, ufill: nil) # mask OOB
101
+ # rain.snap_to([0.0, 1.0, 5.0, 20.0], direction: :floor) # list value at or below
102
+ def snap_to(list, lfill: :clamp, ufill: :clamp, direction: :round)
103
+ ref = list.is_a?(CArray) ? list : CArray.wrap_readonly(list, self.data_type)
104
+ raise ArgumentError, "snap_to: list must be 1-D" unless ref.ndim == 1
105
+ n = ref.elements
106
+ raise ArgumentError, "snap_to: list must have at least one value" if n < 1
107
+
108
+ if n == 1
109
+ # Degenerate: every finite cell snaps to the only value.
110
+ out = CArray.new(ref.data_type, shape).fill(ref[0])
111
+ out.mask = self.mask.to_ca if self.has_mask?
112
+ if self.float?
113
+ inv = self.is_invalid
114
+ if inv.count(true) > 0
115
+ out.mask = out.has_mask? ? (out.mask | inv) : inv
116
+ end
117
+ end
118
+ return out
119
+ end
120
+
121
+ # `locate_nearest_addr` (via `linear_section`) accepts a 1-D `val` only;
122
+ # flatten multi-D input and reshape the result back to preserve the
123
+ # element-wise semantic on any shape.
124
+ if ndim > 1
125
+ return reshape(-1).snap_to(ref, lfill: lfill, ufill: ufill,
126
+ direction: direction).reshape(*shape)
127
+ end
128
+
129
+ # locate_nearest_addr returns int64 indices; OOB (below / above / NaN)
130
+ # cells come back masked. We split OOB into below / above with
131
+ # explicit comparisons so the two sides can be filled independently.
132
+ idx = self.locate_nearest_addr(ref, direction: direction)
133
+ out = ref.project(idx)
134
+
135
+ below = self.lt(ref[0])
136
+ above = self.gt(ref[-1])
137
+
138
+ case lfill
139
+ when :clamp then out[below] = ref[0]
140
+ when nil then # leave masked (locate_nearest_addr already masked OOB)
141
+ else out[below] = lfill
142
+ end
143
+
144
+ case ufill
145
+ when :clamp then out[above] = ref[-1]
146
+ when nil then # leave masked
147
+ else out[above] = ufill
148
+ end
149
+
150
+ # Propagate input mask (locate_nearest_addr / project do not forward
151
+ # `self`'s mask on their own; a masked input cell must produce a
152
+ # masked output cell regardless of the fill options above).
153
+ if self.has_mask?
154
+ m = self.mask.to_ca
155
+ out.mask = out.has_mask? ? (out.mask | m) : m
156
+ end
157
+
158
+ out
159
+ end
160
+
161
+ end
@@ -0,0 +1,57 @@
1
+ # CArray.format (class) and CArray#format (instance) — element-wise
2
+ # Kernel.format producing a CAString. The instance form is the explicit
3
+ # numeric->string escape (a numeric array carries no implicit to_string).
4
+ # Single-feature method file (autoloaded on first format call).
5
+
6
+ class CArray
7
+
8
+ # @overload format(fmt, *argv)
9
+ # Returns a {CAString} of formatted strings. Each output cell at index
10
+ # `idx` is `Kernel.format(fmt, *args)` where a CArray argument contributes
11
+ # its `[*idx]` cell and any non-CArray argument is broadcast as-is. The
12
+ # output shape is taken from the first CArray argument; every CArray
13
+ # argument must share that shape.
14
+ # @param fmt [String] `Kernel.format` template.
15
+ # @param argv [Array<CArray, Object>] per-cell CArrays and/or broadcast scalars.
16
+ # @return [CAString]
17
+ # @raise [ArgumentError] when no CArray argument is given, or CArray shapes differ.
18
+ def self.format (fmt, *argv)
19
+ cas = argv.select { |a| a.is_a?(CArray) }
20
+ raise ArgumentError, "CArray.format: at least one CArray argument is required" if cas.empty?
21
+ shape = cas.first.shape
22
+ cas.each do |a|
23
+ next if a.shape == shape
24
+ raise ArgumentError,
25
+ "CArray.format: shape mismatch (#{a.shape.inspect} vs #{shape.inspect})"
26
+ end
27
+ out = CArray.object(*shape)
28
+ out.map_with_index! do |_, *idx|
29
+ args = argv.map { |a| a.is_a?(CArray) ? a[*idx] : a }
30
+ # a masked cell in any source array masks the output (UNDEF), rather
31
+ # than feeding UNDEF into Kernel.format.
32
+ args.any? { |v| v.equal?(UNDEF) } ? UNDEF : Kernel.format(fmt, *args)
33
+ end
34
+ CAString.wrap(out)
35
+ end
36
+
37
+ # @overload format(fmt, *argv)
38
+ # Returns a {CAString} formatting each cell of `self` with `fmt`; `self`
39
+ # is the first `Kernel.format` argument, so `arr.format("%03d")` renders
40
+ # the cells and `arr.format("%s=%d", other)` interleaves a second array.
41
+ # This is the explicit stringify path for numeric (and any) arrays — the
42
+ # `to_*` string conversions are String-Face only. Equivalent to
43
+ # `CArray.format(fmt, self, *argv)`.
44
+ #
45
+ # Defining a public `CArray#format` shadows the private `Kernel#format`
46
+ # for CArray instances; internal CArray methods therefore use `sprintf` /
47
+ # `Kernel.format` explicitly (verified: no bare `format(...)` call runs on
48
+ # a CArray receiver anywhere in the library).
49
+ # @param fmt [String] `Kernel.format` template.
50
+ # @param argv [Array<CArray, Object>] additional per-cell CArrays / broadcast scalars.
51
+ # @return [CAString]
52
+ # @raise [ArgumentError] when a CArray argument's shape differs from self.
53
+ def format (fmt, *argv)
54
+ CArray.format(fmt, self, *argv)
55
+ end
56
+
57
+ end
@@ -0,0 +1,47 @@
1
+ class CArray
2
+
3
+ # @overload unique(sort: false)
4
+ # Returns a 1-D CArray of the distinct values of `self`, in
5
+ # first-appearance (row-major flatten) order. This is the
6
+ # compressing counterpart of {#mask_duplicates} (which marks
7
+ # without compressing): because different fibers may hold
8
+ # different numbers of distinct values, compression is only
9
+ # well-defined over the whole array, so `unique` is always flat.
10
+ #
11
+ # Named `unique` (not `uniq`) because distinctness is value-based
12
+ # like NumPy / pandas `unique`: unlike Ruby `Array#uniq` it
13
+ # collapses all NaN to a single value (see below), so the name
14
+ # avoids promising `Array#uniq` semantics.
15
+ #
16
+ # Masked cells do not participate and never appear in the result;
17
+ # an all-masked array yields an empty CArray.
18
+ #
19
+ # Distinctness follows `==` for numeric data types, with two float
20
+ # special cases so the result matches value-based expectations:
21
+ # all NaN collapse to a single distinct value (rather than one per
22
+ # cell) and -0.0 / +0.0 are the same value. The value kept for
23
+ # each key is the first one seen, so a leading -0.0 keeps its sign.
24
+ # For `CA_OBJECT` / `CA_FIXLEN` distinctness follows Ruby
25
+ # `eql?` / `hash`; note that Ruby does not collapse distinct NaN
26
+ # objects, so a `CA_OBJECT` array of Float NaN is not collapsed
27
+ # (unlike the numeric path).
28
+ #
29
+ # @param sort [Boolean] when true, return the distinct values
30
+ # sorted ascending instead of in first-appearance order.
31
+ # A time array (`CATime` / `CATimedelta`) answers with its own type on
32
+ # its own unit: the distinct values are values, so the array comes back
33
+ # as itself rather than as raw storage ticks.
34
+ #
35
+ # @return [CArray] 1-D CArray of the distinct values, same data type
36
+ # as `self`.
37
+ def unique (sort: false)
38
+ # Single-pass seen-set hash (C __unique_flat__), one lane per data type family:
39
+ # integer widens to a 64-bit key; float uses the bitwise key with all-NaN
40
+ # collapsed and -0.0 / +0.0 normalized; object keys on rb_hash + rb_eql and
41
+ # fixlen on a byte-hash + memcmp, both reproducing Ruby Hash distinctness.
42
+ # Masked cells are skipped in the kernel.
43
+ levels = __unique_flat__
44
+ sort ? levels.sort : levels
45
+ end
46
+
47
+ end
@@ -0,0 +1,71 @@
1
+ class CArray
2
+
3
+ # @overload value_counts(sort: false)
4
+ # Returns `[values, counts]`, the distinct values of `self` paired
5
+ # with the number of times each occurs. `values` is a 1-D CArray of
6
+ # `self`'s data type; `counts` is a 1-D `CA_INT64` where `counts[i]` is
7
+ # the number of occurrences of `values[i]`. This is the frequency-
8
+ # table member of the value-hash discovery family ({#unique},
9
+ # {#mask_duplicates}, {#nunique}); like {#unique} it always
10
+ # flattens, because per-fiber distinct counts would be ragged.
11
+ #
12
+ # By default the pairs are in first-appearance (row-major flatten)
13
+ # order, matching {#unique}. `sort:` reorders both arrays together:
14
+ #
15
+ # - `false` (default) — first-appearance order.
16
+ # - `:count` — descending frequency; ties keep first-appearance
17
+ # order (deterministic).
18
+ # - `:value` — ascending value (float NaN sorts last, as in
19
+ # `unique(sort: true)`).
20
+ #
21
+ # Masked cells do not participate and never appear; an all-masked
22
+ # array yields two empty CArrays.
23
+ #
24
+ # Numeric distinctness follows `==` with two float special cases so
25
+ # the result matches value-based expectations: all NaN collapse to a
26
+ # single value (their counts add up) and -0.0 / +0.0 are the same
27
+ # value (the first-seen value is kept, so a leading -0.0 keeps its
28
+ # sign). For `CA_OBJECT` / `CA_FIXLEN` distinctness follows Ruby
29
+ # `eql?` / `hash`; Ruby does not collapse distinct NaN objects, so a
30
+ # `CA_OBJECT` array of Float NaN is not collapsed (unlike numeric).
31
+ #
32
+ # @param sort [false, :count, :value] pair ordering.
33
+ # The values keep `self`'s type (a `CATime` comes back as a `CATime` on
34
+ # its own unit); the counts are always a plain `:int64` CArray.
35
+ #
36
+ # @return [Array(CArray, CArray)] `[values, counts]`.
37
+ def value_counts (sort: false)
38
+ unless [false, :count, :value].include?(sort)
39
+ raise ArgumentError, "value_counts: sort must be false, :count, or :value"
40
+ end
41
+ # Single-pass frequency-table hash (C __value_counts_flat__), one lane per
42
+ # data type family: integer widens to a 64-bit key; float uses the bitwise key
43
+ # with all NaN collapsed and -0.0 / +0.0 normalized; object keys on rb_hash +
44
+ # rb_eql and fixlen on a byte-hash + memcmp, both reproducing Ruby Hash
45
+ # distinctness. Masked cells are skipped in the kernel.
46
+ values, counts = __value_counts_flat__
47
+ case sort
48
+ when :count
49
+ # Descending count, ties broken by first-appearance index (stable).
50
+ c = counts.to_a
51
+ order = (0...c.size).sort_by { |i| [-c[i], i] }
52
+ [ values[CArray.int64(order.size) { |i| order[i] }],
53
+ counts[CArray.int64(order.size) { |i| order[i] }] ]
54
+ when :value
55
+ # Ascending value; NaN (numeric) or non-comparable last. Build the
56
+ # permutation with an explicit NaN-last key so float NaN doesn't blow up
57
+ # the Ruby sort, then gather both arrays through it.
58
+ v = values.to_a
59
+ order = (0...v.size).sort_by do |i|
60
+ x = v[i]
61
+ nan = x.is_a?(Float) && x.nan?
62
+ [nan ? 1 : 0, nan ? 0 : x, i]
63
+ end
64
+ [ values[CArray.int64(order.size) { |i| order[i] }],
65
+ counts[CArray.int64(order.size) { |i| order[i] }] ]
66
+ else
67
+ [values, counts]
68
+ end
69
+ end
70
+
71
+ end