This commit is contained in:
@@ -2,25 +2,27 @@ use rand::distributions::{Distribution, Uniform};
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_pcg::Pcg32;
|
||||
|
||||
/// A random number generator.
|
||||
#[derive(Clone)]
|
||||
pub struct Random {
|
||||
/// The seed of the random number generator.
|
||||
seed: u128,
|
||||
/// A float distribution.
|
||||
distribution: Uniform<f64>,
|
||||
/// The underlying RNG. PCG for fast, hard to predict random number generation.
|
||||
random_gen: Pcg32,
|
||||
}
|
||||
|
||||
impl Default for Random {
|
||||
/// The default for the RNG uses the nanoseconds since epoch as seed.
|
||||
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()),
|
||||
}
|
||||
Random::new(seed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Random {
|
||||
/// Creates a new RNG with a specific seed.
|
||||
pub fn new(seed: u128) -> Self {
|
||||
Random {
|
||||
seed,
|
||||
@@ -29,41 +31,60 @@ impl Random {
|
||||
}
|
||||
}
|
||||
|
||||
/// The seed used for the RNG.
|
||||
pub fn get_seed(&self) -> u128 {
|
||||
self.seed
|
||||
}
|
||||
|
||||
/// Get a random 32 bit integer between minimal and maximal 32 bit integer
|
||||
pub fn get(&mut self) -> i32 {
|
||||
self.random_gen.gen()
|
||||
}
|
||||
|
||||
/// Get a random 32 bit signed integer between 0 and max. If max equals 0, always returns 0.
|
||||
pub fn get_max(&mut self, max: i32) -> i32 {
|
||||
assert!(max > 0);
|
||||
if max <= 0 {
|
||||
return 0;
|
||||
}
|
||||
Uniform::from(0..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
/// Get a random 32 bit signed integer between min and max. If max is equal or less than min,
|
||||
/// always returns min.
|
||||
pub fn get_between(&mut self, min: i32, max: i32) -> i32 {
|
||||
assert!(max > min);
|
||||
if max <= min {
|
||||
return min;
|
||||
}
|
||||
Uniform::from(min..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
/// Get a random 32 bit integer unsigned between 0 and maximal 32 bit unsigned int.
|
||||
pub fn get_unsigned(&mut self) -> u32 {
|
||||
self.random_gen.gen()
|
||||
}
|
||||
|
||||
/// Get a random 32 bit signed integer between 0 and max. If max equals 0, always returns 0.
|
||||
pub fn get_max_unsigned(&mut self, max: u32) -> u32 {
|
||||
assert!(max > 0);
|
||||
if max == 0 {
|
||||
return 0;
|
||||
}
|
||||
Uniform::from(0..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
/// Get a random 32 bit unsigned integer between min and max. If max is equal or less than min,
|
||||
/// always returns min.
|
||||
pub fn get_between_unsigned(&mut self, min: u32, max: u32) -> u32 {
|
||||
assert!(max > min);
|
||||
if max <= min {
|
||||
return min;
|
||||
}
|
||||
Uniform::from(min..max).sample(&mut self.random_gen)
|
||||
}
|
||||
|
||||
/// Gets a random 32 bit float between 0.0 and 1.0
|
||||
pub fn get_float(&mut self) -> f32 {
|
||||
self.get_double() as f32
|
||||
}
|
||||
/// Gets a random 64 bit float between 0.0 and 1.0
|
||||
pub fn get_double(&mut self) -> f64 {
|
||||
self.distribution.sample(&mut self.random_gen)
|
||||
}
|
||||
@@ -71,11 +92,13 @@ impl Random {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::utils::random::Random;
|
||||
extern crate test;
|
||||
use std::hint::black_box;
|
||||
use test::Bencher;
|
||||
|
||||
use crate::utils::random::Random;
|
||||
|
||||
extern crate test;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)]
|
||||
fn create_random() {
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
use hashbrown::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::lazy::SyncLazy;
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
|
||||
/// StringKey is an immutable string that is used for indexing of hashmaps or equality a lot.
|
||||
/// By reference counting the string instead of copying, and caching the hash, we can get some
|
||||
/// free speed out of it. Note that StringKeys also compare case insensitive, so that for example
|
||||
/// `charmander` == `Charmander`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StringKey {
|
||||
/// The underlying reference counted string.
|
||||
str: Arc<str>,
|
||||
/// The unique hash of the string.
|
||||
hash: u32,
|
||||
}
|
||||
|
||||
/// A cache of all allocated strings. This allows us to re-use strings that are often used without
|
||||
/// allocation.
|
||||
static STRING_CACHE: SyncLazy<Mutex<HashMap<u32, Weak<str>>>> = SyncLazy::new(|| Mutex::new(HashMap::new()));
|
||||
/// An empty StringKey
|
||||
static EMPTY: SyncLazy<StringKey> = SyncLazy::new(|| StringKey::new(""));
|
||||
|
||||
impl StringKey {
|
||||
/// Calculates the hash of a string key in a const manner.
|
||||
pub const fn get_hash_const<const N: usize>(s: &[u8; N]) -> u32 {
|
||||
let mut crc: u32 = 0xffffffff;
|
||||
|
||||
@@ -29,6 +36,7 @@ impl StringKey {
|
||||
crc ^ 0xffffffff
|
||||
}
|
||||
|
||||
/// Gets the hash of a string.
|
||||
pub fn get_hash(s: &str) -> u32 {
|
||||
let mut crc: u32 = 0xffffffff;
|
||||
for byte in s.bytes() {
|
||||
@@ -37,6 +45,8 @@ impl StringKey {
|
||||
crc ^ 0xffffffff
|
||||
}
|
||||
|
||||
/// Creates a new StringKey. If we can find a value for this StringKey in the cache, we re-use
|
||||
/// that value.
|
||||
pub fn new(s: &str) -> Self {
|
||||
let hash = StringKey::get_hash(s);
|
||||
let mut cache = STRING_CACHE.lock().unwrap();
|
||||
@@ -54,14 +64,17 @@ impl StringKey {
|
||||
v
|
||||
}
|
||||
|
||||
/// Gets the empty StringKey.
|
||||
pub fn empty() -> Self {
|
||||
EMPTY.clone()
|
||||
}
|
||||
|
||||
/// Gets the underlying string for the StringKey.
|
||||
pub fn str(&self) -> &str {
|
||||
&self.str
|
||||
}
|
||||
|
||||
/// Gets the hash of the string value.
|
||||
pub fn hash(&self) -> u32 {
|
||||
self.hash
|
||||
}
|
||||
@@ -93,6 +106,7 @@ impl Display for StringKey {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a character to lowercased in a const safe way.
|
||||
const fn to_lower(c: u8) -> u8 {
|
||||
if c >= b'A' && c <= b'Z' {
|
||||
return c + (b'a' - b'A');
|
||||
@@ -100,6 +114,7 @@ const fn to_lower(c: u8) -> u8 {
|
||||
c
|
||||
}
|
||||
|
||||
/// A lookup table for use in CRC32 hash.
|
||||
const CRC_TABLE: &[u32] = &[
|
||||
0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4,
|
||||
0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148,
|
||||
|
||||
Reference in New Issue
Block a user