use crate::{
math::{erfc, fft_magnitudes},
result::TestResult,
};
use std::f64::consts::SQRT_2;
pub fn spectral(bits: &[u8]) -> TestResult {
let n = bits.len();
if n < 1_000 {
return TestResult::insufficient("nist::spectral", "n < 1000");
}
let x: Vec<f64> = bits
.iter()
.map(|&b| if b == 1 { 1.0 } else { -1.0 })
.collect();
let mags = fft_magnitudes(&x);
let threshold = (n as f64 * 0.05_f64.ln().abs()).sqrt();
let n0 = 0.95 * n as f64 / 2.0; let n1 = mags[..n / 2].iter().filter(|&&m| m < threshold).count() as f64;
let d = (n1 - n0) / (n as f64 * 0.95 * 0.05 / 4.0).sqrt();
let p_value = erfc(d.abs() / SQRT_2);
TestResult::with_note(
"nist::spectral",
p_value,
format!("n={n}, N₀={n0:.1}, N₁={n1}, T={threshold:.4}, d={d:.4}"),
)
}