* Collection of random number programs ... by V. Blobel FUNCTION RNUM() * * A simple portable random number generator * There are only 714025 different values (spacing = 1.4 E-6), but * the period is effectively infinite! * * U = RNUM() random U(0,1) (uniform) distributed number * G = RNGA() random N(0,1) (Gaussian with mean 0 and variance 1) * PARAMETER (M=714025,IA=1366,IC=150889) INTEGER IR(97) LOGICAL START REAL RN(2) SAVE START,K,SN,CS,AL,RM,IY,IR,JDUM DATA START/.TRUE./,K/1/ * ... * random U(0,1) number IF(START) THEN * init START=.FALSE. RM=1.0/FLOAT(M) JDUM=-1 JDUM=MOD(IC-JDUM,M) DO J=1,97 JDUM=MOD(IA*JDUM+IC,M) IR(J)=JDUM END DO JDUM=MOD(IA*JDUM+IC,M) IY=JDUM END IF * next U(0,1) random number from array ... J=1+(97*IY)/M IY=IR(J) RNUM=FLOAT(IY)*RM * ... and store new random number in array JDUM=MOD(IA*JDUM+IC,M) IR(J)=JDUM GOTO 100 * ... ENTRY RNGA() * random N(0,1) standard gaussian number IF(START) THEN * init START=.FALSE. RM=1.0/FLOAT(M) JDUM=-1 JDUM=MOD(IC-JDUM,M) DO J=1,97 JDUM=MOD(IA*JDUM+IC,M) IR(J)=JDUM END DO JDUM=MOD(IA*JDUM+IC,M) IY=JDUM END IF * IF(K.LE.1) THEN * one U(0,1) random number J=1+(97*IY)/M IY=IR(J) RNDL=FLOAT(IY)*RM JDUM=MOD(IA*JDUM+IC,M) IR(J)=JDUM * two U(-1,+1) random numbers 10 DO K=1,2 J=1+(97*IY)/M IY=IR(J) RN(K)=FLOAT(2*IY)*RM-1.0 JDUM=MOD(IA*JDUM+IC,M) IR(J)=JDUM END DO RADSQ=RN(1)*RN(1)+RN(2)*RN(2) * test point inside sircle IF(RADSQ.GT.1.0) GOTO 10 * sine and cosine for random phi SN=RN(1)/SQRT(RADSQ) CS=RN(2)/SQRT(RADSQ) * transform to gaussians AL=SQRT(-2.0*ALOG(RNDL)) RNGA=SN*AL K=2 ELSE RNGA=CS*AL K=1 END IF 100 RETURN END FUNCTION NRPOIS(XMU) * random number of Poisson distribution REAL XLAST,EXPXMU SAVE XLAST,EXPXMU DATA XLAST/0.0/,EXPXMU/1.0/ * ... IF(XMU.LE.0.0) THEN NRPOIS=0.0 RETURN END IF IF(XMU.LT.12.0) THEN * small mean value IF(XMU.NE.XLAST) THEN EXPXMU=EXP(XMU) XLAST=XMU END IF K=0 A=1.0 10 A=A*RNUM() IF(A.GE.EXPXMU) THEN K=K+1 GOTO 10 END IF ELSE * large value, normal approximation K=MAX(0.0,XMU+RNGA()*SQRT(XMU)+0.5) END IF NRPOIS=K END