rand_mt 6.0.2

Reference Mersenne Twister random number generators.
Documentation
// src/mt64/rand.rs
//
// Copyright (c) 2015,2017 rust-mersenne-twister developers
// Copyright (c) 2020 Ryan Lopopolo <rjl@hyperbo.la>
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE> or <http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT> or <http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use rand_core::{Infallible, SeedableRng, TryRng};

use super::Mt64;

impl SeedableRng for Mt64 {
    type Seed = [u8; 8];

    /// Reseed from a little endian encoded `u64`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use rand_core::{Rng, SeedableRng};
    /// # use rand_mt::Mt64;
    /// // Default MT seed
    /// let seed = 5489_u64.to_le_bytes();
    /// let mut mt = Mt64::from_seed(seed);
    /// assert_ne!(mt.next_u64(), mt.next_u64());
    /// ```
    #[inline]
    fn from_seed(seed: Self::Seed) -> Self {
        Self::from(seed)
    }
}

impl TryRng for Mt64 {
    type Error = Infallible;

    /// Generate next `u64` output.
    ///
    /// `u64` is the native output of the generator. This function advances the
    /// RNG step counter by one.
    ///
    /// # Examples
    ///
    /// ```
    /// use rand_core::Rng;
    /// use rand_mt::Mt64;
    ///
    /// let mut rng = Mt64::new_unseeded();
    /// # fn example<T: Rng>(mut rng: T) {
    /// assert_ne!(rng.next_u64(), rng.next_u64());
    /// # }
    /// # example(rng);
    /// ```
    #[inline]
    fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
        Ok(Self::next_u64(self))
    }

    /// Generate next `u32` output.
    ///
    /// This function is implemented by generating one `u64` from the RNG and
    /// performing shifting and masking to turn it into a `u32` output.
    ///
    /// # Examples
    ///
    /// ```
    /// use rand_core::Rng;
    /// use rand_mt::Mt64;
    ///
    /// let mut rng = Mt64::new_unseeded();
    /// # fn example<T: Rng>(mut rng: T) {
    /// assert_ne!(rng.next_u32(), rng.next_u32());
    /// # }
    /// # example(rng);
    /// ```
    #[inline]
    fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
        Ok(Self::next_u32(self))
    }

    /// Fill a buffer with bytes generated from the RNG.
    ///
    /// This method generates random `u64`s (the native output unit of the RNG)
    /// until `dest` is filled.
    ///
    /// This method may discard some output bits if `dest.len()` is not a
    /// multiple of 8.
    ///
    /// # Examples
    ///
    /// ```
    /// use rand_core::Rng;
    /// use rand_mt::Mt64;
    ///
    /// let mut rng = Mt64::new_unseeded();
    /// # fn example<T: Rng>(mut rng: T) {
    /// let mut buf = [0; 32];
    /// rng.fill_bytes(&mut buf);
    /// assert_ne!([0; 32], buf);
    /// let mut buf = [0; 31];
    /// rng.fill_bytes(&mut buf);
    /// assert_ne!([0; 31], buf);
    /// # }
    /// # example(rng);
    /// ```
    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
        Self::fill_bytes(self, dest);
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use core::num::Wrapping;
    use rand_core::{Rng, SeedableRng};

    use super::Mt64;
    use crate::vectors::mt64::{STATE_SEEDED_BY_U64, TEST_OUTPUT};

    #[test]
    fn seeded_state_from_u64_seed() {
        let mt = Mt64::new(0x0123_4567_89ab_cdef_u64);
        let mt_from_seed = Mt64::from_seed(0x0123_4567_89ab_cdef_u64.to_le_bytes());
        assert_eq!(mt.state, mt_from_seed.state);
        for (&Wrapping(x), &y) in mt.state.iter().zip(STATE_SEEDED_BY_U64.iter()) {
            assert_eq!(x, y);
        }
        for (&Wrapping(x), &y) in mt_from_seed.state.iter().zip(STATE_SEEDED_BY_U64.iter()) {
            assert_eq!(x, y);
        }
    }

    #[test]
    fn output_from_u64_slice_key() {
        let key = [0x12345_u64, 0x23456_u64, 0x34567_u64, 0x45678_u64];
        let mut mt = Mt64::new_with_key(key.iter().copied());
        for &x in &TEST_OUTPUT {
            assert_eq!(x, Rng::next_u64(&mut mt));
        }
    }
}