@@ -697,6 +697,13 @@ impl BigUint {
697
697
}
698
698
return BigUint :: new ( shifted) ;
699
699
}
700
+
701
+ /// Determines the fewest bits necessary to express the BigUint.
702
+ pub fn bits ( & self ) -> uint {
703
+ if self . is_zero ( ) { return 0 ; }
704
+ let zeros = self . data . last ( ) . leading_zeros ( ) ;
705
+ return self . data . len ( ) * BigDigit :: bits - ( zeros as uint ) ;
706
+ }
700
707
}
701
708
702
709
#[ cfg( target_word_size = "64" ) ]
@@ -1115,10 +1122,23 @@ trait RandBigInt {
1115
1122
1116
1123
/// Generate a random BigInt of the given bit size.
1117
1124
fn gen_bigint(&mut self, bit_size: uint) -> BigInt;
1125
+
1126
+ /// Generate a random BigUint less than the given bound. Fails
1127
+ /// when the bound is zero.
1128
+ fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
1129
+
1130
+ /// Generate a random BigUint within the given range. The lower
1131
+ /// bound is inclusive; the upper bound is exclusive. Fails when
1132
+ /// the upper bound is not greater than the lower bound.
1133
+ fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
1134
+
1135
+ /// Generate a random BigInt within the given range. The lower
1136
+ /// bound is inclusive; the upper bound is exclusive. Fails when
1137
+ /// the upper bound is not greater than the lower bound.
1138
+ fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
1118
1139
}
1119
1140
1120
1141
impl<R: Rng> RandBigInt for R {
1121
- /// Generate a random BigUint of the given bit size.
1122
1142
fn gen_biguint(&mut self, bit_size: uint) -> BigUint {
1123
1143
let (digits, rem) = bit_size.div_rem(&BigDigit::bits);
1124
1144
let mut data = vec::with_capacity(digits+1);
@@ -1132,7 +1152,6 @@ impl<R: Rng> RandBigInt for R {
1132
1152
return BigUint::new(data);
1133
1153
}
1134
1154
1135
- /// Generate a random BigInt of the given bit size.
1136
1155
fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
1137
1156
// Generate a random BigUint...
1138
1157
let biguint = self.gen_biguint(bit_size);
@@ -1154,6 +1173,32 @@ impl<R: Rng> RandBigInt for R {
1154
1173
};
1155
1174
return BigInt::from_biguint(sign, biguint);
1156
1175
}
1176
+
1177
+ fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
1178
+ assert!(!bound.is_zero());
1179
+ let bits = bound.bits();
1180
+ loop {
1181
+ let n = self.gen_biguint(bits);
1182
+ if n < *bound { return n; }
1183
+ }
1184
+ }
1185
+
1186
+ fn gen_biguint_range(&mut self,
1187
+ lbound: &BigUint,
1188
+ ubound: &BigUint)
1189
+ -> BigUint {
1190
+ assert!(*lbound < *ubound);
1191
+ return *lbound + self.gen_biguint_below(&(*ubound - *lbound));
1192
+ }
1193
+
1194
+ fn gen_bigint_range(&mut self,
1195
+ lbound: &BigInt,
1196
+ ubound: &BigInt)
1197
+ -> BigInt {
1198
+ assert!(*lbound < *ubound);
1199
+ let delta = (*ubound - *lbound).to_biguint();
1200
+ return *lbound + self.gen_biguint_below(&delta).to_bigint();
1201
+ }
1157
1202
}
1158
1203
1159
1204
impl BigInt {
@@ -1780,12 +1825,63 @@ mod biguint_tests {
1780
1825
check ( 30 , "265252859812191058636308480000000" ) ;
1781
1826
}
1782
1827
1828
+ #[ test]
1829
+ fn test_bits ( ) {
1830
+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 0 , 0 ] ) . bits( ) , 0 ) ;
1831
+ assert_eq ! ( BigUint :: from_uint( 0 ) . bits( ) , 0 ) ;
1832
+ assert_eq ! ( BigUint :: from_uint( 1 ) . bits( ) , 1 ) ;
1833
+ assert_eq ! ( BigUint :: from_uint( 3 ) . bits( ) , 2 ) ;
1834
+ let n: BigUint = FromStrRadix :: from_str_radix ( "4000000000" , 16 ) . unwrap ( ) ;
1835
+ assert_eq ! ( n. bits( ) , 39 ) ;
1836
+ let one: BigUint = One :: one ( ) ;
1837
+ assert_eq ! ( ( one << 426 ) . bits( ) , 427 ) ;
1838
+ }
1839
+
1783
1840
#[ test]
1784
1841
fn test_rand ( ) {
1785
1842
let mut rng = task_rng ( ) ;
1786
1843
let _n: BigUint = rng. gen_biguint ( 137 ) ;
1787
1844
assert ! ( rng. gen_biguint( 0 ) . is_zero( ) ) ;
1788
1845
}
1846
+
1847
+ #[ test]
1848
+ fn test_rand_range ( ) {
1849
+ let mut rng = task_rng ( ) ;
1850
+
1851
+ do 10 . times {
1852
+ assert_eq ! ( rng. gen_bigint_range( & BigInt :: from_uint( 236 ) ,
1853
+ & BigInt :: from_uint( 237 ) ) ,
1854
+ BigInt :: from_uint( 236 ) ) ;
1855
+ }
1856
+
1857
+ let l = BigUint :: from_uint ( 403469000 + 2352 ) ;
1858
+ let u = BigUint :: from_uint ( 403469000 + 3513 ) ;
1859
+ do 1000 . times {
1860
+ let n: BigUint = rng. gen_biguint_below ( & u) ;
1861
+ assert ! ( n < u) ;
1862
+
1863
+ let n: BigUint = rng. gen_biguint_range ( & l, & u) ;
1864
+ assert ! ( n >= l) ;
1865
+ assert ! ( n < u) ;
1866
+ }
1867
+ }
1868
+
1869
+ #[ test]
1870
+ #[ should_fail]
1871
+ fn test_zero_rand_range ( ) {
1872
+ task_rng ( ) . gen_biguint_range ( & BigUint :: from_uint ( 54 ) ,
1873
+ & BigUint :: from_uint ( 54 ) ) ;
1874
+ }
1875
+
1876
+ #[ test]
1877
+ #[ should_fail]
1878
+ fn test_negative_rand_range ( ) {
1879
+ let mut rng = task_rng ( ) ;
1880
+ let l = BigUint :: from_uint ( 2352 ) ;
1881
+ let u = BigUint :: from_uint ( 3513 ) ;
1882
+ // Switching u and l should fail:
1883
+ let _n: BigUint = rng. gen_biguint_range ( & u, & l) ;
1884
+ }
1789
1885
}
1790
1886
1791
1887
#[ cfg( test) ]
@@ -2237,6 +2333,48 @@ mod bigint_tests {
2237
2333
let _n: BigInt = rng. gen_bigint ( 137 ) ;
2238
2334
assert ! ( rng. gen_bigint( 0 ) . is_zero( ) ) ;
2239
2335
}
2336
+
2337
+ #[ test]
2338
+ fn test_rand_range ( ) {
2339
+ let mut rng = task_rng ( ) ;
2340
+
2341
+ do 10 . times {
2342
+ assert_eq ! ( rng. gen_bigint_range( & BigInt :: from_uint( 236 ) ,
2343
+ & BigInt :: from_uint( 237 ) ) ,
2344
+ BigInt :: from_uint( 236 ) ) ;
2345
+ }
2346
+
2347
+ fn check ( l : BigInt , u : BigInt ) {
2348
+ let mut rng = task_rng ( ) ;
2349
+ do 1000 . times {
2350
+ let n: BigInt = rng. gen_bigint_range ( & l, & u) ;
2351
+ assert ! ( n >= l) ;
2352
+ assert ! ( n < u) ;
2353
+ }
2354
+ }
2355
+ let l = BigInt :: from_uint ( 403469000 + 2352 ) ;
2356
+ let u = BigInt :: from_uint ( 403469000 + 3513 ) ;
2357
+ check ( l. clone ( ) , u. clone ( ) ) ;
2358
+ check ( -l. clone ( ) , u. clone ( ) ) ;
2359
+ check ( -u. clone ( ) , -l. clone ( ) ) ;
2360
+ }
2361
+
2362
+ #[ test]
2363
+ #[ should_fail]
2364
+ fn test_zero_rand_range ( ) {
2365
+ task_rng ( ) . gen_bigint_range ( & IntConvertible :: from_int ( 54 ) ,
2366
+ & IntConvertible :: from_int ( 54 ) ) ;
2367
+ }
2368
+
2369
+ #[ test]
2370
+ #[ should_fail]
2371
+ fn test_negative_rand_range ( ) {
2372
+ let mut rng = task_rng ( ) ;
2373
+ let l = BigInt :: from_uint ( 2352 ) ;
2374
+ let u = BigInt :: from_uint ( 3513 ) ;
2375
+ // Switching u and l should fail:
2376
+ let _n: BigInt = rng. gen_bigint_range ( & u, & l) ;
2377
+ }
2240
2378
}
2241
2379
2242
2380
#[ cfg( test) ]
0 commit comments