use libc::{c_int, c_uint};
use rand::Rng;
use rand_core::SeedableRng;
use rand_pcg::Pcg32;
use rustix_futex_sync::Mutex;
#[cfg(test)]
static_assertions::assert_eq_size!(c_uint, u32);
static STATE: Mutex<Option<Pcg32>> = Mutex::new(None);
#[no_mangle]
unsafe extern "C" fn rand() -> c_int {
libc!(libc::rand());
let mut guard = STATE.lock();
if guard.is_none() {
internal_seed(&mut guard, 1);
}
(*guard).as_mut().unwrap().random_range(0..libc::RAND_MAX) as c_int
}
#[no_mangle]
unsafe extern "C" fn srand(seed: c_uint) {
libc!(libc::srand(seed));
internal_seed(&mut STATE.lock(), seed);
}
fn internal_seed(state: &mut Option<Pcg32>, seed: c_uint) {
*state = Some(Pcg32::seed_from_u64(u64::from(seed)));
}
#[no_mangle]
unsafe extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
let mut z = (*seed).wrapping_add(0x6D2B79F5);
*seed = z;
z = (z ^ (z >> 15)).wrapping_mul(z | 1);
z ^= z.wrapping_add((z ^ (z >> 7)).wrapping_mul(z | 61));
(z ^ (z >> 14)) as c_int
}