#include "ranlib.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define ABS(x) ((x) >= 0 ? (x) : -(x))
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define max(a,b) ((a) >= (b) ? (a) : (b))
void ftnstop(char*);
float genbet(float aa,float bb)
/*
**********************************************************************
float genbet(float aa,float bb)
GeNerate BETa random deviate
Function
Returns a single random deviate from the beta distribution with
parameters A and B. The density of the beta is
x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1
Arguments
aa --> First parameter of the beta distribution
bb --> Second parameter of the beta distribution
Method
R. C. H. Cheng
Generating Beta Variatew with Nonintegral Shape Parameters
Communications of the ACM, 21:317-322 (1978)
(Algorithms BB and BC)
**********************************************************************
*/
{
#define expmax 89.0
#define infnty 1.0E38
static float olda = -1.0;
static float oldb = -1.0;
static float genbet,a,alpha,b,beta,delta,gamma,k1,k2,r,s,t,u1,u2,v,w,y,z;
static long qsame;
qsame = olda == aa && oldb == bb;
if(qsame) goto S20;
if(!(aa <= 0.0 || bb <= 0.0)) goto S10;
fputs(" AA or BB <= 0 in GENBET - Abort!",stderr);
fprintf(stderr," AA: %16.6E BB %16.6E\n",aa,bb);
exit(1);
S10:
olda = aa;
oldb = bb;
S20:
if(!(min(aa,bb) > 1.0)) goto S100;
/*
Alborithm BB
Initialize
*/
if(qsame) goto S30;
a = min(aa,bb);
b = max(aa,bb);
alpha = a+b;
beta = sqrt((alpha-2.0)/(2.0*a*b-alpha));
gamma = a+1.0/beta;
S30:
S40:
u1 = ranf();
/*
Step 1
*/
u2 = ranf();
v = beta*log(u1/(1.0-u1));
if(!(v > expmax)) goto S50;
w = infnty;
goto S60;
S50:
w = a*exp(v);
S60:
z = pow(u1,2.0)*u2;
r = gamma*v-1.3862944;
s = a+r-w;
/*
Step 2
*/
if(s+2.609438 >= 5.0*z) goto S70;
/*
Step 3
*/
t = log(z);
if(s > t) goto S70;
/*
Step 4
*/
if(r+alpha*log(alpha/(b+w)) < t) goto S40;
S70:
/*
Step 5
*/
if(!(aa == a)) goto S80;
genbet = w/(b+w);
goto S90;
S80:
genbet = b/(b+w);
S90:
goto S230;
S100:
/*
Algorithm BC
Initialize
*/
if(qsame) goto S110;
a = max(aa,bb);
b = min(aa,bb);
alpha = a+b;
beta = 1.0/b;
delta = 1.0+a-b;
k1 = delta*(1.38889E-2+4.16667E-2*b)/(a*beta-0.777778);
k2 = 0.25+(0.5+0.25/delta)*b;
S110:
S120:
u1 = ranf();
/*
Step 1
*/
u2 = ranf();
if(u1 >= 0.5) goto S130;
/*
Step 2
*/
y = u1*u2;
z = u1*y;
if(0.25*u2+z-y >= k1) goto S120;
goto S170;
S130:
/*
Step 3
*/
z = pow(u1,2.0)*u2;
if(!(z <= 0.25)) goto S160;
v = beta*log(u1/(1.0-u1));
if(!(v > expmax)) goto S140;
w = infnty;
goto S150;
S140:
w = a*exp(v);
S150:
goto S200;
S160:
if(z >= k2) goto S120;
S170:
/*
Step 4
Step 5
*/
v = beta*log(u1/(1.0-u1));
if(!(v > expmax)) goto S180;
w = infnty;
goto S190;
S180:
w = a*exp(v);
S190:
if(alpha*(log(alpha/(b+w))+v)-1.3862944 < log(z)) goto S120;
S200:
/*
Step 6
*/
if(!(a == aa)) goto S210;
genbet = w/(b+w);
goto S220;
S210:
genbet = b/(b+w);
S230:
S220:
return genbet;
#undef expmax
#undef infnty
}
float genchi(float df)
/*
**********************************************************************
float genchi(float df)
Generate random value of CHIsquare variable
Function
Generates random deviate from the distribution of a chisquare
with DF degrees of freedom random variable.
Arguments
df --> Degrees of freedom of the chisquare
(Must be positive)
Method
Uses relation between chisquare and gamma.
**********************************************************************
*/
{
static float genchi;
if(!(df <= 0.0)) goto S10;
fputs("DF <= 0 in GENCHI - ABORT",stderr);
fprintf(stderr,"Value of DF: %16.6E\n",df);
exit(1);
S10:
genchi = 2.0*gengam(1.0,df/2.0);
return genchi;
}
float genexp(float av)
/*
**********************************************************************
float genexp(float av)
GENerate EXPonential random deviate
Function
Generates a single random deviate from an exponential
distribution with mean AV.
Arguments
av --> The mean of the exponential distribution from which
a random deviate is to be generated.
Method
Renames SEXPO from TOMS as slightly modified by BWB to use RANF
instead of SUNIF.
For details see:
Ahrens, J.H. and Dieter, U.
Computer Methods for Sampling From the
Exponential and Normal Distributions.
Comm. ACM, 15,10 (Oct. 1972), 873 - 882.
**********************************************************************
*/
{
static float genexp;
genexp = sexpo()*av;
return genexp;
}
float genf(float dfn,float dfd)
/*
**********************************************************************
float genf(float dfn,float dfd)
GENerate random deviate from the F distribution
Function
Generates a random deviate from the F (variance ratio)
distribution with DFN degrees of freedom in the numerator
and DFD degrees of freedom in the denominator.
Arguments
dfn --> Numerator degrees of freedom
(Must be positive)
dfd --> Denominator degrees of freedom
(Must be positive)
Method
Directly generates ratio of chisquare variates
**********************************************************************
*/
{
static float genf,xden,xnum;
if(!(dfn <= 0.0 || dfd <= 0.0)) goto S10;
fputs("Degrees of freedom nonpositive in GENF - abort!",stderr);
fprintf(stderr,"DFN value: %16.6EDFD value: %16.6E\n",dfn,dfd);
exit(1);
S10:
xnum = genchi(dfn)/dfn;
/*
GENF = ( GENCHI( DFN ) / DFN ) / ( GENCHI( DFD ) / DFD )
*/
xden = genchi(dfd)/dfd;
if(!(xden <= 9.999999999998E-39*xnum)) goto S20;
fputs(" GENF - generated numbers would cause overflow",stderr);
fprintf(stderr," Numerator %16.6E Denominator %16.6E\n",xnum,xden);
fputs(" GENF returning 1.0E38",stderr);
genf = 1.0E38;
goto S30;
S20:
genf = xnum/xden;
S30:
return genf;
}
float gengam(float a,float r)
/*
**********************************************************************
float gengam(float a,float r)
GENerates random deviates from GAMma distribution
Function
Generates random deviates from the gamma distribution whose
density is
(A**R)/Gamma(R) * X**(R-1) * Exp(-A*X)
Arguments
a --> Location parameter of Gamma distribution
r --> Shape parameter of Gamma distribution
Method
Renames SGAMMA from TOMS as slightly modified by BWB to use RANF
instead of SUNIF.
For details see:
(Case R >= 1.0)
Ahrens, J.H. and Dieter, U.
Generating Gamma Variates by a
Modified Rejection Technique.
Comm. ACM, 25,1 (Jan. 1982), 47 - 54.
Algorithm GD
(Case 0.0 <= R <= 1.0)
Ahrens, J.H. and Dieter, U.
Computer Methods for Sampling from Gamma,
Beta, Poisson and Binomial Distributions.
Computing, 12 (1974), 223-246/
Adapted algorithm GS.
**********************************************************************
*/
{
static float gengam;
gengam = sgamma(r);
gengam /= a