1use crate::Real;
2use crate::error::KrigingError;
3
4const PROB_EPSILON: Real = 1e-9;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct Probability(Real);
9
10impl Probability {
11 pub fn try_new(p: Real) -> Result<Self, KrigingError> {
14 if !p.is_finite() || p <= 0.0 || p >= 1.0 {
15 return Err(KrigingError::InvalidInput(format!(
16 "probability must be finite and in (0, 1), got {p}"
17 )));
18 }
19 Ok(Self(p))
20 }
21
22 #[inline]
24 pub fn from_known_in_range(p: Real) -> Self {
25 debug_assert!(
26 p.is_finite() && p > 0.0 && p < 1.0,
27 "probability must be in (0, 1)"
28 );
29 Self(p)
30 }
31
32 #[inline]
33 pub fn get(self) -> Real {
34 self.0
35 }
36}
37
38pub fn clamp_probability(p: Real) -> Real {
39 p.clamp(PROB_EPSILON, 1.0 - PROB_EPSILON)
40}
41
42#[inline]
44pub fn logit(p: Probability) -> Real {
45 let p = p.get();
46 (p / (1.0 - p)).ln()
47}
48
49pub fn logit_clamped(p: Real) -> Real {
51 logit(Probability::from_known_in_range(clamp_probability(p)))
52}
53
54pub fn logistic(x: Real) -> Real {
55 1.0 / (1.0 + (-x).exp())
56}