1use std::ops::Range;
2use std::time::SystemTime;
3
4use std::sync::atomic::{AtomicU32, Ordering};
5use std::sync::Once;
6
7#[derive(Clone)]
8pub struct LCG {
9 a: u32,
10 c: u32,
11 m_mask: u32,
12 seed: u32,
13 state: u32,
14}
15
16impl LCG {
17 fn from_state(state: u32) -> Self {
18 let a: u32 = 1664525;
19 let c: u32 = 1013904223;
20 let m: u32 = 2u32 << 30;
21 Self {
22 a,
23 c,
24 m_mask: m - 1,
25 seed: state,
26 state,
27 }
28 }
29
30 fn cal_state(seeds: &[u8]) -> u32 {
31 seeds.iter().fold(0u32, |acc, &byte| {
32 acc.wrapping_mul(31).wrapping_add(byte as u32)
33 })
34 }
35
36 pub fn from_seed(seed: &[u8]) -> Self {
37 Self::from_state(Self::cal_state(seed))
38 }
39
40 pub fn reset(&mut self) {
41 self.state = self.seed;
42 }
43
44 pub fn generate(&mut self) -> u32 {
45 self.state = (self.a.wrapping_mul(self.state).wrapping_add(self.c)) & self.m_mask;
46 self.state
47 }
48
49 pub fn generate_u8(&mut self) -> u8 {
50 (self.generate() % 256) as u8
51 }
52
53 pub fn rand_range(&mut self, range: Range<usize>) -> usize {
54 let Range { start, end } = range;
55 (self.generate() as usize) % (end - start) + start
56 }
57
58 pub fn generate_random_string(&mut self, len: usize) -> String {
59 const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
60
61 (0..len)
62 .map(|_| CHARSET[self.rand_range(0..CHARSET.len())] as char)
63 .collect::<String>()
64 }
65}
66
67pub fn system_random() -> u32 {
68 let now = SystemTime::now()
70 .duration_since(std::time::UNIX_EPOCH)
71 .map(|d| d.as_nanos() % u32::MAX as u128)
72 .unwrap_or(0) as u32;
73
74 let mut rnd = LCG::from_state(now);
75 rnd.generate()
76}
77
78static INIT: Once = Once::new();
79static STATE: AtomicU32 = AtomicU32::new(0);
80
81pub fn simple_random() -> u32 {
82 INIT.call_once(|| {
83 let x = 42u32;
84 let state = &x as *const u32 as u32;
85 STATE.store(state, Ordering::Relaxed);
86 });
87
88 let current_seed = STATE.load(Ordering::Relaxed);
89 let mut lcg = LCG::from_state(current_seed);
90
91 let new_state = lcg.generate();
92
93 STATE.store(new_state, Ordering::Relaxed);
94
95 new_state
96}