#[derive(Debug, Clone)]
pub struct Xoshiro256 {
state: [u64; 4],
}
impl Xoshiro256 {
pub fn seed_from_u64(seed: u64) -> Self {
let s = seed.max(1);
Self {
state: [s, s.wrapping_mul(2), s.wrapping_mul(3), s.wrapping_mul(5)],
}
}
pub fn next_u64(&mut self) -> u64 {
let result = self.state[0].wrapping_add(self.state[3]);
let t = self.state[1] << 17;
self.state[2] ^= self.state[0];
self.state[3] ^= self.state[1];
self.state[1] ^= self.state[2];
self.state[0] ^= self.state[3];
self.state[2] ^= t;
self.state[3] = self.state[3].rotate_left(45);
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn seed_produces_a_value() {
let mut rng = Xoshiro256::seed_from_u64(1);
let _ = rng.next_u64();
}
#[test]
fn different_seeds_produce_different_streams() {
let mut a = Xoshiro256::seed_from_u64(1);
let mut b = Xoshiro256::seed_from_u64(2);
assert_ne!(a.next_u64(), b.next_u64());
}
#[test]
fn same_seed_produces_same_stream() {
let mut a = Xoshiro256::seed_from_u64(42);
let mut b = Xoshiro256::seed_from_u64(42);
for _ in 0..16 {
assert_eq!(a.next_u64(), b.next_u64());
}
}
}