use crate::entropy::EntropySource;
use crate::ranges::GenerateRange;
use crate::rng::Rng;
use crate::rng::{RangeFromRng, ValueFromRng};
use crate::xoshiro::Xoshiro256pp;
#[cfg(feature = "std")]
use crate::DefaultEntropy;
use crate::SplitMix;
pub struct SmallRng(Impl);
type Impl = Xoshiro256pp;
impl Rng for SmallRng {
#[inline]
fn random_u32(&mut self) -> u32 {
self.0.random_u32()
}
#[inline]
fn random_u64(&mut self) -> u64 {
self.0.random_u64()
}
}
impl SmallRng {
#[cfg(feature = "std")]
#[must_use]
pub fn new() -> Self {
Self(Impl::from_entropy(&mut DefaultEntropy::new()))
}
#[must_use]
pub fn from_entropy<T>(entropy_source: &mut T) -> Self
where
T: EntropySource,
{
Self(Impl::from_entropy(entropy_source))
}
#[must_use]
pub fn from_seed(seed: u64) -> Self {
Self(Impl::from_entropy(&mut SplitMix::new(seed)))
}
#[inline]
pub fn random<T>(&mut self) -> T
where
T: ValueFromRng,
Self: Sized,
{
self.0.random()
}
#[inline]
pub fn range<T>(&mut self, range: impl Into<GenerateRange<T>>) -> T
where
T: RangeFromRng,
Self: Sized,
{
self.0.range(range)
}
#[inline]
pub fn iter<'a, T>(&'a mut self) -> impl Iterator<Item = T> + 'a
where
T: ValueFromRng + 'a,
Self: Sized,
{
self.0.iter()
}
#[inline]
pub fn fill<T>(&mut self, destination: &mut [T])
where
T: ValueFromRng,
Self: Sized,
{
self.0.fill(destination);
}
#[inline]
pub fn fill_u8(&mut self, destination: &mut [u8])
where
Self: Sized,
{
self.0.fill_u8(destination);
}
#[inline]
pub fn shuffle<T>(&mut self, target: &mut [T])
where
Self: Sized,
{
self.0.shuffle(target);
}
}
#[cfg(feature = "std")]
impl Default for SmallRng {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use crate::{Rng, SmallRng, SplitMix};
#[test]
fn test_forwarding() {
let mut rng = SmallRng::from_seed(12345678);
assert_ne!(rng.random_u32(), rng.random_u32());
assert_ne!(rng.random_u64(), rng.random_u64());
assert_ne!(rng.random::<u16>(), rng.random::<u16>());
assert_ne!(rng.random::<u32>(), rng.random::<u32>());
assert_ne!(rng.random::<u64>(), rng.random::<u64>());
let mut rng = SmallRng::from_entropy(&mut SplitMix::new(12345678));
assert_ne!(rng.range::<u32>(0..42), rng.range::<u32>(0..42));
{
let mut i = rng.iter::<u128>();
i.next();
assert_ne!(i.next(), i.next());
}
let mut a1 = [0_u8; 32];
let mut a2 = [0_u8; 32];
rng.fill(&mut a1);
rng.fill(&mut a2);
assert_ne!(a1, a2);
a2 = a1;
rng.fill_u8(&mut a1);
rng.fill_u8(&mut a2);
assert_ne!(a1, a2);
a2 = a1;
rng.shuffle(&mut a2);
assert_ne!(a1, a2);
}
#[test]
fn from_seed_generates_reproducible_values() {
let mut rng1 = SmallRng::from_seed(12345678);
let mut rng2 = SmallRng::from_seed(12345678);
assert_eq!(rng1.random_u64(), rng2.random_u64());
}
#[test]
fn from_entropy_generates_reproducible_values() {
let mut rng1 = SmallRng::from_entropy(&mut SplitMix::new(12345678));
let mut rng2 = SmallRng::from_entropy(&mut SplitMix::new(12345678));
assert_eq!(rng1.random_u64(), rng2.random_u64());
}
#[test]
fn different_entropy_produces_different_values() {
let mut rng1 = SmallRng::from_entropy(&mut SplitMix::new(12345678));
let mut rng2 = SmallRng::from_entropy(&mut SplitMix::new(87654321));
assert_ne!(rng1.random_u64(), rng2.random_u64());
}
}