]> git.proxmox.com Git - rustc.git/blob - vendor/rand-0.7.3/src/distributions/exponential.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / vendor / rand-0.7.3 / src / distributions / exponential.rs
1 // Copyright 2018 Developers of the Rand project.
2 // Copyright 2013 The Rust Project Developers.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10 //! The exponential distribution.
11 #![allow(deprecated)]
12
13 use crate::distributions::utils::ziggurat;
14 use crate::distributions::{ziggurat_tables, Distribution};
15 use crate::Rng;
16
17 /// Samples floating-point numbers according to the exponential distribution,
18 /// with rate parameter `λ = 1`. This is equivalent to `Exp::new(1.0)` or
19 /// sampling with `-rng.gen::<f64>().ln()`, but faster.
20 ///
21 /// See `Exp` for the general exponential distribution.
22 ///
23 /// Implemented via the ZIGNOR variant[^1] of the Ziggurat method. The exact
24 /// description in the paper was adjusted to use tables for the exponential
25 /// distribution rather than normal.
26 ///
27 /// [^1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
28 /// Generate Normal Random Samples*](
29 /// https://www.doornik.com/research/ziggurat.pdf).
30 /// Nuffield College, Oxford
31 #[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
32 #[derive(Clone, Copy, Debug)]
33 pub struct Exp1;
34
35 // This could be done via `-rng.gen::<f64>().ln()` but that is slower.
36 impl Distribution<f64> for Exp1 {
37 #[inline]
38 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
39 #[inline]
40 fn pdf(x: f64) -> f64 {
41 (-x).exp()
42 }
43 #[inline]
44 fn zero_case<R: Rng + ?Sized>(rng: &mut R, _u: f64) -> f64 {
45 ziggurat_tables::ZIG_EXP_R - rng.gen::<f64>().ln()
46 }
47
48 ziggurat(
49 rng,
50 false,
51 &ziggurat_tables::ZIG_EXP_X,
52 &ziggurat_tables::ZIG_EXP_F,
53 pdf,
54 zero_case,
55 )
56 }
57 }
58
59 /// The exponential distribution `Exp(lambda)`.
60 ///
61 /// This distribution has density function: `f(x) = lambda * exp(-lambda * x)`
62 /// for `x > 0`.
63 ///
64 /// Note that [`Exp1`](crate::distributions::Exp1) is an optimised implementation for `lambda = 1`.
65 #[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
66 #[derive(Clone, Copy, Debug)]
67 pub struct Exp {
68 /// `lambda` stored as `1/lambda`, since this is what we scale by.
69 lambda_inverse: f64,
70 }
71
72 impl Exp {
73 /// Construct a new `Exp` with the given shape parameter
74 /// `lambda`. Panics if `lambda <= 0`.
75 #[inline]
76 pub fn new(lambda: f64) -> Exp {
77 assert!(lambda > 0.0, "Exp::new called with `lambda` <= 0");
78 Exp {
79 lambda_inverse: 1.0 / lambda,
80 }
81 }
82 }
83
84 impl Distribution<f64> for Exp {
85 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
86 let n: f64 = rng.sample(Exp1);
87 n * self.lambda_inverse
88 }
89 }
90
91 #[cfg(test)]
92 mod test {
93 use super::Exp;
94 use crate::distributions::Distribution;
95
96 #[test]
97 fn test_exp() {
98 let exp = Exp::new(10.0);
99 let mut rng = crate::test::rng(221);
100 for _ in 0..1000 {
101 assert!(exp.sample(&mut rng) >= 0.0);
102 }
103 }
104 #[test]
105 #[should_panic]
106 fn test_exp_invalid_lambda_zero() {
107 Exp::new(0.0);
108 }
109 #[test]
110 #[should_panic]
111 fn test_exp_invalid_lambda_neg() {
112 Exp::new(-10.0);
113 }
114 }