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