1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
#![no_std]
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![warn(clippy::missing_const_for_fn)]
#![warn(clippy::missing_inline_in_public_items)]
#![cfg_attr(docs_rs, feature(doc_cfg))]
//! Pseudo-random number generator crate.
//!
//! NOT FOR CRYPTOGRAPHIC PURPOSES.
//!
//! ## Using This Crate
//!
//! * Create a [PCG32] or [PCG32K] value as your generator.
//! * If you enable this crate's `getrandom` cargo feature then both types
//! will have constructor functions to handle seeding a generator from the
//! [getrandom](getrandom::getrandom) function.
//! * Call `next_u32` on the generator to get pseudo-random `u32` values.
//! * At your option, import the [Gen32] trait for various extension methods.
pub mod formulas;
use formulas::ieee754_random_f32;
mod pcg;
pub use pcg::*;
mod bounded_rand;
pub use bounded_rand::*;
/// A trait for pseudo-random number generators with 32-bit output per step.
pub trait Gen32 {
/// Makes the generator create the next output.
///
/// All `u32` values should have equal chance of occuring.
fn next_u32(&mut self) -> u32;
/// Gives a uniformly distributed value.
#[inline]
fn next_i32(&mut self) -> i32 {
self.next_u32() as i32
}
/// Gives a uniformly distributed value.
#[inline]
fn next_bool(&mut self) -> bool {
(self.next_u32() as i32) < 0
}
/// Gives a value in the range `0.0 ..= 1.0`
#[inline]
fn next_f32_unit(&mut self) -> f32 {
ieee754_random_f32(|| self.next_u32(), false)
}
/// Gives a value in the range `1 ..= 4`
#[inline]
fn d4(&mut self) -> i32 {
let base = self.next_u32() >> 30;
base as i32 + 1
}
/// Gives a value in the range `1 ..= 6`
#[inline]
fn d6(&mut self) -> i32 {
let base = BoundedRandU16::_6.sample(|| (self.next_u32() >> 16) as u16);
i32::from(base) + 1
}
/// Gives a value in the range `1 ..= 8`
#[inline]
fn d8(&mut self) -> i32 {
let base = self.next_u32() >> 29;
base as i32 + 1
}
/// Gives a value in the range `1 ..= 10`
#[inline]
fn d10(&mut self) -> i32 {
let base = BoundedRandU16::_10.sample(|| (self.next_u32() >> 16) as u16);
i32::from(base) + 1
}
/// Gives a value in the range `1 ..= 12`
#[inline]
fn d12(&mut self) -> i32 {
let base = BoundedRandU16::_12.sample(|| (self.next_u32() >> 16) as u16);
i32::from(base) + 1
}
/// Gives a value in the range `1 ..= 20`
#[inline]
fn d20(&mut self) -> i32 {
let base = BoundedRandU16::_20.sample(|| (self.next_u32() >> 16) as u16);
i32::from(base) + 1
}
}
impl Gen32 for PCG32 {
#[inline]
fn next_u32(&mut self) -> u32 {
PCG32::next_u32(self)
}
}
impl<const K: usize> Gen32 for PCG32K<K> {
#[inline]
fn next_u32(&mut self) -> u32 {
PCG32K::<K>::next_u32(self)
}
}