use strafe_type::{FloatConstraint, LogProbability64, Probability64, Rational64, Real64};
use crate::traits::DPQ;
pub fn log1pexp(x: f64) -> f64 {
if x <= 18.0 {
return x.exp().ln_1p();
}
if x > 33.3 {
return x;
}
x + (-x).exp()
}
pub fn plogis<RE1: Into<Real64>, RE2: Into<Real64>, RA: Into<Rational64>>(
x: RE1,
location: RE2,
scale: RA,
lower_tail: bool,
) -> Probability64 {
plogis_inner(x, location, scale, lower_tail, false).into()
}
pub fn log_plogis<RE1: Into<Real64>, RE2: Into<Real64>, RA: Into<Rational64>>(
x: RE1,
location: RE2,
scale: RA,
lower_tail: bool,
) -> LogProbability64 {
plogis_inner(x, location, scale, lower_tail, true).into()
}
fn plogis_inner<RE1: Into<Real64>, RE2: Into<Real64>, RA: Into<Rational64>>(
x: RE1,
location: RE2,
scale: RA,
lower_tail: bool,
log: bool,
) -> f64 {
let mut x = x.into().unwrap();
let location = location.into().unwrap();
let scale = scale.into().unwrap();
x = (x - location) / scale;
if let Some(ret) = x.p_bounds_inf_01(lower_tail, log) {
return ret;
}
if log {
-log1pexp(if lower_tail { -x } else { x })
} else {
1.0 / (1.0 + (if lower_tail { -x } else { x }).exp())
}
}