//! A global, thread-local random number generator.
usecrate::Rng;
use std::cell::Cell; use std::ops::RangeBounds; use std::vec::Vec;
// Chosen by fair roll of the dice. const DEFAULT_RNG_SEED: u64 = 0xef6f79ed30ba75a;
impl Default for Rng { /// Initialize the `Rng` from the system's random number generator. /// /// This is equivalent to [`Rng::new()`]. #[inline] fn default() -> Rng {
Rng::new()
}
}
impl Rng { /// Creates a new random number generator. #[inline] pubfn new() -> Rng {
try_with_rng(Rng::fork).unwrap_or_else(|_| Rng::with_seed(0x4d595df4d0f33173))
}
}
/// Run an operation with the current thread-local generator. #[inline] fn with_rng<R>(f: impl FnOnce(&mut Rng) -> R) -> R {
RNG.with(|rng| { let current = rng.replace(Rng(0));
letmut restore = RestoreOnDrop { rng, current };
f(&mut restore.current)
})
}
/// Try to run an operation with the current thread-local generator. #[inline] fn try_with_rng<R>(f: impl FnOnce(&mut Rng) -> R) -> Result<R, std::thread::AccessError> {
RNG.try_with(|rng| { let current = rng.replace(Rng(0));
letmut restore = RestoreOnDrop { rng, current };
f(&mut restore.current)
})
}
/// Make sure the original RNG is restored even on panic. struct RestoreOnDrop<'a> {
rng: &'a Cell<Rng>,
current: Rng,
}
impl Drop for RestoreOnDrop<'_> { fn drop(&mutself) { self.rng.set(Rng(self.current.0));
}
}
/// Initializes the thread-local generator with the given seed. #[inline] pubfn seed(seed: u64) {
with_rng(|r| r.seed(seed));
}
/// Gives back **current** seed that is being held by the thread-local generator. #[inline] pubfn get_seed() -> u64 {
with_rng(|r| r.get_seed())
}
/// Generates a random `bool`. #[inline] pubfn bool() -> bool {
with_rng(|r| r.bool())
}
/// Generates a random `char` in ranges a-z and A-Z. #[inline] pubfn alphabetic() -> char {
with_rng(|r| r.alphabetic())
}
/// Generates a random `char` in ranges a-z, A-Z and 0-9. #[inline] pubfn alphanumeric() -> char {
with_rng(|r| r.alphanumeric())
}
/// Generates a random `char` in range a-z. #[inline] pubfn lowercase() -> char {
with_rng(|r| r.lowercase())
}
/// Generates a random `char` in range A-Z. #[inline] pubfn uppercase() -> char {
with_rng(|r| r.uppercase())
}
/// Choose an item from an iterator at random. /// /// This function may have an unexpected result if the `len()` property of the /// iterator does not match the actual number of items in the iterator. If /// the iterator is empty, this returns `None`. #[inline] pubfn choice<I>(iter: I) -> Option<I::Item> where
I: IntoIterator,
I::IntoIter: ExactSizeIterator,
{
with_rng(|r| r.choice(iter))
}
/// Generates a random digit in the given `base`. /// /// Digits are represented by `char`s in ranges 0-9 and a-z. /// /// Panics if the base is zero or greater than 36. #[inline] pubfn digit(base: u32) -> char {
with_rng(|r| r.digit(base))
}
macro_rules! integer {
($t:tt, $doc:tt) => { #[doc = $doc] /// /// Panics if the range is empty. #[inline] pubfn $t(range: impl RangeBounds<$t>) -> $t {
with_rng(|r| r.$t(range))
}
};
}
integer!(u8, "Generates a random `u8` in the given range.");
integer!(i8, "Generates a random `i8` in the given range.");
integer!(u16, "Generates a random `u16` in the given range.");
integer!(i16, "Generates a random `i16` in the given range.");
integer!(u32, "Generates a random `u32` in the given range.");
integer!(i32, "Generates a random `i32` in the given range.");
integer!(u64, "Generates a random `u64` in the given range.");
integer!(i64, "Generates a random `i64` in the given range.");
integer!(u128, "Generates a random `u128` in the given range.");
integer!(i128, "Generates a random `i128` in the given range.");
integer!(usize, "Generates a random `usize` in the given range.");
integer!(isize, "Generates a random `isize` in the given range.");
integer!(char, "Generates a random `char` in the given range.");
/// Generates a random `f32` in range `0..1`. pubfn f32() -> f32 {
with_rng(|r| r.f32())
}
/// Generates a random `f64` in range `0..1`. pubfn f64() -> f64 {
with_rng(|r| r.f64())
}
/// Collects `amount` values at random from the iterator into a vector. pubfn choose_multiple<T: Iterator>(source: T, amount: usize) -> Vec<T::Item> {
with_rng(|rng| rng.choose_multiple(source, amount))
}
#[cfg(not(all(
any(target_arch = "wasm32", target_arch = "wasm64"),
target_os = "unknown"
)))] fn random_seed() -> Option<u64> { use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::thread; use std::time::Instant;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.