devela/num/rand/xorshift/
u8.rs
1use crate::{xorshift_basis, ConstDefault, Own};
7
8#[must_use]
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub struct XorShift8<const A: usize = 3, const B: usize = 4, const C: usize = 2>(u8);
15
16impl<const A: usize, const B: usize, const C: usize> Default for XorShift8<A, B, C> {
18 fn default() -> Self {
19 Self::new_unchecked(Self::DEFAULT_SEED)
20 }
21}
22impl<const A: usize, const B: usize, const C: usize> ConstDefault for XorShift8<A, B, C> {
24 const DEFAULT: Self = Self::new_unchecked(Self::DEFAULT_SEED);
25}
26
27impl<const A: usize, const B: usize, const C: usize> XorShift8<A, B, C> {
29 const DEFAULT_SEED: u8 = 0xDE;
30
31 #[cold] #[allow(dead_code)] #[rustfmt::skip]
32 const fn cold_path_default() -> Self { Self::new_unchecked(Self::DEFAULT_SEED) }
33}
34
35impl<const A: usize, const B: usize, const C: usize> XorShift8<A, B, C> {
36 pub const fn new(seed: u8) -> Self {
43 debug_assert![A > 0 && A <= 7];
44 debug_assert![B > 0 && A <= 7];
45 debug_assert![C > 0 && A <= 7];
46 if seed == 0 {
47 Self::cold_path_default()
48 } else {
49 Self(seed)
50 }
51 }
52
53 pub const fn new_unchecked(seed: u8) -> Self {
62 debug_assert![A > 0 && A <= 7];
63 debug_assert![B > 0 && A <= 7];
64 debug_assert![C > 0 && A <= 7];
65 debug_assert![seed != 0, "Seed must be non-zero"];
66 Self(seed)
67 }
68
69 #[must_use]
70 pub const fn inner_state(self) -> u8 {
72 self.0
73 }
74 pub const fn from_state(state: u8) -> Self {
76 Self(state)
77 }
78
79 #[must_use]
81 pub const fn current_u8(&self) -> u8 {
82 self.0
83 }
84
85 pub fn next_u8(&mut self) -> u8 {
88 let mut x = self.0;
89 xorshift_basis!(x, 0, (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, 0, (A, B, C));
98 Self(x)
99 }
100
101 pub const fn own_next_u8(self) -> Own<Self, u8> {
103 let s = self.peek_next_state();
104 let v = s.current_u8();
105 Own::new(s, v)
106 }
107}
108
109impl<const A: usize, const B: usize, const C: usize> XorShift8<A, B, C> {
111 pub const fn new1_u8(seed: u8) -> Self {
115 Self::new(seed)
116 }
117}
118
119#[cfg(feature = "dep_rand_core")]
120#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "dep_rand_core")))]
121mod impl_rand {
122 use super::XorShift8;
123 use crate::_dep::rand_core::{RngCore, SeedableRng};
124
125 impl<const A: usize, const B: usize, const C: usize> RngCore for XorShift8<A, B, C> {
126 fn next_u32(&mut self) -> u32 {
128 u32::from_le_bytes([self.next_u8(), self.next_u8(), self.next_u8(), self.next_u8()])
129 }
130
131 fn next_u64(&mut self) -> u64 {
133 u64::from_le_bytes([
134 self.next_u8(),
135 self.next_u8(),
136 self.next_u8(),
137 self.next_u8(),
138 self.next_u8(),
139 self.next_u8(),
140 self.next_u8(),
141 self.next_u8(),
142 ])
143 }
144
145 fn fill_bytes(&mut self, dest: &mut [u8]) {
146 for byte in dest {
147 *byte = self.next_u8();
148 }
149 }
150 }
151
152 impl<const A: usize, const B: usize, const C: usize> SeedableRng for XorShift8<A, B, C> {
153 type Seed = [u8; 1];
154
155 fn from_seed(seed: Self::Seed) -> Self {
158 if seed[0] == 0 {
159 Self::cold_path_default()
160 } else {
161 Self::new_unchecked(seed[0])
162 }
163 }
164 }
165}