1pub mod algorithms;
40
41use crate::random::algorithms::Algorithm;
42use crate::random::algorithms::{ComplementaryMultiplyWithCarry, MersenneTwister};
43use std::cmp::Ordering;
44use std::time::SystemTime;
45
46pub trait Rng {
48 fn get_i32(&mut self, min: i32, max: i32) -> i32;
50
51 fn get_f32(&mut self, min: f32, max: f32) -> f32;
53
54 fn get_f64(&mut self, min: f64, max: f64) -> f64;
56
57 fn get_i32_mean(&mut self, min: i32, max: i32, mean: i32) -> i32;
59
60 fn get_f32_mean(&mut self, min: f32, max: f32, mean: f32) -> f32;
62
63 fn get_f64_mean(&mut self, min: f64, max: f64, mean: f64) -> f64;
65}
66
67#[derive(Clone, Debug)]
69pub struct Random<A: Algorithm> {
70 algo: A,
72 pub distribution: Distribution,
75
76 y2: Option<f64>,
78}
79
80impl<A: Algorithm> Random<A> {
81 fn default_seed() -> u64 {
82 let now = SystemTime::now();
83 let duration_since = now.duration_since(SystemTime::UNIX_EPOCH).unwrap();
84 duration_since.as_secs()
85 }
86
87 fn get_i(&mut self, mut min: i32, mut max: i32) -> i32 {
88 match max.cmp(&min) {
89 Ordering::Less => std::mem::swap(&mut min, &mut max),
90 Ordering::Equal => return min,
91 Ordering::Greater => (),
92 }
93
94 let delta = max - min + 1; (self.algo.get_int() % delta as u32) as i32 + min
97 }
98
99 fn get_f(&mut self, mut min: f32, mut max: f32) -> f32 {
100 if (max - min).abs() < 0.000_001 {
101 return min;
102 } else if max < min {
103 std::mem::swap(&mut min, &mut max);
104 }
105
106 let delta = max - min;
107
108 self.algo.get_float() * delta + min
109 }
110
111 fn get_d(&mut self, mut min: f64, mut max: f64) -> f64 {
112 if (max - min).abs() < 0.000_001 {
113 return min;
114 } else if max < min {
115 std::mem::swap(&mut min, &mut max);
116 }
117
118 let delta = max - min;
119
120 self.algo.get_double() * delta + min
121 }
122
123 fn get_gaussian_double(&mut self, mean: f64, std_deviation: f64) -> f64 {
126 if let Some(y2) = self.y2.take() {
127 return mean + y2 * std_deviation;
128 }
129
130 let (x1, x2, w) = loop {
131 let x1 = self.algo.get_double() * 2.0 - 1.0;
132 let x2 = self.algo.get_double() * 2.0 - 1.0;
133 let w = x1.powi(2) + x2.powi(2);
134 if w < 1.0 {
135 break (x1, x2, (-2.0 * w.ln() / w).sqrt());
136 }
137 };
138
139 let y1 = x1 * w;
140 self.y2 = Some(x2 * w);
141
142 mean + y1 * std_deviation
143 }
144
145 fn get_gaussian_float(&mut self, mean: f32, std_deviation: f32) -> f32 {
146 self.get_gaussian_double(f64::from(mean), f64::from(std_deviation)) as f32
147 }
148
149 fn get_gaussian_int(&mut self, mean: i32, std_deviation: i32) -> i32 {
150 self.get_gaussian_double(f64::from(mean), f64::from(std_deviation))
151 .round() as i32
152 }
153
154 fn get_gaussian_double_range(&mut self, mut min: f64, mut max: f64) -> f64 {
157 if max < min {
158 std::mem::swap(&mut min, &mut max);
159 }
160
161 let mean = (min + max) / 2.0;
162 let std_deviation = (max - min) / 6.0; self.get_gaussian_double(mean, std_deviation)
165 .max(min)
166 .min(max)
167 }
168
169 fn get_gaussian_float_range(&mut self, min: f32, max: f32) -> f32 {
170 self.get_gaussian_double_range(f64::from(min), f64::from(max)) as f32
171 }
172
173 fn get_gaussian_int_range(&mut self, min: i32, max: i32) -> i32 {
174 self.get_gaussian_double_range(f64::from(min), f64::from(max))
175 .round() as i32
176 }
177
178 fn get_gaussian_double_range_custom(&mut self, mut min: f64, mut max: f64, mean: f64) -> f64 {
181 if max < min {
182 std::mem::swap(&mut min, &mut max);
183 }
184 let d1 = max - mean;
185 let d2 = mean - min;
186 let std_deviation = d1.max(d2) / 3.0;
187
188 self.get_gaussian_double(mean, std_deviation)
189 .max(min)
190 .min(max)
191 }
192
193 fn get_gaussian_float_range_custom(&mut self, min: f32, max: f32, mean: f32) -> f32 {
194 self.get_gaussian_double_range_custom(f64::from(min), f64::from(max), f64::from(mean))
195 as f32
196 }
197
198 fn get_gaussian_int_range_custom(&mut self, min: i32, max: i32, mean: i32) -> i32 {
199 (self
200 .get_gaussian_double_range_custom(f64::from(min), f64::from(max), f64::from(mean))
201 .round() as i32)
202 .max(min)
203 .min(max)
204 }
205
206 fn get_gaussian_double_inv(&mut self, mean: f64, std_deviation: f64) -> f64 {
209 let num = self.get_gaussian_double(mean, std_deviation);
210 if num >= mean {
211 num - 3.0 * std_deviation
212 } else {
213 num + 3.0 * std_deviation
214 }
215 }
216
217 fn get_gaussian_float_inv(&mut self, mean: f32, std_deviation: f32) -> f32 {
218 let num = self.get_gaussian_double(f64::from(mean), f64::from(std_deviation));
219 if num >= f64::from(mean) {
220 (num - 3.0 * f64::from(std_deviation)) as f32
221 } else {
222 (num + 3.0 * f64::from(std_deviation)) as f32
223 }
224 }
225
226 fn get_gaussian_int_inv(&mut self, mean: i32, std_deviation: i32) -> i32 {
227 let num = self.get_gaussian_double(f64::from(mean), f64::from(std_deviation));
228 let integer = num.round() as i32;
229 if num >= f64::from(mean) {
230 integer - 3 * std_deviation
231 } else {
232 integer + 3 * std_deviation
233 }
234 }
235
236 fn get_gaussian_double_range_inv(&mut self, mut min: f64, mut max: f64) -> f64 {
239 if max < min {
240 std::mem::swap(&mut min, &mut max);
241 }
242 let mean = (min + max) / 2.0;
243 let std_deviation = (max - min) / 6.0; self.get_gaussian_double_inv(mean, std_deviation)
246 .max(min)
247 .min(max)
248 }
249
250 fn get_gaussian_float_range_inv(&mut self, min: f32, max: f32) -> f32 {
251 self.get_gaussian_double_range_inv(f64::from(min), f64::from(max)) as f32
252 }
253
254 fn get_gaussian_int_range_inv(&mut self, min: i32, max: i32) -> i32 {
255 (self
256 .get_gaussian_double_range_inv(f64::from(min), f64::from(max))
257 .round() as i32)
258 .max(min)
259 .min(max)
260 }
261
262 fn get_gaussian_double_range_custom_inv(
265 &mut self,
266 mut min: f64,
267 mut max: f64,
268 mean: f64,
269 ) -> f64 {
270 if max < min {
271 std::mem::swap(&mut min, &mut max);
272 }
273
274 let d1 = max - mean;
275 let d2 = mean - min;
276 let std_deviation = d1.max(d2) / 3.0;
277
278 self.get_gaussian_double_inv(mean, std_deviation)
279 .max(min)
280 .min(max)
281 }
282
283 fn get_gaussian_float_range_custom_inv(&mut self, min: f32, max: f32, mean: f32) -> f32 {
284 self.get_gaussian_double_range_custom_inv(f64::from(min), f64::from(max), f64::from(mean))
285 as f32
286 }
287
288 fn get_gaussian_int_range_custom_inv(&mut self, min: i32, max: i32, mean: i32) -> i32 {
289 (self
290 .get_gaussian_double_range_custom_inv(f64::from(min), f64::from(max), f64::from(mean))
291 .round() as i32)
292 .max(min)
293 .min(max)
294 }
295}
296
297impl<A: Algorithm> Rng for Random<A> {
298 fn get_i32(&mut self, min: i32, max: i32) -> i32 {
299 match self.distribution {
300 Distribution::Linear => self.get_i(min, max),
301 Distribution::Gaussian => self.get_gaussian_int(min, max),
302 Distribution::GaussianRange => self.get_gaussian_int_range(min, max),
303 Distribution::GaussianInverse => self.get_gaussian_int_inv(min, max),
304 Distribution::GaussianRangeInverse => self.get_gaussian_int_range_inv(min, max),
305 }
306 }
307
308 fn get_f32(&mut self, min: f32, max: f32) -> f32 {
309 match self.distribution {
310 Distribution::Linear => self.get_f(min, max),
311 Distribution::Gaussian => self.get_gaussian_float(min, max),
312 Distribution::GaussianRange => self.get_gaussian_float_range(min, max),
313 Distribution::GaussianInverse => self.get_gaussian_float_inv(min, max),
314 Distribution::GaussianRangeInverse => self.get_gaussian_float_range_inv(min, max),
315 }
316 }
317
318 fn get_f64(&mut self, min: f64, max: f64) -> f64 {
319 match self.distribution {
320 Distribution::Linear => self.get_d(min, max),
321 Distribution::Gaussian => self.get_gaussian_double(min, max),
322 Distribution::GaussianRange => self.get_gaussian_double_range(min, max),
323 Distribution::GaussianInverse => self.get_gaussian_double_inv(min, max),
324 Distribution::GaussianRangeInverse => self.get_gaussian_double_range_inv(min, max),
325 }
326 }
327
328 fn get_i32_mean(&mut self, min: i32, max: i32, mean: i32) -> i32 {
329 match self.distribution {
330 Distribution::GaussianInverse | Distribution::GaussianRangeInverse => {
331 self.get_gaussian_int_range_custom_inv(min, max, mean)
332 }
333 _ => self.get_gaussian_int_range_custom(min, max, mean),
334 }
335 }
336
337 fn get_f32_mean(&mut self, min: f32, max: f32, mean: f32) -> f32 {
338 match self.distribution {
339 Distribution::GaussianInverse | Distribution::GaussianRangeInverse => {
340 self.get_gaussian_float_range_custom_inv(min, max, mean)
341 }
342 _ => self.get_gaussian_float_range_custom(min, max, mean),
343 }
344 }
345
346 fn get_f64_mean(&mut self, min: f64, max: f64, mean: f64) -> f64 {
347 match self.distribution {
348 Distribution::GaussianInverse | Distribution::GaussianRangeInverse => {
349 self.get_gaussian_double_range_custom_inv(min, max, mean)
350 }
351 _ => self.get_gaussian_double_range_custom(min, max, mean),
352 }
353 }
354}
355
356impl Random<MersenneTwister> {
357 pub fn new_mt() -> Self {
359 Self::new_mt_from_seed(Self::default_seed() as u32)
360 }
361
362 pub fn new_mt_from_seed(seed: u32) -> Self {
364 Self {
365 algo: MersenneTwister::new(seed),
366 distribution: Distribution::Linear,
367
368 y2: None,
369 }
370 }
371}
372
373impl Random<ComplementaryMultiplyWithCarry> {
374 pub fn new_cmwc() -> Self {
376 Self::new_cmwc_from_seed(Self::default_seed() as u32)
377 }
378
379 pub fn new_cmwc_from_seed(seed: u32) -> Self {
382 Self {
383 algo: ComplementaryMultiplyWithCarry::new(seed),
384 distribution: Distribution::Linear,
385
386 y2: None,
387 }
388 }
389}
390
391#[derive(Clone, Copy, Debug)]
393pub enum Distribution {
394 Linear,
396 Gaussian,
398 GaussianRange,
401 GaussianInverse,
403 GaussianRangeInverse,
406}
407
408#[derive(Debug, Copy, Clone)]
427pub struct Dice {
428 nb_rolls: i32,
429 nb_faces: i32,
430 multiplier: f32,
431 add_sub: f32,
432}
433
434impl Dice {
435 pub fn new<S: AsRef<str>>(s: S) -> Self {
448 let mut s = s.as_ref();
449
450 let multiplier = if let Some(m) = s.find(|c| c == '*' || c == 'x') {
452 let value = s[0..m].parse::<f32>().unwrap_or_default();
453 s = &s[m + 1..];
454
455 value
456 } else {
457 1.0
458 };
459
460 let r = s
462 .find(|c| c == 'd' || c == 'D')
463 .expect("Incorrect dice specification format");
464 let nb_rolls = s[0..r].parse::<i32>().unwrap_or_default();
465 s = &s[r + 1..];
466
467 let nb_faces = if let Some(f) = s.find(|c| c == '+' || c == '-') {
469 let value = s[0..f].parse::<i32>().unwrap_or_default();
470 s = &s[f..];
471
472 value
473 } else {
474 let value = s[0..].parse::<i32>().unwrap_or_default();
475 s = &s[s.len()..];
476
477 value
478 };
479
480 let add_sub = if s.is_empty() {
482 0.0
483 } else {
484 s[0..].parse::<f32>().unwrap_or_default()
485 };
486
487 Self {
488 multiplier,
489 nb_rolls,
490 nb_faces,
491 add_sub,
492 }
493 }
494
495 pub fn roll<R: Rng>(&self, mersenne: &mut R) -> i32 {
498 let mut result = 0;
499 for _ in 0..self.nb_rolls {
500 result += mersenne.get_i32(1, self.nb_faces);
501 }
502
503 ((result as f32 + self.add_sub) * self.multiplier) as i32
504 }
505
506 pub fn single_roll<R: Rng, S: AsRef<str>>(mersenne: &mut R, s: S) -> i32 {
511 Self::new(s).roll(mersenne)
512 }
513}
514
515#[cfg(feature = "rng_support")]
516impl<A: Algorithm> rand_core::RngCore for Random<A> {
517 fn next_u32(&mut self) -> u32 {
518 self.algo.get_int()
519 }
520
521 fn next_u64(&mut self) -> u64 {
522 use rand_core::impls;
523 impls::next_u64_via_u32(self)
524 }
525
526 fn fill_bytes(&mut self, dest: &mut [u8]) {
527 use rand_core::impls;
528 impls::fill_bytes_via_next(self, dest)
529 }
530
531 #[allow(clippy::unit_arg)] fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
533 Ok(self.fill_bytes(dest))
534 }
535}
536
537#[cfg(feature = "rng_support")]
538impl rand_core::SeedableRng for Random<MersenneTwister> {
539 type Seed = [u8; 4];
540
541 fn from_seed(seed: Self::Seed) -> Self {
542 let seed = u32::from(seed[0]) << 24
543 | u32::from(seed[1]) << 16
544 | u32::from(seed[2]) << 8
545 | u32::from(seed[3]);
546 Self::new_mt_from_seed(seed)
547 }
548}
549
550#[cfg(feature = "rng_support")]
551impl rand_core::SeedableRng for Random<ComplementaryMultiplyWithCarry> {
552 type Seed = [u8; 4];
553
554 fn from_seed(seed: Self::Seed) -> Self {
555 let seed = u32::from(seed[0]) << 24
556 | u32::from(seed[1]) << 16
557 | u32::from(seed[2]) << 8
558 | u32::from(seed[3]);
559 Self::new_cmwc_from_seed(seed)
560 }
561}