1 // Copyright 2018 Developers of the Rand project.
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 
9 //! The Pareto distribution.
10 
11 use Rng;
12 use distributions::{Distribution, OpenClosed01};
13 
14 /// Samples floating-point numbers according to the Pareto distribution
15 ///
16 /// # Example
17 /// ```
18 /// use rand::prelude::*;
19 /// use rand::distributions::Pareto;
20 ///
21 /// let val: f64 = SmallRng::from_entropy().sample(Pareto::new(1., 2.));
22 /// println!("{}", val);
23 /// ```
24 #[derive(Clone, Copy, Debug)]
25 pub struct Pareto {
26     scale: f64,
27     inv_neg_shape: f64,
28 }
29 
30 impl Pareto {
31     /// Construct a new Pareto distribution with given `scale` and `shape`.
32     ///
33     /// In the literature, `scale` is commonly written as x<sub>m</sub> or k and
34     /// `shape` is often written as α.
35     ///
36     /// # Panics
37     ///
38     /// `scale` and `shape` have to be non-zero and positive.
new(scale: f64, shape: f64) -> Pareto39     pub fn new(scale: f64, shape: f64) -> Pareto {
40         assert!((scale > 0.) & (shape > 0.));
41         Pareto { scale, inv_neg_shape: -1.0 / shape }
42     }
43 }
44 
45 impl Distribution<f64> for Pareto {
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f6446     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
47         let u: f64 = rng.sample(OpenClosed01);
48         self.scale * u.powf(self.inv_neg_shape)
49     }
50 }
51 
52 #[cfg(test)]
53 mod tests {
54     use distributions::Distribution;
55     use super::Pareto;
56 
57     #[test]
58     #[should_panic]
invalid()59     fn invalid() {
60         Pareto::new(0., 0.);
61     }
62 
63     #[test]
sample()64     fn sample() {
65         let scale = 1.0;
66         let shape = 2.0;
67         let d = Pareto::new(scale, shape);
68         let mut rng = ::test::rng(1);
69         for _ in 0..1000 {
70             let r = d.sample(&mut rng);
71             assert!(r >= scale);
72         }
73     }
74 }
75