pub mod ephys;
pub mod ifc;
pub(crate) struct Rng {
s: [u64; 4],
}
impl Rng {
pub(crate) fn seed(seed: u64) -> Self {
let mut state = seed;
let mut next = || {
state = state.wrapping_add(0x9E3779B97F4A7C15);
let mut z = state;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58476D1CE4E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D049BB133111EB);
z ^ (z >> 31)
};
Self {
s: [next(), next(), next(), next()],
}
}
pub(crate) fn next_u64(&mut self) -> u64 {
let result = self.s[0]
.wrapping_add(self.s[3])
.rotate_left(23)
.wrapping_add(self.s[0]);
let t = self.s[1] << 17;
self.s[2] ^= self.s[0];
self.s[3] ^= self.s[1];
self.s[1] ^= self.s[2];
self.s[0] ^= self.s[3];
self.s[2] ^= t;
self.s[3] = self.s[3].rotate_left(45);
result
}
pub(crate) fn next_f64(&mut self) -> f64 {
(self.next_u64() >> 11) as f64 * (1.0 / (1u64 << 53) as f64)
}
pub(crate) fn next_gaussian(&mut self) -> f64 {
let u1 = self.next_f64().max(f64::MIN_POSITIVE);
let u2 = self.next_f64();
(-2.0 * u1.ln()).sqrt() * (std::f64::consts::TAU * u2).cos()
}
}
pub(crate) fn mix(a: u64, b: u64) -> u64 {
let mut z = a
.wrapping_add(b.wrapping_mul(0x9E3779B97F4A7C15))
.wrapping_add(0x9E3779B97F4A7C15);
z = (z ^ (z >> 30)).wrapping_mul(0xBF58476D1CE4E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D049BB133111EB);
z ^ (z >> 31)
}