numkong 7.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.
- package/LICENSE +201 -0
- package/README.md +495 -0
- package/binding.gyp +540 -0
- package/c/dispatch.h +512 -0
- package/c/dispatch_bf16.c +389 -0
- package/c/dispatch_bf16c.c +52 -0
- package/c/dispatch_e2m3.c +263 -0
- package/c/dispatch_e3m2.c +243 -0
- package/c/dispatch_e4m3.c +276 -0
- package/c/dispatch_e5m2.c +272 -0
- package/c/dispatch_f16.c +376 -0
- package/c/dispatch_f16c.c +58 -0
- package/c/dispatch_f32.c +378 -0
- package/c/dispatch_f32c.c +99 -0
- package/c/dispatch_f64.c +296 -0
- package/c/dispatch_f64c.c +98 -0
- package/c/dispatch_i16.c +96 -0
- package/c/dispatch_i32.c +89 -0
- package/c/dispatch_i4.c +150 -0
- package/c/dispatch_i64.c +86 -0
- package/c/dispatch_i8.c +289 -0
- package/c/dispatch_other.c +330 -0
- package/c/dispatch_u1.c +148 -0
- package/c/dispatch_u16.c +124 -0
- package/c/dispatch_u32.c +118 -0
- package/c/dispatch_u4.c +150 -0
- package/c/dispatch_u64.c +102 -0
- package/c/dispatch_u8.c +303 -0
- package/c/numkong.c +950 -0
- package/include/README.md +573 -0
- package/include/module.modulemap +129 -0
- package/include/numkong/attention/sapphireamx.h +1361 -0
- package/include/numkong/attention/sme.h +2066 -0
- package/include/numkong/attention.h +49 -0
- package/include/numkong/capabilities.h +748 -0
- package/include/numkong/cast/README.md +262 -0
- package/include/numkong/cast/haswell.h +975 -0
- package/include/numkong/cast/icelake.h +470 -0
- package/include/numkong/cast/neon.h +1192 -0
- package/include/numkong/cast/rvv.h +1021 -0
- package/include/numkong/cast/sapphire.h +262 -0
- package/include/numkong/cast/serial.h +2262 -0
- package/include/numkong/cast/skylake.h +856 -0
- package/include/numkong/cast/v128relaxed.h +180 -0
- package/include/numkong/cast.h +230 -0
- package/include/numkong/curved/README.md +223 -0
- package/include/numkong/curved/genoa.h +182 -0
- package/include/numkong/curved/haswell.h +276 -0
- package/include/numkong/curved/neon.h +205 -0
- package/include/numkong/curved/neonbfdot.h +212 -0
- package/include/numkong/curved/neonhalf.h +212 -0
- package/include/numkong/curved/rvv.h +305 -0
- package/include/numkong/curved/serial.h +207 -0
- package/include/numkong/curved/skylake.h +457 -0
- package/include/numkong/curved/smef64.h +506 -0
- package/include/numkong/curved.h +517 -0
- package/include/numkong/curved.hpp +144 -0
- package/include/numkong/dot/README.md +425 -0
- package/include/numkong/dot/alder.h +563 -0
- package/include/numkong/dot/genoa.h +315 -0
- package/include/numkong/dot/haswell.h +1688 -0
- package/include/numkong/dot/icelake.h +883 -0
- package/include/numkong/dot/neon.h +818 -0
- package/include/numkong/dot/neonbfdot.h +244 -0
- package/include/numkong/dot/neonfhm.h +360 -0
- package/include/numkong/dot/neonhalf.h +198 -0
- package/include/numkong/dot/neonsdot.h +508 -0
- package/include/numkong/dot/rvv.h +714 -0
- package/include/numkong/dot/rvvbb.h +72 -0
- package/include/numkong/dot/rvvbf16.h +123 -0
- package/include/numkong/dot/rvvhalf.h +129 -0
- package/include/numkong/dot/sapphire.h +141 -0
- package/include/numkong/dot/serial.h +838 -0
- package/include/numkong/dot/sierra.h +405 -0
- package/include/numkong/dot/skylake.h +1084 -0
- package/include/numkong/dot/sve.h +379 -0
- package/include/numkong/dot/svebfdot.h +74 -0
- package/include/numkong/dot/svehalf.h +123 -0
- package/include/numkong/dot/v128relaxed.h +1258 -0
- package/include/numkong/dot.h +1070 -0
- package/include/numkong/dot.hpp +94 -0
- package/include/numkong/dots/README.md +496 -0
- package/include/numkong/dots/alder.h +114 -0
- package/include/numkong/dots/genoa.h +94 -0
- package/include/numkong/dots/haswell.h +295 -0
- package/include/numkong/dots/icelake.h +171 -0
- package/include/numkong/dots/neon.h +120 -0
- package/include/numkong/dots/neonbfdot.h +58 -0
- package/include/numkong/dots/neonfhm.h +94 -0
- package/include/numkong/dots/neonhalf.h +57 -0
- package/include/numkong/dots/neonsdot.h +108 -0
- package/include/numkong/dots/rvv.h +2486 -0
- package/include/numkong/dots/sapphireamx.h +3973 -0
- package/include/numkong/dots/serial.h +2844 -0
- package/include/numkong/dots/sierra.h +97 -0
- package/include/numkong/dots/skylake.h +196 -0
- package/include/numkong/dots/sme.h +5372 -0
- package/include/numkong/dots/smebi32.h +461 -0
- package/include/numkong/dots/smef64.h +1318 -0
- package/include/numkong/dots/smehalf.h +47 -0
- package/include/numkong/dots/v128relaxed.h +294 -0
- package/include/numkong/dots.h +2804 -0
- package/include/numkong/dots.hpp +639 -0
- package/include/numkong/each/README.md +469 -0
- package/include/numkong/each/haswell.h +1658 -0
- package/include/numkong/each/icelake.h +272 -0
- package/include/numkong/each/neon.h +1104 -0
- package/include/numkong/each/neonbfdot.h +212 -0
- package/include/numkong/each/neonhalf.h +410 -0
- package/include/numkong/each/rvv.h +1121 -0
- package/include/numkong/each/sapphire.h +477 -0
- package/include/numkong/each/serial.h +260 -0
- package/include/numkong/each/skylake.h +1562 -0
- package/include/numkong/each.h +2146 -0
- package/include/numkong/each.hpp +434 -0
- package/include/numkong/geospatial/README.md +147 -0
- package/include/numkong/geospatial/haswell.h +593 -0
- package/include/numkong/geospatial/neon.h +571 -0
- package/include/numkong/geospatial/rvv.h +701 -0
- package/include/numkong/geospatial/serial.h +309 -0
- package/include/numkong/geospatial/skylake.h +577 -0
- package/include/numkong/geospatial/v128relaxed.h +613 -0
- package/include/numkong/geospatial.h +453 -0
- package/include/numkong/geospatial.hpp +235 -0
- package/include/numkong/matrix.hpp +336 -0
- package/include/numkong/maxsim/README.md +187 -0
- package/include/numkong/maxsim/alder.h +511 -0
- package/include/numkong/maxsim/genoa.h +115 -0
- package/include/numkong/maxsim/haswell.h +553 -0
- package/include/numkong/maxsim/icelake.h +480 -0
- package/include/numkong/maxsim/neonsdot.h +394 -0
- package/include/numkong/maxsim/sapphireamx.h +877 -0
- package/include/numkong/maxsim/serial.h +490 -0
- package/include/numkong/maxsim/sme.h +929 -0
- package/include/numkong/maxsim/v128relaxed.h +280 -0
- package/include/numkong/maxsim.h +571 -0
- package/include/numkong/maxsim.hpp +133 -0
- package/include/numkong/mesh/README.md +227 -0
- package/include/numkong/mesh/haswell.h +2235 -0
- package/include/numkong/mesh/neon.h +1329 -0
- package/include/numkong/mesh/neonbfdot.h +842 -0
- package/include/numkong/mesh/neonhalf.h +616 -0
- package/include/numkong/mesh/rvv.h +916 -0
- package/include/numkong/mesh/serial.h +742 -0
- package/include/numkong/mesh/skylake.h +1135 -0
- package/include/numkong/mesh/v128relaxed.h +1052 -0
- package/include/numkong/mesh.h +652 -0
- package/include/numkong/mesh.hpp +762 -0
- package/include/numkong/numkong.h +78 -0
- package/include/numkong/numkong.hpp +57 -0
- package/include/numkong/probability/README.md +173 -0
- package/include/numkong/probability/haswell.h +267 -0
- package/include/numkong/probability/neon.h +225 -0
- package/include/numkong/probability/rvv.h +409 -0
- package/include/numkong/probability/serial.h +169 -0
- package/include/numkong/probability/skylake.h +324 -0
- package/include/numkong/probability.h +383 -0
- package/include/numkong/probability.hpp +120 -0
- package/include/numkong/random.h +50 -0
- package/include/numkong/random.hpp +285 -0
- package/include/numkong/reduce/README.md +547 -0
- package/include/numkong/reduce/alder.h +632 -0
- package/include/numkong/reduce/genoa.h +201 -0
- package/include/numkong/reduce/haswell.h +3783 -0
- package/include/numkong/reduce/icelake.h +549 -0
- package/include/numkong/reduce/neon.h +3841 -0
- package/include/numkong/reduce/neonbfdot.h +353 -0
- package/include/numkong/reduce/neonfhm.h +665 -0
- package/include/numkong/reduce/neonhalf.h +157 -0
- package/include/numkong/reduce/neonsdot.h +357 -0
- package/include/numkong/reduce/rvv.h +3407 -0
- package/include/numkong/reduce/serial.h +757 -0
- package/include/numkong/reduce/sierra.h +338 -0
- package/include/numkong/reduce/skylake.h +3792 -0
- package/include/numkong/reduce/v128relaxed.h +2302 -0
- package/include/numkong/reduce.h +1597 -0
- package/include/numkong/reduce.hpp +633 -0
- package/include/numkong/scalar/README.md +89 -0
- package/include/numkong/scalar/haswell.h +113 -0
- package/include/numkong/scalar/neon.h +122 -0
- package/include/numkong/scalar/neonhalf.h +70 -0
- package/include/numkong/scalar/rvv.h +211 -0
- package/include/numkong/scalar/sapphire.h +63 -0
- package/include/numkong/scalar/serial.h +332 -0
- package/include/numkong/scalar/v128relaxed.h +56 -0
- package/include/numkong/scalar.h +683 -0
- package/include/numkong/set/README.md +179 -0
- package/include/numkong/set/haswell.h +334 -0
- package/include/numkong/set/icelake.h +485 -0
- package/include/numkong/set/neon.h +364 -0
- package/include/numkong/set/rvv.h +226 -0
- package/include/numkong/set/rvvbb.h +117 -0
- package/include/numkong/set/serial.h +174 -0
- package/include/numkong/set/sve.h +185 -0
- package/include/numkong/set/v128relaxed.h +240 -0
- package/include/numkong/set.h +457 -0
- package/include/numkong/set.hpp +114 -0
- package/include/numkong/sets/README.md +149 -0
- package/include/numkong/sets/haswell.h +63 -0
- package/include/numkong/sets/icelake.h +66 -0
- package/include/numkong/sets/neon.h +61 -0
- package/include/numkong/sets/serial.h +43 -0
- package/include/numkong/sets/smebi32.h +1099 -0
- package/include/numkong/sets/v128relaxed.h +58 -0
- package/include/numkong/sets.h +339 -0
- package/include/numkong/sparse/README.md +156 -0
- package/include/numkong/sparse/icelake.h +463 -0
- package/include/numkong/sparse/neon.h +288 -0
- package/include/numkong/sparse/serial.h +117 -0
- package/include/numkong/sparse/sve2.h +507 -0
- package/include/numkong/sparse/turin.h +322 -0
- package/include/numkong/sparse.h +363 -0
- package/include/numkong/sparse.hpp +113 -0
- package/include/numkong/spatial/README.md +435 -0
- package/include/numkong/spatial/alder.h +607 -0
- package/include/numkong/spatial/genoa.h +290 -0
- package/include/numkong/spatial/haswell.h +960 -0
- package/include/numkong/spatial/icelake.h +586 -0
- package/include/numkong/spatial/neon.h +773 -0
- package/include/numkong/spatial/neonbfdot.h +165 -0
- package/include/numkong/spatial/neonhalf.h +118 -0
- package/include/numkong/spatial/neonsdot.h +261 -0
- package/include/numkong/spatial/rvv.h +984 -0
- package/include/numkong/spatial/rvvbf16.h +123 -0
- package/include/numkong/spatial/rvvhalf.h +117 -0
- package/include/numkong/spatial/sapphire.h +343 -0
- package/include/numkong/spatial/serial.h +346 -0
- package/include/numkong/spatial/sierra.h +323 -0
- package/include/numkong/spatial/skylake.h +606 -0
- package/include/numkong/spatial/sve.h +224 -0
- package/include/numkong/spatial/svebfdot.h +122 -0
- package/include/numkong/spatial/svehalf.h +109 -0
- package/include/numkong/spatial/v128relaxed.h +717 -0
- package/include/numkong/spatial.h +1425 -0
- package/include/numkong/spatial.hpp +183 -0
- package/include/numkong/spatials/README.md +580 -0
- package/include/numkong/spatials/alder.h +94 -0
- package/include/numkong/spatials/genoa.h +94 -0
- package/include/numkong/spatials/haswell.h +219 -0
- package/include/numkong/spatials/icelake.h +113 -0
- package/include/numkong/spatials/neon.h +109 -0
- package/include/numkong/spatials/neonbfdot.h +60 -0
- package/include/numkong/spatials/neonfhm.h +92 -0
- package/include/numkong/spatials/neonhalf.h +58 -0
- package/include/numkong/spatials/neonsdot.h +109 -0
- package/include/numkong/spatials/rvv.h +1960 -0
- package/include/numkong/spatials/sapphireamx.h +1149 -0
- package/include/numkong/spatials/serial.h +226 -0
- package/include/numkong/spatials/sierra.h +96 -0
- package/include/numkong/spatials/skylake.h +184 -0
- package/include/numkong/spatials/sme.h +1901 -0
- package/include/numkong/spatials/smef64.h +465 -0
- package/include/numkong/spatials/v128relaxed.h +240 -0
- package/include/numkong/spatials.h +3021 -0
- package/include/numkong/spatials.hpp +508 -0
- package/include/numkong/tensor.hpp +1592 -0
- package/include/numkong/trigonometry/README.md +184 -0
- package/include/numkong/trigonometry/haswell.h +652 -0
- package/include/numkong/trigonometry/neon.h +639 -0
- package/include/numkong/trigonometry/rvv.h +699 -0
- package/include/numkong/trigonometry/serial.h +703 -0
- package/include/numkong/trigonometry/skylake.h +721 -0
- package/include/numkong/trigonometry/v128relaxed.h +666 -0
- package/include/numkong/trigonometry.h +467 -0
- package/include/numkong/trigonometry.hpp +166 -0
- package/include/numkong/types.h +1384 -0
- package/include/numkong/types.hpp +5603 -0
- package/include/numkong/vector.hpp +698 -0
- package/javascript/README.md +246 -0
- package/javascript/dist/cjs/numkong-wasm.d.ts +166 -0
- package/javascript/dist/cjs/numkong-wasm.js +617 -0
- package/javascript/dist/cjs/numkong.d.ts +343 -0
- package/javascript/dist/cjs/numkong.js +523 -0
- package/javascript/dist/cjs/package.json +3 -0
- package/javascript/dist/cjs/types.d.ts +284 -0
- package/javascript/dist/cjs/types.js +653 -0
- package/javascript/dist/esm/numkong-wasm.d.ts +166 -0
- package/javascript/dist/esm/numkong-wasm.js +595 -0
- package/javascript/dist/esm/numkong.d.ts +343 -0
- package/javascript/dist/esm/numkong.js +452 -0
- package/javascript/dist/esm/package.json +3 -0
- package/javascript/dist/esm/types.d.ts +284 -0
- package/javascript/dist/esm/types.js +630 -0
- package/javascript/dist-package-cjs.json +3 -0
- package/javascript/dist-package-esm.json +3 -0
- package/javascript/node-gyp-build.d.ts +1 -0
- package/javascript/numkong-wasm.ts +756 -0
- package/javascript/numkong.c +689 -0
- package/javascript/numkong.ts +575 -0
- package/javascript/tsconfig-base.json +39 -0
- package/javascript/tsconfig-cjs.json +8 -0
- package/javascript/tsconfig-esm.json +8 -0
- package/javascript/types.ts +674 -0
- package/package.json +87 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief Random number generation utilities for NumKong types.
|
|
3
|
+
* @file include/numkong/random.hpp
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date February 5, 2026
|
|
6
|
+
*
|
|
7
|
+
* Lightweight header with random fill functions for testing and benchmarking.
|
|
8
|
+
* Only depends on types.hpp to minimize compilation overhead.
|
|
9
|
+
*/
|
|
10
|
+
#ifndef NK_RANDOM_HPP
|
|
11
|
+
#define NK_RANDOM_HPP
|
|
12
|
+
|
|
13
|
+
#include <algorithm> // `std::sort`
|
|
14
|
+
#include <random> // `std::uniform_int_distribution`
|
|
15
|
+
|
|
16
|
+
#include "numkong/types.hpp"
|
|
17
|
+
|
|
18
|
+
namespace ashvardanian::numkong {
|
|
19
|
+
|
|
20
|
+
/** @brief Lightweight clamp to avoid pulling in `<algorithm>` for `std::clamp`. */
|
|
21
|
+
template <typename scalar_type_>
|
|
22
|
+
scalar_type_ clamp(scalar_type_ val, scalar_type_ low, scalar_type_ high) noexcept {
|
|
23
|
+
return val < low ? low : val > high ? high : val;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @brief Fill array with uniform random values.
|
|
28
|
+
*
|
|
29
|
+
* @tparam value_type_ A NumKong wrapper type (e.g., f32_t, f64_t, i32_t).
|
|
30
|
+
* @tparam generator_type_ A random number generator type (e.g., std::mt19937_64).
|
|
31
|
+
* @param generator The random number generator.
|
|
32
|
+
* @param values_ptr Pointer to the array to fill.
|
|
33
|
+
* @param values_count Number of storage values to fill (not dimensions for sub-byte types).
|
|
34
|
+
*/
|
|
35
|
+
template <typename value_type_, typename generator_type_, typename component_type_ = typename value_type_::component_t>
|
|
36
|
+
void fill_uniform(generator_type_ &generator, value_type_ *values_ptr, std::size_t values_count,
|
|
37
|
+
component_type_ min_val, component_type_ max_val) noexcept {
|
|
38
|
+
|
|
39
|
+
// Packed types (u1x8, u4x2, i4x2) need special handling - just fill with random bytes
|
|
40
|
+
if constexpr (dimensions_per_value<value_type_>() > 1) {
|
|
41
|
+
std::uniform_int_distribution<std::int32_t> distribution(min_val, max_val);
|
|
42
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
43
|
+
for (std::size_t j = 0; j < dimensions_per_value<value_type_>(); ++j)
|
|
44
|
+
values_ptr[i][j] = static_cast<component_type_>(distribution(generator));
|
|
45
|
+
}
|
|
46
|
+
// Integer distribution types aren't always defined
|
|
47
|
+
else if constexpr (is_integral_dtype<value_type_>()) {
|
|
48
|
+
using small_integer_t = std::conditional_t<is_signed_dtype<value_type_>(), std::int32_t, std::uint32_t>;
|
|
49
|
+
using large_integer_t = std::conditional_t<is_signed_dtype<value_type_>(), std::int64_t, std::uint64_t>;
|
|
50
|
+
using distribution_integer_t = std::conditional_t<sizeof(value_type_) <= 4, small_integer_t, large_integer_t>;
|
|
51
|
+
std::uniform_int_distribution<distribution_integer_t> distribution(min_val, max_val);
|
|
52
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
53
|
+
values_ptr[i] = static_cast<value_type_>(distribution(generator));
|
|
54
|
+
}
|
|
55
|
+
// Complex types need both real and imaginary parts filled
|
|
56
|
+
else if constexpr (is_complex_dtype<value_type_>()) {
|
|
57
|
+
using component_t = typename value_type_::component_t;
|
|
58
|
+
using distribution_float_t = std::conditional_t<sizeof(component_t) <= 4, float, double>;
|
|
59
|
+
std::uniform_real_distribution<distribution_float_t> distribution(min_val, max_val);
|
|
60
|
+
for (std::size_t i = 0; i < values_count; ++i) {
|
|
61
|
+
auto real = distribution(generator), imag = distribution(generator);
|
|
62
|
+
values_ptr[i] = value_type_(component_t(static_cast<distribution_float_t>(real)),
|
|
63
|
+
component_t(static_cast<distribution_float_t>(imag)));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Floats and other types use a fixed range for better numerical stability
|
|
67
|
+
else {
|
|
68
|
+
using distribution_float_t = std::conditional_t<sizeof(value_type_) <= 4, float, double>;
|
|
69
|
+
std::uniform_real_distribution<distribution_float_t> distribution(min_val, max_val);
|
|
70
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
71
|
+
values_ptr[i] = static_cast<value_type_>(distribution(generator));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @brief Fill array with uniform random values within specified range.
|
|
77
|
+
*/
|
|
78
|
+
template <typename value_type_, typename generator_type_>
|
|
79
|
+
void fill_uniform(generator_type_ &generator, value_type_ *values_ptr, std::size_t values_count) noexcept {
|
|
80
|
+
|
|
81
|
+
// Packed types (u1x8, u4x2, i4x2) need special handling - just fill with random bytes
|
|
82
|
+
if constexpr (dimensions_per_value<value_type_>() > 1) {
|
|
83
|
+
std::uniform_int_distribution<std::uint32_t> distribution(0, 255);
|
|
84
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
85
|
+
values_ptr[i] = value_type_::from_raw(static_cast<typename value_type_::raw_t>(distribution(generator)));
|
|
86
|
+
}
|
|
87
|
+
else if constexpr (is_integral_dtype<value_type_>())
|
|
88
|
+
return fill_uniform(generator, values_ptr, values_count, finite_min<value_type_>(), finite_max<value_type_>());
|
|
89
|
+
else return fill_uniform(generator, values_ptr, values_count, -10, +10);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @brief Fill array with lognormal distribution (good for detecting numerical edge cases).
|
|
94
|
+
*
|
|
95
|
+
* Probability Density Function (PDF):
|
|
96
|
+
*
|
|
97
|
+
* f(x; μ, σ) = 1 / (x · σ · √(2π)) · exp(−(ln x − μ)² / (2σ²)), x > 0
|
|
98
|
+
*
|
|
99
|
+
* Equivalently, if X ~ 𝒩(μ, σ²), then eˣ ~ LogNormal(μ, σ).
|
|
100
|
+
* Values span many orders of magnitude, which is useful for exercising overflow/underflow
|
|
101
|
+
* paths in low-precision arithmetic. Common in modeling latencies, file sizes, and token
|
|
102
|
+
* frequencies in NLP.
|
|
103
|
+
*/
|
|
104
|
+
template <typename value_type_, typename generator_type_>
|
|
105
|
+
void fill_lognormal(generator_type_ &generator, value_type_ *values_ptr, std::size_t values_count, //
|
|
106
|
+
double mean = 0.0, double stddev = 0.5) noexcept {
|
|
107
|
+
|
|
108
|
+
// Packed types (u1x8, u4x2, i4x2) need special handling
|
|
109
|
+
if constexpr (dimensions_per_value<value_type_>() > 1) {
|
|
110
|
+
std::lognormal_distribution<float> distribution(static_cast<float>(mean), static_cast<float>(stddev));
|
|
111
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
112
|
+
for (std::size_t j = 0; j < dimensions_per_value<value_type_>(); ++j)
|
|
113
|
+
values_ptr[i][j] = static_cast<std::uint8_t>(clamp(distribution(generator), 0.0f, 255.0f));
|
|
114
|
+
}
|
|
115
|
+
// Complex types need both real and imaginary parts filled
|
|
116
|
+
else if constexpr (is_complex_dtype<value_type_>()) {
|
|
117
|
+
using component_t = typename value_type_::component_t;
|
|
118
|
+
using distribution_float_t = std::conditional_t<sizeof(component_t) <= 4, float, double>;
|
|
119
|
+
std::lognormal_distribution<distribution_float_t> distribution(static_cast<distribution_float_t>(mean),
|
|
120
|
+
static_cast<distribution_float_t>(stddev));
|
|
121
|
+
std::bernoulli_distribution sign_distribution(0.5);
|
|
122
|
+
distribution_float_t const clamp_max = finite_max<component_t>();
|
|
123
|
+
distribution_float_t const clamp_min = finite_min<component_t>();
|
|
124
|
+
constexpr distribution_float_t signs[] = {1, -1};
|
|
125
|
+
for (std::size_t i = 0; i < values_count; ++i) {
|
|
126
|
+
auto real = clamp(distribution(generator) * signs[sign_distribution(generator)], clamp_min, clamp_max);
|
|
127
|
+
auto imag = clamp(distribution(generator) * signs[sign_distribution(generator)], clamp_min, clamp_max);
|
|
128
|
+
values_ptr[i] = value_type_(component_t(real), component_t(imag));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Floats and integers: unified path with trait-based clamping
|
|
132
|
+
else {
|
|
133
|
+
using distribution_float_t = std::conditional_t<sizeof(value_type_) <= 4, float, double>;
|
|
134
|
+
std::lognormal_distribution<distribution_float_t> distribution(static_cast<distribution_float_t>(mean),
|
|
135
|
+
static_cast<distribution_float_t>(stddev));
|
|
136
|
+
std::bernoulli_distribution sign_distribution(0.5);
|
|
137
|
+
distribution_float_t const clamp_max = static_cast<distribution_float_t>(finite_max<value_type_>());
|
|
138
|
+
distribution_float_t const clamp_min = static_cast<distribution_float_t>(finite_min<value_type_>());
|
|
139
|
+
constexpr distribution_float_t signs[] = {1, -1};
|
|
140
|
+
for (std::size_t i = 0; i < values_count; ++i) {
|
|
141
|
+
distribution_float_t val = distribution(generator);
|
|
142
|
+
if constexpr (is_signed_dtype<value_type_>()) val *= signs[sign_distribution(generator)];
|
|
143
|
+
values_ptr[i] = static_cast<value_type_>(clamp(val, clamp_min, clamp_max));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @brief Fill array with Cauchy distribution (heavy tails for stress testing).
|
|
150
|
+
*
|
|
151
|
+
* Probability Density Function (PDF):
|
|
152
|
+
*
|
|
153
|
+
* f(x; x₀, γ) = 1 / (π · γ · (1 + ((x − x₀) / γ)²))
|
|
154
|
+
*
|
|
155
|
+
* The Cauchy distribution has no defined mean or variance — all moments diverge.
|
|
156
|
+
* This makes it ideal for stress-testing numerical stability with extreme outliers.
|
|
157
|
+
* Common in robust Bayesian priors (half-Cauchy), Levy flights in metaheuristic
|
|
158
|
+
* optimization, and adversarial robustness evaluation.
|
|
159
|
+
*/
|
|
160
|
+
template <typename value_type_, typename generator_type_>
|
|
161
|
+
void fill_cauchy(generator_type_ &generator, value_type_ *values_ptr, std::size_t values_count, //
|
|
162
|
+
double location = 0.0, double scale = 1.0) noexcept {
|
|
163
|
+
|
|
164
|
+
// Packed types (u1x8, u4x2, i4x2) need special handling
|
|
165
|
+
if constexpr (dimensions_per_value<value_type_>() > 1) {
|
|
166
|
+
std::cauchy_distribution<float> distribution(static_cast<float>(location), static_cast<float>(scale));
|
|
167
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
168
|
+
for (std::size_t j = 0; j < dimensions_per_value<value_type_>(); ++j)
|
|
169
|
+
values_ptr[i][j] = static_cast<std::uint8_t>(clamp(distribution(generator), 0.0f, 255.0f));
|
|
170
|
+
}
|
|
171
|
+
// Complex types need both real and imaginary parts filled
|
|
172
|
+
else if constexpr (is_complex_dtype<value_type_>()) {
|
|
173
|
+
using component_t = typename value_type_::component_t;
|
|
174
|
+
using distribution_float_t = std::conditional_t<sizeof(component_t) <= 4, float, double>;
|
|
175
|
+
std::cauchy_distribution<distribution_float_t> distribution(static_cast<distribution_float_t>(location),
|
|
176
|
+
static_cast<distribution_float_t>(scale));
|
|
177
|
+
distribution_float_t const clamp_max = finite_max<component_t>();
|
|
178
|
+
distribution_float_t const clamp_min = finite_min<component_t>();
|
|
179
|
+
for (std::size_t i = 0; i < values_count; ++i) {
|
|
180
|
+
auto real = clamp(distribution(generator), clamp_min, clamp_max);
|
|
181
|
+
auto imag = clamp(distribution(generator), clamp_min, clamp_max);
|
|
182
|
+
values_ptr[i] = value_type_(component_t(real), component_t(imag));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Floats and integers: unified two-sided clamp
|
|
186
|
+
else {
|
|
187
|
+
using distribution_float_t = std::conditional_t<sizeof(value_type_) <= 4, float, double>;
|
|
188
|
+
std::cauchy_distribution<distribution_float_t> distribution(static_cast<distribution_float_t>(location),
|
|
189
|
+
static_cast<distribution_float_t>(scale));
|
|
190
|
+
distribution_float_t const clamp_max = static_cast<distribution_float_t>(finite_max<value_type_>());
|
|
191
|
+
distribution_float_t const clamp_min = static_cast<distribution_float_t>(finite_min<value_type_>());
|
|
192
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
193
|
+
values_ptr[i] = static_cast<value_type_>(clamp(distribution(generator), clamp_min, clamp_max));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @brief Fill arrays with latitude and longitude coordinate values in radians.
|
|
199
|
+
*/
|
|
200
|
+
template <typename value_type_, typename generator_type_>
|
|
201
|
+
void fill_coordinates(generator_type_ &generator, value_type_ *lats_ptr, value_type_ *lons_ptr,
|
|
202
|
+
std::size_t values_count) noexcept {
|
|
203
|
+
|
|
204
|
+
using distribution_float_t = std::conditional_t<sizeof(value_type_) <= 4, float, double>;
|
|
205
|
+
constexpr distribution_float_t pi = distribution_float_t(3.14159265358979323846);
|
|
206
|
+
std::uniform_real_distribution<distribution_float_t> lat_distribution(-pi / 2, pi / 2);
|
|
207
|
+
std::uniform_real_distribution<distribution_float_t> lon_distribution(-pi, pi);
|
|
208
|
+
for (std::size_t i = 0; i < values_count; ++i) {
|
|
209
|
+
lats_ptr[i] = static_cast<value_type_>(lat_distribution(generator));
|
|
210
|
+
lons_ptr[i] = static_cast<value_type_>(lon_distribution(generator));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @brief Fill destination coordinate arrays within a max angular separation of origin coordinates.
|
|
216
|
+
*
|
|
217
|
+
* Uses the great-circle destination formula to place each destination point at a random
|
|
218
|
+
* angular distance (uniform in [0, max_separation_rad]) and random bearing from the
|
|
219
|
+
* corresponding origin point. Coordinates are in radians.
|
|
220
|
+
*/
|
|
221
|
+
template <typename value_type_, typename generator_type_>
|
|
222
|
+
void fill_nearby_coordinates(generator_type_ &generator, value_type_ const *origin_lats_ptr,
|
|
223
|
+
value_type_ const *origin_lons_ptr, value_type_ *dest_lats_ptr, value_type_ *dest_lons_ptr,
|
|
224
|
+
std::size_t values_count, double max_separation_rad) noexcept {
|
|
225
|
+
|
|
226
|
+
using float_t = std::conditional_t<sizeof(value_type_) <= 4, float, double>;
|
|
227
|
+
constexpr float_t pi = float_t(3.14159265358979323846);
|
|
228
|
+
std::uniform_real_distribution<float_t> separation_distribution(0, float_t(max_separation_rad));
|
|
229
|
+
std::uniform_real_distribution<float_t> bearing_distribution(0, float_t(2) * pi);
|
|
230
|
+
for (std::size_t i = 0; i < values_count; ++i) {
|
|
231
|
+
float_t origin_lat = float_t(origin_lats_ptr[i]);
|
|
232
|
+
float_t origin_lon = float_t(origin_lons_ptr[i]);
|
|
233
|
+
float_t separation = separation_distribution(generator);
|
|
234
|
+
float_t bearing = bearing_distribution(generator);
|
|
235
|
+
float_t sin_origin_lat = std::sin(origin_lat), cos_origin_lat = std::cos(origin_lat);
|
|
236
|
+
float_t sin_sep = std::sin(separation), cos_sep = std::cos(separation);
|
|
237
|
+
float_t dest_lat = std::asin(sin_origin_lat * cos_sep + cos_origin_lat * sin_sep * std::cos(bearing));
|
|
238
|
+
float_t dest_lon = origin_lon + std::atan2(std::sin(bearing) * sin_sep * cos_origin_lat,
|
|
239
|
+
cos_sep - sin_origin_lat * std::sin(dest_lat));
|
|
240
|
+
dest_lats_ptr[i] = value_type_(dest_lat);
|
|
241
|
+
dest_lons_ptr[i] = value_type_(dest_lon);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @brief Fill array as a probability distribution (sums to 1.0).
|
|
247
|
+
*/
|
|
248
|
+
template <typename value_type_, typename generator_type_>
|
|
249
|
+
void fill_probability(generator_type_ &generator, value_type_ *values_ptr, std::size_t values_count) noexcept {
|
|
250
|
+
|
|
251
|
+
using distribution_float_t = std::conditional_t<sizeof(value_type_) <= 4, float, double>;
|
|
252
|
+
std::uniform_real_distribution<distribution_float_t> distribution(distribution_float_t(0.01),
|
|
253
|
+
distribution_float_t(1));
|
|
254
|
+
|
|
255
|
+
distribution_float_t sum = 0;
|
|
256
|
+
for (std::size_t i = 0; i < values_count; ++i) {
|
|
257
|
+
distribution_float_t val = distribution(generator);
|
|
258
|
+
values_ptr[i] = static_cast<value_type_>(val);
|
|
259
|
+
sum += val;
|
|
260
|
+
}
|
|
261
|
+
for (std::size_t i = 0; i < values_count; ++i)
|
|
262
|
+
values_ptr[i] = static_cast<value_type_>(static_cast<distribution_float_t>(values_ptr[i]) / sum);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @brief Fill array with sorted unique random integer values (in-place).
|
|
267
|
+
*
|
|
268
|
+
* Draws @p values_count values from [0, max_val - values_count], sorts once, then adds
|
|
269
|
+
* the index to each element. This guarantees uniqueness (duplicates become distinct)
|
|
270
|
+
* and preserves sorted order — all in O(n log n) with exactly one sort, no retry loop.
|
|
271
|
+
* Requires @p max_val >= @p values_count.
|
|
272
|
+
*/
|
|
273
|
+
template <typename value_type_, typename generator_type_>
|
|
274
|
+
void fill_sorted_unique(generator_type_ &generator, value_type_ *values_ptr, std::size_t values_count,
|
|
275
|
+
value_type_ max_val) noexcept {
|
|
276
|
+
using raw_t = typename value_type_::raw_t;
|
|
277
|
+
raw_t range = raw_t(max_val) - raw_t(values_count);
|
|
278
|
+
fill_uniform(generator, values_ptr, values_count, raw_t(0), range);
|
|
279
|
+
std::sort(values_ptr, values_ptr + values_count);
|
|
280
|
+
for (std::size_t i = 0; i < values_count; ++i) values_ptr[i] = value_type_(raw_t(values_ptr[i]) + raw_t(i));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
} // namespace ashvardanian::numkong
|
|
284
|
+
|
|
285
|
+
#endif // NK_RANDOM_HPP
|