devela/num/rand/xorshift/
u16.rs
1use crate::{xorshift_basis, ConstDefault, Own};
7
8#[must_use]
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub struct XorShift16<
19 const BASIS: usize = 0,
20 const A: usize = 7,
21 const B: usize = 9,
22 const C: usize = 8,
23>(u16);
24
25impl Default for XorShift16 {
27 fn default() -> Self {
28 Self::DEFAULT
29 }
30}
31impl ConstDefault for XorShift16 {
33 const DEFAULT: Self = Self::new_unchecked(Self::DEFAULT_SEED);
34}
35
36impl<const BASIS: usize, const A: usize, const B: usize, const C: usize>
38 XorShift16<BASIS, A, B, C>
39{
40 const DEFAULT_SEED: u16 = 0xDEFA;
41
42 #[cold] #[allow(dead_code)] #[rustfmt::skip]
43 const fn cold_path_default() -> Self { Self::new_unchecked(Self::DEFAULT_SEED) }
44}
45
46impl<const BASIS: usize, const A: usize, const B: usize, const C: usize>
47 XorShift16<BASIS, A, B, C>
48{
49 pub const fn new(seed: u16) -> Self {
53 if seed == 0 {
54 Self::cold_path_default()
55 } else {
56 Self(seed)
57 }
58 }
59
60 pub const fn new_unchecked(seed: u16) -> Self {
64 debug_assert![seed != 0, "Seed must be non-zero"];
65 Self(seed)
66 }
67
68 #[must_use]
69 pub const fn inner_state(self) -> u16 {
71 self.0
72 }
73 pub const fn from_state(state: u16) -> Self {
75 Self(state)
76 }
77
78 #[must_use]
80 pub const fn current_u16(&self) -> u16 {
81 self.0
82 }
83
84 #[must_use]
87 pub fn next_u16(&mut self) -> u16 {
88 let mut x = self.0;
89 xorshift_basis!(x, BASIS, (A, B, C));
90 self.0 = x;
91 x
92 }
93
94 pub const fn peek_next_state(&self) -> Self {
96 let mut x = self.0;
97 xorshift_basis!(x, BASIS, (A, B, C));
98 Self(x)
99 }
100
101 pub const fn own_next_u16(self) -> Own<Self, u16> {
103 let s = self.peek_next_state();
104 let v = s.current_u16();
105 Own::new(s, v)
106 }
107}
108
109impl<const BASIS: usize, const A: usize, const B: usize, const C: usize>
111 XorShift16<BASIS, A, B, C>
112{
113 pub const fn new1_u16(seed: u16) -> Self {
117 Self::new(seed)
118 }
119
120 pub const fn new2_u8(seeds: [u8; 2]) -> Self {
124 Self::new(u16::from_le_bytes(seeds))
125 }
126}
127
128#[cfg(all(feature = "dep_rand_core", feature = "join"))]
129#[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = "dep_rand_core", feature = "join"))))]
130mod impl_rand {
131 use crate::_dep::rand_core::{RngCore, SeedableRng};
132 use crate::{Cast, XorShift16};
133
134 impl<const BASIS: usize, const A: usize, const B: usize, const C: usize> RngCore
135 for XorShift16<BASIS, A, B, C>
136 {
137 fn next_u32(&mut self) -> u32 {
139 Cast::<u32>::from_u16_le([self.next_u16(), self.next_u16()])
140 }
141 fn next_u64(&mut self) -> u64 {
143 Cast::<u64>::from_u16_le([
144 self.next_u16(),
145 self.next_u16(),
146 self.next_u16(),
147 self.next_u16(),
148 ])
149 }
150 fn fill_bytes(&mut self, dest: &mut [u8]) {
151 let mut i = 0;
152 while i < dest.len() {
153 let random_u16 = self.next_u16();
154 let bytes = random_u16.to_le_bytes();
155 let remaining = dest.len() - i;
156
157 if remaining >= 2 {
158 dest[i] = bytes[0];
159 dest[i + 1] = bytes[1];
160 i += 2;
161 } else {
162 dest[i] = bytes[0];
163 i += 1;
164 }
165 }
166 }
167 }
168
169 impl<const BASIS: usize, const A: usize, const B: usize, const C: usize> SeedableRng
170 for XorShift16<BASIS, A, B, C>
171 {
172 type Seed = [u8; 2];
173
174 fn from_seed(seed: Self::Seed) -> Self {
177 if seed == [0; 2] {
178 Self::cold_path_default()
179 } else {
180 Self::new_unchecked(u16::from_le_bytes(seed))
181 }
182 }
183 }
184}
185
186#[doc(hidden)]
192#[rustfmt::skip]
193#[allow(dead_code)]
194pub const XOROSHIFT_16_TRIPLETS: [(u8, u8, u8); 4] = [
195 (6, 7, 13), (7, 9, 8), (7, 9, 13), (9, 7, 13)
196];