1use rand_chacha::{ChaCha8Rng, rand_core::SeedableRng};
2use rand_core::RngCore;
3
4const MAXF64: f64 = 9007199254740992.0;
5
6pub struct Source {
7 source: ChaCha8Rng,
8}
9
10impl Source {
11 pub fn new(seed: [u8; 32]) -> Source {
12 Source {
13 source: ChaCha8Rng::from_seed(seed),
14 }
15 }
16
17 pub fn branch(&mut self) -> ([u8; 32], Self) {
18 let seed: [u8; 32] = self.new_seed();
19 (seed, Source::new(seed))
20 }
21
22 pub fn new_seed(&mut self) -> [u8; 32] {
23 let mut seed: [u8; 32] = [0u8; 32];
24 self.fill_bytes(&mut seed);
25 seed
26 }
27
28 #[inline(always)]
29 pub fn next_u64n(&mut self, max: u64, mask: u64) -> u64 {
30 let mut x: u64 = self.next_u64() & mask;
31 while x >= max {
32 x = self.next_u64() & mask;
33 }
34 x
35 }
36
37 #[inline(always)]
38 pub fn next_f64(&mut self, min: f64, max: f64) -> f64 {
39 min + ((self.next_u64() << 11 >> 11) as f64) / MAXF64 * (max - min)
40 }
41
42 #[inline(always)]
43 pub fn next_i32(&mut self) -> i32 {
44 self.next_u32() as i32
45 }
46
47 #[inline(always)]
48 pub fn next_i64(&mut self) -> i64 {
49 self.next_u64() as i64
50 }
51
52 #[inline(always)]
53 pub fn next_i128(&mut self) -> i128 {
54 self.next_u128() as i128
55 }
56
57 #[inline(always)]
58 pub fn next_u128(&mut self) -> u128 {
59 (self.next_u64() as u128) << 64 | (self.next_u64() as u128)
60 }
61}
62
63impl RngCore for Source {
64 #[inline(always)]
65 fn next_u32(&mut self) -> u32 {
66 self.source.next_u32()
67 }
68
69 #[inline(always)]
70 fn next_u64(&mut self) -> u64 {
71 self.source.next_u64()
72 }
73
74 #[inline(always)]
75 fn fill_bytes(&mut self, bytes: &mut [u8]) {
76 self.source.fill_bytes(bytes)
77 }
78}