#![allow(unused_assignments)]
use crate::dpq::r_dt_0;
use crate::dpq::r_dt_1;
use crate::lgammafn;
use crate::libc::fabs;
use crate::libc::DBL_EPSILON;
use crate::nmath::ml_warn_return_nan;
use crate::nmath::r_finite;
use crate::nmath::M_SQRT_2dPI;
use crate::nmath::DBL_MIN_EXP;
use crate::nmath::M_LN_SQRT_PI;
use crate::pbeta;
use crate::pnorm;
use crate::pt;
use crate::rmath::M_LN2;
use libm::exp;
use libm::expm1;
use libm::fmin;
use libm::log1p;
use libm::pow;
use libm::sqrt;
const ITRMAX: usize = 1_000;
const ERRMAX: f64 = 1e-12;
pub fn pnt(t: f64, df: f64, ncp: f64, mut lower_tail: bool, log_p: bool) -> f64 {
let mut albeta = 0.0;
let mut a = 0.0;
let mut b = 0.0;
let mut del = 0.0;
let mut errbd = 0.0;
let mut lambda = 0.0;
let mut rxb = 0.0;
let mut tt = 0.0;
let mut x = 0.0;
let mut geven = 0.0;
let mut godd = 0.0;
let mut p = 0.0;
let mut q = 0.0;
let mut s = 0.0;
let mut tnc = 0.0;
let mut xeven = 0.0;
let mut xodd = 0.0;
let mut negdel = false;
if df <= 0.0 {
return ml_warn_return_nan();
}
if ncp == 0.0 {
return pt(t, df, lower_tail, log_p);
}
if !r_finite(t) {
if t < 0.0 {
return r_dt_0(lower_tail, log_p);
} else {
return r_dt_1(lower_tail, log_p);
}
}
if t >= 0.0 {
negdel = false;
tt = t;
del = ncp;
} else {
if ncp > 40.0 && (!log_p || !lower_tail) {
return r_dt_0(lower_tail, log_p);
}
negdel = true;
tt = -t;
del = -ncp;
}
if df > 4e5 || del * del > 2.0 * M_LN2 * (-DBL_MIN_EXP) {
let s = 1.0 / (4.0 * df);
return pnorm(
tt * (1.0 - s),
del,
sqrt(1.0 + tt * tt * 2.0 * s),
lower_tail != negdel,
log_p,
);
}
x = t * t;
rxb = df / (x + df);
x = x / (x + df);
if x > 0.0 {
lambda = del * del;
p = 0.5 * exp(-0.5 * lambda);
if p == 0.0 {
println!("pnt: underflow occurred");
println!("pnt: value out of range");
return r_dt_0(lower_tail, log_p);
}
q = M_SQRT_2dPI * p * del;
s = 0.5 - p;
if s < 1e-7 {
s = -0.5 * expm1(-0.5 * lambda);
}
a = 0.5;
b = 0.5 * df;
rxb = pow(rxb, b);
albeta = M_LN_SQRT_PI + lgammafn(b) - lgammafn(0.5 + b);
xodd = pbeta(x, a, b, true, false);
godd = 2.0 * rxb * exp(a * x.ln() - albeta);
tnc = b * x;
xeven = if tnc < DBL_EPSILON { tnc } else { 1.0 - rxb };
geven = tnc * rxb;
tnc = p * xodd + q * xeven;
for it in 1..=ITRMAX {
a += 1.0;
xodd -= godd;
xeven -= geven;
godd *= x * (a + b - 1.0) / a;
geven *= x * (a + b - 0.5) / (a + 0.5);
p *= lambda / (2.0 * it as f64);
q *= lambda / (2.0 * it as f64 + 1.0);
tnc += p * xodd + q * xeven;
s -= p;
if s < 1e-10 {
println!("pnt: full precision may not have been achieved");
finis(del, &mut tnc);
break;
}
if s <= 0.0 && it > 1 {
finis(del, &mut tnc);
break;
}
errbd = 2.0 * s * (xodd - godd);
if fabs(errbd) < ERRMAX {
finis(del, &mut tnc);
break;
}
}
println!("pnt: convergence failed");
} else {
tnc = 0.0;
}
lower_tail = lower_tail != negdel;
if tnc > 1.0 - 1e-10 && lower_tail {
println!("pnt: full precision may not have been achieved");
}
r_dt_val(fmin(tnc, 1.0), lower_tail, log_p)
}
fn finis(del: f64, tnc: &mut f64) {
*tnc += pnorm(-del, 0.0, 1.0, true, false);
}
pub fn r_dt_val(x: f64, lower_tail: bool, log_p: bool) -> f64 {
if lower_tail {
r_d_val(x, log_p)
} else {
r_d_clog(x, log_p)
}
}
pub fn r_d_val(x: f64, log_p: bool) -> f64 {
if log_p {
x.ln()
} else {
x
}
}
pub fn r_d_clog(p: f64, log_p: bool) -> f64 {
if log_p {
log1p(-p)
} else {
0.5 - p + 0.5
}
}