devela/num/rand/xorshift/
u128.rs
1#[cfg(any(feature = "join", feature = "split"))]
7use crate::Cast;
8use crate::{ConstDefault, Own};
9
10#[must_use]
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub struct XorShift128([u32; 4]);
18
19impl Default for XorShift128 {
21 fn default() -> Self {
22 Self::DEFAULT
23 }
24}
25impl ConstDefault for XorShift128 {
27 const DEFAULT: Self = Self::new_unchecked(Self::DEFAULT_SEED);
28}
29
30impl XorShift128 {
32 const DEFAULT_SEED: [u32; 4] = [0xDEFA_0017; 4];
33
34 #[cold] #[allow(dead_code)] #[rustfmt::skip]
35 const fn cold_path_default() -> Self { Self::new_unchecked(Self::DEFAULT_SEED) }
36}
37
38impl XorShift128 {
39 pub const fn new(seeds: [u32; 4]) -> Self {
43 if (seeds[0] | seeds[1] | seeds[2] | seeds[3]) == 0 {
44 Self::cold_path_default()
45 } else {
46 Self([seeds[0], seeds[1], seeds[2], seeds[3]])
47 }
48 }
49
50 pub const fn new_unchecked(seeds: [u32; 4]) -> Self {
58 debug_assert![(seeds[0] | seeds[1] | seeds[2] | seeds[3]) != 0, "Seeds must be non-zero"];
59 Self(seeds)
60 }
61
62 #[must_use]
63 pub const fn inner_state(self) -> [u32; 4] {
65 self.0
66 }
67 pub const fn from_state(state: [u32; 4]) -> Self {
69 Self(state)
70 }
71
72 #[must_use]
73 pub const fn current_u64(&self) -> u64 {
75 ((self.0[0] as u64) << 32) | (self.0[1] as u64)
76 }
77
78 #[must_use]
79 pub fn next_u64(&mut self) -> u64 {
83 let t = self.0[3];
84 let mut s = self.0[0];
85 self.0[3] = self.0[2];
86 self.0[2] = self.0[1];
87 self.0[1] = s;
88 s ^= s << 11;
89 s ^= s >> 8;
90 self.0[0] = s ^ t ^ (t >> 19);
91
92 ((self.0[0] as u64) << 32) | (self.0[1] as u64)
93 }
94
95 pub const fn peek_next_state(&self) -> Self {
97 let mut x = self.0;
98
99 let t = x[3];
100 let mut s = x[0];
101 x[3] = x[2];
102 x[2] = x[1];
103 x[1] = s;
104 s ^= s << 11;
105 s ^= s >> 8;
106 x[0] = s ^ t ^ (t >> 19);
107
108 Self(x)
109 }
110
111 pub const fn own_next_u64(self) -> Own<Self, u64> {
113 let s = self.peek_next_state();
114 let v = s.current_u64();
115 Own::new(s, v)
116 }
117}
118
119impl XorShift128 {
121 #[cfg(feature = "split")]
125 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "split")))]
126 pub const fn new1_u128(seed: u128) -> Self {
127 Self::new(Cast(seed).into_u32_le())
128 }
129
130 #[cfg(feature = "split")]
134 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "split")))]
135 pub const fn new2_u64(seeds: [u64; 2]) -> Self {
136 let [x, y] = Cast(seeds[0]).into_u32_le();
137 let [z, a] = Cast(seeds[1]).into_u32_le();
138 Self::new([x, y, z, a])
139 }
140
141 pub const fn new4_u32(seeds: [u32; 4]) -> Self {
145 Self::new(seeds)
146 }
147
148 #[cfg(feature = "join")]
152 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "join")))]
153 pub const fn new8_u16(seeds: [u16; 8]) -> Self {
154 Self::new([
155 Cast::<u32>::from_u16_le([seeds[0], seeds[1]]),
156 Cast::<u32>::from_u16_le([seeds[2], seeds[3]]),
157 Cast::<u32>::from_u16_le([seeds[4], seeds[5]]),
158 Cast::<u32>::from_u16_le([seeds[6], seeds[7]]),
159 ])
160 }
161
162 pub const fn new16_u8(seeds: [u8; 16]) -> Self {
166 Self::new([
167 u32::from_le_bytes([seeds[0], seeds[1], seeds[2], seeds[3]]),
168 u32::from_le_bytes([seeds[4], seeds[5], seeds[6], seeds[7]]),
169 u32::from_le_bytes([seeds[8], seeds[9], seeds[10], seeds[11]]),
170 u32::from_le_bytes([seeds[12], seeds[13], seeds[14], seeds[15]]),
171 ])
172 }
173}
174
175#[cfg(feature = "dep_rand_core")]
176#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "dep_rand_core")))]
177mod impl_rand {
178 use super::XorShift128;
179 use crate::_dep::rand_core::{RngCore, SeedableRng};
180
181 impl RngCore for XorShift128 {
182 fn next_u32(&mut self) -> u32 {
185 self.next_u64() as u32
186 }
187
188 fn next_u64(&mut self) -> u64 {
190 self.next_u64()
191 }
192
193 fn fill_bytes(&mut self, dest: &mut [u8]) {
194 let mut i = 0;
195 while i < dest.len() {
196 let random_u64 = self.next_u64();
197 let bytes = random_u64.to_le_bytes();
198 let remaining = dest.len() - i;
199
200 if remaining >= 8 {
201 dest[i..i + 8].copy_from_slice(&bytes);
202 i += 8;
203 } else {
204 dest[i..].copy_from_slice(&bytes[..remaining]);
205 break;
206 }
207 }
208 }
209 }
210
211 impl SeedableRng for XorShift128 {
212 type Seed = [u8; 16];
213
214 fn from_seed(seed: Self::Seed) -> Self {
217 let mut seed_u32s = [0u32; 4];
218 if seed == [0; 16] {
219 Self::cold_path_default()
220 } else {
221 for i in 0..4 {
222 seed_u32s[i] = u32::from_le_bytes([
223 seed[i * 4],
224 seed[i * 4 + 1],
225 seed[i * 4 + 2],
226 seed[i * 4 + 3],
227 ]);
228 }
229 Self::new_unchecked(seed_u32s)
230 }
231 }
232 }
233}