use crate::{math::erfc, result::TestResult};
pub fn runs(bits: &[u8]) -> TestResult {
let n = bits.len();
if n < 100 {
return TestResult::insufficient("nist::runs", "n < 100");
}
let ones: f64 = bits.iter().map(|&b| b as f64).sum();
let pi = ones / n as f64;
if (pi - 0.5).abs() >= 2.0 / (n as f64).sqrt() {
return TestResult::with_note("nist::runs", 0.0, format!("pre-test failed: π={pi:.4}"));
}
let v_n: usize = bits.windows(2).filter(|w| w[0] != w[1]).count() + 1;
let numer = (v_n as f64 - 2.0 * n as f64 * pi * (1.0 - pi)).abs();
let denom = 2.0 * (2.0 * n as f64).sqrt() * pi * (1.0 - pi);
let p_value = erfc(numer / denom);
TestResult::with_note(
"nist::runs",
p_value,
format!("n={n}, V_n={v_n}, π={pi:.4}"),
)
}