use core::fmt;
use crate::FloatScalar;
mod gamma_fn;
mod digamma_fn;
mod beta_fn;
mod incgamma;
mod erf_fn;
mod betainc;
#[cfg(test)]
mod tests;
pub use gamma_fn::{gamma, lgamma};
pub use digamma_fn::digamma;
pub use beta_fn::{beta, lbeta};
pub use incgamma::{gamma_inc, gamma_inc_upper};
pub use erf_fn::{erf, erfc};
pub use betainc::betainc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SpecialError {
ConvergenceFailure,
DomainError,
}
impl fmt::Display for SpecialError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ConvergenceFailure => write!(f, "series/continued fraction did not converge"),
Self::DomainError => write!(f, "input outside function domain"),
}
}
}
pub(crate) const LANCZOS_G: f64 = 7.0;
pub(crate) const LANCZOS_COEFFS: [f64; 9] = [
0.99999999999980993,
676.5203681218851,
-1259.1392167224028,
771.32342877765313,
-176.61502916214059,
12.507343278686905,
-0.13857109526572012,
9.9843695780195716e-6,
1.5056327351493116e-7,
];
#[inline]
pub(crate) fn lanczos_sum<T: FloatScalar>(z: T) -> T {
let mut sum = T::from(LANCZOS_COEFFS[0]).unwrap();
for (i, &c) in LANCZOS_COEFFS[1..].iter().enumerate() {
let ci = T::from(c).unwrap();
let denom = z + T::from(i + 1).unwrap();
sum = sum + ci / denom;
}
sum
}