use thermite::{
element::{FloatElement, FloatElementWithBits},
math::{
CoreMathWithPolicy as _, TranscendentalMathWithPolicy as _,
policy::{Policy, PrecisionPolicy},
},
prelude::*,
};
use crate::specialized::SpecializedSpecialMath;
#[inline(always)]
pub fn probit_acklam<P, E, V, const REFINE: bool>(p_in: V, a: &[E; 6], b: &[E; 6], c: &[E; 6], d: &[E; 5]) -> V
where
P: Policy,
E: FloatElementWithBits,
V: FloatVectorWithBits<Element = E> + SpecializedSpecialMath<E>,
{
let p = p_in.min(V::ONE - p_in); let is_tail = p.cmp_lt(V::splat(<E as FloatElement>::ConstRatio::<97, 4000>::VALUE));
let q = p - V::HALF;
let mut y = q * (q * q).poly_rational_p::<P, _, _>(a, b);
if const { P::POLICY.avoid_branching } || is_tail.any() {
let q = (-V::TWO * p.ln_p::<P>()).sqrt();
let t = q.poly_rational_p::<P, _, _>(c, d);
y = is_tail.select(t, y);
}
let mut x = y.copysign(p_in - V::HALF);
if const { REFINE && P::POLICY.precision.ge(PrecisionPolicy::Best) } {
let e = <V as SpecializedSpecialMath<E>>::erfc::<P>(x * -V::FRAC_1_SQRT_2).mul_adde(V::HALF, -p_in);
let u = e * V::SQRT_TAU * (x * x * V::HALF).exp_p::<P>();
x -= u / x.mul_adde(u * V::HALF, V::ONE);
}
x
}