⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ranlib.c

📁 一个很好用的常用数学分布实现代码集合
💻 C
📖 第 1 页 / 共 4 页
字号:
               From Modified Normal Distributions.               ACM Trans. Math. Software, 8, 2               (June 1982),163-179********************************************************************************************************************************************                                                                                                                                                 P O I S S O N  DISTRIBUTION                                                                                                                                                                                  ********************************************************************************************************************************************                                                                           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.                                                                            (SLIGHTLY MODIFIED VERSION OF THE PROGRAM IN THE ABOVE ARTICLE)                                                                        **********************************************************************      INTEGER FUNCTION IGNPOI(IR,MU)     INPUT:  IR=CURRENT STATE OF BASIC RANDOM NUMBER GENERATOR             MU=MEAN MU OF THE POISSON DISTRIBUTION     OUTPUT: IGNPOI=SAMPLE FROM THE POISSON-(MU)-DISTRIBUTION     MUPREV=PREVIOUS MU, MUOLD=MU AT LAST EXECUTION OF STEP P OR B.     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*/{extern float fsign( float num, float sign );static float a0 = -0.5;static float a1 = 0.3333333;static float a2 = -0.2500068;static float a3 = 0.2000118;static float a4 = -0.1661269;static float a5 = 0.1421878;static float a6 = -0.1384794;static float a7 = 0.125006;static float muold = 0.0;static float muprev = 0.0;static float fact[10] = {    1.0,1.0,2.0,6.0,24.0,120.0,720.0,5040.0,40320.0,362880.0};static long ignpoi,j,k,kflag,l,m;static float b1,b2,c,c0,c1,c2,c3,d,del,difmuk,e,fk,fx,fy,g,omega,p,p0,px,py,q,s,    t,u,v,x,xx,pp[35];    if(mu == muprev) goto S10;    if(mu < 10.0) goto S120;/*     C A S E  A. (RECALCULATION OF S,D,L IF MU HAS CHANGED)*/    muprev = mu;    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 = (long) (mu-1.1484);S10:/*     STEP N. NORMAL SAMPLE - SNORM(IR) FOR STANDARD NORMAL DEVIATE*/    g = mu+s*snorm();    if(g < 0.0) goto S20;    ignpoi = (long) (g);/*     STEP I. IMMEDIATE ACCEPTANCE IF IGNPOI IS LARGE ENOUGH*/    if(ignpoi >= l) return ignpoi;/*     STEP S. SQUEEZE ACCEPTANCE - SUNIF(IR) FOR (0,1)-SAMPLE U*/    fk = (float)ignpoi;    difmuk = mu-fk;    u = ranf();    if(d*u >= difmuk*difmuk*difmuk) return ignpoi;S20:/*     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(mu == muold) goto S30;    muold = mu;    omega = 0.3989423/s;    b1 = 4.166667E-2/mu;    b2 = 0.3*b1*b1;    c3 = 0.1428571*b1*b2;    c2 = b2-15.0*c3;    c1 = b1-6.0*b2+45.0*c3;    c0 = 1.0-b1+3.0*b2-15.0*c3;    c = 0.1069/mu;S30:    if(g < 0.0) goto S50;/*             'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)*/    kflag = 0;    goto S70;S40:/*     STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)*/    if(fy-u*fy <= py*exp(px-fx)) return ignpoi;S50:/*     STEP E. EXPONENTIAL SAMPLE - SEXPO(IR) FOR STANDARD EXPONENTIAL             DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'             (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)*/    e = sexpo();    u = ranf();    u += (u-1.0);    t = 1.8+fsign(e,u);    if(t <= -0.6744) goto S50;    ignpoi = (long) (mu+s*t);    fk = (float)ignpoi;    difmuk = mu-fk;/*             'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)*/    kflag = 1;    goto S70;S60:/*     STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)*/    if(c*fabs(u) > py*exp(px+e)-fy*exp(fx+e)) goto S50;    return ignpoi;S70:/*     STEP F. 'SUBROUTINE' F. CALCULATION OF PX,PY,FX,FY.             CASE IGNPOI .LT. 10 USES FACTORIALS FROM TABLE FACT*/    if(ignpoi >= 10) goto S80;    px = -mu;    py = pow(mu,(double)ignpoi)/ *(fact+ignpoi);    goto S110;S80:/*             CASE IGNPOI .GE. 10 USES POLYNOMIAL APPROXIMATION             A0-A7 FOR ACCURACY WHEN ADVISABLE             .8333333E-1=1./12.  .3989423=(2*PI)**(-.5)*/    del = 8.333333E-2/fk;    del -= (4.8*del*del*del);    v = difmuk/fk;    if(fabs(v) <= 0.25) goto S90;    px = fk*log(1.0+v)-difmuk-del;    goto S100;S90:    px = fk*v*v*(((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0)-del;S100:    py = 0.3989423/sqrt(fk);S110:    x = (0.5-difmuk)/s;    xx = x*x;    fx = -0.5*xx;    fy = omega*(((c3*xx+c2)*xx+c1)*xx+c0);    if(kflag <= 0) goto S40;    goto S60;S120:/*     C A S E  B. (START NEW TABLE AND CALCULATE P0 IF NECESSARY)*/    muprev = 0.0;    if(mu == muold) goto S130;    muold = mu;    m = max(1L,(long) (mu));    l = 0;    p = exp(-mu);    q = p0 = p;S130:/*     STEP U. UNIFORM SAMPLE FOR INVERSION METHOD*/    u = ranf();    ignpoi = 0;    if(u <= p0) return ignpoi;/*     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) goto S150;    j = 1;    if(u > 0.458) j = min(l,m);    for(k=j; k<=l; k++) {        if(u <= *(pp+k-1)) goto S180;    }    if(l == 35) goto S130;S150:/*     STEP C. CREATION OF NEW POISSON PROBABILITIES P             AND THEIR CUMULATIVES Q=PP(K)*/    l += 1;    for(k=l; k<=35; k++) {        p = p*mu/(float)k;        q += p;        *(pp+k-1) = q;        if(u <= q) goto S170;    }    l = 35;    goto S130;S170:    l = k;S180:    ignpoi = k;    return ignpoi;}long ignuin(long low,long high)/***********************************************************************     long ignuin(long low,long high)               GeNerate Uniform INteger                              Function     Generates an integer uniformly distributed between LOW and HIGH.                              Arguments     low --> Low bound (inclusive) on integer value to be generated     high --> High bound (inclusive) on integer value to be generated                              Note     If (HIGH-LOW) > 2,147,483,561 prints error message on * unit and     stops the program.**********************************************************************     IGNLGI generates integers between 1 and 2147483562     MAXNUM is 1 less than maximum generable value*/{#define maxnum 2147483561Lstatic long ignuin,ign,maxnow,range,ranp1;    if(!(low > high)) goto S10;    fputs(" low > high in ignuin - ABORT",stderr);    exit(1);S10:    range = high-low;    if(!(range > maxnum)) goto S20;    fputs(" high - low too large in ignuin - ABORT",stderr);    exit(1);S20:    if(!(low == high)) goto S30;    ignuin = low;    return ignuin;S30:/*     Number to be generated should be in range 0..RANGE     Set MAXNOW so that the number of integers in 0..MAXNOW is an     integral multiple of the number in 0..RANGE*/    ranp1 = range+1;    maxnow = maxnum/ranp1*ranp1;S40:    ign = ignlgi()-1;    if(!(ign <= maxnow)) goto S50;    ignuin = low+ign%ranp1;    return ignuin;S50:    goto S40;#undef maxnum#undef err1#undef err2}long lennob( char *str )/* Returns the length of str ignoring trailing blanks but not other white space.*/{long i, i_nb;for (i=0, i_nb= -1L; *(str+i); i++)    if ( *(str+i) != ' ' ) i_nb = i;return (i_nb+1);    }long mltmod(long a,long s,long m)/***********************************************************************     long mltmod(long a,long s,long m)                    Returns (A*S) MOD M     This is a transcription from Pascal to Fortran of routine     MULtMod_Decompos from the paper     L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package     with Splitting Facilities." ACM Transactions on Mathematical     Software, 17:98-111 (1991)                              Arguments     a, s, m  -->***********************************************************************/{#define h 32768Lstatic long mltmod,a0,a1,k,p,q,qh,rh;/*     H = 2**((b-2)/2) where b = 32 because we are using a 32 bit      machine. On a different machine recompute H*/    if(!(a <= 0 || a >= m || s <= 0 || s >= m)) goto S10;    fputs(" a, m, s out of order in mltmod - ABORT!",stderr);    fprintf(stderr," a = %12ld s = %12ld m = %12ld\n",a,s,m);    fputs(" mltmod requires: 0 < a < m; 0 < s < m",stderr);    exit(1);S10:    if(!(a < h)) goto S20;    a0 = a;    p = 0;    goto S120;S20:    a1 = a/h;    a0 = a-h*a1;    qh = m/h;    rh = m-h*qh;    if(!(a1 >= h)) goto S50;    a1 -= h;    k = s/qh;    p = h*(s-k*qh)-k*rh;S30:    if(!(p < 0)) goto S40;    p += m;    goto S30;S40:    goto S60;S50:    p = 0;S60:/*     P = (A2*S*H)MOD M*/    if(!(a1 != 0)) goto S90;    q = m/a1;    k = s/q;    p -= (k*(m-a1*q));    if(p > 0) p -= m;    p += (a1*(s-k*q));S70:    if(!(p < 0)) goto S80;    p += m;    goto S70;S90:S80:    k = p/qh;/*     P = ((A2*H + A1)*S)MOD M*/    p = h*(p-k*qh)-k*rh;S100:    if(!(p < 0)) goto S110;    p += m;    goto S100;S120:S110:    if(!(a0 != 0)) goto S150;/*     P = ((A2*H + A1)*H*S)MOD M*/    q = m/a0;    k = s/q;    p -= (k*(m-a0*q));    if(p > 0) p -= m;    p += (a0*(s-k*q));S130:    if(!(p < 0)) goto S140;    p += m;    goto S130;S150:S140:    mltmod = p;    return mltmod;#undef h}void phrtsd(char* phrase,long *seed1,long *seed2)/***********************************************************************     void phrtsd(char* phrase,long *seed1,long *seed2)               PHRase To SeeDs                              Function     Uses a phrase (character string) to generate two seeds for the RGN     random number generator.                              Arguments     phrase --> Phrase to be used for random number generation           seed1 <-- First seed for generator                             seed2 <-- Second seed for generator                                                      Note     Trailing blanks are eliminated before the seeds are generated.     Generated seed values will fall in the range 1..2^30     (1..1,073,741,824)***********************************************************************/{static char table[] ="abcdefghijklmnopqrstuvwxyz\ABCDEFGHIJKLMNOPQRSTUVWXYZ\0123456789\!@#$%^&*()_+[];:'\\\"<>?,./";long ix;static long twop30 = 1073741824L;static long shift[5] = {    1L,64L,4096L,262144L,16777216L};static long i,ichr,j,lphr,values[5];extern long lennob(char *str);    *seed1 = 1234567890L;    *seed2 = 123456789L;    lphr = lennob(phrase);     if(lphr < 1) return;    for(i=0; i<=(lphr-1); i++) {	for (ix=0; table[ix]; ix++) if (*(phrase+i) == table[ix]) break;         if (!table[ix]) ix = 0;        ichr = ix % 64;        if(ichr == 0) ichr = 63;        for(j=1; j<=5; j++) {            *(values+j-1) = ichr-j;            if(*(values+j-1) < 1) *(values+j-1) += 63;        }        for(j=1; j<=5; j++) {            *seed1 = ( *seed1+*(shift+j-1)**(values+j-1) ) % twop30;            *seed2 = ( *seed2+*(shift+j-1)**(values+6-j-1) )  % twop30;        }    }#undef twop30}float ranf(void)/***********************************************************************     float ranf(void)                RANDom number generator as a Function     Returns a random floating point number from a uniform distribution     over 0 - 1 (endpoints of this interval are not returned) using the     current generator     This is a transcription from Pascal to Fortran of routine     Uniform_01 from the paper     L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package     with Splitting Facilities." ACM Transactions on Mathematical     Software, 17:98-111 (1991)***********************************************************************/{static float ranf;/*     4.656613057E-10 is 1/M1  M1 is set in a data statement in IGNLGI      and is currently 2147483563. If M1 changes, change this also.*/    ranf = ignlgi()*4.656613057E-10;    return ranf;}void setgmn(float *meanv,float *covm,long p,float *parm)/***********************************************************************     void setgmn(float *meanv,float *covm,long p,float *parm)            SET Generate Multivariate Normal random deviate                              Function      Places P, MEANV, and the Cholesky factoriztion of COVM      in GENMN.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -