📄 ranlib.c
字号:
Arguments meanv --> Mean vector of multivariate normal distribution. covm <--> (Input) Covariance matrix of the multivariate normal distribution (Output) Destroyed on output p --> Dimension of the normal, or length of MEANV. parm <-- Array of parameters needed to generate multivariate norma deviates (P, MEANV and Cholesky decomposition of COVM). 1 : 1 - P 2 : P + 1 - MEANV P+2 : P*(P+3)/2 + 1 - Cholesky decomposition of COVM Needed dimension is (p*(p+3)/2 + 1)***********************************************************************/{extern void spofa(float *a,long lda,long n,long *info);static long T1;static long i,icount,info,j,D2,D3,D4,D5; T1 = p*(p+3)/2+1;/* TEST THE INPUT*/ if(!(p <= 0)) goto S10; fputs("P nonpositive in SETGMN",stderr); fprintf(stderr,"Value of P: %12ld\n",p); exit(1);S10: *parm = p;/* PUT P AND MEANV INTO PARM*/ for(i=2,D2=1,D3=(p+1-i+D2)/D2; D3>0; D3--,i+=D2) *(parm+i-1) = *(meanv+i-2);/* Cholesky decomposition to find A s.t. trans(A)*(A) = COVM*/ spofa(covm,p,p,&info); if(!(info != 0)) goto S30; fputs(" COVM not positive definite in SETGMN",stderr); exit(1);S30: icount = p+1;/* PUT UPPER HALF OF A, WHICH IS NOW THE CHOLESKY FACTOR, INTO PARM COVM(1,1) = PARM(P+2) COVM(1,2) = PARM(P+3) : COVM(1,P) = PARM(2P+1) COVM(2,2) = PARM(2P+2) ...*/ for(i=1,D4=1,D5=(p-i+D4)/D4; D5>0; D5--,i+=D4) { for(j=i-1; j<p; j++) { icount += 1; *(parm+icount-1) = *(covm+i-1+j*p); } }}float sexpo(void)/*********************************************************************** (STANDARD-) E X P O N E N T I A L DISTRIBUTION ******************************************************************************************************************************************** FOR DETAILS SEE: AHRENS, J.H. AND DIETER, U. COMPUTER METHODS FOR SAMPLING FROM THE EXPONENTIAL AND NORMAL DISTRIBUTIONS. COMM. ACM, 15,10 (OCT. 1972), 873 - 882. ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM 'SA' IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION) Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of SUNIF. The argument IR thus goes away. ********************************************************************** Q(N) = SUM(ALOG(2.0)**K/K!) K=1,..,N , THE HIGHEST N (HERE 8) IS DETERMINED BY Q(N)=1.0 WITHIN STANDARD PRECISION*/{static float q[8] = { 0.6931472,0.9333737,0.9888778,0.9984959,0.9998293,0.9999833,0.9999986,1.0};static long i;static float sexpo,a,u,ustar,umin;static float *q1 = q; a = 0.0; u = ranf(); goto S30;S20: a += *q1;S30: u += u; if(u <= 1.0) goto S20; u -= 1.0; if(u > *q1) goto S60; sexpo = a+u; return sexpo;S60: i = 1; ustar = ranf(); umin = ustar;S70: ustar = ranf(); if(ustar < umin) umin = ustar; i += 1; if(u > *(q+i-1)) goto S70; sexpo = a+umin**q1; return sexpo;}float sgamma(float a)/*********************************************************************** (STANDARD-) G A M M A DISTRIBUTION ******************************************************************************************************************************************** PARAMETER A >= 1.0 ! ********************************************************************** FOR DETAILS SEE: AHRENS, J.H. AND DIETER, U. GENERATING GAMMA VARIATES BY A MODIFIED REJECTION TECHNIQUE. COMM. ACM, 25,1 (JAN. 1982), 47 - 54. STEP NUMBERS CORRESPOND TO ALGORITHM 'GD' IN THE ABOVE PAPER (STRAIGHTFORWARD IMPLEMENTATION) Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of SUNIF. The argument IR thus goes away. ********************************************************************** PARAMETER 0.0 < A < 1.0 ! ********************************************************************** FOR DETAILS SEE: AHRENS, J.H. AND DIETER, U. COMPUTER METHODS FOR SAMPLING FROM GAMMA, BETA, POISSON AND BINOMIAL DISTRIBUTIONS. COMPUTING, 12 (1974), 223 - 246. (ADAPTED IMPLEMENTATION OF ALGORITHM 'GS' IN THE ABOVE PAPER) ********************************************************************** INPUT: A =PARAMETER (MEAN) OF THE STANDARD GAMMA DISTRIBUTION OUTPUT: SGAMMA = SAMPLE FROM THE GAMMA-(A)-DISTRIBUTION COEFFICIENTS Q(K) - FOR Q0 = SUM(Q(K)*A**(-K)) COEFFICIENTS A(K) - FOR Q = Q0+(T*T/2)*SUM(A(K)*V**K) COEFFICIENTS E(K) - FOR EXP(Q)-1 = SUM(E(K)*Q**K) PREVIOUS A PRE-SET TO ZERO - AA IS A', AAA IS A" SQRT32 IS THE SQUAREROOT OF 32 = 5.656854249492380*/{extern float fsign( float num, float sign );static float q1 = 4.166669E-2;static float q2 = 2.083148E-2;static float q3 = 8.01191E-3;static float q4 = 1.44121E-3;static float q5 = -7.388E-5;static float q6 = 2.4511E-4;static float q7 = 2.424E-4;static float a1 = 0.3333333;static float a2 = -0.250003;static float a3 = 0.2000062;static float a4 = -0.1662921;static float a5 = 0.1423657;static float a6 = -0.1367177;static float a7 = 0.1233795;static float e1 = 1.0;static float e2 = 0.4999897;static float e3 = 0.166829;static float e4 = 4.07753E-2;static float e5 = 1.0293E-2;static float aa = 0.0;static float aaa = 0.0;static float sqrt32 = 5.656854;static float sgamma,s2,s,d,t,x,u,r,q0,b,si,c,v,q,e,w,p; if(a == aa) goto S10; if(a < 1.0) goto S120;/* STEP 1: RECALCULATIONS OF S2,S,D IF A HAS CHANGED*/ aa = a; s2 = a-0.5; s = sqrt(s2); d = sqrt32-12.0*s;S10:/* STEP 2: T=STANDARD NORMAL DEVIATE, X=(S,1/2)-NORMAL DEVIATE. IMMEDIATE ACCEPTANCE (I)*/ t = snorm(); x = s+0.5*t; sgamma = x*x; if(t >= 0.0) return sgamma;/* STEP 3: U= 0,1 -UNIFORM SAMPLE. SQUEEZE ACCEPTANCE (S)*/ u = ranf(); if(d*u <= t*t*t) return sgamma;/* STEP 4: RECALCULATIONS OF Q0,B,SI,C IF NECESSARY*/ if(a == aaa) goto S40; aaa = a; r = 1.0/ a; q0 = ((((((q7*r+q6)*r+q5)*r+q4)*r+q3)*r+q2)*r+q1)*r;/* APPROXIMATION DEPENDING ON SIZE OF PARAMETER A THE CONSTANTS IN THE EXPRESSIONS FOR B, SI AND C WERE ESTABLISHED BY NUMERICAL EXPERIMENTS*/ if(a <= 3.686) goto S30; if(a <= 13.022) goto S20;/* CASE 3: A .GT. 13.022*/ b = 1.77; si = 0.75; c = 0.1515/s; goto S40;S20:/* CASE 2: 3.686 .LT. A .LE. 13.022*/ b = 1.654+7.6E-3*s2; si = 1.68/s+0.275; c = 6.2E-2/s+2.4E-2; goto S40;S30:/* CASE 1: A .LE. 3.686*/ b = 0.463+s+0.178*s2; si = 1.235; c = 0.195/s-7.9E-2+1.6E-1*s;S40:/* STEP 5: NO QUOTIENT TEST IF X NOT POSITIVE*/ if(x <= 0.0) goto S70;/* STEP 6: CALCULATION OF V AND QUOTIENT Q*/ v = t/(s+s); if(fabs(v) <= 0.25) goto S50; q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v); goto S60;S50: q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;S60:/* STEP 7: QUOTIENT ACCEPTANCE (Q)*/ if(log(1.0-u) <= q) return sgamma;S70:/* STEP 8: E=STANDARD EXPONENTIAL DEVIATE U= 0,1 -UNIFORM DEVIATE T=(B,SI)-DOUBLE EXPONENTIAL (LAPLACE) SAMPLE*/ e = sexpo(); u = ranf(); u += (u-1.0); t = b+fsign(si*e,u);/* STEP 9: REJECTION IF T .LT. TAU(1) = -.71874483771719*/ if(t < -0.7187449) goto S70;/* STEP 10: CALCULATION OF V AND QUOTIENT Q*/ v = t/(s+s); if(fabs(v) <= 0.25) goto S80; q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v); goto S90;S80: q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;S90:/* STEP 11: HAT ACCEPTANCE (H) (IF Q NOT POSITIVE GO TO STEP 8)*/ if(q <= 0.0) goto S70; if(q <= 0.5) goto S100; w = exp(q)-1.0; goto S110;S100: w = ((((e5*q+e4)*q+e3)*q+e2)*q+e1)*q;S110:/* IF T IS REJECTED, SAMPLE AGAIN AT STEP 8*/ if(c*fabs(u) > w*exp(e-0.5*t*t)) goto S70; x = s+0.5*t; sgamma = x*x; return sgamma;S120:/* ALTERNATE METHOD FOR PARAMETERS A BELOW 1 (.3678794=EXP(-1.))*/ aa = 0.0; b = 1.0+0.3678794*a;S130: p = b*ranf(); if(p >= 1.0) goto S140; sgamma = exp(log(p)/ a); if(sexpo() < sgamma) goto S130; return sgamma;S140: sgamma = -log((b-p)/ a); if(sexpo() < (1.0-a)*log(sgamma)) goto S130; return sgamma;}float snorm(void)/*********************************************************************** (STANDARD-) N O R M A L DISTRIBUTION ******************************************************************************************************************************************** FOR DETAILS SEE: AHRENS, J.H. AND DIETER, U. EXTENSIONS OF FORSYTHE'S METHOD FOR RANDOM SAMPLING FROM THE NORMAL DISTRIBUTION. MATH. COMPUT., 27,124 (OCT. 1973), 927 - 937. ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM 'FL' (M=5) IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION) Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of SUNIF. The argument IR thus goes away. ********************************************************************** THE DEFINITIONS OF THE CONSTANTS A(K), D(K), T(K) AND H(K) ARE ACCORDING TO THE ABOVEMENTIONED ARTICLE*/{static float a[32] = { 0.0,3.917609E-2,7.841241E-2,0.11777,0.1573107,0.1970991,0.2372021,0.2776904, 0.3186394,0.36013,0.4022501,0.4450965,0.4887764,0.5334097,0.5791322, 0.626099,0.6744898,0.7245144,0.7764218,0.8305109,0.8871466,0.9467818, 1.00999,1.077516,1.150349,1.229859,1.318011,1.417797,1.534121,1.67594, 1.862732,2.153875};static float d[31] = { 0.0,0.0,0.0,0.0,0.0,0.2636843,0.2425085,0.2255674,0.2116342,0.1999243, 0.1899108,0.1812252,0.1736014,0.1668419,0.1607967,0.1553497,0.1504094, 0.1459026,0.14177,0.1379632,0.1344418,0.1311722,0.128126,0.1252791, 0.1226109,0.1201036,0.1177417,0.1155119,0.1134023,0.1114027,0.1095039};static float t[31] = { 7.673828E-4,2.30687E-3,3.860618E-3,5.438454E-3,7.0507E-3,8.708396E-3, 1.042357E-2,1.220953E-2,1.408125E-2,1.605579E-2,1.81529E-2,2.039573E-2, 2.281177E-2,2.543407E-2,2.830296E-2,3.146822E-2,3.499233E-2,3.895483E-2, 4.345878E-2,4.864035E-2,5.468334E-2,6.184222E-2,7.047983E-2,8.113195E-2, 9.462444E-2,0.1123001,0.136498,0.1716886,0.2276241,0.330498,0.5847031};static float h[31] = { 3.920617E-2,3.932705E-2,3.951E-2,3.975703E-2,4.007093E-2,4.045533E-2, 4.091481E-2,4.145507E-2,4.208311E-2,4.280748E-2,4.363863E-2,4.458932E-2, 4.567523E-2,4.691571E-2,4.833487E-2,4.996298E-2,5.183859E-2,5.401138E-2, 5.654656E-2,5.95313E-2,6.308489E-2,6.737503E-2,7.264544E-2,7.926471E-2, 8.781922E-2,9.930398E-2,0.11556,0.1404344,0.1836142,0.2790016,0.7010474};static long i;static float snorm,u,s,ustar,aa,w,y,tt; u = ranf(); s = 0.0; if(u > 0.5) s = 1.0; u += (u-s); u = 32.0*u; i = (long) (u); if(i == 32) i = 31; if(i == 0) goto S100;/* START CENTER*/ ustar = u-(float)i; aa = *(a+i-1);S40: if(ustar <= *(t+i-1)) goto S60; w = (ustar-*(t+i-1))**(h+i-1);S50:/* EXIT (BOTH CASES)*/ y = aa+w; snorm = y; if(s == 1.0) snorm = -y; return snorm;S60:/* CENTER CONTINUED*/ u = ranf(); w = u*(*(a+i)-aa); tt = (0.5*w+aa)*w; goto S80;S70: tt = u; ustar = ranf();S80: if(ustar > tt) goto S50; u = ranf(); if(ustar >= u) goto S70; ustar = ranf(); goto S40;S100:/* START TAIL*/ i = 6; aa = *(a+31); goto S120;S110: aa += *(d+i-1); i += 1;S120: u += u; if(u < 1.0) goto S110; u -= 1.0;S140: w = u**(d+i-1); tt = (0.5*w+aa)*w; goto S160;S150: tt = u;S160: ustar = ranf(); if(ustar > tt) goto S50; u = ranf(); if(ustar >= u) goto S150; u = ranf(); goto S140;}float fsign( float num, float sign )/* Transfers sign of argument sign to argument num */{if ( ( sign>0.0f && num<0.0f ) || ( sign<0.0f && num>0.0f ) ) return -num;else return num;}/************************************************************************FTNSTOP:Prints msg to standard error and then exits************************************************************************/void ftnstop(char* msg)/* msg - error message */{ if (msg != NULL) fprintf(stderr,"%s\n",msg); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -