Global mutable Rng

I use random numbers quite a bit in parallel simulations that I'd like to be repeatable (seedable) regardless of threading, so for anyone that does need thread safety and doesn't want to pass around a RNG reference, here's an example of what I do:

#![feature(thread_local)]

extern crate rand;
extern crate xorshift;

use rand::distributions::normal::StandardNormal;
use xorshift::{Rand,Rng,SeedableRng,SplitMix64,Xoroshiro128};

#[thread_local]
static mut RNG:Option<Xoroshiro128> = None;

pub fn seed(x:u64) {
    let mut seeding_rng:SplitMix64 = SeedableRng::from_seed(x);
    unsafe { RNG = Some(Rand::rand(&mut seeding_rng)); }
}

pub fn rnorm() -> f64 {
    unsafe {
        let StandardNormal(x) = RNG.as_mut().unwrap().gen::<StandardNormal>();
        x
    }
}

pub fn rnormv<R:DimName,C:DimName>() -> MatrixMN<f64,R,C>
    where DefaultAllocator:Allocator<f64,R,C> {
    unsafe { MatrixMN::<f64,R,C>::from_iterator(RNG.as_mut().unwrap().gen_iter().map(|x| { let StandardNormal(y) = x; y })) }
}
1 Like