rust/lfprng/src/lib.rs
branchtransitional_engine
changeset 15902 9b73594ac986
parent 15115 de32299de704
equal deleted inserted replaced
15901:f39f0f614dbf 15902:9b73594ac986
       
     1 use rand::{Error, RngCore, SeedableRng};
       
     2 
     1 pub struct LaggedFibonacciPRNG {
     3 pub struct LaggedFibonacciPRNG {
     2     circular_buffer: [u32; 64],
     4     circular_buffer: [u32; 64],
     3     index: usize,
     5     index: usize,
     4 }
     6 }
     5 
     7 
     6 impl LaggedFibonacciPRNG {
     8 impl LaggedFibonacciPRNG {
     7     pub fn new(init_values: &[u8]) -> Self {
     9     pub fn new(init_values: &[u8]) -> Self {
     8         let mut buf = [0xa98765 + 68; 64];
    10         let mut buf = [0xa98765; 64];
     9 
    11 
    10         for i in 0..std::cmp::min(init_values.len(), 54) {
    12         for i in 0..std::cmp::min(init_values.len(), 54) {
    11             buf[i] = init_values[i] as u32;
    13             buf[i] = init_values[i] as u32;
    12         }
    14         }
    13 
    15 
    28         }
    30         }
    29     }
    31     }
    30 
    32 
    31     #[inline]
    33     #[inline]
    32     fn get_next(&mut self) -> u32 {
    34     fn get_next(&mut self) -> u32 {
       
    35         const PRIME_NUM: u32 = 2147483629;
       
    36 
    33         self.index = (self.index + 1) & 0x3f;
    37         self.index = (self.index + 1) & 0x3f;
    34         self.circular_buffer[self.index] = (self.circular_buffer[(self.index + 40) & 0x3f]
    38         let next_value = self.circular_buffer[(self.index + 40) & 0x3f]
    35             + self.circular_buffer[(self.index + 9) & 0x3f])
    39             + self.circular_buffer[(self.index + 9) & 0x3f];
    36             & 0x7fffffff;
    40 
       
    41         self.circular_buffer[self.index] = if next_value > PRIME_NUM {
       
    42             next_value - PRIME_NUM
       
    43         } else {
       
    44             next_value
       
    45         };
    37 
    46 
    38         self.circular_buffer[self.index]
    47         self.circular_buffer[self.index]
    39     }
    48     }
    40 
    49 
    41     #[inline]
    50     #[inline]
    58         self.get_next();
    67         self.get_next();
    59         Some(self.get_next())
    68         Some(self.get_next())
    60     }
    69     }
    61 }
    70 }
    62 
    71 
       
    72 impl RngCore for LaggedFibonacciPRNG {
       
    73     fn next_u32(&mut self) -> u32 {
       
    74         self.get_next().wrapping_add(self.get_next())
       
    75     }
       
    76 
       
    77     fn next_u64(&mut self) -> u64 {
       
    78         ((self.next_u32() as u64) << 32) | self.next_u32() as u64
       
    79     }
       
    80 
       
    81     fn fill_bytes(&mut self, dest: &mut [u8]) {
       
    82         dest.iter_mut().for_each(|x| *x = self.next_u32() as u8);
       
    83     }
       
    84 
       
    85     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
       
    86         Ok(self.fill_bytes(dest))
       
    87     }
       
    88 }
       
    89 
       
    90 impl SeedableRng for LaggedFibonacciPRNG {
       
    91     type Seed = [u8; 32];
       
    92 
       
    93     fn from_seed(seed: Self::Seed) -> Self {
       
    94         LaggedFibonacciPRNG::new(&seed)
       
    95     }
       
    96 }
       
    97 
    63 #[cfg(test)]
    98 #[cfg(test)]
    64 #[test]
    99 #[test]
    65 fn compatibility() {
   100 fn compatibility() {
    66     let mut prng = LaggedFibonacciPRNG::new("{052e2aee-ce41-4720-97bd-559a413bf866}".as_bytes());
   101     let mut prng = LaggedFibonacciPRNG::new("{052e2aee-ce41-4720-97bd-559a413bf866}".as_bytes());
    67 
   102