use super::RandomBackend;
#[derive(Clone, Debug)]
pub struct XorShift {
state: u64,
}
impl XorShift {
pub fn try_new(seed: u64) -> core::result::Result<Self, crate::AporiaError> {
if seed == 0 {
return Err(crate::AporiaError::InvalidSeed("XorShift seed must be non-zero"));
}
Ok(Self { state: seed })
}
pub fn new(seed: u64) -> Self {
if seed == 0 { panic!("invalid zero seed for XorShift"); }
Self { state: seed }
}
}
impl RandomBackend for XorShift {
fn next_u64(&mut self) -> u64 {
let mut x = self.state;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.state = x;
x
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xorshift_basic_sequence_nonzero() {
let mut backend = XorShift::new(1);
let v1 = backend.next_u64();
let v2 = backend.next_u64();
assert_ne!(v1, 0);
assert_ne!(v2, 0);
assert_ne!(v1, v2);
}
#[test]
fn xorshift_zero_seed_panics() {
assert!(XorShift::try_new(0).is_err());
}
}