iceyee_random/
lib.rs

1// **************************************************
2// *  Author: Iceyee                                *
3// *  Mail: iceyee.studio@qq.com                    *
4// *  Git: https://github.com/iceyee                *
5// **************************************************
6//
7// Use.
8
9use std::cell::Cell;
10use std::time::SystemTime;
11
12thread_local! {
13    static SEED: Cell<u64> = Cell::new(0);
14    static THREAD_ID: Cell<u64> = Cell::new(0);
15}
16
17// Enum.
18
19// Trait.
20
21// Struct.
22
23/// 随机数.
24///
25/// 种子是线程变量.
26pub struct Random;
27
28impl Random {
29    /// 设置种子, 种子是线程变量.
30    pub fn set_seed(s: u64) {
31        SEED.with(|seed| seed.set(s));
32        return;
33    }
34
35    /// 下一个随机数.
36    pub fn next() -> u64 {
37        let mut seed: u64 = SEED.with(|seed| {
38            if seed.get() == 0 {
39                let id: u64 = get_thread_id();
40                let time: u64 = SystemTime::now()
41                    .duration_since(std::time::UNIX_EPOCH)
42                    .unwrap()
43                    .as_millis() as u64;
44                seed.set(id ^ time);
45            }
46            seed.get()
47        });
48        let thread_id: u64 = THREAD_ID.with(|id| {
49            if id.get() == 0 {
50                id.set(get_thread_id() & 0xFFFFFFFF)
51            }
52            id.get()
53        });
54        const TABLE: [u64; 32] = [
55            0x59763CEA1457DFC5,
56            0x0E701C6631DCCC01,
57            0x67793534A8C778D7,
58            0x64770DE4EB0B80CE,
59            0x747A9AF32BB93809,
60            0xC71D4F13A1E22A09,
61            0xE74813B3E6C1ECAB,
62            0x3B88A9B5A97C3862,
63            0x24057CC3128D9579,
64            0xD41D3C71A9426A59,
65            0xE5E61B92D1F676F4,
66            0xA01EC8F62398DE1C,
67            0x3025BB78C7E3DD78,
68            0xD869150399B67D2A,
69            0xD4F8F70CEEFBB738,
70            0xF910F138AFE1C1C9,
71            0xE63F12FA3125DB84,
72            0x84DC6ADA95196F95,
73            0x6C47E3124371EF67,
74            0x3339D137640D3929,
75            0x6604916E4DF3C5AF,
76            0x8D86EBD5FD2374CD,
77            0xAD13E8135162601F,
78            0xDA5C5215F3867431,
79            0x1540D632794D96C6,
80            0x012533A3629D7DE8,
81            0x238F9B1046DDCA4C,
82            0xB61FAC20EBE58CEA,
83            0xF6982B86164D089B,
84            0xEAA86C9587A038B3,
85            0xF4B1F470ABDA3652,
86            0x10A7C3C4A75EF01E,
87        ];
88        const N: usize = 2;
89        for x in 0..N {
90            seed = (seed << 63) | (seed >> 1);
91            seed ^= TABLE[x];
92            seed = ((seed as u128) + (TABLE[x + N] as u128)) as u64;
93        }
94        seed += thread_id;
95        SEED.with(|s| s.set(seed));
96        return seed;
97    }
98
99    /// 下一个小于max的随机数, 相当于next() % max.
100    pub fn next_less_than(max: u64) -> u64 {
101        return Self::next() % max;
102    }
103}
104
105// Function.
106
107// 取线程id.
108fn get_thread_id() -> u64 {
109    #[cfg(target_os = "linux")]
110    {
111        // type pthread_t = long unsigned int.
112        // pthread_t pthread_self(void);
113        use std::ffi::c_ulong;
114        unsafe extern "C" {
115            fn pthread_self() -> c_ulong;
116        }
117        return unsafe { pthread_self() } as u64;
118    }
119    #[cfg(target_os = "windows")]
120    {
121        // DWORD GetCurrentThreadId();
122        unsafe extern "C" {
123            fn GetCurrentThreadId() -> u32;
124        }
125        return unsafe { GetCurrentThreadId() } as u64;
126    }
127}