use rand::{rngs::StdRng, thread_rng, Rng, SeedableRng};
use std::collections::VecDeque;
pub struct ThreadLocalRng;
impl ThreadLocalRng {
pub fn gen_range<T, R>(range: R) -> T
where
T: rand::distributions::uniform::SampleUniform,
R: rand::distributions::uniform::SampleRange<T>,
{
thread_rng().gen_range(range)
}
pub fn fetch_uniform(from: f32, to: f32, num: usize) -> VecDeque<f32> {
let mut uniform_numbers = VecDeque::with_capacity(num);
let mut rng = thread_rng();
uniform_numbers.extend((0..num).map(|_| rng.gen_range(from..to)));
uniform_numbers
}
pub fn get_fresh_rng() {
let _ = thread_rng();
}
}
#[derive(Clone)]
pub struct RandomNumberGenerator {
pub rng: StdRng,
}
impl RandomNumberGenerator {
pub fn new() -> Self {
Self {
rng: StdRng::from_entropy(),
}
}
pub fn from_seed(seed: u64) -> Self {
Self {
rng: StdRng::seed_from_u64(seed),
}
}
pub fn fetch_uniform(&mut self, from: f32, to: f32, num: usize) -> VecDeque<f32> {
let mut uniform_numbers = VecDeque::new();
uniform_numbers.extend((0..num).map(|_| self.rng.gen_range(from..to)));
uniform_numbers
}
}
impl Default for RandomNumberGenerator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fetch_uniform_with_positive_range() {
let mut rng = RandomNumberGenerator::new();
let result = rng.fetch_uniform(0.0, 1.0, 5);
assert_eq!(result.len(), 5);
for &num in result.iter() {
assert!((0.0..1.0).contains(&num));
}
}
#[test]
fn test_fetch_uniform_with_negative_range() {
let mut rng = RandomNumberGenerator::new();
let result = rng.fetch_uniform(-1.0, 1.0, 3);
assert_eq!(result.len(), 3);
for &num in result.iter() {
assert!((-1.0..1.0).contains(&num));
}
}
#[test]
fn test_fetch_uniform_with_large_range() {
let mut rng = RandomNumberGenerator::new();
let result = rng.fetch_uniform(-1000.0, 1000.0, 10);
assert_eq!(result.len(), 10);
for &num in result.iter() {
assert!((-1000.0..1000.0).contains(&num));
}
}
#[test]
fn test_fetch_uniform_with_empty_result() {
let mut rng = RandomNumberGenerator::new();
let result = rng.fetch_uniform(1.0, 2.0, 0);
assert!(result.is_empty());
}
#[test]
fn test_clone() {
let mut rng1 = RandomNumberGenerator::from_seed(42);
let mut rng2 = rng1.clone();
let nums1 = rng1.fetch_uniform(0.0, 1.0, 5);
let nums2 = rng2.fetch_uniform(0.0, 1.0, 5);
assert_eq!(nums1, nums2);
}
#[test]
fn test_thread_local_rng() {
let result = ThreadLocalRng::fetch_uniform(0.0, 1.0, 5);
assert_eq!(result.len(), 5);
for &num in result.iter() {
assert!((0.0..1.0).contains(&num));
}
ThreadLocalRng::get_fresh_rng();
}
}