#![cfg_attr(not(test), no_std)]
#[cfg(feature = "std")]
extern crate std;
fn wrapping_next_power_of_two_u32(x: u32) -> u32 {
const H: u32 = 1 << 31;
if x <= H {x.next_power_of_two()} else {0}
}
fn wrapping_next_power_of_two_u64(x: u64) -> u64 {
const H: u64 = 1 << 63;
if x <= H {x.next_power_of_two()} else {0}
}
pub trait Rand: Sized {
fn from_seed(seed: u64) -> Self;
#[cfg(feature = "std")]
fn from_time() -> Self {
use std::time::SystemTime;
let time_seed = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_else(|e| e.duration()).as_micros() as u64;
Self::from_seed(time_seed)
}
fn rand_u32(&mut self) -> u32;
#[inline]
fn rand_u8(&mut self) -> u8 {
self.rand_u32() as u8
}
#[inline]
fn rand_u16(&mut self) -> u16 {
self.rand_u32() as u16
}
#[inline]
fn rand_u64(&mut self) -> u64 {
(self.rand_u32() as u64) << 32 | (self.rand_u32() as u64)
}
#[cfg(target_pointer_width = "32")]
#[inline]
fn rand_usize(&mut self) -> usize {
self.rand_u32() as usize
}
#[cfg(target_pointer_width = "64")]
#[inline]
fn rand_usize(&mut self) -> usize {
self.rand_u64() as usize
}
fn rand_bounded_u32(&mut self, m: u32) -> u32 {
let mask = wrapping_next_power_of_two_u32(m).wrapping_sub(1);
loop {
let x = mask & self.rand_u32();
if x < m {return x;}
}
}
fn rand_bounded_u64(&mut self, m: u64) -> u64 {
let mask = wrapping_next_power_of_two_u64(m).wrapping_sub(1);
loop {
let x = mask & self.rand_u64();
if x < m {return x;}
}
}
#[cfg(target_pointer_width = "32")]
fn rand_bounded_usize(&mut self, m: usize) -> usize {
self.rand_bounded_u32(m as u32) as usize
}
#[cfg(target_pointer_width = "64")]
fn rand_bounded_usize(&mut self, m: usize) -> usize {
self.rand_bounded_u64(m as u64) as usize
}
fn rand_range_u32(&mut self, a: u32, b: u32) -> u32 {
a + self.rand_bounded_u32(b - a)
}
fn rand_range_u64(&mut self, a: u64, b: u64) -> u64 {
a + self.rand_bounded_u64(b - a)
}
fn rand_range_i32(&mut self, a: i32, b: i32) -> i32 {
a + self.rand_bounded_u32((b - a) as u32) as i32
}
fn rand_range_i64(&mut self, a: i64, b: i64) -> i64 {
a + self.rand_bounded_u64((b - a) as u64) as i64
}
fn rand_f32(&mut self) -> f32 {
self.rand_u32() as f32 * 2.3283064E-10
}
fn rand_f64(&mut self) -> f64 {
self.rand_u32() as f64 * 2.3283064365386963E-10
}
#[cfg(feature = "std")]
fn rand_normal_f64(&mut self, mu: f64, sigma: f64) -> f64 {
loop {
let u = 2.0*self.rand_f64() - 1.0;
let v = 2.0*self.rand_f64() - 1.0;
let s = u*u + v*v;
if s < 1.0 && s > 0.0 {
return mu + sigma*u*f64::sqrt(-2.0*f64::ln(s)/s);
}
}
}
fn choice<'a, T>(&mut self, a: &'a [T]) -> &'a T {
&a[self.rand_bounded_usize(a.len())]
}
fn shuffle<T>(&mut self, a: &mut [T]) {
if a.is_empty() {return;}
let mut i = a.len() - 1;
while i > 0 {
let j = self.rand_bounded_usize(i + 1);
a.swap(i, j);
i -= 1;
}
}
fn fill(&mut self, a: &mut[u8]) {
let mut x = self.rand_u32();
let mut count = 3;
for p in a {
*p = x as u8;
if count == 0 {
x = self.rand_u32();
count = 3;
} else {
x >>= 8;
count -= 1;
}
}
}
}
pub fn rand_iter<T: 'static, Generator: Rand>(
rng: &mut Generator,
rand: fn(&mut Generator) -> T
) -> impl '_ + Iterator<Item = T>
{
core::iter::from_fn(move || Some(rand(rng)))
}
pub struct Rng {
state: (u64, u64)
}
impl Rand for Rng {
fn from_seed(seed: u64) -> Self {
Self {state: (
seed ^ 0xf4dbdf2183dcefb7, seed ^ 0x1ad5be0d6dd28e9b )}
}
fn rand_u64(&mut self) -> u64 {
let (mut x, y) = self.state;
self.state.0 = y;
x ^= x << 23;
self.state.1 = x ^ y ^ (x >> 17) ^ (y >> 26);
self.state.1.wrapping_add(y)
}
#[inline]
fn rand_u32(&mut self) -> u32 {
(self.rand_u64() >> 32) as u32
}
}
impl Rng {
pub fn iter<T: 'static>(&mut self, rand: fn(&mut Self) -> T)
-> impl '_ + Iterator<Item = T>
{
rand_iter(self, rand)
}
}
#[cfg(test)]
mod tests {
use crate::{Rng, Rand};
fn rng_test<Generator: Rand>() {
let mut rng = Generator::from_seed(0);
println!("{:?}", rng.rand_range_u32(1, 6));
}
#[test]
fn test0() {
rng_test::<Rng>();
}
}