open System
// Config for normalRand
// Number of samples to average [4 to 10?] (tails stretch/flatten out as this gets larger)
let nSamples = 10
// Creating Random() w/o a seed uses the time of day so if many are created in
// rapid succession they will all use the same seed resulting in identical
// sequences. seed() utilizes an MT safe single instance of Random() to seed the
// generators below to to avoid this problem.
let seed =
let seedGen = new Random()
(fun () -> lock seedGen (fun () -> seedGen.Next()))
/// Creates an infinite sequence of gaussian distributed random #'s with mean and std
/// MT safe, but returned sequence is not
/// possible range of (0,sigma) is +-sigma*sqrt(3*nSamples)
let normalRand mean sigma =
// calc normalization factors up front & alloc a random()
let norm = sigma * sqrt (3*nSamples|>float)
let shift = norm - mean
let scale = 2.0 * norm / (float nSamples)
let randGen = new Random(seed())
// return a gaussian # by averaging another random seq (central limit theory)
let rec gaussAvg n acc =
if n > 0 then gaussAvg (n-1) (acc+randGen.NextDouble())
else (acc * scale) - shift
let rec gaussSeq() = seq { yield gaussAvg nSamples 0.0; yield! gaussSeq()}
gaussSeq()
/// Creates an infinite sequece of white noise (mean 0, std 1)
/// MT safe, but returned sequence is not
let whiteNoise = normalRand 0.0 1.0
/// Creates an infinite sequence of brown noise (by integrating white noise)
/// Not normalized since it's infinite
let brownNoise = whiteNoise |> Seq.scan (fun acc v -> acc+v) 0.0