Skip to main content

rand/rngs/
small.rs

1// Copyright 2018 Developers of the Rand project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! A small fast RNG
10
11use core::convert::Infallible;
12use rand_core::{SeedableRng, TryRng};
13
14#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
15type Rng = super::xoshiro128plusplus::Xoshiro128PlusPlus;
16#[cfg(target_pointer_width = "64")]
17type Rng = super::xoshiro256plusplus::Xoshiro256PlusPlus;
18
19/// A small-state, fast, non-crypto, non-portable PRNG
20///
21/// This is the "standard small" RNG, a generator with the following properties:
22///
23/// - Non-[portable]: any future library version may replace the algorithm
24///   and results may be platform-dependent.
25///   (For a small portable generator, use the [rand_pcg] or [rand_xoshiro] crate.)
26/// - Non-cryptographic: output is easy to predict (insecure)
27/// - [Quality]: statistically good quality
28/// - Fast: the RNG is fast for both bulk generation and single values, with
29///   consistent cost of method calls
30/// - Fast initialization
31/// - Small state: little memory usage (current state size is 16-32 bytes
32///   depending on platform)
33///
34/// The current algorithm is
35/// `Xoshiro256PlusPlus` on 64-bit platforms and `Xoshiro128PlusPlus` on 32-bit
36/// platforms. Both are also implemented by the [rand_xoshiro] crate.
37///
38/// ## Seeding (construction)
39///
40/// This generator implements the [`SeedableRng`] trait. All methods are
41/// suitable for seeding, but note that, even with a fixed seed, output is not
42/// [portable]. Some suggestions:
43///
44/// 1.  To automatically seed with a unique seed, use [`rand::make_rng()`]:
45///     ```
46///     use rand::rngs::SmallRng;
47///     let mut rng: SmallRng = rand::make_rng();
48///     # let _ = rand::Rng::next_u32(&mut rng);
49///     ```
50/// 2.  To use a deterministic integral seed, use `seed_from_u64`. This uses a
51///     hash function internally to yield a (typically) good seed from any
52///     input.
53///     ```
54///     # use rand::{SeedableRng, rngs::SmallRng};
55///     let rng = SmallRng::seed_from_u64(1);
56///     # let _: SmallRng = rng;
57///     ```
58/// 3.  To seed deterministically from text or other input, use [`rand_seeder`].
59///
60/// See also [Seeding RNGs] in the book.
61///
62/// ## Generation
63///
64/// The generators implements [`Rng`] and thus also [`Rng`][crate::Rng].
65/// See also the [Random Values] chapter in the book.
66///
67/// [portable]: https://rust-random.github.io/book/crate-reprod.html
68/// [Seeding RNGs]: https://rust-random.github.io/book/guide-seeding.html
69/// [Random Values]: https://rust-random.github.io/book/guide-values.html
70/// [Quality]: https://rust-random.github.io/book/guide-rngs.html#quality
71/// [`StdRng`]: crate::rngs::StdRng
72/// [rand_pcg]: https://crates.io/crates/rand_pcg
73/// [rand_xoshiro]: https://crates.io/crates/rand_xoshiro
74/// [`rand_seeder`]: https://docs.rs/rand_seeder/latest/rand_seeder/
75/// [`Rng`]: rand_core::Rng
76/// [`rand::make_rng()`]: crate::make_rng
77#[derive(#[automatically_derived]
impl ::core::clone::Clone for SmallRng {
    #[inline]
    fn clone(&self) -> SmallRng {
        SmallRng(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SmallRng {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "SmallRng",
            &&self.0)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SmallRng {
    #[inline]
    fn eq(&self, other: &SmallRng) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SmallRng {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Rng>;
    }
}Eq)]
78pub struct SmallRng(Rng);
79
80impl SeedableRng for SmallRng {
81    // Fix to 256 bits. Changing this is a breaking change!
82    type Seed = [u8; 32];
83
84    #[inline(always)]
85    fn from_seed(seed: Self::Seed) -> Self {
86        // This is for compatibility with 32-bit platforms where Rng::Seed has a different seed size
87        // With MSRV >= 1.77: let seed = *seed.first_chunk().unwrap()
88        const LEN: usize = core::mem::size_of::<<Rng as SeedableRng>::Seed>();
89        let seed = (&seed[..LEN]).try_into().unwrap();
90        SmallRng(Rng::from_seed(seed))
91    }
92
93    #[inline(always)]
94    fn seed_from_u64(state: u64) -> Self {
95        SmallRng(Rng::seed_from_u64(state))
96    }
97}
98
99impl TryRng for SmallRng {
100    type Error = Infallible;
101
102    #[inline(always)]
103    fn try_next_u32(&mut self) -> Result<u32, Infallible> {
104        self.0.try_next_u32()
105    }
106
107    #[inline(always)]
108    fn try_next_u64(&mut self) -> Result<u64, Infallible> {
109        self.0.try_next_u64()
110    }
111
112    #[inline(always)]
113    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> {
114        self.0.try_fill_bytes(dest)
115    }
116}