1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use lazy_static::lazy_static;
use std::num::Wrapping;
use std::sync::{Mutex, MutexGuard};
use std::time::{SystemTime, UNIX_EPOCH};
lazy_static! {
static ref RNG: Mutex<Rng> = Mutex::new(Rng::new(seed()));
}
pub fn get() -> MutexGuard<'static, Rng> {
RNG.lock().unwrap()
}
fn seed() -> u32 {
let start = SystemTime::now();
let since_epoch = start
.duration_since(UNIX_EPOCH)
.expect("time went backwards");
since_epoch.subsec_nanos()
}
pub struct Rng {
x: Wrapping<u32>,
y: Wrapping<u32>,
z: Wrapping<u32>,
w: Wrapping<u32>,
}
impl Rng {
fn new(seed: u32) -> Self {
Rng {
x: Wrapping(seed),
y: Wrapping(seed),
z: Wrapping(seed),
w: Wrapping(seed),
}
}
pub fn u32(&mut self) -> u32 {
let x = self.x;
let t = x ^ (x << 11);
self.x = self.y;
self.y = self.z;
self.z = self.w;
let w_ = self.w;
self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
self.w.0
}
}