rust/lfprng/src/lib.rs
changeset 13886 b6c35ac1c5ba
child 13904 3f0576157749
equal deleted inserted replaced
13885:cd39e87d7a80 13886:b6c35ac1c5ba
       
     1 pub struct LaggedFibonacciPRNG {
       
     2     circular_buffer: [u32; 64],
       
     3     index: usize,
       
     4 }
       
     5 
       
     6 impl LaggedFibonacciPRNG {
       
     7     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         for i in 0..2048 {
       
    20             prng.get_next();
       
    21         }
       
    22 
       
    23         prng
       
    24     }
       
    25 
       
    26     #[inline]
       
    27     fn get_next(&mut self) -> u32 {
       
    28         self.index = (self.index + 1) & 0x3f;
       
    29         self.circular_buffer[self.index] = (self.circular_buffer[(self.index + 40) & 0x3f]
       
    30             + self.circular_buffer[(self.index + 9) & 0x3f])
       
    31             & 0x7fffffff;
       
    32 
       
    33         self.circular_buffer[self.index]
       
    34     }
       
    35 
       
    36     #[inline]
       
    37     fn get_random(&mut self, modulo: u32) -> u32 {
       
    38         self.get_next();
       
    39         self.get_next() % modulo
       
    40     }
       
    41 
       
    42     #[inline]
       
    43     fn add_randomness(&mut self, value: u32) {
       
    44         self.index = (self.index + 1) & 0x3f;
       
    45         self.circular_buffer[self.index] ^= value;
       
    46     }
       
    47 }
       
    48 
       
    49 #[cfg(test)]
       
    50 #[test]
       
    51 fn compatibility() {
       
    52     let mut prng = LaggedFibonacciPRNG::new("{052e2aee-ce41-4720-97bd-559a413bf866}".as_bytes());
       
    53 
       
    54     assert_eq!(prng.get_random(1000), 418);
       
    55     assert_eq!(prng.get_random(1000000), 554064);
       
    56     assert_eq!(prng.get_random(0xffffffff), 239515837);
       
    57 
       
    58     prng.add_randomness(123);
       
    59 
       
    60     for i in 0..=100000 {
       
    61         prng.get_random(2);
       
    62     }
       
    63 
       
    64     assert_eq!(prng.get_random(0xffffffff), 525333582);
       
    65 }