Skip to content

Commit af1ad0f

Browse files
natazielGoose
authored andcommitted
add specialised inverse cdf implementation for geometric distribution
1 parent 8a45d47 commit af1ad0f

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

src/distribution/geometric.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::distribution::{Discrete, DiscreteCDF};
22
use crate::prec;
33
use crate::statistics::*;
44
use core::f64;
5+
use num_traits::{One, Zero};
56

67
/// Implements the
78
/// [Geometric](https://en.wikipedia.org/wiki/Geometric_distribution)
@@ -153,6 +154,33 @@ impl DiscreteCDF<u64, f64> for Geometric {
153154
((-self.p).ln_1p() * (x as f64)).exp()
154155
}
155156
}
157+
158+
/// Calculates the inverse cumulative distribution function for the
159+
/// geometric distribution at `x`.
160+
/// In other languages, such as R, this is known as the the quantile function.
161+
///
162+
/// # Formula
163+
///
164+
/// ```text
165+
/// p = ceil(log(1-x)/log(1-p))
166+
/// ```
167+
///
168+
/// # Panics
169+
/// panics if provided `x` not on interval [0.0, 1.0]
170+
fn inverse_cdf(&self, x: f64) -> u64 {
171+
// ceil(log(1-x)/log(1-self.p)) = ceil(log1p(-x)/log1p(-self.p))
172+
// = ceil((-x).ln_1p()/(-self.p).ln_1p())
173+
// = ((-x).ln_1p()/(-self.p).ln_1p()).ceil()
174+
if x <= self.cdf(self.min()) {
175+
return self.min();
176+
} else if x == <f64>::one() {
177+
return self.max();
178+
} else if !(<f64>::zero()..=<f64>::one()).contains(&x) {
179+
std::panic!("p must be on [0, 1]")
180+
}
181+
182+
((-x).ln_1p() / (-self.p).ln_1p()).ceil() as u64
183+
}
156184
}
157185

158186
impl Min<u64> for Geometric {

0 commit comments

Comments
 (0)