use parking_lot::Mutex;
pub trait RandomProvider: Send + Sync {
fn next_f64(&self) -> f64;
fn next_u64(&self) -> u64;
}
#[derive(Debug)]
pub struct SeededRandom {
state: Mutex<u64>,
}
impl SeededRandom {
pub fn new(seed: u64) -> Self {
Self {
state: Mutex::new(seed),
}
}
fn next_state(&self) -> u64 {
let mut state = self.state.lock();
*state = state
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
*state
}
}
impl RandomProvider for SeededRandom {
fn next_f64(&self) -> f64 {
let bits = self.next_state() >> 33;
bits as f64 / (1u64 << 31) as f64
}
fn next_u64(&self) -> u64 {
self.next_state()
}
}
#[derive(Debug)]
pub struct ThreadRng;
impl Default for ThreadRng {
fn default() -> Self {
Self
}
}
impl RandomProvider for ThreadRng {
fn next_f64(&self) -> f64 {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
let nanos = system_time_nanos();
nanos.hash(&mut hasher);
let bits = hasher.finish() >> 33;
bits as f64 / (1u64 << 31) as f64
}
fn next_u64(&self) -> u64 {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
let nanos = system_time_nanos();
nanos.hash(&mut hasher);
hasher.finish()
}
}
#[cfg(not(target_arch = "wasm32"))]
fn system_time_nanos() -> u128 {
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0)
}
#[cfg(target_arch = "wasm32")]
fn system_time_nanos() -> u128 {
(js_sys::Date::now() * 1_000_000.0) as u128
}