package umontreal.iro.lecuyer.randvar;
import umontreal.iro.lecuyer.rng.*;
import umontreal.iro.lecuyer.probdist.BetaSymmetricalDist;
/**
* This class implements symmetrical beta random variate generators using
* Ulrich's polar method. The method generates two uniform
* random variables
* x∈[0, 1] and
* y∈[- 1, 1] until
*
* x2 + y2 <= 1. Then it returns
*
*
* where
* S = x2 + y2, and α is the shape parameter of the beta
* distribution. The method is valid only when
* α > 1/2.
*
*/
public class BetaSymmetricalPolarGen extends BetaSymmetricalGen {
private double afactor; // = 2/(2*alpha - 1)
private RandomStream stream2;
/**
* Creates a symmetrical beta random variate generator with
* parameter α = alpha, using stream s1 to generate x
* and stream s2 to generate y, as in above. Restriction:
* α > 1/2.
*
*/
public BetaSymmetricalPolarGen (RandomStream s1, RandomStream s2,
double alpha) {
super (s1, null);
stream2 = s2;
if (alpha <= 0.5)
throw new IllegalArgumentException (" must have alpha > 1/2");
afactor = 2.0/(2.0*alpha - 1.0);
setParams (alpha, alpha, 0.0, 1.0);
}
/**
* Creates a symmetrical beta random variate generator with
* parameter α = alpha, using stream s1 to generate x
* and y, as in above. Restriction:
* α > 1/2.
*
*/
public BetaSymmetricalPolarGen (RandomStream s1, double alpha) {
this (s1, s1, alpha);
}
/**
* Creates a new generator for the distribution dist, using
* stream s1 to generate x and stream s2 to generate y,
* as in above.
* Restriction: dist must have
* α > 1/2.
*
*/
public BetaSymmetricalPolarGen (RandomStream s1, RandomStream s2,
BetaSymmetricalDist dist) {
super (s1, dist);
stream2 = s2;
double alp = dist.getAlpha();
if (alp <= 0.5)
throw new IllegalArgumentException (" must have alpha > 1/2");
afactor = 2.0/(2.0*dist.getAlpha() - 1.0);
setParams (alp, alp, 0.0, 1.0);
}
/**
* Creates a new generator for the distribution dist,
* using only one stream s1.
* Restriction: dist must have
* α > 1/2.
*
*/
public BetaSymmetricalPolarGen (RandomStream s1,
BetaSymmetricalDist dist) {
this (s1, s1, dist);
}
/**
* Generates a random number using Ulrich's polar method. Stream
* s1 generates x and stream s2 generates y
* [see eq.].
* Restriction:
* α > 1/2.
*
*/
public static double nextDouble (RandomStream s1, RandomStream s2,
double alpha) {
double u, v, S;
do {
u = s1.nextDouble();
v = -1.0 + 2.0*s2.nextDouble();
S = u*u + v*v;
} while (S > 1.0);
return 0.5 + u*v/S* Math.sqrt(1.0 - Math.pow(S, 2.0/(2.0*alpha - 1.0)));
}
/**
* Generates a random number by Ulrich's polar method using
* stream s. Restriction:
* α > 1/2.
*
*/
public static double nextDouble (RandomStream s, double alpha) {
return nextDouble (s, s, alpha);
}
public double nextDouble() {
// Generates a random number using Ulrich's polar method.
double u, v, S;
do {
u = stream.nextDouble();
v = -1.0 + 2.0*stream2.nextDouble();
S = u*u + v*v;
} while (S > 1.0);
return 0.5 + u*v/S* Math.sqrt(1.0 - Math.pow(S, afactor));
}
/**
* Returns stream s2 associated with this object.
*
*/
public RandomStream getStream2() {
return stream2;
}
}
Ads help maintain this website.