#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
#![no_std]
#![cfg_attr(feature = "simd_support", feature(portable_simd))]
#![cfg_attr(
all(feature = "simd_support", target_feature = "avx512bw"),
feature(stdarch_x86_avx512)
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![allow(
clippy::float_cmp,
clippy::neg_cmp_op_on_partial_ord,
clippy::nonminimal_bool
)]
#![deny(clippy::undocumented_unsafe_blocks)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub use rand_core;
pub use rand_core::{CryptoRng, Rng, SeedableRng, TryCryptoRng, TryRng};
#[macro_use]
mod log_macros;
pub mod distr;
pub mod prelude;
mod rng;
pub mod rngs;
pub mod seq;
#[cfg(feature = "thread_rng")]
pub use crate::rngs::thread::rng;
pub use rng::{Fill, RngExt};
#[cfg(feature = "thread_rng")]
use crate::distr::{Distribution, StandardUniform};
#[cfg(feature = "sys_rng")]
pub fn make_rng<R: SeedableRng>() -> R {
#[cfg(feature = "thread_rng")]
{
R::from_rng(&mut rng())
}
#[cfg(not(feature = "thread_rng"))]
{
R::try_from_rng(&mut rngs::SysRng).expect("unexpected failure from SysRng")
}
}
#[cfg(feature = "std")]
pub struct RngReader<R: TryRng>(pub R);
#[cfg(feature = "std")]
impl<R: TryRng> std::io::Read for RngReader<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
self.0
.try_fill_bytes(buf)
.map_err(|err| std::io::Error::other(std::format!("RNG error: {err}")))?;
Ok(buf.len())
}
}
#[cfg(feature = "std")]
impl<R: TryRng> std::fmt::Debug for RngReader<R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("RngReader").finish()
}
}
#[cfg(feature = "thread_rng")]
#[inline]
pub fn random<T>() -> T
where
StandardUniform: Distribution<T>,
{
rng().random()
}
#[cfg(feature = "thread_rng")]
#[inline]
pub fn random_iter<T>() -> distr::Iter<StandardUniform, rngs::ThreadRng, T>
where
StandardUniform: Distribution<T>,
{
rng().random_iter()
}
#[cfg(feature = "thread_rng")]
#[inline]
pub fn random_range<T, R>(range: R) -> T
where
T: distr::uniform::SampleUniform,
R: distr::uniform::SampleRange<T>,
{
rng().random_range(range)
}
#[cfg(feature = "thread_rng")]
#[inline]
#[track_caller]
pub fn random_bool(p: f64) -> bool {
rng().random_bool(p)
}
#[cfg(feature = "thread_rng")]
#[inline]
#[track_caller]
pub fn random_ratio(numerator: u32, denominator: u32) -> bool {
rng().random_ratio(numerator, denominator)
}
#[cfg(feature = "thread_rng")]
#[inline]
#[track_caller]
pub fn fill<T: Fill>(dest: &mut [T]) {
Fill::fill_slice(dest, &mut rng())
}
#[cfg(test)]
mod test {
use super::*;
use core::convert::Infallible;
pub fn rng(seed: u64) -> impl Rng {
const INC: u64 = 11634580027462260723;
rand_pcg::Pcg32::new(seed, INC)
}
pub fn const_rng(x: u64) -> StepRng {
StepRng(x, 0)
}
pub fn step_rng(x: u64, increment: u64) -> StepRng {
StepRng(x, increment)
}
#[derive(Clone)]
pub struct StepRng(u64, u64);
impl TryRng for StepRng {
type Error = Infallible;
fn try_next_u32(&mut self) -> Result<u32, Infallible> {
self.try_next_u64().map(|x| x as u32)
}
fn try_next_u64(&mut self) -> Result<u64, Infallible> {
let res = self.0;
self.0 = self.0.wrapping_add(self.1);
Ok(res)
}
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> {
rand_core::utils::fill_bytes_via_next_word(dst, || self.try_next_u64())
}
}
#[cfg(feature = "std")]
#[test]
fn rng_reader() {
use std::io::Read;
let mut rng = StepRng(255, 1);
let mut buf = [0u8; 24];
let expected = [
255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
];
RngReader(&mut rng).read_exact(&mut buf).unwrap();
assert_eq!(&buf, &expected);
RngReader(StepRng(255, 1)).read_exact(&mut buf).unwrap();
assert_eq!(&buf, &expected);
}
#[test]
#[cfg(feature = "thread_rng")]
fn test_random() {
let _n: u64 = random();
let _f: f32 = random();
#[allow(clippy::type_complexity)]
let _many: (
(),
[(u32, bool); 3],
(u8, i8, u16, i16, u32, i32, u64, i64),
(f32, (f64, (f64,))),
) = random();
}
#[test]
#[cfg(feature = "thread_rng")]
fn test_range() {
let _n: usize = random_range(42..=43);
let _f: f32 = random_range(42.0..43.0);
}
}