#![no_std]
use core::sync::atomic::{AtomicU64, Ordering};
static STATE: [AtomicU64; 4] = [
AtomicU64::new(0x1469_ABE1_2345_6789),
AtomicU64::new(0x9876_5432_FEDC_BA98),
AtomicU64::new(0xABCD_EF01_2345_6789),
AtomicU64::new(0xFEDC_BA98_7654_3210),
];
#[inline]
pub fn rand64() -> u64 {
let mut s = load_state();
let result = next(&mut s);
store_state(&s);
result
}
#[inline]
pub fn rand32() -> u32 {
(rand64() >> 32) as u32
}
#[inline]
pub fn srand(seed: u64) {
let seed = if seed == 0 { 1 } else { seed };
let mut sm = seed;
let s = [splitmix64(&mut sm), splitmix64(&mut sm), splitmix64(&mut sm), splitmix64(&mut sm)];
store_state(&s);
}
#[inline]
pub fn rand_range(bound: u64) -> u64 {
debug_assert!(bound > 0);
let threshold = bound.wrapping_neg() % bound;
loop {
let r = rand64();
if r >= threshold {
return r % bound;
}
}
}
#[inline]
fn next(s: &mut [u64; 4]) -> u64 {
let result = (s[0].wrapping_add(s[3])).rotate_left(23).wrapping_add(s[0]);
let t = s[1] << 17;
s[2] ^= s[0];
s[3] ^= s[1];
s[1] ^= s[2];
s[0] ^= s[3];
s[2] ^= t;
s[3] = s[3].rotate_left(45);
result
}
#[inline]
fn splitmix64(state: &mut u64) -> u64 {
*state = state.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = *state;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
#[inline]
fn load_state() -> [u64; 4] {
[
STATE[0].load(Ordering::Relaxed),
STATE[1].load(Ordering::Relaxed),
STATE[2].load(Ordering::Relaxed),
STATE[3].load(Ordering::Relaxed),
]
}
#[inline]
fn store_state(s: &[u64; 4]) {
STATE[0].store(s[0], Ordering::Relaxed);
STATE[1].store(s[1], Ordering::Relaxed);
STATE[2].store(s[2], Ordering::Relaxed);
STATE[3].store(s[3], Ordering::Relaxed);
}