From d38757052fc42f138508cbe1e8f7f2422bd7e4b1 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 10 Nov 2017 16:42:59 +0000 Subject: [PATCH 1/4] Split gen_usize_* benchmarks into gen_u32_* and gen_u64_* Copy non-controversial part of dhardy#36 Credit: Paul Dicker --- benches/generators.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/benches/generators.rs b/benches/generators.rs index dd223a2fbc9..fcf31879194 100644 --- a/benches/generators.rs +++ b/benches/generators.rs @@ -9,7 +9,7 @@ const BYTES_LEN: usize = 1024; use std::mem::size_of; use test::{black_box, Bencher}; -use rand::{Rng, NewSeeded, SeedFromRng, StdRng, OsRng, Rand, Default}; +use rand::{Rng, NewSeeded, Sample, SeedFromRng, StdRng, OsRng}; use rand::prng::{XorShiftRng, IsaacRng, Isaac64Rng, ChaChaRng}; macro_rules! gen_bytes { @@ -37,27 +37,34 @@ gen_bytes!(gen_bytes_std, StdRng); gen_bytes!(gen_bytes_os, OsRng); -macro_rules! gen_usize { - ($fnn:ident, $gen:ident) => { +macro_rules! gen_uint { + ($fnn:ident, $ty:ty, $gen:ident) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = $gen::new().unwrap(); b.iter(|| { for _ in 0..RAND_BENCH_N { - black_box(usize::rand(&mut rng, Default)); + black_box(rng.gen::<$ty>()); } }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; + b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } } } -gen_usize!(gen_usize_xorshift, XorShiftRng); -gen_usize!(gen_usize_isaac, IsaacRng); -gen_usize!(gen_usize_isaac64, Isaac64Rng); -gen_usize!(gen_usize_chacha, ChaChaRng); -gen_usize!(gen_usize_std, StdRng); -gen_usize!(gen_usize_os, OsRng); +gen_uint!(gen_u32_xorshift, u32, XorShiftRng); +gen_uint!(gen_u32_isaac, u32, IsaacRng); +gen_uint!(gen_u32_isaac64, u32, Isaac64Rng); +gen_uint!(gen_u32_chacha, u32, ChaChaRng); +gen_uint!(gen_u32_std, u32, StdRng); +gen_uint!(gen_u32_os, u32, OsRng); + +gen_uint!(gen_u64_xorshift, u64, XorShiftRng); +gen_uint!(gen_u64_isaac, u64, IsaacRng); +gen_uint!(gen_u64_isaac64, u64, Isaac64Rng); +gen_uint!(gen_u64_chacha, u64, ChaChaRng); +gen_uint!(gen_u64_std, u64, StdRng); +gen_uint!(gen_u64_os, u64, OsRng); macro_rules! init_gen { ($fnn:ident, $gen:ident) => { From 6e9c1ab2bae5021f469eeba8fa828a4abb96d027 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 10 Nov 2017 17:21:32 +0000 Subject: [PATCH 2/4] Rejig ChaCha and Isaac construction tests --- src/prng/chacha.rs | 25 +++++++++++-------------- src/prng/isaac.rs | 26 +++++++++++--------------- src/prng/isaac64.rs | 27 ++++++++++++--------------- 3 files changed, 34 insertions(+), 44 deletions(-) diff --git a/src/prng/chacha.rs b/src/prng/chacha.rs index 66b6424dce8..db1d127bb9c 100644 --- a/src/prng/chacha.rs +++ b/src/prng/chacha.rs @@ -290,26 +290,23 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng { #[cfg(test)] mod test { - use {Rng, SeedableRng, iter}; - use distributions::ascii_word_char; + use {Rng, SeedableRng, SeedFromRng, iter}; use super::ChaChaRng; #[test] fn test_rng_rand_seeded() { + // Test that various construction techniques produce a working RNG. + let s = iter(&mut ::test::rng()).map(|rng| rng.next_u32()).take(8).collect::>(); - let mut ra: ChaChaRng = SeedableRng::from_seed(&s[..]); - let mut rb: ChaChaRng = SeedableRng::from_seed(&s[..]); - assert!(::test::iter_eq(iter(&mut ra).map(|rng| ascii_word_char(rng)).take(100), - iter(&mut rb).map(|rng| ascii_word_char(rng)).take(100))); - } - - #[test] - fn test_rng_seeded() { + let mut ra = ChaChaRng::from_seed(&s[..]); + ra.next_u32(); + + let mut rb = ChaChaRng::from_rng(&mut ::test::rng()).unwrap(); + rb.next_u32(); + let seed : &[_] = &[0,1,2,3,4,5,6,7]; - let mut ra: ChaChaRng = SeedableRng::from_seed(seed); - let mut rb: ChaChaRng = SeedableRng::from_seed(seed); - assert!(::test::iter_eq(iter(&mut ra).map(|rng| ascii_word_char(rng)).take(100), - iter(&mut rb).map(|rng| ascii_word_char(rng)).take(100))); + let mut rc = ChaChaRng::from_seed(seed); + rc.next_u32(); } #[test] diff --git a/src/prng/isaac.rs b/src/prng/isaac.rs index c5bc12c5bc5..996bc684f5b 100644 --- a/src/prng/isaac.rs +++ b/src/prng/isaac.rs @@ -362,30 +362,26 @@ impl<'a> SeedableRng<&'a [u32]> for IsaacRng { #[cfg(test)] mod test { - use {Rng, SeedableRng, iter}; + use {Rng, SeedableRng, SeedFromRng, iter}; use super::IsaacRng; #[test] - fn test_isaac_from_seed() { + fn test_isaac_construction() { + // Test that various construction techniques produce a working RNG. + let seed = iter(&mut ::test::rng()) .map(|rng| rng.next_u32()) .take(256) .collect::>(); let mut rng1 = IsaacRng::from_seed(&seed[..]); - let mut rng2 = IsaacRng::from_seed(&seed[..]); - for _ in 0..100 { - assert_eq!(rng1.next_u32(), rng2.next_u32()); - } - } - - #[test] - fn test_isaac_from_seed_fixed() { + rng1.next_u32(); + + let mut rng2 = IsaacRng::from_rng(&mut ::test::rng()).unwrap(); + rng2.next_u32(); + let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut rng1 = IsaacRng::from_seed(&seed[..]); - let mut rng2 = IsaacRng::from_seed(&seed[..]); - for _ in 0..100 { - assert_eq!(rng1.next_u32(), rng2.next_u32()); - } + let mut rng3 = IsaacRng::from_seed(&seed[..]); + rng3.next_u32(); } #[test] diff --git a/src/prng/isaac64.rs b/src/prng/isaac64.rs index 7ae27117720..91c0186f3c7 100644 --- a/src/prng/isaac64.rs +++ b/src/prng/isaac64.rs @@ -321,30 +321,27 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng { #[cfg(test)] mod test { - use {Rng, SeedableRng, iter}; + use {Rng, SeedableRng, SeedFromRng, iter}; use super::Isaac64Rng; #[test] - fn test_isaac64_from_seed() { + fn test_isaac64_construction() { + // Test that various construction techniques produce a working RNG. + let seed = iter(&mut ::test::rng()) .map(|rng| rng.next_u64()) .take(256) .collect::>(); let mut rng1 = Isaac64Rng::from_seed(&seed[..]); - let mut rng2 = Isaac64Rng::from_seed(&seed[..]); - for _ in 0..100 { - assert_eq!(rng1.next_u64(), rng2.next_u64()); - } - } - - #[test] - fn test_isaac64_from_seed_fixed() { + rng1.next_u64(); + + let mut rng2 = Isaac64Rng::from_rng(&mut ::test::rng()).unwrap(); + rng2.next_u64(); + let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut rng1 = Isaac64Rng::from_seed(&seed[..]); - let mut rng2 = Isaac64Rng::from_seed(&seed[..]); - for _ in 0..100 { - assert_eq!(rng1.next_u64(), rng2.next_u64()); - } + let mut rng3 = Isaac64Rng::from_seed(&seed[..]); + rng3.next_u64(); + } #[test] From ae365ef352eeb0a4a249b598dde7723ddf37a32d Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 10 Nov 2017 17:21:53 +0000 Subject: [PATCH 3/4] Add true_bytes tests for ChaCha and Isaac; fix 2 bugs in fill_bytes impls --- src/prng/chacha.rs | 16 +++++++++++++++- src/prng/isaac.rs | 14 ++++++++++++++ src/prng/isaac64.rs | 18 ++++++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/prng/chacha.rs b/src/prng/chacha.rs index db1d127bb9c..a9ae8996b09 100644 --- a/src/prng/chacha.rs +++ b/src/prng/chacha.rs @@ -235,7 +235,7 @@ impl Rng for ChaChaRng { unsafe{ copy_nonoverlapping( &self.buffer[self.index].0 as *const u32 as *const u8, l.as_mut_ptr(), - words) }; + 4 * words) }; self.index += words; } let n = left.len(); @@ -351,6 +351,20 @@ mod test { 0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4)); } + #[test] + fn test_rng_true_bytes() { + let seed : &[_] = &[0u32; 8]; + let mut ra: ChaChaRng = SeedableRng::from_seed(seed); + let mut buf = [0u8; 32]; + ra.fill_bytes(&mut buf); + // Same as first values in test_isaac_true_values as bytes in LE order + assert_eq!(buf, + [118, 184, 224, 173, 160, 241, 61, 144, + 64, 93, 106, 229, 83, 134, 189, 40, + 189, 210, 25, 184, 160, 141, 237, 26, + 168, 54, 239, 204, 139, 119, 13, 199]); + } + #[test] fn test_rng_clone() { let seed : &[_] = &[0u32; 8]; diff --git a/src/prng/isaac.rs b/src/prng/isaac.rs index 996bc684f5b..82944144cb8 100644 --- a/src/prng/isaac.rs +++ b/src/prng/isaac.rs @@ -407,6 +407,20 @@ mod test { 141456972, 2478885421)); } + #[test] + fn test_isaac_true_bytes() { + let seed: &[_] = &[1, 23, 456, 7890, 12345]; + let mut rng1 = IsaacRng::from_seed(seed); + let mut buf = [0u8; 32]; + rng1.fill_bytes(&mut buf); + // Same as first values in test_isaac_true_values as bytes in LE order + assert_eq!(buf, + [82, 186, 128, 152, 71, 240, 20, 52, + 45, 175, 180, 15, 86, 16, 99, 125, + 101, 203, 81, 214, 97, 162, 134, 250, + 103, 78, 203, 15, 150, 3, 210, 164]); + } + #[test] fn test_isaac_new_uninitialized() { // Compare the results from initializing `IsaacRng` with diff --git a/src/prng/isaac64.rs b/src/prng/isaac64.rs index 91c0186f3c7..1d84d555f72 100644 --- a/src/prng/isaac64.rs +++ b/src/prng/isaac64.rs @@ -219,7 +219,7 @@ impl Rng for Isaac64Rng { } fn fill_bytes(&mut self, dest: &mut [u8]) { - ::rand_core::impls::fill_bytes_via_u32(self, dest); + ::rand_core::impls::fill_bytes_via_u64(self, dest); } fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error> { @@ -370,7 +370,21 @@ mod test { 596345674630742204, 9947027391921273664, 11788097613744130851, 10391409374914919106)); } - + + #[test] + fn test_isaac64_true_bytes() { + let seed: &[_] = &[1, 23, 456, 7890, 12345]; + let mut rng1 = Isaac64Rng::from_seed(seed); + let mut buf = [0u8; 32]; + rng1.fill_bytes(&mut buf); + // Same as first values in test_isaac64_true_values as bytes in LE order + assert_eq!(buf, + [140, 237, 103, 8, 93, 196, 151, 7, + 156, 242, 26, 63, 54, 166, 135, 199, + 141, 186, 192, 50, 116, 69, 205, 240, + 98, 205, 127, 160, 83, 98, 49, 17]); + } + #[test] fn test_isaac_new_uninitialized() { // Compare the results from initializing `IsaacRng` with From fd2660b5427265320e145d11d5e26dc4d7844203 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 10 Nov 2017 17:34:55 +0000 Subject: [PATCH 4/4] Isaac64: add test for true 32-bit values Includes both the values output now and the values which should be output by #36. --- src/prng/isaac64.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/prng/isaac64.rs b/src/prng/isaac64.rs index 1d84d555f72..2c84927c2d8 100644 --- a/src/prng/isaac64.rs +++ b/src/prng/isaac64.rs @@ -371,6 +371,28 @@ mod test { 11788097613744130851, 10391409374914919106)); } + #[test] + fn test_isaac64_true_values_32() { + let seed: &[_] = &[1, 23, 456, 7890, 12345]; + let mut rng1 = Isaac64Rng::from_seed(seed); + let v = (0..10).map(|_| rng1.next_u32()).collect::>(); + // Subset of above values, as an LE u32 sequence + // TODO: switch to this sequence? +// assert_eq!(v, +// [141028748, 127386717, +// 1058730652, 3347555894, +// 851491469, 4039984500, +// 2692730210, 288449107, +// 646103879, 2782923823]); + // Subset of above values, using only low-half of each u64 + assert_eq!(v, + [141028748, 1058730652, + 851491469, 2692730210, + 646103879, 4195642895, + 2836348583, 1312677241, + 999139615, 253604626]); + } + #[test] fn test_isaac64_true_bytes() { let seed: &[_] = &[1, 23, 456, 7890, 12345];