impl SampleUniform for BigInt
This commit is contained in:
parent
4ef07c4625
commit
b72822bbde
@ -117,6 +117,14 @@ pub fn magnitude(i: &BigInt) -> &BigUint {
|
||||
&i.data
|
||||
}
|
||||
|
||||
/// Return the owned magnitude of a `BigInt`.
|
||||
///
|
||||
/// This is in a private module, pseudo pub(crate)
|
||||
#[cfg(feature = "rand")]
|
||||
pub fn into_magnitude(i: BigInt) -> BigUint {
|
||||
i.data
|
||||
}
|
||||
|
||||
impl PartialEq for BigInt {
|
||||
#[inline]
|
||||
fn eq(&self, other: &BigInt) -> bool {
|
||||
|
@ -8,7 +8,7 @@ use BigUint;
|
||||
use Sign::*;
|
||||
|
||||
use big_digit::BigDigit;
|
||||
use bigint::magnitude;
|
||||
use bigint::{magnitude, into_magnitude};
|
||||
|
||||
use traits::Zero;
|
||||
use integer::Integer;
|
||||
@ -143,3 +143,40 @@ impl UniformSampler for UniformBigUint {
|
||||
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;
|
||||
|
||||
fn new(low: Self::X, high: Self::X) -> Self {
|
||||
assert!(low < high);
|
||||
UniformBigInt {
|
||||
len: into_magnitude(high - &low),
|
||||
base: low,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_inclusive(low: Self::X, high: Self::X) -> Self {
|
||||
assert!(low <= high);
|
||||
Self::new(low, high + 1u32)
|
||||
}
|
||||
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
|
||||
&self.base + BigInt::from(rng.gen_biguint_below(&self.len))
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ pub use bigint::BigInt;
|
||||
pub use bigint::ToBigInt;
|
||||
|
||||
#[cfg(feature = "rand")]
|
||||
pub use bigrand::{RandBigInt, UniformBigUint};
|
||||
pub use bigrand::{RandBigInt, UniformBigUint, UniformBigInt};
|
||||
|
||||
mod big_digit {
|
||||
/// A `BigDigit` is a `BigUint`'s composing element.
|
||||
|
@ -85,6 +85,8 @@ mod bigint {
|
||||
use num_bigint::{BigInt, RandBigInt};
|
||||
use num_traits::Zero;
|
||||
use rand::thread_rng;
|
||||
use rand::Rng;
|
||||
use rand::distributions::Uniform;
|
||||
|
||||
#[test]
|
||||
fn test_rand() {
|
||||
@ -134,4 +136,29 @@ mod bigint {
|
||||
// Switching u and l should fail:
|
||||
let _n: BigInt = rng.gen_bigint_range(&u, &l);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rand_uniform() {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let tiny = Uniform::new(BigInt::from(236u32), BigInt::from(237u32));
|
||||
for _ in 0..10 {
|
||||
assert_eq!(rng.sample(&tiny), BigInt::from(236u32));
|
||||
}
|
||||
|
||||
fn check(l: BigInt, u: BigInt) {
|
||||
let mut rng = thread_rng();
|
||||
let range = Uniform::new(l.clone(), u.clone());
|
||||
for _ in 0..1000 {
|
||||
let n: BigInt = rng.sample(&range);
|
||||
assert!(n >= l);
|
||||
assert!(n < u);
|
||||
}
|
||||
}
|
||||
let l: BigInt = BigInt::from(403469000 + 2352);
|
||||
let u: BigInt = BigInt::from(403469000 + 3513);
|
||||
check(l.clone(), u.clone());
|
||||
check(-l.clone(), u.clone());
|
||||
check(-u.clone(), -l.clone());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user