rand/rngs/
xoshiro256plusplus.rs1use rand_core::impls::fill_bytes_via_next;
10use rand_core::le::read_u64_into;
11use rand_core::{RngCore, SeedableRng};
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct Xoshiro256PlusPlus {
26    s: [u64; 4],
27}
28
29impl SeedableRng for Xoshiro256PlusPlus {
30    type Seed = [u8; 32];
31
32    #[inline]
35    fn from_seed(seed: [u8; 32]) -> Xoshiro256PlusPlus {
36        let mut state = [0; 4];
37        read_u64_into(&seed, &mut state);
38        if state.iter().all(|&x| x == 0) {
41            return Self::seed_from_u64(0);
42        }
43        Xoshiro256PlusPlus { s: state }
44    }
45
46    #[inline]
50    fn seed_from_u64(mut state: u64) -> Self {
51        const PHI: u64 = 0x9e3779b97f4a7c15;
52        let mut s = [0; 4];
53        for i in s.iter_mut() {
54            state = state.wrapping_add(PHI);
55            let mut z = state;
56            z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
57            z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
58            z = z ^ (z >> 31);
59            *i = z;
60        }
61        debug_assert_ne!(s, [0; 4]);
64        Xoshiro256PlusPlus { s }
65    }
66}
67
68impl RngCore for Xoshiro256PlusPlus {
69    #[inline]
70    fn next_u32(&mut self) -> u32 {
71        let val = self.next_u64();
74        (val >> 32) as u32
75    }
76
77    #[inline]
78    fn next_u64(&mut self) -> u64 {
79        let res = self.s[0]
80            .wrapping_add(self.s[3])
81            .rotate_left(23)
82            .wrapping_add(self.s[0]);
83
84        let t = self.s[1] << 17;
85
86        self.s[2] ^= self.s[0];
87        self.s[3] ^= self.s[1];
88        self.s[1] ^= self.s[2];
89        self.s[0] ^= self.s[3];
90
91        self.s[2] ^= t;
92
93        self.s[3] = self.s[3].rotate_left(45);
94
95        res
96    }
97
98    #[inline]
99    fn fill_bytes(&mut self, dst: &mut [u8]) {
100        fill_bytes_via_next(self, dst)
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::Xoshiro256PlusPlus;
107    use rand_core::{RngCore, SeedableRng};
108
109    #[test]
110    fn reference() {
111        let mut rng = Xoshiro256PlusPlus::from_seed([
112            1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
113            0, 0, 0,
114        ]);
115        let expected = [
118            41943041,
119            58720359,
120            3588806011781223,
121            3591011842654386,
122            9228616714210784205,
123            9973669472204895162,
124            14011001112246962877,
125            12406186145184390807,
126            15849039046786891736,
127            10450023813501588000,
128        ];
129        for &e in &expected {
130            assert_eq!(rng.next_u64(), e);
131        }
132    }
133
134    #[test]
135    fn stable_seed_from_u64_and_from_seed() {
136        let mut rng = Xoshiro256PlusPlus::seed_from_u64(0);
139        let mut rng_from_seed_0 = Xoshiro256PlusPlus::from_seed([0; 32]);
141        let expected = [
142            5987356902031041503,
143            7051070477665621255,
144            6633766593972829180,
145            211316841551650330,
146            9136120204379184874,
147            379361710973160858,
148            15813423377499357806,
149            15596884590815070553,
150            5439680534584881407,
151            1369371744833522710,
152        ];
153        for &e in &expected {
154            assert_eq!(rng.next_u64(), e);
155            assert_eq!(rng_from_seed_0.next_u64(), e);
156        }
157    }
158}