use fastrand as fr;
use paste::paste;
use crate::Wdg;
use std::cell::Cell;
#[allow(clippy::derivable_impls)]
impl Default for Wdg {
fn default() -> Self {
Self(fr::Rng::default())
}
}
impl Wdg {
pub fn new() -> Self {
try_with_wdg(Wdg::fork).unwrap_or_else(|_| Wdg::with_seed(0x0d_6a_b0_f1_c7_ff_b9_1b))
}
}
thread_local! {
static GLOBAL_WDG: Cell<Wdg> = Cell::new(Wdg(fr::Rng::new()));
}
fn with_wdg<R>(f: impl FnOnce(&mut Wdg) -> R) -> R {
GLOBAL_WDG.with(|wdg| {
let current = wdg.replace(Wdg::with_seed(0));
let mut restore = RestoreOnDrop { wdg, current };
f(&mut restore.current)
})
}
fn try_with_wdg<R>(f: impl FnOnce(&mut Wdg) -> R) -> Result<R, std::thread::AccessError> {
GLOBAL_WDG.try_with(|wdg| {
let current = wdg.replace(Wdg::with_seed(0));
let mut restore = RestoreOnDrop { wdg, current };
f(&mut restore.current)
})
}
struct RestoreOnDrop<'a> {
wdg: &'a Cell<Wdg>,
current: Wdg,
}
impl Drop for RestoreOnDrop<'_> {
fn drop(&mut self) {
self.wdg.set(Wdg(self.current.0.clone()));
}
}
pub fn seed(seed: u64) {
with_wdg(|wdg| wdg.seed(seed));
}
pub fn get_seed() -> u64 {
with_wdg(|wdg| wdg.get_seed())
}
pub fn nan_f32() -> f32 {
with_wdg(|wdg| wdg.nan_f32())
}
pub fn nan_f64() -> f64 {
with_wdg(|wdg| wdg.nan_f64())
}
pub fn subnormal_f32() -> f32 {
with_wdg(|wdg| wdg.subnormal_f32())
}
pub fn subnormal_f64() -> f64 {
with_wdg(|wdg| wdg.subnormal_f64())
}
pub fn normal_f32() -> f32 {
with_wdg(|wdg| wdg.normal_f32())
}
pub fn normal_f64() -> f64 {
with_wdg(|wdg| wdg.normal_f64())
}
pub fn special_f32() -> f32 {
with_wdg(|wdg| wdg.special_f32())
}
pub fn special_f64() -> f64 {
with_wdg(|wdg| wdg.special_f64())
}
pub fn f32() -> f32 {
with_wdg(|wdg| wdg.f32())
}
pub fn f64() -> f64 {
with_wdg(|wdg| wdg.f64())
}
macro_rules! int_uint {
($($t:ty),+ $(,)?) => {
$(
int_uint_inner!($t);
)+
};
}
macro_rules! int_uint_inner {
($t:ty) => {
paste! {
#[doc = stringify!($t)]
pub fn [<special_ $t>]() -> $t {
with_wdg(|wdg| wdg.[<special_ $t>]())
}
#[doc = stringify!($t)]
pub fn $t() -> $t {
with_wdg(|wdg| wdg.$t())
}
}
};
}
int_uint!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);