2024-04-06 18:56:09 +02:00
|
|
|
/// A trait to represent RNG for u64 values.
|
|
|
|
pub trait RandGen {
|
|
|
|
fn gen(&mut self) -> u64;
|
|
|
|
}
|
|
|
|
|
2024-04-06 20:30:53 +02:00
|
|
|
// A simple pcg64_fast RNG implementation, for code-generation.
|
2024-04-06 18:56:09 +02:00
|
|
|
#[cfg(test)]
|
2024-04-06 20:30:53 +02:00
|
|
|
pub struct SimpleRng(u128);
|
2024-04-06 18:56:09 +02:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
impl SimpleRng {
|
|
|
|
pub fn new() -> Self {
|
2024-04-06 20:30:53 +02:00
|
|
|
Self(0xcafef00dd15ea5e5 | 1) // https://xkcd.com/221/
|
2024-04-06 18:56:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn gen(&mut self) -> u64 {
|
2024-04-06 20:30:53 +02:00
|
|
|
const MULTIPLIER: u128 = 0x2360_ED05_1FC6_5DA4_4385_DF64_9FCC_F645;
|
|
|
|
const XSHIFT: u32 = 64; // (128 - 64 + 64) / 2
|
|
|
|
const ROTATE: u32 = 122; // 128 - 6
|
|
|
|
|
|
|
|
self.0 = self.0.wrapping_mul(MULTIPLIER);
|
|
|
|
let rot = (self.0 >> ROTATE) as u32;
|
|
|
|
let xsl = (self.0 >> XSHIFT) as u64 ^ (self.0 as u64);
|
|
|
|
xsl.rotate_right(rot)
|
2024-04-06 18:56:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
impl RandGen for SimpleRng {
|
|
|
|
fn gen(&mut self) -> u64 {
|
|
|
|
self.gen()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn rng() {
|
|
|
|
let mut rng = SimpleRng::new();
|
|
|
|
|
2024-04-06 20:30:53 +02:00
|
|
|
assert_eq!(rng.gen(), 64934999470316615);
|
|
|
|
assert_eq!(rng.gen(), 15459456780870779090);
|
|
|
|
assert_eq!(rng.gen(), 13715484424881807779);
|
|
|
|
assert_eq!(rng.gen(), 17718572936700675021);
|
|
|
|
assert_eq!(rng.gen(), 14587996314750246637);
|
2024-04-06 18:56:09 +02:00
|
|
|
}
|
|
|
|
}
|