#[derive(Clone, Debug)]
pub struct Mulberry32 {
a: u32,
}
impl Mulberry32 {
#[inline]
pub fn new(seed: u32) -> Self {
Self { a: seed }
}
#[inline]
pub fn seeded(seed: u32) -> Self {
Self { a: if seed == 0 { 1 } else { seed } }
}
#[inline]
pub fn next_f64(&mut self) -> f64 {
self.a = self.a.wrapping_add(0x6d2b_79f5);
let mut t = (self.a ^ (self.a >> 15)).wrapping_mul(self.a | 1);
t = (t.wrapping_add((t ^ (t >> 7)).wrapping_mul(t | 61))) ^ t;
((t ^ (t >> 14)) as f64) / 4_294_967_296.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn first_draws_match_reference() {
let mut r = Mulberry32::seeded(1);
let expected = [
0.6270739405881613,
0.002735721180215478,
0.5274470399599522,
];
for &e in &expected {
let got = r.next_f64();
assert!((got - e).abs() < 1e-15, "got {got}, expected {e}");
}
}
#[test]
fn zero_seed_maps_to_one() {
let mut a = Mulberry32::seeded(0);
let mut b = Mulberry32::seeded(1);
assert_eq!(a.next_f64(), b.next_f64());
}
}