use crate::Real;
use crate::error::KrigingError;
const PROB_EPSILON: Real = 1e-9;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Probability(Real);
impl Probability {
pub fn try_new(p: Real) -> Result<Self, KrigingError> {
if !p.is_finite() || p <= 0.0 || p >= 1.0 {
return Err(KrigingError::InvalidInput(format!(
"probability must be finite and in (0, 1), got {p}"
)));
}
Ok(Self(p))
}
#[inline]
pub fn from_known_in_range(p: Real) -> Self {
debug_assert!(
p.is_finite() && p > 0.0 && p < 1.0,
"probability must be in (0, 1)"
);
Self(p)
}
#[inline]
pub fn get(self) -> Real {
self.0
}
}
pub fn clamp_probability(p: Real) -> Real {
p.clamp(PROB_EPSILON, 1.0 - PROB_EPSILON)
}
#[inline]
pub fn logit(p: Probability) -> Real {
let p = p.get();
(p / (1.0 - p)).ln()
}
pub fn logit_clamped(p: Real) -> Real {
logit(Probability::from_known_in_range(clamp_probability(p)))
}
pub fn logistic(x: Real) -> Real {
1.0 / (1.0 + (-x).exp())
}