use num_traits::Float;
use strafe_type::{FloatConstraint, LogProbability64, Probability64, Real64};
use crate::traits::DPQ;
pub fn qgeom<P1: Into<Probability64>, P2: Into<Probability64>>(
p: P1,
prob: P2,
lower_tail: bool,
) -> Real64 {
let p = p.into().unwrap();
qgeom_inner(p, prob, lower_tail, false)
}
pub fn log_qgeom<LP: Into<LogProbability64>, P: Into<Probability64>>(
p: LP,
prob: P,
lower_tail: bool,
) -> Real64 {
let p = p.into().unwrap();
qgeom_inner(p, prob, lower_tail, true)
}
pub fn qgeom_inner<P: Into<Probability64>>(p: f64, prob: P, lower_tail: bool, log: bool) -> Real64 {
let prob = prob.into().unwrap();
if prob <= 0.0 {
return f64::nan().into();
}
if prob == 1.0 {
return 0.0.into();
}
if let Some(ret) = p.q_p01_boundaries(0.0, f64::infinity(), lower_tail, log) {
return ret.into();
}
(p.dt_clog(lower_tail, log) / (-prob).ln_1p() - 1.0 - 1e-12)
.ceil()
.max(0.0)
.into()
}