From af35fd30355b6ed8a4e5b757680a8db697a7b2ca Mon Sep 17 00:00:00 2001 From: TheIronBorn <> Date: Wed, 30 May 2018 21:57:38 -0700 Subject: [PATCH 1/3] switch gen_biguint to fill_bytes --- src/bigrand.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/bigrand.rs b/src/bigrand.rs index 610fdb32..077d7447 100644 --- a/src/bigrand.rs +++ b/src/bigrand.rs @@ -2,6 +2,7 @@ use rand::prelude::*; use rand::distributions::uniform::{SampleUniform, UniformSampler}; +use rand::AsByteSliceMut; use BigInt; use BigUint; @@ -39,13 +40,15 @@ impl RandBigInt for R { fn gen_biguint(&mut self, bit_size: usize) -> BigUint { use super::big_digit::BITS; let (digits, rem) = bit_size.div_rem(&BITS); - let mut data = Vec::with_capacity(digits + 1); - for _ in 0..digits { - data.push(self.gen()); - } + let mut data = vec![BigDigit::default(); digits + (rem > 0) as usize]; + // `fill_bytes` is faster than many `gen::` calls + self.fill_bytes(data[..].as_byte_slice_mut()); + // Swap bytes per the `Rng::fill` source. This might be + // unnecessary if reproducibility across architectures is not + // desired. + data.to_le(); if rem > 0 { - let final_digit: BigDigit = self.gen(); - data.push(final_digit >> (BITS - rem)); + data[digits] >>= BITS - rem; } BigUint::new(data) } From b2c9577f6315b4b804699294c0e9bf9aa226c9a3 Mon Sep 17 00:00:00 2001 From: TheIronBorn <> Date: Mon, 25 Jun 2018 18:00:55 -0700 Subject: [PATCH 2/3] rand benches --- benches/bigint.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/benches/bigint.rs b/benches/bigint.rs index cd849ffe..7a763c2d 100644 --- a/benches/bigint.rs +++ b/benches/bigint.rs @@ -214,6 +214,52 @@ fn from_str_radix_36(b: &mut Bencher) { from_str_radix_bench(b, 36); } +fn rand_bench(b: &mut Bencher, bits: usize) { + let mut rng = get_rng(); + + b.iter(|| rng.gen_bigint(bits)); +} + +#[bench] +fn rand_64(b: &mut Bencher) { + rand_bench(b, 1 << 6); +} + +#[bench] +fn rand_256(b: &mut Bencher) { + rand_bench(b, 1 << 8); +} + +#[bench] +fn rand_1009(b: &mut Bencher) { + rand_bench(b, 1009); +} + +#[bench] +fn rand_2048(b: &mut Bencher) { + rand_bench(b, 1 << 11); +} + +#[bench] +fn rand_4096(b: &mut Bencher) { + rand_bench(b, 1 << 12); +} + +#[bench] +fn rand_8192(b: &mut Bencher) { + rand_bench(b, 1 << 13); +} + +#[bench] +fn rand_65536(b: &mut Bencher) { + rand_bench(b, 1 << 16); +} + +#[bench] +fn rand_131072(b: &mut Bencher) { + rand_bench(b, 1 << 17); +} + #[bench] fn shl(b: &mut Bencher) { let n = BigUint::one() << 1000; From 8b5a0920101073de12ff13f925110c02dcbae45f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 2 Jul 2018 11:09:07 -0700 Subject: [PATCH 3/3] Add tests for PRNG value stability --- tests/rand.rs | 144 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 2 deletions(-) diff --git a/tests/rand.rs b/tests/rand.rs index 9e0a277d..fcbb8f6f 100644 --- a/tests/rand.rs +++ b/tests/rand.rs @@ -8,7 +8,7 @@ mod biguint { use num_bigint::{BigUint, RandBigInt, RandomBits}; use num_traits::Zero; use rand::thread_rng; - use rand::Rng; + use rand::{Rng, SeedableRng}; use rand::distributions::Uniform; #[test] @@ -89,13 +89,83 @@ mod biguint { assert!(n < u); } } + + fn seeded_value_stability(expected: &[&str]) { + let mut seed = ::default(); + for (i, x) in seed.as_mut().iter_mut().enumerate() { + *x = (i as u8).wrapping_mul(191); + } + let mut rng = R::from_seed(seed); + for (i, &s) in expected.iter().enumerate() { + let n: BigUint = s.parse().unwrap(); + let r = rng.gen_biguint((1 << i) + i); + assert_eq!(n, r); + } + } + + #[test] + fn test_chacha_value_stability() { + const EXPECTED: &[&str] = &[ + "0", + "0", + "52", + "84", + "23780", + "86502865016", + "187057847319509867386", + "34045731223080904464438757488196244981910", + "23813754422987836414755953516143692594193066497413249270287126597896871975915808", + "57401636903146945411652549098818446911814352529449356393690984105383482703074355\ + 67088360974672291353736011718191813678720755501317478656550386324355699624671", + ]; + use rand::prng::ChaChaRng; + seeded_value_stability::(EXPECTED); + } + + #[test] + fn test_isaac_value_stability() { + const EXPECTED: &[&str] = &[ + "1", + "4", + "3", + "649", + "89116", + "7730042024", + "20773149082453254949", + "35999009049239918667571895439206839620281", + "10191757312714088681302309313551624007714035309632506837271600807524767413673006", + "37805949268912387809989378008822038725134260145886913321084097194957861133272558\ + 43458183365174899239251448892645546322463253898288141861183340823194379722556", + ]; + use rand::prng::IsaacRng; + seeded_value_stability::(EXPECTED); + } + + #[test] + fn test_xorshift_value_stability() { + const EXPECTED: &[&str] = &[ + "1", + "0", + "37", + "395", + "181116", + "122718231117", + "1068467172329355695001", + "28246925743544411614293300167064395633287", + "12750053187017853048648861493745244146555950255549630854523304068318587267293038", + "53041498719137109355568081064978196049094604705283682101683207799515709404788873\ + 53417136457745727045473194367732849819278740266658219147356315674940229288531", + ]; + use rand::prng::XorShiftRng; + seeded_value_stability::(EXPECTED); + } } mod bigint { use num_bigint::{BigInt, RandBigInt, RandomBits}; use num_traits::Zero; use rand::thread_rng; - use rand::Rng; + use rand::{Rng, SeedableRng}; use rand::distributions::Uniform; #[test] @@ -181,4 +251,74 @@ mod bigint { check(-l.clone(), u.clone()); check(-u.clone(), -l.clone()); } + + fn seeded_value_stability(expected: &[&str]) { + let mut seed = ::default(); + for (i, x) in seed.as_mut().iter_mut().enumerate() { + *x = (i as u8).wrapping_mul(191); + } + let mut rng = R::from_seed(seed); + for (i, &s) in expected.iter().enumerate() { + let n: BigInt = s.parse().unwrap(); + let r = rng.gen_bigint((1 << i) + i); + assert_eq!(n, r); + } + } + + #[test] + fn test_chacha_value_stability() { + const EXPECTED: &[&str] = &[ + "0", + "-6", + "-1", + "1321", + "-147247", + "8486373526", + "-272736656290199720696", + "2731152629387534140535423510744221288522", + "-28820024790651190394679732038637785320661450462089347915910979466834461433196572", + "501454570554170484799723603981439288209930393334472085317977614690773821680884844\ + 8530978478667288338327570972869032358120588620346111979053742269317702532328", + ]; + use rand::prng::ChaChaRng; + seeded_value_stability::(EXPECTED); + } + + #[test] + fn test_isaac_value_stability() { + const EXPECTED: &[&str] = &[ + "1", + "0", + "5", + "113", + "-132240", + "-36348760761", + "-365690596708430705434", + "-14090753008246284277803606722552430292432", + "-26313941628626248579319341019368550803676255307056857978955881718727601479436059", + "-14563174552421101848999036239003801073335703811160945137332228646111920972691151\ + 88341090358094331641182310792892459091016794928947242043358702692294695845817", + ]; + use rand::prng::IsaacRng; + seeded_value_stability::(EXPECTED); + } + + #[test] + fn test_xorshift_value_stability() { + const EXPECTED: &[&str] = &[ + "-1", + "-4", + "11", + "-1802", + "966495", + "-62592045703", + "-602281783447192077116", + "-34335811410223060575607987996861632509125", + "29156580925282215857325937227200350542000244609280383263289720243118706105351199", + "49920038676141573457451407325930326489996232208489690499754573826911037849083623\ + 24546142615325187412887314466195222441945661833644117700809693098722026764846", + ]; + use rand::prng::XorShiftRng; + seeded_value_stability::(EXPECTED); + } }