maniac_runtime/utils/
random.rs

1use 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    // Return the current time as the number of nanoseconds since the Unix epoch as a u64
39    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