devela/num/rand/xorshift/
u8.rs1use crate::{ConstDefault, Own, xorshift_basis};
7
8#[doc = crate::TAG_RAND!()]
9#[must_use]
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub struct XorShift8<const A: usize = 3, const B: usize = 4, const C: usize = 2>(u8);
16
17impl<const A: usize, const B: usize, const C: usize> Default for XorShift8<A, B, C> {
19 fn default() -> Self {
20 Self::new_unchecked(Self::DEFAULT_SEED)
21 }
22}
23impl<const A: usize, const B: usize, const C: usize> ConstDefault for XorShift8<A, B, C> {
25 const DEFAULT: Self = Self::new_unchecked(Self::DEFAULT_SEED);
26}
27
28impl<const A: usize, const B: usize, const C: usize> XorShift8<A, B, C> {
30 const DEFAULT_SEED: u8 = 0xDE;
31
32 #[cold] #[allow(dead_code)] #[rustfmt::skip]
33 const fn cold_path_default() -> Self { Self::new_unchecked(Self::DEFAULT_SEED) }
34}
35
36impl<const A: usize, const B: usize, const C: usize> XorShift8<A, B, C> {
37 pub const fn new(seed: u8) -> Self {
44 debug_assert![A > 0 && A <= 7];
45 debug_assert![B > 0 && A <= 7];
46 debug_assert![C > 0 && A <= 7];
47 if seed == 0 { Self::cold_path_default() } else { Self(seed) }
48 }
49
50 pub const fn new_unchecked(seed: u8) -> Self {
59 debug_assert![A > 0 && A <= 7];
60 debug_assert![B > 0 && A <= 7];
61 debug_assert![C > 0 && A <= 7];
62 debug_assert![seed != 0, "Seed must be non-zero"];
63 Self(seed)
64 }
65
66 #[must_use]
67 pub const fn inner_state(self) -> u8 {
69 self.0
70 }
71 pub const fn from_state(state: u8) -> Self {
73 Self(state)
74 }
75
76 #[must_use]
78 pub const fn current_u8(&self) -> u8 {
79 self.0
80 }
81
82 pub fn next_u8(&mut self) -> u8 {
85 let mut x = self.0;
86 xorshift_basis!(x, 0, (A, B, C));
87 self.0 = x;
88 x
89 }
90
91 pub const fn peek_next_state(&self) -> Self {
93 let mut x = self.0;
94 xorshift_basis!(x, 0, (A, B, C));
95 Self(x)
96 }
97
98 pub const fn own_next_u8(self) -> Own<Self, u8> {
100 let s = self.peek_next_state();
101 let v = s.current_u8();
102 Own::new(s, v)
103 }
104}
105
106impl<const A: usize, const B: usize, const C: usize> XorShift8<A, B, C> {
108 pub const fn new1_u8(seed: u8) -> Self {
112 Self::new(seed)
113 }
114}
115
116#[cfg(feature = "dep_rand_core")]
117#[cfg_attr(nightly_doc, doc(cfg(feature = "dep_rand_core")))]
118mod impl_rand {
119 use super::XorShift8;
120 use crate::_dep::rand_core::{RngCore, SeedableRng};
121
122 impl<const A: usize, const B: usize, const C: usize> RngCore for XorShift8<A, B, C> {
123 fn next_u32(&mut self) -> u32 {
125 u32::from_le_bytes([self.next_u8(), self.next_u8(), self.next_u8(), self.next_u8()])
126 }
127
128 fn next_u64(&mut self) -> u64 {
130 u64::from_le_bytes([
131 self.next_u8(),
132 self.next_u8(),
133 self.next_u8(),
134 self.next_u8(),
135 self.next_u8(),
136 self.next_u8(),
137 self.next_u8(),
138 self.next_u8(),
139 ])
140 }
141
142 fn fill_bytes(&mut self, dest: &mut [u8]) {
143 for byte in dest {
144 *byte = self.next_u8();
145 }
146 }
147 }
148
149 impl<const A: usize, const B: usize, const C: usize> SeedableRng for XorShift8<A, B, C> {
150 type Seed = [u8; 1];
151
152 fn from_seed(seed: Self::Seed) -> Self {
155 if seed[0] == 0 {
156 Self::cold_path_default()
157 } else {
158 Self::new_unchecked(seed[0])
159 }
160 }
161 }
162}