use crate::{Z32, Z64};
use paste::paste;
use rand::Rng;
use rand::distr::{
Distribution, StandardUniform,
uniform::{Error, SampleBorrow, SampleUniform, UniformInt, UniformSampler},
};
macro_rules! impl_rand {
( $($z:literal), *) => {
$(
paste!{
impl<const P: [<u $z>]> Distribution<[<Z $z>]<P>> for StandardUniform {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [<Z $z>]<P> {
let num = rng.random_range(0..P);
[<Z $z>]::new_unchecked(num)
}
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct [<UniformZ $z>]<const P: [<u $z>]>(UniformInt<[<u $z>]>);
impl<const P: [<u $z>]> UniformSampler for [<UniformZ $z>]<P> {
type X = [<Z $z>]<P>;
fn new<B1, B2>(low: B1, high: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
{
Ok([<UniformZ $z>](
UniformInt::<[<u $z>]>::new(
low.borrow().repr(),
high.borrow().repr()
)?
))
}
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
{
Ok([<UniformZ $z>](UniformInt::<[<u $z>]>::new_inclusive(
low.borrow().repr(),
high.borrow().repr(),
)?))
}
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
[<Z $z>]::new_unchecked(self.0.sample(rng))
}
}
impl<const P: [<u $z>]> SampleUniform for [<Z $z>]<P> {
type Sampler = [<UniformZ $z>]<P>;
}
}
)*
}
}
impl_rand! {32, 64}
#[cfg(test)]
mod tests {
use rand::{Rng, SeedableRng};
const PRIMES: [u64; 3] = [3, 443619635352171979, 1152921504606846883];
#[test]
fn random() {
use crate::Z64;
let mut rng = rand_xoshiro::Xoshiro256StarStar::seed_from_u64(0);
for _ in 0..1000 {
let _z: Z64<{ PRIMES[0] }> = rng.random();
let _z: Z64<{ PRIMES[1] }> = rng.random();
let _z: Z64<{ PRIMES[2] }> = rng.random();
}
}
#[test]
fn random_range() {
use crate::Z64;
let mut rng = rand_xoshiro::Xoshiro256StarStar::seed_from_u64(0);
const P: u64 = PRIMES[2];
const MIN: Z64<P> = Z64::new(7);
const MAX: Z64<P> = Z64::new(153);
for _ in 0..1000 {
let z = rng.random_range(MIN..MAX);
assert!(z >= MIN);
assert!(z < MAX);
}
}
}