blob: bb9151b63819683ea84418f8cb8edfb7ae91840f (
plain)
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
|
//! Implements rng using the xoshiro256++ algorithm
use rand::{
SeedableRng,
rand_core::{RngCore, le},
};
/// Deterministic pseudo random number generator.
///
/// Is is a copy of `SmallRng` from `rand`, but is gurenteed
/// to be reproducible across versions and platforms.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DungeonRng {
s: [u64; 4],
}
impl SeedableRng for DungeonRng {
// Fix to 256 bits. Changing this is a breaking change!
type Seed = [u8; 32];
#[inline]
fn from_seed(seed: Self::Seed) -> Self {
let mut state = [0; 4];
le::read_u64_into(&seed, &mut state);
Self { s: state }
}
#[inline]
fn seed_from_u64(mut state: u64) -> Self {
const PHI: u64 = 0x9e3779b97f4a7c15;
let mut s = [0; 4];
for i in &mut s {
state = state.wrapping_add(PHI);
let mut z = state;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
z = z ^ (z >> 31);
*i = z;
}
Self { s }
}
}
impl RngCore for DungeonRng {
#[inline]
fn next_u32(&mut self) -> u32 {
let val = self.next_u64();
(val >> 32) as u32
}
#[inline]
fn next_u64(&mut self) -> u64 {
let res = self.s[0]
.wrapping_add(self.s[3])
.rotate_left(23)
.wrapping_add(self.s[0]);
let t = self.s[1] << 17;
self.s[2] ^= self.s[0];
self.s[3] ^= self.s[1];
self.s[1] ^= self.s[2];
self.s[0] ^= self.s[3];
self.s[2] ^= t;
self.s[3] = self.s[3].rotate_left(45);
res
}
#[inline]
fn fill_bytes(&mut self, dst: &mut [u8]) {
le::fill_bytes_via_next(self, dst);
}
}
|