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

8 months ago
  1. use std::num::Wrapping;
  2. // An unremarkable odd number
  3. const ODD: Wrapping<u64> = Wrapping(0x9f32e1cbc5e1374b);
  4. pub(crate) struct MSQW {
  5. reservoir: u64,
  6. level: u8,
  7. accumulator: Wrapping<u64>,
  8. state: Wrapping<u64>,
  9. }
  10. impl MSQW {
  11. pub fn new() -> Self {
  12. Self { accumulator: Wrapping(0), state: Wrapping(0), reservoir: 0, level: 0 }
  13. }
  14. pub fn update(&mut self) -> u32 {
  15. self.accumulator += ODD;
  16. self.state += self.accumulator;
  17. self.state = self.state * self.state;
  18. self.state = Wrapping(self.state.0.rotate_left(32));
  19. return self.state.0 as u32;
  20. }
  21. pub fn update_xor(&mut self) -> u32 {
  22. self.accumulator += ODD;
  23. self.state ^= self.accumulator;
  24. self.state = self.state * self.state;
  25. self.state = Wrapping(self.state.0.rotate_left(32));
  26. return self.state.0 as u32;
  27. }
  28. pub fn mix(&mut self, randomness: u64) {
  29. self.state ^= Wrapping(randomness);
  30. self.update_xor();
  31. }
  32. pub fn add(&mut self, bit: bool) {
  33. self.level += 1;
  34. self.reservoir <<= 1;
  35. if bit {
  36. self.reservoir |= 1;
  37. }
  38. if self.level == 64 {
  39. self.mix(self.reservoir);
  40. self.level = 0;
  41. }
  42. }
  43. }