summaryrefslogtreecommitdiffstats
path: root/third_party/rust/num-bigint/src/bigrand.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/num-bigint/src/bigrand.rs')
-rw-r--r--third_party/rust/num-bigint/src/bigrand.rs218
1 files changed, 218 insertions, 0 deletions
diff --git a/third_party/rust/num-bigint/src/bigrand.rs b/third_party/rust/num-bigint/src/bigrand.rs
new file mode 100644
index 0000000000..4a13b29df4
--- /dev/null
+++ b/third_party/rust/num-bigint/src/bigrand.rs
@@ -0,0 +1,218 @@
+//! Randomization of big integers
+
+use rand::distributions::uniform::{SampleUniform, UniformSampler};
+use rand::prelude::*;
+use rand::AsByteSliceMut;
+
+use BigInt;
+use BigUint;
+use Sign::*;
+
+use big_digit::BigDigit;
+use bigint::{into_magnitude, magnitude};
+
+use integer::Integer;
+use traits::Zero;
+
+pub trait RandBigInt {
+ /// Generate a random `BigUint` of the given bit size.
+ fn gen_biguint(&mut self, bit_size: usize) -> BigUint;
+
+ /// Generate a random BigInt of the given bit size.
+ fn gen_bigint(&mut self, bit_size: usize) -> BigInt;
+
+ /// Generate a random `BigUint` less than the given bound. Fails
+ /// when the bound is zero.
+ fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
+
+ /// Generate a random `BigUint` within the given range. The lower
+ /// bound is inclusive; the upper bound is exclusive. Fails when
+ /// the upper bound is not greater than the lower bound.
+ fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
+
+ /// Generate a random `BigInt` within the given range. The lower
+ /// bound is inclusive; the upper bound is exclusive. Fails when
+ /// the upper bound is not greater than the lower bound.
+ fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
+}
+
+impl<R: Rng + ?Sized> RandBigInt for R {
+ fn gen_biguint(&mut self, bit_size: usize) -> BigUint {
+ use super::big_digit::BITS;
+ let (digits, rem) = bit_size.div_rem(&BITS);
+ let mut data = vec![BigDigit::default(); digits + (rem > 0) as usize];
+ // `fill_bytes` is faster than many `gen::<u32>` calls
+ self.fill_bytes(data[..].as_byte_slice_mut());
+ // Swap bytes per the `Rng::fill` source. This might be
+ // unnecessary if reproducibility across architectures is not
+ // desired.
+ data.to_le();
+ if rem > 0 {
+ data[digits] >>= BITS - rem;
+ }
+ BigUint::new(data)
+ }
+
+ fn gen_bigint(&mut self, bit_size: usize) -> BigInt {
+ loop {
+ // Generate a random BigUint...
+ let biguint = self.gen_biguint(bit_size);
+ // ...and then randomly assign it a Sign...
+ let sign = if biguint.is_zero() {
+ // ...except that if the BigUint is zero, we need to try
+ // again with probability 0.5. This is because otherwise,
+ // the probability of generating a zero BigInt would be
+ // double that of any other number.
+ if self.gen() {
+ continue;
+ } else {
+ NoSign
+ }
+ } else if self.gen() {
+ Plus
+ } else {
+ Minus
+ };
+ return BigInt::from_biguint(sign, biguint);
+ }
+ }
+
+ fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
+ assert!(!bound.is_zero());
+ let bits = bound.bits();
+ loop {
+ let n = self.gen_biguint(bits);
+ if n < *bound {
+ return n;
+ }
+ }
+ }
+
+ fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint {
+ assert!(*lbound < *ubound);
+ if lbound.is_zero() {
+ self.gen_biguint_below(ubound)
+ } else {
+ lbound + self.gen_biguint_below(&(ubound - lbound))
+ }
+ }
+
+ fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt {
+ assert!(*lbound < *ubound);
+ if lbound.is_zero() {
+ BigInt::from(self.gen_biguint_below(magnitude(&ubound)))
+ } else if ubound.is_zero() {
+ lbound + BigInt::from(self.gen_biguint_below(magnitude(&lbound)))
+ } else {
+ let delta = ubound - lbound;
+ lbound + BigInt::from(self.gen_biguint_below(magnitude(&delta)))
+ }
+ }
+}
+
+/// The back-end implementing rand's `UniformSampler` for `BigUint`.
+#[derive(Clone, Debug)]
+pub struct UniformBigUint {
+ base: BigUint,
+ len: BigUint,
+}
+
+impl UniformSampler for UniformBigUint {
+ type X = BigUint;
+
+ #[inline]
+ fn new(low: Self::X, high: Self::X) -> Self {
+ assert!(low < high);
+ UniformBigUint {
+ len: high - &low,
+ base: low,
+ }
+ }
+
+ #[inline]
+ fn new_inclusive(low: Self::X, high: Self::X) -> Self {
+ assert!(low <= high);
+ Self::new(low, high + 1u32)
+ }
+
+ #[inline]
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
+ &self.base + rng.gen_biguint_below(&self.len)
+ }
+
+ #[inline]
+ fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X {
+ rng.gen_biguint_range(&low, &high)
+ }
+}
+
+impl SampleUniform for BigUint {
+ type Sampler = UniformBigUint;
+}
+
+/// The back-end implementing rand's `UniformSampler` for `BigInt`.
+#[derive(Clone, Debug)]
+pub struct UniformBigInt {
+ base: BigInt,
+ len: BigUint,
+}
+
+impl UniformSampler for UniformBigInt {
+ type X = BigInt;
+
+ #[inline]
+ fn new(low: Self::X, high: Self::X) -> Self {
+ assert!(low < high);
+ UniformBigInt {
+ len: into_magnitude(high - &low),
+ base: low,
+ }
+ }
+
+ #[inline]
+ fn new_inclusive(low: Self::X, high: Self::X) -> Self {
+ assert!(low <= high);
+ Self::new(low, high + 1u32)
+ }
+
+ #[inline]
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
+ &self.base + BigInt::from(rng.gen_biguint_below(&self.len))
+ }
+
+ #[inline]
+ fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X {
+ rng.gen_bigint_range(&low, &high)
+ }
+}
+
+impl SampleUniform for BigInt {
+ type Sampler = UniformBigInt;
+}
+
+/// A random distribution for `BigUint` and `BigInt` values of a particular bit size.
+#[derive(Clone, Copy, Debug)]
+pub struct RandomBits {
+ bits: usize,
+}
+
+impl RandomBits {
+ #[inline]
+ pub fn new(bits: usize) -> RandomBits {
+ RandomBits { bits }
+ }
+}
+
+impl Distribution<BigUint> for RandomBits {
+ #[inline]
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint {
+ rng.gen_biguint(self.bits)
+ }
+}
+
+impl Distribution<BigInt> for RandomBits {
+ #[inline]
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt {
+ rng.gen_bigint(self.bits)
+ }
+}