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