// Return a number from a unit Gaussian distribution. The mean is 0 and the // standard deviation is 1.0. // First we generate two uniformly random variables inside the complex unit // circle. Then we transform these into Gaussians using the Box-Muller // transformation. This method is described in Numerical Recipes in C // ISBN 0-521-43108-5 at http://world.std.com/~nr // When we find a number, we also find its twin, so we cache that here so // that every other call is a lookup rather than a calculation. (I think GNU // does this in their implementations as well, but I don't remember for // certain.) double GAUnitGaussian(){ static GABoolean cached=gaFalse; static double cachevalue; if(cached == gaTrue){ cached = gaFalse; return cachevalue; } double rsquare, factor, var1, var2; do{ var1 = 2.0 * GARandomDouble() - 1.0; var2 = 2.0 * GARandomDouble() - 1.0; rsquare = var1*var1 + var2*var2; } while(rsquare >= 1.0 || rsquare == 0.0); double val = -2.0 * log(rsquare) / rsquare; if(val > 0.0) factor = sqrt(val); else factor = 0.0; // should not happen, but might due to roundoff cachevalue = var1 * factor; cached = gaTrue; return (var2 * factor); }
// Return a number from gaussian distribution. This code was pinched from the // GNU libg++ Normal.cc implementation of a normal distribution. That is, in // turn, based on Simulation, Modelling & Analysis by Law & Kelton, pp259. // // My random number generator (actually just the system's) isn't as good as // that in the libg++, but this should be OK for this purpose. double Gauss(double mean, double variance){ for(;;) { double u1 = GARandomDouble(); double u2 = GARandomDouble(); double v1 = 2 * u1 - 1; double v2 = 2 * u2 - 1; double w = (v1 * v1) + (v2 * v2); if (w <= 1) { double y = sqrt( (-2 * log(w)) / w); double x1 = v1 * y; // double x2 = v2 * y; // we don't use this one return(x1 * sqrt(variance) + mean); } } }