--- 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"
--- 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() {