1use std::any::Any;
2
3use rand::Rng;
4
5pub trait PseudoRandomNumberGenerator {
8 fn initial_seed(&self) -> u64;
12
13 fn next(&mut self) -> u64;
15
16 fn as_any_mut(&mut self) -> &mut dyn Any;
18}
19
20pub struct RealPseudoRandomNumberGenerator {
21 initial_seed: u64,
22 seed: u64,
23}
24
25impl RealPseudoRandomNumberGenerator {
26 pub fn new(seed: Option<u64>) -> Self {
31 let seed = seed.unwrap_or_else(|| Self::generate_seed());
32 Self {
33 initial_seed: seed,
34 seed,
35 }
36 }
37
38 fn generate_seed() -> u64 {
39 let mut rng = rand::thread_rng();
40 rng.gen()
41 }
42
43 fn next_seed(seed: u64) -> u64 {
45 const A: u64 = 0x5D588B656C078965;
47 const C: u64 = 0x0000000000269EC3;
48 seed.wrapping_mul(A).overflowing_add(C).0
49 }
50}
51
52impl PseudoRandomNumberGenerator for RealPseudoRandomNumberGenerator {
53 fn initial_seed(&self) -> u64 {
54 self.initial_seed
55 }
56
57 fn next(&mut self) -> u64 {
58 self.seed = Self::next_seed(self.seed);
59 self.seed >> 32
61 }
62
63 fn as_any_mut(&mut self) -> &mut dyn Any {
64 self
65 }
66}
67
68#[cfg(test)]
69mod prng_tests {
70 use crate::rng::{
71 PseudoRandomNumberGenerator,
72 RealPseudoRandomNumberGenerator,
73 };
74
75 #[test]
76 fn stores_initial_seed() {
77 assert_eq!(
78 RealPseudoRandomNumberGenerator::new(Some(12345)).initial_seed(),
79 12345
80 );
81 assert_eq!(
82 RealPseudoRandomNumberGenerator::new(Some(6789100000)).initial_seed(),
83 6789100000
84 );
85 }
86}