use num_traits::Float;
use strafe_type::{FloatConstraint, LogProbability64, Positive64, Probability64, Real64};
use crate::{
distribution::norm::{log_qnorm, qnorm},
traits::DPQ,
};
pub fn qlnorm<PR: Into<Probability64>, R: Into<Real64>, PO: Into<Positive64>>(
p: PR,
meanlog: R,
sdlog: PO,
lower_tail: bool,
) -> Real64 {
let p = p.into().unwrap();
qlnorm_inner(p, meanlog, sdlog, lower_tail, false)
}
pub fn log_qlnorm<LP: Into<LogProbability64>, R: Into<Real64>, P: Into<Positive64>>(
p: LP,
meanlog: R,
sdlog: P,
lower_tail: bool,
) -> Real64 {
let p = p.into().unwrap();
qlnorm_inner(p, meanlog, sdlog, lower_tail, true)
}
fn qlnorm_inner<R: Into<Real64>, P: Into<Positive64>>(
p: f64,
meanlog: R,
sdlog: P,
lower_tail: bool,
log: bool,
) -> Real64 {
if let Some(ret) = p.q_p01_boundaries(0.0, f64::infinity(), lower_tail, log) {
return ret.into();
}
let ret = if log {
log_qnorm(p, meanlog, sdlog, lower_tail).unwrap().exp()
} else {
qnorm(p, meanlog, sdlog, lower_tail).unwrap().exp()
};
ret.into()
}