use num_traits::Float;
use strafe_type::{FloatConstraint, LogProbability64, Probability64, Rational64, Real64};
use crate::traits::DPQ;
pub fn qlogis<P: Into<Probability64>, RE: Into<Real64>, RA: Into<Rational64>>(
p: P,
location: RE,
scale: RA,
lower_tail: bool,
) -> Real64 {
let p = p.into().unwrap();
qlogis_inner(p, location, scale, lower_tail, false)
}
pub fn log_qlogis<LP: Into<LogProbability64>, RE: Into<Real64>, RA: Into<Rational64>>(
p: LP,
location: RE,
scale: RA,
lower_tail: bool,
) -> Real64 {
let p = p.into().unwrap();
qlogis_inner(p, location, scale, lower_tail, true)
}
pub fn qlogis_inner<RE: Into<Real64>, RA: Into<Rational64>>(
mut p: f64,
location: RE,
scale: RA,
lower_tail: bool,
log: bool,
) -> Real64 {
let location = location.into().unwrap();
let scale = scale.into().unwrap();
if let Some(ret) = p.q_p01_boundaries(f64::NEG_INFINITY, f64::infinity(), lower_tail, log) {
return ret.into();
}
if scale == 0.0 {
return location.into();
}
p = if log {
if lower_tail {
p - p.log1_exp()
} else {
p.log1_exp() - p
}
} else if lower_tail {
p / (1.0 - p).ln()
} else {
((1.0 - p) / p).ln()
};
(location + scale * p).into()
}