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
use rand::{RngCore, SeedableRng};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct SquirrelRng {
position: u32,
seed: u32,
}
impl SquirrelRng {
pub fn new() -> Self {
Self {
position: 0,
seed: rand::thread_rng().next_u32(),
}
}
pub fn with_seed(seed: u32) -> Self {
Self { position: 0, seed }
}
}
impl Default for SquirrelRng {
fn default() -> Self {
SquirrelRng::new()
}
}
impl RngCore for SquirrelRng {
#[inline]
fn next_u32(&mut self) -> u32 {
let result = squirrel3(self.position, self.seed);
self.position = self.position.wrapping_add(1);
result
}
#[inline]
fn next_u64(&mut self) -> u64 {
next_u64_via_u32(self)
}
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
fill_bytes_via_next(self, dest);
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for SquirrelRng {
type Seed = [u8; 4];
fn from_seed(seed: Self::Seed) -> Self {
Self::with_seed(u32::from_le_bytes(seed))
}
}
#[inline]
pub fn squirrel3(position: u32, seed: u32) -> u32 {
const BIT_NOISE1: u32 = 0x68E31DA4;
const BIT_NOISE2: u32 = 0xB5297A4D;
const BIT_NOISE3: u32 = 0x1B56C4E9;
let mut mangled = position as u32;
mangled = mangled.wrapping_mul(BIT_NOISE1);
mangled = mangled.wrapping_add(seed);
mangled ^= mangled >> 8;
mangled = mangled.wrapping_add(BIT_NOISE2);
mangled ^= mangled << 8;
mangled = mangled.wrapping_mul(BIT_NOISE3);
mangled ^= mangled >> 8;
mangled
}
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
let x = u64::from(rng.next_u32());
let y = u64::from(rng.next_u32());
(y << 32) | x
}
fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
let mut left = dest;
while left.len() >= 8 {
let (l, r) = { left }.split_at_mut(8);
left = r;
let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
l.copy_from_slice(&chunk);
}
let n = left.len();
if n > 4 {
let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
left.copy_from_slice(&chunk[..n]);
} else if n > 0 {
let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
left.copy_from_slice(&chunk[..n]);
}
}