Skip to main content

rand/
rng.rs

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//! [`RngExt`] trait
11
12use crate::distr::uniform::{SampleRange, SampleUniform};
13use crate::distr::{self, Distribution, StandardUniform};
14use core::num::Wrapping;
15use core::{mem, slice};
16use rand_core::Rng;
17
18/// User-level interface for RNGs
19///
20/// [`Rng`] is the `dyn`-safe implementation-level interface for Random
21/// (Number) Generators. This trait, `RngExt`, provides a user-level interface
22/// on RNGs. It is implemented automatically for any <code>R: [Rng][]</code>.
23///
24/// This trait must usually be brought into scope via `use rand::RngExt;` or
25/// `use rand::prelude::*;`.
26///
27/// # Generic usage
28///
29/// The basic pattern is `fn foo<R: Rng + ?Sized>(rng: &mut R)`. Some
30/// things are worth noting here:
31///
32/// - Since `RngExt: Rng` and every `RngExt` implements `Rng`, it makes no
33///   difference whether we use `R: Rng` or `R: RngExt` for `R: Sized`.
34/// - Only `Rng` is dyn safe, supporting `&mut dyn Rng` and `R: Rng + ?Sized`.
35///
36/// An alternative pattern is possible: `fn foo<R: Rng>(rng: R)`. This has some
37/// trade-offs. It allows the argument to be consumed directly without a `&mut`;
38/// also it still works directly
39/// on references (including type-erased references). Unfortunately within the
40/// function `foo` it is not known whether `rng` is a reference type or not,
41/// hence many uses of `rng` require an extra reference, either explicitly
42/// (`distr.sample(&mut rng)`) or implicitly (`rng.random()`); one may hope the
43/// optimiser can remove redundant references later.
44///
45/// Example:
46///
47/// ```
48/// use rand::{Rng, RngExt};
49///
50/// fn foo<R: Rng + ?Sized>(rng: &mut R) -> f32 {
51///     rng.random()
52/// }
53///
54/// # let v = foo(&mut rand::rng());
55/// ```
56pub trait RngExt: Rng {
57    /// Return a random value via the [`StandardUniform`] distribution.
58    ///
59    /// # Example
60    ///
61    /// ```
62    /// use rand::RngExt;
63    ///
64    /// let mut rng = rand::rng();
65    /// let x: u32 = rng.random();
66    /// println!("{}", x);
67    /// println!("{:?}", rng.random::<(f64, bool)>());
68    /// ```
69    ///
70    /// # Arrays and tuples
71    ///
72    /// The `rng.random()` method is able to generate arrays
73    /// and tuples (up to 12 elements), so long as all element types can be
74    /// generated.
75    ///
76    /// For arrays of integers, especially for those with small element types
77    /// (< 64 bit), it will likely be faster to instead use [`RngExt::fill`],
78    /// though note that generated values will differ.
79    ///
80    /// ```
81    /// use rand::RngExt;
82    ///
83    /// let mut rng = rand::rng();
84    /// let tuple: (u8, i32, char) = rng.random(); // arbitrary tuple support
85    ///
86    /// let arr1: [f32; 32] = rng.random();        // array construction
87    /// let mut arr2 = [0u8; 128];
88    /// rng.fill(&mut arr2);                    // array fill
89    /// ```
90    ///
91    /// [`StandardUniform`]: distr::StandardUniform
92    #[inline]
93    fn random<T>(&mut self) -> T
94    where
95        StandardUniform: Distribution<T>,
96    {
97        StandardUniform.sample(self)
98    }
99
100    /// Return an iterator over [`random`](Self::random) variates
101    ///
102    /// This is a just a wrapper over [`RngExt::sample_iter`] using
103    /// [`distr::StandardUniform`].
104    ///
105    /// Note: this method consumes its argument. Use
106    /// `(&mut rng).random_iter()` to avoid consuming the RNG.
107    ///
108    /// # Example
109    ///
110    /// ```
111    /// use rand::{rngs::SmallRng, RngExt, SeedableRng};
112    ///
113    /// let rng = SmallRng::seed_from_u64(0);
114    /// let v: Vec<i32> = rng.random_iter().take(5).collect();
115    /// assert_eq!(v.len(), 5);
116    /// ```
117    #[inline]
118    fn random_iter<T>(self) -> distr::Iter<StandardUniform, Self, T>
119    where
120        Self: Sized,
121        StandardUniform: Distribution<T>,
122    {
123        StandardUniform.sample_iter(self)
124    }
125
126    /// Generate a random value in the given range.
127    ///
128    /// This function is optimised for the case that only a single sample is
129    /// made from the given range. See also the [`Uniform`] distribution
130    /// type which may be faster if sampling from the same range repeatedly.
131    ///
132    /// All supported types may be sampled with `low..high_exclusive`
133    /// ([`Range`]) and `low..=high` ([`RangeInclusive`]) syntax. Unsigned
134    /// integer types also support `..high_exclusive` ([`RangeTo`]) and
135    /// `..=high` ([`RangeToInclusive`]) syntax.
136    ///
137    /// # Panics
138    ///
139    /// Panics if the range is empty, or if `high - low` overflows for floats.
140    ///
141    /// # Example
142    ///
143    /// ```
144    /// use rand::RngExt;
145    ///
146    /// let mut rng = rand::rng();
147    ///
148    /// // Exclusive range
149    /// println!("{}", rng.random_range::<u32, _>(..10));
150    /// println!("{}", rng.random_range(-40.0..1.3e5));
151    ///
152    /// // Inclusive range
153    /// println!("{}", rng.random_range(-10..=10));
154    /// println!("{}", rng.random_range('a'..='z'));
155    /// ```
156    ///
157    /// [`Uniform`]: distr::uniform::Uniform
158    /// [`Range`]: std::ops::Range
159    /// [`RangeInclusive`]: std::ops::RangeInclusive
160    /// [`RangeTo`]: std::ops::RangeTo
161    /// [`RangeToInclusive`]: std::ops::RangeToInclusive
162    #[track_caller]
163    fn random_range<T, R>(&mut self, range: R) -> T
164    where
165        T: SampleUniform,
166        R: SampleRange<T>,
167    {
168        assert!(!range.is_empty(), "cannot sample empty range");
169        range.sample_single(self).unwrap()
170    }
171
172    /// Return a bool with a probability `p` of being true.
173    ///
174    /// See also the [`Bernoulli`] distribution, which may be faster if
175    /// sampling from the same probability repeatedly.
176    ///
177    /// # Example
178    ///
179    /// ```
180    /// use rand::RngExt;
181    ///
182    /// let mut rng = rand::rng();
183    /// println!("{}", rng.random_bool(1.0 / 3.0));
184    /// ```
185    ///
186    /// # Panics
187    ///
188    /// If `p < 0` or `p > 1`.
189    ///
190    /// [`Bernoulli`]: distr::Bernoulli
191    #[inline]
192    #[track_caller]
193    fn random_bool(&mut self, p: f64) -> bool {
194        match distr::Bernoulli::new(p) {
195            Ok(d) => self.sample(d),
196            Err(_) => panic!("p={:?} is outside range [0.0, 1.0]", p),
197        }
198    }
199
200    /// Return a bool with a probability of `numerator/denominator` of being
201    /// true.
202    ///
203    /// That is, `random_ratio(2, 3)` has chance of 2 in 3, or about 67%, of
204    /// returning true. If `numerator == denominator`, then the returned value
205    /// is guaranteed to be `true`. If `numerator == 0`, then the returned
206    /// value is guaranteed to be `false`.
207    ///
208    /// See also the [`Bernoulli`] distribution, which may be faster if
209    /// sampling from the same `numerator` and `denominator` repeatedly.
210    ///
211    /// # Panics
212    ///
213    /// If `denominator == 0` or `numerator > denominator`.
214    ///
215    /// # Example
216    ///
217    /// ```
218    /// use rand::RngExt;
219    ///
220    /// let mut rng = rand::rng();
221    /// println!("{}", rng.random_ratio(2, 3));
222    /// ```
223    ///
224    /// [`Bernoulli`]: distr::Bernoulli
225    #[inline]
226    #[track_caller]
227    fn random_ratio(&mut self, numerator: u32, denominator: u32) -> bool {
228        match distr::Bernoulli::from_ratio(numerator, denominator) {
229            Ok(d) => self.sample(d),
230            Err(_) => panic!(
231                "p={}/{} is outside range [0.0, 1.0]",
232                numerator, denominator
233            ),
234        }
235    }
236
237    /// Sample a new value, using the given distribution.
238    ///
239    /// ### Example
240    ///
241    /// ```
242    /// use rand::RngExt;
243    /// use rand::distr::Uniform;
244    ///
245    /// let mut rng = rand::rng();
246    /// let x = rng.sample(Uniform::new(10u32, 15).unwrap());
247    /// // Type annotation requires two types, the type and distribution; the
248    /// // distribution can be inferred.
249    /// let y = rng.sample::<u16, _>(Uniform::new(10, 15).unwrap());
250    /// ```
251    fn sample<T, D: Distribution<T>>(&mut self, distr: D) -> T {
252        distr.sample(self)
253    }
254
255    /// Create an iterator that generates values using the given distribution.
256    ///
257    /// Note: this method consumes its arguments. Use
258    /// `(&mut rng).sample_iter(..)` to avoid consuming the RNG.
259    ///
260    /// # Example
261    ///
262    /// ```
263    /// use rand::RngExt;
264    /// use rand::distr::{Alphanumeric, Uniform, StandardUniform};
265    ///
266    /// let mut rng = rand::rng();
267    ///
268    /// // Vec of 16 x f32:
269    /// let v: Vec<f32> = (&mut rng).sample_iter(StandardUniform).take(16).collect();
270    ///
271    /// // String:
272    /// let s: String = (&mut rng).sample_iter(Alphanumeric)
273    ///     .take(7)
274    ///     .map(char::from)
275    ///     .collect();
276    ///
277    /// // Combined values
278    /// println!("{:?}", (&mut rng).sample_iter(StandardUniform).take(5)
279    ///                              .collect::<Vec<(f64, bool)>>());
280    ///
281    /// // Dice-rolling:
282    /// let die_range = Uniform::new_inclusive(1, 6).unwrap();
283    /// let mut roll_die = (&mut rng).sample_iter(die_range);
284    /// while roll_die.next().unwrap() != 6 {
285    ///     println!("Not a 6; rolling again!");
286    /// }
287    /// ```
288    fn sample_iter<T, D>(self, distr: D) -> distr::Iter<D, Self, T>
289    where
290        D: Distribution<T>,
291        Self: Sized,
292    {
293        distr.sample_iter(self)
294    }
295
296    /// Fill any type implementing [`Fill`] with random data
297    ///
298    /// This method is implemented for types which may be safely reinterpreted
299    /// as an (aligned) `[u8]` slice then filled with random data. It is often
300    /// faster than using [`RngExt::random`] but not value-equivalent.
301    ///
302    /// The distribution is expected to be uniform with portable results, but
303    /// this cannot be guaranteed for third-party implementations.
304    ///
305    /// # Example
306    ///
307    /// ```
308    /// use rand::RngExt;
309    ///
310    /// let mut arr = [0i8; 20];
311    /// rand::rng().fill(&mut arr[..]);
312    /// ```
313    ///
314    /// [`fill_bytes`]: Rng::fill_bytes
315    #[track_caller]
316    fn fill<T: Fill>(&mut self, dest: &mut [T]) {
317        Fill::fill_slice(dest, self)
318    }
319}
320
321impl<R: Rng + ?Sized> RngExt for R {}
322
323/// Support filling a slice with random data
324///
325/// This trait allows slices of "plain data" types to be efficiently filled
326/// with random data.
327///
328/// Implementations are expected to be portable across machines unless
329/// clearly documented otherwise (see the
330/// [Chapter on Portability](https://rust-random.github.io/book/portability.html)).
331/// The implementations provided achieve this by byte-swapping on big-endian
332/// machines.
333pub trait Fill: Sized {
334    /// Fill this with random data
335    fn fill_slice<R: Rng + ?Sized>(this: &mut [Self], rng: &mut R);
336}
337
338impl Fill for u8 {
339    fn fill_slice<R: Rng + ?Sized>(this: &mut [Self], rng: &mut R) {
340        rng.fill_bytes(this)
341    }
342}
343
344/// Call target for unsafe macros
345const unsafe fn __unsafe() {}
346
347/// Implement `Fill` for given type `$t`.
348///
349/// # Safety
350/// All bit patterns of `[u8; size_of::<$t>()]` must represent values of `$t`.
351macro_rules! impl_fill {
352    () => {};
353    (to_le! plain $x:ident) => {
354        $x.to_le()
355    };
356    (to_le! wrapping $x:ident) => {
357        Wrapping($x.0.to_le())
358    };
359    (fill_slice! $t:ty, $to_le:tt) => {
360        fn fill_slice<R: Rng + ?Sized>(this: &mut [Self], rng: &mut R) {
361            if this.len() > 0 {
362                let size = mem::size_of_val(this);
363                rng.fill_bytes(
364                    // SAFETY: `this` non-null and valid for reads and writes within its `size`
365                    // bytes. `this` meets the alignment requirements of `&mut [u8]`.
366                    // The contents of `this` are initialized. Both `[u8]` and `[$t]` are valid
367                    // for all bit-patterns of their contents (note that the SAFETY requirement
368                    // on callers of this macro). `this` is not borrowed.
369                    unsafe {
370                        slice::from_raw_parts_mut(this.as_mut_ptr()
371                            as *mut u8,
372                            size
373                        )
374                    }
375                );
376                for x in this {
377                    *x = impl_fill!(to_le! $to_le x);
378                }
379            }
380        }
381    };
382    ($t:ty) => {{
383        // Force caller to wrap with an `unsafe` block
384        __unsafe();
385
386        impl Fill for $t {
387            impl_fill!(fill_slice! $t, plain);
388        }
389
390        impl Fill for Wrapping<$t> {
391            impl_fill!(fill_slice! $t, wrapping);
392        }}
393    };
394    ($t:ty, $($tt:ty,)*) => {{
395        impl_fill!($t);
396        // TODO: this could replace above impl once Rust #32463 is fixed
397        // impl_fill!(Wrapping<$t>);
398        impl_fill!($($tt,)*);
399    }}
400}
401
402// SAFETY: All bit patterns of `[u8; size_of::<$t>()]` represent values of `u*`.
403const _: () = unsafe { impl_fill!(u16, u32, u64, u128,) };
404// SAFETY: All bit patterns of `[u8; size_of::<$t>()]` represent values of `i*`.
405const _: () = unsafe { impl_fill!(i8, i16, i32, i64, i128,) };
406
407#[cfg(test)]
408mod test {
409    use super::*;
410    use crate::test::{const_rng, rng};
411    #[cfg(feature = "alloc")]
412    use alloc::boxed::Box;
413
414    #[test]
415    fn test_fill_bytes_default() {
416        let mut r = const_rng(0x11_22_33_44_55_66_77_88);
417
418        // check every remainder mod 8, both in small and big vectors.
419        let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87];
420        for &n in lengths.iter() {
421            let mut buffer = [0u8; 87];
422            let v = &mut buffer[0..n];
423            r.fill_bytes(v);
424
425            // use this to get nicer error messages.
426            for (i, &byte) in v.iter().enumerate() {
427                if byte == 0 {
428                    panic!("byte {} of {} is zero", i, n)
429                }
430            }
431        }
432    }
433
434    #[test]
435    fn test_fill() {
436        let x = 9041086907909331047; // a random u64
437        let mut rng = const_rng(x);
438
439        // Convert to byte sequence and back to u64; byte-swap twice if BE.
440        let mut array = [0u64; 2];
441        rng.fill(&mut array);
442        assert_eq!(array, [x, x]);
443        assert_eq!(rng.next_u64(), x);
444
445        // Convert to bytes then u32 in LE order
446        let mut array = [0u32; 2];
447        rng.fill(&mut array);
448        assert_eq!(array, [x as u32, (x >> 32) as u32]);
449        assert_eq!(rng.next_u32(), x as u32);
450
451        // Check equivalence using wrapped arrays
452        let mut warray = [Wrapping(0u32); 2];
453        rng.fill(&mut warray);
454        assert_eq!(array[0], warray[0].0);
455        assert_eq!(array[1], warray[1].0);
456    }
457
458    #[test]
459    fn test_fill_empty() {
460        let mut array = [0u32; 0];
461        let mut rng = rng(1);
462        rng.fill(&mut array);
463        rng.fill(&mut array[..]);
464    }
465
466    #[test]
467    fn test_random_range_int() {
468        let mut r = rng(101);
469        for _ in 0..1000 {
470            let a = r.random_range(-4711..17);
471            assert!((-4711..17).contains(&a));
472            let a: i8 = r.random_range(-3..42);
473            assert!((-3..42).contains(&a));
474            let a: u16 = r.random_range(10..99);
475            assert!((10..99).contains(&a));
476            let a: i32 = r.random_range(-100..2000);
477            assert!((-100..2000).contains(&a));
478            let a: u32 = r.random_range(12..=24);
479            assert!((12..=24).contains(&a));
480
481            assert_eq!(r.random_range(..1u32), 0u32);
482            assert_eq!(r.random_range(-12i64..-11), -12i64);
483            assert_eq!(r.random_range(3_000_000..3_000_001), 3_000_000);
484        }
485    }
486
487    #[test]
488    fn test_random_range_float() {
489        let mut r = rng(101);
490        for _ in 0..1000 {
491            let a = r.random_range(-4.5..1.7);
492            assert!((-4.5..1.7).contains(&a));
493            let a = r.random_range(-1.1..=-0.3);
494            assert!((-1.1..=-0.3).contains(&a));
495
496            assert_eq!(r.random_range(0.0f32..=0.0), 0.);
497            assert_eq!(r.random_range(-11.0..=-11.0), -11.);
498            assert_eq!(r.random_range(3_000_000.0..=3_000_000.0), 3_000_000.);
499        }
500    }
501
502    #[test]
503    #[should_panic]
504    #[allow(clippy::reversed_empty_ranges)]
505    fn test_random_range_panic_int() {
506        let mut r = rng(102);
507        r.random_range(5..-2);
508    }
509
510    #[test]
511    #[should_panic]
512    #[allow(clippy::reversed_empty_ranges)]
513    fn test_random_range_panic_usize() {
514        let mut r = rng(103);
515        r.random_range(5..2);
516    }
517
518    #[test]
519    #[allow(clippy::bool_assert_comparison)]
520    fn test_random_bool() {
521        let mut r = rng(105);
522        for _ in 0..5 {
523            assert_eq!(r.random_bool(0.0), false);
524            assert_eq!(r.random_bool(1.0), true);
525        }
526    }
527
528    #[test]
529    fn test_rng_mut_ref() {
530        fn use_rng(mut r: impl RngExt) {
531            let _ = r.next_u32();
532        }
533
534        let mut rng = rng(109);
535        use_rng(&mut rng);
536    }
537
538    #[test]
539    fn test_rng_trait_object() {
540        use crate::distr::{Distribution, StandardUniform};
541        let mut rng = rng(109);
542        let mut r = &mut rng as &mut dyn Rng;
543        r.next_u32();
544        r.random::<i32>();
545        assert_eq!(r.random_range(0..1), 0);
546        let _c: u8 = StandardUniform.sample(&mut r);
547    }
548
549    #[test]
550    #[cfg(feature = "alloc")]
551    fn test_rng_boxed_trait() {
552        use crate::distr::{Distribution, StandardUniform};
553        let rng = rng(110);
554        let mut r = Box::new(rng) as Box<dyn Rng>;
555        r.next_u32();
556        r.random::<i32>();
557        assert_eq!(r.random_range(0..1), 0);
558        let _c: u8 = StandardUniform.sample(&mut r);
559    }
560
561    #[test]
562    #[cfg_attr(miri, ignore)] // Miri is too slow
563    fn test_gen_ratio_average() {
564        const NUM: u32 = 3;
565        const DENOM: u32 = 10;
566        const N: u32 = 100_000;
567
568        let mut sum: u32 = 0;
569        let mut rng = rng(111);
570        for _ in 0..N {
571            if rng.random_ratio(NUM, DENOM) {
572                sum += 1;
573            }
574        }
575        // Have Binomial(N, NUM/DENOM) distribution
576        let expected = (NUM * N) / DENOM; // exact integer
577        assert!(((sum - expected) as i32).abs() < 500);
578    }
579}