diff --git a/Cargo.toml b/Cargo.toml index b9d5321..6507995 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,12 @@ license = "MIT" default = ["thread_rng"] # The thread_rng feature requires the rand dependency -thread_rng = ["rand"] +thread_rng = ["rand/getrandom"] [dependencies] -rand_core = "0.5" -rand = {version = "0.7", optional = true} +rand_core = "0.6" +rand = {version = "0.8", optional = true} + +[dev-dependencies] +rand_xorshift = "0.3.0" +rand_core = {version = "0.6", features=["getrandom"]} \ No newline at end of file diff --git a/README.md b/README.md index 4744cd4..8520cd1 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ sfmt Rust implementation of [SIMD-oriented Fast Mersenne Twister (SFMT)] interface using x86-SIMD in `std::arch`. This is pure rust re-implementation, and tested on Windows/macOS/Linux. +This works with limited parameters (607, 1279, 2281, 4253, 11213, 19937, 44497, 86243, 132049, 216091). [SIMD-oriented Fast Mersenne Twister (SFMT)]: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/ @@ -14,7 +15,7 @@ Limitations ------------ - Supported only on x86 and x86_64 (due to original SFMT) -- Algorithms other than MT19937 are not supported (may be fixed in future release) +- Require rustc >= 1.51 License -------- diff --git a/benches/rand_gen.rs b/benches/rand_gen.rs index bcbb2cd..61e03b8 100644 --- a/benches/rand_gen.rs +++ b/benches/rand_gen.rs @@ -5,6 +5,8 @@ extern crate sfmt; extern crate test; use rand::*; +use rand_core::SeedableRng; +use rand_xorshift::*; use sfmt::SFMT; use test::Bencher; diff --git a/src/lib.rs b/src/lib.rs index 69ea4a6..7f08472 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ //! //! ``` //! use rand_core::{RngCore, SeedableRng}; -//! let mut rng = sfmt::SFMT::seed_from_u64(42); +//! let mut rng = sfmt::SFMT19937::seed_from_u64(42); //! let r = rng.next_u32(); //! println!("random u32 number = {}", r); //! ``` @@ -15,94 +15,183 @@ mod sfmt; #[cfg(feature = "thread_rng")] mod thread_rng; -use rand_core::{impls, Error, RngCore, SeedableRng}; - -use self::packed::*; #[cfg(feature = "thread_rng")] pub use self::thread_rng::{thread_rng, ThreadRng}; -/// State of SFMT -/// -/// This struct implements random number generation through `rand::Rng`. -#[derive(Clone)] -pub struct SFMT { - /// the 128-bit internal state array - state: [i32x4; sfmt::SFMT_N], - /// index counter to the 32-bit internal state array - idx: usize, -} +/// Fall back to [`SFMT19937`], not be a breaking change. +pub type SFMT = SFMT19937; +/// SFMT with a state length 607 +pub type SFMT607 = paramed::SFMT<607, { 607 / 128 + 1 }>; +/// SFMT with a state length 1279 +pub type SFMT1279 = paramed::SFMT<1279, { 1279 / 128 + 1 }>; +/// SFMT with a state length 2281 +pub type SFMT2281 = paramed::SFMT<2281, { 2281 / 128 + 1 }>; +/// SFMT with a state length 4253 +pub type SFMT4253 = paramed::SFMT<4253, { 4253 / 128 + 1 }>; +/// SFMT with a state length 11213 +pub type SFMT11213 = paramed::SFMT<11213, { 11213 / 128 + 1 }>; +/// SFMT with a state length 19937 +pub type SFMT19937 = paramed::SFMT<19937, { 19937 / 128 + 1 }>; +/// SFMT with a state length 44497 +pub type SFMT44497 = paramed::SFMT<44497, { 44497 / 128 + 1 }>; +/// SFMT with a state length 86243. +pub type SFMT86243 = paramed::SFMT<86243, { 86243 / 128 + 1 }>; +/// SFMT with a state length 132049. +pub type SFMT132049 = paramed::SFMT<132049, { 132049 / 128 + 1 }>; +/// SFMT with a state length 216091. +pub type SFMT216091 = paramed::SFMT<216091, { 216091 / 128 + 1 }>; -impl SFMT { - fn pop32(&mut self) -> u32 { - let val = extract(self.state[self.idx / 4], self.idx % 4); - self.idx += 1; - val - } +/// Internal implemention of SFMT with `MEXP` parameter. +pub mod paramed { + use crate::{ + packed::*, + sfmt::{SfmtParams, SFMTMEXP}, + }; + use rand_core::{impls, Error, RngCore, SeedableRng}; - fn pop64(&mut self) -> u64 { - let p = self.state.as_ptr() as *const u32; - let val = unsafe { - let p = p.offset(self.idx as isize); - *(p as *const u64) // reinterpret cast [u32; 2] -> u64 - }; - self.idx += 2; - val + /// State of SFMT + /// + /// This struct implements random number generation through `rand::Rng`. + /// The MEXP is a parameter that defines a length of state. + /// MEXP is limted to be a known value, and it is checked at compile time. + /// MEXP can only be `607,1279,2281,4253,11213,19937,44497,86243,132049,216091`. + /// Since there is a limitation to const generics, we also need the `MEXP_N = {MEXP / 128 + 1}` + /// ``` + /// # use rand_core::SeedableRng; + /// let s = sfmt::SFMT19937::seed_from_u64(23); + /// ``` + #[derive(Clone)] + pub struct SFMT { + /// the 128-bit internal state array + pub(crate) state: [i32x4; MEXP_N], + /// index counter to the 32-bit internal state array + pub(crate) idx: usize, } - fn gen_all(&mut self) { - sfmt::sfmt_gen_rand_all(self); - self.idx = 0; - } -} + impl SFMT + where + SFMTMEXP: SfmtParams, + { + fn pop32(&mut self) -> u32 { + let val = extract(self.state[self.idx / 4], self.idx % 4); + self.idx += 1; + val + } -impl SeedableRng for SFMT { - type Seed = [u8; 4]; + fn pop64(&mut self) -> u64 { + let p = self.state.as_ptr() as *const u32; + let val = unsafe { + let p = p.offset(self.idx as isize); + *(p as *const u64) // reinterpret cast [u32; 2] -> u64 + }; + self.idx += 2; + val + } - fn from_seed(seed: [u8; 4]) -> Self { - let mut sfmt = SFMT { - state: [zero(); sfmt::SFMT_N], - idx: 0, - }; - let seed = unsafe { *(seed.as_ptr() as *const u32) }; - sfmt::sfmt_init_gen_rand(&mut sfmt, seed); - sfmt + fn gen_all(&mut self) { + SFMTMEXP::::sfmt_gen_rand_all(self); + self.idx = 0; + } } -} -impl RngCore for SFMT { - fn next_u32(&mut self) -> u32 { - if self.idx >= sfmt::SFMT_N32 { - self.gen_all(); + impl SeedableRng for SFMT + where + SFMTMEXP: SfmtParams, + { + type Seed = [u8; 4]; + + fn from_seed(seed: [u8; 4]) -> Self { + let mut sfmt = Self { + state: [zero(); MEXP_N], + idx: 0, + }; + let seed = unsafe { *(seed.as_ptr() as *const u32) }; + SFMTMEXP::::sfmt_init_gen_rand(&mut sfmt, seed); + sfmt } - self.pop32() } - fn next_u64(&mut self) -> u64 { - if self.idx >= sfmt::SFMT_N32 - 1 { - // drop last u32 if idx == N32-1 - self.gen_all(); + impl RngCore for SFMT + where + SFMTMEXP: SfmtParams, + { + fn next_u32(&mut self) -> u32 { + if self.idx >= SFMTMEXP::::SFMT_N32 { + self.gen_all(); + } + self.pop32() } - self.pop64() - } - fn fill_bytes(&mut self, dest: &mut [u8]) { - impls::fill_bytes_via_next(self, dest) - } + fn next_u64(&mut self) -> u64 { + if self.idx >= SFMTMEXP::::SFMT_N32 - 1 { + // drop last u32 if idx == N32-1 + self.gen_all(); + } + self.pop64() + } - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - Ok(self.fill_bytes(dest)) + fn fill_bytes(&mut self, dest: &mut [u8]) { + impls::fill_bytes_via_next(self, dest) + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + Ok(self.fill_bytes(dest)) + } } } - #[cfg(test)] mod tests { use super::*; use rand_core::{RngCore, SeedableRng}; #[test] - fn random() { + fn random_607() { + let mut rng = SFMT607::seed_from_u64(0); + for _ in 0..607 * 20 { + // Generate many random numbers to test the overwrap + let r = rng.next_u64(); + if r % 2 == 0 { + let _r = rng.next_u32(); + } // shift SFMT.idx randomly + } + } + #[test] + fn random_19937() { let mut rng = SFMT::seed_from_u64(0); - for _ in 0..sfmt::SFMT_N * 20 { + for _ in 0..19937 * 20 { + // Generate many random numbers to test the overwrap + let r = rng.next_u64(); + if r % 2 == 0 { + let _r = rng.next_u32(); + } // shift SFMT.idx randomly + } + } + #[test] + fn random_44497() { + let mut rng = SFMT44497::seed_from_u64(0); + for _ in 0..44497 * 20 { + // Generate many random numbers to test the overwrap + let r = rng.next_u64(); + if r % 2 == 0 { + let _r = rng.next_u32(); + } // shift SFMT.idx randomly + } + } + #[test] + fn random_86243() { + let mut rng = SFMT86243::seed_from_u64(0); + for _ in 0..86243 * 20 { + // Generate many random numbers to test the overwrap + let r = rng.next_u64(); + if r % 2 == 0 { + let _r = rng.next_u32(); + } // shift SFMT.idx randomly + } + } + #[test] + fn random_216091() { + let mut rng = SFMT216091::seed_from_u64(0); + for _ in 0..216091 * 20 { // Generate many random numbers to test the overwrap let r = rng.next_u64(); if r % 2 == 0 { diff --git a/src/packed.rs b/src/packed.rs index 4e8e8b6..f4f7d3f 100644 --- a/src/packed.rs +++ b/src/packed.rs @@ -23,7 +23,7 @@ pub(crate) fn extract(vals: i32x4, imm: usize) -> u32 { 1 => _mm_extract_epi32(vals, 1) as u32, 2 => _mm_extract_epi32(vals, 2) as u32, 3 => _mm_extract_epi32(vals, 3) as u32, - _ => unreachable!(), + _ => core::hint::unreachable_unchecked(), } } } @@ -35,8 +35,10 @@ pub(crate) fn insert(vals: &mut i32x4, val: i32, imm: usize) { 1 => _mm_insert_epi32(*vals, val, 1), 2 => _mm_insert_epi32(*vals, val, 2), 3 => _mm_insert_epi32(*vals, val, 3), - _ => unreachable!(), + _ => core::hint::unreachable_unchecked(), } }; - ::std::mem::replace(vals, updated); + unsafe { + ::std::ptr::write(vals, updated); + } } diff --git a/src/sfmt.rs b/src/sfmt.rs index 31aa45e..4d0810f 100644 --- a/src/sfmt.rs +++ b/src/sfmt.rs @@ -3,112 +3,320 @@ use super::*; use crate::packed::*; -const SFMT_MEXP: usize = 19937; -pub const SFMT_N: usize = SFMT_MEXP / 128 + 1; // = 156 -pub const SFMT_N32: usize = SFMT_N * 4; - -const SFMT_POS1: usize = 122; -const SFMT_SL1: i32 = 18; -const SFMT_SL2: i32 = 1; -const SFMT_SR1: i32 = 11; -const SFMT_SR2: i32 = 1; -const SFMT_MSK1: i32 = 0xdfffffef_u32 as i32; -const SFMT_MSK2: i32 = 0xddfecb7f_u32 as i32; -const SFMT_MSK3: i32 = 0xbffaffff_u32 as i32; -const SFMT_MSK4: i32 = 0xbffffff6_u32 as i32; -const SFMT_PARITY1: u32 = 0x00000001; -const SFMT_PARITY2: u32 = 0x00000000; -const SFMT_PARITY3: u32 = 0x00000000; -const SFMT_PARITY4: u32 = 0x13c9e684; - -fn mm_recursion(a: i32x4, b: i32x4, c: i32x4, d: i32x4) -> i32x4 { - #[cfg(target_arch = "x86")] - use std::arch::x86::*; - #[cfg(target_arch = "x86_64")] - use std::arch::x86_64::*; - - unsafe { - let mask = new(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4); - let y = _mm_srli_epi32(b, SFMT_SR1); - let z = _mm_srli_si128(c, SFMT_SR2); - let v = _mm_slli_epi32(d, SFMT_SL1); - let z = _mm_xor_si128(z, a); - let z = _mm_xor_si128(z, v); - let x = _mm_slli_si128(a, SFMT_SL2); - let y = _mm_and_si128(y, mask); - let z = _mm_xor_si128(z, x); - _mm_xor_si128(z, y) - } -} +/// Parameters used in sfmt. +pub trait SfmtParams: Sized { + const SFMT_MEXP: usize = MEXP; + const SFMT_N: usize = MEXP_N; //Self::SFMT_MEXP / 128 + 1; + const SFMT_N32: usize = Self::SFMT_N * 4; + + const SFMT_POS1: usize; + const SFMT_SL1: i32; + const SFMT_SL2: i32; + const SFMT_SR1: i32; + const SFMT_SR2: i32; + const SFMT_MSK1: i32; + const SFMT_MSK2: i32; + const SFMT_MSK3: i32; + const SFMT_MSK4: i32; + const SFMT_PARITY1: u32; + const SFMT_PARITY2: u32; + const SFMT_PARITY3: u32; + const SFMT_PARITY4: u32; -pub fn sfmt_gen_rand_all(sfmt: &mut SFMT) { - let st = &mut sfmt.state; - let mut r1 = st[SFMT_N - 2]; - let mut r2 = st[SFMT_N - 1]; - for i in 0..(SFMT_N - SFMT_POS1) { - st[i] = mm_recursion(st[i], st[i + SFMT_POS1], r1, r2); - r1 = r2; - r2 = st[i]; + fn mm_recursion(a: i32x4, b: i32x4, c: i32x4, d: i32x4) -> i32x4 { + #[cfg(target_arch = "x86")] + use std::arch::x86::*; + #[cfg(target_arch = "x86_64")] + use std::arch::x86_64::*; + + unsafe { + let mask = new( + Self::SFMT_MSK1, + Self::SFMT_MSK2, + Self::SFMT_MSK3, + Self::SFMT_MSK4, + ); + let y = _mm_srli_epi32(b, Self::SFMT_SR1); + let z = _mm_srli_si128(c, Self::SFMT_SR2); + let v = _mm_slli_epi32(d, Self::SFMT_SL1); + let z = _mm_xor_si128(z, a); + let z = _mm_xor_si128(z, v); + let x = _mm_slli_si128(a, Self::SFMT_SL2); + let y = _mm_and_si128(y, mask); + let z = _mm_xor_si128(z, x); + _mm_xor_si128(z, y) + } } - for i in (SFMT_N - SFMT_POS1)..SFMT_N { - st[i] = mm_recursion(st[i], st[i + SFMT_POS1 - SFMT_N], r1, r2); - r1 = r2; - r2 = st[i]; + + fn sfmt_gen_rand_all(sfmt: &mut paramed::SFMT) { + let st = &mut sfmt.state; + let mut r1 = st[Self::SFMT_N - 2]; + let mut r2 = st[Self::SFMT_N - 1]; + for i in 0..(Self::SFMT_N - Self::SFMT_POS1) { + st[i] = Self::mm_recursion(st[i], st[i + Self::SFMT_POS1], r1, r2); + r1 = r2; + r2 = st[i]; + } + for i in (Self::SFMT_N - Self::SFMT_POS1)..Self::SFMT_N { + st[i] = Self::mm_recursion(st[i], st[i + Self::SFMT_POS1 - Self::SFMT_N], r1, r2); + r1 = r2; + r2 = st[i]; + } } -} -pub fn period_certification(sfmt: &mut SFMT) { - let mut inner = 0_u32; - let st = &mut sfmt.state[0]; - let parity = [SFMT_PARITY1, SFMT_PARITY2, SFMT_PARITY3, SFMT_PARITY4]; - for i in 0..4 { - inner ^= extract(*st, i) & parity[i]; + fn period_certification(sfmt: &mut paramed::SFMT) { + let mut inner = 0_u32; + let st = &mut sfmt.state[0]; + let parity = [ + Self::SFMT_PARITY1, + Self::SFMT_PARITY2, + Self::SFMT_PARITY3, + Self::SFMT_PARITY4, + ]; + for i in 0..4 { + inner ^= extract(*st, i) & parity[i]; + } + for i in [16, 8, 4, 2, 1].iter() { + inner ^= inner >> i; + } + inner &= 1; + if inner == 1 { + return; + } + for i in 0..4 { + let mut work = 1_u32; + for _ in 0..32 { + if (work & parity[i]) != 0 { + let val = extract(*st, i) ^ work; + insert(st, val as i32, i); + return; + } + work = work << 1; + } + } } - for i in [16, 8, 4, 2, 1].iter() { - inner ^= inner >> i; + + fn iterate(pre: i32, i: i32) -> i32 { + use std::num::Wrapping; + let pre = Wrapping(pre as u32); + let i = Wrapping(i as u32); + (Wrapping(1812433253) * (pre ^ (pre >> 30)) + i).0 as i32 } - inner &= 1; - if inner == 1 { - return; + + fn map(a: i32, idx: i32) -> (i32x4, i32) { + let b = Self::iterate(a, 4 * idx + 1); + let c = Self::iterate(b, 4 * idx + 2); + let d = Self::iterate(c, 4 * idx + 3); + let a2 = Self::iterate(d, 4 * idx + 4); + (new(a, b, c, d), a2) } - for i in 0..4 { - let mut work = 1_u32; - for _ in 0..32 { - if (work & parity[i]) != 0 { - let val = extract(*st, i) ^ work; - insert(st, val as i32, i); - return; - } - work = work << 1; + + fn sfmt_init_gen_rand(sfmt: &mut paramed::SFMT, seed: u32) { + let mut pre = seed as i32; + for (idx, v) in sfmt.state.iter_mut().enumerate() { + let (v_, pre_) = Self::map(pre, idx as i32); + *v = v_; + pre = pre_; } + sfmt.idx = Self::SFMT_N32; + Self::period_certification(sfmt); } } +/// Wrapper for `MEXP` parameter. +pub struct SFMTMEXP; -fn iterate(pre: i32, i: i32) -> i32 { - use std::num::Wrapping; - let pre = Wrapping(pre as u32); - let i = Wrapping(i as u32); - (Wrapping(1812433253) * (pre ^ (pre >> 30)) + i).0 as i32 -} - -fn map(a: i32, idx: i32) -> (i32x4, i32) { - let b = iterate(a, 4 * idx + 1); - let c = iterate(b, 4 * idx + 2); - let d = iterate(c, 4 * idx + 3); - let a2 = iterate(d, 4 * idx + 4); - (new(a, b, c, d), a2) +macro_rules! parms_impl { + ($mexp : expr, $n : expr, $pos1 : expr, $sl1 : expr, $sl2 : expr, $sr1 : expr, $sr2 : expr, + $msk1 : expr, $msk2 : expr, $msk3 : expr, $msk4 : expr, + $parity1 : expr, $parity2 : expr, $parity3 : expr, $parity4 : expr) => { + impl SfmtParams<$mexp, $n> for SFMTMEXP<$mexp, $n> { + const SFMT_POS1: usize = $pos1; + const SFMT_SL1: i32 = $sl1; + const SFMT_SL2: i32 = $sl2; + const SFMT_SR1: i32 = $sr1; + const SFMT_SR2: i32 = $sr2; + const SFMT_MSK1: i32 = $msk1 as i32; + const SFMT_MSK2: i32 = $msk2 as i32; + const SFMT_MSK3: i32 = $msk3 as i32; + const SFMT_MSK4: i32 = $msk4 as i32; + const SFMT_PARITY1: u32 = $parity1; + const SFMT_PARITY2: u32 = $parity2; + const SFMT_PARITY3: u32 = $parity3; + const SFMT_PARITY4: u32 = $parity4; + } + }; } -pub fn sfmt_init_gen_rand(sfmt: &mut SFMT, seed: u32) { - let mut pre = seed as i32; - for (idx, v) in sfmt.state.iter_mut().enumerate() { - let (v_, pre_) = map(pre, idx as i32); - *v = v_; - pre = pre_; - } - sfmt.idx = SFMT_N32; - period_certification(sfmt); -} +parms_impl!( + 607, + { 607 / 128 + 1 }, + 2, + 15, + 3, + 13, + 3, + 0xfdff_37ff_u32, + 0xef7f_3f7d_u32, + 0xff77_7b7d_u32, + 0x7ff7_fb2f_u32, + 0x0000_0001, + 0x0000_0000, + 0x0000_0000, + 0x5986_f054 +); +parms_impl!( + 1279, + { 1279 / 128 + 1 }, + 7, + 14, + 3, + 5, + 1, + 0xf7fe_fffd_u32, + 0x7fef_cfff_u32, + 0xaff3_ef3f_u32, + 0xb5ff_ff7f_u32, + 0x0000_0001_u32, + 0x0000_0000_u32, + 0x0000_0000_u32, + 0x2000_0000_u32 +); +parms_impl!( + 2281, + { 2281 / 128 + 1 }, + 12, + 19, + 1, + 5, + 1, + 0xbff7_ffbf_u32, + 0xfdff_fffe_u32, + 0xf7ffe_f7f_u32, + 0xf2f7_cbbf_u32, + 0x0000_0001_u32, + 0x0000_0000_u32, + 0x0000_0000_u32, + 0x41df_a600_u32 +); +parms_impl!( + 4253, + { 4253 / 128 + 1 }, + 17, + 20, + 1, + 7, + 1, + 0x9f7b_ffff_u32, + 0x9fff_ff5f_u32, + 0x3eff_fffb_u32, + 0xffff_f7bb_u32, + 0xa800_0001_u32, + 0xaf53_90a3_u32, + 0xb740_b3f8_u32, + 0x6c11_486d_u32 +); +parms_impl!( + 11213, + { 11213 / 128 + 1 }, + 68, + 14, + 3, + 7, + 3, + 0xefff_f7fb_u32, + 0xffff_ffef_u32, + 0xdfdf_bfff_u32, + 0x7fff_dbfd_u32, + 0x0000_0001_u32, + 0x0000_0000_u32, + 0xb740_b3f8_u32, + 0x6c11_486d_u32 +); +parms_impl!( + 19937, + { 19937 / 128 + 1 }, + 122, + 18, + 1, + 11, + 1, + 0xdfff_ffef_u32, + 0xddfe_cb7f_u32, + 0xbffa_ffff_u32, + 0xbfff_fff6_u32, + 0x0000_0001_u32, + 0x0000_0000_u32, + 0x0000_0000_u32, + 0x13c9_e684_u32 +); +parms_impl!( + 44497, + { 44497 / 128 + 1 }, + 330, + 5, + 3, + 9, + 3, + 0xefff_fffb_u32, + 0xdfbe_bfff_u32, + 0xbfbf_7bef_u32, + 0x9ffd_7bff_u32, + 0x0000_0001_u32, + 0x0000_0000_u32, + 0xa3ac_4000_u32, + 0xecc1_327a_u32 +); +parms_impl!( + 86243, + { 86243 / 128 + 1 }, + 366, + 6, + 7, + 19, + 1, + 0xfdbf_bff7_u32, + 0xfd77_efff_u32, + 0xfd77_efff_u32, + 0xbf9f_f3ff_u32, + 0x0000_0001_u32, + 0x0000_0000_u32, + 0x0000_0000_u32, + 0x3952_8d85_u32 +); +parms_impl!( + 132049, + { 132049 / 128 + 1 }, + 110, + 19, + 1, + 21, + 1, + 0xffff_bb5f_u32, + 0xfb6e_bf95_u32, + 0xfffe_fffa_u32, + 0xcff7_7fff_u32, + 0x0000_0001_u32, + 0x0000_0000_u32, + 0xcb52_0000_u32, + 0xc7e9_1c7d_u32 +); +parms_impl!( + 216091, + { 216091 / 128 + 1 }, + 627, + 11, + 3, + 10, + 1, + 0xbff7_bff7_u32, + 0xbfff_ffff_u32, + 0xbfff_fa7f_u32, + 0xffdd_fbfb_u32, + 0xf800_0001_u32, + 0x89e8_0709_u32, + 0x3bd2_b64b_u32, + 0x0c64_b1e4_u32 +); #[cfg(test)] mod tests { @@ -138,7 +346,7 @@ mod tests { fn test_init() { let seed: u32 = 1234; let seed = unsafe { *(&seed as *const u32 as *const [u8; 4]) }; - let sfmt = SFMT::from_seed(seed); + let sfmt = paramed::SFMT::<19937, { 19937 / 128 + 1 }>::from_seed(seed); let ans = read_answer("check/init1234.txt").unwrap(); for (v, a) in sfmt.state.iter().zip(ans.iter()) { assert_eq!(split(*v), split(*a)); @@ -146,16 +354,16 @@ mod tests { } #[test] - fn test_mm_recursion() { + fn test_mm_recursion_19937() { let a = new(1, 2, 3, 4); - let z = mm_recursion(a, a, a, a); + let z = SFMTMEXP::<19937, { 19937 / 128 + 1 }>::mm_recursion(a, a, a, a); let zc = new(33816833, 50856450, 67896067, 1049604); // calculated by C code assert_eq!(split(z), split(zc)); let b = new(431, 232, 83, 14); let c = new(213, 22, 93, 234); let d = new(112, 882, 23, 124); - let z = mm_recursion(a, b, c, d); + let z = SFMTMEXP::<19937, { 19937 / 128 + 1 }>::mm_recursion(a, b, c, d); let zc = new(398459137, 1355284994, -363068669, 32506884); // calculated by C code assert_eq!(split(z), split(zc)); } diff --git a/src/thread_rng.rs b/src/thread_rng.rs index 85f5b25..cd0becb 100644 --- a/src/thread_rng.rs +++ b/src/thread_rng.rs @@ -2,7 +2,7 @@ use super::SFMT; -use rand::{Error, RngCore, SeedableRng}; +use rand_core::{Error, RngCore, SeedableRng}; use std::cell::RefCell; use std::rc::Rc;