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
104
105
106
107
108
109
110
111
112
113
mod packed;
mod sfmt;
#[cfg(feature = "thread_rng")]
mod thread_rng;
use rand_core::{impls, Error, RngCore, SeedableRng};
use self::packed::*;
#[cfg(feature = "thread_rng")]
pub use self::thread_rng::{thread_rng, ThreadRng};
#[derive(Clone)]
pub struct SFMT {
state: [i32x4; sfmt::SFMT_N],
idx: usize,
}
impl SFMT {
fn pop32(&mut self) -> u32 {
let val = extract(self.state[self.idx / 4], self.idx % 4);
self.idx += 1;
val
}
fn pop64(&mut self) -> u64 {
let p = self.state.as_ptr() as *const u32;
let val = unsafe {
let p = p.offset(self.idx as isize);
*(p as *const u64)
};
self.idx += 2;
val
}
fn gen_all(&mut self) {
sfmt::sfmt_gen_rand_all(self);
self.idx = 0;
}
}
impl SeedableRng for SFMT {
type Seed = [u8; 4];
fn from_seed(seed: [u8; 4]) -> Self {
let mut sfmt = SFMT {
state: [zero(); sfmt::SFMT_N],
idx: 0,
};
let seed = unsafe { *(seed.as_ptr() as *const u32) };
sfmt::sfmt_init_gen_rand(&mut sfmt, seed);
sfmt
}
}
impl RngCore for SFMT {
fn next_u32(&mut self) -> u32 {
if self.idx >= sfmt::SFMT_N32 {
self.gen_all();
}
self.pop32()
}
fn next_u64(&mut self) -> u64 {
if self.idx >= sfmt::SFMT_N32 - 1 {
self.gen_all();
}
self.pop64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}
}
#[cfg(test)]
mod tests {
use super::*;
use rand_core::{RngCore, SeedableRng};
#[test]
fn random() {
let mut rng = SFMT::seed_from_u64(0);
for _ in 0..sfmt::SFMT_N * 20 {
let r = rng.next_u64();
if r % 2 == 0 {
let _r = rng.next_u32();
}
}
}
}