00001 INTEGER FUNCTION ignpoi(mu) 00002 C********************************************************************** 00003 C 00004 C INTEGER FUNCTION IGNPOI( MU ) 00005 C 00006 C GENerate POIsson random deviate 00007 C 00008 C 00009 C Function 00010 C 00011 C 00012 C Generates a single random deviate from a Poisson 00013 C distribution with mean MU. 00014 C 00015 C 00016 C Arguments 00017 C 00018 C 00019 C MU --> The mean of the Poisson distribution from which 00020 C a random deviate is to be generated. 00021 C REAL MU 00022 C JJV (MU >= 0.0) 00023 C 00024 C IGNPOI <-- The random deviate. 00025 C INTEGER IGNPOI (non-negative) 00026 C 00027 C 00028 C Method 00029 C 00030 C 00031 C Renames KPOIS from TOMS as slightly modified by BWB to use RANF 00032 C instead of SUNIF. 00033 C 00034 C For details see: 00035 C 00036 C Ahrens, J.H. and Dieter, U. 00037 C Computer Generation of Poisson Deviates 00038 C From Modified Normal Distributions. 00039 C ACM Trans. Math. Software, 8, 2 00040 C (June 1982),163-179 00041 C 00042 C********************************************************************** 00043 C**********************************************************************C 00044 C**********************************************************************C 00045 C C 00046 C C 00047 C P O I S S O N DISTRIBUTION C 00048 C C 00049 C C 00050 C**********************************************************************C 00051 C**********************************************************************C 00052 C C 00053 C FOR DETAILS SEE: C 00054 C C 00055 C AHRENS, J.H. AND DIETER, U. C 00056 C COMPUTER GENERATION OF POISSON DEVIATES C 00057 C FROM MODIFIED NORMAL DISTRIBUTIONS. C 00058 C ACM TRANS. MATH. SOFTWARE, 8,2 (JUNE 1982), 163 - 179. C 00059 C C 00060 C (SLIGHTLY MODIFIED VERSION OF THE PROGRAM IN THE ABOVE ARTICLE) C 00061 C C 00062 C**********************************************************************C 00063 C 00064 C INTEGER FUNCTION IGNPOI(IR,MU) 00065 C 00066 C INPUT: IR=CURRENT STATE OF BASIC RANDOM NUMBER GENERATOR 00067 C MU=MEAN MU OF THE POISSON DISTRIBUTION 00068 C OUTPUT: IGNPOI=SAMPLE FROM THE POISSON-(MU)-DISTRIBUTION 00069 C 00070 C 00071 C 00072 C MUPREV=PREVIOUS MU, MUOLD=MU AT LAST EXECUTION OF STEP P OR CASE B 00073 C TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT 00074 C COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL 00075 C 00076 C 00077 C 00078 C SEPARATION OF CASES A AND B 00079 C 00080 C .. Scalar Arguments .. 00081 REAL mu 00082 C .. 00083 C .. Local Scalars .. 00084 REAL a0,a1,a2,a3,a4,a5,a6,a7,b1,b2,c,c0,c1,c2,c3,d,del,difmuk,e, 00085 + fk,fx,fy,g,muold,muprev,omega,p,p0,px,py,q,s,t,u,v,x,xx 00086 C JJV I added a variable 'll' here - it is the 'l' for CASE A 00087 INTEGER j,k,kflag,l,ll,m 00088 C .. 00089 C .. Local Arrays .. 00090 REAL fact(10),pp(35) 00091 C .. 00092 C .. External Functions .. 00093 REAL ranf,sexpo,snorm 00094 EXTERNAL ranf,sexpo,snorm 00095 C .. 00096 C .. Intrinsic Functions .. 00097 INTRINSIC abs,alog,exp,float,ifix,max0,min0,sign,sqrt 00098 C .. 00099 C JJV added this for case: mu unchanged 00100 C .. Save statement .. 00101 SAVE s, d, l, ll, omega, c3, c2, c1, c0, c, m, p, q, p0, 00102 + a0, a1, a2, a3, a4, a5, a6, a7, fact, muprev, muold 00103 C .. 00104 C JJV end addition - I am including vars in Data statements 00105 C .. Data statements .. 00106 C JJV changed initial values of MUPREV and MUOLD to -1.0E37 00107 C JJV if no one calls IGNPOI with MU = -1.0E37 the first time, 00108 C JJV the code shouldn't break 00109 DATA muprev,muold/-1.0E37,-1.0E37/ 00110 DATA a0,a1,a2,a3,a4,a5,a6,a7/-.5,.3333333,-.2500068,.2000118, 00111 + -.1661269,.1421878,-.1384794,.1250060/ 00112 DATA fact/1.,1.,2.,6.,24.,120.,720.,5040.,40320.,362880./ 00113 C .. 00114 C .. Executable Statements .. 00115 00116 IF (mu.EQ.muprev) GO TO 10 00117 IF (mu.LT.10.0) GO TO 120 00118 C 00119 C C A S E A. (RECALCULATION OF S,D,LL IF MU HAS CHANGED) 00120 C 00121 C JJV This is the case where I changed 'l' to 'll' 00122 C JJV Here 'll' is set once and used in a comparison once 00123 00124 muprev = mu 00125 s = sqrt(mu) 00126 d = 6.0*mu*mu 00127 C 00128 C THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL 00129 C PROBABILITIES FK WHENEVER K >= M(MU). LL=IFIX(MU-1.1484) 00130 C IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 . 00131 C 00132 ll = ifix(mu-1.1484) 00133 C 00134 C STEP N. NORMAL SAMPLE - SNORM(IR) FOR STANDARD NORMAL DEVIATE 00135 C 00136 10 g = mu + s*snorm() 00137 IF (g.LT.0.0) GO TO 20 00138 ignpoi = ifix(g) 00139 C 00140 C STEP I. IMMEDIATE ACCEPTANCE IF IGNPOI IS LARGE ENOUGH 00141 C 00142 IF (ignpoi.GE.ll) RETURN 00143 C 00144 C STEP S. SQUEEZE ACCEPTANCE - SUNIF(IR) FOR (0,1)-SAMPLE U 00145 C 00146 fk = float(ignpoi) 00147 difmuk = mu - fk 00148 u = ranf() 00149 IF (d*u.GE.difmuk*difmuk*difmuk) RETURN 00150 C 00151 C STEP P. PREPARATIONS FOR STEPS Q AND H. 00152 C (RECALCULATIONS OF PARAMETERS IF NECESSARY) 00153 C .3989423=(2*PI)**(-.5) .416667E-1=1./24. .1428571=1./7. 00154 C THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE 00155 C APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK. 00156 C C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION. 00157 C 00158 20 IF (mu.EQ.muold) GO TO 30 00159 muold = mu 00160 omega = .3989423/s 00161 b1 = .4166667E-1/mu 00162 b2 = .3*b1*b1 00163 c3 = .1428571*b1*b2 00164 c2 = b2 - 15.*c3 00165 c1 = b1 - 6.*b2 + 45.*c3 00166 c0 = 1. - b1 + 3.*b2 - 15.*c3 00167 c = .1069/mu 00168 30 IF (g.LT.0.0) GO TO 50 00169 C 00170 C 'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN) 00171 C 00172 kflag = 0 00173 GO TO 70 00174 C 00175 C STEP Q. QUOTIENT ACCEPTANCE (RARE CASE) 00176 C 00177 40 IF (fy-u*fy.LE.py*exp(px-fx)) RETURN 00178 C 00179 C STEP E. EXPONENTIAL SAMPLE - SEXPO(IR) FOR STANDARD EXPONENTIAL 00180 C DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT' 00181 C (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.) 00182 C 00183 50 e = sexpo() 00184 u = ranf() 00185 u = u + u - 1.0 00186 t = 1.8 + sign(e,u) 00187 IF (t.LE. (-.6744)) GO TO 50 00188 ignpoi = ifix(mu+s*t) 00189 fk = float(ignpoi) 00190 difmuk = mu - fk 00191 C 00192 C 'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN) 00193 C 00194 kflag = 1 00195 GO TO 70 00196 C 00197 C STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION) 00198 C 00199 60 IF (c*abs(u).GT.py*exp(px+e)-fy*exp(fx+e)) GO TO 50 00200 RETURN 00201 C 00202 C STEP F. 'SUBROUTINE' F. CALCULATION OF PX,PY,FX,FY. 00203 C CASE IGNPOI .LT. 10 USES FACTORIALS FROM TABLE FACT 00204 C 00205 70 IF (ignpoi.GE.10) GO TO 80 00206 px = -mu 00207 py = mu**ignpoi/fact(ignpoi+1) 00208 GO TO 110 00209 C 00210 C CASE IGNPOI .GE. 10 USES POLYNOMIAL APPROXIMATION 00211 C A0-A7 FOR ACCURACY WHEN ADVISABLE 00212 C .8333333E-1=1./12. .3989423=(2*PI)**(-.5) 00213 C 00214 80 del = .8333333E-1/fk 00215 del = del - 4.8*del*del*del 00216 v = difmuk/fk 00217 IF (abs(v).LE.0.25) GO TO 90 00218 px = fk*alog(1.0+v) - difmuk - del 00219 GO TO 100 00220 00221 90 px = fk*v*v* (((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0) - 00222 + del 00223 100 py = .3989423/sqrt(fk) 00224 110 x = (0.5-difmuk)/s 00225 xx = x*x 00226 fx = -0.5*xx 00227 fy = omega* (((c3*xx+c2)*xx+c1)*xx+c0) 00228 IF (kflag.LE.0) GO TO 40 00229 GO TO 60 00230 C 00231 C C A S E B. (START NEW TABLE AND CALCULATE P0 IF NECESSARY) 00232 C 00233 C JJV changed MUPREV assignment from 0.0 to initial value 00234 120 muprev = -1.0E37 00235 IF (mu.EQ.muold) GO TO 130 00236 C JJV added argument checker here 00237 IF (mu.GE.0.0) GO TO 125 00238 WRITE (*,*) 'MU < 0 in IGNPOI - ABORT' 00239 WRITE (*,*) 'Value of MU: ',mu 00240 CALL XSTOPX ('MU < 0 in IGNPOI - ABORT') 00241 C JJV added line label here 00242 125 muold = mu 00243 m = max0(1,ifix(mu)) 00244 l = 0 00245 p = exp(-mu) 00246 q = p 00247 p0 = p 00248 C 00249 C STEP U. UNIFORM SAMPLE FOR INVERSION METHOD 00250 C 00251 130 u = ranf() 00252 ignpoi = 0 00253 IF (u.LE.p0) RETURN 00254 C 00255 C STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE 00256 C PP-TABLE OF CUMULATIVE POISSON PROBABILITIES 00257 C (0.458=PP(9) FOR MU=10) 00258 C 00259 IF (l.EQ.0) GO TO 150 00260 j = 1 00261 IF (u.GT.0.458) j = min0(l,m) 00262 DO 140 k = j,l 00263 IF (u.LE.pp(k)) GO TO 180 00264 140 CONTINUE 00265 IF (l.EQ.35) GO TO 130 00266 C 00267 C STEP C. CREATION OF NEW POISSON PROBABILITIES P 00268 C AND THEIR CUMULATIVES Q=PP(K) 00269 C 00270 150 l = l + 1 00271 DO 160 k = l,35 00272 p = p*mu/float(k) 00273 q = q + p 00274 pp(k) = q 00275 IF (u.LE.q) GO TO 170 00276 160 CONTINUE 00277 l = 35 00278 GO TO 130 00279 00280 170 l = k 00281 180 ignpoi = k 00282 RETURN 00283 00284 END