quad_rand/
lib.rs

1#![no_std]
2extern crate alloc;
3
4use alloc::vec::Vec;
5use core::sync::atomic::{AtomicU64, Ordering};
6
7mod fy;
8
9const DEFAULT_INC: u64 = 1442695040888963407;
10const MULTIPLIER: u64 = 6364136223846793005;
11
12pub struct RandGenerator {
13    state: AtomicU64,
14}
15
16impl RandGenerator {
17    pub const fn new() -> Self {
18        Self {
19            state: AtomicU64::new(0),
20        }
21    }
22    pub fn srand(&self, seed: u64) {
23        self.state.store(0, Ordering::Relaxed);
24        self.rand();
25        let oldstate = self.state.load(Ordering::Relaxed);
26        self.state
27            .store(oldstate.wrapping_add(seed), Ordering::Relaxed);
28        self.rand();
29    }
30    pub fn rand(&self) -> u32 {
31        let oldstate: u64 = self.state.load(Ordering::Relaxed);
32        self.state.store(
33            oldstate.wrapping_mul(MULTIPLIER).wrapping_add(DEFAULT_INC),
34            Ordering::Relaxed,
35        );
36        let xorshifted: u32 = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
37        let rot: u32 = (oldstate >> 59) as u32;
38        xorshifted.rotate_right(rot)
39    }
40    #[inline]
41    pub fn gen_range<T>(&self, low: T, high: T) -> T
42    where
43        T: RandomRange,
44    {
45        T::gen_range_with_state(self, low, high)
46    }
47}
48
49static GLOBAL_STATE: RandGenerator = RandGenerator::new();
50
51/// Seeds the pseudo-random number generator used by rand()
52/// with the value seed.
53#[inline]
54pub fn srand(seed: u64) {
55    GLOBAL_STATE.srand(seed);
56}
57
58/// Returns a pseudo-random number in the range of 0 to u32::MAX.
59#[inline]
60pub fn rand() -> u32 {
61    GLOBAL_STATE.rand()
62}
63
64pub trait RandomRange {
65    fn gen_range(low: Self, high: Self) -> Self;
66    fn gen_range_with_state(state: &RandGenerator, low: Self, high: Self) -> Self;
67}
68
69macro_rules! impl_random_range{
70    ($($ty:ty),*,)=>{
71        $(
72            impl RandomRange for $ty{
73                #[inline]
74                fn gen_range(low: Self, high: Self) -> Self{
75                    Self::gen_range_with_state(&GLOBAL_STATE, low, high)
76                }
77                #[inline]
78                fn gen_range_with_state(gen: &RandGenerator, low: Self, high: Self) -> Self {
79                    let r = gen.rand() as f64 / (u32::MAX as f64 + 1.0);
80                    let r = low as f64 + (high as f64 - low as f64) * r;
81                    r as Self
82                }
83            }
84        )*
85    }
86}
87impl_random_range!(f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize,);
88
89#[inline]
90pub fn gen_range<T>(low: T, high: T) -> T
91where
92    T: RandomRange,
93{
94    GLOBAL_STATE.gen_range(low, high)
95}
96
97pub struct SliceChooseIter<'a, T> {
98    source: &'a [T],
99    indices: alloc::vec::IntoIter<usize>,
100}
101
102impl<'a, T> Iterator for SliceChooseIter<'a, T> {
103    type Item = &'a T;
104
105    #[inline]
106    fn next(&mut self) -> Option<&'a T> {
107        self.indices.next().map(|ix| &self.source[ix])
108    }
109}
110
111pub trait ChooseRandom<T> {
112    #[inline]
113    fn shuffle(&mut self) {
114        self.shuffle_with_state(&GLOBAL_STATE)
115    }
116    #[inline]
117    fn choose(&self) -> Option<&T> {
118        self.choose_with_state(&GLOBAL_STATE)
119    }
120    #[inline]
121    fn choose_mut(&mut self) -> Option<&mut T> {
122        self.choose_mut_with_state(&GLOBAL_STATE)
123    }
124    #[inline]
125    fn choose_multiple(&self, amount: usize) -> SliceChooseIter<T> {
126        self.choose_multiple_with_state(&GLOBAL_STATE, amount)
127    }
128
129    fn shuffle_with_state(&mut self, state: &RandGenerator);
130    fn choose_with_state(&self, state: &RandGenerator) -> Option<&T>;
131    fn choose_mut_with_state(&mut self, state: &RandGenerator) -> Option<&mut T>;
132    fn choose_multiple_with_state(
133        &self,
134        state: &RandGenerator,
135        _amount: usize,
136    ) -> SliceChooseIter<T>;
137}
138
139impl<T> ChooseRandom<T> for [T] {
140    #[inline]
141    fn shuffle_with_state(&mut self, state: &RandGenerator) {
142        let mut fy = fy::FisherYates::default();
143
144        fy.shuffle_with_state(state, self);
145    }
146
147    #[inline]
148    fn choose_with_state(&self, state: &RandGenerator) -> Option<&T> {
149        let ix = state.gen_range(0, self.len());
150        self.get(ix)
151    }
152
153    #[inline]
154    fn choose_mut_with_state(&mut self, state: &RandGenerator) -> Option<&mut T> {
155        let ix = state.gen_range(0, self.len());
156        self.get_mut(ix)
157    }
158
159    #[inline]
160    fn choose_multiple_with_state(
161        &self,
162        state: &RandGenerator,
163        amount: usize,
164    ) -> SliceChooseIter<T> {
165        let mut indices = (0..self.len())
166            .enumerate()
167            .map(|(i, _)| i)
168            .collect::<Vec<usize>>();
169
170        indices.shuffle_with_state(state);
171        indices.resize(amount, 0);
172
173        SliceChooseIter {
174            source: self,
175            indices: indices.into_iter(),
176        }
177    }
178}
179
180#[cfg(feature = "rand")]
181pub mod compat {
182    pub struct QuadRandWithState<'a>(pub &'a crate::RandGenerator);
183
184    impl<'a> rand::RngCore for QuadRandWithState<'a> {
185        #[inline]
186        fn next_u32(&mut self) -> u32 {
187            self.0.gen_range(0, u32::MAX)
188        }
189
190        #[inline]
191        fn next_u64(&mut self) -> u64 {
192            self.0.gen_range(0, u64::MAX)
193        }
194
195        #[inline]
196        fn fill_bytes(&mut self, dest: &mut [u8]) {
197            for i in 0..dest.len() {
198                dest[i] = self.0.gen_range(0, 255)
199            }
200        }
201
202        #[inline]
203        fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
204            Ok(self.fill_bytes(dest))
205        }
206    }
207
208    pub struct QuadRand;
209
210    impl rand::RngCore for QuadRand {
211        #[inline]
212        fn next_u32(&mut self) -> u32 {
213            QuadRandWithState(&crate::GLOBAL_STATE).next_u32()
214        }
215
216        #[inline]
217        fn next_u64(&mut self) -> u64 {
218            QuadRandWithState(&crate::GLOBAL_STATE).next_u64()
219        }
220
221        #[inline]
222        fn fill_bytes(&mut self, dest: &mut [u8]) {
223            QuadRandWithState(&crate::GLOBAL_STATE).fill_bytes(dest)
224        }
225
226        #[inline]
227        fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
228            QuadRandWithState(&crate::GLOBAL_STATE).try_fill_bytes(dest)
229        }
230    }
231}