/
xorshift.rs
87 lines (77 loc) · 1.7 KB
/
xorshift.rs
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
//! Xorshift random number generator
use std::{
fmt::{Debug, Display},
time::SystemTime,
};
#[derive(Clone, Default, Copy, Debug)]
pub struct XorShift<T>
where
T: std::fmt::Debug + Sized + Copy + Display + Shift,
{
seed: T,
}
impl<T> XorShift<T>
where
T: std::fmt::Debug + Sized + Copy + Display + Shift,
{
pub fn new() -> Self {
XorShift::from_seed(T::seed())
}
pub fn from_seed(seed: T) -> XorShift<T> {
XorShift { seed }
}
}
impl<T> Iterator for XorShift<T>
where
T: std::fmt::Debug + Sized + Copy + Display + Shift,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
T::shift(&mut self.seed);
Some(self.seed)
}
}
pub trait Shift {
fn seed() -> Self;
fn shift(n: &mut Self);
}
impl Shift for u64 {
fn seed() -> Self {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs()
}
fn shift(state: &mut u64) {
*state ^= *state << 13;
*state ^= *state >> 7;
*state ^= *state << 17;
}
}
impl Shift for u32 {
fn seed() -> Self {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as u32
}
fn shift(state: &mut u32) {
*state ^= *state << 13;
*state ^= *state >> 17;
*state ^= *state << 5;
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn test_xorshift() {
let mut set = HashSet::new();
let xorshift = XorShift::<u64>::new();
for v in xorshift.take(100_000) {
assert!(!set.contains(&v));
set.insert(v);
}
}
}