#[inline]
#[must_use]
pub fn next_f32(&mut self) -> f32 {
- let value = (self.next_u64() >> (64 - 24)) as i64 as f32;
- value * 5.960_464_5e-8 // 0x1p-24f
+ let value = (self.next_u64() >> (64 - 24)) as f32;
+ value * 5.960_464_5e-8 // 0x1p-24
}
/// Generates a uniformly distributed random f64 in the range `0.0..1.0`
#[inline]
#[must_use]
pub fn next_f64(&mut self) -> f64 {
- let value = (self.next_u64() >> (64 - 53)) as i64 as f64;
+ let value = (self.next_u64() >> (64 - 53)) as f64;
value * 1.110_223_024_625_156_5e-16 // 0x1p-53
}
+ /// Generates a uniformly distributed random f32 in the range `-1.0..1.0`
+ ///
+ /// Always draws one 64 bit word from the PRNG.
+ #[inline]
+ #[must_use]
+ pub fn next_f32_s(&mut self) -> f32 {
+ let value = (self.next_u64() as i64 >> (64 - 25)) as f32;
+ value * 5.960_464_5e-8 // 0x1p-24
+ }
+
+ /// Generates a uniformly distributed random f64 in the range `-1.0..1.0`
+ ///
+ /// Always draws one 64 bit word from the PRNG.
+ #[inline]
+ #[must_use]
+ pub fn next_f64_s(&mut self) -> f64 {
+ let value = (self.next_u64() as i64 >> (64 - 54)) as f64;
+ value * 1.110_223_024_625_156_5e-16 // 0x1p-53
+ }
+
+ /// Generate a uniformly distributed point on the unit disc using rejection
+ /// sampling.
+ ///
+ /// Returns a tuple containing the dot product of the point with itself, as
+ /// well as the point.
+ ///
+ /// (p.p, [px, py])
+ ///
+ /// # Notes
+ ///
+ /// Uniform point on unit disc by Marc B. Reynolds:
+ /// https://marc-b-reynolds.github.io/distribution/2016/11/28/Uniform.html
+ pub fn next_uniform_unit_disc_f32(&mut self) -> (f32, [f32; 2]) {
+ let mut x;
+ let mut y;
+ let mut d;
+ loop {
+ x = self.next_f32_s();
+ y = self.next_f32_s();
+ d = x * x + y * y;
+ if d < 1.0 {
+ break;
+ }
+ }
+ (d, [x, y])
+ }
+
+ /// Generate a uniformly distributed point on the unit circle.
+ ///
+ /// # Notes
+ ///
+ /// Uniform point on unit circle by Marc B. Reynolds:
+ /// https://marc-b-reynolds.github.io/distribution/2016/11/28/Uniform.html
+ pub fn next_uniform_unit_circle_f32(&mut self) -> [f32; 2] {
+ const BIAS: f32 = 1.0 / 68719476736.0; // 0x1p-36
+ let (d, [x, y]) = self.next_uniform_unit_disc_f32();
+ let s = (d + BIAS * BIAS).sqrt().recip();
+ let x = x + BIAS;
+ [x * s, y * s]
+ }
+
/// Randomly select an an element from `slice` with uniform probability.
///
/// Always draws two 64 bit words from the PRNG.
assert!(x >= 0.0 && x < 1.0);
}
}
+
+ #[test]
+ fn uniform_f32_s() {
+ let mut rng = Pcg64::new();
+ for _ in 0..100_000 {
+ let x = rng.next_f32_s();
+ assert!(x >= -1.0 && x < 1.0);
+ }
+ }
+
+ #[test]
+ fn uniform_f64_s() {
+ let mut rng = Pcg64::new();
+ for _ in 0..100_000 {
+ let x = rng.next_f64_s();
+ assert!(x >= -1.0 && x < 1.0);
+ }
+ }
}