From 2bb37d2789957cb3eae632e0e714e3852c1531de Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Wed, 29 Jan 2025 22:31:11 -0800 Subject: [PATCH] Upgrade to `rand_core` 0.9, MSRV 1.81.0, breaking change bonanza Upgrade to `rand_core` 0.9. `rand_mt` exports trait impls of `rand_core::RngCore` as part of its public API, so this dep upgrade is a breaking change. While we are making breaking changes: - Bump MSRV to 1.81.0. - Implement `core::error::Error` instead of `std::error::Error`. - Remove `std` feature. - Remove implicit `rand_core` feature. - Upgrade to Rust 2021 edition. - Upgrade `getrandom` dev dependency to 0.3.0. - Revisit #31 and make the names less unwieldy. Prepare for 5.0.0 release. --- .github/workflows/ci.yaml | 7 +- Cargo.toml | 26 +++-- README.md | 18 ++-- src/lib.rs | 68 ++++--------- src/mt.rs | 197 +++++++++++++++++--------------------- src/mt/rand.rs | 67 ++++--------- src/mt64.rs | 190 +++++++++++++++++------------------- src/mt64/rand.rs | 67 ++++--------- 8 files changed, 250 insertions(+), 390 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ef0d23d54..2558051f2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -57,26 +57,21 @@ jobs: - name: Install Rust toolchain uses: artichoke/setup-rust/build-and-test@v1.12.1 with: - toolchain: "1.47.0" + toolchain: "1.81.0" - name: Compile run: cargo build --verbose - # skip tests because dev dependencies have a higher MSRV than rand_mt does. - name: Compile tests - if: false run: cargo test --no-run - name: Test - if: false run: cargo test - name: Test with all features - if: false run: cargo test --all-features - name: Test with no default features - if: false run: cargo test --no-default-features rust: diff --git a/Cargo.toml b/Cargo.toml index 88e2f9162..c61d26c9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,13 @@ [package] name = "rand_mt" -version = "4.2.2" # remember to set `html_root_url` in `src/lib.rs`. -authors = ["David Creswick ", "Ryan Lopopolo "] +version = "5.0.0" # remember to set `html_root_url` in `src/lib.rs`. +authors = [ + "David Creswick ", + "Ryan Lopopolo ", +] license = "MIT OR Apache-2.0" -edition = "2018" -rust-version = "1.47.0" +edition = "2021" +rust-version = "1.81.0" readme = "README.md" repository = "https://github.com/artichoke/rand_mt" documentation = "https://docs.rs/rand_mt" @@ -12,22 +15,17 @@ homepage = "https://github.com/artichoke/rand_mt" description = "Reference Mersenne Twister random number generators." keywords = ["random", "rand", "rng", "mt"] categories = ["algorithms", "no-std", "no-std::no-alloc"] -include = ["src/**/*", "tests/**/*", "LICENSE-*", "README.md"] +include = ["/src/**/*", "/tests/**/*", "/LICENSE-*", "/README.md"] [features] -default = ["rand-traits", "std"] -rand-traits = ["rand_core"] -# Enables `std::error::Error` impls. -std = [] +default = ["rand-traits"] +rand-traits = ["dep:rand_core"] [dependencies] -# 0.6.1 is vulnerable to underfilling a buffer. -# -# https://rustsec.org/advisories/RUSTSEC-2021-0023 -rand_core = { version = "0.6.2", default-features = false, optional = true } +rand_core = { version = "0.9.0", default-features = false, optional = true } [dev-dependencies] -getrandom = { version = "0.2.0", default-features = false } +getrandom = { version = "0.3.1", default-features = false } # Check that crate versions are properly updated in documentation and code when # bumping the version. diff --git a/README.md b/README.md index 46159b963..f4f08d1d6 100644 --- a/README.md +++ b/README.md @@ -18,16 +18,22 @@ The Mersenne Twister algorithms are not suitable for cryptographic uses, but are ubiquitous. See the [Mersenne Twister website]. A variant of Mersenne Twister is the [default PRNG in Ruby]. +[mersenne twister website]: + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html +[default prng in ruby]: https://ruby-doc.org/core-3.1.2/Random.html + This crate optionally depends on [`rand_core`] and implements `RngCore` on the RNGs in this crate. +[`rand_core`]: https://crates.io/crates/rand_core + ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] -rand_mt = "4.2.2" +rand_mt = "5.0.0" ``` Then create a RNG like: @@ -46,8 +52,6 @@ are enabled by default: - **rand-traits** - Enables a dependency on [`rand_core`]. Activating this feature implements `RngCore` and `SeedableRng` on the RNGs in this crate. -- **std** - Enables a dependency on the Rust Standard Library. Activating this - feature enables [`std::error::Error`] impls on error types in this crate. Mersenne Twister requires approximately 2.5 kilobytes of internal state. To make the RNGs implemented in this crate practical to embed in other structs, you may @@ -55,7 +59,7 @@ wish to store the RNG in a `Box`. ### Minimum Supported Rust Version -This crate requires at least Rust 1.47.0. This version can be bumped in minor +This crate requires at least Rust 1.81.0. This version can be bumped in minor releases. ## License @@ -67,10 +71,4 @@ releases. `rand_mt` is derived from `rust-mersenne-twister` @ [`1.1.1`] which is Copyright (c) 2015 rust-mersenne-twister developers. -[mersenne twister website]: - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html -[default prng in ruby]: https://ruby-doc.org/core-3.1.2/Random.html -[`rand_core`]: https://crates.io/crates/rand_core -[`rand_core`]: https://crates.io/crates/rand_core -[`std::error::error`]: https://doc.rust-lang.org/std/error/trait.Error.html [`1.1.1`]: https://github.com/dcrewi/rust-mersenne-twister/tree/1.1.1 diff --git a/src/lib.rs b/src/lib.rs index cad30a3ee..ddd59c08b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,17 +34,16 @@ //! //! This crate provides: //! -//! - [`Mt19937GenRand32`], the original reference Mersenne Twister -//! implementation known as `MT19937`. This is a good choice on both 32-bit -//! and 64-bit CPUs (for 32-bit output). -//! - [`Mt19937GenRand64`], the 64-bit variant of `MT19937` known as -//! `MT19937-64`. This algorithm produces a different output stream than -//! `MT19937` and produces 64-bit output. This is a good choice on 64-bit -//! CPUs. +//! - [`Mt`], the original reference Mersenne Twister implementation known as +//! `MT19937`. This is a good choice on both 32-bit and 64-bit CPUs (for +//! 32-bit output). +//! - [`Mt64`], the 64-bit variant of `MT19937` known as `MT19937-64`. This +//! algorithm produces a different output stream than `MT19937` and produces +//! 64-bit output. This is a good choice on 64-bit CPUs. //! -//! Both of these RNGs use approximately 2.5 kilobytes of state. -//! [`Mt19937GenRand32`] uses a 32-bit seed. [`Mt19937GenRand64`] uses a 64-bit -//! seed. Both can be seeded from an iterator of seeds. +//! Both of these RNGs use approximately 2.5 kilobytes of state. [`Mt`] uses a +//! 32-bit seed. [`Mt64`] uses a 64-bit seed. Both can be seeded from an +//! iterator of seeds. //! //! Both RNGs implement a `recover` constructor which can reconstruct the RNG //! state from a sequence of output samples. @@ -79,54 +78,34 @@ //! //! - **rand-traits** - Enables a dependency on [`rand_core`]. Activating this //! feature implements `RngCore` and `SeedableRng` on the RNGs in this crate. -//! - **std** - Enables a dependency on the Rust Standard Library. Activating -//! this feature enables [`std::error::Error`] impls on error types in this -//! crate. //! //! Mersenne Twister requires approximately 2.5 kilobytes of internal state. To //! make the RNGs implemented in this crate practical to embed in other structs, //! you may wish to store the RNG in a [`Box`]. //! #![cfg_attr( - not(feature = "std"), - doc = "[`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html" -)] -#![cfg_attr(feature = "std", doc = "[`Box`]: std::boxed::Box")] -#![cfg_attr( - not(feature = "std"), - doc = "[`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html" -)] -#![cfg_attr( - not(feature = "rand_core"), + not(feature = "rand-traits"), doc = "[`rand_core`]: https://crates.io/crates/rand_core" )] -//! +//! [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html" -#![doc(html_root_url = "https://docs.rs/rand_mt/4.2.2")] +#![doc(html_root_url = "https://docs.rs/rand_mt/5.0.0")] #![no_std] -#[cfg(feature = "std")] +#[cfg(any(test, doctest))] extern crate std; use core::fmt; -pub use crate::mt::Mt19937GenRand32; -pub use crate::mt64::Mt19937GenRand64; +pub use crate::mt::Mt; +pub use crate::mt64::Mt64; mod mt; mod mt64; #[cfg(test)] mod vectors; -/// A type alias for [`Mt19937GenRand32`], 32-bit Mersenne Twister. -pub type Mt = Mt19937GenRand32; - -/// A type alias for [`Mt19937GenRand64`], 64-bit Mersenne Twister. -pub type Mt64 = Mt19937GenRand64; - /// Error returned from fallible Mersenne Twister recovery constructors. -/// -/// When the `std` feature is enabled, this type implements `std::error::Error`. #[non_exhaustive] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub enum RecoverRngError { @@ -151,27 +130,22 @@ impl fmt::Display for RecoverRngError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::TooFewSamples(expected) => { - write!(f, "Too few samples given to recover: expected {}", expected) + write!(f, "Too few samples given to recover: expected {expected}") + } + Self::TooManySamples(expected) => { + write!(f, "Too many samples given to recover: expected {expected}") } - Self::TooManySamples(expected) => write!( - f, - "Too many samples given to recover: expected {}", - expected - ), } } } -#[cfg(feature = "std")] -impl std::error::Error for RecoverRngError {} +impl core::error::Error for RecoverRngError {} #[cfg(test)] mod tests { - #[cfg(feature = "std")] use super::RecoverRngError; #[test] - #[cfg(feature = "std")] fn error_display_is_not_empty() { use core::fmt::Write as _; use std::string::String; @@ -184,7 +158,7 @@ mod tests { ]; for tc in test_cases { let mut buf = String::new(); - write!(&mut buf, "{}", tc).unwrap(); + write!(&mut buf, "{tc}").unwrap(); assert!(!buf.is_empty()); } } diff --git a/src/mt.rs b/src/mt.rs index 25993f29a..1fe5cf120 100644 --- a/src/mt.rs +++ b/src/mt.rs @@ -11,7 +11,6 @@ use core::convert::TryFrom; use core::fmt; -use core::mem::size_of; use core::num::Wrapping; use crate::RecoverRngError; @@ -33,50 +32,45 @@ const LOWER_MASK: Wrapping = Wrapping(0x7fff_ffff); /// /// # Size /// -/// `Mt19937GenRand32` requires approximately 2.5 kilobytes of internal state. +/// `Mt` requires approximately 2.5 kilobytes of internal state. /// -/// You may wish to store an `Mt19937GenRand32` on the heap in a [`Box`] to make -/// it easier to embed in another struct. +/// You may wish to store an `Mt` on the heap in a [`Box`] to make it easier to +/// embed in another struct. /// -/// `Mt19937GenRand32` is also the same size as -/// [`Mt19937GenRand64`](crate::Mt19937GenRand64). +/// `Mt` is also the same size as [`Mt64`](crate::Mt64). /// /// ``` /// # use core::mem; -/// # use rand_mt::{Mt19937GenRand32, Mt19937GenRand64}; -/// assert_eq!(2504, mem::size_of::()); -/// assert_eq!(mem::size_of::(), mem::size_of::()); +/// # use rand_mt::{Mt, Mt64}; +/// assert_eq!(2504, size_of::()); +/// assert_eq!(size_of::(), size_of::()); /// ``` -#[cfg_attr(feature = "std", doc = "[`Box`]: std::boxed::Box")] -#[cfg_attr( - not(feature = "std"), - doc = "[`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html" -)] +/// +/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[allow(clippy::module_name_repetitions)] -pub struct Mt19937GenRand32 { +pub struct Mt { idx: usize, state: [Wrapping; N], } -impl fmt::Debug for Mt19937GenRand32 { +impl fmt::Debug for Mt { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Mt19937GenRand32 {}") + f.write_str("Mt {}") } } -impl Default for Mt19937GenRand32 { - /// Return a new `Mt19937GenRand32` with the default seed. +impl Default for Mt { + /// Return a new `Mt` with the default seed. /// - /// Equivalent to calling [`Mt19937GenRand32::new_unseeded`]. + /// Equivalent to calling [`Mt::new_unseeded`]. #[inline] fn default() -> Self { Self::new_unseeded() } } -impl From<[u8; 4]> for Mt19937GenRand32 { +impl From<[u8; 4]> for Mt { /// Construct a Mersenne Twister RNG from 4 bytes. /// /// The given bytes are treated as a little endian encoded `u32`. @@ -84,21 +78,21 @@ impl From<[u8; 4]> for Mt19937GenRand32 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand32; + /// # use rand_mt::Mt; /// // Default MT seed /// let seed = 5489_u32.to_le_bytes(); - /// let mut mt = Mt19937GenRand32::from(seed); + /// let mut mt = Mt::from(seed); /// assert_ne!(mt.next_u32(), mt.next_u32()); /// ``` /// /// This constructor is equivalent to passing a little endian encoded `u32`. /// /// ``` - /// # use rand_mt::Mt19937GenRand32; + /// # use rand_mt::Mt; /// // Default MT seed /// let seed = 5489_u32.to_le_bytes(); - /// let mt1 = Mt19937GenRand32::from(seed); - /// let mt2 = Mt19937GenRand32::new(5489_u32); + /// let mt1 = Mt::from(seed); + /// let mt2 = Mt::new(5489_u32); /// assert_eq!(mt1, mt2); /// ``` #[inline] @@ -107,7 +101,7 @@ impl From<[u8; 4]> for Mt19937GenRand32 { } } -impl From for Mt19937GenRand32 { +impl From for Mt { /// Construct a Mersenne Twister RNG from a `u32` seed. /// /// This function is equivalent to [`new`]. @@ -115,17 +109,17 @@ impl From for Mt19937GenRand32 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand32; + /// # use rand_mt::Mt; /// // Default MT seed /// let seed = 5489_u32; - /// let mt1 = Mt19937GenRand32::from(seed); - /// let mt2 = Mt19937GenRand32::new(seed); + /// let mt1 = Mt::from(seed); + /// let mt2 = Mt::new(seed); /// assert_eq!(mt1, mt2); /// /// // Non-default MT seed /// let seed = 9927_u32; - /// let mt1 = Mt19937GenRand32::from(seed); - /// let mt2 = Mt19937GenRand32::new(seed); + /// let mt1 = Mt::from(seed); + /// let mt2 = Mt::new(seed); /// assert_eq!(mt1, mt2); /// ``` /// @@ -136,7 +130,7 @@ impl From for Mt19937GenRand32 { } } -impl From<[u32; N]> for Mt19937GenRand32 { +impl From<[u32; N]> for Mt { /// Recover the internal state of a Mersenne Twister using the past 624 /// samples. /// @@ -156,17 +150,16 @@ impl From<[u32; N]> for Mt19937GenRand32 { } } -impl TryFrom<&[u32]> for Mt19937GenRand32 { +impl TryFrom<&[u32]> for Mt { type Error = RecoverRngError; /// Attempt to recover the internal state of a Mersenne Twister using the /// past 624 samples. /// - /// This conversion takes a history of samples from a RNG and returns a - /// RNG that will produce identical output to the RNG that supplied the - /// samples. + /// This conversion takes a history of samples from a RNG and returns a RNG + /// that will produce identical output to the RNG that supplied the samples. /// - /// This conversion is implemented with [`Mt19937GenRand32::recover`]. + /// This conversion is implemented with [`Mt::recover`]. /// /// # Errors /// @@ -182,8 +175,8 @@ impl TryFrom<&[u32]> for Mt19937GenRand32 { } } -impl Mt19937GenRand32 { - /// Default seed used by [`Mt19937GenRand32::new_unseeded`]. +impl Mt { + /// Default seed used by [`Mt::new_unseeded`]. pub const DEFAULT_SEED: u32 = 5489_u32; /// Create a new Mersenne Twister random number generator using the given @@ -194,19 +187,19 @@ impl Mt19937GenRand32 { /// ## Constructing with a `u32` seed /// /// ``` - /// # use rand_mt::Mt19937GenRand32; + /// # use rand_mt::Mt; /// let seed = 123_456_789_u32; - /// let mt1 = Mt19937GenRand32::new(seed); - /// let mt2 = Mt19937GenRand32::from(seed.to_le_bytes()); + /// let mt1 = Mt::new(seed); + /// let mt2 = Mt::from(seed.to_le_bytes()); /// assert_eq!(mt1, mt2); /// ``` /// /// ## Constructing with default seed /// /// ``` - /// # use rand_mt::Mt19937GenRand32; - /// let mt1 = Mt19937GenRand32::new(Mt19937GenRand32::DEFAULT_SEED); - /// let mt2 = Mt19937GenRand32::new_unseeded(); + /// # use rand_mt::Mt; + /// let mt1 = Mt::new(Mt::DEFAULT_SEED); + /// let mt2 = Mt::new_unseeded(); /// assert_eq!(mt1, mt2); /// ``` #[inline] @@ -245,11 +238,11 @@ impl Mt19937GenRand32 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand32; + /// # use rand_mt::Mt; /// // Default MT seed /// let seed = 5489_u32; - /// let mt = Mt19937GenRand32::new(seed); - /// let unseeded = Mt19937GenRand32::new_unseeded(); + /// let mt = Mt::new(seed); + /// let unseeded = Mt::new_unseeded(); /// assert_eq!(mt, unseeded); /// ``` #[inline] @@ -266,8 +259,8 @@ impl Mt19937GenRand32 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand32; - /// let mut mt = Mt19937GenRand32::new_unseeded(); + /// # use rand_mt::Mt; + /// let mut mt = Mt::new_unseeded(); /// assert_ne!(mt.next_u64(), mt.next_u64()); /// ``` #[inline] @@ -285,8 +278,8 @@ impl Mt19937GenRand32 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand32; - /// let mut mt = Mt19937GenRand32::new_unseeded(); + /// # use rand_mt::Mt; + /// let mut mt = Mt::new_unseeded(); /// assert_ne!(mt.next_u32(), mt.next_u32()); /// ``` #[inline] @@ -313,8 +306,8 @@ impl Mt19937GenRand32 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand32; - /// let mut mt = Mt19937GenRand32::new_unseeded(); + /// # use rand_mt::Mt; + /// let mut mt = Mt::new_unseeded(); /// let mut buf = [0; 32]; /// mt.fill_bytes(&mut buf); /// assert_ne!([0; 32], buf); @@ -391,9 +384,9 @@ impl Mt19937GenRand32 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand32; + /// # use rand_mt::Mt; /// // Default MT seed - /// let mut mt = Mt19937GenRand32::new_unseeded(); + /// let mut mt = Mt::new_unseeded(); /// let first = mt.next_u32(); /// mt.fill_bytes(&mut [0; 512]); /// // Default MT seed @@ -401,7 +394,10 @@ impl Mt19937GenRand32 { /// assert_eq!(first, mt.next_u32()); /// ``` #[inline] - #[allow(clippy::cast_possible_truncation)] + #[expect( + clippy::cast_possible_truncation, + reason = "const N is always less than u32::MAX" + )] pub fn reseed(&mut self, seed: u32) { self.idx = N; self.state[0] = Wrapping(seed); @@ -481,7 +477,7 @@ fn untemper(mut x: u32) -> u32 { } #[inline] -fn fill_next_state(rng: &mut Mt19937GenRand32) { +fn fill_next_state(rng: &mut Mt) { for i in 0..N - M { let x = (rng.state[i] & UPPER_MASK) | (rng.state[i + 1] & LOWER_MASK); rng.state[i] = rng.state[i + M] ^ (x >> 1) ^ ((x & ONE) * MATRIX_A); @@ -501,14 +497,14 @@ mod tests { use core::iter; use core::num::Wrapping; - use super::{Mt19937GenRand32, N}; + use super::{Mt, N}; use crate::vectors::mt::{STATE_SEEDED_BY_SLICE, STATE_SEEDED_BY_U32, TEST_OUTPUT}; use crate::RecoverRngError; #[test] fn seeded_state_from_u32_seed() { - let mt = Mt19937GenRand32::new(0x1234_5678_u32); - let mt_from_seed = Mt19937GenRand32::from(0x1234_5678_u32.to_le_bytes()); + let mt = Mt::new(0x1234_5678_u32); + let mt_from_seed = Mt::from(0x1234_5678_u32.to_le_bytes()); assert_eq!(mt.state, mt_from_seed.state); for (&Wrapping(x), &y) in mt.state.iter().zip(STATE_SEEDED_BY_U32.iter()) { assert_eq!(x, y); @@ -521,7 +517,7 @@ mod tests { #[test] fn seeded_state_from_u32_slice_key() { let key = [0x123_u32, 0x234_u32, 0x345_u32, 0x456_u32]; - let mt = Mt19937GenRand32::new_with_key(key.iter().copied()); + let mt = Mt::new_with_key(key.iter().copied()); for (&Wrapping(x), &y) in mt.state.iter().zip(STATE_SEEDED_BY_SLICE.iter()) { assert_eq!(x, y); } @@ -529,13 +525,13 @@ mod tests { #[test] fn seed_with_empty_iter_returns() { - let _rng = Mt19937GenRand32::new_with_key(iter::empty()); + let _rng = Mt::new_with_key(iter::empty()); } #[test] fn output_from_u32_slice_key() { let key = [0x123_u32, 0x234_u32, 0x345_u32, 0x456_u32]; - let mut mt = Mt19937GenRand32::new_with_key(key.iter().copied()); + let mut mt = Mt::new_with_key(key.iter().copied()); for &x in &TEST_OUTPUT { assert_eq!(x, mt.next_u32()); } @@ -543,36 +539,26 @@ mod tests { #[test] fn temper_untemper_is_identity() { - let mut buf = [0; 4]; for _ in 0..10_000 { - getrandom::getrandom(&mut buf).unwrap(); - let x = u32::from_le_bytes(buf); - assert_eq!(x, super::untemper(super::temper(x))); - let x = u32::from_be_bytes(buf); + let x = getrandom::u32().unwrap(); assert_eq!(x, super::untemper(super::temper(x))); } } #[test] fn untemper_temper_is_identity() { - let mut buf = [0; 4]; for _ in 0..10_000 { - getrandom::getrandom(&mut buf).unwrap(); - let x = u32::from_le_bytes(buf); - assert_eq!(x, super::temper(super::untemper(x))); - let x = u32::from_be_bytes(buf); + let x = getrandom::u32().unwrap(); assert_eq!(x, super::temper(super::untemper(x))); } } #[test] fn recovery_via_from() { - let mut buf = [0; 4]; for _ in 0..100 { - getrandom::getrandom(&mut buf).unwrap(); - let seed = u32::from_le_bytes(buf); + let seed = getrandom::u32().unwrap(); for skip in 0..256 { - let mut orig_mt = Mt19937GenRand32::new(seed); + let mut orig_mt = Mt::new(seed); // skip some samples so the RNG is in an intermediate state for _ in 0..skip { orig_mt.next_u32(); @@ -581,7 +567,7 @@ mod tests { for sample in &mut samples { *sample = orig_mt.next_u32(); } - let mut recovered_mt = Mt19937GenRand32::from(samples); + let mut recovered_mt = Mt::from(samples); for _ in 0..624 * 2 { assert_eq!(orig_mt.next_u32(), recovered_mt.next_u32()); } @@ -591,12 +577,10 @@ mod tests { #[test] fn recovery_via_recover() { - let mut buf = [0; 4]; for _ in 0..100 { - getrandom::getrandom(&mut buf).unwrap(); - let seed = u32::from_le_bytes(buf); + let seed = getrandom::u32().unwrap(); for skip in 0..256 { - let mut orig_mt = Mt19937GenRand32::new(seed); + let mut orig_mt = Mt::new(seed); // skip some samples so the RNG is in an intermediate state for _ in 0..skip { orig_mt.next_u32(); @@ -605,7 +589,7 @@ mod tests { for sample in &mut samples { *sample = orig_mt.next_u32(); } - let mut recovered_mt = Mt19937GenRand32::recover(samples.iter().copied()).unwrap(); + let mut recovered_mt = Mt::recover(samples.iter().copied()).unwrap(); for _ in 0..624 * 2 { assert_eq!(orig_mt.next_u32(), recovered_mt.next_u32()); } @@ -616,24 +600,24 @@ mod tests { #[test] fn recover_required_exact_sample_length_via_from() { assert_eq!( - Mt19937GenRand32::try_from(&[0; 0][..]), + Mt::try_from(&[0; 0][..]), Err(RecoverRngError::TooFewSamples(N)) ); assert_eq!( - Mt19937GenRand32::try_from(&[0; 1][..]), + Mt::try_from(&[0; 1][..]), Err(RecoverRngError::TooFewSamples(N)) ); assert_eq!( - Mt19937GenRand32::try_from(&[0; 623][..]), + Mt::try_from(&[0; 623][..]), Err(RecoverRngError::TooFewSamples(N)) ); - Mt19937GenRand32::try_from(&[0; 624][..]).unwrap(); + Mt::try_from(&[0; 624][..]).unwrap(); assert_eq!( - Mt19937GenRand32::try_from(&[0; 625][..]), + Mt::try_from(&[0; 625][..]), Err(RecoverRngError::TooManySamples(N)) ); assert_eq!( - Mt19937GenRand32::try_from(&[0; 1000][..]), + Mt::try_from(&[0; 1000][..]), Err(RecoverRngError::TooManySamples(N)) ); } @@ -641,53 +625,52 @@ mod tests { #[test] fn recover_required_exact_sample_length_via_recover() { assert_eq!( - Mt19937GenRand32::recover([0; 0].iter().copied()), + Mt::recover([0; 0].iter().copied()), Err(RecoverRngError::TooFewSamples(N)) ); assert_eq!( - Mt19937GenRand32::recover([0; 1].iter().copied()), + Mt::recover([0; 1].iter().copied()), Err(RecoverRngError::TooFewSamples(N)) ); assert_eq!( - Mt19937GenRand32::recover([0; 623].iter().copied()), + Mt::recover([0; 623].iter().copied()), Err(RecoverRngError::TooFewSamples(N)) ); - Mt19937GenRand32::recover([0; 624].iter().copied()).unwrap(); + Mt::recover([0; 624].iter().copied()).unwrap(); assert_eq!( - Mt19937GenRand32::recover([0; 625].iter().copied()), + Mt::recover([0; 625].iter().copied()), Err(RecoverRngError::TooManySamples(N)) ); assert_eq!( - Mt19937GenRand32::recover([0; 1000].iter().copied()), + Mt::recover([0; 1000].iter().copied()), Err(RecoverRngError::TooManySamples(N)) ); } #[test] - #[cfg(feature = "std")] fn fmt_debug_does_not_leak_seed() { use core::fmt::Write as _; use std::string::String; - let random = Mt19937GenRand32::new(874); + let random = Mt::new(874); let mut buf = String::new(); - write!(&mut buf, "{:?}", random).unwrap(); + write!(&mut buf, "{random:?}").unwrap(); assert!(!buf.contains("874")); - assert_eq!(buf, "Mt19937GenRand32 {}"); + assert_eq!(buf, "Mt {}"); - let random = Mt19937GenRand32::new(123_456); + let random = Mt::new(123_456); let mut buf = String::new(); - write!(&mut buf, "{:?}", random).unwrap(); + write!(&mut buf, "{random:?}").unwrap(); assert!(!buf.contains("123456")); - assert_eq!(buf, "Mt19937GenRand32 {}"); + assert_eq!(buf, "Mt {}"); } #[test] fn default_is_new_unseeded() { - let mut default = Mt19937GenRand32::default(); - let mut unseeded = Mt19937GenRand32::new_unseeded(); + let mut default = Mt::default(); + let mut unseeded = Mt::new_unseeded(); assert_eq!(default, unseeded); for _ in 0..1024 { diff --git a/src/mt/rand.rs b/src/mt/rand.rs index db21e4018..08fe9d65c 100644 --- a/src/mt/rand.rs +++ b/src/mt/rand.rs @@ -9,11 +9,11 @@ // 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 rand_core::{RngCore, SeedableRng}; -use super::Mt19937GenRand32; +use super::Mt; -impl SeedableRng for Mt19937GenRand32 { +impl SeedableRng for Mt { type Seed = [u8; 4]; /// Reseed from a little endian encoded `u32`. @@ -22,11 +22,11 @@ impl SeedableRng for Mt19937GenRand32 { /// /// ``` /// use rand_core::{RngCore, SeedableRng}; - /// use rand_mt::Mt19937GenRand32; + /// use rand_mt::Mt; /// /// // Default MT seed /// let seed = 5489_u32.to_le_bytes(); - /// let mut rng = Mt19937GenRand32::from_seed(seed); + /// let mut rng = Mt::from_seed(seed); /// # fn example(mut rng: T) { /// assert_ne!(rng.next_u32(), rng.next_u32()); /// # } @@ -38,7 +38,7 @@ impl SeedableRng for Mt19937GenRand32 { } } -impl RngCore for Mt19937GenRand32 { +impl RngCore for Mt { /// Generate next `u64` output. /// /// This function is implemented by generating two `u32`s from the RNG and @@ -48,9 +48,9 @@ impl RngCore for Mt19937GenRand32 { /// /// ``` /// use rand_core::RngCore; - /// use rand_mt::Mt19937GenRand32; + /// use rand_mt::Mt; /// - /// let mut rng = Mt19937GenRand32::new_unseeded(); + /// let mut rng = Mt::new_unseeded(); /// # fn example(mut rng: T) { /// assert_ne!(rng.next_u64(), rng.next_u64()); /// # } @@ -70,9 +70,9 @@ impl RngCore for Mt19937GenRand32 { /// /// ``` /// use rand_core::RngCore; - /// use rand_mt::Mt19937GenRand32; + /// use rand_mt::Mt; /// - /// let mut rng = Mt19937GenRand32::new_unseeded(); + /// let mut rng = Mt::new_unseeded(); /// # fn example(mut rng: T) { /// assert_ne!(rng.next_u32(), rng.next_u32()); /// # } @@ -95,9 +95,9 @@ impl RngCore for Mt19937GenRand32 { /// /// ``` /// use rand_core::RngCore; - /// use rand_mt::Mt19937GenRand32; + /// use rand_mt::Mt; /// - /// let mut rng = Mt19937GenRand32::new_unseeded(); + /// let mut rng = Mt::new_unseeded(); /// # fn example(mut rng: T) { /// let mut buf = [0; 32]; /// rng.fill_bytes(&mut buf); @@ -112,41 +112,6 @@ impl RngCore for Mt19937GenRand32 { 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 `u32`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 4. - /// - /// `try_fill_bytes` is implemented with [`fill_bytes`](RngCore::fill_bytes) - /// and is infallible. - /// - /// # Examples - /// - /// ``` - /// use rand_core::RngCore; - /// use rand_mt::Mt19937GenRand32; - /// - /// let mut rng = Mt19937GenRand32::new_unseeded(); - /// # fn example(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)] @@ -154,13 +119,13 @@ mod tests { use core::num::Wrapping; use rand_core::{RngCore, SeedableRng}; - use super::Mt19937GenRand32; + use super::Mt; use crate::vectors::mt::{STATE_SEEDED_BY_U32, TEST_OUTPUT}; #[test] fn seeded_state_from_u32_seed() { - let rng = Mt19937GenRand32::new(0x1234_5678_u32); - let rng_from_seed = Mt19937GenRand32::from_seed(0x1234_5678_u32.to_le_bytes()); + let rng = Mt::new(0x1234_5678_u32); + let rng_from_seed = Mt::from_seed(0x1234_5678_u32.to_le_bytes()); assert_eq!(rng.state, rng_from_seed.state); for (&Wrapping(x), &y) in rng.state.iter().zip(STATE_SEEDED_BY_U32.iter()) { assert_eq!(x, y); @@ -173,7 +138,7 @@ mod tests { #[test] fn output_from_u32_slice_key() { let key = [0x123_u32, 0x234_u32, 0x345_u32, 0x456_u32]; - let mut rng = Mt19937GenRand32::new_with_key(key.iter().copied()); + let mut rng = Mt::new_with_key(key.iter().copied()); for &x in &TEST_OUTPUT { assert_eq!(x, RngCore::next_u32(&mut rng)); } diff --git a/src/mt64.rs b/src/mt64.rs index 630527c16..c55bfe2ad 100644 --- a/src/mt64.rs +++ b/src/mt64.rs @@ -11,7 +11,6 @@ use core::convert::TryFrom; use core::fmt; -use core::mem::size_of; use core::num::Wrapping; use crate::RecoverRngError; @@ -26,63 +25,57 @@ const MATRIX_A: Wrapping = Wrapping(0xb502_6f5a_a966_19e9); const UM: Wrapping = Wrapping(0xffff_ffff_8000_0000); // Most significant 33 bits const LM: Wrapping = Wrapping(0x7fff_ffff); // Least significant 31 bits -/// The 64-bit flavor of the Mersenne Twister pseudorandom number -/// generator. +/// The 64-bit flavor of the Mersenne Twister pseudorandom number generator. /// /// # Size /// -/// `Mt19937GenRand64` requires approximately 2.5 kilobytes of internal state. +/// `Mt64` requires approximately 2.5 kilobytes of internal state. /// -/// You may wish to store an `Mt19937GenRand64` on the heap in a [`Box`] to make it -/// easier to embed in another struct. +/// You may wish to store an `Mt64` on the heap in a [`Box`] to make it easier +/// to embed in another struct. /// -/// `Mt19937GenRand64` is also the same size as -/// [`Mt19937GenRand32`](crate::Mt19937GenRand32). +/// `Mt64` is also the same size as [`Mt`](crate::Mt). /// /// ``` -/// # use core::mem; -/// # use rand_mt::{Mt19937GenRand32, Mt19937GenRand64}; -/// assert_eq!(2504, mem::size_of::()); -/// assert_eq!(mem::size_of::(), mem::size_of::()); +/// # use rand_mt::{Mt, Mt64}; +/// assert_eq!(2504, size_of::()); +/// assert_eq!(size_of::(), size_of::()); /// ``` -#[cfg_attr(feature = "std", doc = "[`Box`]: std::boxed::Box")] -#[cfg_attr( - not(feature = "std"), - doc = "[`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html" -)] +/// +/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct Mt19937GenRand64 { +pub struct Mt64 { idx: usize, state: [Wrapping; NN], } -impl fmt::Debug for Mt19937GenRand64 { +impl fmt::Debug for Mt64 { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Mt19937GenRand64 {}") + f.write_str("Mt64 {}") } } -impl Default for Mt19937GenRand64 { - /// Return a new `Mt19937GenRand64` with the default seed. +impl Default for Mt64 { + /// Return a new `Mt64` with the default seed. /// - /// Equivalent to calling [`Mt19937GenRand64::new_unseeded`]. + /// Equivalent to calling [`Mt64::new_unseeded`]. #[inline] fn default() -> Self { Self::new_unseeded() } } -impl From<[u8; 8]> for Mt19937GenRand64 { +impl From<[u8; 8]> for Mt64 { /// Construct a Mersenne Twister RNG from 8 bytes. /// /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand64; + /// # use rand_mt::Mt64; /// // Default MT seed /// let seed = 5489_u64.to_le_bytes(); - /// let mut mt = Mt19937GenRand64::from(seed); + /// let mut mt = Mt64::from(seed); /// assert_ne!(mt.next_u64(), mt.next_u64()); /// ``` #[inline] @@ -91,7 +84,7 @@ impl From<[u8; 8]> for Mt19937GenRand64 { } } -impl From for Mt19937GenRand64 { +impl From for Mt64 { /// Construct a Mersenne Twister RNG from a `u64` seed. /// /// This function is equivalent to [`new`]. @@ -99,17 +92,17 @@ impl From for Mt19937GenRand64 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand64; + /// # use rand_mt::Mt64; /// // Default MT seed /// let seed = 5489_u64; - /// let mt1 = Mt19937GenRand64::from(seed); - /// let mt2 = Mt19937GenRand64::new(seed); + /// let mt1 = Mt64::from(seed); + /// let mt2 = Mt64::new(seed); /// assert_eq!(mt1, mt2); /// /// // Non-default MT seed /// let seed = 9927_u64; - /// let mt1 = Mt19937GenRand64::from(seed); - /// let mt2 = Mt19937GenRand64::new(seed); + /// let mt1 = Mt64::from(seed); + /// let mt2 = Mt64::new(seed); /// assert_eq!(mt1, mt2); /// ``` /// @@ -120,7 +113,7 @@ impl From for Mt19937GenRand64 { } } -impl From<[u64; NN]> for Mt19937GenRand64 { +impl From<[u64; NN]> for Mt64 { /// Recover the internal state of a Mersenne Twister using the past 312 /// samples. /// @@ -140,7 +133,7 @@ impl From<[u64; NN]> for Mt19937GenRand64 { } } -impl TryFrom<&[u64]> for Mt19937GenRand64 { +impl TryFrom<&[u64]> for Mt64 { type Error = RecoverRngError; /// Attempt to recover the internal state of a Mersenne Twister using the @@ -150,7 +143,7 @@ impl TryFrom<&[u64]> for Mt19937GenRand64 { /// RNG that will produce identical output to the RNG that supplied the /// samples. /// - /// This conversion is implemented with [`Mt19937GenRand64::recover`]. + /// This conversion is implemented with [`Mt64::recover`]. /// /// # Errors /// @@ -166,8 +159,8 @@ impl TryFrom<&[u64]> for Mt19937GenRand64 { } } -impl Mt19937GenRand64 { - /// Default seed used by [`Mt19937GenRand64::new_unseeded`]. +impl Mt64 { + /// Default seed used by [`Mt64::new_unseeded`]. pub const DEFAULT_SEED: u64 = 5489_u64; /// Create a new Mersenne Twister random number generator using the given @@ -178,19 +171,19 @@ impl Mt19937GenRand64 { /// ## Constructing with a `u64` seed /// /// ``` - /// # use rand_mt::Mt19937GenRand64; + /// # use rand_mt::Mt64; /// let seed = 123_456_789_u64; - /// let mt1 = Mt19937GenRand64::new(seed); - /// let mt2 = Mt19937GenRand64::from(seed.to_le_bytes()); + /// let mt1 = Mt64::new(seed); + /// let mt2 = Mt64::from(seed.to_le_bytes()); /// assert_eq!(mt1, mt2); /// ``` /// /// ## Constructing with default seed /// /// ``` - /// # use rand_mt::Mt19937GenRand64; - /// let mt1 = Mt19937GenRand64::new(Mt19937GenRand64::DEFAULT_SEED); - /// let mt2 = Mt19937GenRand64::new_unseeded(); + /// # use rand_mt::Mt64; + /// let mt1 = Mt64::new(Mt64::DEFAULT_SEED); + /// let mt2 = Mt64::new_unseeded(); /// assert_eq!(mt1, mt2); /// ``` #[inline] @@ -229,11 +222,11 @@ impl Mt19937GenRand64 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand64; + /// # use rand_mt::Mt64; /// // Default MT seed /// let seed = 5489_u64; - /// let mt = Mt19937GenRand64::new(seed); - /// let unseeded = Mt19937GenRand64::new_unseeded(); + /// let mt = Mt64::new(seed); + /// let unseeded = Mt64::new_unseeded(); /// assert_eq!(mt, unseeded); /// ``` #[inline] @@ -250,8 +243,8 @@ impl Mt19937GenRand64 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand64; - /// let mut mt = Mt19937GenRand64::new_unseeded(); + /// # use rand_mt::Mt64; + /// let mut mt = Mt64::new_unseeded(); /// assert_ne!(mt.next_u64(), mt.next_u64()); /// ``` #[inline] @@ -275,12 +268,15 @@ impl Mt19937GenRand64 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand64; - /// let mut mt = Mt19937GenRand64::new_unseeded(); + /// # use rand_mt::Mt64; + /// let mut mt = Mt64::new_unseeded(); /// assert_ne!(mt.next_u32(), mt.next_u32()); /// ``` #[inline] - #[allow(clippy::cast_possible_truncation)] + #[expect( + clippy::cast_possible_truncation, + reason = "Mt64 natively generates 64-bit ints, so truncate to yield a u32" + )] pub fn next_u32(&mut self) -> u32 { self.next_u64() as u32 } @@ -296,8 +292,8 @@ impl Mt19937GenRand64 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand64; - /// let mut mt = Mt19937GenRand64::new_unseeded(); + /// # use rand_mt::Mt64; + /// let mut mt = Mt64::new_unseeded(); /// let mut buf = [0; 32]; /// mt.fill_bytes(&mut buf); /// assert_ne!([0; 32], buf); @@ -374,9 +370,9 @@ impl Mt19937GenRand64 { /// # Examples /// /// ``` - /// # use rand_mt::Mt19937GenRand64; + /// # use rand_mt::Mt64; /// // Default MT seed - /// let mut mt = Mt19937GenRand64::new_unseeded(); + /// let mut mt = Mt64::new_unseeded(); /// let first = mt.next_u64(); /// mt.fill_bytes(&mut [0; 512]); /// // Default MT seed @@ -398,7 +394,6 @@ impl Mt19937GenRand64 { /// /// Key can have any length. #[inline] - #[allow(clippy::cast_possible_truncation)] pub fn reseed_with_key(&mut self, key: I) where I: IntoIterator, @@ -463,7 +458,7 @@ fn untemper(mut x: u64) -> u64 { } #[inline] -fn fill_next_state(rng: &mut Mt19937GenRand64) { +fn fill_next_state(rng: &mut Mt64) { for i in 0..NN - MM { let x = (rng.state[i] & UM) | (rng.state[i + 1] & LM); rng.state[i] = rng.state[i + MM] ^ (x >> 1) ^ ((x & ONE) * MATRIX_A); @@ -482,14 +477,14 @@ mod tests { use core::convert::TryFrom; use core::num::Wrapping; - use super::{Mt19937GenRand64, NN}; + use super::{Mt64, NN}; use crate::vectors::mt64::{STATE_SEEDED_BY_SLICE, STATE_SEEDED_BY_U64, TEST_OUTPUT}; use crate::RecoverRngError; #[test] fn seeded_state_from_u64_seed() { - let mt = Mt19937GenRand64::new(0x0123_4567_89ab_cdef_u64); - let mt_from_seed = Mt19937GenRand64::from(0x0123_4567_89ab_cdef_u64.to_le_bytes()); + let mt = Mt64::new(0x0123_4567_89ab_cdef_u64); + let mt_from_seed = Mt64::from(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); @@ -502,7 +497,7 @@ mod tests { #[test] fn seeded_state_from_u64_slice_key() { let key = [0x12345_u64, 0x23456_u64, 0x34567_u64, 0x45678_u64]; - let mt = Mt19937GenRand64::new_with_key(key.iter().copied()); + let mt = Mt64::new_with_key(key.iter().copied()); for (&Wrapping(x), &y) in mt.state.iter().zip(STATE_SEEDED_BY_SLICE.iter()) { assert_eq!(x, y); } @@ -510,13 +505,13 @@ mod tests { #[test] fn seed_with_empty_iter_returns() { - let _rng = Mt19937GenRand64::new_with_key(core::iter::empty()); + let _rng = Mt64::new_with_key(core::iter::empty()); } #[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()); + let mut mt = Mt64::new_with_key(key.iter().copied()); for &x in &TEST_OUTPUT { assert_eq!(x, mt.next_u64()); } @@ -524,36 +519,26 @@ mod tests { #[test] fn temper_untemper_is_identity() { - let mut buf = [0; 8]; for _ in 0..10_000 { - getrandom::getrandom(&mut buf).unwrap(); - let x = u64::from_le_bytes(buf); - assert_eq!(x, super::untemper(super::temper(x))); - let x = u64::from_be_bytes(buf); + let x = getrandom::u64().unwrap(); assert_eq!(x, super::untemper(super::temper(x))); } } #[test] fn untemper_temper_is_identity() { - let mut buf = [0; 8]; for _ in 0..10_000 { - getrandom::getrandom(&mut buf).unwrap(); - let x = u64::from_le_bytes(buf); - assert_eq!(x, super::temper(super::untemper(x))); - let x = u64::from_be_bytes(buf); + let x = getrandom::u64().unwrap(); assert_eq!(x, super::temper(super::untemper(x))); } } #[test] fn recovery_via_from() { - let mut buf = [0; 8]; for _ in 0..100 { - getrandom::getrandom(&mut buf).unwrap(); - let seed = u64::from_le_bytes(buf); + let seed = getrandom::u64().unwrap(); for skip in 0..256 { - let mut orig_mt = Mt19937GenRand64::new(seed); + let mut orig_mt = Mt64::new(seed); // skip some samples so the RNG is in an intermediate state for _ in 0..skip { orig_mt.next_u64(); @@ -562,7 +547,7 @@ mod tests { for sample in &mut samples { *sample = orig_mt.next_u64(); } - let mut recovered_mt = Mt19937GenRand64::from(samples); + let mut recovered_mt = Mt64::from(samples); for _ in 0..312 * 2 { assert_eq!(orig_mt.next_u64(), recovered_mt.next_u64()); } @@ -572,12 +557,10 @@ mod tests { #[test] fn recovery_via_recover() { - let mut buf = [0; 8]; for _ in 0..100 { - getrandom::getrandom(&mut buf).unwrap(); - let seed = u64::from_le_bytes(buf); + let seed = getrandom::u64().unwrap(); for skip in 0..256 { - let mut orig_mt = Mt19937GenRand64::new(seed); + let mut orig_mt = Mt64::new(seed); // skip some samples so the RNG is in an intermediate state for _ in 0..skip { orig_mt.next_u64(); @@ -586,7 +569,7 @@ mod tests { for sample in &mut samples { *sample = orig_mt.next_u64(); } - let mut recovered_mt = Mt19937GenRand64::recover(samples.iter().copied()).unwrap(); + let mut recovered_mt = Mt64::recover(samples.iter().copied()).unwrap(); for _ in 0..312 * 2 { assert_eq!(orig_mt.next_u64(), recovered_mt.next_u64()); } @@ -597,24 +580,24 @@ mod tests { #[test] fn recover_required_exact_sample_length_via_from() { assert_eq!( - Mt19937GenRand64::try_from(&[0; 0][..]), + Mt64::try_from(&[0; 0][..]), Err(RecoverRngError::TooFewSamples(NN)) ); assert_eq!( - Mt19937GenRand64::try_from(&[0; 1][..]), + Mt64::try_from(&[0; 1][..]), Err(RecoverRngError::TooFewSamples(NN)) ); assert_eq!( - Mt19937GenRand64::try_from(&[0; 311][..]), + Mt64::try_from(&[0; 311][..]), Err(RecoverRngError::TooFewSamples(NN)) ); - Mt19937GenRand64::try_from(&[0; 312][..]).unwrap(); + Mt64::try_from(&[0; 312][..]).unwrap(); assert_eq!( - Mt19937GenRand64::try_from(&[0; 313][..]), + Mt64::try_from(&[0; 313][..]), Err(RecoverRngError::TooManySamples(NN)) ); assert_eq!( - Mt19937GenRand64::try_from(&[0; 1000][..]), + Mt64::try_from(&[0; 1000][..]), Err(RecoverRngError::TooManySamples(NN)) ); } @@ -622,53 +605,52 @@ mod tests { #[test] fn recover_required_exact_sample_length_via_recover() { assert_eq!( - Mt19937GenRand64::recover([0; 0].iter().copied()), + Mt64::recover([0; 0].iter().copied()), Err(RecoverRngError::TooFewSamples(NN)) ); assert_eq!( - Mt19937GenRand64::recover([0; 1].iter().copied()), + Mt64::recover([0; 1].iter().copied()), Err(RecoverRngError::TooFewSamples(NN)) ); assert_eq!( - Mt19937GenRand64::recover([0; 311].iter().copied()), + Mt64::recover([0; 311].iter().copied()), Err(RecoverRngError::TooFewSamples(NN)) ); - Mt19937GenRand64::recover([0; 312].iter().copied()).unwrap(); + Mt64::recover([0; 312].iter().copied()).unwrap(); assert_eq!( - Mt19937GenRand64::recover([0; 313].iter().copied()), + Mt64::recover([0; 313].iter().copied()), Err(RecoverRngError::TooManySamples(NN)) ); assert_eq!( - Mt19937GenRand64::recover([0; 1000].iter().copied()), + Mt64::recover([0; 1000].iter().copied()), Err(RecoverRngError::TooManySamples(NN)) ); } #[test] - #[cfg(feature = "std")] fn fmt_debug_does_not_leak_seed() { use core::fmt::Write as _; use std::string::String; - let random = Mt19937GenRand64::new(874); + let random = Mt64::new(874); let mut buf = String::new(); - write!(&mut buf, "{:?}", random).unwrap(); + write!(&mut buf, "{random:?}").unwrap(); assert!(!buf.contains("874")); - assert_eq!(buf, "Mt19937GenRand64 {}"); + assert_eq!(buf, "Mt64 {}"); - let random = Mt19937GenRand64::new(123_456); + let random = Mt64::new(123_456); let mut buf = String::new(); - write!(&mut buf, "{:?}", random).unwrap(); + write!(&mut buf, "{random:?}").unwrap(); assert!(!buf.contains("123456")); - assert_eq!(buf, "Mt19937GenRand64 {}"); + assert_eq!(buf, "Mt64 {}"); } #[test] fn default_is_new_unseeded() { - let mut default = Mt19937GenRand64::default(); - let mut unseeded = Mt19937GenRand64::new_unseeded(); + let mut default = Mt64::default(); + let mut unseeded = Mt64::new_unseeded(); assert_eq!(default, unseeded); for _ in 0..1024 { diff --git a/src/mt64/rand.rs b/src/mt64/rand.rs index 607fad1e9..44a3e4d42 100644 --- a/src/mt64/rand.rs +++ b/src/mt64/rand.rs @@ -9,11 +9,11 @@ // 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 rand_core::{RngCore, SeedableRng}; -use super::Mt19937GenRand64; +use super::Mt64; -impl SeedableRng for Mt19937GenRand64 { +impl SeedableRng for Mt64 { type Seed = [u8; 8]; /// Reseed from a little endian encoded `u64`. @@ -22,10 +22,10 @@ impl SeedableRng for Mt19937GenRand64 { /// /// ``` /// # use rand_core::{RngCore, SeedableRng}; - /// # use rand_mt::Mt19937GenRand64; + /// # use rand_mt::Mt64; /// // Default MT seed /// let seed = 5489_u64.to_le_bytes(); - /// let mut mt = Mt19937GenRand64::from_seed(seed); + /// let mut mt = Mt64::from_seed(seed); /// assert_ne!(mt.next_u64(), mt.next_u64()); /// ``` #[inline] @@ -34,7 +34,7 @@ impl SeedableRng for Mt19937GenRand64 { } } -impl RngCore for Mt19937GenRand64 { +impl RngCore for Mt64 { /// Generate next `u64` output. /// /// `u64` is the native output of the generator. This function advances the @@ -44,9 +44,9 @@ impl RngCore for Mt19937GenRand64 { /// /// ``` /// use rand_core::RngCore; - /// use rand_mt::Mt19937GenRand64; + /// use rand_mt::Mt64; /// - /// let mut rng = Mt19937GenRand64::new_unseeded(); + /// let mut rng = Mt64::new_unseeded(); /// # fn example(mut rng: T) { /// assert_ne!(rng.next_u64(), rng.next_u64()); /// # } @@ -66,9 +66,9 @@ impl RngCore for Mt19937GenRand64 { /// /// ``` /// use rand_core::RngCore; - /// use rand_mt::Mt19937GenRand64; + /// use rand_mt::Mt64; /// - /// let mut rng = Mt19937GenRand64::new_unseeded(); + /// let mut rng = Mt64::new_unseeded(); /// # fn example(mut rng: T) { /// assert_ne!(rng.next_u32(), rng.next_u32()); /// # } @@ -91,9 +91,9 @@ impl RngCore for Mt19937GenRand64 { /// /// ``` /// use rand_core::RngCore; - /// use rand_mt::Mt19937GenRand64; + /// use rand_mt::Mt64; /// - /// let mut rng = Mt19937GenRand64::new_unseeded(); + /// let mut rng = Mt64::new_unseeded(); /// # fn example(mut rng: T) { /// let mut buf = [0; 32]; /// rng.fill_bytes(&mut buf); @@ -108,41 +108,6 @@ impl RngCore for Mt19937GenRand64 { 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(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)] @@ -150,13 +115,13 @@ mod tests { use core::num::Wrapping; use rand_core::{RngCore, SeedableRng}; - use super::Mt19937GenRand64; + use super::Mt64; 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()); + 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); @@ -169,7 +134,7 @@ mod tests { #[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()); + let mut mt = Mt64::new_with_key(key.iter().copied()); for &x in &TEST_OUTPUT { assert_eq!(x, RngCore::next_u64(&mut mt)); }