num_bigint/
bigrand.rs
1#![cfg(feature = "rand")]
3#![cfg_attr(docsrs, doc(cfg(feature = "rand")))]
4
5use rand::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler};
6use rand::prelude::*;
7
8use crate::BigInt;
9use crate::BigUint;
10use crate::Sign::*;
11
12use crate::biguint::biguint_from_vec;
13
14use num_integer::Integer;
15use num_traits::{ToPrimitive, Zero};
16
17pub trait RandBigInt {
21 fn gen_biguint(&mut self, bit_size: u64) -> BigUint;
23
24 fn gen_bigint(&mut self, bit_size: u64) -> BigInt;
26
27 fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
30
31 fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
35
36 fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
40}
41
42fn gen_bits<R: Rng + ?Sized>(rng: &mut R, data: &mut [u32], rem: u64) {
43 rng.fill(data);
45 if rem > 0 {
46 let last = data.len() - 1;
47 data[last] >>= 32 - rem;
48 }
49}
50
51impl<R: Rng + ?Sized> RandBigInt for R {
52 cfg_digit!(
53 fn gen_biguint(&mut self, bit_size: u64) -> BigUint {
54 let (digits, rem) = bit_size.div_rem(&32);
55 let len = (digits + (rem > 0) as u64)
56 .to_usize()
57 .expect("capacity overflow");
58 let mut data = vec![0u32; len];
59 gen_bits(self, &mut data, rem);
60 biguint_from_vec(data)
61 }
62
63 fn gen_biguint(&mut self, bit_size: u64) -> BigUint {
64 use core::slice;
65
66 let (digits, rem) = bit_size.div_rem(&32);
67 let len = (digits + (rem > 0) as u64)
68 .to_usize()
69 .expect("capacity overflow");
70 let native_digits = Integer::div_ceil(&bit_size, &64);
71 let native_len = native_digits.to_usize().expect("capacity overflow");
72 let mut data = vec![0u64; native_len];
73 unsafe {
74 let ptr = data.as_mut_ptr() as *mut u32;
76 debug_assert!(native_len * 2 >= len);
77 let data = slice::from_raw_parts_mut(ptr, len);
78 gen_bits(self, data, rem);
79 }
80 #[cfg(target_endian = "big")]
81 for digit in &mut data {
82 *digit = (*digit << 32) | (*digit >> 32);
84 }
85 biguint_from_vec(data)
86 }
87 );
88
89 fn gen_bigint(&mut self, bit_size: u64) -> BigInt {
90 loop {
91 let biguint = self.gen_biguint(bit_size);
93 let sign = if biguint.is_zero() {
95 if self.gen() {
100 continue;
101 } else {
102 NoSign
103 }
104 } else if self.gen() {
105 Plus
106 } else {
107 Minus
108 };
109 return BigInt::from_biguint(sign, biguint);
110 }
111 }
112
113 fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
114 assert!(!bound.is_zero());
115 let bits = bound.bits();
116 loop {
117 let n = self.gen_biguint(bits);
118 if n < *bound {
119 return n;
120 }
121 }
122 }
123
124 fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint {
125 assert!(*lbound < *ubound);
126 if lbound.is_zero() {
127 self.gen_biguint_below(ubound)
128 } else {
129 lbound + self.gen_biguint_below(&(ubound - lbound))
130 }
131 }
132
133 fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt {
134 assert!(*lbound < *ubound);
135 if lbound.is_zero() {
136 BigInt::from(self.gen_biguint_below(ubound.magnitude()))
137 } else if ubound.is_zero() {
138 lbound + BigInt::from(self.gen_biguint_below(lbound.magnitude()))
139 } else {
140 let delta = ubound - lbound;
141 lbound + BigInt::from(self.gen_biguint_below(delta.magnitude()))
142 }
143 }
144}
145
146#[derive(Clone, Debug)]
148pub struct UniformBigUint {
149 base: BigUint,
150 len: BigUint,
151}
152
153impl UniformSampler for UniformBigUint {
154 type X = BigUint;
155
156 #[inline]
157 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
158 where
159 B1: SampleBorrow<Self::X> + Sized,
160 B2: SampleBorrow<Self::X> + Sized,
161 {
162 let low = low_b.borrow();
163 let high = high_b.borrow();
164 assert!(low < high);
165 UniformBigUint {
166 len: high - low,
167 base: low.clone(),
168 }
169 }
170
171 #[inline]
172 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
173 where
174 B1: SampleBorrow<Self::X> + Sized,
175 B2: SampleBorrow<Self::X> + Sized,
176 {
177 let low = low_b.borrow();
178 let high = high_b.borrow();
179 assert!(low <= high);
180 Self::new(low, high + 1u32)
181 }
182
183 #[inline]
184 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
185 &self.base + rng.gen_biguint_below(&self.len)
186 }
187
188 #[inline]
189 fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X
190 where
191 B1: SampleBorrow<Self::X> + Sized,
192 B2: SampleBorrow<Self::X> + Sized,
193 {
194 rng.gen_biguint_range(low.borrow(), high.borrow())
195 }
196}
197
198impl SampleUniform for BigUint {
199 type Sampler = UniformBigUint;
200}
201
202#[derive(Clone, Debug)]
204pub struct UniformBigInt {
205 base: BigInt,
206 len: BigUint,
207}
208
209impl UniformSampler for UniformBigInt {
210 type X = BigInt;
211
212 #[inline]
213 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
214 where
215 B1: SampleBorrow<Self::X> + Sized,
216 B2: SampleBorrow<Self::X> + Sized,
217 {
218 let low = low_b.borrow();
219 let high = high_b.borrow();
220 assert!(low < high);
221 UniformBigInt {
222 len: (high - low).into_parts().1,
223 base: low.clone(),
224 }
225 }
226
227 #[inline]
228 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
229 where
230 B1: SampleBorrow<Self::X> + Sized,
231 B2: SampleBorrow<Self::X> + Sized,
232 {
233 let low = low_b.borrow();
234 let high = high_b.borrow();
235 assert!(low <= high);
236 Self::new(low, high + 1u32)
237 }
238
239 #[inline]
240 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
241 &self.base + BigInt::from(rng.gen_biguint_below(&self.len))
242 }
243
244 #[inline]
245 fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X
246 where
247 B1: SampleBorrow<Self::X> + Sized,
248 B2: SampleBorrow<Self::X> + Sized,
249 {
250 rng.gen_bigint_range(low.borrow(), high.borrow())
251 }
252}
253
254impl SampleUniform for BigInt {
255 type Sampler = UniformBigInt;
256}
257
258#[derive(Clone, Copy, Debug)]
262pub struct RandomBits {
263 bits: u64,
264}
265
266impl RandomBits {
267 #[inline]
268 pub fn new(bits: u64) -> RandomBits {
269 RandomBits { bits }
270 }
271}
272
273impl Distribution<BigUint> for RandomBits {
274 #[inline]
275 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint {
276 rng.gen_biguint(self.bits)
277 }
278}
279
280impl Distribution<BigInt> for RandomBits {
281 #[inline]
282 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt {
283 rng.gen_bigint(self.bits)
284 }
285}