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,240 @@
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
+ # - Angle normalisation on Numeric (deg_360 / deg_180 / rad_2pi / rad_pi).
14
+ # - Comparison helpers on Numeric (#eq / #ne) for symmetric usage:
15
+ # `5.eq(ca)` dispatches to `ca.eq(5)`.
16
+ # - Symmetric bitwise operators on Integer / TrueClass / FalseClass
17
+ # so that `5 | bool_ca`, `0xff & flag_ca`, `1 << position_ca` work
18
+ # without writing CA_INT(5) on the left.
19
+ #
20
+ # None of these are loaded by default `require "carray"`. Each file
21
+ # that wants any of them must opt in:
22
+ #
23
+ # using CArray::CoreExtensions
24
+ #
25
+ # Refinements are lexically scoped to the file (or class/module body)
26
+ # where `using` is written. Methods defined in that scope resolve
27
+ # the refined methods at call time regardless of who is calling.
28
+ #
29
+ # This file is auto-loaded on first reference to CArray::CoreExtensions.
30
+ #
31
+ # ----------------------------------------------------------------------------
32
+
33
+ class CArray
34
+ # Refinement carrying the carray-flavoured additions to Float / Integer /
35
+ # Rational / Numeric / TrueClass / FalseClass, for files that opt in with
36
+ # `using CArray::CoreExtensions`.
37
+ #
38
+ # It provides postfix math on scalars (so `(0.0415*(t-218.8)).tanh` reads
39
+ # the same whether `t` is a Float or a CArray), angle normalisation, and
40
+ # comparison helpers. Being a refinement, it is lexically scoped: nothing
41
+ # changes for code that does not opt in.
42
+ module CoreExtensions
43
+
44
+ # @!visibility private
45
+ MATH_METHODS = %i[
46
+ sqrt exp log log10
47
+ sin cos tan sinh cosh tanh
48
+ asin acos atan asinh acosh atanh
49
+ ].freeze
50
+
51
+ [Float, Integer, Rational].each do |klass|
52
+ refine(klass) do
53
+ MATH_METHODS.each do |m|
54
+ define_method(m) { Math.send(m, self) }
55
+ end
56
+ def rad
57
+ self.to_f * Math::PI / 180.0
58
+ end
59
+ def deg
60
+ self.to_f * 180.0 / Math::PI
61
+ end
62
+ def distance(other)
63
+ (self.to_f - other.to_f).abs
64
+ end
65
+ # M.1 (PyTorch alignment) scalar polymorphism additions.
66
+ # `trunc` is left to Ruby's built-in semantics (Float#truncate
67
+ # returns Integer when arg=0) — its CArray counterpart preserves
68
+ # dtype, so scalar-side use should call .to_f.trunc explicitly.
69
+ # Math.expm1 / Math.log1p don't exist in stdlib; hand-roll.
70
+ def expm1
71
+ Math.exp(self) - 1.0
72
+ end
73
+ def log1p
74
+ Math.log(1.0 + self)
75
+ end
76
+ def rsqrt
77
+ 1.0 / Math.sqrt(self)
78
+ end
79
+ def square
80
+ self * self
81
+ end
82
+ def signbit
83
+ self.negative?
84
+ end
85
+ end
86
+ end
87
+
88
+ refine Numeric do
89
+ def deg_360
90
+ a = self.to_f
91
+ fa = a / 360.0
92
+ if a >= 0
93
+ (fa - fa.floor) * 360.0
94
+ else
95
+ (fa - fa.ceil + 1) * 360.0
96
+ end
97
+ end
98
+
99
+ def deg_180
100
+ a = self.to_f
101
+ fa = (a + 180.0) / 360.0
102
+ b = if a >= 0
103
+ (fa - fa.floor) * 360.0 - 180.0
104
+ else
105
+ (fa - fa.ceil) * 360.0 - 180.0
106
+ end
107
+ b += 360.0 if b <= -180.0
108
+ b
109
+ end
110
+
111
+ def rad_2pi
112
+ a = self.to_f
113
+ two_pi = 2 * Math::PI
114
+ fa = a / two_pi
115
+ if a >= 0
116
+ (fa - fa.floor) * two_pi
117
+ else
118
+ (fa - fa.ceil + 1) * two_pi
119
+ end
120
+ end
121
+
122
+ def rad_pi
123
+ a = self.to_f
124
+ two_pi = 2 * Math::PI
125
+ fa = (a + Math::PI) / two_pi
126
+ b = if a >= 0
127
+ (fa - fa.floor) * two_pi - Math::PI
128
+ else
129
+ (fa - fa.ceil) * two_pi - Math::PI
130
+ end
131
+ b += two_pi if b <= -Math::PI
132
+ b
133
+ end
134
+
135
+ def eq(other)
136
+ if CArray === other
137
+ other.eq(self)
138
+ else
139
+ self == other
140
+ end
141
+ end
142
+
143
+ def ne(other)
144
+ if CArray === other
145
+ other.ne(self)
146
+ else
147
+ self != other
148
+ end
149
+ end
150
+ end
151
+
152
+ refine Integer do
153
+ def |(other)
154
+ if CArray === other
155
+ if other.boolean?
156
+ other.bit_or(self)
157
+ else
158
+ l, r = other.coerce(self)
159
+ l | r
160
+ end
161
+ else
162
+ super
163
+ end
164
+ end
165
+
166
+ def &(other)
167
+ if CArray === other
168
+ if other.boolean?
169
+ other.bit_and(self)
170
+ else
171
+ l, r = other.coerce(self)
172
+ l & r
173
+ end
174
+ else
175
+ super
176
+ end
177
+ end
178
+
179
+ def ^(other)
180
+ if CArray === other
181
+ if other.boolean?
182
+ other.bit_xor(self)
183
+ else
184
+ l, r = other.coerce(self)
185
+ l ^ r
186
+ end
187
+ else
188
+ super
189
+ end
190
+ end
191
+
192
+ def <<(other)
193
+ if CArray === other
194
+ l, r = other.coerce(self)
195
+ l << r
196
+ else
197
+ super
198
+ end
199
+ end
200
+
201
+ def >>(other)
202
+ if CArray === other
203
+ l, r = other.coerce(self)
204
+ l >> r
205
+ else
206
+ super
207
+ end
208
+ end
209
+ end
210
+
211
+ [TrueClass, FalseClass].each do |klass|
212
+ refine(klass) do
213
+ def |(other)
214
+ if CArray === other && other.boolean?
215
+ other.bit_or(self)
216
+ else
217
+ super
218
+ end
219
+ end
220
+
221
+ def &(other)
222
+ if CArray === other && other.boolean?
223
+ other.bit_and(self)
224
+ else
225
+ super
226
+ end
227
+ end
228
+
229
+ def ^(other)
230
+ if CArray === other && other.boolean?
231
+ other.bit_xor(self)
232
+ else
233
+ super
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ end # module CoreExtensions
240
+ end # class CArray
@@ -0,0 +1,233 @@
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
+ end
198
+ data_type = self::DataType
199
+ data_type ||= guess_data_type_from_values(start, stop, step)
200
+ CArray.send(:__cast__, data_type, start..stop-step, step)
201
+ end
202
+
203
+ # @overload full(shape, fill_value)
204
+ # Returns a new CArray of the given shape filled with
205
+ # `fill_value`. `shape` accepts an Integer or an Array of
206
+ # Integers. The `data_type` is inferred from `fill_value`
207
+ # when the receiver is not a typed class.
208
+ # @param shape [Integer, Array<Integer>]
209
+ # @param fill_value [Object] value used to fill the array.
210
+ # @return [CArray]
211
+ def full (shape, fill_value)
212
+ data_type = self::DataType
213
+ data_type ||= guess_data_type_from_values(fill_value)
214
+ shape = [shape] unless shape.is_a?(Array)
215
+ CArray.new(data_type, shape).fill(fill_value)
216
+ end
217
+
218
+ # @overload empty(*shape)
219
+ # Returns a new CArray of the given shape whose contents are
220
+ # **uninitialised**. The caller must overwrite the array
221
+ # before reading from it. `CA_OBJECT` silently falls back to
222
+ # a zero-VALUE init required for GC safety.
223
+ # @param shape [Array<Integer>, Array<Array<Integer>>]
224
+ # @return [CArray]
225
+ def empty (*args)
226
+ CArray.__alloc_uninit__(self::DataType || CA_FLOAT64,
227
+ normalize_shape(args))
228
+ end
229
+
230
+ end
231
+
232
+ end
233
+
@@ -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
@@ -0,0 +1,132 @@
1
+ # CAFrame row concatenation (memo §5, spine = addressing + gather).
2
+ #
3
+ # Two entry points, mirroring the CArray-level taxonomy:
4
+ #
5
+ # +CAFrame.meld+ view frame, strict same-dtype per column,
6
+ # each column is a CAMeld view over the inputs
7
+ # +CAFrame.concatenate+ eager frame, auto-casts per column,
8
+ # each column is a materialised entity
9
+ #
10
+ # Both are class methods (symmetric N-ary; no frame is privileged), like
11
+ # +CArray.meld+ / +CArray.concatenate+, not instance verbs.
12
+
13
+ class CAFrame
14
+ # Weld frames along the row axis, view-style. Each output column is
15
+ # +CArray.meld+ of that column across the input frames, so the result
16
+ # is a view frame that shares storage with the inputs (chain composability
17
+ # preserved: writes to the result flow back to whichever input frame owns
18
+ # the target segment, and vice versa).
19
+ #
20
+ # Per-column +data_type+ must match across frames (CArray.meld is a view
21
+ # constructor that refuses to auto-cast — silent promotion here would
22
+ # hide schema drift). For an eager, auto-casting alternative use
23
+ # {CAFrame.concatenate}.
24
+ #
25
+ # Column matching is by name (output order follows the first frame);
26
+ # every frame must carry the same column-name set. N-D columns carry
27
+ # their trailing dimensions along; masks are preserved.
28
+ #
29
+ # The index is welded too when every frame has one (their +axis_name+
30
+ # must agree); if none do, the result has no index; a mix raises.
31
+ # Column-set mismatch raises — a union-with-UNDEF mode is a possible
32
+ # future opt-in, kept out here to stay explicit (memo §4.2).
33
+ #
34
+ # CAFrame.meld(jan, feb, mar) # view over three months
35
+ # CAFrame.meld([jan, feb, mar]) # an Array is accepted too
36
+ def self.meld(*frames)
37
+ frames = frames.flatten
38
+ check_concat_inputs(frames, verb: "meld")
39
+ first = frames.first
40
+ names = first.variable_names
41
+ check_column_sets(frames, names, verb: "meld")
42
+ cols = {}
43
+ names.each do |name|
44
+ cols[name] = CArray.meld(frames.map { |f| f[name] }, axis: 0)
45
+ end
46
+ new(cols, axis_name: first.axis_name, index: meld_index(frames))
47
+ end
48
+
49
+ # Concatenate frames along the row axis, eagerly. Each output column is
50
+ # +CArray.concatenate+ of that column across the input frames, so per-column
51
+ # dtypes auto-promote to a common type. The result is a fresh, independent
52
+ # frame — writes to it do not propagate back to the input frames.
53
+ #
54
+ # For a view frame that shares storage with the inputs (strict same dtype
55
+ # per column, chain composability preserved) use {CAFrame.meld}.
56
+ #
57
+ # Column matching, index handling, and column-set / index-mix rules
58
+ # match {CAFrame.meld}.
59
+ #
60
+ # CAFrame.concatenate(jan, feb, mar) # eager, independent result
61
+ # CAFrame.concatenate([jan, feb, mar]) # an Array is accepted too
62
+ def self.concatenate(*frames)
63
+ frames = frames.flatten
64
+ check_concat_inputs(frames, verb: "concatenate")
65
+ first = frames.first
66
+ names = first.variable_names
67
+ check_column_sets(frames, names, verb: "concatenate")
68
+ cols = {}
69
+ names.each do |name|
70
+ cols[name] = CArray.concatenate(frames.map { |f| f[name] })
71
+ end
72
+ new(cols, axis_name: first.axis_name, index: concatenate_index(frames))
73
+ end
74
+
75
+ # ---- shared validators -------------------------------------------------
76
+
77
+ def self.check_concat_inputs(frames, verb:)
78
+ raise ArgumentError, "#{verb} requires at least one frame" if frames.empty?
79
+ unless frames.all? { |f| f.is_a?(CAFrame) }
80
+ raise ArgumentError, "#{verb} expects CAFrame arguments"
81
+ end
82
+ end
83
+ private_class_method :check_concat_inputs
84
+
85
+ def self.check_column_sets(frames, names, verb:)
86
+ expected = names.sort
87
+ frames.each_with_index do |f, i|
88
+ next if i.zero?
89
+ if f.variable_names.sort != expected
90
+ raise ArgumentError,
91
+ "#{verb}: frame #{i} has columns #{f.variable_names.inspect}, " \
92
+ "expected the same set as #{names.inspect}"
93
+ end
94
+ end
95
+ end
96
+ private_class_method :check_column_sets
97
+
98
+ # ---- index helpers -----------------------------------------------------
99
+
100
+ # Index welded via CArray.meld (view). Every frame must agree: all
101
+ # indexed (axis names must match) or none.
102
+ def self.meld_index(frames)
103
+ indexes, axis = index_pieces(frames, verb: "meld")
104
+ return nil unless indexes
105
+ axis # unused; kept for symmetry
106
+ CArray.meld(indexes, axis: 0)
107
+ end
108
+ private_class_method :meld_index
109
+
110
+ # Index concatenated eagerly via CArray.concatenate.
111
+ def self.concatenate_index(frames)
112
+ indexes, _axis = index_pieces(frames, verb: "concatenate")
113
+ return nil unless indexes
114
+ CArray.concatenate(indexes)
115
+ end
116
+ private_class_method :concatenate_index
117
+
118
+ def self.index_pieces(frames, verb:)
119
+ indexes = frames.map(&:index)
120
+ return nil if indexes.none?
121
+ unless indexes.all?
122
+ raise ArgumentError, "#{verb}: some frames have an index and others do not"
123
+ end
124
+ axis_names = frames.map(&:axis_name).uniq
125
+ unless axis_names.size == 1
126
+ raise ArgumentError,
127
+ "#{verb}: indexed frames have different axis names #{axis_names.inspect}"
128
+ end
129
+ [indexes, axis_names.first]
130
+ end
131
+ private_class_method :index_pieces
132
+ end