You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
54 lines
1.3 KiB
54 lines
1.3 KiB
use std::num::Wrapping;
|
|
|
|
// An unremarkable odd number
|
|
const ODD: Wrapping<u64> = Wrapping(0x9f32e1cbc5e1374b);
|
|
|
|
pub(crate) struct MSQW {
|
|
reservoir: u64,
|
|
level: u8,
|
|
accumulator: Wrapping<u64>,
|
|
state: Wrapping<u64>,
|
|
}
|
|
|
|
impl MSQW {
|
|
pub fn new() -> Self {
|
|
Self { accumulator: Wrapping(0), state: Wrapping(0), reservoir: 0, level: 0 }
|
|
}
|
|
|
|
pub fn update(&mut self) -> u32 {
|
|
self.accumulator += ODD;
|
|
self.state += self.accumulator;
|
|
self.state = self.state * self.state;
|
|
self.state = Wrapping(self.state.0.rotate_left(32));
|
|
|
|
return self.state.0 as u32;
|
|
}
|
|
|
|
pub fn update_xor(&mut self) -> u32 {
|
|
self.accumulator += ODD;
|
|
self.state ^= self.accumulator;
|
|
self.state = self.state * self.state;
|
|
self.state = Wrapping(self.state.0.rotate_left(32));
|
|
|
|
return self.state.0 as u32;
|
|
}
|
|
|
|
pub fn mix(&mut self, randomness: u64) {
|
|
self.state ^= Wrapping(randomness);
|
|
self.update_xor();
|
|
}
|
|
|
|
pub fn add(&mut self, bit: bool) {
|
|
self.level += 1;
|
|
|
|
self.reservoir <<= 1;
|
|
if bit {
|
|
self.reservoir |= 1;
|
|
}
|
|
|
|
if self.level == 64 {
|
|
self.mix(self.reservoir);
|
|
self.level = 0;
|
|
}
|
|
}
|
|
}
|