ferray_random/
generator.rs1use ferray_core::{Array, FerrayError, Ix1};
7
8use crate::bitgen::{BitGenerator, Xoshiro256StarStar};
9
10pub struct Generator<B: BitGenerator = Xoshiro256StarStar> {
25 pub(crate) bg: B,
27 pub(crate) seed: u64,
29}
30
31impl<B: BitGenerator> Generator<B> {
32 pub fn new(bg: B) -> Self {
34 Self { bg, seed: 0 }
35 }
36
37 pub(crate) fn new_with_seed(bg: B, seed: u64) -> Self {
39 Self { bg, seed }
40 }
41
42 #[inline]
44 pub fn bit_generator(&mut self) -> &mut B {
45 &mut self.bg
46 }
47
48 #[inline]
50 pub fn next_u64(&mut self) -> u64 {
51 self.bg.next_u64()
52 }
53
54 #[inline]
56 pub fn next_f64(&mut self) -> f64 {
57 self.bg.next_f64()
58 }
59
60 #[inline]
62 pub fn next_u64_bounded(&mut self, bound: u64) -> u64 {
63 self.bg.next_u64_bounded(bound)
64 }
65}
66
67pub fn default_rng() -> Generator<Xoshiro256StarStar> {
78 let seed = {
81 let mut buf = [0u8; 8];
82 if getrandom::getrandom(&mut buf).is_ok() {
83 u64::from_ne_bytes(buf)
84 } else {
85 use std::time::SystemTime;
87 let dur = SystemTime::now()
88 .duration_since(SystemTime::UNIX_EPOCH)
89 .unwrap_or_default();
90 let nanos = dur.as_nanos();
91 let mut s = nanos as u64;
92 s ^= (nanos >> 64) as u64;
93 let stack_var: u8 = 0;
94 s ^= &stack_var as *const u8 as u64;
95 s
96 }
97 };
98 default_rng_seeded(seed)
99}
100
101pub fn default_rng_seeded(seed: u64) -> Generator<Xoshiro256StarStar> {
111 let bg = Xoshiro256StarStar::seed_from_u64(seed);
112 Generator::new_with_seed(bg, seed)
113}
114
115pub fn spawn_generators<B: BitGenerator + Clone>(
124 parent: &mut Generator<B>,
125 n: usize,
126) -> Result<Vec<Generator<B>>, FerrayError> {
127 if n == 0 {
128 return Err(FerrayError::invalid_value("spawn count must be > 0"));
129 }
130
131 let mut children = Vec::with_capacity(n);
132
133 let mut test_bg = parent.bg.clone();
135 if test_bg.jump().is_some() {
136 let mut current = parent.bg.clone();
138 for _ in 0..n {
139 children.push(Generator::new(current.clone()));
140 current.jump();
141 }
142 parent.bg = current;
144 return Ok(children);
145 }
146
147 if let Some(first) = B::stream(parent.seed, 0) {
149 drop(first);
150 for i in 0..n {
151 if let Some(bg) = B::stream(parent.seed, i as u64) {
152 children.push(Generator::new(bg));
153 }
154 }
155 if children.len() == n {
156 return Ok(children);
157 }
158 children.clear();
159 }
160
161 for _ in 0..n {
163 let child_seed = parent.bg.next_u64();
164 let bg = B::seed_from_u64(child_seed);
165 children.push(Generator::new(bg));
166 }
167 Ok(children)
168}
169
170pub(crate) fn generate_vec<B: BitGenerator>(
172 rng: &mut Generator<B>,
173 size: usize,
174 mut f: impl FnMut(&mut B) -> f64,
175) -> Vec<f64> {
176 let mut data = Vec::with_capacity(size);
177 for _ in 0..size {
178 data.push(f(&mut rng.bg));
179 }
180 data
181}
182
183pub(crate) fn generate_vec_i64<B: BitGenerator>(
185 rng: &mut Generator<B>,
186 size: usize,
187 mut f: impl FnMut(&mut B) -> i64,
188) -> Vec<i64> {
189 let mut data = Vec::with_capacity(size);
190 for _ in 0..size {
191 data.push(f(&mut rng.bg));
192 }
193 data
194}
195
196pub(crate) fn vec_to_array1(data: Vec<f64>) -> Result<Array<f64, Ix1>, FerrayError> {
198 let n = data.len();
199 Array::<f64, Ix1>::from_vec(Ix1::new([n]), data)
200}
201
202pub(crate) fn vec_to_array1_i64(data: Vec<i64>) -> Result<Array<i64, Ix1>, FerrayError> {
204 let n = data.len();
205 Array::<i64, Ix1>::from_vec(Ix1::new([n]), data)
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn default_rng_seeded_deterministic() {
214 let mut rng1 = default_rng_seeded(42);
215 let mut rng2 = default_rng_seeded(42);
216 for _ in 0..100 {
217 assert_eq!(rng1.next_u64(), rng2.next_u64());
218 }
219 }
220
221 #[test]
222 fn default_rng_works() {
223 let mut rng = default_rng();
224 let v = rng.next_f64();
225 assert!((0.0..1.0).contains(&v));
226 }
227
228 #[test]
229 fn spawn_xoshiro() {
230 let mut parent = default_rng_seeded(42);
231 let children = spawn_generators(&mut parent, 4).unwrap();
232 assert_eq!(children.len(), 4);
233 }
234
235 #[test]
236 fn spawn_zero_is_error() {
237 let mut parent = default_rng_seeded(42);
238 assert!(spawn_generators(&mut parent, 0).is_err());
239 }
240}