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::{distribution::birthday::p::pbirthday, func::lgamma};

pub fn qbirthday<P: Into<Probability64>, N1: Into<Natural64> + Copy, N2: Into<Natural64> + Copy>(
    prob: P,
    classes: N1,
    coincident: N2,
) -> Real64 {
    let k = coincident.into().unwrap() as usize;
    let c = classes.into().unwrap() as usize;
    let p = prob.into().unwrap();
    if p <= 0.0 {
        return 1.0.into();
    }
    if p >= 1.0 {
        return c.saturating_mul(k - 1).saturating_add(1).into();
    }

    let k = coincident.into().unwrap();
    let c = classes.into().unwrap();

    let mut N = (((k - 1.0) * c.ln() + lgamma(k + 1.0).unwrap() + (-(-p).ln_1p()).ln()) / k).exp();
    N = N.ceil();
    if pbirthday(N, classes, coincident).unwrap() < p {
        N += 1.0;
        while pbirthday(N, classes, coincident).unwrap() < p {
            N += 1.0;
        }
    } else if pbirthday(N - 1.0, classes, coincident).unwrap() >= p {
        N -= 1.0;
        while pbirthday(N - 1.0, classes, coincident).unwrap() >= p {
            N -= 1.0;
        }
    }
    N.into()
}