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
#![feature(stdsimd)]
extern crate rand;
mod sfmt;
mod thread_rng;
use rand::Rng;
use std::simd::*;
pub use thread_rng::{thread_rng, ThreadRng};
#[derive(Clone)]
pub struct SFMT {
state: [i32x4; sfmt::SFMT_N],
idx: usize,
}
impl SFMT {
pub fn new(seed: u32) -> Self {
let mut sfmt = SFMT {
state: [i32x4::new(0, 0, 0, 0); sfmt::SFMT_N],
idx: 0,
};
sfmt::sfmt_init_gen_rand(&mut sfmt, seed);
sfmt
}
fn pop32(&mut self) -> u32 {
let val = self.state[self.idx / 4].extract(self.idx % 4) as u32;
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 Rng 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()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn random() {
let mut rng = SFMT::new(1234);
for _ in 0..sfmt::SFMT_N * 20 {
let r = rng.gen::<u64>();
if r % 2 == 0 {
let _r = rng.gen::<u32>();
}
}
}
}