1use crate::distribution::{Discrete, DiscreteCDF};
2use crate::function::{factorial, gamma};
3use crate::statistics::*;
4use crate::{Result, StatsError};
5use rand::Rng;
6use std::f64;
7use std::u64;
8
9#[derive(Debug, Copy, Clone, PartialEq)]
24pub struct Poisson {
25 lambda: f64,
26}
27
28impl Poisson {
29 pub fn new(lambda: f64) -> Result<Poisson> {
48 if lambda.is_nan() || lambda <= 0.0 {
49 Err(StatsError::BadParams)
50 } else {
51 Ok(Poisson { lambda })
52 }
53 }
54
55 pub fn lambda(&self) -> f64 {
66 self.lambda
67 }
68}
69
70impl ::rand::distributions::Distribution<f64> for Poisson {
71 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
77 sample_unchecked(rng, self.lambda)
78 }
79}
80
81impl DiscreteCDF<u64, f64> for Poisson {
82 fn cdf(&self, x: u64) -> f64 {
93 gamma::gamma_ur(x as f64 + 1.0, self.lambda)
94 }
95
96 fn sf(&self, x: u64) -> f64 {
107 gamma::gamma_lr(x as f64 + 1.0, self.lambda)
108 }
109}
110
111impl Min<u64> for Poisson {
112 fn min(&self) -> u64 {
121 0
122 }
123}
124
125impl Max<u64> for Poisson {
126 fn max(&self) -> u64 {
135 u64::MAX
136 }
137}
138
139impl Distribution<f64> for Poisson {
140 fn mean(&self) -> Option<f64> {
150 Some(self.lambda)
151 }
152 fn variance(&self) -> Option<f64> {
162 Some(self.lambda)
163 }
164 fn entropy(&self) -> Option<f64> {
174 Some(
175 0.5 * (2.0 * f64::consts::PI * f64::consts::E * self.lambda).ln()
176 - 1.0 / (12.0 * self.lambda)
177 - 1.0 / (24.0 * self.lambda * self.lambda)
178 - 19.0 / (360.0 * self.lambda * self.lambda * self.lambda),
179 )
180 }
181 fn skewness(&self) -> Option<f64> {
191 Some(1.0 / self.lambda.sqrt())
192 }
193}
194
195impl Median<f64> for Poisson {
196 fn median(&self) -> f64 {
206 (self.lambda + 1.0 / 3.0 - 0.02 / self.lambda).floor()
207 }
208}
209
210impl Mode<Option<u64>> for Poisson {
211 fn mode(&self) -> Option<u64> {
221 Some(self.lambda.floor() as u64)
222 }
223}
224
225impl Discrete<u64, f64> for Poisson {
226 fn pmf(&self, x: u64) -> f64 {
237 (-self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x as u64)).exp()
238 }
239
240 fn ln_pmf(&self, x: u64) -> f64 {
252 -self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x as u64)
253 }
254}
255pub fn sample_unchecked<R: Rng + ?Sized>(rng: &mut R, lambda: f64) -> f64 {
261 if lambda < 30.0 {
262 let limit = (-lambda).exp();
263 let mut count = 0.0;
264 let mut product: f64 = rng.gen();
265 while product >= limit {
266 count += 1.0;
267 product *= rng.gen::<f64>();
268 }
269 count
270 } else {
271 let c = 0.767 - 3.36 / lambda;
272 let beta = f64::consts::PI / (3.0 * lambda).sqrt();
273 let alpha = beta * lambda;
274 let k = c.ln() - lambda - beta.ln();
275
276 loop {
277 let u: f64 = rng.gen();
278 let x = (alpha - ((1.0 - u) / u).ln()) / beta;
279 let n = (x + 0.5).floor();
280 if n < 0.0 {
281 continue;
282 }
283
284 let v: f64 = rng.gen();
285 let y = alpha - beta * x;
286 let temp = 1.0 + y.exp();
287 let lhs = y + (v / (temp * temp)).ln();
288 let rhs = k + n * lambda.ln() - factorial::ln_factorial(n as u64);
289 if lhs <= rhs {
290 return n;
291 }
292 }
293 }
294}
295
296#[rustfmt::skip]
297#[cfg(all(test, feature = "nightly"))]
298mod tests {
299 use std::fmt::Debug;
300 use crate::statistics::*;
301 use crate::distribution::{DiscreteCDF, Discrete, Poisson};
302 use crate::distribution::internal::*;
303 use crate::consts::ACC;
304
305 fn try_create(lambda: f64) -> Poisson {
306 let n = Poisson::new(lambda);
307 assert!(n.is_ok());
308 n.unwrap()
309 }
310
311 fn create_case(lambda: f64) {
312 let n = try_create(lambda);
313 assert_eq!(lambda, n.lambda());
314 }
315
316 fn bad_create_case(lambda: f64) {
317 let n = Poisson::new(lambda);
318 assert!(n.is_err());
319 }
320
321 fn get_value<T, F>(lambda: f64, eval: F) -> T
322 where T: PartialEq + Debug,
323 F: Fn(Poisson) -> T
324 {
325 let n = try_create(lambda);
326 eval(n)
327 }
328
329 fn test_case<T, F>(lambda: f64, expected: T, eval: F)
330 where T: PartialEq + Debug,
331 F: Fn(Poisson) -> T
332 {
333 let x = get_value(lambda, eval);
334 assert_eq!(expected, x);
335 }
336
337 fn test_almost<F>(lambda: f64, expected: f64, acc: f64, eval: F)
338 where F: Fn(Poisson) -> f64
339 {
340 let x = get_value(lambda, eval);
341 assert_almost_eq!(expected, x, acc);
342 }
343
344 #[test]
345 fn test_create() {
346 create_case(1.5);
347 create_case(5.4);
348 create_case(10.8);
349 }
350
351 #[test]
352 fn test_bad_create() {
353 bad_create_case(f64::NAN);
354 bad_create_case(-1.5);
355 bad_create_case(0.0);
356 }
357
358 #[test]
359 fn test_mean() {
360 let mean = |x: Poisson| x.mean().unwrap();
361 test_case(1.5, 1.5, mean);
362 test_case(5.4, 5.4, mean);
363 test_case(10.8, 10.8, mean);
364 }
365
366 #[test]
367 fn test_variance() {
368 let variance = |x: Poisson| x.variance().unwrap();
369 test_case(1.5, 1.5, variance);
370 test_case(5.4, 5.4, variance);
371 test_case(10.8, 10.8, variance);
372 }
373
374 #[test]
375 fn test_entropy() {
376 let entropy = |x: Poisson| x.entropy().unwrap();
377 test_almost(1.5, 1.531959153102376331946, 1e-15, entropy);
378 test_almost(5.4, 2.244941839577643504608, 1e-15, entropy);
379 test_case(10.8, 2.600596429676975222694, entropy);
380 }
381
382 #[test]
383 fn test_skewness() {
384 let skewness = |x: Poisson| x.skewness().unwrap();
385 test_almost(1.5, 0.8164965809277260327324, 1e-15, skewness);
386 test_almost(5.4, 0.4303314829119352094644, 1e-16, skewness);
387 test_almost(10.8, 0.3042903097250922852539, 1e-16, skewness);
388 }
389
390 #[test]
391 fn test_median() {
392 let median = |x: Poisson| x.median();
393 test_case(1.5, 1.0, median);
394 test_case(5.4, 5.0, median);
395 test_case(10.8, 11.0, median);
396 }
397
398 #[test]
399 fn test_mode() {
400 let mode = |x: Poisson| x.mode().unwrap();
401 test_case(1.5, 1, mode);
402 test_case(5.4, 5, mode);
403 test_case(10.8, 10, mode);
404 }
405
406 #[test]
407 fn test_min_max() {
408 let min = |x: Poisson| x.min();
409 let max = |x: Poisson| x.max();
410 test_case(1.5, 0, min);
411 test_case(5.4, 0, min);
412 test_case(10.8, 0, min);
413 test_case(1.5, u64::MAX, max);
414 test_case(5.4, u64::MAX, max);
415 test_case(10.8, u64::MAX, max);
416 }
417
418 #[test]
419 fn test_pmf() {
420 let pmf = |arg: u64| move |x: Poisson| x.pmf(arg);
421 test_almost(1.5, 0.334695240222645000000000000000, 1e-15, pmf(1));
422 test_almost(1.5, 0.000003545747740570180000000000, 1e-20, pmf(10));
423 test_almost(1.5, 0.000000000000000304971208961018, 1e-30, pmf(20));
424 test_almost(5.4, 0.024389537090108400000000000000, 1e-17, pmf(1));
425 test_almost(5.4, 0.026241240591792300000000000000, 1e-16, pmf(10));
426 test_almost(5.4, 0.000000825202200316548000000000, 1e-20, pmf(20));
427 test_almost(10.8, 0.000220314636840657000000000000, 1e-18, pmf(1));
428 test_almost(10.8, 0.121365183659420000000000000000, 1e-15, pmf(10));
429 test_almost(10.8, 0.003908139778574110000000000000, 1e-16, pmf(20));
430 }
431
432 #[test]
433 fn test_ln_pmf() {
434 let ln_pmf = |arg: u64| move |x: Poisson| x.ln_pmf(arg);
435 test_almost(1.5, -1.09453489189183485135413967177, 1e-15, ln_pmf(1));
436 test_almost(1.5, -12.5497614919938728510400000000, 1e-14, ln_pmf(10));
437 test_almost(1.5, -35.7263142985901000000000000000, 1e-13, ln_pmf(20));
438 test_case(5.4, -3.71360104642977159156055355910, ln_pmf(1));
439 test_almost(5.4, -3.64042303737322774736223038530, 1e-15, ln_pmf(10));
440 test_almost(5.4, -14.0076373893489089949388000000, 1e-14, ln_pmf(20));
441 test_almost(10.8, -8.42045386586982559781714423000, 1e-14, ln_pmf(1));
442 test_almost(10.8, -2.10895123177378079525424989992, 1e-14, ln_pmf(10));
443 test_almost(10.8, -5.54469377815000936289610059500, 1e-14, ln_pmf(20));
444 }
445
446 #[test]
447 fn test_cdf() {
448 let cdf = |arg: u64| move |x: Poisson| x.cdf(arg);
449 test_almost(1.5, 0.5578254003710750000000, 1e-15, cdf(1));
450 test_almost(1.5, 0.9999994482467640000000, 1e-15, cdf(10));
451 test_case(1.5, 1.0, cdf(20));
452 test_almost(5.4, 0.0289061180327211000000, 1e-16, cdf(1));
453 test_almost(5.4, 0.9774863006897650000000, 1e-15, cdf(10));
454 test_almost(5.4, 0.9999997199928290000000, 1e-15, cdf(20));
455 test_almost(10.8, 0.0002407141402518290000, 1e-16, cdf(1));
456 test_almost(10.8, 0.4839692359955690000000, 1e-15, cdf(10));
457 test_almost(10.8, 0.9961800769608090000000, 1e-15, cdf(20));
458 }
459
460 #[test]
461 fn test_sf() {
462 let sf = |arg: u64| move |x: Poisson| x.sf(arg);
463 test_almost(1.5, 0.44217459962892536, 1e-15, sf(1));
464 test_almost(1.5, 0.0000005517532358246565, 1e-15, sf(10));
465 test_almost(1.5, 2.3372210700347092e-17, 1e-15, sf(20));
466 test_almost(5.4, 0.971093881967279, 1e-16, sf(1));
467 test_almost(5.4, 0.022513699310235582, 1e-15, sf(10));
468 test_almost(5.4, 0.0000002800071708975261, 1e-15, sf(20));
469 test_almost(10.8, 0.9997592858597482, 1e-16, sf(1));
470 test_almost(10.8, 0.5160307640044303, 1e-15, sf(10));
471 test_almost(10.8, 0.003819923039191422, 1e-15, sf(20));
472 }
473
474 #[test]
475 fn test_discrete() {
476 test::check_discrete_distribution(&try_create(0.3), 10);
477 test::check_discrete_distribution(&try_create(4.5), 30);
478 }
479}