clock_rand/fast/
xoshiro256.rs1use crate::error::Result;
7use crate::fast::splitmix64::SplitMix64;
8use crate::seed::Seed;
9use crate::traits::{DeterministicRng, Rng, SeedableRng};
10
11#[derive(Debug, Clone)]
17pub struct Xoshiro256Plus {
18 state: [u64; 4],
19}
20
21impl Xoshiro256Plus {
22 pub fn new(seed: u64) -> Self {
24 let mut splitmix = SplitMix64::new(seed);
25 Self {
26 state: splitmix.seed_xoshiro256(),
27 }
28 }
29
30 pub fn from_seed_obj(seed: &Seed) -> Result<Self> {
32 let seed_bytes = seed.as_ref();
33 if seed_bytes.len() < 8 {
34 let mut expanded = seed_bytes.to_vec();
36 while expanded.len() < 8 {
37 expanded.extend_from_slice(seed_bytes);
38 }
39 let seed_value = u64::from_le_bytes([
40 expanded[0],
41 expanded[1],
42 expanded[2],
43 expanded[3],
44 expanded[4],
45 expanded[5],
46 expanded[6],
47 expanded[7],
48 ]);
49 Ok(Self::new(seed_value))
50 } else {
51 let seed_value = u64::from_le_bytes([
52 seed_bytes[0],
53 seed_bytes[1],
54 seed_bytes[2],
55 seed_bytes[3],
56 seed_bytes[4],
57 seed_bytes[5],
58 seed_bytes[6],
59 seed_bytes[7],
60 ]);
61 Ok(Self::new(seed_value))
62 }
63 }
64
65 #[inline(always)]
67 pub fn next_u64(&mut self) -> u64 {
68 let result = self.state[0].wrapping_add(self.state[3]);
69 let t = self.state[1] << 17;
70
71 self.state[2] ^= self.state[0];
72 self.state[3] ^= self.state[1];
73 self.state[1] ^= self.state[2];
74 self.state[0] ^= self.state[3];
75
76 self.state[2] ^= t;
77 self.state[3] = self.state[3].rotate_left(45);
78
79 result
80 }
81
82 #[inline]
84 pub fn next_u32(&mut self) -> u32 {
85 (self.next_u64() >> 32) as u32
86 }
87
88 #[inline]
90 pub fn fill_bytes(&mut self, dest: &mut [u8]) {
91 let mut chunks = dest.chunks_exact_mut(8);
92 for chunk in chunks.by_ref() {
93 let value = self.next_u64();
94 chunk.copy_from_slice(&value.to_le_bytes());
95 }
96 let remainder = chunks.into_remainder();
97 if !remainder.is_empty() {
98 let value = self.next_u64();
99 let bytes = value.to_le_bytes();
100 remainder.copy_from_slice(&bytes[..remainder.len()]);
101 }
102 }
103
104 #[inline]
106 pub fn jump(&mut self) {
107 const JUMP: [u64; 4] = [
108 0x180ec6d33cfd0aba,
109 0xd5a61266f0c9392c,
110 0xa9582618e03fc9aa,
111 0x39abdc4529b1661c,
112 ];
113
114 let mut s0 = 0;
115 let mut s1 = 0;
116 let mut s2 = 0;
117 let mut s3 = 0;
118
119 for j in &JUMP {
120 for b in 0..64 {
121 if (j & (1u64 << b)) != 0 {
122 s0 ^= self.state[0];
123 s1 ^= self.state[1];
124 s2 ^= self.state[2];
125 s3 ^= self.state[3];
126 }
127 self.next_u64();
128 }
129 }
130
131 self.state[0] = s0;
132 self.state[1] = s1;
133 self.state[2] = s2;
134 self.state[3] = s3;
135 }
136
137 #[inline]
139 pub fn long_jump(&mut self) {
140 const LONG_JUMP: [u64; 4] = [
141 0x76e15d3efefdcbbf,
142 0xc5004e441c522fb3,
143 0x77710069854ee241,
144 0x39109bb02acbe635,
145 ];
146
147 let mut s0 = 0;
148 let mut s1 = 0;
149 let mut s2 = 0;
150 let mut s3 = 0;
151
152 for j in &LONG_JUMP {
153 for b in 0..64 {
154 if (j & (1u64 << b)) != 0 {
155 s0 ^= self.state[0];
156 s1 ^= self.state[1];
157 s2 ^= self.state[2];
158 s3 ^= self.state[3];
159 }
160 self.next_u64();
161 }
162 }
163
164 self.state[0] = s0;
165 self.state[1] = s1;
166 self.state[2] = s2;
167 self.state[3] = s3;
168 }
169
170 pub fn save_state(&self) -> [u64; 4] {
172 self.state
173 }
174
175 pub fn restore_state(&mut self, state: [u64; 4]) {
177 self.state = state;
178 }
179}
180
181impl Rng for Xoshiro256Plus {
182 #[inline]
183 fn next_u32(&mut self) -> u32 {
184 self.next_u32()
185 }
186
187 #[inline]
188 fn next_u64(&mut self) -> u64 {
189 self.next_u64()
190 }
191
192 #[inline]
193 fn fill_bytes(&mut self, dest: &mut [u8]) {
194 self.fill_bytes(dest)
195 }
196}
197
198impl DeterministicRng for Xoshiro256Plus {
199 #[inline]
200 fn is_deterministic(&self) -> bool {
201 true
202 }
203}
204
205impl SeedableRng for Xoshiro256Plus {
206 type Seed = Seed;
207
208 fn from_seed(seed: Self::Seed) -> Self {
209 Self::from_seed_obj(&seed).expect("Seed should be valid")
210 }
211
212 fn reseed(&mut self, seed: Self::Seed) -> Result<()> {
213 *self = Self::from_seed_obj(&seed)?;
214 Ok(())
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221
222 #[test]
223 fn test_xoshiro256_deterministic() {
224 let mut rng1 = Xoshiro256Plus::new(12345);
225 let mut rng2 = Xoshiro256Plus::new(12345);
226
227 for _ in 0..100 {
228 assert_eq!(rng1.next_u64(), rng2.next_u64());
229 }
230 }
231
232 #[test]
233 fn test_xoshiro256_jump() {
234 let mut rng1 = Xoshiro256Plus::new(12345);
235 let mut rng2 = Xoshiro256Plus::new(12345);
236
237 for _ in 0..10 {
239 rng1.next_u64();
240 }
241
242 rng2.jump();
244 assert_ne!(rng1.next_u64(), rng2.next_u64());
245 }
246
247 #[test]
248 fn test_xoshiro256_save_restore() {
249 let mut rng = Xoshiro256Plus::new(42);
250 let _ = rng.next_u64();
251 let state = rng.save_state();
252
253 let mut rng2 = Xoshiro256Plus::new(0);
254 rng2.restore_state(state);
255
256 assert_eq!(rng.next_u64(), rng2.next_u64());
257 }
258}