devela/num/rand/xoroshiro/
u128.rs
1#[cfg(feature = "alloc")]
12use crate::Box;
13#[cfg(any(feature = "join", feature = "split"))]
14use crate::Cast;
15use crate::{ConstDefault, Own};
16#[cfg(feature = "std")]
17use crate::{Hasher, HasherBuild, RandomState};
18
19#[must_use]
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27pub struct Xoroshiro128pp([u32; 4]);
28
29impl Xoroshiro128pp {
31 #[must_use]
35 pub const fn new(seed: [u32; 4]) -> Option<Self> {
36 if (seed[0] | seed[1] | seed[2] | seed[3]) == 0 {
37 Self::cold_path_result()
38 } else {
39 Some(Self(seed))
40 }
41 }
42
43 pub const fn new_unchecked(seed: [u32; 4]) -> Self {
48 debug_assert!((seed[0] | seed[1] | seed[2] | seed[3]) != 0, "Seed must be non-zero");
49 Self(seed)
50 }
51
52 #[inline(never)]
56 pub fn from_stack() -> Self {
57 let (a, b, c, d) = (0, 0, 0, 0);
58 let seed: [u32; 4] = [
59 &a as *const _ as u32,
60 &b as *const _ as u32,
61 &c as *const _ as u32,
62 &d as *const _ as u32,
63 ];
64 Self::new_unchecked(seed)
65 }
66
67 #[inline(never)]
71 #[cfg(feature = "alloc")]
72 pub fn from_heap() -> Self {
73 let (a, b, c, d) = (0, Box::new(0), Box::new(0), 0);
74 let seed: [u32; 4] = [
75 &a as *const _ as u32,
76 &b as *const _ as u32,
77 &c as *const _ as u32,
78 &d as *const _ as u32,
79 ];
80 Self::new_unchecked(seed)
81 }
82
83 #[inline(never)]
85 #[cfg(feature = "std")]
86 pub fn from_randomstate() -> Self {
87 let h = RandomState::new();
88 let (mut hasher1, mut hasher2) = (h.build_hasher(), h.build_hasher());
89 hasher1.write_u32(Self::DEFAULT_SEED[0]);
90 hasher2.write_u32(Self::DEFAULT_SEED[0]);
91 let (hash1, hash2) = (hasher1.finish(), hasher2.finish());
92 let seed = [(hash1 >> 32) as u32, hash1 as u32, (hash2 >> 32) as u32, hash2 as u32];
93 Self::new_unchecked(seed)
94 }
95
96 #[must_use]
97 pub const fn inner_state(self) -> [u32; 4] {
99 self.0
100 }
101 pub const fn from_state(state: [u32; 4]) -> Self {
103 Self(state)
104 }
105}
106
107impl Xoroshiro128pp {
109 pub fn jump(&mut self) {
111 self.jump_with_constant(Self::JUMP);
112 }
113
114 pub fn long_jump(&mut self) {
116 self.jump_with_constant(Self::LONG_JUMP);
117 }
118
119 #[must_use]
123 pub fn next_u32(&mut self) -> u32 {
124 let result = self.current_u32();
125 let t = self.0[1] << 9;
126 self.0[2] ^= self.0[0];
127 self.0[3] ^= self.0[1];
128 self.0[1] ^= self.0[2];
129 self.0[0] ^= self.0[3];
130 self.0[2] ^= t;
131 self.0[3] = Self::rotl(self.0[3], 11);
132 result
133 }
134
135 #[must_use]
137 pub fn next2(&mut self) -> [u32; 2] {
138 [self.next_u32(), self.next_u32()]
139 }
140 #[must_use]
142 pub fn next4(&mut self) -> [u32; 4] {
143 [self.next_u32(), self.next_u32(), self.next_u32(), self.next_u32()]
144 }
145 #[must_use]
147 pub fn next4_u8(&mut self) -> [u8; 4] {
148 self.next_u32().to_ne_bytes()
149 }
150 #[must_use]
152 #[cfg(feature = "split")]
153 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "split")))]
154 pub fn next2_u16(&mut self) -> [u16; 2] {
155 Cast(self.next_u32()).into_u16_ne()
156 }
157 #[must_use]
159 #[cfg(feature = "join")]
160 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "join")))]
161 pub fn next_u64(&mut self) -> u64 {
162 Cast::<u64>::from_u32_ne(self.next2())
163 }
164 #[must_use]
166 #[cfg(feature = "join")]
167 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "join")))]
168 pub fn next_u128(&mut self) -> u128 {
169 Cast::<u128>::from_u32_ne(self.next4())
170 }
171}
172
173impl Xoroshiro128pp {
175 #[must_use]
177 pub const fn current_u32(self) -> u32 {
178 Self::rotl(self.0[0].wrapping_add(self.0[3]), 7).wrapping_add(self.0[0])
179 }
180
181 pub const fn copy_peek_next_state(self) -> Self {
183 let mut x = self.0;
184 let t = x[1] << 9;
185 x[2] ^= x[0];
186 x[3] ^= x[1];
187 x[1] ^= x[2];
188 x[0] ^= x[3];
189 x[2] ^= t;
190 x[3] = Self::rotl(x[3], 11);
191 Self(x)
192 }
193
194 pub const fn own_next_u32(self) -> Own<Self, u32> {
196 let next_state = self.copy_peek_next_state();
197 let next_value = next_state.current_u32();
198 Own::new(next_state, next_value)
199 }
200
201 pub const fn copy_jump(self) -> Self {
203 self.copy_jump_with_constant(Self::JUMP)
204 }
205
206 pub const fn copy_long_jump(self) -> Self {
208 self.copy_jump_with_constant(Self::LONG_JUMP)
209 }
210}
211
212impl Xoroshiro128pp {
214 #[cfg(feature = "split")]
218 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "split")))]
219 pub const fn new1_u128(seed: u128) -> Option<Self> {
220 Self::new(Cast(seed).into_u32_le())
221 }
222
223 #[cfg(feature = "split")]
227 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "split")))]
228 pub const fn new2_u64(seeds: [u64; 2]) -> Option<Self> {
229 let [x, y] = Cast(seeds[0]).into_u32_le();
230 let [z, a] = Cast(seeds[1]).into_u32_le();
231 Self::new([x, y, z, a])
232 }
233
234 pub const fn new4_u32(seeds: [u32; 4]) -> Option<Self> {
238 Self::new(seeds)
239 }
240
241 #[cfg(feature = "join")]
245 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "join")))]
246 pub const fn new8_u16(seeds: [u16; 8]) -> Option<Self> {
247 Self::new([
248 Cast::<u32>::from_u16_le([seeds[0], seeds[1]]),
249 Cast::<u32>::from_u16_le([seeds[2], seeds[3]]),
250 Cast::<u32>::from_u16_le([seeds[4], seeds[5]]),
251 Cast::<u32>::from_u16_le([seeds[6], seeds[7]]),
252 ])
253 }
254
255 pub const fn new16_u8(seeds: [u8; 16]) -> Option<Self> {
259 Self::new([
260 u32::from_le_bytes([seeds[0], seeds[1], seeds[2], seeds[3]]),
261 u32::from_le_bytes([seeds[4], seeds[5], seeds[6], seeds[7]]),
262 u32::from_le_bytes([seeds[8], seeds[9], seeds[10], seeds[11]]),
263 u32::from_le_bytes([seeds[12], seeds[13], seeds[14], seeds[15]]),
264 ])
265 }
266}
267
268impl Default for Xoroshiro128pp {
272 fn default() -> Self {
273 Self::new_unchecked(Self::DEFAULT_SEED)
274 }
275}
276impl ConstDefault for Xoroshiro128pp {
278 const DEFAULT: Self = Self::new_unchecked(Self::DEFAULT_SEED);
279}
280
281#[cfg(feature = "dep_rand_core")]
282#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "dep_rand_core")))]
283mod impl_rand {
284 use super::Xoroshiro128pp;
285 use crate::_dep::rand_core::{RngCore, SeedableRng};
286
287 impl RngCore for Xoroshiro128pp {
288 fn next_u32(&mut self) -> u32 {
290 self.next_u32()
291 }
292 fn next_u64(&mut self) -> u64 {
294 ((self.next_u32() as u64) << 32) | (self.next_u32() as u64)
295 }
296 fn fill_bytes(&mut self, dest: &mut [u8]) {
297 let mut i = 0;
298 while i < dest.len() {
299 let random_u32 = self.next_u32();
300 let bytes = random_u32.to_le_bytes();
301 let remaining = dest.len() - i;
302
303 if remaining >= 4 {
304 dest[i..i + 4].copy_from_slice(&bytes);
305 i += 4;
306 } else {
307 dest[i..].copy_from_slice(&bytes[..remaining]);
308 break;
309 }
310 }
311 }
312 }
313
314 impl SeedableRng for Xoroshiro128pp {
315 type Seed = [u8; 16];
316
317 fn from_seed(seed: Self::Seed) -> Self {
320 let mut seed_u32s = [0u32; 4];
321 if seed == [0; 16] {
322 Self::cold_path_default()
323 } else {
324 for i in 0..4 {
325 seed_u32s[i] = u32::from_le_bytes([
326 seed[i * 4],
327 seed[i * 4 + 1],
328 seed[i * 4 + 2],
329 seed[i * 4 + 3],
330 ]);
331 }
332 Self::new_unchecked(seed_u32s)
333 }
334 }
335 }
336}
337
338impl Xoroshiro128pp {
341 const DEFAULT_SEED: [u32; 4] = [0xDEFA_0017; 4];
342 const JUMP: [u32; 4] = [0x8764_000b, 0xf542_d2d3, 0x6fa0_35c3, 0x77f2_db5b];
343 const LONG_JUMP: [u32; 4] = [0xb523_952e, 0x0b6f_099f, 0xccf_5a0ef, 0x1c58_0662];
344
345 #[cold] #[rustfmt::skip]
346 const fn cold_path_result() -> Option<Self> { None }
347 #[cold] #[allow(dead_code)] #[rustfmt::skip]
348 const fn cold_path_default() -> Self { Self::new_unchecked(Self::DEFAULT_SEED) }
349
350 const fn rotl(x: u32, k: i32) -> u32 {
352 (x << k) | (x >> (32 - k))
353 }
354
355 fn jump_with_constant(&mut self, jump: [u32; 4]) {
356 let (mut s0, mut s1, mut s2, mut s3) = (0, 0, 0, 0);
357 for &j in jump.iter() {
358 for b in 0..32 {
359 if (j & (1 << b)) != 0 {
360 s0 ^= self.0[0];
361 s1 ^= self.0[1];
362 s2 ^= self.0[2];
363 s3 ^= self.0[3];
364 }
365 let _ = self.next_u32();
366 }
367 }
368 self.0 = [s0, s1, s2, s3];
369 }
370
371 const fn copy_jump_with_constant(self, jump: [u32; 4]) -> Self {
372 let (mut s0, mut s1, mut s2, mut s3) = (0, 0, 0, 0);
373 let mut state = self;
374 let mut i = 0;
375 while i < jump.len() {
376 let mut b = 0;
377 while b < 32 {
378 if (jump[i] & (1 << b)) != 0 {
379 s0 ^= state.0[0];
380 s1 ^= state.0[1];
381 s2 ^= state.0[2];
382 s3 ^= state.0[3];
383 }
384 state = state.copy_peek_next_state();
385 b += 1;
386 }
387 i += 1;
388 }
389 Self([s0, s1, s2, s3])
390 }
391}