More documentation.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2022-07-01 17:07:22 +02:00
parent 03f5e3bb5a
commit 8f6ecdd4ad
35 changed files with 721 additions and 262 deletions

View File

@@ -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() {

View File

@@ -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,