@@ -23,6 +23,7 @@ use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
23
23
use std:: int;
24
24
use std:: num;
25
25
use std:: num:: { IntConvertible , Zero , One , ToStrRadix , FromStrRadix , Orderable } ;
26
+ use std:: rand:: { Rng , RngUtil } ;
26
27
use std:: str;
27
28
use std:: uint;
28
29
use std:: vec;
@@ -1088,6 +1089,53 @@ impl FromStrRadix for BigInt {
1088
1089
}
1089
1090
}
1090
1091
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
+
1091
1139
impl BigInt {
1092
1140
/// Creates and initializes an BigInt.
1093
1141
#[inline]
@@ -1149,6 +1197,7 @@ mod biguint_tests {
1149
1197
use std::cmp::{Less, Equal, Greater};
1150
1198
use std::int;
1151
1199
use std::num::{IntConvertible, Zero, One, FromStrRadix};
1200
+ use std::rand::{task_rng};
1152
1201
use std::str;
1153
1202
use std::uint;
1154
1203
use std::vec;
@@ -1656,6 +1705,13 @@ mod biguint_tests {
1656
1705
check ( 20 , "2432902008176640000" ) ;
1657
1706
check ( 30 , "265252859812191058636308480000000" ) ;
1658
1707
}
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
+ }
1659
1715
}
1660
1716
1661
1717
#[ cfg( test) ]
@@ -1665,6 +1721,7 @@ mod bigint_tests {
1665
1721
use std:: cmp:: { Less , Equal , Greater } ;
1666
1722
use std:: int;
1667
1723
use std:: num:: { IntConvertible , Zero , One , FromStrRadix } ;
1724
+ use std:: rand:: { task_rng} ;
1668
1725
use std:: uint;
1669
1726
1670
1727
#[ test]
@@ -2085,6 +2142,13 @@ mod bigint_tests {
2085
2142
let zero: BigInt = Zero :: zero ( ) ;
2086
2143
assert_eq ! ( -zero, zero) ;
2087
2144
}
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
+ }
2088
2152
}
2089
2153
2090
2154
#[ cfg( test) ]
0 commit comments