mod binomial;
mod discrete_uniform;
mod geometric;
mod hypergeometric;
mod multinomial;
mod negative_binomial;
mod poisson;
pub use binomial::Binomial;
pub use discrete_uniform::DiscreteUniform;
pub use geometric::Geometric;
pub use hypergeometric::Hypergeometric;
pub use multinomial::Multinomial;
pub use negative_binomial::NegativeBinomial;
pub use poisson::Poisson;
pub(crate) fn log_binom(n: u64, k: u64) -> f64 {
use super::continuous::special::lgamma;
if k > n {
return f64::NEG_INFINITY;
}
if k == 0 || k == n {
return 0.0;
}
let n_f = n as f64;
let k_f = k as f64;
lgamma(n_f + 1.0) - lgamma(k_f + 1.0) - lgamma(n_f - k_f + 1.0)
}
#[allow(dead_code)]
pub(crate) fn binom(n: u64, k: u64) -> f64 {
log_binom(n, k).exp()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_log_binom() {
assert!((log_binom(5, 2).exp() - 10.0).abs() < 1e-10);
assert!((log_binom(10, 5).exp() - 252.0).abs() < 1e-6);
assert!((log_binom(5, 0) - 0.0).abs() < 1e-10); assert!((log_binom(5, 5) - 0.0).abs() < 1e-10); assert!(log_binom(3, 5).is_infinite()); }
}