Skip to main content

random/
xorshift.rs

1use crate::Source;
2
3/// An instance of the Xorshift128+ algorithm.
4///
5/// ## References
6///
7/// 1. Sebastiano Vigna, “Further Scramblings of Marsaglia’s Xorshift
8///    Generators,” CoRR, 2014.
9///
10/// 2. <https://en.wikipedia.org/wiki/Xorshift#xorshift.2B>
11#[derive(Clone, Copy)]
12pub struct Xorshift128Plus(u64, u64);
13
14impl Xorshift128Plus {
15    /// Create an instance of the algorithm.
16    ///
17    /// At least one bit of the seed should be one.
18    #[inline(always)]
19    pub fn new(seed: [u64; 2]) -> Self {
20        debug_assert!(
21            seed[0] | seed[1] != 0,
22            "at least one bit of the seed should be one"
23        );
24        Xorshift128Plus(seed[0], seed[1])
25    }
26}
27
28impl Source for Xorshift128Plus {
29    #[inline(always)]
30    fn read_u64(&mut self) -> u64 {
31        let (mut x, y) = (self.0, self.1);
32        self.0 = y;
33        x = x ^ (x << 23);
34        x = x ^ (x >> 17);
35        x = x ^ y ^ (y >> 26);
36        self.1 = x;
37        x.wrapping_add(y)
38    }
39}
40
41impl From<[u64; 2]> for Xorshift128Plus {
42    #[inline(always)]
43    fn from(seed: [u64; 2]) -> Self {
44        Self::new(seed)
45    }
46}
47
48impl From<Xorshift128Plus> for [u64; 2] {
49    #[inline(always)]
50    fn from(source: Xorshift128Plus) -> Self {
51        [source.0, source.1]
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use crate::Xorshift128Plus;
58
59    #[test]
60    #[should_panic]
61    fn new_zero_seed() {
62        let _ = Xorshift128Plus::new([0, 0]);
63    }
64}