Module utils

Utilties to aid trait implementations

Portability

For cross-platform reproducibility, Little-Endian order (least-significant part first) has been chosen as the standard for inter-type conversion. For example, next_u64_via_u32 generates two u32 values x, y, then outputs (y << 32) | x.

Byte-swapping (like the std to_le functions) is only needed to convert to/from byte sequences, and since its purpose is reproducibility, non-reproducible sources (e.g. OsRng) need not bother with it.

Implementing TryRng

Usually an implementation of TryRng will implement one of the three methods over its internal source. The following helpers are provided for the remaining implementations.

fn try_next_u32:

fn try_next_u64:

fn try_fill_bytes:

Implementing SeedableRng

In many cases, SeedableRng::Seed must be converted to [u32; _] or [u64; _]. read_words may be used for this.

Example

We demonstrate a simple multiplicative congruential generator (MCG), taken from M.E. O'Neill's blog post Does It Beat the Minimal Standard?.

use core::convert::Infallible;
use rand_core::{Rng, SeedableRng, TryRng, utils};

pub struct Mcg128(u128);

impl SeedableRng for Mcg128 {
    type Seed = [u8; 16];

    #[inline]
    fn from_seed(seed: Self::Seed) -> Self {
        // Always use little-endian byte order to ensure portable results
        Self(u128::from_le_bytes(seed))
    }
}

impl TryRng for Mcg128 {
    type Error = Infallible;

    #[inline]
    fn try_next_u32(&mut self) -> Result<u32, Infallible> {
        Ok((self.next_u64() >> 32) as u32)
    }

    #[inline]
    fn try_next_u64(&mut self) -> Result<u64, Infallible> {
        self.0 = self.0.wrapping_mul(0x0fc94e3bf4e9ab32866458cd56f5e605);
        Ok((self.0 >> 64) as u64)
    }

    #[inline]
    fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> {
        utils::fill_bytes_via_next_word(dst, || self.try_next_u64())
    }
}
#
# let mut rng = Mcg128::seed_from_u64(42);
# assert_eq!(rng.next_u32(), 3443086493);
# assert_eq!(rng.next_u64(), 3462997187007721903);
# let mut buf = [0u8; 5];
# rng.fill_bytes(&mut buf);
# assert_eq!(buf, [154, 23, 43, 68, 75]);

Traits

Functions