use crate::betaincinv;
pub fn betainv(p: f64, a: f64, b: f64) -> f64 {
if p.is_nan() || p < 0.0 || p > 1.0 {
return f64::NAN;
}
if a.is_nan() || a <= 0.0 || a.is_infinite() {
return f64::NAN;
}
if b.is_nan() || b <= 0.0 || b.is_infinite() {
return f64::NAN;
}
let q = betaincinv(p, a, b, true);
return q;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::betacdf;
#[test]
fn test_betainv_uniform_identity() {
assert!((betainv(0.1, 1.0, 1.0) - 0.1).abs() < 1e-15);
assert!((betainv(0.5, 1.0, 1.0) - 0.5).abs() < 1e-15);
assert!((betainv(0.9, 1.0, 1.0) - 0.9).abs() < 1e-15);
}
#[test]
fn test_betainv_known_values() {
let tol = 1e-12;
assert!((betainv(0.488, 1.0, 3.0) - 0.2).abs() < tol);
assert!((betainv(0.5, 2.0, 2.0) - 0.5).abs() < tol);
}
#[test]
fn test_betainv_roundtrip() {
let a = 2.5;
let b = 1.5;
let probabilities = [0.001, 0.1, 0.5, 0.9, 0.999];
for &p in &probabilities {
let x = betainv(p, a, b);
let p_back = betacdf(x, a, b, false);
assert!((p - p_back).abs() < 1e-10, "p: {}, x: {}, p_back: {}", p, x, p_back);
}
}
#[test]
fn test_betainv_boundaries() {
let a = 2.0;
let b = 3.0;
assert_eq!(betainv(0.0, a, b), 0.0);
assert_eq!(betainv(1.0, a, b), 1.0);
assert!(betainv(0.5, 0.0, b).is_nan());
assert!(betainv(0.5, a, 0.0).is_nan());
}
}