ya_rand/
xoshiro512pp.rs

1use crate::rng::{Generator, SeedableGenerator};
2use crate::util;
3
4/// Rust implementation of the xoshiro512++ PRNG.
5///
6/// This generator is very fast, high-quality, and small,
7/// but not cryptographically secure.
8///
9/// More information can be found at: <https://prng.di.unimi.it/>.
10#[derive(Debug, PartialEq, Eq)]
11pub struct Xoshiro512pp {
12    state: [u64; 8],
13}
14
15impl Default for Xoshiro512pp {
16    fn default() -> Self {
17        Self::new_with_seed(0)
18    }
19}
20
21impl SeedableGenerator for Xoshiro512pp {
22    fn new_with_seed(seed: u64) -> Self {
23        let state = util::state_from_seed(seed);
24        let mut ret = Self { state };
25        let _discard_first = ret.u64();
26        ret
27    }
28}
29
30impl Generator for Xoshiro512pp {
31    #[inline]
32    fn try_new() -> Result<Self, getrandom::Error> {
33        let state = util::state_from_entropy()?;
34        Ok(Self { state })
35    }
36
37    #[cfg_attr(feature = "inline", inline)]
38    fn u64(&mut self) -> u64 {
39        let result = self.state[0]
40            .wrapping_add(self.state[2])
41            .rotate_left(17)
42            .wrapping_add(self.state[2]);
43        let tmp = self.state[1] << 11;
44
45        self.state[2] ^= self.state[0];
46        self.state[5] ^= self.state[1];
47        self.state[1] ^= self.state[2];
48        self.state[7] ^= self.state[3];
49        self.state[3] ^= self.state[4];
50        self.state[4] ^= self.state[5];
51        self.state[0] ^= self.state[6];
52        self.state[6] ^= self.state[7];
53
54        self.state[6] ^= tmp;
55        self.state[7] = self.state[7].rotate_left(21);
56
57        result
58    }
59}