devela/num/rand/xorshift/
u128p.rs1#[cfg(any(feature = "join", feature = "split"))]
7use crate::Cast;
8use crate::{ConstDefault, Own};
9
10#[doc = crate::TAG_RAND!()]
11#[must_use]
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub struct XorShift128p([u64; 2]);
20
21impl Default for XorShift128p {
23 fn default() -> Self {
24 Self::DEFAULT
25 }
26}
27impl ConstDefault for XorShift128p {
29 const DEFAULT: Self = Self::new_unchecked(Self::DEFAULT_SEED);
30}
31
32impl XorShift128p {
34 const DEFAULT_SEED: [u64; 2] = [0xDEFA_0017_DEFA_0017; 2];
35
36 #[cold] #[allow(dead_code)] #[rustfmt::skip]
37 const fn cold_path_default() -> Self { Self::new_unchecked(Self::DEFAULT_SEED) }
38}
39
40impl XorShift128p {
41 pub const fn new(seeds: [u64; 2]) -> Self {
45 if (seeds[0] | seeds[1]) == 0 { Self::cold_path_default() } else { Self(seeds) }
46 }
47
48 pub const fn new_unchecked(seeds: [u64; 2]) -> Self {
56 debug_assert![(seeds[0] | seeds[1]) != 0, "Seeds must be non-zero"];
57 Self(seeds)
58 }
59
60 #[must_use]
61 pub const fn inner_state(self) -> [u64; 2] {
63 self.0
64 }
65 pub const fn from_state(state: [u64; 2]) -> Self {
67 Self(state)
68 }
69
70 #[must_use]
72 pub const fn current_u64(&self) -> u64 {
73 self.0[0].wrapping_add(self.0[1])
74 }
75
76 #[must_use]
78 pub fn next_u64(&mut self) -> u64 {
79 let [s0, mut s1] = [self.0[0], self.0[1]];
80 let result = s0.wrapping_add(s1);
81
82 s1 ^= s0;
83 self.0[0] = s0.rotate_left(55) ^ s1 ^ (s1 << 14); self.0[1] = s1.rotate_left(36); result
87 }
88
89 pub const fn peek_next_state(&self) -> Self {
91 let mut x = self.0;
92 let [s0, mut s1] = [x[0], x[1]];
93
94 s1 ^= s0;
95 x[0] = s0.rotate_left(55) ^ s1 ^ (s1 << 14); x[1] = s1.rotate_left(36); Self(x)
99 }
100
101 pub const fn own_next_u64(self) -> Own<Self, u64> {
103 let s = self.peek_next_state();
104 let v = s.current_u64();
105 Own::new(s, v)
106 }
107}
108
109impl XorShift128p {
111 #[cfg(feature = "split")]
115 #[cfg_attr(nightly_doc, doc(cfg(feature = "split")))]
116 pub const fn new1_u128(seed: u128) -> Self {
117 Self::new(Cast(seed).into_u64_le())
118 }
119
120 pub const fn new2_u64(seeds: [u64; 2]) -> Self {
124 Self::new(seeds)
125 }
126
127 #[cfg(feature = "join")]
131 #[cfg_attr(nightly_doc, doc(cfg(feature = "join")))]
132 pub const fn new4_u32(seeds: [u32; 4]) -> Self {
133 Self::new([
134 Cast::<u64>::from_u32_le([seeds[0], seeds[1]]),
135 Cast::<u64>::from_u32_le([seeds[2], seeds[3]]),
136 ])
137 }
138
139 #[cfg(feature = "join")]
143 #[cfg_attr(nightly_doc, doc(cfg(feature = "join")))]
144 pub const fn new8_u16(seeds: [u16; 8]) -> Self {
145 Self::new([
146 Cast::<u64>::from_u16_le([seeds[0], seeds[1], seeds[2], seeds[3]]),
147 Cast::<u64>::from_u16_le([seeds[4], seeds[5], seeds[6], seeds[7]]),
148 ])
149 }
150
151 pub const fn new16_u8(seeds: [u8; 16]) -> Self {
155 let s = seeds;
156 Self::new([
157 u64::from_le_bytes([s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]]),
158 u64::from_le_bytes([s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]]),
159 ])
160 }
161}
162
163#[cfg(feature = "dep_rand_core")]
164#[cfg_attr(nightly_doc, doc(cfg(feature = "dep_rand_core")))]
165mod impl_rand {
166 use super::XorShift128p;
167 use crate::_dep::rand_core::{RngCore, SeedableRng};
168
169 impl RngCore for XorShift128p {
170 fn next_u32(&mut self) -> u32 {
173 self.next_u64() as u32
174 }
175
176 fn next_u64(&mut self) -> u64 {
178 self.next_u64()
179 }
180
181 fn fill_bytes(&mut self, dest: &mut [u8]) {
182 let mut i = 0;
183 while i < dest.len() {
184 let random_u64 = self.next_u64();
185 let bytes = random_u64.to_le_bytes();
186 let remaining = dest.len() - i;
187
188 if remaining >= 8 {
189 dest[i..i + 8].copy_from_slice(&bytes);
190 i += 8;
191 } else {
192 dest[i..].copy_from_slice(&bytes[..remaining]);
193 break;
194 }
195 }
196 }
197 }
198
199 impl SeedableRng for XorShift128p {
200 type Seed = [u8; 16];
201
202 fn from_seed(seed: Self::Seed) -> Self {
205 let mut seed_u64s = [0u64; 2];
206 if seed == [0; 16] {
207 Self::cold_path_default()
208 } else {
209 for i in 0..2 {
210 seed_u64s[i] = u64::from_le_bytes([
211 seed[i * 8],
212 seed[i * 8 + 1],
213 seed[i * 8 + 2],
214 seed[i * 8 + 3],
215 seed[i * 8 + 4],
216 seed[i * 8 + 5],
217 seed[i * 8 + 6],
218 seed[i * 8 + 7],
219 ]);
220 }
221 Self::new_unchecked(seed_u64s)
222 }
223 }
224 }
225}