1use crate::consts::{INCREMENTOR, INIT_INC, INIT_STATE};
25
26#[cfg(feature = "std")]
27use std::{
28 hash::{Hash, Hasher},
29 num::Wrapping,
30};
31
32#[cfg(not(feature = "std"))]
33use core::{
34 hash::{Hash, Hasher},
35 num::Wrapping,
36};
37
38use rand_core::{impls, Error, RngCore, SeedableRng};
39
40#[cfg(feature = "serde")]
41use serde::{Deserialize, Serialize};
42
43mod consts;
44
45#[derive(Debug, Clone, Eq, PartialEq)]
53#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
54pub struct Pcg {
55 state: u64,
56 inc: u64,
57}
58
59impl Pcg {
60 pub fn new(seed: u64, seq: u64) -> Pcg {
78 Pcg {
79 state: seed,
80 inc: (seq << 1) | 1,
81 }
82 }
83}
84
85impl Default for Pcg {
86 fn default() -> Self {
87 Pcg {
88 state: INIT_STATE,
89 inc: INIT_INC,
90 }
91 }
92}
93
94impl RngCore for Pcg {
95 fn next_u32(&mut self) -> u32 {
96 self.next_u64() as u32
97 }
98
99 fn next_u64(&mut self) -> u64 {
100 let old_state = self.state;
101 self.state = (Wrapping(old_state) * Wrapping(INCREMENTOR) + Wrapping(self.inc)).0;
102 let xor_shifted = (old_state >> 18) ^ old_state >> 27;
103
104 let rot = (old_state >> 59) as i64;
107 (xor_shifted >> rot as u64) | (xor_shifted << ((-rot) & 31))
108 }
109
110 fn fill_bytes(&mut self, dest: &mut [u8]) {
111 impls::fill_bytes_via_next(self, dest)
112 }
113
114 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
115 self.fill_bytes(dest);
116 Ok(())
117 }
118}
119
120const N: usize = 8;
122
123#[derive(Debug, Copy, Clone, Eq, PartialEq)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub struct PcgSeed(pub [u8; N]);
134
135#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
140pub struct U64(pub u64);
141
142const MASK: u8 = 0b11111111;
144
145impl From<PcgSeed> for U64 {
146 fn from(seed: PcgSeed) -> Self {
147 let mut res: u64 = 0;
148
149 for (i, &byte) in seed.0.iter().enumerate() {
152 let shift_up = (N - i - 1) * 8;
156 let byte = byte as u64;
157 let block = (byte << shift_up) as u64;
158 res |= block;
159 }
160 U64(res)
161 }
162}
163
164impl Default for PcgSeed {
165 fn default() -> Self {
166 Self([0; N])
167 }
168}
169
170impl AsMut<[u8]> for PcgSeed {
171 fn as_mut(&mut self) -> &mut [u8] {
172 &mut self.0
173 }
174}
175
176impl Hash for PcgSeed {
177 fn hash<H: Hasher>(&self, state: &mut H) {
178 let seed_vec = self.0.to_vec();
180 seed_vec.hash(state);
181 }
182}
183
184impl From<u64> for PcgSeed {
185 fn from(init: u64) -> Self {
186 let mut seed: [u8; N] = [0; N];
187
188 for i in 0..N {
189 let shift_factor = (N - i - 1) * 8;
190 let section = (init >> shift_factor) as u8;
191 seed[i] = section & MASK;
192 }
193 PcgSeed(seed)
194 }
195}
196
197impl From<U64> for PcgSeed {
198 fn from(init: U64) -> Self {
199 init.0.into()
200 }
201}
202
203impl SeedableRng for Pcg {
204 type Seed = PcgSeed;
205
206 fn from_seed(seed: Self::Seed) -> Pcg {
207 Pcg::new(U64::from(seed).0, INIT_INC)
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214 use std::fmt::{Binary, Debug};
215
216 fn assert_eq_binary<T>(a: T, b: T)
221 where
222 T: PartialEq + Debug + Binary,
223 {
224 let b_str_a = format!("{:b}", a);
225 let b_str_b = format!("{:b}", b);
226 assert_eq!(b_str_a, b_str_b);
227 }
228
229 #[test]
230 fn test_seed_to_u64() {
231 let mut seed = PcgSeed::default();
232 seed.0[0] = MASK;
233
234 let converted_int = U64::from(seed);
235 let expected = (MASK as u64) << ((N - 1) * 8);
236 assert_eq_binary(converted_int.0, expected);
237
238 let mut seed = PcgSeed::default();
239 seed.0[N - 1] = MASK;
240 let converted_int = U64::from(seed);
241 let expected = MASK as u64;
242 assert_eq_binary(converted_int.0, expected)
243 }
244
245 #[test]
246 fn test_u64_to_seed() {
247 let integer = (MASK as u64) << ((N - 1) * 8);
248 let seed = PcgSeed::from(integer);
249 let mut expected = PcgSeed::default();
250 expected.0[0] = MASK;
251 assert_eq!(seed, expected);
252
253 let integer = MASK as u64;
254 let seed = PcgSeed::from(integer);
255 let mut expected = PcgSeed::default();
256 expected.0[N - 1] = MASK;
257 assert_eq!(seed, expected);
258 }
259}