-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathrand.rs
77 lines (63 loc) · 2.41 KB
/
rand.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! Random number generator support.
use super::BoxedUint;
use crate::{
uint::rand::{random_bits_core, random_mod_core},
NonZero, RandomBits, RandomBitsError, RandomMod,
};
use rand_core::RngCore;
impl RandomBits for BoxedUint {
fn try_random_bits(rng: &mut impl RngCore, bit_length: u32) -> Result<Self, RandomBitsError> {
Self::try_random_bits_with_precision(rng, bit_length, bit_length)
}
fn try_random_bits_with_precision(
rng: &mut impl RngCore,
bit_length: u32,
bits_precision: u32,
) -> Result<Self, RandomBitsError> {
if bit_length > bits_precision {
return Err(RandomBitsError::BitLengthTooLarge {
bit_length,
bits_precision,
});
}
let mut ret = BoxedUint::zero_with_precision(bits_precision);
random_bits_core(rng, &mut ret.limbs, bit_length)?;
Ok(ret)
}
}
impl RandomMod for BoxedUint {
fn random_mod(rng: &mut impl RngCore, modulus: &NonZero<Self>) -> Self {
let mut n = BoxedUint::zero_with_precision(modulus.bits_precision());
random_mod_core(rng, &mut n, modulus, modulus.bits());
n
}
}
#[cfg(test)]
mod tests {
use crate::{BoxedUint, NonZero, RandomBits, RandomMod};
use rand_core::SeedableRng;
#[test]
fn random() {
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(1);
let r = BoxedUint::random_bits(&mut rng, 256);
assert!(r.bits_precision() == 256);
let r = BoxedUint::random_bits(&mut rng, 256 - 32 + 1);
assert!(r.bits_precision() == 256);
assert!(r < BoxedUint::one_with_precision(256) << (256 - 32 + 1));
}
#[test]
fn random_mod() {
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(1);
// Ensure `random_mod` runs in a reasonable amount of time
let modulus = NonZero::new(BoxedUint::from(42u8)).unwrap();
let res = BoxedUint::random_mod(&mut rng, &modulus);
// Check that the value is in range
assert!(res < BoxedUint::from(42u8));
// Ensure `random_mod` runs in a reasonable amount of time
// when the modulus is larger than 1 limb
let modulus = NonZero::new(BoxedUint::from(0x10000000000000001u128)).unwrap();
let res = BoxedUint::random_mod(&mut rng, &modulus);
// Check that the value is in range
assert!(res < BoxedUint::from(0x10000000000000001u128));
}
}