randomize/
lib.rs

1#![no_std]
2#![allow(unused_mut)]
3#![warn(missing_docs)]
4#![forbid(unsafe_code)]
5#![warn(missing_debug_implementations)]
6#![warn(clippy::missing_const_for_fn)]
7#![warn(clippy::missing_inline_in_public_items)]
8#![cfg_attr(docsrs, feature(doc_cfg))]
9
10//! Pseudo-random number generator crate.
11//!
12//! NOT FOR CRYPTOGRAPHIC PURPOSES.
13//!
14//! ## Using This Crate
15//!
16//! * Create a [PCG32] or [PCG32K] value as your generator.
17//!   * If you enable this crate's `getrandom` cargo feature then both types
18//!     will have constructor functions to handle seeding a generator from the
19//!     [getrandom](getrandom::getrandom) function.
20//! * Call `next_u32` on the generator to get pseudo-random `u32` values.
21//! * At your option, import the [Gen32] trait for various extension methods.
22
23pub mod formulas;
24use formulas::ieee754_random_f32;
25
26mod pcg;
27pub use pcg::*;
28
29mod bounded_rand;
30pub use bounded_rand::*;
31
32/// A trait for pseudo-random number generators with 32-bit output per step.
33pub trait Gen32 {
34  /// Makes the generator create the next output.
35  ///
36  /// All `u32` values should have equal chance of occuring.
37  fn next_u32(&mut self) -> u32;
38
39  /// Gives a uniformly distributed value.
40  #[inline]
41  fn next_i32(&mut self) -> i32 {
42    self.next_u32() as i32
43  }
44
45  /// Gives a uniformly distributed value.
46  #[inline]
47  fn next_bool(&mut self) -> bool {
48    (self.next_u32() as i32) < 0
49  }
50
51  /// Gives a value in the range `0.0 ..= 1.0`
52  #[inline]
53  fn next_f32_unit(&mut self) -> f32 {
54    ieee754_random_f32(|| self.next_u32(), false)
55  }
56
57  /// Gives a value in the range `1 ..= 4`
58  #[inline]
59  fn d4(&mut self) -> i32 {
60    let base = self.next_u32() >> 30;
61    base as i32 + 1
62  }
63
64  /// Gives a value in the range `1 ..= 6`
65  #[inline]
66  fn d6(&mut self) -> i32 {
67    let base = BoundedRandU16::_6.sample(|| (self.next_u32() >> 16) as u16);
68    i32::from(base) + 1
69  }
70
71  /// Gives a value in the range `1 ..= 8`
72  #[inline]
73  fn d8(&mut self) -> i32 {
74    let base = self.next_u32() >> 29;
75    base as i32 + 1
76  }
77
78  /// Gives a value in the range `1 ..= 10`
79  #[inline]
80  fn d10(&mut self) -> i32 {
81    let base = BoundedRandU16::_10.sample(|| (self.next_u32() >> 16) as u16);
82    i32::from(base) + 1
83  }
84
85  /// Gives a value in the range `1 ..= 12`
86  #[inline]
87  fn d12(&mut self) -> i32 {
88    let base = BoundedRandU16::_12.sample(|| (self.next_u32() >> 16) as u16);
89    i32::from(base) + 1
90  }
91
92  /// Gives a value in the range `1 ..= 20`
93  #[inline]
94  fn d20(&mut self) -> i32 {
95    let base = BoundedRandU16::_20.sample(|| (self.next_u32() >> 16) as u16);
96    i32::from(base) + 1
97  }
98}
99
100impl Gen32 for PCG32 {
101  #[inline]
102  fn next_u32(&mut self) -> u32 {
103    PCG32::next_u32(self)
104  }
105}
106impl<const K: usize> Gen32 for PCG32K<K> {
107  #[inline]
108  fn next_u32(&mut self) -> u32 {
109    PCG32K::<K>::next_u32(self)
110  }
111}