1use std::cell::RefCell;
8
9static mut WHITE_NOISE_TAB: [f64; 1024] = [0.0; 1024];
12
13#[allow(rustdoc::private_intra_doc_links)]
14pub fn init_white_noise_tab() {
16 let mut rng = RandGen::new();
17 unsafe {
18 for i in 0..WHITE_NOISE_TAB.len() {
19 WHITE_NOISE_TAB[i as usize] = rng.next_open01();
20 }
21 }
22}
23
24#[derive(Debug, Copy, Clone, PartialEq)]
25pub struct RandGen {
29 r: [u64; 2],
30}
31
32pub fn next_xoroshiro128(state: &mut [u64; 2]) -> u64 {
37 let s0: u64 = state[0];
38 let mut s1: u64 = state[1];
39 let result: u64 = s0.wrapping_add(s1);
40
41 s1 ^= s0;
42 state[0] = s0.rotate_left(55) ^ s1 ^ (s1 << 14); state[1] = s1.rotate_left(36); result
46}
47
48pub fn u64_to_open01(u: u64) -> f64 {
53 use core::f64::EPSILON;
54 let float_size = std::mem::size_of::<f64>() as u32 * 8;
55 let fraction = u >> (float_size - 52);
56 let exponent_bits: u64 = (1023 as u64) << 52;
57 f64::from_bits(fraction | exponent_bits) - (1.0 - EPSILON / 2.0)
58}
59
60impl RandGen {
61 pub fn new() -> Self {
62 RandGen { r: [0x193a6754a8a7d469, 0x97830e05113ba7bb] }
63 }
64
65 pub fn next(&mut self) -> u64 {
67 next_xoroshiro128(&mut self.r)
68 }
69
70 pub fn next_open01(&mut self) -> f64 {
72 u64_to_open01(self.next())
73 }
74}
75
76#[derive(Debug, Copy, Clone)]
77pub struct Rng {
80 sm: SplitMix64,
81}
82
83impl Rng {
84 pub fn new() -> Self {
85 Self { sm: SplitMix64::new(0x193a67f4a8a6d769) }
86 }
87
88 pub fn seed(&mut self, seed: u64) {
89 self.sm = SplitMix64::new(seed);
90 }
91
92 #[inline]
93 pub fn next(&mut self) -> f32 {
94 self.sm.next_open01() as f32
95 }
96
97 #[inline]
98 pub fn next_u64(&mut self) -> u64 {
99 self.sm.next_u64()
100 }
101}
102
103thread_local! {
104 static GLOBAL_RNG: RefCell<Rng> = RefCell::new(Rng::new());
105}
106
107#[inline]
108pub fn rand_01() -> f32 {
109 GLOBAL_RNG.with(|r| r.borrow_mut().next())
110}
111
112#[inline]
113pub fn rand_u64() -> u64 {
114 GLOBAL_RNG.with(|r| r.borrow_mut().next_u64())
115}
116
117#[derive(Debug, Copy, Clone)]
136pub struct SplitMix64(pub u64);
137
138const PHI: u64 = 0x9e3779b97f4a7c15;
140
141impl SplitMix64 {
142 pub fn new(seed: u64) -> Self {
143 Self(seed)
144 }
145 pub fn new_from_i64(seed: i64) -> Self {
146 Self::new(u64::from_be_bytes(seed.to_be_bytes()))
147 }
148
149 pub fn new_time_seed() -> Self {
150 use std::time::SystemTime;
151
152 match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
153 Ok(n) => Self::new(n.as_secs() as u64),
154 Err(_) => Self::new(123456789),
155 }
156 }
157
158 #[inline]
159 pub fn next_u64(&mut self) -> u64 {
160 self.0 = self.0.wrapping_add(PHI);
161 let mut z = self.0;
162 z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
163 z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
164 z ^ (z >> 31)
165 }
166
167 #[inline]
168 pub fn next_i64(&mut self) -> i64 {
169 i64::from_be_bytes(self.next_u64().to_be_bytes())
170 }
171
172 #[inline]
173 pub fn next_open01(&mut self) -> f64 {
174 u64_to_open01(self.next_u64())
175 }
176}