From 3d735e4a63e49ca43d09f4bb9cfe19b3a7ce9407 Mon Sep 17 00:00:00 2001 From: David Creswick Date: Thu, 5 Sep 2013 19:03:54 -0500 Subject: [PATCH 1/4] Generate random BigUints and BigInts --- src/libextra/num/bigint.rs | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index cb76422815530..3738c914ca9a3 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -23,6 +23,7 @@ use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use std::int; use std::num; use std::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable}; +use std::rand::{Rng, RngUtil}; use std::str; use std::uint; use std::vec; @@ -520,6 +521,27 @@ impl FromStrRadix for BigUint { } } +trait RandBigUInt { + /// Generate a random BigUint of the given bit size. + fn gen_biguint(&mut self, bit_size: uint) -> BigUint; +} + +impl RandBigUInt for R { + /// Generate a random BigUint of the given bit size. + fn gen_biguint(&mut self, bit_size: uint) -> BigUint { + let (digits, rem) = bit_size.div_rem(&BigDigit::bits); + let mut data = vec::with_capacity(digits+1); + for _ in range(0, digits) { + data.push(self.gen()); + } + if rem > 0 { + let final_digit: BigDigit = self.gen(); + data.push(final_digit >> (BigDigit::bits - rem)); + } + return BigUint::new(data); + } +} + impl BigUint { /// Creates and initializes an BigUint. #[inline] @@ -1051,6 +1073,22 @@ impl FromStrRadix for BigInt { } } +trait RandBigInt { + /// Generate a random BigInt of the given bit size. + fn gen_bigint(&mut self, bit_size: uint) -> BigInt; +} + +impl RandBigInt for R { + /// Generate a random BigUint of the given bit size. + fn gen_bigint(&mut self, bit_size: uint) -> BigInt { + let biguint = self.gen_biguint(bit_size); + let sign = if biguint.is_zero() { Zero } + else if self.gen() { Plus } + else { Minus }; + return BigInt::from_biguint(sign, biguint); + } +} + impl BigInt { /// Creates and initializes an BigInt. #[inline] @@ -1112,6 +1150,7 @@ mod biguint_tests { use std::cmp::{Less, Equal, Greater}; use std::int; use std::num::{IntConvertible, Zero, One, FromStrRadix}; + use std::rand::{task_rng}; use std::str; use std::uint; use std::vec; @@ -1577,6 +1616,12 @@ mod biguint_tests { check(20, "2432902008176640000"); check(30, "265252859812191058636308480000000"); } + + #[test] + fn test_rand() { + let mut rng = task_rng(); + rng.gen_bigint(137); + } } #[cfg(test)] @@ -1586,6 +1631,7 @@ mod bigint_tests { use std::cmp::{Less, Equal, Greater}; use std::int; use std::num::{IntConvertible, Zero, One, FromStrRadix}; + use std::rand::{task_rng}; use std::uint; #[test] @@ -2006,6 +2052,13 @@ mod bigint_tests { let zero: BigInt = Zero::zero(); assert_eq!(-zero, zero); } + + #[test] + fn test_rand() { + let mut rng = task_rng(); + rng.gen_bigint(137); + assert!(rng.gen_bigint(0).is_zero()); + } } #[cfg(test)] From 43399529343bff6fc4ee5643b1f8f642b151ffff Mon Sep 17 00:00:00 2001 From: David Creswick Date: Thu, 5 Sep 2013 21:39:14 -0500 Subject: [PATCH 2/4] test the correct function (oops) --- src/libextra/num/bigint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 3738c914ca9a3..d59a0c9a04247 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -1620,7 +1620,7 @@ mod biguint_tests { #[test] fn test_rand() { let mut rng = task_rng(); - rng.gen_bigint(137); + let n: BigUint = rng.gen_biguint(137); } } @@ -2056,7 +2056,7 @@ mod bigint_tests { #[test] fn test_rand() { let mut rng = task_rng(); - rng.gen_bigint(137); + let n: BigInt = rng.gen_bigint(137); assert!(rng.gen_bigint(0).is_zero()); } } From 54368afc03054937e7f5a3b7a9b8cf9c8e85d962 Mon Sep 17 00:00:00 2001 From: David Creswick Date: Fri, 6 Sep 2013 13:57:21 -0500 Subject: [PATCH 3/4] Incorporate feedback from huonw - use identifiers with underscores to avoid unused variable warning - implement on R: Rng instead of on R: RngUtil - bugfix: zero BigInts were being generated twice as often as any other number - test that gen_biguint(0) always returns zero --- src/libextra/num/bigint.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index d59a0c9a04247..b691cb3c29641 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -526,7 +526,7 @@ trait RandBigUInt { fn gen_biguint(&mut self, bit_size: uint) -> BigUint; } -impl RandBigUInt for R { +impl RandBigUInt for R { /// Generate a random BigUint of the given bit size. fn gen_biguint(&mut self, bit_size: uint) -> BigUint { let (digits, rem) = bit_size.div_rem(&BigDigit::bits); @@ -1078,13 +1078,27 @@ trait RandBigInt { fn gen_bigint(&mut self, bit_size: uint) -> BigInt; } -impl RandBigInt for R { +impl RandBigInt for R { /// Generate a random BigUint of the given bit size. fn gen_bigint(&mut self, bit_size: uint) -> BigInt { + // Generate a random BigUint... let biguint = self.gen_biguint(bit_size); - let sign = if biguint.is_zero() { Zero } - else if self.gen() { Plus } - else { Minus }; + // ...and then randomly assign it a Sign... + let sign = if biguint.is_zero() { + // ...except that if the BigUint is zero, we need to try + // again with probability 0.5. This is because otherwise, + // the probability of generating a zero BigInt would be + // double that of any other number. + if self.gen() { + return self.gen_bigint(bit_size); + } else { + Zero + } + } else if self.gen() { + Plus + } else { + Minus + }; return BigInt::from_biguint(sign, biguint); } } @@ -1620,7 +1634,8 @@ mod biguint_tests { #[test] fn test_rand() { let mut rng = task_rng(); - let n: BigUint = rng.gen_biguint(137); + let _n: BigUint = rng.gen_biguint(137); + assert!(rng.gen_biguint(0).is_zero()); } } @@ -2056,7 +2071,7 @@ mod bigint_tests { #[test] fn test_rand() { let mut rng = task_rng(); - let n: BigInt = rng.gen_bigint(137); + let _n: BigInt = rng.gen_bigint(137); assert!(rng.gen_bigint(0).is_zero()); } } From 4946e0ea5ee727893a74321be2fb3b291f320809 Mon Sep 17 00:00:00 2001 From: David Creswick Date: Mon, 9 Sep 2013 11:31:40 -0500 Subject: [PATCH 4/4] Merge RandBigUint and RandBigInt into single trait --- src/libextra/num/bigint.rs | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index b691cb3c29641..93ffbb1c45cf6 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -521,27 +521,6 @@ impl FromStrRadix for BigUint { } } -trait RandBigUInt { - /// Generate a random BigUint of the given bit size. - fn gen_biguint(&mut self, bit_size: uint) -> BigUint; -} - -impl RandBigUInt for R { - /// Generate a random BigUint of the given bit size. - fn gen_biguint(&mut self, bit_size: uint) -> BigUint { - let (digits, rem) = bit_size.div_rem(&BigDigit::bits); - let mut data = vec::with_capacity(digits+1); - for _ in range(0, digits) { - data.push(self.gen()); - } - if rem > 0 { - let final_digit: BigDigit = self.gen(); - data.push(final_digit >> (BigDigit::bits - rem)); - } - return BigUint::new(data); - } -} - impl BigUint { /// Creates and initializes an BigUint. #[inline] @@ -1074,12 +1053,29 @@ impl FromStrRadix for BigInt { } trait RandBigInt { + /// Generate a random BigUint of the given bit size. + fn gen_biguint(&mut self, bit_size: uint) -> BigUint; + /// Generate a random BigInt of the given bit size. fn gen_bigint(&mut self, bit_size: uint) -> BigInt; } impl RandBigInt for R { /// Generate a random BigUint of the given bit size. + fn gen_biguint(&mut self, bit_size: uint) -> BigUint { + let (digits, rem) = bit_size.div_rem(&BigDigit::bits); + let mut data = vec::with_capacity(digits+1); + for _ in range(0, digits) { + data.push(self.gen()); + } + if rem > 0 { + let final_digit: BigDigit = self.gen(); + data.push(final_digit >> (BigDigit::bits - rem)); + } + return BigUint::new(data); + } + + /// Generate a random BigInt of the given bit size. fn gen_bigint(&mut self, bit_size: uint) -> BigInt { // Generate a random BigUint... let biguint = self.gen_biguint(bit_size);