Skip to main content

num_bigint/bigrand/
distr.rs

1//! Random distributions of big integers
2#![allow(clippy::duplicate_mod)]
3
4use super::{rand, BigRng};
5use crate::{BigInt, BigUint, RandomBits, UniformBigInt, UniformBigUint};
6
7use rand::distr::uniform::{Error, SampleBorrow, SampleUniform, UniformSampler};
8use rand::distr::Distribution;
9use rand::Rng;
10
11/// Registers [`UniformBigUint`] as the back-end enabling
12/// [`Uniform`][rand::distr::Uniform] for [`BigUint`].
13impl SampleUniform for BigUint {
14    type Sampler = UniformBigUint;
15}
16
17/// Enables [`Uniform`][rand::distr::Uniform] for [`BigUint`].
18impl UniformSampler for UniformBigUint {
19    type X = BigUint;
20
21    #[inline]
22    fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
23    where
24        B1: SampleBorrow<Self::X> + Sized,
25        B2: SampleBorrow<Self::X> + Sized,
26    {
27        let low = low_b.borrow();
28        let high = high_b.borrow();
29        if low < high {
30            Ok(UniformBigUint {
31                len: high - low,
32                base: low.clone(),
33            })
34        } else {
35            Err(Error::EmptyRange)
36        }
37    }
38
39    #[inline]
40    fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
41    where
42        B1: SampleBorrow<Self::X> + Sized,
43        B2: SampleBorrow<Self::X> + Sized,
44    {
45        let low = low_b.borrow();
46        let high = high_b.borrow();
47        if low <= high {
48            Ok(UniformBigUint {
49                len: high - low + 1u32,
50                base: low.clone(),
51            })
52        } else {
53            Err(Error::EmptyRange)
54        }
55    }
56
57    #[inline]
58    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
59        &self.base + rng.random_biguint_below(&self.len)
60    }
61
62    #[inline]
63    fn sample_single<R: Rng + ?Sized, B1, B2>(
64        low: B1,
65        high: B2,
66        rng: &mut R,
67    ) -> Result<Self::X, Error>
68    where
69        B1: SampleBorrow<Self::X> + Sized,
70        B2: SampleBorrow<Self::X> + Sized,
71    {
72        let low = low.borrow();
73        let high = high.borrow();
74        if low < high {
75            Ok(rng.random_biguint_range(low, high))
76        } else {
77            Err(Error::EmptyRange)
78        }
79    }
80
81    #[inline]
82    fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
83        low: B1,
84        high: B2,
85        rng: &mut R,
86    ) -> Result<Self::X, Error>
87    where
88        B1: SampleBorrow<Self::X> + Sized,
89        B2: SampleBorrow<Self::X> + Sized,
90    {
91        let low = low.borrow();
92        let high = high.borrow();
93        if low <= high {
94            Ok(rng.random_biguint_range(low, &(high + 1u32)))
95        } else {
96            Err(Error::EmptyRange)
97        }
98    }
99}
100
101/// Registers [`UniformBigInt`] as the back-end enabling
102/// [`Uniform`][rand::distr::Uniform] for [`BigInt`].
103impl SampleUniform for BigInt {
104    type Sampler = UniformBigInt;
105}
106
107/// Enables [`Uniform`][rand::distr::Uniform] for [`BigInt`].
108impl UniformSampler for UniformBigInt {
109    type X = BigInt;
110
111    #[inline]
112    fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
113    where
114        B1: SampleBorrow<Self::X> + Sized,
115        B2: SampleBorrow<Self::X> + Sized,
116    {
117        let low = low_b.borrow();
118        let high = high_b.borrow();
119        if low < high {
120            Ok(UniformBigInt {
121                len: (high - low).into_parts().1,
122                base: low.clone(),
123            })
124        } else {
125            Err(Error::EmptyRange)
126        }
127    }
128
129    #[inline]
130    fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
131    where
132        B1: SampleBorrow<Self::X> + Sized,
133        B2: SampleBorrow<Self::X> + Sized,
134    {
135        let low = low_b.borrow();
136        let high = high_b.borrow();
137        if low <= high {
138            Ok(UniformBigInt {
139                len: (high - low).into_parts().1 + 1u32,
140                base: low.clone(),
141            })
142        } else {
143            Err(Error::EmptyRange)
144        }
145    }
146
147    #[inline]
148    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
149        &self.base + BigInt::from(rng.random_biguint_below(&self.len))
150    }
151
152    #[inline]
153    fn sample_single<R: Rng + ?Sized, B1, B2>(
154        low: B1,
155        high: B2,
156        rng: &mut R,
157    ) -> Result<Self::X, Error>
158    where
159        B1: SampleBorrow<Self::X> + Sized,
160        B2: SampleBorrow<Self::X> + Sized,
161    {
162        let low = low.borrow();
163        let high = high.borrow();
164        if low < high {
165            Ok(rng.random_bigint_range(low, high))
166        } else {
167            Err(Error::EmptyRange)
168        }
169    }
170
171    #[inline]
172    fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
173        low: B1,
174        high: B2,
175        rng: &mut R,
176    ) -> Result<Self::X, Error>
177    where
178        B1: SampleBorrow<Self::X> + Sized,
179        B2: SampleBorrow<Self::X> + Sized,
180    {
181        let low = low.borrow();
182        let high = high.borrow();
183        if low <= high {
184            Ok(rng.random_bigint_range(low, &(high + 1u32)))
185        } else {
186            Err(Error::EmptyRange)
187        }
188    }
189}
190
191impl Distribution<BigUint> for RandomBits {
192    #[inline]
193    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint {
194        rng.random_biguint(self.bits)
195    }
196}
197
198impl Distribution<BigInt> for RandomBits {
199    #[inline]
200    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt {
201        rng.random_bigint(self.bits)
202    }
203}