use hashbrown::HashSet;
pub fn compute_min_uniqueness_ratio(baseline: &[f64], sample: &[f64]) -> f64 {
fn count_unique(data: &[f64]) -> usize {
let unique: HashSet<i64> = data.iter().map(|&v| (v * 1000.0) as i64).collect();
unique.len()
}
let n_baseline = baseline.len().max(1);
let n_sample = sample.len().max(1);
let ratio_baseline = count_unique(baseline) as f64 / n_baseline as f64;
let ratio_sample = count_unique(sample) as f64 / n_sample as f64;
ratio_baseline.min(ratio_sample)
}
pub const DISCRETE_MODE_THRESHOLD: f64 = 0.10;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_all_identical() {
let baseline = vec![100.0; 1000];
let sample = vec![100.0; 1000];
let ratio = compute_min_uniqueness_ratio(&baseline, &sample);
assert!(
ratio < 0.01,
"All identical values should give very low ratio"
);
}
#[test]
fn test_all_unique() {
let baseline: Vec<f64> = (0..1000).map(|i| i as f64).collect();
let sample: Vec<f64> = (1000..2000).map(|i| i as f64).collect();
let ratio = compute_min_uniqueness_ratio(&baseline, &sample);
assert!(
(ratio - 1.0).abs() < 0.01,
"All unique values should give ratio ~1.0"
);
}
#[test]
fn test_boundary_10_percent() {
let mut baseline = vec![0.0; 1000];
for i in 0..100 {
baseline[i * 10] = i as f64;
}
let sample: Vec<f64> = (0..1000).map(|i| i as f64).collect();
let ratio = compute_min_uniqueness_ratio(&baseline, &sample);
assert!(
(0.09..=0.11).contains(&ratio),
"10% unique should be near threshold, got {}",
ratio
);
}
#[test]
fn test_empty_slices() {
let empty: Vec<f64> = vec![];
let ratio = compute_min_uniqueness_ratio(&empty, &empty);
assert!(ratio == 0.0);
}
#[test]
fn test_quantization_precision() {
let baseline = vec![100.0, 100.0001, 100.0002];
let sample = vec![200.0, 200.0001, 200.0002];
let ratio = compute_min_uniqueness_ratio(&baseline, &sample);
assert!(
ratio < 0.5,
"Sub-0.001ns differences should be treated as identical"
);
}
}