1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3use wrapping_arithmetic::wrappit;
4
5#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16#[derive(Clone, Eq, PartialEq, Debug)]
17pub struct Krull64 {
18 lcg0: u64,
20 lcg1: u64,
22 stream: u64,
24}
25
26#[inline]
31fn origin_0(stream: u64) -> u64 {
32 !stream
33}
34
35#[inline]
36fn origin_128(stream: u64) -> u128 {
37 origin_0(stream) as u128
38}
39
40impl Krull64 {
41 #[inline]
42 fn lcg_128(&self) -> u128 {
43 self.lcg0 as u128 | ((self.lcg1 as u128) << 64)
44 }
45
46 #[inline]
47 fn multiplier(&self) -> u64 {
48 super::LCG_M65_1 as u64
49 }
50
51 #[inline]
52 fn multiplier_128(&self) -> u128 {
53 super::LCG_M65_1
54 }
55
56 #[inline]
57 fn increment_128(&self) -> u128 {
58 ((self.stream as u128) << 1) | 1
66 }
67
68 #[inline]
70 fn origin_0(&self) -> u64 {
71 origin_0(self.stream)
72 }
73
74 #[inline]
76 fn origin_128(&self) -> u128 {
77 origin_128(self.stream)
78 }
79
80 #[wrappit]
82 #[inline]
83 pub fn step(&mut self) -> u64 {
84 let lcg = (self.lcg0 as u128) * self.multiplier() as u128 + self.increment_128();
87 self.lcg1 = ((lcg >> 64) as u64) + self.lcg1 * self.multiplier() + self.lcg0;
88 self.lcg0 = lcg as u64;
89 self.get()
90 }
91
92 #[inline]
94 pub fn step_128(&mut self) -> u128 {
95 self.step() as u128 | ((self.step() as u128) << 64)
96 }
97
98 #[wrappit]
100 #[inline]
101 pub fn get(&self) -> u64 {
102 let x = self.lcg1;
106
107 let x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
112 let x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
113 let x = (x ^ (x >> 31)) * 0xd6e8feb86659fd93;
114 x ^ (x >> 32)
115 }
116
117 #[wrappit]
119 #[inline]
120 pub fn step_slow(&mut self) -> u64 {
121 let lcg = self.lcg_128() * self.multiplier_128() + self.increment_128();
122 self.lcg0 = lcg as u64;
123 self.lcg1 = (lcg >> 64) as u64;
124 self.get()
125 }
126
127 #[allow(clippy::new_without_default)]
130 pub fn new() -> Self {
131 Krull64 {
132 lcg0: origin_0(0),
133 lcg1: 0,
134 stream: 0,
135 }
136 }
137
138 pub fn from_32(seed: u32) -> Self {
142 Krull64::from_64(seed as u64)
143 }
144
145 pub fn from_64(seed: u64) -> Self {
149 Krull64 {
150 lcg0: origin_0(seed),
151 lcg1: 0,
152 stream: seed,
153 }
154 }
155
156 pub fn from_128(seed: u128) -> Self {
163 let mut krull = Krull64::from_64(((seed >> 64) ^ seed) as u64);
164 krull.set_position((seed as u128) << 64);
165 krull
166 }
167
168 pub fn jump(&mut self, steps: i128) {
171 let lcg = crate::lcg::get_state(
172 self.multiplier_128(),
173 self.increment_128(),
174 self.lcg_128(),
175 steps as u128,
176 );
177 self.lcg0 = lcg as u64;
178 self.lcg1 = (lcg >> 64) as u64;
179 }
180
181 pub fn position(&self) -> u128 {
183 crate::lcg::get_iterations(
184 self.multiplier_128(),
185 self.increment_128(),
186 self.origin_128(),
187 self.lcg_128(),
188 )
189 }
190
191 pub fn set_position(&mut self, position: u128) {
193 let lcg = crate::lcg::get_state(
194 self.multiplier_128(),
195 self.increment_128(),
196 self.origin_128(),
197 position,
198 );
199 self.lcg0 = lcg as u64;
200 self.lcg1 = (lcg >> 64) as u64;
201 }
202
203 #[inline]
205 pub fn reset(&mut self) {
206 self.lcg0 = self.origin_0();
207 self.lcg1 = 0;
208 }
209
210 #[inline]
212 pub fn stream(&self) -> u64 {
213 self.stream
214 }
215
216 pub fn set_stream(&mut self, stream: u64) {
218 self.stream = stream;
219 self.reset();
220 }
221}
222
223use super::{Error, RngCore, SeedableRng};
224
225impl RngCore for Krull64 {
226 fn next_u32(&mut self) -> u32 {
227 self.step() as u32
228 }
229
230 fn next_u64(&mut self) -> u64 {
231 self.step()
232 }
233
234 fn fill_bytes(&mut self, dest: &mut [u8]) {
235 let bytes = dest.len();
236 let mut i = 0;
237 while i < bytes {
238 let x = self.step();
239 let j = bytes.min(i + 8);
240 dest[i..j].copy_from_slice(&x.to_le_bytes()[0..(j - i)]);
242 i = j;
243 }
244 }
245
246 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
247 self.fill_bytes(dest);
248 Ok(())
249 }
250}
251
252impl SeedableRng for Krull64 {
253 type Seed = [u8; 16];
254
255 fn from_seed(seed: Self::Seed) -> Self {
258 Krull64::from_128(u128::from_le_bytes(seed))
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use super::super::*;
266 use super::*;
267
268 #[test]
269 pub fn run_tests() {
270 let krull64_expected: [u64; 16] = [
271 0x57c1b6c1df5ed4d2,
272 0x1efdba83398cf412,
273 0xa02d8dfda06ac9ce,
274 0xf6e3f32be5e81841,
275 0xc2a690083e597e0d,
276 0x3b1b2ed3fa6c15aa,
277 0x241c691340a479b2,
278 0x88c24c8d79bb67c1,
279 0x09f213c4fc2b61dc,
280 0xa4b6ad95c713c951,
281 0xa43904ae3341edf7,
282 0xee2dca4d5fd5f8fa,
283 0x27bdddbeaa4aadb0,
284 0x98c78e68dbf634b2,
285 0xf0edc57017a0d5a5,
286 0x8647ea5de51eca23,
287 ];
288 let mut krull64 = Krull64::from_64(0);
289 for x in krull64_expected {
290 assert_eq!(x, krull64.next_u64());
291 }
292
293 let mut r: u128 = 0;
294 let mut rnd = || -> u128 {
295 r = r.wrapping_mul(LCG_M128_1).wrapping_add(0xffff);
296 r
297 };
298
299 for _ in 0..1 << 12 {
300 let seed = rnd() as u64;
301 let mut krull1 = Krull64::new();
302 assert_eq!(0, krull1.stream());
303 assert_eq!(0, krull1.position());
304 krull1.set_stream(seed);
305 assert_eq!(seed, krull1.stream());
306 assert_eq!(0, krull1.position());
307 let mut krull2 = Krull64::from_64(seed);
308 assert_eq!(seed, krull2.stream());
309 assert_eq!(0, krull2.position());
310
311 let pos2 = rnd();
312 let pos1 = pos2 & rnd();
313 krull1.set_position(pos1);
314 krull2.set_position(pos2);
315 assert_eq!(pos1, krull1.position());
316 assert_eq!(pos2, krull2.position());
317 krull1.jump((pos2 - pos1) as i128);
318 assert_eq!(pos2, krull1.position());
319 assert_eq!(krull1.next_u64(), krull2.next_u64());
320 krull1.jump(-1);
321 assert_eq!(pos2, krull1.position());
322 krull2.jump(-1);
323 assert_eq!(pos2, krull2.position());
324 krull1.jump(-((pos2 - pos1) as i128));
325 assert_eq!(pos1, krull1.position());
326
327 let n = 1 + (rnd() & 0x3ff);
328 for _ in 0..n {
329 krull1.next_u64();
330 }
331 assert_eq!(pos1 + n, krull1.position());
332
333 assert_eq!(seed, krull1.stream());
334
335 let bytes = 1 + (rnd() & 0x7f);
336 let mut buffer1 = [0u8; 0x80];
337 let mut buffer2 = [0u8; 0x80];
338 krull1.reset();
339 assert_eq!(0, krull1.position());
340 krull1.fill_bytes(&mut buffer1[0..bytes as usize]);
341 krull2.reset();
342 for i in 0..0x10 {
343 let x = krull2.next_u64();
344 buffer2[(i << 3)..((i + 1) << 3)].copy_from_slice(&x.to_le_bytes());
345 }
346 assert!(buffer1[0..bytes as usize]
347 .iter()
348 .zip(buffer2[0..bytes as usize].iter())
349 .all(|(x, y)| x == y));
350 }
351 }
352}