1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
///```rust
///use doe::*;
///let lcg = LCG::new();
///for _ in 0..10000{
/// let data = lcg.random_in_range(1..=20).to_string().push_back("\n");
/// fs::fs::append_data_to_file("doe.txt", data).unwrap();
///}
/// ```
#[allow(warnings)]
pub mod rand {
/// A Linear Congruential Generator (LCG) is a simple type of random number generator
/// that produces a sequence of pseudo-random numbers based on a linear recurrence relation.
#[derive(Debug, Clone, Default)]
pub struct LCG {
seed: u128,
a: u128,
c: u128,
m: u128,
}
impl LCG {
/// Creates a new LCG instance with the specified initial seed is timestamp as nanoseconds.
///
/// ```rust
///use doe::*;
///let lcg = LCG::new();
///for _ in 0..10000{
/// let data = lcg.random_in_range(1..=20).to_string().push_back("\n");
/// fs::fs::append_data_to_file("doe.txt", data).unwrap();
///}
/// ```
/// # Returns
///
/// A new `LCG` instance with the specified seed and default constants.
pub fn new() -> LCG {
let seed = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos();
Self::init(seed, 1664525, 1013904223, 2u128.pow(32))
}
///random_in_range
/// ```rust
///use doe::*;
///let lcg = LCG::new();
///for _ in 0..10000{
/// lcg.random_in_range(-30..30).dprintln();
///}
/// ```
///
pub fn random_in_range(&self, range: impl std::ops::RangeBounds<i128>) -> i128 {
let min = match range.start_bound() {
std::ops::Bound::Included(v) => *v,
std::ops::Bound::Excluded(v) => *v,
std::ops::Bound::Unbounded => 0,
};
let max = match range.end_bound() {
std::ops::Bound::Included(v) => *v + 1,
std::ops::Bound::Excluded(v) => *v,
std::ops::Bound::Unbounded => i128::MAX,
};
let random = Self::new().random();
let sub = (max - min) as f64;
f64::floor(random * sub) as i128 + min
}
///random_in_range_f64
///```rust
///use doe::*;
///let lcg = LCG::new();
///for _ in 0..10000{
/// lcg.random_in_range_f64(-30.0..30.0).dprintln();
///}
/// ```
pub fn random_in_range_f64(&self, range: impl std::ops::RangeBounds<f64>) -> f64 {
let min = match range.start_bound() {
std::ops::Bound::Included(v) => *v,
std::ops::Bound::Excluded(v) => *v,
std::ops::Bound::Unbounded => 0.0,
};
let max = match range.end_bound() {
std::ops::Bound::Included(v) => *v,
std::ops::Bound::Excluded(v) => *v,
std::ops::Bound::Unbounded => f64::MAX,
};
let random = Self::new().random();
let sub = max - min;
(random * sub) + min
}
/// Creates a new LCG instance with the specified initial seed value.
///
/// # Arguments
///
/// * `seed` - The initial seed value for the LCG.
///
/// # Returns
///
/// A new `LCG` instance with the specified seed and default constants.
pub fn new_with_seed(seed: u128) -> LCG {
Self::init(seed, 1664525, 1013904223, 2u128.pow(32))
}
/// Creates a new LCG instance with the specified initial seed value and constants.
///
/// # Arguments
///
/// * `seed` - The initial seed value for the LCG.
/// * `a` - The multiplier constant for the LCG.
/// * `c` - The increment constant for the LCG.
/// * `m` - The modulus constant for the LCG.
///
/// # Returns
///
/// A new `LCG` instance with the specified seed and constants.
pub fn init(seed: u128, a: u128, c: u128, m: u128) -> LCG {
LCG { seed, a, c, m }
}
/// Generates the next random number in the sequence.
///
/// # Returns
///
/// The next pseudo-random number in the sequence as a `f64` value between 0 and 1.
pub fn random(&mut self) -> f64 {
self.seed = (self.a * self.seed + self.c) % self.m;
self.seed as f64 / self.m as f64
}
pub fn random_f32(&mut self) -> f32 {
self.seed = (self.a * self.seed + self.c) % self.m;
self.seed as f32 / self.m as f32
}
}
}