Coverage Report

Created: 2026-07-13 08:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rand-0.8.6/src/distributions/distribution.rs
Line
Count
Source
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.
37
    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
    /// ```
73
0
    fn sample_iter<R>(self, rng: R) -> DistIter<Self, R, T>
74
0
    where
75
0
        R: Rng,
76
0
        Self: Sized,
77
    {
78
0
        DistIter {
79
0
            distr: self,
80
0
            rng,
81
0
            phantom: ::core::marker::PhantomData,
82
0
        }
83
0
    }
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
    /// ```
102
0
    fn map<F, S>(self, func: F) -> DistMap<Self, F, T, S>
103
0
    where
104
0
        F: Fn(T) -> S,
105
0
        Self: Sized,
106
    {
107
0
        DistMap {
108
0
            distr: self,
109
0
            func,
110
0
            phantom: ::core::marker::PhantomData,
111
0
        }
112
0
    }
113
}
114
115
impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
116
0
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T {
117
0
        (*self).sample(rng)
118
0
    }
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)]
143
0
    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
0
        Some(self.distr.sample(&mut self.rng))
148
0
    }
149
150
0
    fn size_hint(&self) -> (usize, Option<usize>) {
151
0
        (usize::max_value(), None)
152
0
    }
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(feature = "nightly")]
163
unsafe 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
{
187
0
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> S {
188
0
        (self.func)(self.distr.sample(rng))
189
0
    }
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`
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]
203
0
    fn sample_string<R: Rng + ?Sized>(&self, rng: &mut R, len: usize) -> String {
204
0
        let mut s = String::new();
205
0
        self.append_string(rng, &mut s, len);
206
0
        s
207
0
    }
208
}
209
210
#[cfg(test)]
211
mod tests {
212
    use crate::distributions::{Distribution, Uniform};
213
    use crate::Rng;
214
215
    #[test]
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]
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]
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")]
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
}