genbet.f

Go to the documentation of this file.
00001       REAL FUNCTION genbet(aa,bb)
00002 C**********************************************************************
00003 C
00004 C     REAL FUNCTION GENBET( A, B )
00005 C               GeNerate BETa random deviate
00006 C
00007 C
00008 C                              Function
00009 C
00010 C
00011 C     Returns a single random deviate from the beta distribution with
00012 C     parameters A and B.  The density of the beta is
00013 C               x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1
00014 C
00015 C
00016 C                              Arguments
00017 C
00018 C
00019 C     A --> First parameter of the beta distribution
00020 C                         REAL A
00021 C     JJV                 (A > 1.0E-37)
00022 C
00023 C     B --> Second parameter of the beta distribution
00024 C                         REAL B
00025 C     JJV                 (B > 1.0E-37)
00026 C
00027 C
00028 C                              Method
00029 C
00030 C
00031 C     R. C. H. Cheng
00032 C     Generating Beta Variates with Nonintegral Shape Parameters
00033 C     Communications of the ACM, 21:317-322  (1978)
00034 C     (Algorithms BB and BC)
00035 C
00036 C**********************************************************************
00037 C     .. Parameters ..
00038 C     Close to the largest number that can be exponentiated
00039       REAL expmax
00040 C     JJV changed this - 89 was too high, and LOG(1.0E38) = 87.49823
00041       PARAMETER (expmax=87.49823)
00042 C     Close to the largest representable single precision number
00043       REAL infnty
00044       PARAMETER (infnty=1.0E38)
00045 C     JJV added the parameter minlog
00046 C     Close to the smallest number of which a LOG can be taken.
00047       REAL minlog
00048       PARAMETER (minlog=1.0E-37)
00049 C     ..
00050 C     .. Scalar Arguments ..
00051       REAL aa,bb
00052 C     ..
00053 C     .. Local Scalars ..
00054       REAL a,alpha,b,beta,delta,gamma,k1,k2,olda,oldb,r,s,t,u1,u2,v,w,y,
00055      +     z
00056       LOGICAL qsame
00057 C     ..
00058 C     .. External Functions ..
00059       REAL ranf
00060       EXTERNAL ranf
00061 C     ..
00062 C     .. Intrinsic Functions ..
00063       INTRINSIC exp,log,max,min,sqrt
00064 C     ..
00065 C     .. Save statement ..
00066 C     JJV added a,b
00067       SAVE olda,oldb,alpha,beta,gamma,k1,k2,a,b
00068 C     ..
00069 C     .. Data statements ..
00070 C     JJV changed these to ridiculous values
00071       DATA olda,oldb/-1.0E37,-1.0E37/
00072 C     ..
00073 C     .. Executable Statements ..
00074       qsame = (olda.EQ.aa) .AND. (oldb.EQ.bb)
00075       IF (qsame) GO TO 20
00076 C     JJV added small minimum for small log problem in calc of W
00077       IF (.NOT. (aa.LT.minlog.OR.bb.LT.minlog)) GO TO 10
00078       WRITE (*,*) ' AA or BB < ',minlog,' in GENBET - Abort!'
00079       WRITE (*,*) ' AA: ',aa,' BB ',bb
00080       CALL XSTOPX (' AA or BB too small in GENBET - Abort!')
00081 
00082    10 olda = aa
00083       oldb = bb
00084    20 IF (.NOT. (min(aa,bb).GT.1.0)) GO TO 100
00085 
00086 
00087 C     Alborithm BB
00088 
00089 C
00090 C     Initialize
00091 C
00092       IF (qsame) GO TO 30
00093       a = min(aa,bb)
00094       b = max(aa,bb)
00095       alpha = a + b
00096       beta = sqrt((alpha-2.0)/ (2.0*a*b-alpha))
00097       gamma = a + 1.0/beta
00098    30 CONTINUE
00099    40 u1 = ranf()
00100 C
00101 C     Step 1
00102 C
00103       u2 = ranf()
00104       v = beta*log(u1/ (1.0-u1))
00105 C     JJV altered this
00106       IF (v.GT.expmax) GO TO 55
00107 C     JJV added checker to see if a*exp(v) will overflow
00108 C     JJV 50 _was_ w = a*exp(v); also note here a > 1.0
00109    50 w = exp(v)
00110       IF (w.GT.infnty/a) GO TO 55
00111       w = a*w
00112       GO TO 60
00113  55   w = infnty
00114 
00115    60 z = u1**2*u2
00116       r = gamma*v - 1.3862944
00117       s = a + r - w
00118 C
00119 C     Step 2
00120 C
00121       IF ((s+2.609438).GE. (5.0*z)) GO TO 70
00122 C
00123 C     Step 3
00124 C
00125       t = log(z)
00126       IF (s.GT.t) GO TO 70
00127 C
00128 C     Step 4
00129 C
00130 C     JJV added checker to see if log(alpha/(b+w)) will 
00131 C     JJV overflow.  If so, we count the log as -INF, and
00132 C     JJV consequently evaluate conditional as true, i.e.
00133 C     JJV the algorithm rejects the trial and starts over
00134 C     JJV May not need this here since ALPHA > 2.0
00135       IF (alpha/(b+w).LT.minlog) GO TO 40
00136 
00137       IF ((r+alpha*log(alpha/ (b+w))).LT.t) GO TO 40
00138 C
00139 C     Step 5
00140 C
00141    70 IF (.NOT. (aa.EQ.a)) GO TO 80
00142       genbet = w/ (b+w)
00143       GO TO 90
00144 
00145    80 genbet = b/ (b+w)
00146    90 GO TO 230
00147 
00148 
00149 C     Algorithm BC
00150 
00151 C
00152 C     Initialize
00153 C
00154   100 IF (qsame) GO TO 110
00155       a = max(aa,bb)
00156       b = min(aa,bb)
00157       alpha = a + b
00158       beta = 1.0/b
00159       delta = 1.0 + a - b
00160       k1 = delta* (0.0138889+0.0416667*b)/ (a*beta-0.777778)
00161       k2 = 0.25 + (0.5+0.25/delta)*b
00162   110 CONTINUE
00163   120 u1 = ranf()
00164 C
00165 C     Step 1
00166 C
00167       u2 = ranf()
00168       IF (u1.GE.0.5) GO TO 130
00169 C
00170 C     Step 2
00171 C
00172       y = u1*u2
00173       z = u1*y
00174       IF ((0.25*u2+z-y).GE.k1) GO TO 120
00175       GO TO 170
00176 C
00177 C     Step 3
00178 C
00179   130 z = u1**2*u2
00180       IF (.NOT. (z.LE.0.25)) GO TO 160
00181       v = beta*log(u1/ (1.0-u1))
00182 
00183 C     JJV instead of checking v > expmax at top, I will check
00184 C     JJV if a < 1, then check the appropriate values
00185 
00186       IF (a.GT.1.0) GO TO 135
00187 C     JJV A < 1 so it can help out if EXP(V) would overflow
00188       IF (v.GT.expmax) GO TO 132
00189       w = a*exp(v)
00190       GO TO 200
00191  132  w = v + log(a)
00192       IF (w.GT.expmax) GO TO 140
00193       w = exp(w)
00194       GO TO 200
00195 
00196 C     JJV in this case A > 1
00197  135  IF (v.GT.expmax) GO TO 140
00198       w = exp(v)
00199       IF (w.GT.infnty/a) GO TO 140
00200       w = a*w
00201       GO TO 200
00202  140  w = infnty
00203       GO TO 200
00204 
00205   160 IF (z.GE.k2) GO TO 120
00206 C
00207 C     Step 4
00208 C
00209 C
00210 C     Step 5
00211 C
00212   170 v = beta*log(u1/ (1.0-u1))
00213 
00214 C     JJV same kind of checking as above
00215       IF (a.GT.1.0) GO TO 175
00216 C     JJV A < 1 so it can help out if EXP(V) would overflow
00217       IF (v.GT.expmax) GO TO 172
00218       w = a*exp(v)
00219       GO TO 190
00220  172  w = v + log(a)
00221       IF (w.GT.expmax) GO TO 180
00222       w = exp(w)
00223       GO TO 190
00224 
00225 C     JJV in this case A > 1
00226  175  IF (v.GT.expmax) GO TO 180
00227       w = exp(v)
00228       IF (w.GT.infnty/a) GO TO 180
00229       w = a*w
00230       GO TO 190
00231 
00232   180 w = infnty
00233 
00234 C     JJV here we also check to see if log overlows; if so, we treat it
00235 C     JJV as -INF, which means condition is true, i.e. restart
00236   190 IF (alpha/(b+w).LT.minlog) GO TO 120
00237       IF ((alpha* (log(alpha/ (b+w))+v)-1.3862944).LT.log(z)) GO TO 120
00238 C
00239 C     Step 6
00240 C
00241   200 IF (.NOT. (a.EQ.aa)) GO TO 210
00242       genbet = w/ (b+w)
00243       GO TO 220
00244 
00245   210 genbet = b/ (b+w)
00246   220 CONTINUE
00247   230 RETURN
00248 
00249       END
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines