@@ -2,6 +2,7 @@ use crate::distribution::{Discrete, DiscreteCDF};
22use crate :: prec;
33use crate :: statistics:: * ;
44use 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
158186impl Min < u64 > for Geometric {
0 commit comments