#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BoundedRandU32 {
count: u32,
threshold: u32,
}
impl BoundedRandU32 {
#[allow(missing_docs)]
pub const _4: Self = Self::new(4);
#[allow(missing_docs)]
pub const _6: Self = Self::new(6);
#[allow(missing_docs)]
pub const _8: Self = Self::new(8);
#[allow(missing_docs)]
pub const _10: Self = Self::new(10);
#[allow(missing_docs)]
pub const _12: Self = Self::new(12);
#[allow(missing_docs)]
pub const _20: Self = Self::new(20);
#[inline]
pub const fn new(count: u32) -> Self {
let threshold = count.wrapping_neg() % count;
Self { count, threshold }
}
#[inline]
pub const fn try_new(count: u32) -> Option<Self> {
if count > 0 {
Some(Self::new(count))
} else {
None
}
}
#[inline]
pub const fn count(self) -> u32 {
self.count
}
#[inline]
pub const fn place_in_range(self, val: u32) -> Option<u32> {
let mul: u64 = (val as u64).wrapping_mul(self.count as u64);
let low_part: u32 = mul as u32;
if low_part < self.threshold {
None
} else {
debug_assert!(((mul >> 32) as u32) < self.count());
Some((mul >> 32) as u32)
}
}
#[inline]
pub fn sample<F: FnMut() -> u32>(self, mut f: F) -> u32 {
loop {
if let Some(output) = self.place_in_range(f()) {
return output;
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BoundedRandU16 {
count: u16,
threshold: u16,
}
impl BoundedRandU16 {
#[allow(missing_docs)]
pub const _4: Self = Self::new(4);
#[allow(missing_docs)]
pub const _6: Self = Self::new(6);
#[allow(missing_docs)]
pub const _8: Self = Self::new(8);
#[allow(missing_docs)]
pub const _10: Self = Self::new(10);
#[allow(missing_docs)]
pub const _12: Self = Self::new(12);
#[allow(missing_docs)]
pub const _20: Self = Self::new(20);
#[inline]
pub const fn new(count: u16) -> Self {
let threshold = count.wrapping_neg() % count;
Self { count, threshold }
}
#[inline]
pub const fn try_new(count: u16) -> Option<Self> {
if count > 0 {
Some(Self::new(count))
} else {
None
}
}
#[inline]
pub const fn count(self) -> u16 {
self.count
}
#[inline]
pub const fn place_in_range(self, val: u16) -> Option<u16> {
let mul: u32 = (val as u32).wrapping_mul(self.count as u32);
let low_part: u16 = mul as u16;
if low_part < self.threshold {
None
} else {
debug_assert!(((mul >> 16) as u16) < self.count());
Some((mul >> 16) as u16)
}
}
#[inline]
pub fn sample<F: FnMut() -> u16>(self, mut f: F) -> u16 {
loop {
if let Some(output) = self.place_in_range(f()) {
return output;
}
}
}
}