package umontreal.iro.lecuyer.randvar;
import umontreal.iro.lecuyer.rng.*;
import umontreal.iro.lecuyer.probdist.*;
/**
* This class implements gamma random variate generators using
* a rejection method with loglogistic envelopes,.
* For each gamma variate, the first two uniforms are taken from the
* main stream and all additional uniforms (after the first rejection)
* are obtained from the auxiliary stream.
*
*/
public class GammaRejectionLoglogisticGen extends GammaGen {
private RandomStream auxStream;
// UNURAN parameters for the distribution
private double beta;
private double gamma;
// Generator parameters
// Rejection with log-logistic envelopes
private double aa;
private double bb;
private double cc;
/**
* Creates a gamma random variate generator with parameters α =
* alpha and λ = lambda, using main stream s and
* auxiliary stream aux.
* The auxiliary stream is used when a random number of uniforms
* is required for a rejection-type generation method.
*
*/
public GammaRejectionLoglogisticGen (RandomStream s, RandomStream aux,
double alpha, double lambda) {
super (s, null);
auxStream = aux;
setParams (alpha, lambda);
beta = 1.0/lambda;
gamma = 0.0;
init ();
}
/**
* Creates a gamma random variate generator with parameters α =
* alpha and λ = lambda, using stream s.
*
*/
public GammaRejectionLoglogisticGen (RandomStream s,
double alpha, double lambda) {
this (s, s, alpha, lambda);
}
/**
* Creates a new generator object for the gamma
* distribution dist, using main stream s and
* auxiliary stream aux.
* The auxiliary stream is used when a random number of uniforms
* is required for a rejection-type generation method.
*
*/
public GammaRejectionLoglogisticGen (RandomStream s, RandomStream aux,
GammaDist dist) {
super (s, dist);
auxStream = aux;
if (dist != null)
setParams (dist.getAlpha(), dist.getLambda());
beta = 1.0/dist.getLambda();
gamma = 0.0;
init ();
}
/**
* Creates a new generator object for the gamma
* distribution dist and stream s for both the main and
* auxiliary stream.
*
*/
public GammaRejectionLoglogisticGen (RandomStream s, GammaDist dist) {
this (s, s, dist);
}
/**
* Returns the auxiliary stream associated with this object.
*
*/
public RandomStream getAuxStream() {
return auxStream;
}
public double nextDouble() {
return rejectionLogLogistic
(stream, auxStream, alpha, beta, gamma, aa, bb, cc);
}
/**
* Generates a new gamma variate with parameters
* α = alpha and λ = lambda, using
* main stream s and auxiliary stream aux.
*
*/
public static double nextDouble (RandomStream s, RandomStream aux,
double alpha, double lambda) {
double aa, bb, cc;
// Code taken from UNURAN
aa = (alpha > 1.0) ? Math.sqrt (alpha + alpha - 1.0) : alpha;
bb = alpha - 1.386294361;
cc = alpha + aa;
return rejectionLogLogistic (s, aux, alpha, 1.0/lambda, 0.0, aa, bb, cc);
}
/**
* Same as {@link #nextDouble nextDouble} (s, s, alpha, lambda).
*
*/
public static double nextDouble (RandomStream s, double alpha,
double lambda) {
return nextDouble (s, s, alpha, lambda);
}
private static double rejectionLogLogistic
(RandomStream stream, RandomStream auxStream,
double alpha, double beta, double gamma,
double aa, double bb, double cc) {
// Code taken from UNURAN
double X;
double u1,u2,v,r,z;
while (true) {
u1 = stream.nextDouble();
u2 = stream.nextDouble();
stream = auxStream;
v = Math.log (u1/(1.0 - u1))/aa;
X = alpha*Math.exp (v);
r = bb + cc*v - X;
z = u1*u1*u2;
if (r + 2.504077397 >= 4.5*z) break;
if (r >= Math.log (z)) break;
}
return gamma + beta*X;
}
private void init() {
// Code taken from UNURAN
aa = (alpha > 1.0) ? Math.sqrt (alpha + alpha - 1.0) : alpha;
bb = alpha - 1.386294361;
cc = alpha + aa;
}
}
Ads help maintain this website.