Skip to main content

rand/
lib.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//! Utilities for random number generation
11//!
12//! Rand provides utilities to generate random numbers, to convert them to
13//! useful types and distributions, and some randomness-related algorithms.
14//!
15//! # Quick Start
16//!
17//! ```
18//! // The prelude import enables methods we use below, specifically
19//! // Rng::random, Rng::sample, SliceRandom::shuffle and IndexedRandom::choose.
20//! use rand::prelude::*;
21//!
22//! // Get an RNG:
23//! let mut rng = rand::rng();
24//!
25//! // Try printing a random unicode code point (probably a bad idea)!
26//! println!("char: '{}'", rng.random::<char>());
27//! // Try printing a random alphanumeric value instead!
28//! println!("alpha: '{}'", rng.sample(rand::distr::Alphanumeric) as char);
29//!
30//! // Generate and shuffle a sequence:
31//! let mut nums: Vec<i32> = (1..100).collect();
32//! nums.shuffle(&mut rng);
33//! // And take a random pick (yes, we didn't need to shuffle first!):
34//! let _ = nums.choose(&mut rng);
35//! ```
36//!
37//! # The Book
38//!
39//! For the user guide and further documentation, please read
40//! [The Rust Rand Book](https://rust-random.github.io/book).
41
42#![doc(
43    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
44    html_favicon_url = "https://www.rust-lang.org/favicon.ico"
45)]
46#![deny(missing_docs)]
47#![deny(missing_debug_implementations)]
48#![doc(test(attr(allow(unused_variables), deny(warnings))))]
49#![no_std]
50#![cfg_attr(feature = "simd_support", feature(portable_simd))]
51#![cfg_attr(
52    all(feature = "simd_support", target_feature = "avx512bw"),
53    feature(stdarch_x86_avx512)
54)]
55#![cfg_attr(docsrs, feature(doc_cfg))]
56#![allow(
57    clippy::float_cmp,
58    clippy::neg_cmp_op_on_partial_ord,
59    clippy::nonminimal_bool
60)]
61#![deny(clippy::undocumented_unsafe_blocks)]
62
63#[cfg(feature = "alloc")]
64extern crate alloc;
65#[cfg(feature = "std")]
66extern crate std;
67
68// Re-export rand_core itself
69pub use rand_core;
70
71// Re-exports from rand_core
72pub use rand_core::{CryptoRng, Rng, SeedableRng, TryCryptoRng, TryRng};
73
74// Public modules
75pub mod distr;
76pub mod prelude;
77mod rng;
78pub mod rngs;
79pub mod seq;
80
81// Public exports
82#[cfg(feature = "thread_rng")]
83pub use crate::rngs::thread::rng;
84
85pub use rng::{Fill, RngExt};
86
87#[cfg(feature = "thread_rng")]
88use crate::distr::{Distribution, StandardUniform};
89
90/// Construct and seed an RNG
91///
92/// This method yields a seeded RNG, using [`rng`] ([`ThreadRng`]) if enabled or
93/// [`SysRng`] otherwise.
94///
95/// # Examples
96///
97/// ```
98/// let mut rng: rand::rngs::SmallRng = rand::make_rng();
99/// # let _ = rand::Rng::next_u32(&mut rng);
100/// ```
101///
102/// # Panics
103///
104/// If [`SysRng`] fails to obtain entropy from the OS. This is unlikely
105/// outside of early boot or unusual system conditions.
106///
107/// # Security
108///
109/// Refer to [`ThreadRng#Security`].
110///
111/// [`SysRng`]: crate::rngs::SysRng
112/// [`ThreadRng`]: crate::rngs::ThreadRng
113/// [`ThreadRng#Security`]: crate::rngs::ThreadRng#security
114#[cfg(feature = "sys_rng")]
115#[track_caller]
116pub fn make_rng<R: SeedableRng>() -> R {
117    #[cfg(feature = "thread_rng")]
118    {
119        R::from_rng(&mut rng())
120    }
121
122    #[cfg(not(feature = "thread_rng"))]
123    {
124        R::try_from_rng(&mut rngs::SysRng).expect("unexpected failure from SysRng")
125    }
126}
127
128/// Adapter to support [`std::io::Read`] over a [`TryRng`]
129///
130/// # Examples
131///
132/// ```no_run
133/// use std::{io, io::Read};
134/// use std::fs::File;
135/// use rand::{rngs::SysRng, RngReader};
136///
137/// io::copy(
138///     &mut RngReader(SysRng).take(100),
139///     &mut File::create("/tmp/random.bytes").unwrap()
140/// ).unwrap();
141/// ```
142#[cfg(feature = "std")]
143pub struct RngReader<R: TryRng>(pub R);
144
145#[cfg(feature = "std")]
146impl<R: TryRng> std::io::Read for RngReader<R> {
147    #[inline]
148    fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
149        self.0
150            .try_fill_bytes(buf)
151            .map_err(|err| std::io::Error::other(std::format!("RNG error: {err}")))?;
152        Ok(buf.len())
153    }
154}
155
156#[cfg(feature = "std")]
157impl<R: TryRng> std::fmt::Debug for RngReader<R> {
158    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159        f.debug_tuple("RngReader").finish()
160    }
161}
162
163/// Generate a random value using the thread-local random number generator.
164///
165/// This function is shorthand for <code>[rng()].[random()](RngExt::random)</code>:
166///
167/// -   See [`ThreadRng`] for documentation of the generator and security
168/// -   See [`StandardUniform`] for documentation of supported types and distributions
169///
170/// # Examples
171///
172/// ```
173/// let x = rand::random::<u8>();
174/// println!("{}", x);
175///
176/// let y = rand::random::<f64>();
177/// println!("{}", y);
178///
179/// if rand::random() { // generates a boolean
180///     println!("Better lucky than good!");
181/// }
182/// ```
183///
184/// If you're calling `random()` repeatedly, consider using a local `rng`
185/// handle to save an initialization-check on each usage:
186///
187/// ```
188/// use rand::RngExt; // provides the `random` method
189///
190/// let mut rng = rand::rng(); // a local handle to the generator
191///
192/// let mut v = vec![1, 2, 3];
193///
194/// for x in v.iter_mut() {
195///     *x = rng.random();
196/// }
197/// ```
198///
199/// [`StandardUniform`]: distr::StandardUniform
200/// [`ThreadRng`]: rngs::ThreadRng
201#[cfg(feature = "thread_rng")]
202#[inline]
203pub fn random<T>() -> T
204where
205    StandardUniform: Distribution<T>,
206{
207    rng().random()
208}
209
210/// Return an iterator over [`random()`] variates
211///
212/// This function is shorthand for
213/// <code>[rng()].[random_iter](RngExt::random_iter)()</code>.
214///
215/// # Example
216///
217/// ```
218/// let v: Vec<i32> = rand::random_iter().take(5).collect();
219/// println!("{v:?}");
220/// ```
221#[cfg(feature = "thread_rng")]
222#[inline]
223pub fn random_iter<T>() -> distr::Iter<StandardUniform, rngs::ThreadRng, T>
224where
225    StandardUniform: Distribution<T>,
226{
227    rng().random_iter()
228}
229
230/// Generate a random value in the given range using the thread-local random number generator.
231///
232/// This function is shorthand for
233/// <code>[rng()].[random_range](RngExt::random_range)(<var>range</var>)</code>.
234///
235/// # Example
236///
237/// ```
238/// let y: f32 = rand::random_range(0.0..=1e9);
239/// println!("{}", y);
240///
241/// let words: Vec<&str> = "Mary had a little lamb".split(' ').collect();
242/// println!("{}", words[rand::random_range(..words.len())]);
243/// ```
244/// Note that the second example can also be achieved (without `collect`'ing
245/// to a `Vec`) using [`seq::IteratorRandom::choose`].
246#[cfg(feature = "thread_rng")]
247#[inline]
248pub fn random_range<T, R>(range: R) -> T
249where
250    T: distr::uniform::SampleUniform,
251    R: distr::uniform::SampleRange<T>,
252{
253    rng().random_range(range)
254}
255
256/// Return a bool with a probability `p` of being true.
257///
258/// This function is shorthand for
259/// <code>[rng()].[random_bool](RngExt::random_bool)(<var>p</var>)</code>.
260///
261/// # Example
262///
263/// ```
264/// println!("{}", rand::random_bool(1.0 / 3.0));
265/// ```
266///
267/// # Panics
268///
269/// If `p < 0` or `p > 1`.
270#[cfg(feature = "thread_rng")]
271#[inline]
272#[track_caller]
273pub fn random_bool(p: f64) -> bool {
274    rng().random_bool(p)
275}
276
277/// Return a bool with a probability of `numerator/denominator` of being
278/// true.
279///
280/// That is, `random_ratio(2, 3)` has chance of 2 in 3, or about 67%, of
281/// returning true. If `numerator == denominator`, then the returned value
282/// is guaranteed to be `true`. If `numerator == 0`, then the returned
283/// value is guaranteed to be `false`.
284///
285/// See also the [`Bernoulli`] distribution, which may be faster if
286/// sampling from the same `numerator` and `denominator` repeatedly.
287///
288/// This function is shorthand for
289/// <code>[rng()].[random_ratio](RngExt::random_ratio)(<var>numerator</var>, <var>denominator</var>)</code>.
290///
291/// # Panics
292///
293/// If `denominator == 0` or `numerator > denominator`.
294///
295/// # Example
296///
297/// ```
298/// println!("{}", rand::random_ratio(2, 3));
299/// ```
300///
301/// [`Bernoulli`]: distr::Bernoulli
302#[cfg(feature = "thread_rng")]
303#[inline]
304#[track_caller]
305pub fn random_ratio(numerator: u32, denominator: u32) -> bool {
306    rng().random_ratio(numerator, denominator)
307}
308
309/// Fill any type implementing [`Fill`] with random data
310///
311/// This function is shorthand for
312/// <code>[rng()].[fill](RngExt::fill)(<var>dest</var>)</code>.
313///
314/// # Example
315///
316/// ```
317/// let mut arr = [0i8; 20];
318/// rand::fill(&mut arr[..]);
319/// ```
320///
321/// Note that you can instead use [`random()`] to generate an array of random
322/// data, though this is slower for small elements (smaller than the RNG word
323/// size).
324#[cfg(feature = "thread_rng")]
325#[inline]
326#[track_caller]
327pub fn fill<T: Fill>(dest: &mut [T]) {
328    Fill::fill_slice(dest, &mut rng())
329}
330
331#[cfg(test)]
332mod test {
333    use super::*;
334    use core::convert::Infallible;
335
336    /// Construct a deterministic RNG with the given seed
337    pub fn rng(seed: u64) -> impl Rng {
338        // For tests, we want a statistically good, fast, reproducible RNG.
339        // PCG32 will do fine, and will be easy to embed if we ever need to.
340        const INC: u64 = 11634580027462260723;
341        rand_pcg::Pcg32::new(seed, INC)
342    }
343
344    /// Construct a generator yielding a constant value
345    pub fn const_rng(x: u64) -> StepRng {
346        StepRng(x, 0)
347    }
348
349    /// Construct a generator yielding an arithmetic sequence
350    pub fn step_rng(x: u64, increment: u64) -> StepRng {
351        StepRng(x, increment)
352    }
353
354    #[derive(Clone)]
355    pub struct StepRng(u64, u64);
356    impl TryRng for StepRng {
357        type Error = Infallible;
358
359        fn try_next_u32(&mut self) -> Result<u32, Infallible> {
360            self.try_next_u64().map(|x| x as u32)
361        }
362
363        fn try_next_u64(&mut self) -> Result<u64, Infallible> {
364            let res = self.0;
365            self.0 = self.0.wrapping_add(self.1);
366            Ok(res)
367        }
368
369        fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> {
370            rand_core::utils::fill_bytes_via_next_word(dst, || self.try_next_u64())
371        }
372    }
373
374    #[cfg(feature = "std")]
375    #[test]
376    fn rng_reader() {
377        use std::io::Read;
378
379        let mut rng = StepRng(255, 1);
380        let mut buf = [0u8; 24];
381        let expected = [
382            255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
383        ];
384
385        RngReader(&mut rng).read_exact(&mut buf).unwrap();
386        assert_eq!(&buf, &expected);
387
388        RngReader(StepRng(255, 1)).read_exact(&mut buf).unwrap();
389        assert_eq!(&buf, &expected);
390    }
391
392    #[test]
393    #[cfg(feature = "thread_rng")]
394    fn test_random() {
395        let _n: u64 = random();
396        let _f: f32 = random();
397        #[allow(clippy::type_complexity)]
398        let _many: (
399            (),
400            [(u32, bool); 3],
401            (u8, i8, u16, i16, u32, i32, u64, i64),
402            (f32, (f64, (f64,))),
403        ) = random();
404    }
405
406    #[test]
407    #[cfg(feature = "thread_rng")]
408    fn test_range() {
409        let _n: usize = random_range(42..=43);
410        let _f: f32 = random_range(42.0..43.0);
411    }
412}