1 //! Randomization of big integers 2 3 use rand::distributions::uniform::{SampleUniform, UniformSampler}; 4 use rand::prelude::*; 5 use rand::AsByteSliceMut; 6 7 use BigInt; 8 use BigUint; 9 use Sign::*; 10 11 use big_digit::BigDigit; 12 use bigint::{into_magnitude, magnitude}; 13 14 use integer::Integer; 15 use traits::Zero; 16 17 /// A trait for sampling random big integers. 18 /// 19 /// The `rand` feature must be enabled to use this. See crate-level documentation for details. 20 pub trait RandBigInt { 21 /// Generate a random `BigUint` of the given bit size. gen_biguint(&mut self, bit_size: usize) -> BigUint22 fn gen_biguint(&mut self, bit_size: usize) -> BigUint; 23 24 /// Generate a random BigInt of the given bit size. gen_bigint(&mut self, bit_size: usize) -> BigInt25 fn gen_bigint(&mut self, bit_size: usize) -> BigInt; 26 27 /// Generate a random `BigUint` less than the given bound. Fails 28 /// when the bound is zero. gen_biguint_below(&mut self, bound: &BigUint) -> BigUint29 fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint; 30 31 /// Generate a random `BigUint` within the given range. The lower 32 /// bound is inclusive; the upper bound is exclusive. Fails when 33 /// the upper bound is not greater than the lower bound. gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint34 fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint; 35 36 /// Generate a random `BigInt` within the given range. The lower 37 /// bound is inclusive; the upper bound is exclusive. Fails when 38 /// the upper bound is not greater than the lower bound. gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt39 fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt; 40 } 41 42 impl<R: Rng + ?Sized> RandBigInt for R { gen_biguint(&mut self, bit_size: usize) -> BigUint43 fn gen_biguint(&mut self, bit_size: usize) -> BigUint { 44 use super::big_digit::BITS; 45 let (digits, rem) = bit_size.div_rem(&BITS); 46 let mut data = vec![BigDigit::default(); digits + (rem > 0) as usize]; 47 // `fill_bytes` is faster than many `gen::<u32>` calls 48 self.fill_bytes(data[..].as_byte_slice_mut()); 49 // Swap bytes per the `Rng::fill` source. This might be 50 // unnecessary if reproducibility across architectures is not 51 // desired. 52 data.to_le(); 53 if rem > 0 { 54 data[digits] >>= BITS - rem; 55 } 56 BigUint::new(data) 57 } 58 gen_bigint(&mut self, bit_size: usize) -> BigInt59 fn gen_bigint(&mut self, bit_size: usize) -> BigInt { 60 loop { 61 // Generate a random BigUint... 62 let biguint = self.gen_biguint(bit_size); 63 // ...and then randomly assign it a Sign... 64 let sign = if biguint.is_zero() { 65 // ...except that if the BigUint is zero, we need to try 66 // again with probability 0.5. This is because otherwise, 67 // the probability of generating a zero BigInt would be 68 // double that of any other number. 69 if self.gen() { 70 continue; 71 } else { 72 NoSign 73 } 74 } else if self.gen() { 75 Plus 76 } else { 77 Minus 78 }; 79 return BigInt::from_biguint(sign, biguint); 80 } 81 } 82 gen_biguint_below(&mut self, bound: &BigUint) -> BigUint83 fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint { 84 assert!(!bound.is_zero()); 85 let bits = bound.bits(); 86 loop { 87 let n = self.gen_biguint(bits); 88 if n < *bound { 89 return n; 90 } 91 } 92 } 93 gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint94 fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint { 95 assert!(*lbound < *ubound); 96 if lbound.is_zero() { 97 self.gen_biguint_below(ubound) 98 } else { 99 lbound + self.gen_biguint_below(&(ubound - lbound)) 100 } 101 } 102 gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt103 fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt { 104 assert!(*lbound < *ubound); 105 if lbound.is_zero() { 106 BigInt::from(self.gen_biguint_below(magnitude(&ubound))) 107 } else if ubound.is_zero() { 108 lbound + BigInt::from(self.gen_biguint_below(magnitude(&lbound))) 109 } else { 110 let delta = ubound - lbound; 111 lbound + BigInt::from(self.gen_biguint_below(magnitude(&delta))) 112 } 113 } 114 } 115 116 /// The back-end implementing rand's `UniformSampler` for `BigUint`. 117 #[derive(Clone, Debug)] 118 pub struct UniformBigUint { 119 base: BigUint, 120 len: BigUint, 121 } 122 123 impl UniformSampler for UniformBigUint { 124 type X = BigUint; 125 126 #[inline] new(low: Self::X, high: Self::X) -> Self127 fn new(low: Self::X, high: Self::X) -> Self { 128 assert!(low < high); 129 UniformBigUint { 130 len: high - &low, 131 base: low, 132 } 133 } 134 135 #[inline] new_inclusive(low: Self::X, high: Self::X) -> Self136 fn new_inclusive(low: Self::X, high: Self::X) -> Self { 137 assert!(low <= high); 138 Self::new(low, high + 1u32) 139 } 140 141 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X142 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 143 &self.base + rng.gen_biguint_below(&self.len) 144 } 145 146 #[inline] sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X147 fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { 148 rng.gen_biguint_range(&low, &high) 149 } 150 } 151 152 impl SampleUniform for BigUint { 153 type Sampler = UniformBigUint; 154 } 155 156 /// The back-end implementing rand's `UniformSampler` for `BigInt`. 157 #[derive(Clone, Debug)] 158 pub struct UniformBigInt { 159 base: BigInt, 160 len: BigUint, 161 } 162 163 impl UniformSampler for UniformBigInt { 164 type X = BigInt; 165 166 #[inline] new(low: Self::X, high: Self::X) -> Self167 fn new(low: Self::X, high: Self::X) -> Self { 168 assert!(low < high); 169 UniformBigInt { 170 len: into_magnitude(high - &low), 171 base: low, 172 } 173 } 174 175 #[inline] new_inclusive(low: Self::X, high: Self::X) -> Self176 fn new_inclusive(low: Self::X, high: Self::X) -> Self { 177 assert!(low <= high); 178 Self::new(low, high + 1u32) 179 } 180 181 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X182 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 183 &self.base + BigInt::from(rng.gen_biguint_below(&self.len)) 184 } 185 186 #[inline] sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X187 fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { 188 rng.gen_bigint_range(&low, &high) 189 } 190 } 191 192 impl SampleUniform for BigInt { 193 type Sampler = UniformBigInt; 194 } 195 196 /// A random distribution for `BigUint` and `BigInt` values of a particular bit size. 197 /// 198 /// The `rand` feature must be enabled to use this. See crate-level documentation for details. 199 #[derive(Clone, Copy, Debug)] 200 pub struct RandomBits { 201 bits: usize, 202 } 203 204 impl RandomBits { 205 #[inline] new(bits: usize) -> RandomBits206 pub fn new(bits: usize) -> RandomBits { 207 RandomBits { bits } 208 } 209 } 210 211 impl Distribution<BigUint> for RandomBits { 212 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint213 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint { 214 rng.gen_biguint(self.bits) 215 } 216 } 217 218 impl Distribution<BigInt> for RandomBits { 219 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt220 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt { 221 rng.gen_bigint(self.bits) 222 } 223 } 224