use statrs::distribution::{DiscreteCDF, Hypergeometric};
pub fn hypergeometric_pvalue(
population_size: u64,
successes_in_population: u64,
sample_size: u64,
observed_overlap: u64,
) -> f64 {
let hypergeom = Hypergeometric::new(population_size, successes_in_population, sample_size)
.expect("Failed to create hypergeometric distribution");
if observed_overlap == 0 {
return 1.0; }
hypergeom.sf(observed_overlap - 1)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hypergeometric_pvalue_scenario_1() {
let p_value = hypergeometric_pvalue(3, 1, 1, 1);
assert!((p_value - 0.3333333333333333).abs() < 1e-10);
let p_value = hypergeometric_pvalue(3, 1, 2, 1);
assert!((p_value - 0.6666666666666666).abs() < 1e-10);
let p_value = hypergeometric_pvalue(3, 1, 3, 1);
assert!((p_value - 1.0).abs() < 1e-10);
}
#[test]
fn test_hypergeometric_pvalue_scenario_2() {
let p_value = hypergeometric_pvalue(3, 2, 1, 1);
assert!((p_value - 0.6666666666666666).abs() < 1e-10);
let p_value = hypergeometric_pvalue(3, 2, 2, 2);
assert!((p_value - 0.3333333333333333).abs() < 1e-10);
}
#[test]
fn test_hypergeometric_pvalue_scenario_3() {
let p_value = hypergeometric_pvalue(10, 1, 1, 0);
assert!((p_value - 1.0).abs() < 1e-10);
}
}