pub struct Randomizer {
state: u64,
}
impl Randomizer {
pub fn new(seed: u64) -> Randomizer {
Randomizer {
state: seed.wrapping_add(0xDEADBEEFDEADBEEF),
}
}
pub fn write(&mut self, buf: &[u8]) {
for &i in buf {
self.write_u8(i);
}
}
pub fn read(&mut self, buf: &mut [u8]) {
for i in buf {
*i = self.read_u8();
}
}
pub fn read_u8(&mut self) -> u8 {
self.state = self.state.wrapping_mul(6364136223846793005).wrapping_add(1);
(self.state.wrapping_mul(1152921504735157271).rotate_right(2) ^ 0xFAB00105C0DE) as u8
}
pub fn write_u8(&mut self, b: u8) {
self.state ^= b as u64;
self.read_u8();
}
}
#[cfg(test)]
mod test {
use super::*;
#[ignore]
#[test]
fn test_fairness() {
let mut hits = [0u32; 256];
let mut rand = Randomizer::new(0);
for _ in 0..100000000 {
hits[rand.read_u8() as usize] += 1;
}
for &i in hits.iter() {
assert!(i < 400000, "Divergence not low enough, i = {}", i);
}
}
#[ignore]
#[test]
fn test_residue() {
fn fairness(n: u64) {
const TESTS: u64 = 10000000;
use std::mem;
let mut hits = vec![0; n as usize];
let mut rand = Randomizer::new(0);
for _ in 0..TESTS {
let mut buf = [0; 8];
rand.read(&mut buf);
unsafe {
hits[(mem::transmute::<[u8; 8], u64>(buf) % n) as usize] += 1;
}
}
for &i in hits.iter() {
assert!(i < TESTS / n, "Residue divergence not low enough, n = {}, div = {}", n, i as f64 / TESTS as f64 * n as f64);
}
}
for i in 3..1000 {
fairness(i);
}
}
#[ignore]
#[test]
fn bitstream_test() {
let mut ones = 0u64;
let mut rand = Randomizer::new(0);
for _ in 0..100000000 {
ones += rand.read_u8().count_ones() as u64;
}
assert!(ones <= 400000000, "Bits are biased. {}% ones.", ones as f64 / 400000000.0);
}
}