1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#![no_std]
#[cfg(feature = "std")]
#[macro_use]
extern crate std;
#[cfg(feature = "std")]
mod thread;
pub extern crate random_trait;
pub use random_trait::Random;
#[cfg(feature = "std")]
use thread::FromRawPtr;
#[cfg(feature = "std")]
pub use thread::ThreadFastRng;
use core::mem;
#[cfg(feature = "doc-comment")]
extern crate doc_comment;
#[cfg(feature = "doc-comment")]
doc_comment::doctest!("../README.md");
const PCG_DEFAULT_MULTIPLIER_64: u64 = 6_364_136_223_846_793_005;
pub struct FastRng {
state: u64,
inc: u64,
}
impl FastRng {
#[cfg(feature = "std")]
pub fn new() -> Self {
let (a, b) = time_seed();
Self::seed(a, b)
}
#[cfg(feature = "std")]
pub fn thread_local() -> ThreadFastRng {
use std::cell::RefCell;
thread_local! {
pub static THREAD_FAST_RNG: RefCell<FastRng> = RefCell::new(FastRng::new());
}
let ptr = THREAD_FAST_RNG.with(|r| r.as_ptr());
ThreadFastRng::from_ptr(ptr)
}
pub fn seed(seed: u64, seq: u64) -> Self {
let init_inc = (seq << 1) | 1;
let init_state = seed + init_inc;
let mut rng = FastRng { state: init_state, inc: init_inc };
rng.state = rng.state.wrapping_mul(PCG_DEFAULT_MULTIPLIER_64).wrapping_add(rng.inc);
rng
}
fn gen_u32(&mut self) -> u32 {
let old_state = self.state;
self.state = self.state.wrapping_mul(PCG_DEFAULT_MULTIPLIER_64).wrapping_add(self.inc);
let xorshift = (((old_state >> 18) ^ old_state) >> 27) as u32;
let rot = (old_state >> 59) as i32;
(xorshift >> rot) | (xorshift << ((-rot) & 31))
}
}
#[cfg(feature = "std")]
fn time_seed() -> (u64, u64) {
use std::time;
let now = time::SystemTime::now();
let unix = now.duration_since(time::UNIX_EPOCH).unwrap();
(unix.as_secs(), u64::from(unix.subsec_nanos()))
}
impl Random for FastRng {
type Error = ();
fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
for chunk in buf.chunks_mut(4) {
let rand: [u8; 4] = unsafe { mem::transmute(self.gen_u32()) };
let len = chunk.len();
chunk.copy_from_slice(&rand[..len]);
}
Ok(())
}
fn get_u32(&mut self) -> u32 {
self.gen_u32()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_local() {
let mut local_rng = FastRng::thread_local();
let a: u64 = local_rng.gen();
let b: u32 = local_rng.gen();
let c: [u8; 64] = local_rng.gen();
assert_ne!(a, 0);
assert_ne!(b, 0);
assert_ne!(&c[..], &[0u8; 64][..]);
}
#[test]
fn test_float() {
let mut rng = FastRng::new();
let f: f32 = rng.gen();
assert!(f > 0.0 && f < 1.0);
let f: f64 = rng.gen();
assert!(f > 0.0 && f < 1.0);
}
}