competitive_library/other/
xorshift.rs1use std::{
3 fmt::{Debug, Display},
4 time::SystemTime,
5};
6
7#[derive(Clone, Default, Copy, Debug)]
8pub struct XorShift<T>
9where
10 T: std::fmt::Debug + Sized + Copy + Display + Shift,
11{
12 seed: T,
13}
14
15impl<T> XorShift<T>
16where
17 T: std::fmt::Debug + Sized + Copy + Display + Shift,
18{
19 pub fn new() -> Self {
20 XorShift::from_seed(T::seed())
21 }
22 pub fn from_seed(seed: T) -> XorShift<T> {
23 XorShift { seed }
24 }
25}
26
27impl<T> Iterator for XorShift<T>
28where
29 T: std::fmt::Debug + Sized + Copy + Display + Shift,
30{
31 type Item = T;
32
33 fn next(&mut self) -> Option<Self::Item> {
34 T::shift(&mut self.seed);
35 Some(self.seed)
36 }
37}
38
39pub trait Shift {
40 fn seed() -> Self;
41 fn shift(n: &mut Self);
42}
43
44impl Shift for u64 {
45 fn seed() -> Self {
46 SystemTime::now()
47 .duration_since(SystemTime::UNIX_EPOCH)
48 .unwrap()
49 .as_secs()
50 }
51
52 fn shift(state: &mut u64) {
53 *state ^= *state << 13;
54 *state ^= *state >> 7;
55 *state ^= *state << 17;
56 }
57}
58impl Shift for u32 {
59 fn seed() -> Self {
60 SystemTime::now()
61 .duration_since(SystemTime::UNIX_EPOCH)
62 .unwrap()
63 .as_secs() as u32
64 }
65
66 fn shift(state: &mut u32) {
67 *state ^= *state << 13;
68 *state ^= *state >> 17;
69 *state ^= *state << 5;
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use std::collections::HashSet;
77 #[test]
78 fn test_xorshift() {
79 let mut set = HashSet::new();
80 let xorshift = XorShift::<u64>::new();
81
82 for v in xorshift.take(100_000) {
83 assert!(!set.contains(&v));
84 set.insert(v);
85 }
86 }
87}