1 //! Randomization of big integers
2 
3 use rand::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler};
4 use rand::prelude::*;
5 
6 use crate::BigInt;
7 use crate::BigUint;
8 use crate::Sign::*;
9 
10 use crate::biguint::biguint_from_vec;
11 
12 use num_integer::Integer;
13 use num_traits::{ToPrimitive, Zero};
14 
15 /// A trait for sampling random big integers.
16 ///
17 /// The `rand` feature must be enabled to use this. See crate-level documentation for details.
18 pub trait RandBigInt {
19     /// Generate a random `BigUint` of the given bit size.
gen_biguint(&mut self, bit_size: u64) -> BigUint20     fn gen_biguint(&mut self, bit_size: u64) -> BigUint;
21 
22     /// Generate a random BigInt of the given bit size.
gen_bigint(&mut self, bit_size: u64) -> BigInt23     fn gen_bigint(&mut self, bit_size: u64) -> BigInt;
24 
25     /// Generate a random `BigUint` less than the given bound. Fails
26     /// when the bound is zero.
gen_biguint_below(&mut self, bound: &BigUint) -> BigUint27     fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
28 
29     /// Generate a random `BigUint` within the given range. The lower
30     /// bound is inclusive; the upper bound is exclusive. Fails when
31     /// the upper bound is not greater than the lower bound.
gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint32     fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
33 
34     /// Generate a random `BigInt` within the given range. The lower
35     /// bound is inclusive; the upper bound is exclusive. Fails when
36     /// the upper bound is not greater than the lower bound.
gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt37     fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
38 }
39 
gen_bits<R: Rng + ?Sized>(rng: &mut R, data: &mut [u32], rem: u64)40 fn gen_bits<R: Rng + ?Sized>(rng: &mut R, data: &mut [u32], rem: u64) {
41     // `fill` is faster than many `gen::<u32>` calls
42     rng.fill(data);
43     if rem > 0 {
44         let last = data.len() - 1;
45         data[last] >>= 32 - rem;
46     }
47 }
48 
49 impl<R: Rng + ?Sized> RandBigInt for R {
50     #[cfg(not(u64_digit))]
gen_biguint(&mut self, bit_size: u64) -> BigUint51     fn gen_biguint(&mut self, bit_size: u64) -> BigUint {
52         let (digits, rem) = bit_size.div_rem(&32);
53         let len = (digits + (rem > 0) as u64)
54             .to_usize()
55             .expect("capacity overflow");
56         let mut data = vec![0u32; len];
57         gen_bits(self, &mut data, rem);
58         biguint_from_vec(data)
59     }
60 
61     #[cfg(u64_digit)]
gen_biguint(&mut self, bit_size: u64) -> BigUint62     fn gen_biguint(&mut self, bit_size: u64) -> BigUint {
63         use core::slice;
64 
65         let (digits, rem) = bit_size.div_rem(&32);
66         let len = (digits + (rem > 0) as u64)
67             .to_usize()
68             .expect("capacity overflow");
69         let native_digits = bit_size.div_ceil(&64);
70         let native_len = native_digits.to_usize().expect("capacity overflow");
71         let mut data = vec![0u64; native_len];
72         unsafe {
73             // Generate bits in a `&mut [u32]` slice for value stability
74             let ptr = data.as_mut_ptr() as *mut u32;
75             debug_assert!(native_len * 2 >= len);
76             let data = slice::from_raw_parts_mut(ptr, len);
77             gen_bits(self, data, rem);
78         }
79         #[cfg(target_endian = "big")]
80         for digit in &mut data {
81             // swap u32 digits into u64 endianness
82             *digit = (*digit << 32) | (*digit >> 32);
83         }
84         biguint_from_vec(data)
85     }
86 
gen_bigint(&mut self, bit_size: u64) -> BigInt87     fn gen_bigint(&mut self, bit_size: u64) -> BigInt {
88         loop {
89             // Generate a random BigUint...
90             let biguint = self.gen_biguint(bit_size);
91             // ...and then randomly assign it a Sign...
92             let sign = if biguint.is_zero() {
93                 // ...except that if the BigUint is zero, we need to try
94                 // again with probability 0.5. This is because otherwise,
95                 // the probability of generating a zero BigInt would be
96                 // double that of any other number.
97                 if self.gen() {
98                     continue;
99                 } else {
100                     NoSign
101                 }
102             } else if self.gen() {
103                 Plus
104             } else {
105                 Minus
106             };
107             return BigInt::from_biguint(sign, biguint);
108         }
109     }
110 
gen_biguint_below(&mut self, bound: &BigUint) -> BigUint111     fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
112         assert!(!bound.is_zero());
113         let bits = bound.bits();
114         loop {
115             let n = self.gen_biguint(bits);
116             if n < *bound {
117                 return n;
118             }
119         }
120     }
121 
gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint122     fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint {
123         assert!(*lbound < *ubound);
124         if lbound.is_zero() {
125             self.gen_biguint_below(ubound)
126         } else {
127             lbound + self.gen_biguint_below(&(ubound - lbound))
128         }
129     }
130 
gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt131     fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt {
132         assert!(*lbound < *ubound);
133         if lbound.is_zero() {
134             BigInt::from(self.gen_biguint_below(ubound.magnitude()))
135         } else if ubound.is_zero() {
136             lbound + BigInt::from(self.gen_biguint_below(lbound.magnitude()))
137         } else {
138             let delta = ubound - lbound;
139             lbound + BigInt::from(self.gen_biguint_below(delta.magnitude()))
140         }
141     }
142 }
143 
144 /// The back-end implementing rand's `UniformSampler` for `BigUint`.
145 #[derive(Clone, Debug)]
146 pub struct UniformBigUint {
147     base: BigUint,
148     len: BigUint,
149 }
150 
151 impl UniformSampler for UniformBigUint {
152     type X = BigUint;
153 
154     #[inline]
new<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,155     fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
156     where
157         B1: SampleBorrow<Self::X> + Sized,
158         B2: SampleBorrow<Self::X> + Sized,
159     {
160         let low = low_b.borrow();
161         let high = high_b.borrow();
162         assert!(low < high);
163         UniformBigUint {
164             len: high - low,
165             base: low.clone(),
166         }
167     }
168 
169     #[inline]
new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,170     fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
171     where
172         B1: SampleBorrow<Self::X> + Sized,
173         B2: SampleBorrow<Self::X> + Sized,
174     {
175         let low = low_b.borrow();
176         let high = high_b.borrow();
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 + rng.gen_biguint_below(&self.len)
184     }
185 
186     #[inline]
sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,187     fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X
188     where
189         B1: SampleBorrow<Self::X> + Sized,
190         B2: SampleBorrow<Self::X> + Sized,
191     {
192         rng.gen_biguint_range(low.borrow(), high.borrow())
193     }
194 }
195 
196 impl SampleUniform for BigUint {
197     type Sampler = UniformBigUint;
198 }
199 
200 /// The back-end implementing rand's `UniformSampler` for `BigInt`.
201 #[derive(Clone, Debug)]
202 pub struct UniformBigInt {
203     base: BigInt,
204     len: BigUint,
205 }
206 
207 impl UniformSampler for UniformBigInt {
208     type X = BigInt;
209 
210     #[inline]
new<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,211     fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
212     where
213         B1: SampleBorrow<Self::X> + Sized,
214         B2: SampleBorrow<Self::X> + Sized,
215     {
216         let low = low_b.borrow();
217         let high = high_b.borrow();
218         assert!(low < high);
219         UniformBigInt {
220             len: (high - low).into_parts().1,
221             base: low.clone(),
222         }
223     }
224 
225     #[inline]
new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,226     fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
227     where
228         B1: SampleBorrow<Self::X> + Sized,
229         B2: SampleBorrow<Self::X> + Sized,
230     {
231         let low = low_b.borrow();
232         let high = high_b.borrow();
233         assert!(low <= high);
234         Self::new(low, high + 1u32)
235     }
236 
237     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X238     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
239         &self.base + BigInt::from(rng.gen_biguint_below(&self.len))
240     }
241 
242     #[inline]
sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,243     fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X
244     where
245         B1: SampleBorrow<Self::X> + Sized,
246         B2: SampleBorrow<Self::X> + Sized,
247     {
248         rng.gen_bigint_range(low.borrow(), high.borrow())
249     }
250 }
251 
252 impl SampleUniform for BigInt {
253     type Sampler = UniformBigInt;
254 }
255 
256 /// A random distribution for `BigUint` and `BigInt` values of a particular bit size.
257 ///
258 /// The `rand` feature must be enabled to use this. See crate-level documentation for details.
259 #[derive(Clone, Copy, Debug)]
260 pub struct RandomBits {
261     bits: u64,
262 }
263 
264 impl RandomBits {
265     #[inline]
new(bits: u64) -> RandomBits266     pub fn new(bits: u64) -> RandomBits {
267         RandomBits { bits }
268     }
269 }
270 
271 impl Distribution<BigUint> for RandomBits {
272     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint273     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint {
274         rng.gen_biguint(self.bits)
275     }
276 }
277 
278 impl Distribution<BigInt> for RandomBits {
279     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt280     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt {
281         rng.gen_bigint(self.bits)
282     }
283 }
284