Initial commit, implements most of the static_data side.
This commit is contained in:
1
src/utils/mod.rs
Normal file
1
src/utils/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod random;
|
||||
179
src/utils/random.rs
Normal file
179
src/utils/random.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
use rand::distributions::{Distribution, Uniform};
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_pcg::Pcg32;
|
||||
|
||||
pub struct Random {
|
||||
seed: u128,
|
||||
distribution: Uniform<f64>,
|
||||
random_gen: Pcg32,
|
||||
}
|
||||
|
||||
impl Default for Random {
|
||||
fn default() -> Self {
|
||||
let seed = chrono::Utc::now().timestamp_nanos() as u128;
|
||||
Random {
|
||||
seed,
|
||||
distribution: Uniform::from(0.0..1.0),
|
||||
random_gen: Pcg32::from_seed(seed.to_be_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Random {
|
||||
pub fn new(seed: u128) -> Self {
|
||||
Random {
|
||||
seed,
|
||||
distribution: Uniform::from(0.0..1.0),
|
||||
random_gen: Pcg32::from_seed(seed.to_be_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_seed(&self) -> u128 {
|
||||
self.seed
|
||||
}
|
||||
|
||||
pub fn get(&mut self) -> i32 {
|
||||
self.random_gen.gen()
|
||||
}
|
||||
|
||||
pub fn get_max(&mut self, max: i32) -> i32 {
|
||||
assert!(max > 0);
|
||||
Uniform::from(0..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
pub fn get_between(&mut self, min: i32, max: i32) -> i32 {
|
||||
assert!(max > min);
|
||||
Uniform::from(min..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
pub fn get_unsigned(&mut self) -> u32 {
|
||||
self.random_gen.gen()
|
||||
}
|
||||
|
||||
pub fn get_max_unsigned(&mut self, max: u32) -> u32 {
|
||||
assert!(max > 0);
|
||||
Uniform::from(0..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
pub fn get_between_unsigned(&mut self, min: u32, max: u32) -> u32 {
|
||||
assert!(max > min);
|
||||
Uniform::from(min..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
pub fn get_float(&mut self) -> f32 {
|
||||
self.get_double() as f32
|
||||
}
|
||||
pub fn get_double(&mut self) -> f64 {
|
||||
self.distribution.sample(&mut self.random_gen)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::utils::random::Random;
|
||||
|
||||
#[test]
|
||||
fn create_random() {
|
||||
let _default = Random::default();
|
||||
let _empty = Random::new(100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_random_with_seed() {
|
||||
let mut v = Random::new(10);
|
||||
assert_eq!(v.get(), 1755576946);
|
||||
assert_eq!(v.get(), 1254514019);
|
||||
assert_eq!(v.get(), 1735834837);
|
||||
assert_eq!(v.get(), 51079449);
|
||||
assert_eq!(v.get(), 506997516);
|
||||
assert_eq!(v.get(), -173527621);
|
||||
assert_eq!(v.get(), 683138464);
|
||||
assert_eq!(v.get(), 580236580);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_random_with_limit_with_seed() {
|
||||
let mut v = Random::new(10);
|
||||
assert_eq!(v.get_max(10), 4);
|
||||
assert_eq!(v.get_max(10), 2);
|
||||
assert_eq!(v.get_max(10), 4);
|
||||
assert_eq!(v.get_max(10), 0);
|
||||
assert_eq!(v.get_max(10), 1);
|
||||
assert_eq!(v.get_max(10), 9);
|
||||
assert_eq!(v.get_max(10), 1);
|
||||
assert_eq!(v.get_max(10), 1);
|
||||
|
||||
assert_eq!(v.get_max(2), 0);
|
||||
assert_eq!(v.get_max(2), 1);
|
||||
assert_eq!(v.get_max(2), 1);
|
||||
assert_eq!(v.get_max(2), 1);
|
||||
assert_eq!(v.get_max(2), 0);
|
||||
assert_eq!(v.get_max(2), 1);
|
||||
assert_eq!(v.get_max(2), 0);
|
||||
assert_eq!(v.get_max(2), 0);
|
||||
assert_eq!(v.get_max(2), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_random_with_limit_with_range() {
|
||||
let mut v = Random::new(10);
|
||||
assert_eq!(v.get_between(10, 30), 18);
|
||||
assert_eq!(v.get_between(10, 30), 15);
|
||||
assert_eq!(v.get_between(10, 30), 18);
|
||||
assert_eq!(v.get_between(10, 30), 10);
|
||||
assert_eq!(v.get_between(10, 30), 12);
|
||||
assert_eq!(v.get_between(10, 30), 29);
|
||||
assert_eq!(v.get_between(10, 30), 13);
|
||||
assert_eq!(v.get_between(10, 30), 12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_random_distribution() {
|
||||
let mut v = Random::new(10);
|
||||
const AMOUNT: usize = 100_000;
|
||||
|
||||
let mut arr: [i32; AMOUNT] = [0; AMOUNT];
|
||||
for i in 0..AMOUNT {
|
||||
arr[i] = v.get_between(0, 2);
|
||||
}
|
||||
|
||||
let mut num_zeros = 0;
|
||||
let mut num_ones = 0;
|
||||
for v in arr.iter() {
|
||||
if *v == 0 {
|
||||
num_zeros += 1;
|
||||
} else if *v == 1 {
|
||||
num_ones += 1;
|
||||
}
|
||||
}
|
||||
let div = num_zeros as f32 / num_ones as f32;
|
||||
assert_approx_eq::assert_approx_eq!(div, 1.0, 0.01);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_random_distribution_0_to_3() {
|
||||
let mut v = Random::new(10);
|
||||
const AMOUNT: usize = 100_000;
|
||||
|
||||
let mut arr: [i32; AMOUNT] = [0; AMOUNT];
|
||||
for i in 0..AMOUNT {
|
||||
arr[i] = v.get_between(0, 3);
|
||||
}
|
||||
|
||||
let mut num_zeros = 0;
|
||||
let mut num_ones = 0;
|
||||
let mut num_twos = 0;
|
||||
for v in arr.iter() {
|
||||
if *v == 0 {
|
||||
num_zeros += 1;
|
||||
} else if *v == 1 {
|
||||
num_ones += 1;
|
||||
} else if *v == 2 {
|
||||
num_twos += 1;
|
||||
}
|
||||
}
|
||||
assert_approx_eq::assert_approx_eq!(num_zeros as f32 / num_ones as f32, 1.0, 0.01);
|
||||
assert_approx_eq::assert_approx_eq!(num_zeros as f32 / num_twos as f32, 1.0, 0.01);
|
||||
assert_approx_eq::assert_approx_eq!(num_ones as f32 / num_twos as f32, 1.0, 0.01);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user