use super::RandomBackend;
use crate::backend::SplitMix64;
#[derive(Clone, Debug)]
pub struct Xoshiro256StarStar {
s: [u64; 4],
}
impl Xoshiro256StarStar {
pub fn new(seed: u64) -> Self {
let mut state = SplitMix64::new(seed);
let mut s = [0u64; 4];
for x in s.iter_mut().take(4) {
*x = state.next_u64();
}
Self { s }
}
fn rotl(x: u64, k: u32) -> u64 {
(x << k) | (x >> (64 - k))
}
}
impl RandomBackend for Xoshiro256StarStar {
fn next_u64(&mut self) -> u64 {
let result = Self::rotl(self.s[1].wrapping_mul(5), 7).wrapping_mul(9);
let t = self.s[1] << 17;
self.s[2] ^= self.s[0];
self.s[3] ^= self.s[1];
self.s[1] ^= self.s[2];
self.s[0] ^= self.s[3];
self.s[2] ^= t;
self.s[3] = Self::rotl(self.s[3], 45);
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xoshiro256starstar_progresses() {
let mut xo = Xoshiro256StarStar::new(13579);
let a = xo.next_u64();
let b = xo.next_u64();
assert_ne!(a, b);
}
}