1use crate::distribution::{Discrete, DiscreteCDF};
2use crate::function::{factorial, gamma};
3use crate::statistics::*;
4use std::f64;
5
6#[derive(Copy, Clone, PartialEq, Debug)]
21pub struct Poisson {
22 lambda: f64,
23}
24
25#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
27#[non_exhaustive]
28pub enum PoissonError {
29 LambdaInvalid,
31}
32
33impl std::fmt::Display for PoissonError {
34 #[cfg_attr(coverage_nightly, coverage(off))]
35 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
36 match self {
37 PoissonError::LambdaInvalid => write!(f, "Lambda is NaN, zero or less than zero"),
38 }
39 }
40}
41
42impl std::error::Error for PoissonError {}
43
44impl Poisson {
45 pub fn new(lambda: f64) -> Result<Poisson, PoissonError> {
64 if lambda.is_nan() || lambda <= 0.0 {
65 Err(PoissonError::LambdaInvalid)
66 } else {
67 Ok(Poisson { lambda })
68 }
69 }
70
71 pub fn lambda(&self) -> f64 {
82 self.lambda
83 }
84}
85
86impl std::fmt::Display for Poisson {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 write!(f, "Pois({})", self.lambda)
89 }
90}
91
92#[cfg(feature = "rand")]
93#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
94impl ::rand::distributions::Distribution<u64> for Poisson {
95 fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> u64 {
101 sample_unchecked(rng, self.lambda) as u64
102 }
103}
104
105#[cfg(feature = "rand")]
106#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
107impl ::rand::distributions::Distribution<f64> for Poisson {
108 fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
114 sample_unchecked(rng, self.lambda)
115 }
116}
117
118impl DiscreteCDF<u64, f64> for Poisson {
119 fn cdf(&self, x: u64) -> f64 {
130 gamma::gamma_ur(x as f64 + 1.0, self.lambda)
131 }
132
133 fn sf(&self, x: u64) -> f64 {
144 gamma::gamma_lr(x as f64 + 1.0, self.lambda)
145 }
146}
147
148impl Min<u64> for Poisson {
149 fn min(&self) -> u64 {
158 0
159 }
160}
161
162impl Max<u64> for Poisson {
163 fn max(&self) -> u64 {
172 u64::MAX
173 }
174}
175
176impl Distribution<f64> for Poisson {
177 fn mean(&self) -> Option<f64> {
187 Some(self.lambda)
188 }
189
190 fn variance(&self) -> Option<f64> {
200 Some(self.lambda)
201 }
202
203 fn entropy(&self) -> Option<f64> {
213 Some(
214 0.5 * (2.0 * f64::consts::PI * f64::consts::E * self.lambda).ln()
215 - 1.0 / (12.0 * self.lambda)
216 - 1.0 / (24.0 * self.lambda * self.lambda)
217 - 19.0 / (360.0 * self.lambda * self.lambda * self.lambda),
218 )
219 }
220
221 fn skewness(&self) -> Option<f64> {
231 Some(1.0 / self.lambda.sqrt())
232 }
233}
234
235impl Median<f64> for Poisson {
236 fn median(&self) -> f64 {
246 (self.lambda + 1.0 / 3.0 - 0.02 / self.lambda).floor()
247 }
248}
249
250impl Mode<Option<u64>> for Poisson {
251 fn mode(&self) -> Option<u64> {
261 Some(self.lambda.floor() as u64)
262 }
263}
264
265impl Discrete<u64, f64> for Poisson {
266 fn pmf(&self, x: u64) -> f64 {
277 (-self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x)).exp()
278 }
279
280 fn ln_pmf(&self, x: u64) -> f64 {
292 -self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x)
293 }
294}
295
296#[cfg(feature = "rand")]
302#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
303pub fn sample_unchecked<R: ::rand::Rng + ?Sized>(rng: &mut R, lambda: f64) -> f64 {
304 if lambda < 30.0 {
305 let limit = (-lambda).exp();
306 let mut count = 0.0;
307 let mut product: f64 = rng.gen();
308 while product >= limit {
309 count += 1.0;
310 product *= rng.gen::<f64>();
311 }
312 count
313 } else {
314 let c = 0.767 - 3.36 / lambda;
315 let beta = f64::consts::PI / (3.0 * lambda).sqrt();
316 let alpha = beta * lambda;
317 let k = c.ln() - lambda - beta.ln();
318
319 loop {
320 let u: f64 = rng.gen();
321 let x = (alpha - ((1.0 - u) / u).ln()) / beta;
322 let n = (x + 0.5).floor();
323 if n < 0.0 {
324 continue;
325 }
326
327 let v: f64 = rng.gen();
328 let y = alpha - beta * x;
329 let temp = 1.0 + y.exp();
330 let lhs = y + (v / (temp * temp)).ln();
331 let rhs = k + n * lambda.ln() - factorial::ln_factorial(n as u64);
332 if lhs <= rhs {
333 return n;
334 }
335 }
336 }
337}
338
339#[rustfmt::skip]
340#[cfg(test)]
341mod tests {
342 use super::*;
343 use crate::distribution::internal::*;
344 use crate::testing_boiler;
345
346 testing_boiler!(lambda: f64; Poisson; PoissonError);
347
348 #[test]
349 fn test_create() {
350 create_ok(1.5);
351 create_ok(5.4);
352 create_ok(10.8);
353 }
354
355 #[test]
356 fn test_bad_create() {
357 create_err(f64::NAN);
358 create_err(-1.5);
359 create_err(0.0);
360 }
361
362 #[test]
363 fn test_mean() {
364 let mean = |x: Poisson| x.mean().unwrap();
365 test_exact(1.5, 1.5, mean);
366 test_exact(5.4, 5.4, mean);
367 test_exact(10.8, 10.8, mean);
368 }
369
370 #[test]
371 fn test_variance() {
372 let variance = |x: Poisson| x.variance().unwrap();
373 test_exact(1.5, 1.5, variance);
374 test_exact(5.4, 5.4, variance);
375 test_exact(10.8, 10.8, variance);
376 }
377
378 #[test]
379 fn test_entropy() {
380 let entropy = |x: Poisson| x.entropy().unwrap();
381 test_absolute(1.5, 1.531959153102376331946, 1e-15, entropy);
382 test_absolute(5.4, 2.244941839577643504608, 1e-15, entropy);
383 test_exact(10.8, 2.600596429676975222694, entropy);
384 }
385
386 #[test]
387 fn test_skewness() {
388 let skewness = |x: Poisson| x.skewness().unwrap();
389 test_absolute(1.5, 0.8164965809277260327324, 1e-15, skewness);
390 test_absolute(5.4, 0.4303314829119352094644, 1e-16, skewness);
391 test_absolute(10.8, 0.3042903097250922852539, 1e-16, skewness);
392 }
393
394 #[test]
395 fn test_median() {
396 let median = |x: Poisson| x.median();
397 test_exact(1.5, 1.0, median);
398 test_exact(5.4, 5.0, median);
399 test_exact(10.8, 11.0, median);
400 }
401
402 #[test]
403 fn test_mode() {
404 let mode = |x: Poisson| x.mode().unwrap();
405 test_exact(1.5, 1, mode);
406 test_exact(5.4, 5, mode);
407 test_exact(10.8, 10, mode);
408 }
409
410 #[test]
411 fn test_min_max() {
412 let min = |x: Poisson| x.min();
413 let max = |x: Poisson| x.max();
414 test_exact(1.5, 0, min);
415 test_exact(5.4, 0, min);
416 test_exact(10.8, 0, min);
417 test_exact(1.5, u64::MAX, max);
418 test_exact(5.4, u64::MAX, max);
419 test_exact(10.8, u64::MAX, max);
420 }
421
422 #[test]
423 fn test_pmf() {
424 let pmf = |arg: u64| move |x: Poisson| x.pmf(arg);
425 test_absolute(1.5, 0.334695240222645000000000000000, 1e-15, pmf(1));
426 test_absolute(1.5, 0.000003545747740570180000000000, 1e-20, pmf(10));
427 test_absolute(1.5, 0.000000000000000304971208961018, 1e-30, pmf(20));
428 test_absolute(5.4, 0.024389537090108400000000000000, 1e-17, pmf(1));
429 test_absolute(5.4, 0.026241240591792300000000000000, 1e-16, pmf(10));
430 test_absolute(5.4, 0.000000825202200316548000000000, 1e-20, pmf(20));
431 test_absolute(10.8, 0.000220314636840657000000000000, 1e-18, pmf(1));
432 test_absolute(10.8, 0.121365183659420000000000000000, 1e-15, pmf(10));
433 test_absolute(10.8, 0.003908139778574110000000000000, 1e-16, pmf(20));
434 }
435
436 #[test]
437 fn test_ln_pmf() {
438 let ln_pmf = |arg: u64| move |x: Poisson| x.ln_pmf(arg);
439 test_absolute(1.5, -1.09453489189183485135413967177, 1e-15, ln_pmf(1));
440 test_absolute(1.5, -12.5497614919938728510400000000, 1e-14, ln_pmf(10));
441 test_absolute(1.5, -35.7263142985901000000000000000, 1e-13, ln_pmf(20));
442 test_exact(5.4, -3.71360104642977159156055355910, ln_pmf(1));
443 test_absolute(5.4, -3.64042303737322774736223038530, 1e-15, ln_pmf(10));
444 test_absolute(5.4, -14.0076373893489089949388000000, 1e-14, ln_pmf(20));
445 test_absolute(10.8, -8.42045386586982559781714423000, 1e-14, ln_pmf(1));
446 test_absolute(10.8, -2.10895123177378079525424989992, 1e-14, ln_pmf(10));
447 test_absolute(10.8, -5.54469377815000936289610059500, 1e-14, ln_pmf(20));
448 }
449
450 #[test]
451 fn test_cdf() {
452 let cdf = |arg: u64| move |x: Poisson| x.cdf(arg);
453 test_absolute(1.5, 0.5578254003710750000000, 1e-15, cdf(1));
454 test_absolute(1.5, 0.9999994482467640000000, 1e-15, cdf(10));
455 test_exact(1.5, 1.0, cdf(20));
456 test_absolute(5.4, 0.0289061180327211000000, 1e-16, cdf(1));
457 test_absolute(5.4, 0.9774863006897650000000, 1e-15, cdf(10));
458 test_absolute(5.4, 0.9999997199928290000000, 1e-15, cdf(20));
459 test_absolute(10.8, 0.0002407141402518290000, 1e-16, cdf(1));
460 test_absolute(10.8, 0.4839692359955690000000, 1e-15, cdf(10));
461 test_absolute(10.8, 0.9961800769608090000000, 1e-15, cdf(20));
462 }
463
464 #[test]
465 fn test_sf() {
466 let sf = |arg: u64| move |x: Poisson| x.sf(arg);
467 test_absolute(1.5, 0.44217459962892536, 1e-15, sf(1));
468 test_absolute(1.5, 0.0000005517532358246565, 1e-15, sf(10));
469 test_absolute(1.5, 2.3372210700347092e-17, 1e-15, sf(20));
470 test_absolute(5.4, 0.971093881967279, 1e-16, sf(1));
471 test_absolute(5.4, 0.022513699310235582, 1e-15, sf(10));
472 test_absolute(5.4, 0.0000002800071708975261, 1e-15, sf(20));
473 test_absolute(10.8, 0.9997592858597482, 1e-16, sf(1));
474 test_absolute(10.8, 0.5160307640044303, 1e-15, sf(10));
475 test_absolute(10.8, 0.003819923039191422, 1e-15, sf(20));
476 }
477
478 #[test]
479 fn test_discrete() {
480 test::check_discrete_distribution(&create_ok(0.3), 10);
481 test::check_discrete_distribution(&create_ok(4.5), 30);
482 }
483}