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 }