#[cfg(loom)]
pub struct SimpleRng {
state: u64,
}
#[cfg(not(loom))]
pub(crate) struct SimpleRng {
state: u64,
}
impl SimpleRng {
#[cfg(loom)]
#[inline]
pub fn next_u32(&mut self) -> u32 {
next_u32(&mut self.state)
}
#[cfg(not(loom))]
#[inline]
pub(crate) fn next_u32(&mut self) -> u32 {
next_u32(&mut self.state)
}
}
fn next_u32(state: &mut u64) -> u32 {
*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 ^ (z >> 31);
z as u32
}
#[cfg(loom)]
#[inline]
pub fn simple_rng(op_id: &str, law_name: &str) -> SimpleRng {
SimpleRng {
state: seed(op_id, law_name),
}
}
#[cfg(not(loom))]
#[inline]
pub(crate) fn simple_rng(op_id: &str, law_name: &str) -> SimpleRng {
SimpleRng {
state: seed(op_id, law_name),
}
}
fn seed(op_id: &str, law_name: &str) -> u64 {
let mut hash = 0xcbf2_9ce4_8422_2325_u64;
if let Ok(seed) = std::env::var("VYRE_CONFORM_SEED") {
mix_bytes(&mut hash, seed.as_bytes());
}
mix_bytes(&mut hash, op_id.as_bytes());
mix_bytes(&mut hash, law_name.as_bytes());
hash
}
fn mix_bytes(hash: &mut u64, bytes: &[u8]) {
for byte in bytes {
*hash ^= u64::from(*byte);
*hash = hash.wrapping_mul(0x0000_0100_0000_01B3);
}
}