rust/lfprng/src/lib.rs
branchhedgeroid
changeset 15510 7030706266df
parent 15115 de32299de704
child 15902 9b73594ac986
equal deleted inserted replaced
7861:bc7b6aa5d67a 15510:7030706266df
       
     1 pub struct LaggedFibonacciPRNG {
       
     2     circular_buffer: [u32; 64],
       
     3     index: usize,
       
     4 }
       
     5 
       
     6 impl LaggedFibonacciPRNG {
       
     7     pub fn new(init_values: &[u8]) -> Self {
       
     8         let mut buf = [0xa98765 + 68; 64];
       
     9 
       
    10         for i in 0..std::cmp::min(init_values.len(), 54) {
       
    11             buf[i] = init_values[i] as u32;
       
    12         }
       
    13 
       
    14         let mut prng = Self {
       
    15             circular_buffer: buf,
       
    16             index: 54,
       
    17         };
       
    18 
       
    19         prng.discard(2048);
       
    20 
       
    21         prng
       
    22     }
       
    23 
       
    24     #[inline]
       
    25     pub fn discard(&mut self, count: usize) {
       
    26         for _i in 0..count {
       
    27             self.get_next();
       
    28         }
       
    29     }
       
    30 
       
    31     #[inline]
       
    32     fn get_next(&mut self) -> u32 {
       
    33         self.index = (self.index + 1) & 0x3f;
       
    34         self.circular_buffer[self.index] = (self.circular_buffer[(self.index + 40) & 0x3f]
       
    35             + self.circular_buffer[(self.index + 9) & 0x3f])
       
    36             & 0x7fffffff;
       
    37 
       
    38         self.circular_buffer[self.index]
       
    39     }
       
    40 
       
    41     #[inline]
       
    42     pub fn get_random(&mut self, modulo: u32) -> u32 {
       
    43         self.get_next();
       
    44         self.get_next() % modulo
       
    45     }
       
    46 
       
    47     #[inline]
       
    48     pub fn add_randomness(&mut self, value: u32) {
       
    49         self.index = (self.index + 1) & 0x3f;
       
    50         self.circular_buffer[self.index] ^= value;
       
    51     }
       
    52 }
       
    53 
       
    54 impl Iterator for LaggedFibonacciPRNG {
       
    55     type Item = u32;
       
    56 
       
    57     fn next(&mut self) -> Option<Self::Item> {
       
    58         self.get_next();
       
    59         Some(self.get_next())
       
    60     }
       
    61 }
       
    62 
       
    63 #[cfg(test)]
       
    64 #[test]
       
    65 fn compatibility() {
       
    66     let mut prng = LaggedFibonacciPRNG::new("{052e2aee-ce41-4720-97bd-559a413bf866}".as_bytes());
       
    67 
       
    68     assert_eq!(prng.get_random(1000), 418);
       
    69     assert_eq!(prng.get_random(1000000), 554064);
       
    70     assert_eq!(prng.get_random(0xffffffff), 239515837);
       
    71 
       
    72     prng.add_randomness(123);
       
    73 
       
    74     for i in 0..=100000 {
       
    75         prng.get_random(2);
       
    76     }
       
    77 
       
    78     assert_eq!(prng.get_random(0xffffffff), 525333582);
       
    79 }