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}