unc_rng/
lib.rs

1pub struct Rng {
2    state: (u64, u64)
3}
4
5impl Rng {
6    pub fn new(random_vec_seed: &Vec<u8>) -> Self {
7        let mut seed = 0;
8
9        seed |= u64::from(random_vec_seed[0]) << 56;
10        seed |= u64::from(random_vec_seed[1]) << 48;
11        seed |= u64::from(random_vec_seed[2]) << 40;
12        seed |= u64::from(random_vec_seed[3]) << 32;
13        seed |= u64::from(random_vec_seed[4]) << 24;
14        seed |= u64::from(random_vec_seed[5]) << 16;
15        seed |= u64::from(random_vec_seed[6]) << 8;
16        seed |= u64::from(random_vec_seed[7]) << 0;
17
18        Self {state: (
19            seed ^ 0xf4dbdf2183dcefb7, // [crc32(b"0"), crc32(b"1")]
20            seed ^ 0x1ad5be0d6dd28e9b  // [crc32(b"2"), crc32(b"3")]
21        )}
22    }
23
24    pub fn rand_u64(&mut self) -> u64 {
25        let (mut x, y) = self.state;
26        self.state.0 = y;
27        x ^= x << 23;
28        self.state.1 = x ^ y ^ (x >> 17) ^ (y >> 26);
29        self.state.1.wrapping_add(y)
30    }
31
32    #[inline]
33    pub fn rand_u32(&mut self) -> u32 {
34        (self.rand_u64() >> 32) as u32
35    }
36    #[inline]
37    pub fn rand_u8(&mut self) -> u8 {
38        self.rand_u32() as u8
39    }
40
41    #[inline]
42    pub fn rand_u16(&mut self) -> u16 {
43        self.rand_u32() as u16
44    }
45
46    #[cfg(target_pointer_width = "32")]
47    #[inline]
48    pub fn rand_usize(&mut self) -> usize {
49        self.rand_u32() as usize
50    }
51
52    #[cfg(target_pointer_width = "64")]
53    #[inline]
54    pub fn rand_usize(&mut self) -> usize {
55        self.rand_u64() as usize
56    }
57
58    // Algorithm to generate an equidistributed random number in 0..m.
59    // Applies the idea of rejection sampling.
60    pub fn rand_bounded_u32(&mut self, m: u32) -> u32 {
61        let threshold = m.wrapping_neg().wrapping_rem(m);
62        loop {
63            let r = self.rand_u32();
64            if r >= threshold {
65                return r.wrapping_rem(m);
66            }
67        }
68    }
69
70    pub fn rand_bounded_u64(&mut self, m: u64) -> u64 {
71        let threshold = m.wrapping_neg().wrapping_rem(m);
72        loop {
73            let r = self.rand_u64();
74            if r >= threshold {
75                return r.wrapping_rem(m);
76            }
77        }
78    }
79
80    #[cfg(target_pointer_width = "32")]
81    pub fn rand_bounded_usize(&mut self, m: usize) -> usize {
82        self.rand_bounded_u32(m as u32) as usize
83    }
84
85    #[cfg(target_pointer_width = "64")]
86    pub fn rand_bounded_usize(&mut self, m: usize) -> usize {
87        self.rand_bounded_u64(m as u64) as usize
88    }
89
90    pub fn rand_range_u32(&mut self, a: u32, b: u32) -> u32 {
91       a + self.rand_bounded_u32(b-a)
92    }
93    pub fn rand_range_u64(&mut self, a: u64, b: u64) -> u64 {
94       a + self.rand_bounded_u64(b-a)
95    }
96    pub fn rand_range_i32(&mut self, a: i32, b: i32) -> i32 {
97        a + self.rand_bounded_u32((b-a) as u32) as i32
98    }
99    pub fn rand_range_i64(&mut self, a: i64, b: i64) -> i64 {
100        a + self.rand_bounded_u64((b-a) as u64) as i64
101    }
102
103    pub fn rand_f32(&mut self) -> f32 {
104        self.rand_u32() as f32 * 2.3283064E-10
105    }
106
107    pub fn rand_f64(&mut self) -> f64 {
108        self.rand_u32() as f64 * 2.3283064365386963E-10
109    }
110
111    pub fn shuffle<T>(&mut self, a: &mut [T]) {
112        if a.is_empty() {return;}
113        let mut i = a.len() - 1;
114        while i > 0 {
115            let j = self.rand_usize()%(i + 1);
116            a.swap(i, j);
117            i -= 1;
118        }
119    }
120
121    pub fn fill(&mut self, a: &mut[u8]) {
122        let mut x = self.rand_u32();
123        let mut count = 3;
124        for p in a {
125            *p = x as u8;
126            if count == 0 {
127                x = self.rand_u32();
128                count = 3;
129            } else {
130                x  >>= 8;
131                count -= 1;
132            }
133        }
134    }
135}