Skip to content

Commit

Permalink
Isaac*Rng: replace new_from_u64 with seed_from_u64
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Jul 7, 2018
1 parent fff888a commit 02750aa
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 31 deletions.
8 changes: 8 additions & 0 deletions rand_core/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
Self::new(R::from_seed(seed))
}

fn seed_from_u64(seed: u64) -> Self {
Self::new(R::seed_from_u64(seed))
}

fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
Ok(Self::new(R::from_rng(rng)?))
}
Expand Down Expand Up @@ -494,6 +498,10 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
Self::new(R::from_seed(seed))
}

fn seed_from_u64(seed: u64) -> Self {
Self::new(R::seed_from_u64(seed))
}

fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
Ok(Self::new(R::from_rng(rng)?))
}
Expand Down
8 changes: 8 additions & 0 deletions src/deprecated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ impl SeedableRng for IsaacRng {
fn from_seed(seed: Self::Seed) -> Self {
IsaacRng(prng::IsaacRng::from_seed(seed))
}

fn seed_from_u64(seed: u64) -> Self {
IsaacRng(prng::IsaacRng::seed_from_u64(seed))
}

fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
prng::IsaacRng::from_rng(rng).map(IsaacRng)
Expand Down Expand Up @@ -99,6 +103,10 @@ impl SeedableRng for Isaac64Rng {
Isaac64Rng(prng::Isaac64Rng::from_seed(seed))
}

fn seed_from_u64(seed: u64) -> Self {
Isaac64Rng(prng::Isaac64Rng::seed_from_u64(seed))
}

fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
prng::Isaac64Rng::from_rng(rng).map(Isaac64Rng)
}
Expand Down
46 changes: 27 additions & 19 deletions src/prng/isaac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ impl SeedableRng for IsaacRng {
fn from_seed(seed: Self::Seed) -> Self {
IsaacRng(BlockRng::<IsaacCore>::from_seed(seed))
}

/// Create an ISAAC random number generator using an `u64` as seed.
/// If `seed == 0` this will produce the same stream of random numbers as
/// the reference implementation when used unseeded.
fn seed_from_u64(seed: u64) -> Self {
IsaacRng(BlockRng::<IsaacCore>::seed_from_u64(seed))
}

fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
BlockRng::<IsaacCore>::from_rng(rng).map(|rng| IsaacRng(rng))
Expand All @@ -130,8 +137,9 @@ impl IsaacRng {
/// Create an ISAAC random number generator using an `u64` as seed.
/// If `seed == 0` this will produce the same stream of random numbers as
/// the reference implementation when used unseeded.
#[deprecated(since="0.6.0", note="use SeedableRng::seed_from_u64 instead")]
pub fn new_from_u64(seed: u64) -> Self {
IsaacRng(BlockRng::new(IsaacCore::new_from_u64(seed)))
Self::seed_from_u64(seed)
}
}

Expand Down Expand Up @@ -302,22 +310,6 @@ impl IsaacCore {

Self { mem, a: w(0), b: w(0), c: w(0) }
}

/// Create an ISAAC random number generator using an `u64` as seed.
/// If `seed == 0` this will produce the same stream of random numbers as
/// the reference implementation when used unseeded.
fn new_from_u64(seed: u64) -> Self {
let mut key = [w(0); RAND_SIZE];
key[0] = w(seed as u32);
key[1] = w((seed >> 32) as u32);
// Initialize with only one pass.
// A second pass does not improve the quality here, because all of the
// seed was already available in the first round.
// Not doing the second pass has the small advantage that if
// `seed == 0` this method produces exactly the same state as the
// reference implementation when used unseeded.
Self::init(key, 1)
}
}

impl SeedableRng for IsaacCore {
Expand All @@ -333,6 +325,22 @@ impl SeedableRng for IsaacCore {
}
Self::init(seed_extended, 2)
}

/// Create an ISAAC random number generator using an `u64` as seed.
/// If `seed == 0` this will produce the same stream of random numbers as
/// the reference implementation when used unseeded.
fn seed_from_u64(seed: u64) -> Self {
let mut key = [w(0); RAND_SIZE];
key[0] = w(seed as u32);
key[1] = w((seed >> 32) as u32);
// Initialize with only one pass.
// A second pass does not improve the quality here, because all of the
// seed was already available in the first round.
// Not doing the second pass has the small advantage that if
// `seed == 0` this method produces exactly the same state as the
// reference implementation when used unseeded.
Self::init(key, 1)
}

fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
// Custom `from_rng` implementation that fills a seed with the same size
Expand Down Expand Up @@ -426,11 +434,11 @@ mod test {
#[test]
fn test_isaac_new_uninitialized() {
// Compare the results from initializing `IsaacRng` with
// `new_from_u64(0)`, to make sure it is the same as the reference
// `seed_from_u64(0)`, to make sure it is the same as the reference
// implementation when used uninitialized.
// Note: We only test the first 16 integers, not the full 256 of the
// first block.
let mut rng = IsaacRng::new_from_u64(0);
let mut rng = IsaacRng::seed_from_u64(0);
let mut results = [0u32; 16];
for i in results.iter_mut() { *i = rng.next_u32(); }
let expected: [u32; 16] = [
Expand Down
37 changes: 25 additions & 12 deletions src/prng/isaac64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ impl SeedableRng for Isaac64Rng {
Isaac64Rng(BlockRng64::<Isaac64Core>::from_seed(seed))
}

/// Create an ISAAC random number generator using an `u64` as seed.
/// If `seed == 0` this will produce the same stream of random numbers as
/// the reference implementation when used unseeded.
fn seed_from_u64(seed: u64) -> Self {
Isaac64Rng(BlockRng64::<Isaac64Core>::seed_from_u64(seed))
}

fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
BlockRng64::<Isaac64Core>::from_rng(rng).map(|rng| Isaac64Rng(rng))
}
Expand All @@ -120,8 +127,9 @@ impl Isaac64Rng {
/// Create an ISAAC-64 random number generator using an `u64` as seed.
/// If `seed == 0` this will produce the same stream of random numbers as
/// the reference implementation when used unseeded.
#[deprecated(since="0.6.0", note="use SeedableRng::seed_from_u64 instead")]
pub fn new_from_u64(seed: u64) -> Self {
Isaac64Rng(BlockRng64::new(Isaac64Core::new_from_u64(seed)))
Self::seed_from_u64(seed)
}
}

Expand Down Expand Up @@ -271,16 +279,9 @@ impl Isaac64Core {
/// Create an ISAAC-64 random number generator using an `u64` as seed.
/// If `seed == 0` this will produce the same stream of random numbers as
/// the reference implementation when used unseeded.
#[deprecated(since="0.6.0", note="use SeedableRng::seed_from_u64 instead")]
pub fn new_from_u64(seed: u64) -> Self {
let mut key = [w(0); RAND_SIZE];
key[0] = w(seed);
// Initialize with only one pass.
// A second pass does not improve the quality here, because all of the
// seed was already available in the first round.
// Not doing the second pass has the small advantage that if
// `seed == 0` this method produces exactly the same state as the
// reference implementation when used unseeded.
Self::init(key, 1)
Self::seed_from_u64(seed)
}
}

Expand All @@ -297,6 +298,18 @@ impl SeedableRng for Isaac64Core {
}
Self::init(seed_extended, 2)
}

fn seed_from_u64(seed: u64) -> Self {
let mut key = [w(0); RAND_SIZE];
key[0] = w(seed);
// Initialize with only one pass.
// A second pass does not improve the quality here, because all of the
// seed was already available in the first round.
// Not doing the second pass has the small advantage that if
// `seed == 0` this method produces exactly the same state as the
// reference implementation when used unseeded.
Self::init(key, 1)
}

fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
// Custom `from_rng` implementation that fills a seed with the same size
Expand Down Expand Up @@ -416,11 +429,11 @@ mod test {
#[test]
fn test_isaac64_new_uninitialized() {
// Compare the results from initializing `IsaacRng` with
// `new_from_u64(0)`, to make sure it is the same as the reference
// `seed_from_u64(0)`, to make sure it is the same as the reference
// implementation when used uninitialized.
// Note: We only test the first 16 integers, not the full 256 of the
// first block.
let mut rng = Isaac64Rng::new_from_u64(0);
let mut rng = Isaac64Rng::seed_from_u64(0);
let mut results = [0u64; 16];
for i in results.iter_mut() { *i = rng.next_u64(); }
let expected: [u64; 16] = [
Expand Down

0 comments on commit 02750aa

Please sign in to comment.