Translated to Fortran 90 by Alan Miller from:
RANLIB
Library of Fortran Routines for Random Number Generation
Compiled and Written by:
Barry W. Brown
James Lovato
Department of Biomathematics, Box 237
The University of Texas, M.D. Anderson Cancer Center
1515 Holcombe Boulevard
Houston, TX 77030
This work was supported by grant CA-16672 from the National Cancer Institute. GENerate POIsson random deviate Function Generates a single random deviate from a Poisson distribution with mean mu. Arguments mu --> The mean of the Poisson distribution from which a random deviate is to be generated. REAL mu Method For details see: Ahrens, J.H. and Dieter, U. Computer Generation of Poisson Deviates From Modified Normal Distributions. ACM Trans. Math. Software, 8, 2 (June 1982),163-179 TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT COEFFICIENTS A(K) - FOR PX = FKVVSUM(A(K)V**K)-DEL SEPARATION OF CASES A AND B .. Scalar Arguments ..
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real, | intent(in) | :: | mu | |||
logical, | intent(in) | :: | first |
FUNCTION random_Poisson(mu, first) RESULT(ival) !********************************************************************** ! Translated to Fortran 90 by Alan Miller from: ! RANLIB ! ! Library of Fortran Routines for Random Number Generation ! ! Compiled and Written by: ! ! Barry W. Brown ! James Lovato ! ! Department of Biomathematics, Box 237 ! The University of Texas, M.D. Anderson Cancer Center ! 1515 Holcombe Boulevard ! Houston, TX 77030 ! ! This work was supported by grant CA-16672 from the National Cancer Institute. ! GENerate POIsson random deviate ! Function ! Generates a single random deviate from a Poisson distribution with mean mu. ! Arguments ! mu --> The mean of the Poisson distribution from which ! a random deviate is to be generated. ! REAL mu ! Method ! For details see: ! Ahrens, J.H. and Dieter, U. ! Computer Generation of Poisson Deviates ! From Modified Normal Distributions. ! ACM Trans. Math. Software, 8, 2 ! (June 1982),163-179 ! TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT ! COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL ! SEPARATION OF CASES A AND B ! .. Scalar Arguments .. REAL, INTENT(IN) :: mu LOGICAL, INTENT(IN) :: first INTEGER :: ival ! .. ! .. Local Scalars .. REAL :: b1, b2, c, c0, c1, c2, c3, del, difmuk, e, fk, fx, fy, g, & omega, px, py, t, u, v, x, xx REAL, SAVE :: s, d, p, q, p0 INTEGER :: j, k, kflag LOGICAL, SAVE :: full_init INTEGER, SAVE :: l, m ! .. ! .. Local Arrays .. REAL, SAVE :: pp(35) ! .. ! .. Data statements .. REAL, PARAMETER :: a0 = -.5, a1 = .3333333, a2 = -.2500068, a3 = .2000118, & a4 = -.1661269, a5 = .1421878, a6 = -.1384794, & a7 = .1250060 REAL, PARAMETER :: fact(10) = (/ 1., 1., 2., 6., 24., 120., 720., 5040., & 40320., 362880. /) ! .. ! .. Executable Statements .. IF (mu > 10.0) THEN ! C A S E A. (RECALCULATION OF S, D, L IF MU HAS CHANGED) IF (first) THEN s = SQRT(mu) d = 6.0*mu*mu ! THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL ! PROBABILITIES FK WHENEVER K >= M(MU). L=IFIX(MU-1.1484) ! IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 . l = mu - 1.1484 full_init = .false. END IF ! STEP N. NORMAL SAMPLE - random_normal() FOR STANDARD NORMAL DEVIATE g = mu + s*random_normal() IF (g > 0.0) THEN ival = g ! STEP I. IMMEDIATE ACCEPTANCE IF ival IS LARGE ENOUGH IF (ival>=l) RETURN ! STEP S. SQUEEZE ACCEPTANCE - SAMPLE U fk = ival difmuk = mu - fk CALL RANDOM_NUMBER(u) IF (d*u >= difmuk*difmuk*difmuk) RETURN END IF ! STEP P. PREPARATIONS FOR STEPS Q AND H. ! (RECALCULATIONS OF PARAMETERS IF NECESSARY) ! .3989423=(2*PI)**(-.5) .416667E-1=1./24. .1428571=1./7. ! THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE ! APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK. ! C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION. IF (.NOT. full_init) THEN omega = .3989423/s b1 = .4166667E-1/mu b2 = .3*b1*b1 c3 = .1428571*b1*b2 c2 = b2 - 15.*c3 c1 = b1 - 6.*b2 + 45.*c3 c0 = 1. - b1 + 3.*b2 - 15.*c3 c = .1069/mu full_init = .true. END IF IF (g < 0.0) GO TO 50 ! 'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN) kflag = 0 GO TO 70 ! STEP Q. QUOTIENT ACCEPTANCE (RARE CASE) 40 IF (fy-u*fy <= py*EXP(px-fx)) RETURN ! STEP E. EXPONENTIAL SAMPLE - random_exponential() FOR STANDARD EXPONENTIAL ! DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT' ! (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.) 50 e = random_exponential() CALL RANDOM_NUMBER(u) u = u + u - one t = 1.8 + SIGN(e, u) IF (t <= (-.6744)) GO TO 50 ival = mu + s*t fk = ival difmuk = mu - fk ! 'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN) kflag = 1 GO TO 70 ! STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)\ 60 IF (c*ABS(u) > py*EXP(px+e) - fy*EXP(fx+e)) GO TO 50 RETURN ! STEP F. 'SUBROUTINE' F. CALCULATION OF PX, PY, FX, FY. ! CASE ival < 10 USES FACTORIALS FROM TABLE FACT 70 IF (ival>=10) GO TO 80 px = -mu py = mu**ival/fact(ival+1) GO TO 110 ! CASE ival >= 10 USES POLYNOMIAL APPROXIMATION ! A0-A7 FOR ACCURACY WHEN ADVISABLE ! .8333333E-1=1./12. .3989423=(2*PI)**(-.5) 80 del = .8333333E-1/fk del = del - 4.8*del*del*del v = difmuk/fk IF (ABS(v)>0.25) THEN px = fk*LOG(one + v) - difmuk - del ELSE px = fk*v*v* (((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0) - del END IF py = .3989423/SQRT(fk) 110 x = (half - difmuk)/s xx = x*x fx = -half*xx fy = omega* (((c3*xx + c2)*xx + c1)*xx + c0) IF (kflag <= 0) GO TO 40 GO TO 60 !--------------------------------------------------------------------------- ! C A S E B. mu < 10 ! START NEW TABLE AND CALCULATE P0 IF NECESSARY ELSE IF (first) THEN m = MAX(1, INT(mu)) l = 0 p = EXP(-mu) q = p p0 = p END IF ! STEP U. UNIFORM SAMPLE FOR INVERSION METHOD DO CALL RANDOM_NUMBER(u) ival = 0 IF (u <= p0) RETURN ! STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE ! PP-TABLE OF CUMULATIVE POISSON PROBABILITIES ! (0.458=PP(9) FOR MU=10) IF (l == 0) GO TO 150 j = 1 IF (u > 0.458) j = MIN(l, m) DO k = j, l IF (u <= pp(k)) GO TO 180 END DO IF (l == 35) CYCLE ! STEP C. CREATION OF NEW POISSON PROBABILITIES P ! AND THEIR CUMULATIVES Q=PP(K) 150 l = l + 1 DO k = l, 35 p = p*mu / k q = q + p pp(k) = q IF (u <= q) GO TO 170 END DO l = 35 END DO 170 l = k 180 ival = k RETURN END IF RETURN END FUNCTION random_Poisson