ID:195051
 
//Title: Cached Gaussian Random Number Generator
//Credit to: Jtgibson
//Contributed by: Jtgibson
//Special thanks to: Lummox JR


/*
This is a simple Gaussian random number generator, inspired by Lummox JR and by
the information presented at http://www.taygeta.com/random/gaussian.html

Use gaussrand.rnd() to return a Gaussian random number. The system will
automatically generate two Gaussian random numbers at a time, returning one and
caching the other for later. The second time, it will yield the cached number,
clearing the cached number so it can generate a new pair of numbers next time.
(If you simply use generate() each time, the cached number will always be
wasted.)

A Gaussian random number is a number which is centred around zero and can
theoretically progress from negative infinity to positive infinity. However,
99.7% of the time, it will be greater than -3 and less than +3; 95.45% of the
time, it will be greater than -2 and less than +2, and 68.27% of the time, it
will be greater than -1 and less than +1. These "waypoints" of +/- 1, 2, 3 are
considered "standard deviations".

See also:
http://en.wikipedia.org/wiki/68-95-99.7_rule
http://en.wikipedia.org/wiki/Standard_deviation#Rules_for_normally_distributed_data
*/


gaussrand
var/tmp/alt = null

proc/rnd()
if(alt == null)
. = generate()
//usr << "DBG: generated numbers [.] and [alt], using [.]"
else
. = alt; alt = null
//usr << "DBG: using cached number [.]"

proc/generate()
var/x1, x2, w, y1, y2
do
x1 = 2.0 * rand() - 1.0
x2 = 2.0 * rand() - 1.0
w = x1 * x1 + x2 * x2
while(w >= 1.0)

w = sqrt((-2.0*log(w))/w)
y1 = x1 * w
y2 = x2 * w

alt = y2
return y1


///*
//Testing code/sample implementation:

mob/verb/test_gaussrand()
spawn()
var/gaussrand/gaussrand = new
var/iterations = 1000

while(iterations--)
usr << gaussrand.rnd()
sleep(1)
//*/