1 //! Randomization of big integers 2 3 use rand::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler}; 4 use rand::prelude::*; 5 use rand::AsByteSliceMut; 6 use rand::Rng; 7 8 use BigInt; 9 use BigUint; 10 use Sign::*; 11 12 use big_digit::BigDigit; 13 use bigint::{into_magnitude, magnitude}; 14 use integer::Integer; 15 #[cfg(feature = "prime")] 16 use num_iter::range_step; 17 use num_traits::Zero; 18 #[cfg(feature = "prime")] 19 use num_traits::{FromPrimitive, ToPrimitive}; 20 21 #[cfg(feature = "prime")] 22 use crate::prime::probably_prime; 23 24 pub trait RandBigInt { 25 /// Generate a random `BigUint` of the given bit size. gen_biguint(&mut self, bit_size: usize) -> BigUint26 fn gen_biguint(&mut self, bit_size: usize) -> BigUint; 27 28 /// Generate a random BigInt of the given bit size. gen_bigint(&mut self, bit_size: usize) -> BigInt29 fn gen_bigint(&mut self, bit_size: usize) -> BigInt; 30 31 /// Generate a random `BigUint` less than the given bound. Fails 32 /// when the bound is zero. gen_biguint_below(&mut self, bound: &BigUint) -> BigUint33 fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint; 34 35 /// Generate a random `BigUint` within the given range. The lower 36 /// bound is inclusive; the upper bound is exclusive. Fails when 37 /// the upper bound is not greater than the lower bound. gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint38 fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint; 39 40 /// Generate a random `BigInt` within the given range. The lower 41 /// bound is inclusive; the upper bound is exclusive. Fails when 42 /// the upper bound is not greater than the lower bound. gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt43 fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt; 44 } 45 46 impl<R: Rng + ?Sized> RandBigInt for R { gen_biguint(&mut self, bit_size: usize) -> BigUint47 fn gen_biguint(&mut self, bit_size: usize) -> BigUint { 48 use super::big_digit::BITS; 49 let (digits, rem) = bit_size.div_rem(&BITS); 50 let mut data = smallvec![BigDigit::default(); digits + (rem > 0) as usize]; 51 // `fill_bytes` is faster than many `gen::<u32>` calls 52 self.fill_bytes(data[..].as_byte_slice_mut()); 53 // Swap bytes per the `Rng::fill` source. This might be 54 // unnecessary if reproducibility across architectures is not 55 // desired. 56 data.to_le(); 57 if rem > 0 { 58 data[digits] >>= BITS - rem; 59 } 60 BigUint::new_native(data) 61 } 62 gen_bigint(&mut self, bit_size: usize) -> BigInt63 fn gen_bigint(&mut self, bit_size: usize) -> BigInt { 64 loop { 65 // Generate a random BigUint... 66 let biguint = self.gen_biguint(bit_size); 67 // ...and then randomly assign it a Sign... 68 let sign = if biguint.is_zero() { 69 // ...except that if the BigUint is zero, we need to try 70 // again with probability 0.5. This is because otherwise, 71 // the probability of generating a zero BigInt would be 72 // double that of any other number. 73 if self.gen() { 74 continue; 75 } else { 76 NoSign 77 } 78 } else if self.gen() { 79 Plus 80 } else { 81 Minus 82 }; 83 return BigInt::from_biguint(sign, biguint); 84 } 85 } 86 gen_biguint_below(&mut self, bound: &BigUint) -> BigUint87 fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint { 88 assert!(!bound.is_zero()); 89 let bits = bound.bits(); 90 loop { 91 let n = self.gen_biguint(bits); 92 if n < *bound { 93 return n; 94 } 95 } 96 } 97 gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint98 fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint { 99 assert!(*lbound < *ubound); 100 if lbound.is_zero() { 101 self.gen_biguint_below(ubound) 102 } else { 103 lbound + self.gen_biguint_below(&(ubound - lbound)) 104 } 105 } 106 gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt107 fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt { 108 assert!(*lbound < *ubound); 109 if lbound.is_zero() { 110 BigInt::from(self.gen_biguint_below(magnitude(&ubound))) 111 } else if ubound.is_zero() { 112 lbound + BigInt::from(self.gen_biguint_below(magnitude(&lbound))) 113 } else { 114 let delta = ubound - lbound; 115 lbound + BigInt::from(self.gen_biguint_below(magnitude(&delta))) 116 } 117 } 118 } 119 120 /// The back-end implementing rand's `UniformSampler` for `BigUint`. 121 #[derive(Clone, Debug)] 122 pub struct UniformBigUint { 123 base: BigUint, 124 len: BigUint, 125 } 126 127 impl UniformSampler for UniformBigUint { 128 type X = BigUint; 129 130 #[inline] new<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,131 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self 132 where 133 B1: SampleBorrow<Self::X> + Sized, 134 B2: SampleBorrow<Self::X> + Sized, 135 { 136 let low = low_b.borrow(); 137 let high = high_b.borrow(); 138 139 assert!(low < high); 140 141 UniformBigUint { 142 len: high - low, 143 base: low.clone(), 144 } 145 } 146 147 #[inline] new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,148 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self 149 where 150 B1: SampleBorrow<Self::X> + Sized, 151 B2: SampleBorrow<Self::X> + Sized, 152 { 153 Self::new(low_b, high_b.borrow() + 1u32) 154 } 155 156 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X157 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 158 &self.base + rng.gen_biguint_below(&self.len) 159 } 160 161 #[inline] sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,162 fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X 163 where 164 B1: SampleBorrow<Self::X> + Sized, 165 B2: SampleBorrow<Self::X> + Sized, 166 { 167 let low = low_b.borrow(); 168 let high = high_b.borrow(); 169 170 rng.gen_biguint_range(low, high) 171 } 172 } 173 174 impl SampleUniform for BigUint { 175 type Sampler = UniformBigUint; 176 } 177 178 /// The back-end implementing rand's `UniformSampler` for `BigInt`. 179 #[derive(Clone, Debug)] 180 pub struct UniformBigInt { 181 base: BigInt, 182 len: BigUint, 183 } 184 185 impl UniformSampler for UniformBigInt { 186 type X = BigInt; 187 188 #[inline] 189 #[inline] new<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,190 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self 191 where 192 B1: SampleBorrow<Self::X> + Sized, 193 B2: SampleBorrow<Self::X> + Sized, 194 { 195 let low = low_b.borrow(); 196 let high = high_b.borrow(); 197 198 assert!(low < high); 199 UniformBigInt { 200 len: into_magnitude(high - low), 201 base: low.clone(), 202 } 203 } 204 205 #[inline] new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,206 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self 207 where 208 B1: SampleBorrow<Self::X> + Sized, 209 B2: SampleBorrow<Self::X> + Sized, 210 { 211 let low = low_b.borrow(); 212 let high = high_b.borrow(); 213 214 assert!(low <= high); 215 Self::new(low, high + 1u32) 216 } 217 218 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X219 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 220 &self.base + BigInt::from(rng.gen_biguint_below(&self.len)) 221 } 222 223 #[inline] sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,224 fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X 225 where 226 B1: SampleBorrow<Self::X> + Sized, 227 B2: SampleBorrow<Self::X> + Sized, 228 { 229 let low = low_b.borrow(); 230 let high = high_b.borrow(); 231 232 rng.gen_bigint_range(low, high) 233 } 234 } 235 236 impl SampleUniform for BigInt { 237 type Sampler = UniformBigInt; 238 } 239 240 /// A random distribution for `BigUint` and `BigInt` values of a particular bit size. 241 #[derive(Clone, Copy, Debug)] 242 pub struct RandomBits { 243 bits: usize, 244 } 245 246 impl RandomBits { 247 #[inline] new(bits: usize) -> RandomBits248 pub fn new(bits: usize) -> RandomBits { 249 RandomBits { bits } 250 } 251 } 252 253 impl Distribution<BigUint> for RandomBits { 254 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint255 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint { 256 rng.gen_biguint(self.bits) 257 } 258 } 259 260 impl Distribution<BigInt> for RandomBits { 261 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt262 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt { 263 rng.gen_bigint(self.bits) 264 } 265 } 266 267 /// A generic trait for generating random primes. 268 /// 269 /// *Warning*: This is highly dependend on the provided random number generator, 270 /// to provide actually random primes. 271 /// 272 /// # Example 273 #[cfg_attr(feature = "std", doc = " ```")] 274 #[cfg_attr(not(feature = "std"), doc = " ```ignore")] 275 /// extern crate rand; 276 /// extern crate num_bigint_dig as num_bigint; 277 /// 278 /// use rand::thread_rng; 279 /// use num_bigint::RandPrime; 280 /// 281 /// let mut rng = thread_rng(); 282 /// let p = rng.gen_prime(1024); 283 /// assert_eq!(p.bits(), 1024); 284 /// ``` 285 /// 286 #[cfg(feature = "prime")] 287 pub trait RandPrime { 288 /// Generate a random prime number with as many bits as given. gen_prime(&mut self, bits: usize) -> BigUint289 fn gen_prime(&mut self, bits: usize) -> BigUint; 290 } 291 292 /// A list of small, prime numbers that allows us to rapidly 293 /// exclude some fraction of composite candidates when searching for a random 294 /// prime. This list is truncated at the point where smallPrimesProduct exceeds 295 /// a u64. It does not include two because we ensure that the candidates are 296 /// odd by construction. 297 #[cfg(feature = "prime")] 298 const SMALL_PRIMES: [u8; 15] = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]; 299 300 #[cfg(feature = "prime")] 301 lazy_static! { 302 /// The product of the values in SMALL_PRIMES and allows us 303 /// to reduce a candidate prime by this number and then determine whether it's 304 /// coprime to all the elements of SMALL_PRIMES without further BigUint 305 /// operations. 306 static ref SMALL_PRIMES_PRODUCT: BigUint = BigUint::from_u64(16_294_579_238_595_022_365).unwrap(); 307 } 308 309 #[cfg(feature = "prime")] 310 impl<R: Rng + ?Sized> RandPrime for R { gen_prime(&mut self, bit_size: usize) -> BigUint311 fn gen_prime(&mut self, bit_size: usize) -> BigUint { 312 if bit_size < 2 { 313 panic!("prime size must be at least 2-bit"); 314 } 315 316 let mut b = bit_size % 8; 317 if b == 0 { 318 b = 8; 319 } 320 321 let bytes_len = (bit_size + 7) / 8; 322 let mut bytes = vec![0u8; bytes_len]; 323 324 loop { 325 self.fill_bytes(&mut bytes); 326 // Clear bits in the first byte to make sure the candidate has a size <= bits. 327 bytes[0] &= ((1u32 << (b as u32)) - 1) as u8; 328 329 // Don't let the value be too small, i.e, set the most significant two bits. 330 // Setting the top two bits, rather than just the top bit, 331 // means that when two of these values are multiplied together, 332 // the result isn't ever one bit short. 333 if b >= 2 { 334 bytes[0] |= 3u8.wrapping_shl(b as u32 - 2); 335 } else { 336 // Here b==1, because b cannot be zero. 337 bytes[0] |= 1; 338 if bytes_len > 1 { 339 bytes[1] |= 0x80; 340 } 341 } 342 343 // Make the value odd since an even number this large certainly isn't prime. 344 bytes[bytes_len - 1] |= 1u8; 345 346 let mut p = BigUint::from_bytes_be(&bytes); 347 // must always be a u64, as the SMALL_PRIMES_PRODUCT is a u64 348 let rem = (&p % &*SMALL_PRIMES_PRODUCT).to_u64().unwrap(); 349 350 'next: for delta in range_step(0, 1 << 20, 2) { 351 let m = rem + delta; 352 353 for prime in &SMALL_PRIMES { 354 if m % u64::from(*prime) == 0 && (bit_size > 6 || m != u64::from(*prime)) { 355 continue 'next; 356 } 357 } 358 359 if delta > 0 { 360 p += BigUint::from_u64(delta).unwrap(); 361 } 362 363 break; 364 } 365 366 // There is a tiny possibility that, by adding delta, we caused 367 // the number to be one bit too long. Thus we check bit length here. 368 if p.bits() == bit_size && probably_prime(&p, 20) { 369 return p; 370 } 371 } 372 } 373 } 374