/ src / util / pcg.rs
pcg.rs
  1  /* This file is part of DarkFi (https://dark.fi)
  2   *
  3   * Copyright (C) 2020-2025 Dyne.org foundation
  4   *
  5   * This program is free software: you can redistribute it and/or modify
  6   * it under the terms of the GNU Affero General Public License as
  7   * published by the Free Software Foundation, either version 3 of the
  8   * License, or (at your option) any later version.
  9   *
 10   * This program is distributed in the hope that it will be useful,
 11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13   * GNU Affero General Public License for more details.
 14   *
 15   * You should have received a copy of the GNU Affero General Public License
 16   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17   */
 18  
 19  use rand::{CryptoRng, Error, RngCore};
 20  
 21  pub struct Pcg32 {
 22      state: u64,
 23      increment: u64,
 24  }
 25  
 26  impl Pcg32 {
 27      const MULTIPLIER: u64 = 6364136223846793005;
 28      const INCREMENT: u64 = 1442695040888963407;
 29  
 30      pub fn new(seed: u64) -> Self {
 31          let mut rng = Self { state: 0, increment: Self::INCREMENT | 1 };
 32          rng.state = rng.state.wrapping_add(seed);
 33          rng.state = rng.state.wrapping_mul(Self::MULTIPLIER).wrapping_add(rng.increment);
 34          rng
 35      }
 36  
 37      fn next_u32(&mut self) -> u32 {
 38          let old_state = self.state;
 39          self.state = old_state.wrapping_mul(Self::MULTIPLIER).wrapping_add(self.increment);
 40          let xorshifted = ((old_state >> 18) ^ old_state) >> 27;
 41          let rot = old_state >> 59;
 42          ((xorshifted >> rot) | (xorshifted << ((!rot).wrapping_add(1) & 31))) as u32
 43      }
 44  }
 45  
 46  impl CryptoRng for Pcg32 {}
 47  
 48  impl RngCore for Pcg32 {
 49      fn next_u32(&mut self) -> u32 {
 50          self.next_u32()
 51      }
 52  
 53      fn next_u64(&mut self) -> u64 {
 54          ((self.next_u32() as u64) << 32) | (self.next_u32() as u64)
 55      }
 56  
 57      fn fill_bytes(&mut self, dest: &mut [u8]) {
 58          let mut i = 0;
 59          while i + 4 <= dest.len() {
 60              let bytes = self.next_u32().to_le_bytes();
 61              dest[i..i + 4].copy_from_slice(&bytes);
 62              i += 4;
 63          }
 64          if i < dest.len() {
 65              let bytes = self.next_u32().to_le_bytes();
 66              for (j, dest_byte) in dest[i..].iter_mut().enumerate() {
 67                  *dest_byte = bytes[j];
 68              }
 69          }
 70      }
 71  
 72      fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
 73          self.fill_bytes(dest);
 74          Ok(())
 75      }
 76  }
 77  
 78  #[cfg(test)]
 79  mod tests {
 80      use super::*;
 81  
 82      #[test]
 83      fn test_pcg() {
 84          const ITERS: usize = 10000;
 85  
 86          let mut rng0 = Pcg32::new(42);
 87          let mut rng1 = Pcg32::new(42);
 88  
 89          for i in 0..ITERS {
 90              let a = rng0.next_u32();
 91              let b = rng1.next_u32();
 92              assert!(a == b);
 93  
 94              let a = rng0.next_u64();
 95              let b = rng1.next_u64();
 96              assert!(a == b);
 97  
 98              let mut buf0 = vec![0u8; i];
 99              let mut buf1 = vec![0u8; i];
100              rng0.fill_bytes(&mut buf0);
101              rng1.fill_bytes(&mut buf1);
102              assert!(buf0 == buf1);
103          }
104      }
105  }