1#![no_std]
2#![deny(missing_docs)]
3#![cfg_attr(test, deny(warnings))]
4
5#[cfg(feature = "std")]
19#[macro_use]
20extern crate std;
21
22#[cfg(feature = "std")]
23mod thread;
24
25pub extern crate random_trait;
26pub use random_trait::Random;
27
28#[cfg(feature = "std")]
29use thread::FromRawPtr;
30#[cfg(feature = "std")]
31pub use thread::ThreadFastRng;
32
33use core::mem;
34
35#[cfg(feature = "doc-comment")]
36extern crate doc_comment;
37#[cfg(feature = "doc-comment")]
38doc_comment::doctest!("../README.md");
39
40const PCG_DEFAULT_MULTIPLIER_64: u64 = 6_364_136_223_846_793_005;
41
42pub struct FastRng {
46 state: u64,
48 inc: u64,
49}
50
51impl FastRng {
52 #[cfg(feature = "std")]
64 pub fn new() -> Self {
65 let (a, b) = time_seed();
66 Self::seed(a, b)
67 }
68
69 pub fn seed(seed: u64, seq: u64) -> Self {
71 let init_inc = (seq << 1) | 1;
72 let init_state = seed + init_inc;
73 let mut rng = FastRng { state: init_state, inc: init_inc };
74 rng.state = rng.state.wrapping_mul(PCG_DEFAULT_MULTIPLIER_64).wrapping_add(rng.inc);
75 rng
76 }
77
78 fn gen_u32(&mut self) -> u32 {
79 let old_state = self.state;
80 self.state = self.state.wrapping_mul(PCG_DEFAULT_MULTIPLIER_64).wrapping_add(self.inc);
81
82 let xorshift = (((old_state >> 18) ^ old_state) >> 27) as u32;
83 let rot = (old_state >> 59) as i32;
84 (xorshift >> rot) | (xorshift << ((-rot) & 31))
85 }
86}
87
88#[cfg(feature = "std")]
99pub fn local_rng() -> ThreadFastRng {
100 use std::cell::RefCell;
101 thread_local! {
102 pub static THREAD_FAST_RNG: RefCell<FastRng> = RefCell::new(FastRng::new());
103 }
104 let ptr = THREAD_FAST_RNG.with(|r| r.as_ptr());
105 ThreadFastRng::from_ptr(ptr)
106}
107
108#[cfg(feature = "std")]
109fn time_seed() -> (u64, u64) {
110 use std::time;
111 let now = time::SystemTime::now();
112 let unix = now.duration_since(time::UNIX_EPOCH).unwrap();
113
114 (unix.as_secs(), u64::from(unix.subsec_nanos()))
115}
116
117impl Random for FastRng {
118 type Error = ();
119
120 fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
121 for chunk in buf.chunks_mut(4) {
122 let rand: [u8; 4] = unsafe { mem::transmute(self.gen_u32()) };
123 let len = chunk.len();
124 chunk.copy_from_slice(&rand[..len]);
125 }
126 Ok(())
127 }
128 fn get_u32(&mut self) -> u32 {
129 self.gen_u32()
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_local() {
139 let mut local_rng = local_rng();
140 let a: u64 = local_rng.gen();
141 let b: u32 = local_rng.gen();
142 let c: [u8; 64] = local_rng.gen();
143 assert_ne!(a, 0);
144 assert_ne!(b, 0);
145 assert_ne!(&c[..], &[0u8; 64][..]);
146 }
147
148 #[test]
149 fn test_float() {
150 let mut rng = FastRng::new();
151 let f: f32 = rng.gen();
152 assert!(f > 0.0 && f < 1.0);
153 let f: f64 = rng.gen();
154 assert!(f > 0.0 && f < 1.0);
155 }
156}