#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use arkhe_rand::{gen_range, RngSource};
use proptest::prelude::*;
proptest! {
#[test]
fn split_determinism(seed in any::<[u8; 32]>()) {
let mut parent_a = RngSource::from_seed(&seed);
let mut parent_b = RngSource::from_seed(&seed);
let mut child_a = parent_a.split();
let mut child_b = parent_b.split();
let mut buf_a = [0u8; 64];
let mut buf_b = [0u8; 64];
child_a.fill_bytes(&mut buf_a);
child_b.fill_bytes(&mut buf_b);
prop_assert_eq!(buf_a, buf_b);
}
#[test]
fn fill_bytes_monotonic_advance(
seed in any::<[u8; 32]>(),
split_at in 0usize..=64usize,
) {
let mut a = RngSource::from_seed(&seed);
let mut b = RngSource::from_seed(&seed);
let mut whole = [0u8; 64];
a.fill_bytes(&mut whole);
let mut combined = [0u8; 64];
b.fill_bytes(&mut combined[..split_at]);
b.fill_bytes(&mut combined[split_at..]);
prop_assert_eq!(whole, combined);
}
}
#[test]
fn lemire_unbiased_chi_square_n7() {
const N: u32 = 7;
const SAMPLES: u32 = 1_000_000;
const CHI2_CRIT_DF6_ALPHA_1E_4: f64 = 27.86;
let seed = [0x42u8; 32];
let mut rng = RngSource::from_seed(&seed);
let mut counts = [0u64; N as usize];
for _ in 0..SAMPLES {
let r = gen_range(&mut rng, 0..N);
counts[r as usize] += 1;
}
let expected = f64::from(SAMPLES) / f64::from(N);
let chi_sq: f64 = counts
.iter()
.map(|&c| {
let diff = c as f64 - expected;
diff * diff / expected
})
.sum();
assert!(
chi_sq < CHI2_CRIT_DF6_ALPHA_1E_4,
"chi² = {chi_sq} >= critical {CHI2_CRIT_DF6_ALPHA_1E_4} (α=1e-4, df=6)"
);
}