16 releases
0.1.3400 | Oct 3, 2021 |
---|---|
0.1.3355 | Oct 3, 2021 |
0.1.3000 | Sep 29, 2021 |
#1305 in Algorithms
5KB
71 lines
Arbitrary state length, additive xor based PRNG:
How to use this library:
It is recommended to keep one global state, initialized once with a state length greater than 4 bytes, and to pass it by mutable reference when fetching random numbers.
Here is some source code explaining the simpler aspects, more functionality such as iterators can be found in the source code.
use std::time::{SystemTime, UNIX_EPOCH};
use xor_rand::XorRand;
fn main() {
// Default creation, 8 bytes state size
// let mut prng = XorRand::default();
// Creating prng, 0-2 is bad, 3-4 ok, 5-8 good, 9+ excellent
let mut prng = XorRand::new(16);
// Seeding prng
prng.seed("Hello, world!".as_bytes());
let number = i64::from_be_bytes(prng.next_bytes());
println!("Well this was unexpected: {}", number);
// Seeding with system time
let now = SystemTime::now();
let since_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards");
let seed = since_epoch.as_micros();
prng.seed(&seed.to_be_bytes());
// Simple byte use
println!(
"The first byte this prng should output: {}",
prng.next_byte()
);
// Simple integer use
for _ in 0..10 {
let random_num = u128::from_be_bytes(prng.next_bytes());
println!("Here is a pseudo random number: {}!", random_num);
}
// Passing to functions
roll_dice(&mut prng);
// An example of how to NOT get uniform floats.
// Instead, get a uniform integer and cast to a float, divide to get required precision.
println!(
"NON UNIFORM RANDOMNESS: {:+e}",
f64::from_be_bytes(prng.next_bytes())
);
}
fn roll_dice(prng: &mut XorRand) {
let dice_roll = u32::from_le_bytes(prng.next_bytes()) % 6;
println!("You rolled a {}!", dice_roll + 1);
}
Where this xor based PRNG came from:
I was messing around with state mixing, found something which worked supprising well, and this came out of it. It was too good not to share with the world.