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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#[macro_use]
extern crate lazy_static;
use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
pub struct Generator {
x: u64,
w: u64,
s: u64,
seed: u64,
}
impl Generator {
pub fn new(seed: u64) -> Generator {
Generator {
x: 0,
w: 0,
s: (seed << 1).wrapping_add(0xb5ad4eceda1ce2a9),
seed: seed,
}
}
pub fn u64(&mut self) -> u64 {
self.w = self.w.wrapping_add(self.s);
self.x = (self.x.wrapping_mul(self.x).wrapping_add(self.w) >> 32)
| (self.x.wrapping_mul(self.x).wrapping_add(self.w) << 32);
self.x
}
pub fn f64(&mut self) -> f64 {
self.u64() as f64 / ((0xFFFFFFFFFFFFFFFFu64 as f64) + 1.0)
}
pub fn fill(&mut self, bytes: &mut [u8]) {
let mut rval = self.u64();
let mut i = 0;
for b in bytes {
*b = (rval & 0xff) as u8;
rval >>= 8;
i += 1;
if i & 7 == 0 {
rval = self.u64();
}
}
}
}
lazy_static! {
static ref RAND: Mutex<Generator> = {
let seed = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
Mutex::new(Generator::new(seed))
};
}
pub fn last_seed() -> u64 {
RAND.lock().unwrap().seed
}
pub fn seed(seed: u64) {
let mut rc = RAND.lock().unwrap();
*rc = Generator::new(seed);
}
pub fn u64() -> u64 {
RAND.lock().unwrap().u64()
}
pub fn f64() -> f64 {
RAND.lock().unwrap().f64()
}
pub fn fill(bytes: &mut [u8]) {
RAND.lock().unwrap().fill(bytes)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn various() {
assert!(last_seed() != 0);
assert!(u64() != 0);
let mut bytes = vec![0; 64];
fill(&mut bytes);
let mut ok = false;
for b in &bytes {
if *b != 0 {
ok = true;
break;
}
}
assert!(ok);
}
}