-
-
Save RandyMcMillan/827a2e6a8863a09512d5b1416dbacbd0 to your computer and use it in GitHub Desktop.
Xoroshiro128PlusPlus.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #![no_std] | |
| // Conditionally link `std` when compiling an executable target (non-test binary) | |
| #[cfg(not(test))] | |
| extern crate std; | |
| /// A lightweight, fast, `#![no_std]` Pseudo-Random Number Generator (PRNG) | |
| /// based on the Xoroshiro128++ algorithm. | |
| #[derive(Debug, Clone, PartialEq, Eq)] | |
| pub struct Xoroshiro128PlusPlus { | |
| s: [u64; 2], | |
| } | |
| impl Xoroshiro128PlusPlus { | |
| /// Creates a new generator using a 64-bit seed. | |
| /// | |
| /// Uses a SplitMix64 PRNG internally to expand a single `u64` seed | |
| /// into the full 128-bit internal state. | |
| pub const fn from_seed(seed: u64) -> Self { | |
| let /* mut */ sm = SplitMix64::new(seed); | |
| let (s0, sm) = sm.next_u64(); | |
| let (s1, _) = sm.next_u64(); | |
| Self { s: [s0, s1] } | |
| } | |
| /// Creates a generator directly from a 128-bit state (`[u64; 2]`). | |
| /// Note: State cannot be entirely zero. | |
| pub const fn from_state(state: [u64; 2]) -> Self { | |
| if state[0] == 0 && state[1] == 0 { | |
| Self { | |
| s: [0x8A5CD789635D2DFF, 0x121FD2155C472F96], | |
| } | |
| } else { | |
| Self { s: state } | |
| } | |
| } | |
| /// Generates the next random `u64`. | |
| pub fn next_u64(&mut self) -> u64 { | |
| let s0 = self.s[0]; | |
| let mut s1 = self.s[1]; | |
| let result = s0.wrapping_add(s1).rotate_left(17).wrapping_add(s0); | |
| s1 ^= s0; | |
| self.s[0] = s0.rotate_left(49) ^ s1 ^ (s1 << 21); | |
| self.s[1] = s1.rotate_left(28); | |
| result | |
| } | |
| /// Generates the next random `u32`. | |
| pub fn next_u32(&mut self) -> u32 { | |
| (self.next_u64() >> 32) as u32 | |
| } | |
| /// Generates a random boolean with 50% probability. | |
| pub fn gen_bool(&mut self) -> bool { | |
| (self.next_u64() & 1) == 1 | |
| } | |
| /// Generates a random integer within a range `[low, high)`. | |
| pub fn gen_range(&mut self, low: u64, high: u64) -> u64 { | |
| assert!(low < high, "low must be strictly less than high"); | |
| let range = high - low; | |
| low + (self.next_u64() % range) | |
| } | |
| /// Generates a floating-point number in the uniform range `[0.0, 1.0)`. | |
| pub fn gen_f32(&mut self) -> f32 { | |
| let bits = (self.next_u32() >> 8) as f32; | |
| bits * (1.0 / (1 << 24) as f32) | |
| } | |
| /// Generates a 64-bit floating point number in `[0.0, 1.0)`. | |
| pub fn gen_f64(&mut self) -> f64 { | |
| let bits = (self.next_u64() >> 11) as f64; | |
| bits * (1.0 / (1u64 << 53) as f64) | |
| } | |
| } | |
| /// Helper SplitMix64 generator used solely for state initialization. | |
| #[derive(Debug, Clone, Copy)] | |
| struct SplitMix64 { | |
| state: u64, | |
| } | |
| impl SplitMix64 { | |
| const fn new(seed: u64) -> Self { | |
| Self { state: seed } | |
| } | |
| /// Pure `const fn` progression returning the generated `u64` and updated state. | |
| const fn next_u64(self) -> (u64, Self) { | |
| let next_state = self.state.wrapping_add(0x9E3779B97F4A7C15); | |
| let mut z = next_state; | |
| z = (z ^ (z >> 30)).wrapping_mul(0xBF58476D1CE4E5B9); | |
| z = (z ^ (z >> 27)).wrapping_mul(0x94D049BB133111EB); | |
| let val = z ^ (z >> 31); | |
| (val, Self { state: next_state }) | |
| } | |
| } | |
| fn main() { | |
| let mut rng = Xoroshiro128PlusPlus::from_seed(0xDEAD_BEEF_1234_5678); | |
| std::println!("Random u64: {}", rng.next_u64()); | |
| std::println!("Random u32: {}", rng.next_u32()); | |
| std::println!("Random Bool: {}", rng.gen_bool()); | |
| std::println!("Range [1,10): {}", rng.gen_range(1, 10)); | |
| std::println!("Random f32: {}", rng.gen_f32()); | |
| std::println!("Random f64: {}", rng.gen_f64()); | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=35186883ebb191f83da922d9309bcd07