@@ -23,6 +23,7 @@ use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
2323use std:: int;
2424use std:: num;
2525use std:: num:: { IntConvertible , Zero , One , ToStrRadix , FromStrRadix , Orderable } ;
26+ use std:: rand:: { Rng , RngUtil } ;
2627use std:: str;
2728use std:: uint;
2829use std:: vec;
@@ -1088,6 +1089,53 @@ impl FromStrRadix for BigInt {
10881089 }
10891090}
10901091
1092+ trait RandBigInt {
1093+ /// Generate a random BigUint of the given bit size.
1094+ fn gen_biguint(&mut self, bit_size: uint) -> BigUint;
1095+
1096+ /// Generate a random BigInt of the given bit size.
1097+ fn gen_bigint(&mut self, bit_size: uint) -> BigInt;
1098+ }
1099+
1100+ impl<R: Rng> RandBigInt for R {
1101+ /// Generate a random BigUint of the given bit size.
1102+ fn gen_biguint(&mut self, bit_size: uint) -> BigUint {
1103+ let (digits, rem) = bit_size.div_rem(&BigDigit::bits);
1104+ let mut data = vec::with_capacity(digits+1);
1105+ for _ in range(0, digits) {
1106+ data.push(self.gen());
1107+ }
1108+ if rem > 0 {
1109+ let final_digit: BigDigit = self.gen();
1110+ data.push(final_digit >> (BigDigit::bits - rem));
1111+ }
1112+ return BigUint::new(data);
1113+ }
1114+
1115+ /// Generate a random BigInt of the given bit size.
1116+ fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
1117+ // Generate a random BigUint...
1118+ let biguint = self.gen_biguint(bit_size);
1119+ // ...and then randomly assign it a Sign...
1120+ let sign = if biguint.is_zero() {
1121+ // ...except that if the BigUint is zero, we need to try
1122+ // again with probability 0.5. This is because otherwise,
1123+ // the probability of generating a zero BigInt would be
1124+ // double that of any other number.
1125+ if self.gen() {
1126+ return self.gen_bigint(bit_size);
1127+ } else {
1128+ Zero
1129+ }
1130+ } else if self.gen() {
1131+ Plus
1132+ } else {
1133+ Minus
1134+ };
1135+ return BigInt::from_biguint(sign, biguint);
1136+ }
1137+ }
1138+
10911139impl BigInt {
10921140 /// Creates and initializes an BigInt.
10931141 #[inline]
@@ -1149,6 +1197,7 @@ mod biguint_tests {
11491197 use std::cmp::{Less, Equal, Greater};
11501198 use std::int;
11511199 use std::num::{IntConvertible, Zero, One, FromStrRadix};
1200+ use std::rand::{task_rng};
11521201 use std::str;
11531202 use std::uint;
11541203 use std::vec;
@@ -1656,6 +1705,13 @@ mod biguint_tests {
16561705 check ( 20 , "2432902008176640000" ) ;
16571706 check ( 30 , "265252859812191058636308480000000" ) ;
16581707 }
1708+
1709+ #[ test]
1710+ fn test_rand ( ) {
1711+ let mut rng = task_rng ( ) ;
1712+ let _n: BigUint = rng. gen_biguint ( 137 ) ;
1713+ assert ! ( rng. gen_biguint( 0 ) . is_zero( ) ) ;
1714+ }
16591715}
16601716
16611717#[ cfg( test) ]
@@ -1665,6 +1721,7 @@ mod bigint_tests {
16651721 use std:: cmp:: { Less , Equal , Greater } ;
16661722 use std:: int;
16671723 use std:: num:: { IntConvertible , Zero , One , FromStrRadix } ;
1724+ use std:: rand:: { task_rng} ;
16681725 use std:: uint;
16691726
16701727 #[ test]
@@ -2085,6 +2142,13 @@ mod bigint_tests {
20852142 let zero: BigInt = Zero :: zero ( ) ;
20862143 assert_eq ! ( -zero, zero) ;
20872144 }
2145+
2146+ #[ test]
2147+ fn test_rand ( ) {
2148+ let mut rng = task_rng ( ) ;
2149+ let _n: BigInt = rng. gen_bigint ( 137 ) ;
2150+ assert ! ( rng. gen_bigint( 0 ) . is_zero( ) ) ;
2151+ }
20882152}
20892153
20902154#[ cfg( test) ]
0 commit comments