apint/apint/
rand_impl.rs

1use apint::{ApInt};
2use bitwidth::{BitWidth};
3use digit::{Digit};
4
5use rand;
6
7impl rand::Rand for Digit {
8    /// Creates a random `Digit` using the given random number generator.
9	fn rand<R: rand::Rng>(rng: &mut R) -> Digit {
10		Digit(rng.next_u64())
11	}
12}
13
14/// # Random Utilities using `rand` crate.
15impl ApInt {
16	/// Creates a new `ApInt` with the given `BitWidth` and random `Digit`s.
17	pub fn random_with_width(width: BitWidth) -> ApInt {
18		ApInt::random_with_width_using(width, &mut rand::weak_rng())
19	}
20
21	/// Creates a new `ApInt` with the given `BitWidth` and random `Digit`s
22    /// using the given random number generator.
23    /// 
24    /// **Note:** This is useful for cryptographic or testing purposes.
25    pub fn random_with_width_using<R>(width: BitWidth, rng: &mut R) -> ApInt
26        where R: rand::Rng
27    {
28        let required_digits = width.required_digits();
29        assert!(required_digits >= 1);
30        let random_digits = rng.gen_iter::<Digit>().take(required_digits);
31        ApInt::from_iter(random_digits)
32            .expect("We asserted that `required_digits` is at least `1` or greater
33                     so it is safe to assume that `ApInt::from_iter` won't fail.")
34            .into_truncate(width) // This truncation will be cheap always!
35            .expect("`BitWidth::required_digits` returns an upper bound for the
36                     number of required digits, so it is safe to truncate.")
37    }
38
39    /// Randomizes the digits of this `ApInt` inplace.
40    /// 
41    /// This won't change its `BitWidth`.
42    pub fn randomize(&mut self) {
43        self.randomize_using(&mut rand::weak_rng())
44    }
45
46    /// Randomizes the digits of this `ApInt` inplace using the given
47    /// random number generator.
48    /// 
49    /// This won't change its `BitWidth`.
50    pub fn randomize_using<R>(&mut self, rng: &mut R)
51        where R: rand::Rng
52    {
53        self.digits_mut()
54            .zip(rng.gen_iter::<Digit>())
55            .for_each(|(d, r)| *d = r);
56        self.clear_unused_bits();
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn random_with_width_using() {
66        let mut rng = rand::XorShiftRng::new_unseeded();
67        let r = &mut rng;
68        assert_eq!(ApInt::random_with_width_using(BitWidth::w1(), r), ApInt::from_bit(false));
69        assert_eq!(ApInt::random_with_width_using(BitWidth::w8(), r), ApInt::from_u8(140));
70        assert_eq!(ApInt::random_with_width_using(BitWidth::w16(), r), ApInt::from_u16(970));
71        assert_eq!(ApInt::random_with_width_using(BitWidth::w32(), r), ApInt::from_u32(2466290541));
72        assert_eq!(ApInt::random_with_width_using(BitWidth::w64(), r), ApInt::from_u64(16730135874920933484));
73        assert_eq!(ApInt::random_with_width_using(BitWidth::w128(), r), ApInt::from_u128(217725508292902744084870179638383324996));
74    }
75
76    #[test]
77    fn randomize_using() {
78        let mut rng1 = rand::XorShiftRng::new_unseeded();
79        let mut rng2 = rand::XorShiftRng::new_unseeded();
80        let r1 = &mut rng1;
81        let r2 = &mut rng2;
82
83        {
84            let mut randomized = ApInt::from_bit(false);
85            randomized.randomize_using(r1);
86            let new_random = ApInt::random_with_width_using(BitWidth::w1(), r2);
87            assert_eq!(randomized, new_random);
88        }{
89            let mut randomized = ApInt::from_u8(0);
90            randomized.randomize_using(r1);
91            let new_random = ApInt::random_with_width_using(BitWidth::w8(), r2);
92            assert_eq!(randomized, new_random);
93        }{
94            let mut randomized = ApInt::from_u16(0);
95            randomized.randomize_using(r1);
96            let new_random = ApInt::random_with_width_using(BitWidth::w16(), r2);
97            assert_eq!(randomized, new_random);
98        }{
99            let mut randomized = ApInt::from_u32(0);
100            randomized.randomize_using(r1);
101            let new_random = ApInt::random_with_width_using(BitWidth::w32(), r2);
102            assert_eq!(randomized, new_random);
103        }{
104            let mut randomized = ApInt::from_u64(0);
105            randomized.randomize_using(r1);
106            let new_random = ApInt::random_with_width_using(BitWidth::w64(), r2);
107            assert_eq!(randomized, new_random);
108        }{
109            let mut randomized = ApInt::from_u128(0);
110            randomized.randomize_using(r1);
111            let new_random = ApInt::random_with_width_using(BitWidth::w128(), r2);
112            assert_eq!(randomized, new_random);
113        }
114    }
115}