# HG changeset patch # User unC0Rr # Date 1672825032 -3600 # Node ID 9b73594ac98626c00123bce23230a5872c46e4d4 # Parent f39f0f614dbf937ae20923692a0018f5236ba1bc Update lfprng for better distribution, make it conform 'rand' package traits diff -r f39f0f614dbf -r 9b73594ac986 rust/lfprng/Cargo.toml --- a/rust/lfprng/Cargo.toml Tue Jan 03 12:05:59 2023 +0100 +++ b/rust/lfprng/Cargo.toml Wed Jan 04 10:37:12 2023 +0100 @@ -5,3 +5,4 @@ edition = "2018" [dependencies] +rand = "0.8" diff -r f39f0f614dbf -r 9b73594ac986 rust/lfprng/src/lib.rs --- a/rust/lfprng/src/lib.rs Tue Jan 03 12:05:59 2023 +0100 +++ b/rust/lfprng/src/lib.rs Wed Jan 04 10:37:12 2023 +0100 @@ -1,3 +1,5 @@ +use rand::{Error, RngCore, SeedableRng}; + pub struct LaggedFibonacciPRNG { circular_buffer: [u32; 64], index: usize, @@ -5,7 +7,7 @@ impl LaggedFibonacciPRNG { pub fn new(init_values: &[u8]) -> Self { - let mut buf = [0xa98765 + 68; 64]; + let mut buf = [0xa98765; 64]; for i in 0..std::cmp::min(init_values.len(), 54) { buf[i] = init_values[i] as u32; @@ -30,10 +32,17 @@ #[inline] fn get_next(&mut self) -> u32 { + const PRIME_NUM: u32 = 2147483629; + self.index = (self.index + 1) & 0x3f; - self.circular_buffer[self.index] = (self.circular_buffer[(self.index + 40) & 0x3f] - + self.circular_buffer[(self.index + 9) & 0x3f]) - & 0x7fffffff; + let next_value = self.circular_buffer[(self.index + 40) & 0x3f] + + self.circular_buffer[(self.index + 9) & 0x3f]; + + self.circular_buffer[self.index] = if next_value > PRIME_NUM { + next_value - PRIME_NUM + } else { + next_value + }; self.circular_buffer[self.index] } @@ -60,6 +69,32 @@ } } +impl RngCore for LaggedFibonacciPRNG { + fn next_u32(&mut self) -> u32 { + self.get_next().wrapping_add(self.get_next()) + } + + 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]) { + dest.iter_mut().for_each(|x| *x = self.next_u32() as u8); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + Ok(self.fill_bytes(dest)) + } +} + +impl SeedableRng for LaggedFibonacciPRNG { + type Seed = [u8; 32]; + + fn from_seed(seed: Self::Seed) -> Self { + LaggedFibonacciPRNG::new(&seed) + } +} + #[cfg(test)] #[test] fn compatibility() {