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