use rand::RngCore;
use std::time::SystemTime;
use std::{fmt::Display, time::UNIX_EPOCH};
const MASK: u32 = 1 << 16;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct R30 {
pub state: u32,
}
impl R30 {
#[inline(always)]
pub fn new(seed: u32) -> Self {
R30 { state: seed }
}
#[inline(always)]
pub fn center() -> Self {
R30 { state: MASK }
}
#[inline(always)]
pub fn evolve(&mut self) {
let left = self.state.rotate_left(1);
let right = self.state.rotate_right(1);
self.state = left ^ (self.state | right);
}
#[inline(always)]
pub fn next_bool(&mut self) -> bool {
let bit: bool = (self.state & MASK) != 0;
self.evolve();
bit
}
#[inline(always)]
pub fn next_u32(&mut self) -> u32 {
let mut bits = 0u32;
for i in 0..32 {
let bit = self.next_bool() as u32;
bits |= bit << i;
}
bits
}
#[inline(always)]
pub fn next_u64(&mut self) -> u64 {
let mut bits = 0u64;
for i in 0..64 {
let bit = self.next_bool() as u64;
bits |= bit << i;
}
bits
}
#[inline(always)]
pub fn next_u8(&mut self) -> u8 {
let mut bits = 0u8;
for i in 0..8 {
let bit = self.next_bool() as u8;
bits |= bit << i;
}
bits
}
#[inline(always)]
pub fn next_i32(&mut self) -> i32 {
self.next_u32() as i32
}
#[inline(always)]
pub fn next_i64(&mut self) -> i64 {
self.next_u64() as i64
}
#[inline(always)]
pub fn next_f32(&mut self) -> f32 {
self.next_u32() as f32 / u32::MAX as f32
}
#[inline(always)]
pub fn next_f64(&mut self) -> f64 {
self.next_u64() as f64 / u64::MAX as f64
}
#[inline(always)]
pub fn next_u64_in(&mut self, a: u64, b: u64) -> u64 {
let y: u64 = self.next_u64();
return y % (b + 1 - a) + a;
}
#[inline(always)]
pub fn next_u32_in(&mut self, a: u32, b: u32) -> u32 {
let y: u32 = self.next_u32();
return y % (b + 1 - a) + a;
}
pub fn rand_choice<'a, T>(&'a mut self, xs: &'a Vec<T>) -> &T {
let ix: usize = self.next_u64_in(0, xs.len() as u64 - 1) as usize;
return &xs[ix];
}
}
impl Default for R30 {
fn default() -> Self {
let mut time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Fucky wucky in computing distance since UNIX_EPOCH UWU")
.as_secs();
time *= time;
R30 { state: time as u32 }
}
}
impl RngCore for R30 {
fn next_u32(&mut self) -> u32 {
self.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.next_u64()
}
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<(), rand::Error> {
Ok(self.fill_bytes(dest))
}
}
impl Display for R30 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.state)
}
}