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