//! Sources of deterministic "randomness" for rendering applications. /// Convert a `u32` to a float in [0.0, 1.0). /// /// Use for getting f32 values from random u32 sources. /// /// Note: this is a linear mapping from [0, int_max] to [0.0, 1.0). #[inline(always)] pub fn u32_to_f32_norm(n: u32) -> f32 { f32::from_bits((n >> 9) | 0x3f800000) - 1.0 } //------------------------------------------------------------- /// A fast RNG. /// #[derive(Debug, Copy, Clone)] pub struct Rng { state: u64, } impl Rng { /// Creates a new Rng from a seed. /// /// A seed of zero is perfectly fine, and does not affect the quality /// of the generator. #[inline] pub fn new(seed: u64) -> Self { Self { state: seed } } /// Gets the nth relative RNG stream from this one. /// /// The returned stream will be at the same point in its sequence as /// this one. #[inline] pub fn nth_stream(&self, n: u64) -> Self { Self { // We just jump forward 2^40*n states. This gives us 2^24 // unique streams, each of which is 2^40 numbers long. state: self .state .wrapping_add(0xa0761d6478bd642f_u64.wrapping_mul(1 << 40).wrapping_mul(n)), } } /// Returns a random u32 in [0, int_max]. #[inline(always)] pub fn u32(&mut self) -> u32 { self.u64() as u32 } /// Returns a random u64 in [0, int_max]. #[inline(always)] pub fn u64(&mut self) -> u64 { // The wyrand RNG. self.state = self.state.wrapping_add(0xa0761d6478bd642f); let t = (self.state as u128).wrapping_mul(self.state as u128 ^ 0xe7037ed1a0b428db); ((t >> 64) ^ t) as u64 } } //------------------------------------------------------------- /// A fast 32-bit mixing function. /// /// Scrambles the input number to produce a different deterministic /// "random" number. #[inline(always)] pub fn mix_u32(mut n: u32) -> u32 { // From https://github.com/skeeto/hash-prospector n ^= n >> 16; n = n.wrapping_mul(0x21f0aaad); n ^= n >> 15; n = n.wrapping_mul(0xd35a2d97); n ^= n >> 15; // Xor by a random number so input zero doesn't map to output zero. // The particular number used here isn't special. n ^ 0xe6fe3beb } /// A fast seedable 32-bit mixing function. /// /// Same as `mix_u32()` but takes a seed. #[inline(always)] pub fn mix_seed_u32(n: u32, seed: u32) -> u32 { // We rotate the bits of `seed` so it's unlikely to interact with `n` // in bad ways if they're both e.g. incrementing. The particular // rotation constant used here isn't special. mix_u32(n ^ seed.rotate_left(23)) } /// A fast 64-bit mixing function. /// /// Scrambles the input number to produce a different deterministic /// "random" number. #[inline(always)] pub fn mix_u64(mut n: u64) -> u64 { // From https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html n ^= n >> 30; n = n.wrapping_mul(0xbf58476d1ce4e5b9); n ^= n >> 27; n = n.wrapping_mul(0x94d049bb133111eb); n ^= n >> 31; // Xor by a random number so input zero doesn't map to output zero. // The particular number used here isn't special. n ^ 0x4acc3f27cc712c9d } /// A fast seedable 64-bit mixing function. /// /// Same as `mix_u64()` but takes a seed. #[inline(always)] pub fn mix_seed_u64(n: u64, seed: u64) -> u64 { // We rotate the bits of `seed` so it's unlikely to interact with `n` // in bad ways if they're both e.g. incrementing. The particular // rotation constant used here isn't special. mix_u64(n ^ seed.rotate_left(47)) }