use num_traits::Float;
use strafe_type::{FloatConstraint, LogProbability64, Positive64, Probability64, Real64};
use crate::{distribution::func::bratio, traits::DPQ};
pub fn pbeta_raw(x: f64, a: f64, b: f64, lower_tail: bool, log: bool) -> f64 {
if a == 0.0 || b == 0.0 || !a.is_finite() || !b.is_finite() {
return if a == 0.0 && b == 0.0 {
if log {
-std::f64::consts::LN_2
} else {
0.5
}
} else if a == 0.0 || a / b == 0.0 {
f64::dt_1(lower_tail, log)
} else if b == 0.0 || b / a == 0.0 {
f64::dt_0(lower_tail, log)
} else {
if x < 0.5 {
f64::dt_0(lower_tail, log)
} else {
f64::dt_1(lower_tail, log)
}
};
}
if x >= 1.0 {
return f64::dt_1(lower_tail, log);
}
let x1 = 0.5 - x + 0.5;
let mut w = f64::nan();
let mut w1 = f64::nan();
let mut ierr = 0;
bratio(a, b, x, x1, &mut w, &mut w1, &mut ierr, log);
if ierr != 0 {
panic!("Error in bratio {}", ierr);
}
if lower_tail {
w
} else {
w1
}
}
pub fn pbeta<R: Into<Real64>, P1: Into<Positive64>, P2: Into<Positive64>>(
x: R,
a: P1,
b: P2,
lower_tail: bool,
) -> Probability64 {
pbeta_inner(x, a, b, lower_tail, false).into()
}
pub fn log_pbeta<R: Into<Real64>, P1: Into<Positive64>, P2: Into<Positive64>>(
x: R,
a: P1,
b: P2,
lower_tail: bool,
) -> LogProbability64 {
pbeta_inner(x, a, b, lower_tail, true).into()
}
pub fn pbeta_inner<R: Into<Real64>, P1: Into<Positive64>, P2: Into<Positive64>>(
x: R,
a: P1,
b: P2,
lower_tail: bool,
log: bool,
) -> f64 {
let x = x.into().unwrap();
let a = a.into().unwrap();
let b = b.into().unwrap();
if x <= 0.0 {
return f64::dt_0(lower_tail, log);
}
if x >= 1.0 {
return f64::dt_1(lower_tail, log);
}
pbeta_raw(x, a, b, lower_tail, log)
}