use num_traits::Float;
mod f64;
pub trait Gamma: Float {
fn ln_gamma(self) -> Self {
self.gamma().ln()
}
fn gamma(self) -> Self;
fn upper_gamma_regularized(self, x: Self) -> Self {
Self::one() - self.lower_gamma_regularized(x)
}
fn upper_gamma_incomplete(self, x: Self) -> Self {
self.upper_gamma_regularized(x) * self.gamma()
}
fn lower_gamma_regularized(self, x: Self) -> Self;
fn lower_gamma_incomplete(self, x: Self) -> Self {
self.lower_gamma_regularized(x) * self.gamma()
}
}
impl Gamma for f32 {
fn gamma(self) -> Self {
Gamma::gamma(self as f64) as f32
}
fn lower_gamma_regularized(self, x: Self) -> Self {
Gamma::lower_gamma_regularized(self as f64, x as f64) as f32
}
fn ln_gamma(self) -> Self {
Gamma::ln_gamma(self as f64) as f32
}
fn upper_gamma_regularized(self, x: Self) -> Self {
Gamma::upper_gamma_regularized(self as f64, x as f64) as f32
}
fn upper_gamma_incomplete(self, x: Self) -> Self {
Gamma::upper_gamma_incomplete(self as f64, x as f64) as f32
}
fn lower_gamma_incomplete(self, x: Self) -> Self {
Gamma::lower_gamma_incomplete(self as f64, x as f64) as f32
}
}
#[cfg(test)]
mod tests {
use crate::gamma::Gamma;
#[test]
fn upper_gamma_accuracy() {
assert!((Gamma::upper_gamma_regularized(1.5, 0.5) - 0.801252f64).abs() < 0.001);
}
}