]> git.nega.tv - josh/narcissus/commitdiff
narcissus-core: Improve float random generation
authorJoshua Simmons <josh@nega.tv>
Sun, 31 Mar 2024 03:22:24 +0000 (05:22 +0200)
committerJoshua Simmons <josh@nega.tv>
Sun, 31 Mar 2024 03:22:24 +0000 (05:22 +0200)
Change `next_f32` to output in the range `[0.0,1.0)`.
Add `next_f64`.
Add very basic smoke test.

engine/narcissus-core/src/rand.rs
title/shark/src/main.rs

index e46c2065543ae93322bdfe1eb5b3b0bad955126e..1ad91473aa6bde4f12ae4a4dd5c4ee537c9189b1 100644 (file)
@@ -62,16 +62,26 @@ impl Pcg64 {
         (result + carry as u64).widen()
     }
 
-    /// Generates a uniformly distributed random float in the range `-1.0..1.0`
+    /// Generates a uniformly distributed random f32 in the range `0.0..1.0`
     ///
-    /// Always draws two 64 bit words from the PRNG.
+    /// Always draws one 64 bit word from the PRNG.
     #[inline]
     #[must_use]
     pub fn next_f32(&mut self) -> f32 {
-        let value = (self.next_u64() >> (64 - 25)) as i64 as f32;
+        let value = (self.next_u64() >> (64 - 24)) as i64 as f32;
         value * 5.960_464_5e-8 // 0x1p-24f
     }
 
+    /// Generates a uniformly distributed random f64 in the range `0.0..1.0`
+    ///
+    /// Always draws one 64 bit word from the PRNG.
+    #[inline]
+    #[must_use]
+    pub fn next_f64(&mut self) -> f64 {
+        let value = (self.next_u64() >> (64 - 53)) as i64 as f64;
+        value * 1.110_223_024_625_156_5e-16 // 0x1p-53
+    }
+
     /// Randomly select an an element from `slice` with uniform probability.
     ///
     /// Always draws two 64 bit words from the PRNG.
@@ -219,4 +229,22 @@ mod tests {
         let mut rng = Pcg64::new();
         assert_eq!(rng.select(slice), None);
     }
+
+    #[test]
+    fn uniform_f32() {
+        let mut rng = Pcg64::new();
+        for _ in 0..100_000 {
+            let x = rng.next_f32();
+            assert!(x >= 0.0 && x < 1.0);
+        }
+    }
+
+    #[test]
+    fn uniform_f64() {
+        let mut rng = Pcg64::new();
+        for _ in 0..100_000 {
+            let x = rng.next_f64();
+            assert!(x >= 0.0 && x < 1.0);
+        }
+    }
 }
index 271c7ebad680716ae13e294e53b6ea327d97e92b..1bed1219a017b2ed3f7b3d2f80fcdcb534adcd9e 100644 (file)
@@ -188,7 +188,7 @@ pub fn main() {
             let x = x as f32 * shark_distance - NUM_SHARKS as f32 / 2.0 * shark_distance;
             let z = z as f32 * shark_distance - NUM_SHARKS as f32 / 2.0 * shark_distance;
             shark_transforms.push(Affine3 {
-                matrix: Mat3::from_axis_rotation(Vec3::Y, HalfTurn::new(rng.next_f32())),
+                matrix: Mat3::from_axis_rotation(Vec3::Y, HalfTurn::new(rng.next_f32() * 2.0)),
                 translate: vec3(x, 0.0, z),
             })
         }