use crate::algos::rand::RandomNumberGenerator;
pub struct LcgRng {
state: u64,
}
impl LcgRng {
pub fn new(seed: u64) -> Self {
Self { state: seed }
}
pub fn next(&mut self) -> u64 {
let a: u64 = 1664525;
let c = 1013904223;
let m = 2u64.pow(32);
self.state = (a.wrapping_mul(self.state) + c) % m;
self.state
}
}
impl RandomNumberGenerator for LcgRng {
fn next(&mut self) -> u64 {
self.next()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::BTreeSet;
#[test]
fn test_lcg() {
let mut rng = LcgRng::new(0);
assert_eq!(rng.next(), 1013904223);
assert_eq!(rng.next(), 1196435762);
assert_eq!(rng.next(), 3519870697);
assert_eq!(rng.next(), 2868466484);
assert_eq!(rng.next(), 1649599747);
}
#[test]
fn doesnt_overflow() {
let mut rng = LcgRng::new(0);
let mut used = BTreeSet::new();
for _ in 0..1000000 {
let val = rng.next();
assert!(!used.contains(&val));
used.insert(val);
}
}
}