#![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",
html_root_url = "https://rust-random.github.io/rand/"
)]
#![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;
#[allow(unused)]
macro_rules! trace { ($($x:tt)*) => (
#[cfg(feature = "log")] {
log::trace!($($x)*)
}
) }
#[allow(unused)]
macro_rules! debug { ($($x:tt)*) => (
#[cfg(feature = "log")] {
log::debug!($($x)*)
}
) }
#[allow(unused)]
macro_rules! info { ($($x:tt)*) => (
#[cfg(feature = "log")] {
log::info!($($x)*)
}
) }
#[allow(unused)]
macro_rules! warn { ($($x:tt)*) => (
#[cfg(feature = "log")] {
log::warn!($($x)*)
}
) }
#[allow(unused)]
macro_rules! error { ($($x:tt)*) => (
#[cfg(feature = "log")] {
log::error!($($x)*)
}
) }
pub use rand_core;
pub use rand_core::{CryptoRng, RngCore, SeedableRng, TryCryptoRng, TryRngCore};
pub mod distr;
pub mod prelude;
mod rng;
pub mod rngs;
pub mod seq;
#[cfg(feature = "thread_rng")]
pub use crate::rngs::thread::rng;
#[cfg(feature = "thread_rng")]
#[deprecated(since = "0.9.0", note = "Renamed to `rng`")]
#[inline]
pub fn thread_rng() -> crate::rngs::ThreadRng {
rng()
}
pub use rng::{Fill, Rng};
#[cfg(feature = "thread_rng")]
use crate::distr::{Distribution, StandardUniform};
#[cfg(feature = "std")]
pub struct RngReader<R: TryRngCore>(pub R);
#[cfg(feature = "std")]
impl<R: TryRngCore> 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: TryRngCore> 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::*;
pub fn rng(seed: u64) -> impl RngCore {
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 RngCore for StepRng {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
fn next_u64(&mut self) -> u64 {
let res = self.0;
self.0 = self.0.wrapping_add(self.1);
res
}
fn fill_bytes(&mut self, dst: &mut [u8]) {
rand_core::le::fill_bytes_via_next(self, dst)
}
}
#[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);
}
}