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,518 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Random-number fill and shuffle: random / randomn / shuffle (+ bang
4
+ variants). Ruby-facing docs live in yard-stubs/carray_random.rb.
5
+
6
+ Backend: Ruby's built-in Random (MT19937) via public C API. When
7
+ the `rng:` kwarg is nil, uses the per-ractor default RNG
8
+ (rb_genrand_*); otherwise uses the given Random instance
9
+ (rb_random_*).
10
+
11
+ Dispatch:
12
+ random! -> uniform fill (per-dtype branch below)
13
+ randomn! -> standard normal via Box-Muller (float / complex only)
14
+ shuffle! -> Fisher-Yates over the flat buffer, or per-slice
15
+ when axis: is given (byte-chunk swap)
16
+ non-bang -> template / copy then delegate to the bang form
17
+
18
+ ---------------------------------------------------------------------------- */
19
+
20
+ #include "carray.h"
21
+ #include <math.h>
22
+ #include <string.h>
23
+
24
+
25
+ static inline double
26
+ ca_random_real(VALUE rng)
27
+ {
28
+ if (NIL_P(rng))
29
+ return rb_genrand_real();
30
+ else
31
+ return rb_random_real(rng);
32
+ }
33
+
34
+ static inline unsigned long
35
+ ca_random_ulong_limited(VALUE rng, unsigned long limit)
36
+ {
37
+ if (NIL_P(rng))
38
+ return rb_genrand_ulong_limited(limit);
39
+ else
40
+ return rb_random_ulong_limited(rng, limit);
41
+ }
42
+
43
+ /* ---- random! ----------------------------------------------------------- */
44
+
45
+ /* CArray#random!([low,] [high], rng:) — fill self with uniform random
46
+ * numbers in-place, returning self. Range surface mirrors Numo/NumPy
47
+ * (half-open [low, high) as the default) plus Ruby idiom (`..` closed,
48
+ * `...` half-open):
49
+ *
50
+ * random! float [0.0, 1.0); integer -> ArgumentError
51
+ * random!(high) [0, high) (Ruby rand shorthand)
52
+ * random!(low, high) [low, high) (Numo positional)
53
+ * random!(a..b) [a, b] closed (integer: b included)
54
+ * random!(a...b) [a, b) half-open
55
+ * random!(..., rng: r) any of the above with a custom Random source
56
+ *
57
+ * For float, `..` and `...` return the same distribution (endpoint
58
+ * probability ~2^-53); the closed form is honored syntactically but not
59
+ * enforced at the mantissa level, matching NumPy/SciPy convention.
60
+ * Boolean fills 0/1 with 50% probability each and ignores the range
61
+ * argument. Rejects CA_OBJECT / CA_FIXLEN. */
62
+ static VALUE
63
+ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
64
+ {
65
+ CArray *ca;
66
+ VALUE arg1 = Qnil, arg2 = Qnil, opts = Qnil;
67
+ VALUE low_val = Qnil, high_val = Qnil;
68
+ int is_default = 1;
69
+ int high_is_closed = 0;
70
+ double low_dbl = 0.0, high_dbl = 0.0;
71
+ long low_long = 0, high_long = 0;
72
+ unsigned long limit = 0;
73
+ ca_size_t i, n;
74
+ VALUE rng = Qnil;
75
+
76
+ rb_scan_args(argc, argv, "02:", &arg1, &arg2, &opts);
77
+ rb_scan_options(opts, "rng", &rng);
78
+
79
+ /* Parse positional args into (low_val, high_val) + high_is_closed. */
80
+ if (rb_obj_is_kind_of(arg1, rb_cRange)) {
81
+ if (!NIL_P(arg2)) {
82
+ rb_raise(rb_eArgError,
83
+ "random: cannot combine a Range with a second positional arg");
84
+ }
85
+ low_val = rb_funcall(arg1, rb_intern("begin"), 0);
86
+ high_val = rb_funcall(arg1, rb_intern("end"), 0);
87
+ if (NIL_P(low_val) || NIL_P(high_val)) {
88
+ rb_raise(rb_eArgError,
89
+ "random: Range must have finite begin and end");
90
+ }
91
+ high_is_closed = ! RTEST(rb_funcall(arg1, rb_intern("exclude_end?"), 0));
92
+ is_default = 0;
93
+ } else if (!NIL_P(arg1) && !NIL_P(arg2)) {
94
+ low_val = arg1;
95
+ high_val = arg2;
96
+ is_default = 0;
97
+ } else if (!NIL_P(arg1)) {
98
+ low_val = INT2FIX(0);
99
+ high_val = arg1;
100
+ is_default = 0;
101
+ }
102
+
103
+ rb_ca_modify(self);
104
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
105
+
106
+ if (ca->data_type == CA_OBJECT || ca->data_type == CA_FIXLEN) {
107
+ rb_raise(rb_eCADataTypeError,
108
+ "random! is not supported for object/fixlen arrays");
109
+ }
110
+
111
+ /* Materialize (low, high) as the correct scalar type and validate.
112
+ * For integer dtypes, `..` closed adds 1 to high (turns into half-open
113
+ * for the sampler); for float dtypes, closed and half-open are
114
+ * equivalent so no adjustment. */
115
+ if (!is_default) {
116
+ int is_integer_dtype = (ca->data_type >= CA_INT8
117
+ && ca->data_type <= CA_UINT64);
118
+ if (is_integer_dtype) {
119
+ low_long = NUM2LONG(low_val);
120
+ high_long = NUM2LONG(high_val);
121
+ if (high_is_closed) high_long += 1;
122
+ if (low_long >= high_long) {
123
+ rb_raise(rb_eArgError,
124
+ "random: low must be less than high "
125
+ "(got low=%ld, high=%ld)",
126
+ low_long, high_long);
127
+ }
128
+ limit = (unsigned long)(high_long - low_long) - 1;
129
+ } else {
130
+ low_dbl = NUM2DBL(low_val);
131
+ high_dbl = NUM2DBL(high_val);
132
+ if (low_dbl >= high_dbl) {
133
+ rb_raise(rb_eArgError,
134
+ "random: low must be less than high "
135
+ "(got low=%g, high=%g)",
136
+ low_dbl, high_dbl);
137
+ }
138
+ }
139
+ }
140
+
141
+ n = ca->elements;
142
+ ca_attach(ca);
143
+
144
+ switch (ca->data_type) {
145
+ case CA_FLOAT64: {
146
+ double *p = (double *)ca->ptr;
147
+ if (is_default) {
148
+ for (i = 0; i < n; i++)
149
+ p[i] = ca_random_real(rng);
150
+ } else {
151
+ double range = high_dbl - low_dbl;
152
+ for (i = 0; i < n; i++)
153
+ p[i] = low_dbl + ca_random_real(rng) * range;
154
+ }
155
+ break;
156
+ }
157
+ case CA_FLOAT32: {
158
+ float *p = (float *)ca->ptr;
159
+ if (is_default) {
160
+ for (i = 0; i < n; i++)
161
+ p[i] = (float)ca_random_real(rng);
162
+ } else {
163
+ double range = high_dbl - low_dbl;
164
+ for (i = 0; i < n; i++)
165
+ p[i] = (float)(low_dbl + ca_random_real(rng) * range);
166
+ }
167
+ break;
168
+ }
169
+ case CA_CMPLX128: {
170
+ double complex *p = (double complex *)ca->ptr;
171
+ if (is_default) {
172
+ for (i = 0; i < n; i++)
173
+ p[i] = ca_random_real(rng) + ca_random_real(rng) * I;
174
+ } else {
175
+ double range = high_dbl - low_dbl;
176
+ for (i = 0; i < n; i++)
177
+ p[i] = (low_dbl + ca_random_real(rng) * range)
178
+ + (low_dbl + ca_random_real(rng) * range) * I;
179
+ }
180
+ break;
181
+ }
182
+ case CA_CMPLX64: {
183
+ float complex *p = (float complex *)ca->ptr;
184
+ if (is_default) {
185
+ for (i = 0; i < n; i++)
186
+ p[i] = (float)ca_random_real(rng) + (float)ca_random_real(rng) * I;
187
+ } else {
188
+ double range = high_dbl - low_dbl;
189
+ for (i = 0; i < n; i++)
190
+ p[i] = (float)(low_dbl + ca_random_real(rng) * range)
191
+ + (float)(low_dbl + ca_random_real(rng) * range) * I;
192
+ }
193
+ break;
194
+ }
195
+ case CA_BOOLEAN: {
196
+ boolean8_t *p = (boolean8_t *)ca->ptr;
197
+ for (i = 0; i < n; i++)
198
+ p[i] = (ca_random_real(rng) < 0.5) ? 1 : 0;
199
+ break;
200
+ }
201
+ default: {
202
+ /* integer types: CA_INT8..CA_UINT64 */
203
+ if (is_default) {
204
+ ca_sync(ca);
205
+ ca_detach(ca);
206
+ rb_raise(rb_eArgError,
207
+ "random! on an integer array requires a range: "
208
+ "a.random!(high), a.random!(low, high), or "
209
+ "a.random!(low..high) / a.random!(low...high)");
210
+ }
211
+ switch (ca->data_type) {
212
+ case CA_INT8: {
213
+ int8_t *p = (int8_t *)ca->ptr;
214
+ for (i = 0; i < n; i++)
215
+ p[i] = (int8_t)(low_long + ca_random_ulong_limited(rng, limit));
216
+ break;
217
+ }
218
+ case CA_UINT8: {
219
+ uint8_t *p = (uint8_t *)ca->ptr;
220
+ for (i = 0; i < n; i++)
221
+ p[i] = (uint8_t)(low_long + ca_random_ulong_limited(rng, limit));
222
+ break;
223
+ }
224
+ case CA_INT16: {
225
+ int16_t *p = (int16_t *)ca->ptr;
226
+ for (i = 0; i < n; i++)
227
+ p[i] = (int16_t)(low_long + ca_random_ulong_limited(rng, limit));
228
+ break;
229
+ }
230
+ case CA_UINT16: {
231
+ uint16_t *p = (uint16_t *)ca->ptr;
232
+ for (i = 0; i < n; i++)
233
+ p[i] = (uint16_t)(low_long + ca_random_ulong_limited(rng, limit));
234
+ break;
235
+ }
236
+ case CA_INT32: {
237
+ int32_t *p = (int32_t *)ca->ptr;
238
+ for (i = 0; i < n; i++)
239
+ p[i] = (int32_t)(low_long + ca_random_ulong_limited(rng, limit));
240
+ break;
241
+ }
242
+ case CA_UINT32: {
243
+ uint32_t *p = (uint32_t *)ca->ptr;
244
+ for (i = 0; i < n; i++)
245
+ p[i] = (uint32_t)(low_long + ca_random_ulong_limited(rng, limit));
246
+ break;
247
+ }
248
+ case CA_INT64: {
249
+ int64_t *p = (int64_t *)ca->ptr;
250
+ for (i = 0; i < n; i++)
251
+ p[i] = (int64_t)(low_long + ca_random_ulong_limited(rng, limit));
252
+ break;
253
+ }
254
+ case CA_UINT64: {
255
+ uint64_t *p = (uint64_t *)ca->ptr;
256
+ for (i = 0; i < n; i++)
257
+ p[i] = (uint64_t)(low_long + ca_random_ulong_limited(rng, limit));
258
+ break;
259
+ }
260
+ default:
261
+ ca_sync(ca);
262
+ ca_detach(ca);
263
+ rb_raise(rb_eCADataTypeError,
264
+ "random! is not supported for this data type");
265
+ }
266
+ break;
267
+ }
268
+ }
269
+
270
+ ca_sync(ca);
271
+ ca_detach(ca);
272
+ return self;
273
+ }
274
+
275
+ /* ---- randomn! ---------------------------------------------------------- */
276
+
277
+ static inline void
278
+ box_muller_pair(VALUE rng, double *r1, double *r2)
279
+ {
280
+ double u1 = ca_random_real(rng);
281
+ double u2 = ca_random_real(rng);
282
+ while (u1 == 0.0)
283
+ u1 = ca_random_real(rng);
284
+ double r = sqrt(-2.0 * log(u1));
285
+ double theta = 2.0 * M_PI * u2;
286
+ *r1 = r * cos(theta);
287
+ *r2 = r * sin(theta);
288
+ }
289
+
290
+ /* CArray#randomn!(rng:) — fill self with standard normal N(0, 1)
291
+ * samples in-place via Box-Muller, returning self.
292
+ *
293
+ * Restricted to float / complex dtypes. Complex fills real + imag as
294
+ * two independent normals per cell. */
295
+ static VALUE
296
+ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
297
+ {
298
+ CArray *ca;
299
+ VALUE opts = Qnil;
300
+ ca_size_t i, n;
301
+
302
+ rb_scan_args(argc, argv, "0:", &opts);
303
+ VALUE rng = Qnil;
304
+ rb_scan_options(opts, "rng", &rng);
305
+
306
+ rb_ca_modify(self);
307
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
308
+
309
+ if (ca->data_type != CA_FLOAT64 && ca->data_type != CA_FLOAT32 &&
310
+ ca->data_type != CA_CMPLX128 && ca->data_type != CA_CMPLX64) {
311
+ rb_raise(rb_eCADataTypeError,
312
+ "randomn! requires float or complex array");
313
+ }
314
+
315
+ n = ca->elements;
316
+ ca_attach(ca);
317
+
318
+ switch (ca->data_type) {
319
+ case CA_FLOAT64: {
320
+ double *p = (double *)ca->ptr;
321
+ ca_size_t pairs = n / 2;
322
+ for (i = 0; i < pairs; i++) {
323
+ box_muller_pair(rng, &p[2*i], &p[2*i+1]);
324
+ }
325
+ if (n % 2 == 1) {
326
+ double r1, r2;
327
+ box_muller_pair(rng, &r1, &r2);
328
+ p[n-1] = r1;
329
+ }
330
+ break;
331
+ }
332
+ case CA_FLOAT32: {
333
+ float *p = (float *)ca->ptr;
334
+ ca_size_t pairs = n / 2;
335
+ for (i = 0; i < pairs; i++) {
336
+ double r1, r2;
337
+ box_muller_pair(rng, &r1, &r2);
338
+ p[2*i] = (float)r1;
339
+ p[2*i+1] = (float)r2;
340
+ }
341
+ if (n % 2 == 1) {
342
+ double r1, r2;
343
+ box_muller_pair(rng, &r1, &r2);
344
+ p[n-1] = (float)r1;
345
+ }
346
+ break;
347
+ }
348
+ case CA_CMPLX128: {
349
+ double complex *p = (double complex *)ca->ptr;
350
+ for (i = 0; i < n; i++) {
351
+ double r1, r2;
352
+ box_muller_pair(rng, &r1, &r2);
353
+ p[i] = r1 + r2 * I;
354
+ }
355
+ break;
356
+ }
357
+ case CA_CMPLX64: {
358
+ float complex *p = (float complex *)ca->ptr;
359
+ for (i = 0; i < n; i++) {
360
+ double r1, r2;
361
+ box_muller_pair(rng, &r1, &r2);
362
+ p[i] = (float)r1 + (float)r2 * I;
363
+ }
364
+ break;
365
+ }
366
+ default:
367
+ break;
368
+ }
369
+
370
+ ca_sync(ca);
371
+ ca_detach(ca);
372
+ return self;
373
+ }
374
+
375
+ /* ---- shuffle! ---------------------------------------------------------- */
376
+
377
+ static void
378
+ swap_chunks(char *a, char *b, ca_size_t chunk_bytes, char *tmp)
379
+ {
380
+ memcpy(tmp, a, chunk_bytes);
381
+ memcpy(a, b, chunk_bytes);
382
+ memcpy(b, tmp, chunk_bytes);
383
+ }
384
+
385
+ /* CArray#shuffle!(axis:, rng:) — Fisher-Yates permute self in-place,
386
+ * returning self.
387
+ *
388
+ * Without axis:, shuffles all cells as if flattened. With axis:,
389
+ * permutes slices along that axis (the trailing sub-slab is treated
390
+ * as a byte chunk and swapped whole, so multi-dim slices move
391
+ * together). */
392
+ static VALUE
393
+ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
394
+ {
395
+ CArray *ca;
396
+ VALUE opts = Qnil, v_axis = Qnil;
397
+ ca_size_t n;
398
+ int axis = -1;
399
+
400
+ rb_scan_args(argc, argv, "0:", &opts);
401
+ VALUE rng = Qnil;
402
+ rb_scan_options(opts, "rng,axis", &rng, &v_axis);
403
+
404
+ rb_ca_modify(self);
405
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
406
+
407
+ if (ca->elements <= 1) return self;
408
+
409
+ ca_attach(ca);
410
+
411
+ if (NIL_P(v_axis)) {
412
+ /* shuffle all elements */
413
+ n = ca->elements;
414
+ ca_size_t elem_bytes = ca->bytes;
415
+ char *tmp = (char *)xmalloc(elem_bytes);
416
+ char *p = ca->ptr;
417
+
418
+ for (ca_size_t i = n - 1; i > 0; i--) {
419
+ unsigned long j = ca_random_ulong_limited(rng, (unsigned long)i);
420
+ if ((ca_size_t)j != i) {
421
+ swap_chunks(p + i * elem_bytes, p + j * elem_bytes, elem_bytes, tmp);
422
+ }
423
+ }
424
+ xfree(tmp);
425
+ }
426
+ else {
427
+ axis = NUM2INT(v_axis);
428
+ if (axis < 0) axis += ca->ndim;
429
+ if (axis < 0 || axis >= ca->ndim) {
430
+ ca_sync(ca);
431
+ ca_detach(ca);
432
+ rb_raise(rb_eArgError,
433
+ "axis %d is out of range for ndim %d", axis, ca->ndim);
434
+ }
435
+
436
+ n = ca->dim[axis];
437
+ if (n <= 1) {
438
+ ca_sync(ca);
439
+ ca_detach(ca);
440
+ return self;
441
+ }
442
+
443
+ ca_size_t outer = 1;
444
+ for (int d = 0; d < axis; d++)
445
+ outer *= ca->dim[d];
446
+
447
+ ca_size_t inner = 1;
448
+ for (int d = axis + 1; d < ca->ndim; d++)
449
+ inner *= ca->dim[d];
450
+
451
+ ca_size_t chunk_bytes = inner * ca->bytes;
452
+ ca_size_t stride = n * chunk_bytes;
453
+ char *tmp = (char *)xmalloc(chunk_bytes);
454
+
455
+ for (ca_size_t o = 0; o < outer; o++) {
456
+ char *base = ca->ptr + o * stride;
457
+ for (ca_size_t i = n - 1; i > 0; i--) {
458
+ unsigned long j = ca_random_ulong_limited(rng, (unsigned long)i);
459
+ if ((ca_size_t)j != i) {
460
+ swap_chunks(base + i * chunk_bytes,
461
+ base + j * chunk_bytes,
462
+ chunk_bytes, tmp);
463
+ }
464
+ }
465
+ }
466
+ xfree(tmp);
467
+ }
468
+
469
+ ca_sync(ca);
470
+ ca_detach(ca);
471
+ return self;
472
+ }
473
+
474
+ /* ---- shuffle (copy) ---------------------------------------------------- */
475
+
476
+ /* CArray#shuffle(axis:, rng:) — non-bang variant: shuffle a copy of self. */
477
+ static VALUE
478
+ rb_ca_shuffle(int argc, VALUE *argv, VALUE self)
479
+ {
480
+ volatile VALUE copy = rb_funcall(self, rb_intern("copy"), 0);
481
+ return rb_ca_shuffle_bang(argc, argv, copy);
482
+ }
483
+
484
+ /* ---- random (copy) ----------------------------------------------------- */
485
+
486
+ /* CArray#random([low,] [high], rng:) — non-bang variant: return a
487
+ * newly templated array filled uniformly. Shape and dtype come from
488
+ * CArray#template, so the receiver is only consulted for those.
489
+ * Accepts the same argument forms as {rb_ca_random_bang}. */
490
+ static VALUE
491
+ rb_ca_random(int argc, VALUE *argv, VALUE self)
492
+ {
493
+ volatile VALUE copy = rb_funcall(self, rb_intern("template"), 0);
494
+ return rb_ca_random_bang(argc, argv, copy);
495
+ }
496
+
497
+ /* CArray#randomn(rng:) — non-bang variant: return a newly templated
498
+ * array filled with standard normal samples. */
499
+ static VALUE
500
+ rb_ca_randomn(int argc, VALUE *argv, VALUE self)
501
+ {
502
+ volatile VALUE copy = rb_funcall(self, rb_intern("template"), 0);
503
+ return rb_ca_randomn_bang(argc, argv, copy);
504
+ }
505
+
506
+ /* ---- Init -------------------------------------------------------------- */
507
+
508
+ void
509
+ Init_carray_random (void)
510
+ {
511
+ rb_define_method(rb_cCArray, "random!", rb_ca_random_bang, -1);
512
+ rb_define_method(rb_cCArray, "randomn!", rb_ca_randomn_bang, -1);
513
+ rb_define_method(rb_cCArray, "shuffle!", rb_ca_shuffle_bang, -1);
514
+
515
+ rb_define_method(rb_cCArray, "random", rb_ca_random, -1);
516
+ rb_define_method(rb_cCArray, "randomn", rb_ca_randomn, -1);
517
+ rb_define_method(rb_cCArray, "shuffle", rb_ca_shuffle, -1);
518
+ }