use std::ops::{Add, AddAssign};
use rand::{
distributions::{uniform::SampleUniform, Distribution, Uniform},
Rng,
};
use crate::prng::make_prng;
pub fn int_in_range<T>(randomness: [u8; 32], begin: T, end: T) -> T
where
T: SampleUniform + Int,
{
let mut rng = make_prng(randomness);
rng.gen_range(begin..=end)
}
pub fn ints_in_range<T>(randomness: [u8; 32], count: usize, begin: T, end: T) -> Vec<T>
where
T: SampleUniform + Int,
{
let mut rng = make_prng(randomness);
let uniform: Uniform<T> = Uniform::new_inclusive(begin, end);
let mut out = Vec::with_capacity(count);
for _ in 0..count {
out.push(uniform.sample(&mut rng));
}
debug_assert_eq!(out.len(), count); debug_assert_eq!(out.capacity(), count); out
}
pub trait Int: PartialOrd + Default + Copy {}
impl Int for u8 {}
impl Int for u16 {}
impl Int for u32 {}
impl Int for u64 {}
impl Int for u128 {}
impl Int for usize {}
impl Int for i8 {}
impl Int for i16 {}
impl Int for i32 {}
impl Int for i64 {}
impl Int for i128 {}
impl Int for isize {}
pub trait Uint: PartialOrd + Default + Copy + AddAssign<Self> + Add<Self> + Int {
const ZERO: Self;
const ONE: Self;
fn checked_add(self, rhs: Self) -> Option<Self>;
}
impl Uint for u8 {
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline]
fn checked_add(self, rhs: Self) -> Option<Self> {
self.checked_add(rhs)
}
}
impl Uint for u16 {
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline]
fn checked_add(self, rhs: Self) -> Option<Self> {
self.checked_add(rhs)
}
}
impl Uint for u32 {
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline]
fn checked_add(self, rhs: Self) -> Option<Self> {
self.checked_add(rhs)
}
}
impl Uint for u64 {
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline]
fn checked_add(self, rhs: Self) -> Option<Self> {
self.checked_add(rhs)
}
}
impl Uint for u128 {
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline]
fn checked_add(self, rhs: Self) -> Option<Self> {
self.checked_add(rhs)
}
}
impl Uint for usize {
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline]
fn checked_add(self, rhs: Self) -> Option<Self> {
self.checked_add(rhs)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn int_in_range_works() {
let result = int_in_range(
[
88, 85, 86, 91, 61, 64, 60, 71, 234, 24, 246, 200, 35, 73, 38, 187, 54, 59, 96, 9,
237, 27, 215, 103, 148, 230, 28, 48, 51, 114, 203, 219,
],
4,
18,
);
assert_eq!(result, 11);
let result = int_in_range(
[
207, 251, 10, 105, 100, 223, 244, 6, 207, 231, 253, 206, 157, 68, 143, 184, 209,
222, 70, 249, 114, 160, 213, 73, 147, 94, 136, 191, 94, 98, 99, 170,
],
4,
18,
);
assert_eq!(result, 17);
let result = int_in_range(
[
43, 140, 160, 0, 187, 41, 212, 6, 218, 53, 58, 198, 80, 209, 171, 239, 222, 247,
30, 23, 184, 79, 79, 221, 192, 225, 217, 142, 135, 164, 169, 255,
],
4,
18,
);
assert_eq!(result, 6);
let result = int_in_range(
[
43, 140, 160, 0, 187, 41, 212, 6, 218, 53, 58, 198, 80, 209, 171, 239, 222, 247,
30, 23, 184, 79, 79, 221, 192, 225, 217, 142, 135, 164, 169, 255,
],
123,
123,
);
assert_eq!(result, 123);
let result = int_in_range(
[
74, 71, 86, 169, 247, 21, 60, 71, 234, 24, 246, 215, 35, 73, 38, 187, 54, 59, 96,
9, 237, 27, 215, 103, 14, 230, 28, 48, 51, 114, 203, 219,
],
-100,
100,
);
assert_eq!(result, -28);
let result = int_in_range(
[
74, 71, 86, 169, 247, 21, 60, 71, 234, 24, 246, 215, 35, 73, 38, 187, 54, 59, 96,
9, 237, 27, 215, 103, 14, 230, 28, 48, 51, 114, 203, 219,
],
17u128,
u128::MAX,
);
assert_eq!(result, 226364637901700064573816523306429827859);
}
#[test]
#[should_panic = "cannot sample empty range"]
fn int_in_range_panicks_for_empty() {
let result = int_in_range(
[
52, 187, 72, 255, 102, 110, 115, 233, 50, 165, 124, 255, 217, 131, 112, 209, 253,
176, 108, 99, 102, 225, 12, 36, 82, 107, 106, 207, 99, 107, 197, 84,
],
4,
3,
);
assert_eq!(result, 5);
}
#[test]
fn ints_in_range_works() {
let randomness = [
88, 85, 86, 91, 61, 64, 60, 71, 234, 24, 246, 200, 35, 73, 38, 187, 54, 59, 96, 9, 237,
27, 215, 103, 148, 230, 28, 48, 51, 114, 203, 219,
];
let result = ints_in_range(randomness, 0, 4, 18);
assert!(result.is_empty());
let result = ints_in_range(randomness, 1, 4, 18);
assert_eq!(result, [11]);
let result = ints_in_range(randomness, 2, 4, 18);
assert_eq!(result, [11, 16]);
let result = ints_in_range(randomness, 48, u8::MIN, u8::MAX);
assert_eq!(
result,
[
219, 146, 8, 157, 12, 162, 84, 223, 3, 97, 133, 37, 53, 86, 198, 64, 75, 26, 54,
96, 70, 55, 212, 140, 127, 33, 198, 177, 149, 112, 67, 160, 86, 188, 211, 226, 189,
175, 183, 201, 74, 108, 124, 109, 59, 47, 153, 44
]
);
}
}