| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- /* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- use rand::{CryptoRng, Error, RngCore};
- pub struct Pcg32 {
- state: u64,
- increment: u64,
- }
- impl Pcg32 {
- const MULTIPLIER: u64 = 6364136223846793005;
- const INCREMENT: u64 = 1442695040888963407;
- pub fn new(seed: u64) -> Self {
- let mut rng = Self { state: 0, increment: Self::INCREMENT | 1 };
- rng.state = rng.state.wrapping_add(seed);
- rng.state = rng.state.wrapping_mul(Self::MULTIPLIER).wrapping_add(rng.increment);
- rng
- }
- fn next_u32(&mut self) -> u32 {
- let old_state = self.state;
- self.state = old_state.wrapping_mul(Self::MULTIPLIER).wrapping_add(self.increment);
- let xorshifted = ((old_state >> 18) ^ old_state) >> 27;
- let rot = old_state >> 59;
- (xorshifted >> rot | xorshifted << ((!rot).wrapping_add(1) & 31)) as u32
- }
- }
- impl CryptoRng for Pcg32 {}
- impl RngCore for Pcg32 {
- fn next_u32(&mut self) -> u32 {
- self.next_u32()
- }
- fn next_u64(&mut self) -> u64 {
- (self.next_u32() as u64) << 32 | (self.next_u32() as u64)
- }
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- let mut i = 0;
- while i + 4 <= dest.len() {
- let bytes = self.next_u32().to_le_bytes();
- dest[i..i + 4].copy_from_slice(&bytes);
- i += 4;
- }
- if i < dest.len() {
- let bytes = self.next_u32().to_le_bytes();
- for (j, dest_byte) in dest[i..].iter_mut().enumerate() {
- *dest_byte = bytes[j];
- }
- }
- }
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- self.fill_bytes(dest);
- Ok(())
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- #[test]
- fn test_pcg() {
- const ITERS: usize = 10000;
- let mut rng0 = Pcg32::new(42);
- let mut rng1 = Pcg32::new(42);
- for i in 0..ITERS {
- let a = rng0.next_u32();
- let b = rng1.next_u32();
- assert!(a == b);
- let a = rng0.next_u64();
- let b = rng1.next_u64();
- assert!(a == b);
- let mut buf0 = vec![0u8; i];
- let mut buf1 = vec![0u8; i];
- rng0.fill_bytes(&mut buf0);
- rng1.fill_bytes(&mut buf1);
- assert!(buf0 == buf1);
- }
- }
- }
|