maniac_runtime/utils/
random.rs1use std::cell::UnsafeCell;
2
3use rand::{RngCore, rng};
4
5const RND_MULTIPLIER: u64 = 0x5DEECE66D;
6const RND_ADDEND: u64 = 0xB;
7const RND_MASK: u64 = (1 << 48) - 1;
8
9pub struct Random {
10 seed: u64,
11}
12
13impl Random {
14 pub fn new() -> Self {
15 Self { seed: rng().next_u64() }
16 }
17
18 pub fn new_with_seed(seed: u64) -> Self {
19 Self { seed }
20 }
21
22 pub fn seed(&self) -> u64 {
23 self.seed
24 }
25
26 pub fn next(&mut self) -> u64 {
27 let old_seed = self.seed;
28 let next_seed = (old_seed
29 .wrapping_mul(RND_MULTIPLIER)
30 .wrapping_add(RND_ADDEND))
31 & RND_MASK;
32 self.seed = next_seed;
33 next_seed >> 16
34 }
35}
36
37fn now_nanos() -> u64 {
38 use std::time::{SystemTime, UNIX_EPOCH};
40 let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards");
41 now.as_nanos() as u64
42}
43
44
45thread_local! {
46 static THREAD_RND: UnsafeCell<Random> = UnsafeCell::new(Random { seed: now_nanos() });
47}
48
49pub fn random_u64() -> u64 {
50 THREAD_RND.with(|r| unsafe { &mut *r.get() }.next())
51}
52
53pub fn random_usize() -> usize {
54 THREAD_RND.with(|r| unsafe { &mut *r.get() }.next()) as usize
55}
56
57
58