1 // Copyright 2018 Developers of the Rand project.
2 // Copyright 2013-2017 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 //! Distribution trait and associates
11 
12 use crate::Rng;
13 use core::iter;
14 #[cfg(feature = "alloc")]
15 use alloc::string::String;
16 
17 /// Types (distributions) that can be used to create a random instance of `T`.
18 ///
19 /// It is possible to sample from a distribution through both the
20 /// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and
21 /// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which
22 /// produces an iterator that samples from the distribution.
23 ///
24 /// All implementations are expected to be immutable; this has the significant
25 /// advantage of not needing to consider thread safety, and for most
26 /// distributions efficient state-less sampling algorithms are available.
27 ///
28 /// Implementations are typically expected to be portable with reproducible
29 /// results when used with a PRNG with fixed seed; see the
30 /// [portability chapter](https://rust-random.github.io/book/portability.html)
31 /// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize`
32 /// type requires different sampling on 32-bit and 64-bit machines.
33 ///
34 /// [`sample_iter`]: Distribution::sample_iter
35 pub trait Distribution<T> {
36     /// Generate a random value of `T`, using `rng` as the source of randomness.
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T37     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;
38 
39     /// Create an iterator that generates random values of `T`, using `rng` as
40     /// the source of randomness.
41     ///
42     /// Note that this function takes `self` by value. This works since
43     /// `Distribution<T>` is impl'd for `&D` where `D: Distribution<T>`,
44     /// however borrowing is not automatic hence `distr.sample_iter(...)` may
45     /// need to be replaced with `(&distr).sample_iter(...)` to borrow or
46     /// `(&*distr).sample_iter(...)` to reborrow an existing reference.
47     ///
48     /// # Example
49     ///
50     /// ```
51     /// use rand::thread_rng;
52     /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard};
53     ///
54     /// let mut rng = thread_rng();
55     ///
56     /// // Vec of 16 x f32:
57     /// let v: Vec<f32> = Standard.sample_iter(&mut rng).take(16).collect();
58     ///
59     /// // String:
60     /// let s: String = Alphanumeric
61     ///     .sample_iter(&mut rng)
62     ///     .take(7)
63     ///     .map(char::from)
64     ///     .collect();
65     ///
66     /// // Dice-rolling:
67     /// let die_range = Uniform::new_inclusive(1, 6);
68     /// let mut roll_die = die_range.sample_iter(&mut rng);
69     /// while roll_die.next().unwrap() != 6 {
70     ///     println!("Not a 6; rolling again!");
71     /// }
72     /// ```
sample_iter<R>(self, rng: R) -> DistIter<Self, R, T> where R: Rng, Self: Sized,73     fn sample_iter<R>(self, rng: R) -> DistIter<Self, R, T>
74     where
75         R: Rng,
76         Self: Sized,
77     {
78         DistIter {
79             distr: self,
80             rng,
81             phantom: ::core::marker::PhantomData,
82         }
83     }
84 
85     /// Create a distribution of values of 'S' by mapping the output of `Self`
86     /// through the closure `F`
87     ///
88     /// # Example
89     ///
90     /// ```
91     /// use rand::thread_rng;
92     /// use rand::distributions::{Distribution, Uniform};
93     ///
94     /// let mut rng = thread_rng();
95     ///
96     /// let die = Uniform::new_inclusive(1, 6);
97     /// let even_number = die.map(|num| num % 2 == 0);
98     /// while !even_number.sample(&mut rng) {
99     ///     println!("Still odd; rolling again!");
100     /// }
101     /// ```
map<F, S>(self, func: F) -> DistMap<Self, F, T, S> where F: Fn(T) -> S, Self: Sized,102     fn map<F, S>(self, func: F) -> DistMap<Self, F, T, S>
103     where
104         F: Fn(T) -> S,
105         Self: Sized,
106     {
107         DistMap {
108             distr: self,
109             func,
110             phantom: ::core::marker::PhantomData,
111         }
112     }
113 }
114 
115 impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T116     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T {
117         (*self).sample(rng)
118     }
119 }
120 
121 /// An iterator that generates random values of `T` with distribution `D`,
122 /// using `R` as the source of randomness.
123 ///
124 /// This `struct` is created by the [`sample_iter`] method on [`Distribution`].
125 /// See its documentation for more.
126 ///
127 /// [`sample_iter`]: Distribution::sample_iter
128 #[derive(Debug)]
129 pub struct DistIter<D, R, T> {
130     distr: D,
131     rng: R,
132     phantom: ::core::marker::PhantomData<T>,
133 }
134 
135 impl<D, R, T> Iterator for DistIter<D, R, T>
136 where
137     D: Distribution<T>,
138     R: Rng,
139 {
140     type Item = T;
141 
142     #[inline(always)]
next(&mut self) -> Option<T>143     fn next(&mut self) -> Option<T> {
144         // Here, self.rng may be a reference, but we must take &mut anyway.
145         // Even if sample could take an R: Rng by value, we would need to do this
146         // since Rng is not copyable and we cannot enforce that this is "reborrowable".
147         Some(self.distr.sample(&mut self.rng))
148     }
149 
size_hint(&self) -> (usize, Option<usize>)150     fn size_hint(&self) -> (usize, Option<usize>) {
151         (usize::max_value(), None)
152     }
153 }
154 
155 impl<D, R, T> iter::FusedIterator for DistIter<D, R, T>
156 where
157     D: Distribution<T>,
158     R: Rng,
159 {
160 }
161 
162 #[cfg(features = "nightly")]
163 impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
164 where
165     D: Distribution<T>,
166     R: Rng,
167 {
168 }
169 
170 /// A distribution of values of type `S` derived from the distribution `D`
171 /// by mapping its output of type `T` through the closure `F`.
172 ///
173 /// This `struct` is created by the [`Distribution::map`] method.
174 /// See its documentation for more.
175 #[derive(Debug)]
176 pub struct DistMap<D, F, T, S> {
177     distr: D,
178     func: F,
179     phantom: ::core::marker::PhantomData<fn(T) -> S>,
180 }
181 
182 impl<D, F, T, S> Distribution<S> for DistMap<D, F, T, S>
183 where
184     D: Distribution<T>,
185     F: Fn(T) -> S,
186 {
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> S187     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> S {
188         (self.func)(self.distr.sample(rng))
189     }
190 }
191 
192 /// `String` sampler
193 ///
194 /// Sampling a `String` of random characters is not quite the same as collecting
195 /// a sequence of chars. This trait contains some helpers.
196 #[cfg(feature = "alloc")]
197 pub trait DistString {
198     /// Append `len` random chars to `string`
append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize)199     fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize);
200 
201     /// Generate a `String` of `len` random chars
202     #[inline]
sample_string<R: Rng + ?Sized>(&self, rng: &mut R, len: usize) -> String203     fn sample_string<R: Rng + ?Sized>(&self, rng: &mut R, len: usize) -> String {
204         let mut s = String::new();
205         self.append_string(rng, &mut s, len);
206         s
207     }
208 }
209 
210 #[cfg(test)]
211 mod tests {
212     use crate::distributions::{Distribution, Uniform};
213     use crate::Rng;
214 
215     #[test]
test_distributions_iter()216     fn test_distributions_iter() {
217         use crate::distributions::Open01;
218         let mut rng = crate::test::rng(210);
219         let distr = Open01;
220         let mut iter = Distribution::<f32>::sample_iter(distr, &mut rng);
221         let mut sum: f32 = 0.;
222         for _ in 0..100 {
223             sum += iter.next().unwrap();
224         }
225         assert!(0. < sum && sum < 100.);
226     }
227 
228     #[test]
test_distributions_map()229     fn test_distributions_map() {
230         let dist = Uniform::new_inclusive(0, 5).map(|val| val + 15);
231 
232         let mut rng = crate::test::rng(212);
233         let val = dist.sample(&mut rng);
234         assert!((15..=20).contains(&val));
235     }
236 
237     #[test]
test_make_an_iter()238     fn test_make_an_iter() {
239         fn ten_dice_rolls_other_than_five<R: Rng>(
240             rng: &mut R,
241         ) -> impl Iterator<Item = i32> + '_ {
242             Uniform::new_inclusive(1, 6)
243                 .sample_iter(rng)
244                 .filter(|x| *x != 5)
245                 .take(10)
246         }
247 
248         let mut rng = crate::test::rng(211);
249         let mut count = 0;
250         for val in ten_dice_rolls_other_than_five(&mut rng) {
251             assert!((1..=6).contains(&val) && val != 5);
252             count += 1;
253         }
254         assert_eq!(count, 10);
255     }
256 
257     #[test]
258     #[cfg(feature = "alloc")]
test_dist_string()259     fn test_dist_string() {
260         use core::str;
261         use crate::distributions::{Alphanumeric, DistString, Standard};
262         let mut rng = crate::test::rng(213);
263 
264         let s1 = Alphanumeric.sample_string(&mut rng, 20);
265         assert_eq!(s1.len(), 20);
266         assert_eq!(str::from_utf8(s1.as_bytes()), Ok(s1.as_str()));
267 
268         let s2 = Standard.sample_string(&mut rng, 20);
269         assert_eq!(s2.chars().count(), 20);
270         assert_eq!(str::from_utf8(s2.as_bytes()), Ok(s2.as_str()));
271     }
272 }
273