1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
// 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::{Error, RngCore, SeedableRng};
use super::Mt19937GenRand64;
impl SeedableRng for Mt19937GenRand64 {
type Seed = [u8; 8];
/// Reseed from a little endian encoded `u64`.
///
/// # Examples
///
/// ```
/// # use rand_core::{RngCore, SeedableRng};
/// # use rand_mt::Mt19937GenRand64;
/// // Default MT seed
/// let seed = 5489_u64.to_le_bytes();
/// let mut mt = Mt19937GenRand64::from_seed(seed);
/// assert_ne!(mt.next_u64(), mt.next_u64());
/// ```
#[inline]
fn from_seed(seed: Self::Seed) -> Self {
Self::from(seed)
}
}
impl RngCore for Mt19937GenRand64 {
/// 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::RngCore;
/// use rand_mt::Mt19937GenRand64;
///
/// let mut rng = Mt19937GenRand64::new_unseeded();
/// # fn example<T: RngCore>(mut rng: T) {
/// assert_ne!(rng.next_u64(), rng.next_u64());
/// # }
/// # example(rng);
/// ```
#[inline]
fn next_u64(&mut self) -> u64 {
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::RngCore;
/// use rand_mt::Mt19937GenRand64;
///
/// let mut rng = Mt19937GenRand64::new_unseeded();
/// # fn example<T: RngCore>(mut rng: T) {
/// assert_ne!(rng.next_u32(), rng.next_u32());
/// # }
/// # example(rng);
/// ```
#[inline]
fn next_u32(&mut self) -> u32 {
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::RngCore;
/// use rand_mt::Mt19937GenRand64;
///
/// let mut rng = Mt19937GenRand64::new_unseeded();
/// # fn example<T: RngCore>(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 fill_bytes(&mut self, dest: &mut [u8]) {
Self::fill_bytes(self, dest);
}
/// 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.
///
/// `try_fill_bytes` is implemented with [`fill_bytes`](RngCore::fill_bytes)
/// and is infallible.
///
/// # Examples
///
/// ```
/// use rand_core::RngCore;
/// use rand_mt::Mt19937GenRand64;
///
/// let mut rng = Mt19937GenRand64::new_unseeded();
/// # fn example<T: RngCore>(mut rng: T) -> Result<(), rand_core::Error> {
/// let mut buf = [0; 32];
/// rng.try_fill_bytes(&mut buf)?;
/// assert_ne!([0; 32], buf);
/// let mut buf = [0; 31];
/// rng.try_fill_bytes(&mut buf)?;
/// assert_ne!([0; 31], buf);
/// # Ok(())
/// # }
/// # example(rng).unwrap()
/// ```
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Self::fill_bytes(self, dest);
Ok(())
}
}
#[cfg(test)]
mod tests {
use core::num::Wrapping;
use rand_core::{RngCore, SeedableRng};
use super::Mt19937GenRand64;
use crate::vectors::mt64::{STATE_SEEDED_BY_U64, TEST_OUTPUT};
#[test]
fn seeded_state_from_u64_seed() {
let mt = Mt19937GenRand64::new(0x0123_4567_89ab_cdef_u64);
let mt_from_seed = Mt19937GenRand64::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 = Mt19937GenRand64::new_with_key(key.iter().copied());
for &x in TEST_OUTPUT.iter() {
assert_eq!(x, RngCore::next_u64(&mut mt));
}
}
}