devela/num/prob/rand/prng/
xabc.rs1use crate::{ConstInit, Own, whilst};
7use crate::{Infallible, InfallibleResult, RandQualities, RandSeedable, RandTry};
8
9#[doc = crate::_tags!(rand)]
10#[doc = crate::_doc_meta!{location("num/prob/rand")}]
12#[doc = crate::_doc_vendor!("Xabc")]
42#[must_use]
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub struct Xabc {
45 a: u8,
46 b: u8,
47 c: u8,
48 x: u8,
49}
50
51impl Default for Xabc {
53 fn default() -> Self {
54 Self::INIT
55 }
56}
57impl ConstInit for Xabc {
59 const INIT: Self = Self::new(Self::DEFAULT_SEED);
60}
61
62impl Xabc {
64 #[doc(hidden)]
65 pub const DEFAULT_SEED: [u8; 3] = [0xDE, 0xFA, 0x17];
66}
67
68impl Xabc {
69 pub const fn new(seeds: [u8; 3]) -> Self {
71 let a = seeds[0];
72 let b = seeds[1];
73 let c = seeds[2];
74 let x = 1;
75 let a = a ^ c ^ x;
76 let b = b.wrapping_add(a);
77 let c = c.wrapping_add(b >> 1) ^ a;
78 Self { a, b, c, x }
79 }
80
81 pub const fn reseed(&mut self, seeds: [u8; 3]) {
83 self.a ^= seeds[0];
85 self.b ^= seeds[1];
86 self.c ^= seeds[2];
87
88 self.x += 1;
89 self.a = self.a ^ self.c ^ self.x;
90 self.b = self.b.wrapping_add(self.a);
91 self.c = self.c.wrapping_add(self.b >> 1) ^ self.a;
92 }
93
94 #[must_use]
95 pub const fn inner_state(self) -> [u8; 4] {
97 [self.a, self.b, self.c, self.x]
98 }
99 pub const fn from_state(state: [u8; 4]) -> Self {
101 Self { a: state[0], b: state[1], c: state[2], x: state[3] }
102 }
103
104 #[must_use]
106 pub const fn current_u8(&self) -> u8 {
107 self.c
108 }
109 #[must_use]
111 pub const fn next_u8(&mut self) -> u8 {
112 self.x = self.x.wrapping_add(1);
114 self.a = self.a ^ self.c ^ self.x;
116 self.b = self.b.wrapping_add(self.a);
118 self.c = self.c.wrapping_add(self.b >> 1) ^ self.a;
121 self.c
122 }
123
124 pub const fn peek_next_state(&self) -> Self {
126 let [mut a, mut b, mut c, mut x] = [self.a, self.b, self.c, self.x];
127 x += 1;
128 a = a ^ c ^ x;
129 b = b.wrapping_add(a);
130 c = c.wrapping_add(b >> 1) ^ a;
131 Self { a, b, c, x }
132 }
133
134 pub const fn own_next_u8(self) -> Own<Self, u8> {
136 let s = self.peek_next_state();
137 let v = s.current_u8();
138 Own::new(s, v)
139 }
140 pub const fn fill_bytes(&mut self, buffer: &mut [u8]) {
142 whilst! { i in 0..buffer.len(); {
143 buffer[i] = self.next_u8();
144 }}
145 }
146}
147
148impl Xabc {
150 pub const fn new3_u8(seeds: [u8; 3]) -> Self {
154 Self::new(seeds)
155 }
156 pub const fn next_u16(&mut self) -> u16 {
158 u16::from_le_bytes([self.next_u8(), self.next_u8()])
159 }
160 pub const fn next_u32(&mut self) -> u32 {
162 u32::from_le_bytes([self.next_u8(), self.next_u8(), self.next_u8(), self.next_u8()])
163 }
164 pub const fn next_u64(&mut self) -> u64 {
166 u64::from_le_bytes([
167 self.next_u8(),
168 self.next_u8(),
169 self.next_u8(),
170 self.next_u8(),
171 self.next_u8(),
172 self.next_u8(),
173 self.next_u8(),
174 self.next_u8(),
175 ])
176 }
177}
178
179crate::items! {
180 impl RandTry for Xabc {
181 type Error = Infallible;
182 const RAND_OUTPUT_BITS: u32 = 8;
183 const RAND_STATE_BITS: u32 = 32;
184 const RAND_QUALITIES: RandQualities = RandQualities::WEAK_PRNG;
185 fn rand_try_next_u8(&mut self) -> InfallibleResult<u8> { Ok(self.next_u8()) }
186 fn rand_try_next_u16(&mut self) -> InfallibleResult<u16> { Ok(self.next_u16()) }
187 fn rand_try_next_u32(&mut self) -> InfallibleResult<u32> { Ok(self.next_u32()) }
188 fn rand_try_next_u64(&mut self) -> InfallibleResult<u64> { Ok(self.next_u64()) }
189 fn rand_try_fill_bytes(&mut self, buffer: &mut [u8]) -> InfallibleResult<()> {
190 self.fill_bytes(buffer); Ok(())
191 }
192 }
193 impl RandSeedable for Xabc {
194 type RandSeed = [u8; 3];
195 #[inline(always)]
196 fn rand_from_seed(seed: Self::RandSeed) -> Self { Self::new(seed) }
197 }
198}
199crate::__impl_dep_rand_core!(Xabc);