r2rs-nmath 0.1.1

Statistics programming for Rust based on R's nmath package
Documentation
// "Whatever you do, work at it with all your heart, as working for the Lord,
// not for human masters, since you know that you will receive an inheritance
// from the Lord as a reward. It is the Lord Christ you are serving."
// (Col 3:23-24)

use strafe_type::{FloatConstraint, Natural64, Probability64, Real64};

use crate::func::lgamma;

pub fn pbirthday<R: Into<Real64>, N1: Into<Natural64>, N2: Into<Natural64>>(
    q: R,
    classes: N1,
    coincident: N2,
) -> Probability64 {
    let n = q.into().unwrap();
    let k = coincident.into().unwrap();
    let c = classes.into().unwrap();

    if k < 2.0 {
        1.0.into()
    } else if k == 2.0 {
        let mut lhs = c as isize;
        let mut rhs = c as isize - n as isize + 1;
        if lhs > rhs {
            std::mem::swap(&mut lhs, &mut rhs);
        }
        let temp = 1.0
            - (lhs..rhs)
                .map(|c1| c1 as f64 / c)
                .fold(1.0, |acc, c1| acc * c1);
        temp.into()
    } else if k > n {
        0.0.into()
    } else if n > c * (k - 1.0) {
        1.0.into()
    } else {
        let LHS = n * (-n / (c * k)).exp() / (1.0 - n / (c * (k + 1.0))).powf(1.0 / k);
        let lxx = k * LHS.ln() - (k - 1.0) * c.ln() - lgamma(k + 1.0).unwrap();
        (-(-lxx.exp()).exp_m1()).into()
    }
}