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}