Skip to content

Commit

Permalink
Implement SeedableRng::seed_from_u64
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Jun 23, 2018
1 parent af1303c commit 6ea3f6a
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 17 deletions.
29 changes: 29 additions & 0 deletions rand_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

use core::default::Default;
use core::convert::AsMut;
use core::ptr::copy_nonoverlapping;

#[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box;

Expand Down Expand Up @@ -297,6 +298,34 @@ pub trait SeedableRng: Sized {
/// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad
/// seed"). This is assuming only a small number of values must be rejected.
fn from_seed(seed: Self::Seed) -> Self;

/// Create a new PRNG using a `u64` seed.
///
/// This is provided as a convenient way to construct PRNGs from simple
/// numbers. It is not suitable for cryptography.
fn seed_from_u64(input: u64) -> Self {
// We use PCG to generate a u32 sequence, and copy to the seed
const MUL: u64 = 6364136223846793005;
const INC: u64 = 11634580027462260723;
let mut state = input.wrapping_mul(MUL).wrapping_add(INC);

let mut seed = Self::Seed::default();
for chunk in seed.as_mut().chunks_mut(4) {
let oldstate = state;
state = oldstate.wrapping_mul(MUL).wrapping_add(INC);

let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
let rot = (oldstate >> 59) as u32;
let x = xorshifted.rotate_right(rot).to_le();

unsafe {
let xp = &x as *const u32 as *const u8;
copy_nonoverlapping(xp, chunk.as_mut_ptr(), chunk.len());
}
}

Self::from_seed(seed)
}

/// Create a new PRNG seeded from another `Rng`.
///
Expand Down
18 changes: 2 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,21 +903,7 @@ mod test {
}

pub fn rng(seed: u64) -> TestRng<StdRng> {
// TODO: use from_hashable
let mut state = seed;
let mut seed = <StdRng as SeedableRng>::Seed::default();
for x in seed.iter_mut() {
// PCG algorithm
const MUL: u64 = 6364136223846793005;
const INC: u64 = 11634580027462260723;
let oldstate = state;
state = oldstate.wrapping_mul(MUL).wrapping_add(INC);

let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
let rot = (oldstate >> 59) as u32;
*x = xorshifted.rotate_right(rot) as u8;
}
TestRng { inner: StdRng::from_seed(seed) }
TestRng { inner: StdRng::seed_from_u64(seed) }
}

#[test]
Expand Down Expand Up @@ -1063,6 +1049,6 @@ mod test {
}
}
let avg = (sum as f64) / (N as f64);
assert!((avg - (NUM as f64)/(DENOM as f64)).abs() < 1e-3);
assert!((avg - (NUM as f64)/(DENOM as f64)).abs() < 3e-3);
}
}
2 changes: 1 addition & 1 deletion src/seq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ mod test {
}
for count in chosen.iter() {
let err = *count - 1000 / 9;
assert!(-25 <= err && err <= 25);
assert!(err.abs() <= 30);
}

assert_eq!((0..0).choose(&mut r), None);
Expand Down

0 comments on commit 6ea3f6a

Please sign in to comment.