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