#![doc = include_str!("../README.md")]
#![no_std]
#[cfg(feature = "std")]
extern crate std;
use core::fmt::Debug;
use core::fmt::Formatter;
use core::fmt;
use core::hint::cold_path;
use core::hint::select_unpredictable;
use core::mem::MaybeUninit;
use core::num::NonZeroU128;
use core::num::NonZeroU32;
use core::num::NonZeroU64;
#[derive(Clone)]
pub struct Rng { state: NonZeroU128 }
#[inline(always)]
const fn concat(x: u64, y: u64) -> u128 {
x as u128 ^ (y as u128) << 64
}
#[inline(always)]
const fn lo(x: u128) -> u64 {
x as u64
}
#[inline(always)]
const fn hi(x: u128) -> u64 {
(x >> 64) as u64
}
#[inline(always)]
const fn asr(x: u64, a: usize) -> u64 {
((x as i64) >> a) as u64
}
#[inline(always)]
const fn lsl(x: u64, a: usize) -> u64 {
x << a
}
#[inline(always)]
const fn mulhi(x: u64, y: u64) -> u64 {
((x as u128 * y as u128) >> 64) as u64
}
impl Rng {
pub const fn new(seed: NonZeroU128) -> Self {
const M: u128 = 0x93c4_67e3_7db0_c7a4_d1be_3f81_0152_cb57;
let x = seed.get();
let x = x.wrapping_mul(M);
let x = x.swap_bytes();
let x = x.wrapping_mul(M);
let x = x.swap_bytes();
let x = x.wrapping_mul(M);
let s = unsafe { NonZeroU128::new_unchecked(x) };
Self { state: s }
}
pub const fn from_u64(seed: u64) -> Self {
let s = concat(seed, 1);
let s = unsafe { NonZeroU128::new_unchecked(s) };
Self::new(s)
}
#[inline(always)]
pub const fn state(&self) -> NonZeroU128 {
self.state
}
#[inline(always)]
pub const fn from_state(state: NonZeroU128) -> Self {
Self { state }
}
#[cfg(feature = "getrandom")]
#[inline(never)]
#[cold]
pub fn from_operating_system() -> Self {
let mut buf = [0; 16];
getrandom::fill(&mut buf).expect("getrandom::fill failed!");
let s = 1 | u128::from_le_bytes(buf);
let s = unsafe { NonZeroU128::new_unchecked(s) };
Self { state: s }
}
#[inline(always)]
pub fn bernoulli(&mut self, p: f64) -> bool {
let n = (p * f64::from_bits(0x43f0_0000_0000_0000)) as u64;
let x = self.u64();
x < n || n == u64::MAX
}
#[inline(always)]
pub fn bool(&mut self) -> bool {
self.i64() < 0
}
#[inline(always)]
pub fn i32(&mut self) -> i32 {
self.u64() as i32
}
#[inline(always)]
pub fn i64(&mut self) -> i64 {
self.u64() as i64
}
#[inline(always)]
pub fn i128(&mut self) -> i128 {
self.u128() as i128
}
#[inline(always)]
pub fn u32(&mut self) -> u32 {
self.u64() as u32
}
#[inline(always)]
pub fn u64(&mut self) -> u64 {
let s = self.state.get();
let x = lo(s);
let y = hi(s);
let s = concat(y ^ asr(x, 4), x ^ lsl(y, 7));
let s = unsafe { NonZeroU128::new_unchecked(s) };
self.state = s;
y.wrapping_add(x.wrapping_mul(x)) ^ mulhi(x, x)
}
#[inline(always)]
pub fn u128(&mut self) -> u128 {
let x = self.u64();
let y = self.u64();
concat(x, y)
}
#[inline(always)]
pub fn non_zero_u32(&mut self) -> NonZeroU32 {
loop {
if let Some(x) = NonZeroU32::new(self.u32()) {
break x
}
}
}
#[inline(always)]
pub fn non_zero_u64(&mut self) -> NonZeroU64 {
loop {
if let Some(x) = NonZeroU64::new(self.u64()) {
break x
}
}
}
#[inline(always)]
pub fn non_zero_u128(&mut self) -> NonZeroU128 {
loop {
if let Some(x) = NonZeroU128::new(self.u128()) {
break x
}
}
}
#[inline(always)]
pub fn bounded_u32(&mut self, n: u32) -> u32 {
let x = self.u64();
let n = n as u64;
let m = n + 1;
let a = mulhi(x, m);
let b = x.wrapping_mul(m);
if b.overflowing_add(n).1 {
debug_assert!(m != 0);
let mut r = b;
loop {
let y = self.u64();
let c = mulhi(y, m);
let d = y.wrapping_mul(m);
let s = r.overflowing_add(c);
let w = s.0;
let p = s.1;
if w != u64::MAX { break (a + p as u64) as u32 }
r = d;
cold_path();
}
} else {
a as u32
}
}
#[inline(always)]
pub fn bounded_u64(&mut self, n: u64) -> u64 {
let x = self.u64();
let m = n.wrapping_add(1);
let a = mulhi(x, m);
let b = x.wrapping_mul(m);
let u = select_unpredictable(m == 0, x, a);
if b.overflowing_add(n).1 {
debug_assert!(m != 0);
let mut r = b;
loop {
let y = self.u64();
let c = mulhi(y, m);
let d = y.wrapping_mul(m);
let s = r.overflowing_add(c);
let w = s.0;
let p = s.1;
if w != u64::MAX { break a + p as u64 }
r = d;
cold_path();
}
} else {
u
}
}
#[inline(always)]
pub fn bounded_usize(&mut self, n: usize) -> usize {
match const { usize::BITS } {
32 => self.bounded_u32(n as u32) as usize,
64 => self.bounded_u64(n as u64) as usize,
_ => unimplemented!(),
}
}
#[inline(always)]
pub fn range_i32(&mut self, a: i32, b: i32) -> i32 {
self.range_u32(a as u32, b as u32) as i32
}
#[inline(always)]
pub fn range_i64(&mut self, a: i64, b: i64) -> i64 {
self.range_u64(a as u64, b as u64) as i64
}
#[inline(always)]
pub fn range_isize(&mut self, a: isize, b: isize) -> isize {
self.range_usize(a as usize, b as usize) as isize
}
#[inline(always)]
pub fn range_u32(&mut self, a: u32, b: u32) -> u32 {
a.wrapping_add(self.bounded_u32(b.wrapping_sub(a)))
}
#[inline(always)]
pub fn range_u64(&mut self, a: u64, b: u64) -> u64 {
a.wrapping_add(self.bounded_u64(b.wrapping_sub(a)))
}
#[inline(always)]
pub fn range_usize(&mut self, a: usize, b: usize) -> usize {
a.wrapping_add(self.bounded_usize(b.wrapping_sub(a)))
}
#[inline(always)]
pub fn f32(&mut self) -> f32 {
let x = self.i64();
let x = f32::from_bits(0x2000_0000) * (x as f32);
x.abs()
}
#[inline(always)]
pub fn f64(&mut self) -> f64 {
let x = self.i64();
let x = f64::from_bits(0x3c00_0000_0000_0000) * (x as f64);
x.abs()
}
#[inline(always)]
pub fn biunit_f32(&mut self) -> f32 {
let x = self.i64();
let x = (x & 1) + (x >> 1);
f32::from_bits(0x2080_0000) * (x as f32)
}
#[inline(always)]
pub fn biunit_f64(&mut self) -> f64 {
let x = self.i64();
let x = (x & 1) + (x >> 1);
f64::from_bits(0x3c10_0000_0000_0000) * (x as f64)
}
#[inline(always)]
unsafe fn fill_unchecked_inlined(&mut self, dst: *mut u8, len: usize) {
let mut p = dst;
let mut n = len;
if n == 0 { return }
while n >= 17 {
let x = self.u64().to_le_bytes();
let y = self.u64().to_le_bytes();
unsafe { p.copy_from_nonoverlapping(&raw const x as _, 8) };
p = unsafe { p.add(8) };
n = n - 8;
unsafe { p.copy_from_nonoverlapping(&raw const y as _, 8) };
p = unsafe { p.add(8) };
n = n - 8;
}
if n >= 9 {
let x = self.u64().to_le_bytes();
unsafe { p.copy_from_nonoverlapping(&raw const x as _, 8) };
p = unsafe { p.add(8) };
n = n - 8;
}
let x = self.u64().to_le_bytes();
match n {
1 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 1) },
2 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 2) },
3 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 3) },
4 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 4) },
5 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 5) },
6 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 6) },
7 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 7) },
8 => unsafe { p.copy_from_nonoverlapping(&raw const x as _, 8) },
_ => unreachable!(),
}
}
pub fn fill(&mut self, dst: &mut [u8]) {
let n = dst.len();
unsafe { self.fill_unchecked(&raw mut *dst as _, n) };
}
pub unsafe fn fill_unchecked(&mut self, dst: *mut u8, len: usize) {
unsafe { self.fill_unchecked_inlined(dst, len) };
}
pub fn fill_uninit<'a>(&mut self, dst: &'a mut [MaybeUninit<u8>]) -> &'a mut [u8] {
let n = dst.len();
unsafe { self.fill_unchecked(&raw mut *dst as _, n) };
unsafe { dst.assume_init_mut() }
}
pub fn byte_array<const N: usize>(&mut self) -> [u8; N] {
let mut buf = [0; N];
unsafe { self.fill_unchecked_inlined(&raw mut buf as _, N) };
buf
}
pub fn shuffle<T>(&mut self, slice: &mut [T]) {
let n = slice.len();
if n >= 2 {
let p = &raw mut *slice as *mut T;
for i in 1 .. n {
let j = self.bounded_usize(i);
unsafe { p.add(i).swap(p.add(j)) };
}
}
}
}
impl Debug for Rng {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Rng").finish_non_exhaustive()
}
}
#[cfg(feature = "rand_core")]
impl rand_core::TryRng for Rng {
type Error = rand_core::Infallible;
#[inline(always)]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.u32())
}
#[inline(always)]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.u64())
}
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
self.fill(dst);
Ok(())
}
}
#[cfg(feature = "rand_core")]
impl rand_core::SeedableRng for Rng {
type Seed = [u8; 16];
#[inline(always)]
fn from_seed(seed: Self::Seed) -> Self {
let s = 1 | u128::from_le_bytes(seed);
let s = unsafe { NonZeroU128::new_unchecked(s) };
Self::from_state(s)
}
fn seed_from_u64(seed: u64) -> Self {
Self::from_u64(seed)
}
fn from_rng<T: rand_core::Rng + ?Sized>(g: &mut T) -> Self {
let Ok(x) = Self::try_from_rng(g);
x
}
fn try_from_rng<T: rand_core::TryRng + ?Sized>(g: &mut T) -> Result<Self, T::Error> {
let x = g.try_next_u64()?;
let y = g.try_next_u64()?;
let s = 1 | concat(x, y);
let s = unsafe { NonZeroU128::new_unchecked(s) };
Ok(Self::from_state(s))
}
}
#[cfg(feature = "thread_local")]
pub mod thread_local {
use std::cell::Cell;
use std::mem::MaybeUninit;
use std::num::NonZeroU128;
use std::num::NonZeroU32;
use std::num::NonZeroU64;
use std::thread_local;
use super::Rng;
thread_local! {
static RNG: Cell<Option<NonZeroU128>> = const {
Cell::new(None)
};
}
#[inline(always)]
fn with<T>(f: impl FnOnce(&mut Rng) -> T) -> T {
RNG.with(|state| {
let mut g =
match state.get() {
None => Rng::from_operating_system(),
Some(s) => Rng::from_state(s),
};
let x = f(&mut g);
state.set(Some(g.state()));
x
})
}
pub fn bernoulli(p: f64) -> bool {
with(|g| g.bernoulli(p))
}
pub fn bool() -> bool {
with(|g| g.bool())
}
pub fn i32() -> i32 {
with(|g| g.i32())
}
pub fn i64() -> i64 {
with(|g| g.i64())
}
pub fn i128() -> i128 {
with(|g| g.i128())
}
pub fn u32() -> u32 {
with(|g| g.u32())
}
pub fn u64() -> u64 {
with(|g| g.u64())
}
pub fn u128() -> u128 {
with(|g| g.u128())
}
pub fn non_zero_u32() -> NonZeroU32 {
with(|g| g.non_zero_u32())
}
pub fn non_zero_u64() -> NonZeroU64 {
with(|g| g.non_zero_u64())
}
pub fn non_zero_u128() -> NonZeroU128 {
with(|g| g.non_zero_u128())
}
pub fn bounded_u32(n: u32) -> u32 {
with(|g| g.bounded_u32(n))
}
pub fn bounded_u64(n: u64) -> u64 {
with(|g| g.bounded_u64(n))
}
pub fn bounded_usize(n: usize) -> usize {
with(|g| g.bounded_usize(n))
}
pub fn range_i32(a: i32, b: i32) -> i32 {
with(|g| g.range_i32(a, b))
}
pub fn range_i64(a: i64, b: i64) -> i64 {
with(|g| g.range_i64(a, b))
}
pub fn range_isize(a: isize, b: isize) -> isize {
with(|g| g.range_isize(a, b))
}
pub fn range_u32(a: u32, b: u32) -> u32 {
with(|g| g.range_u32(a, b))
}
pub fn range_u64(a: u64, b: u64) -> u64 {
with(|g| g.range_u64(a, b))
}
pub fn range_usize(a: usize, b: usize) -> usize {
with(|g| g.range_usize(a, b))
}
pub fn f32() -> f32 {
with(|g| g.f32())
}
pub fn f64() -> f64 {
with(|g| g.f64())
}
pub fn biunit_f32() -> f32 {
with(|g| g.biunit_f32())
}
pub fn biunit_f64() -> f64 {
with(|g| g.biunit_f64())
}
pub fn fill(dst: &mut [u8]) {
with(|g| g.fill(dst))
}
pub unsafe fn fill_unchecked(dst: *mut u8, len: usize) {
with(|g| unsafe { g.fill_unchecked(dst, len) })
}
pub fn fill_uninit(dst: &mut [MaybeUninit<u8>]) -> &mut [u8] {
with(|g| g.fill_uninit(dst))
}
pub fn byte_array<const N: usize>() -> [u8; N] {
with(|g| g.byte_array())
}
}