use devela::convert::{u16_into_u8_le, u32_into_u8_le};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Xyza8a {
x: u8,
y: u8,
z: u8,
a: u8,
}
impl Default for Xyza8a {
fn default() -> Self {
Self::new(Self::DEFAULT_SEED)
}
}
impl Xyza8a {
const DEFAULT_SEED: [u8; 4] = [0xDE, 0xFA, 0x00, 0x17];
}
impl Xyza8a {
#[inline]
pub const fn new(seeds: [u8; 4]) -> Self {
Self {
x: seeds[0],
y: seeds[1],
z: seeds[2],
a: seeds[3],
}
}
#[inline(always)]
#[must_use]
pub const fn current_u8(&self) -> u8 {
self.a
}
#[inline]
pub fn next_u8(&mut self) -> u8 {
let t = self.x ^ (self.x << 4);
self.x = self.y;
self.y = self.z;
self.z = self.a;
self.a = self.z ^ t ^ (self.z >> 1) ^ (t << 1);
self.a
}
#[inline]
#[must_use]
pub const fn next_new(&self) -> Self {
let mut new = *self;
let t = new.x ^ (new.x << 4);
new.x = new.y;
new.y = new.z;
new.z = new.a;
new.a = new.z ^ t ^ (new.z >> 1) ^ (t << 1);
new
}
}
impl Xyza8a {
#[inline]
pub const fn new1_u32(seed: u32) -> Self {
Self::new(u32_into_u8_le(seed))
}
#[inline]
pub const fn new2_u16(seeds: [u16; 2]) -> Self {
let [x, y] = u16_into_u8_le(seeds[0]);
let [z, a] = u16_into_u8_le(seeds[1]);
Self::new([x, y, z, a])
}
#[inline(always)]
pub const fn new4_u8(seeds: [u8; 4]) -> Self {
Self::new(seeds)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Xyza8b {
x: u8,
y: u8,
z: u8,
a: u8,
}
impl Default for Xyza8b {
fn default() -> Self {
Self::new(Self::DEFAULT_SEED)
}
}
impl Xyza8b {
const DEFAULT_SEED: [u8; 4] = [0xDE, 0xFA, 0x00, 0x17];
}
impl Xyza8b {
#[inline]
pub const fn new(seeds: [u8; 4]) -> Self {
Self {
x: seeds[0],
y: seeds[1],
z: seeds[2],
a: seeds[3],
}
}
#[inline(always)]
pub const fn current_u8(&self) -> u8 {
self.a
}
#[inline]
pub fn next_u8(&mut self) -> u8 {
let t = self.x ^ (self.x >> 1);
self.x = self.y;
self.y = self.z;
self.z = self.a;
self.a = self.z ^ t ^ (self.z >> 3) ^ (t << 1);
self.a
}
#[inline]
pub const fn next_new(&self) -> Self {
let mut new = *self;
let t = new.x ^ (new.x >> 1);
new.x = new.y;
new.y = new.z;
new.z = new.a;
new.a = new.z ^ t ^ (new.z >> 3) ^ (t << 1);
new
}
}
impl Xyza8b {
#[inline]
pub const fn new1_u32(seed: u32) -> Self {
Self::new(u32_into_u8_le(seed))
}
#[inline]
pub const fn new2_u16(seeds: [u16; 2]) -> Self {
let [x, y] = u16_into_u8_le(seeds[0]);
let [z, b] = u16_into_u8_le(seeds[1]);
Self::new([x, y, z, b])
}
#[inline(always)]
pub const fn new4_u8(seeds: [u8; 4]) -> Self {
Self::new(seeds)
}
}
#[cfg(feature = "rand_core")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "rand_core")))]
mod impl_rand {
use super::{Xyza8a, Xyza8b};
use rand_core::{Error, RngCore, SeedableRng};
impl RngCore for Xyza8a {
fn next_u32(&mut self) -> u32 {
u32::from_le_bytes([
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
])
}
fn next_u64(&mut self) -> u64 {
u64::from_le_bytes([
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
])
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
for byte in dest {
*byte = self.next_u8();
}
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for Xyza8a {
type Seed = [u8; 4];
fn from_seed(seeds: Self::Seed) -> Self {
Self::new(seeds)
}
}
impl RngCore for Xyza8b {
fn next_u32(&mut self) -> u32 {
u32::from_le_bytes([
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
])
}
fn next_u64(&mut self) -> u64 {
u64::from_le_bytes([
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8(),
])
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
for byte in dest {
*byte = self.next_u8();
}
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for Xyza8b {
type Seed = [u8; 4];
fn from_seed(seeds: Self::Seed) -> Self {
Self::new(seeds)
}
}
}