#[cfg(test)]
mod tests {
use clock_rand::*;
#[test]
#[cfg(feature = "fast_rng")]
fn test_chi_square() {
let mut rng = Xoshiro256Plus::new(42);
let mut buckets = [0u64; 10];
for _ in 0..10000 {
let value = rng.next_u64();
let bucket = (value % 10) as usize;
buckets[bucket] += 1;
}
let expected = 10000 / 10;
let mut chi_square = 0.0;
for &count in &buckets {
let diff = count as f64 - expected as f64;
chi_square += (diff * diff) / expected as f64;
}
assert!(chi_square < 20.0, "Chi-square test failed: {}", chi_square);
}
#[test]
#[cfg(feature = "fast_rng")]
fn test_runs() {
let mut rng = Xoshiro256Plus::new(42);
let mut bits = Vec::new();
for _ in 0..1000 {
bits.push((rng.next_u64() & 1) == 1);
}
let mut runs = 1;
for i in 1..bits.len() {
if bits[i] != bits[i - 1] {
runs += 1;
}
}
assert!(runs > 400 && runs < 600, "Runs test failed: {}", runs);
}
#[test]
#[cfg(feature = "fast_rng")]
fn test_serial_correlation() {
let mut rng = Xoshiro256Plus::new(42);
let mut values = Vec::new();
for _ in 0..1000 {
values.push(rng.next_u64());
}
let mut covariance = 0.0;
let mut variance = 0.0;
let mean: f64 = values.iter().map(|&v| v as f64).sum::<f64>() / values.len() as f64;
for i in 1..values.len() {
let diff1 = values[i - 1] as f64 - mean;
let diff2 = values[i] as f64 - mean;
covariance += diff1 * diff2;
}
for &value in &values {
let diff = value as f64 - mean;
variance += diff * diff;
}
covariance /= (values.len() - 1) as f64;
variance /= (values.len() - 1) as f64;
let correlation = if variance > 0.0 {
covariance / variance
} else {
0.0
};
assert!(
correlation.abs() < 0.1,
"Serial correlation too high: {}",
correlation
);
}
#[test]
#[cfg(feature = "fast_rng")]
fn test_birthday_spacing() {
let mut rng = Xoshiro256Plus::new(42);
let mut seen = std::collections::HashSet::new();
let mut collisions = 0;
for _ in 0..10000 {
let value = rng.next_u64();
if !seen.insert(value) {
collisions += 1;
}
}
assert!(collisions < 10, "Too many collisions: {}", collisions);
}
}