4df328243c
FNV-1a für Zustandsprüfsummen und SplitMix64 als einzige Zufallsquelle des Kerns. Beide sind gegen veröffentlichte Referenzwerte geprüft. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
35 lines
1.0 KiB
Rust
35 lines
1.0 KiB
Rust
//! Repeatable pseudo random numbers (SplitMix64).
|
|
//!
|
|
//! The core never uses any other source of randomness. The same seed always
|
|
//! gives the same sequence, on every machine.
|
|
|
|
/// Pseudo random number generator with 64 bits of state.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Rng {
|
|
state: u64,
|
|
}
|
|
|
|
impl Rng {
|
|
pub fn new(seed: u64) -> Self {
|
|
Self { state: seed }
|
|
}
|
|
|
|
/// Returns the next value of the sequence.
|
|
pub fn next_u64(&mut self) -> u64 {
|
|
self.state = self.state.wrapping_add(0x9E37_79B9_7F4A_7C15);
|
|
let mut z = self.state;
|
|
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
|
|
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
|
|
z ^ (z >> 31)
|
|
}
|
|
|
|
/// Returns a value in `0..bound`.
|
|
///
|
|
/// # Panics
|
|
/// Panics if `bound` is zero.
|
|
pub fn below(&mut self, bound: u32) -> u32 {
|
|
assert!(bound > 0, "bound must be greater than zero");
|
|
((u128::from(self.next_u64()) * u128::from(bound)) >> 64) as u32
|
|
}
|
|
}
|