A random number generator is required, which returns a sample from a normal (Gaussian) distribution, I ported the John D. Cook C # generator to F # :
let mutable m_w = 521288629u
let mutable m_z = 362436069u
let private getUint () =
m_z <- 36969u * (m_z &&& 65535u) + (m_z >>> 16)
m_w <- 18000u * (m_w &&& 65535u) + (m_w >>> 16)
(m_z <<< 16) + m_w
let private setSeed () =
let dt = System.DateTime.Now
let x = dt.ToFileTime ()
m_w <- uint32 (x >>> 16)
m_z <- uint32 (x % 4294967296L)
let private getUniform () =
let u = getUint ()
(float u + 1.) * 2.328306435454494e-10
let private randomNormal () =
let u1 = getUniform ()
let u2 = getUniform ()
let r = sqrt (-2. * (log u1))
let theta = 2. * System.Math.PI * u2
r * sin (theta)
let randn () =
setSeed ()
randomNormal ()
let randns n m =
setSeed ()
[| for i in 0 .. n - 1 -> randomNormal () |]
This implementation works fine, but is not thread safe. Given that code that depends on it makes extensive use of the parallel thread library, I need to make it thread safe.
This does not seem obvious to me, because the method is based on two mutable elements, which are largely irreplaceable. Is there any other way to ensure thread safety without resorting to locks?
Is there any other way to implement a regular pseudo-random generator using only immutable members?