package umontreal.iro.lecuyer.randvar;
import umontreal.iro.lecuyer.rng.*;
import umontreal.iro.lecuyer.probdist.*;
/**
* This class implements normal random variate generators using
* the Kindermann-Ramage method.
* The code was taken from UNURAN. It includes the correction
* of the error in the original Kindermann-Ramage method found by the
* authors in.
*
*/
public class NormalKindermannRamageGen extends NormalGen {
/**
* Creates a normal random variate generator with mean mu
* and standard deviation sigma, using stream s.
*
*/
public NormalKindermannRamageGen (RandomStream s,
double mu, double sigma) {
super (s, null);
setParams (mu, sigma);
}
/**
* Creates a standard normal random variate generator with mean
* 0 and standard deviation 1, using stream s.
*
*/
public NormalKindermannRamageGen (RandomStream s) {
this (s, 0.0, 1.0);
}
/**
* Creates a random variate generator for the normal distribution
* dist and stream s.
*
*/
public NormalKindermannRamageGen (RandomStream s, NormalDist dist) {
super (s, dist);
if (dist != null)
setParams (dist.getMu(), dist.getSigma());
}
public double nextDouble() {
return kindermanRamage (stream, mu, sigma);
}
public static double nextDouble (RandomStream s, double mu, double sigma) {
return kindermanRamage (s, mu, sigma);
}
/**
* Generates a variate from the normal distribution with
* parameters μ = mu and σ = sigma, using
* stream s.
*
*/
//>>>>>>>>>>>>>>>>>>>> P R I V A T E S M E T H O D S <<<<<<<<<<<<<<<<<<<<
private static double kindermanRamage (RandomStream stream, double mu, double sigma) {
final double XI = 2.216035867166471;
final double PIhochK = 0.3989422804;
double U, V, W, X;
double t, z;
U = stream.nextDouble();
if (U < 0.884070402298758) {
V = stream.nextDouble();
X = XI*(1.131131635444180*U + V - 1.);
}
else if (U >= 0.973310954173898) {
do {
V = stream.nextDouble();
W = stream.nextDouble();
if (W == 0.) { t=0.; continue; }
t = XI*XI/2. - Math.log (W);
} while ( (V*V*t) > (XI*XI/2.) );
X = (U < 0.986655477086949) ? Math.pow (2*t,0.5) : -Math.pow (2*t,0.5);
}
else if (U >= 0.958720824790463) {
do {
V = stream.nextDouble();
W = stream.nextDouble();
z = V - W;
t = XI - 0.630834801921960*Math.min (V, W);
} while (Math.max (V, W) > 0.755591531667601 && 0.034240503750111*
Math.abs (z) > (PIhochK*Math.exp (t*t/(-2.)) -
0.180025191068563*(XI - Math.abs (t))) );
X = (z < 0) ? t : -t;
}
else if (U >= 0.911312780288703) {
do {
V = stream.nextDouble();
W = stream.nextDouble();
z = V - W;
t = 0.479727404222441 + 1.105473661022070*Math.min (V, W);
} while (Math.max (V, W) > 0.872834976671790 && 0.049264496373128*
Math.abs (z) > (PIhochK*Math.exp (t*t/(-2))
- 0.180025191068563*(XI - Math.abs (t))) );
X = (z < 0) ? t : -t;
}
else {
do {
V = stream.nextDouble();
W = stream.nextDouble();
z = V - W;
t = 0.479727404222441 - 0.595507138015940*Math.min (V, W);
if (t < 0.0)
continue;
} while (Math.max (V, W) > 0.805777924423817 && 0.053377549506886*
Math.abs (z) > (PIhochK*Math.exp (t*t/(-2)) -
0.180025191068563*(XI - Math.abs (t))) );
X = (z < 0) ? t : -t;
}
return mu + sigma*X;
}
}
Ads help maintain this website.