56 lines
2.0 KiB
Rust
56 lines
2.0 KiB
Rust
use rand::SeedableRng;
|
|
use rand_xoshiro::Xoshiro256StarStar;
|
|
|
|
/// Convert an RNG state buffer to an instance of [`Xoshiro256StarStar`].
|
|
///
|
|
/// While [`SeedableRng::from_seed`] is an infallible function,
|
|
/// it relies on some methods that can't be compiled by the SPIR-V
|
|
/// backend (specifically, formatting functions in the core crate).
|
|
///
|
|
/// In practice, the xoshiro RNG state is entirely defined by its seed,
|
|
/// so this function does the work of [`SeedableRng::from_seed`] by
|
|
/// transmuting the seed value to an RNG instance.
|
|
///
|
|
/// This function assumes a properly-initialized state array;
|
|
/// output may silently degenerate if the initial state is all zeros,
|
|
/// so this module is private to the crate.
|
|
pub(crate) fn xoshiro256starstar_from_seed(
|
|
rng_state: <Xoshiro256StarStar as SeedableRng>::Seed,
|
|
) -> Xoshiro256StarStar {
|
|
let mut rng_state_actual = [0u64; 4];
|
|
|
|
// NOTE: Bit shifting is tedious, but we don't have great alternatives:
|
|
// - `chunks_exact` has issues with pointer casting
|
|
// - `u64::from_le_bytes` has issues with `OpBitcast` in SPIR-V validation
|
|
for i in 0..rng_state_actual.len() {
|
|
for j in 0..size_of::<u64>() {
|
|
rng_state_actual[i] |= (rng_state[i * size_of::<u64>() + j] as u64) << j * 8;
|
|
}
|
|
}
|
|
|
|
unsafe { core::mem::transmute(rng_state_actual) }
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::rng::xoshiro256starstar_from_seed;
|
|
use core::iter::zip;
|
|
use rand::{RngExt, SeedableRng};
|
|
use rand_xoshiro::Xoshiro256StarStar;
|
|
|
|
#[test]
|
|
fn match_seeded() {
|
|
let mut seed: <Xoshiro256StarStar as SeedableRng>::Seed = [0u8; 32];
|
|
for i in 0..seed.len() {
|
|
seed[i] = i as u8;
|
|
}
|
|
|
|
let rng1 = Xoshiro256StarStar::from_seed(seed).random_iter::<u64>();
|
|
let rng2 = xoshiro256starstar_from_seed(seed).random_iter::<u64>();
|
|
|
|
zip(rng1, rng2)
|
|
.take(100)
|
|
.for_each(|(rng1_value, rng2_value)| assert_eq!(rng1_value, rng2_value));
|
|
}
|
|
}
|