lcg_rand/
lib.rs

1pub mod rand {
2    //! This is NOT secure for any cryptographic uses, and is not designed to be.
3    //!
4    //! This module is an implementation of the Linear Congruential Generator algorithm.
5    //!
6    //! See the [Wikipedia page](https://en.wikipedia.org/wiki/Linear_congruential_generator) for more
7    //! information.
8    use std::time::SystemTime;
9
10    const MODULUS: u128 = 2u128.pow(64);
11    const INCREMENT: u64 = 1442695040888963407;
12    const MULTIPLIER: u64 = 6364136223846793005;
13
14    pub struct LCG {
15        pub seed: u64,
16        value: u64,
17        modulus: u128,
18        increment: u64,
19        multiplier: u64,
20    }
21
22    impl LCG {
23        pub fn new() -> LCG {
24            //! Generates new LCG object using default parameters, and seconds since unix epoch as seed.
25            //!
26            //! **Warning**: will panic if system time is before Jan 1st, 1970 midnight.
27            let s = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs();
28
29            LCG {
30                seed: s,
31                value: s,
32                modulus: MODULUS,
33                increment: INCREMENT,
34                multiplier: MULTIPLIER,
35            }
36        }
37
38        pub fn from_seed(seed: u64) -> LCG {
39            //! Generate a new LCG object using the given seed, and default mod, inc, and mul.
40            LCG {
41                seed,
42                value: seed,
43                modulus: MODULUS,
44                increment: INCREMENT,
45                multiplier: MULTIPLIER,
46            }
47        }
48
49        pub fn from_parameters(seed: u64, modulus: u128, increment: u64, multiplier: u64) -> LCG {
50            //! Generate an LCG object with all parameters overridden.
51            LCG {
52                seed,
53                value: seed,
54                modulus,
55                increment,
56                multiplier
57            }
58        }
59
60        pub fn next(&mut self) -> u64 {
61            //! Generate the next value and return it.
62            self.value = (
63                ((self.multiplier as u128) * (self.value as u128) + self.increment as u128) % self.modulus
64            ) as u64;
65
66            self.value
67        }
68
69        pub fn range(&mut self, start: u64, end: u64) -> u64 {
70            //! Restrain the value of [next()](crate::rand::LCG::next) to given values.
71            //!
72            //! This is inclusive, so both the `start` and `end` parameters could be the result.
73            let _ = self.next();
74
75            (self.value % (end - start + 1)) + start
76        }
77
78        pub fn choose<'a, T>(&'a mut self, v: &'a [T]) -> &T {
79            //! Take a slice and return a random item in it.
80            //!
81            //! **Warning**: Will panic if given empty slice.
82            return &v[
83                self.range(0, (v.len()-1) as u64) as usize
84            ];
85        }
86    }
87}