use num_traits::Float;
use strafe_type::{FloatConstraint, Positive64, Rational64, Real64};
use crate::{distribution::pois::dpois_raw, traits::DPQ};
pub fn dgamma<RE: Into<Real64>, P: Into<Positive64>, RA: Into<Rational64>>(
x: RE,
shape: P,
scale: RA,
log: bool,
) -> Real64 {
let x = x.into().unwrap();
let shape = shape.into().unwrap();
let scale = scale.into().unwrap();
let mut pr = 0.0;
if x < 0.0 {
return f64::d_0(log).into();
}
if shape == 0.0 {
let ret = if x == 0.0 {
f64::infinity()
} else {
f64::d_0(log)
};
return ret.into();
}
if x == 0.0 {
if shape < 1.0 {
return f64::infinity().into();
}
if shape > 1.0 {
return f64::d_0(log).into();
}
return if log { -scale.ln() } else { (1.0) / scale }.into();
}
if shape < 1.0 {
pr = dpois_raw(shape, x / scale, log);
return if log {
pr + if (shape / x).is_finite() {
(shape / x).ln()
} else {
shape.ln() - x.ln()
}
} else {
pr * shape / x
}
.into();
}
pr = dpois_raw(shape - 1.0, x / scale, log);
if log { pr - scale.ln() } else { pr / scale }.into()
}