Annotation of capa/capa51/pProj/ranlib.c, revision 1.1.1.1
1.1 albertel 1:
2: #include "ranlib.h"
3: #include <stdio.h>
4: #include <math.h>
5: #include <stdlib.h>
6: #define abs(x) ((x) >= 0 ? (x) : -(x))
7: #define min(a,b) ((a) <= (b) ? (a) : (b))
8: #define max(a,b) ((a) >= (b) ? (a) : (b))
9:
10: /*
11: **********************************************************************
12: float genbet(float aa,float bb)
13: GeNerate BETa random deviate
14: Function
15: Returns a single random deviate from the beta distribution with
16: parameters A and B. The density of the beta is
17: x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1
18: Arguments
19: aa --> First parameter of the beta distribution
20:
21: bb --> Second parameter of the beta distribution
22:
23: Method
24: R. C. H. Cheng
25: Generating Beta Variatew with Nonintegral Shape Parameters
26: Communications of the ACM, 21:317-322 (1978)
27: (Algorithms BB and BC)
28: **********************************************************************
29: */
30: float genbet(float aa,float bb)
31: {
32: #define expmax 89.0
33: #define infnty 1.0E38
34: static float olda = -1.0;
35: static float oldb = -1.0;
36: static float genbet,a,alpha,b,beta,delta,gamma,k1,k2,r,s,t,u1,u2,v,w,y,z;
37: static long qsame;
38:
39: qsame = olda == aa && oldb == bb;
40: if(qsame) goto S20;
41: if(!(aa <= 0.0 || bb <= 0.0)) goto S10;
42: puts(" AA or BB <= 0 in GENBET - Abort!");
43: printf(" AA: %16.6E BB %16.6E\n",aa,bb);
44: exit(1);
45: S10:
46: olda = aa;
47: oldb = bb;
48: S20:
49: if(!(min(aa,bb) > 1.0)) goto S100;
50: /*
51: Alborithm BB
52: Initialize
53: */
54: if(qsame) goto S30;
55: a = min(aa,bb);
56: b = max(aa,bb);
57: alpha = a+b;
58: beta = sqrt((alpha-2.0)/(2.0*a*b-alpha));
59: gamma = a+1.0/beta;
60: S30:
61: S40:
62: u1 = ranf();
63: /*
64: Step 1
65: */
66: u2 = ranf();
67: v = beta*log(u1/(1.0-u1));
68: if(!(v > expmax)) goto S50;
69: w = infnty;
70: goto S60;
71: S50:
72: w = a*exp(v);
73: S60:
74: z = pow(u1,2.0)*u2;
75: r = gamma*v-1.3862944;
76: s = a+r-w;
77: /*
78: Step 2
79: */
80: if(s+2.609438 >= 5.0*z) goto S70;
81: /*
82: Step 3
83: */
84: t = log(z);
85: if(s > t) goto S70;
86: /*
87: Step 4
88: */
89: if(r+alpha*log(alpha/(b+w)) < t) goto S40;
90: S70:
91: /*
92: Step 5
93: */
94: if(!(aa == a)) goto S80;
95: genbet = w/(b+w);
96: goto S90;
97: S80:
98: genbet = b/(b+w);
99: S90:
100: goto S230;
101: S100:
102: /*
103: Algorithm BC
104: Initialize
105: */
106: if(qsame) goto S110;
107: a = max(aa,bb);
108: b = min(aa,bb);
109: alpha = a+b;
110: beta = 1.0/b;
111: delta = 1.0+a-b;
112: k1 = delta*(1.38889E-2+4.16667E-2*b)/(a*beta-0.777778);
113: k2 = 0.25+(0.5+0.25/delta)*b;
114: S110:
115: S120:
116: u1 = ranf();
117: /*
118: Step 1
119: */
120: u2 = ranf();
121: if(u1 >= 0.5) goto S130;
122: /*
123: Step 2
124: */
125: y = u1*u2;
126: z = u1*y;
127: if(0.25*u2+z-y >= k1) goto S120;
128: goto S170;
129: S130:
130: /*
131: Step 3
132: */
133: z = pow(u1,2.0)*u2;
134: if(!(z <= 0.25)) goto S160;
135: v = beta*log(u1/(1.0-u1));
136: if(!(v > expmax)) goto S140;
137: w = infnty;
138: goto S150;
139: S140:
140: w = a*exp(v);
141: S150:
142: goto S200;
143: S160:
144: if(z >= k2) goto S120;
145: S170:
146: /*
147: Step 4
148: Step 5
149: */
150: v = beta*log(u1/(1.0-u1));
151: if(!(v > expmax)) goto S180;
152: w = infnty;
153: goto S190;
154: S180:
155: w = a*exp(v);
156: S190:
157: if(alpha*(log(alpha/(b+w))+v)-1.3862944 < log(z)) goto S120;
158: S200:
159: /*
160: Step 6
161: */
162: if(!(a == aa)) goto S210;
163: genbet = w/(b+w);
164: goto S220;
165: S210:
166: genbet = b/(b+w);
167: S230:
168: S220:
169: return genbet;
170: #undef expmax
171: #undef infnty
172: }
173: float genchi(float df)
174: /*
175: **********************************************************************
176: float genchi(float df)
177: Generate random value of CHIsquare variable
178: Function
179: Generates random deviate from the distribution of a chisquare
180: with DF degrees of freedom random variable.
181: Arguments
182: df --> Degrees of freedom of the chisquare
183: (Must be positive)
184:
185: Method
186: Uses relation between chisquare and gamma.
187: **********************************************************************
188: */
189: {
190: static float genchi;
191:
192: if(!(df <= 0.0)) goto S10;
193: puts("DF <= 0 in GENCHI - ABORT");
194: printf("Value of DF: %16.6E\n",df);
195: exit(1);
196: S10:
197: genchi = 2.0*gengam(1.0,df/2.0);
198: return genchi;
199: }
200: float genexp(float av)
201: /*
202: **********************************************************************
203: float genexp(float av)
204: GENerate EXPonential random deviate
205: Function
206: Generates a single random deviate from an exponential
207: distribution with mean AV.
208: Arguments
209: av --> The mean of the exponential distribution from which
210: a random deviate is to be generated.
211: Method
212: Renames SEXPO from TOMS as slightly modified by BWB to use RANF
213: instead of SUNIF.
214: For details see:
215: Ahrens, J.H. and Dieter, U.
216: Computer Methods for Sampling From the
217: Exponential and Normal Distributions.
218: Comm. ACM, 15,10 (Oct. 1972), 873 - 882.
219: **********************************************************************
220: */
221: {
222: static float genexp;
223:
224: genexp = sexpo()*av;
225: return genexp;
226: }
227: float genf(float dfn,float dfd)
228: /*
229: **********************************************************************
230: float genf(float dfn,float dfd)
231: GENerate random deviate from the F distribution
232: Function
233: Generates a random deviate from the F (variance ratio)
234: distribution with DFN degrees of freedom in the numerator
235: and DFD degrees of freedom in the denominator.
236: Arguments
237: dfn --> Numerator degrees of freedom
238: (Must be positive)
239: dfd --> Denominator degrees of freedom
240: (Must be positive)
241: Method
242: Directly generates ratio of chisquare variates
243: **********************************************************************
244: */
245: {
246: static float genf,xden,xnum;
247:
248: if(!(dfn <= 0.0 || dfd <= 0.0)) goto S10;
249: puts("Degrees of freedom nonpositive in GENF - abort!");
250: printf("DFN value: %16.6EDFD value: %16.6E\n",dfn,dfd);
251: exit(1);
252: S10:
253: xnum = genchi(dfn)/dfn;
254: /*
255: GENF = ( GENCHI( DFN ) / DFN ) / ( GENCHI( DFD ) / DFD )
256: */
257: xden = genchi(dfd)/dfd;
258: if(!(xden <= 9.999999999998E-39*xnum)) goto S20;
259: puts(" GENF - generated numbers would cause overflow");
260: printf(" Numerator %16.6E Denominator %16.6E\n",xnum,xden);
261: puts(" GENF returning 1.0E38");
262: genf = 1.0E38;
263: goto S30;
264: S20:
265: genf = xnum/xden;
266: S30:
267: return genf;
268: }
269: float gengam(float a,float r)
270: /*
271: **********************************************************************
272: float gengam(float a,float r)
273: GENerates random deviates from GAMma distribution
274: Function
275: Generates random deviates from the gamma distribution whose
276: density is
277: (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X)
278: Arguments
279: a --> Location parameter of Gamma distribution
280: r --> Shape parameter of Gamma distribution
281: Method
282: Renames SGAMMA from TOMS as slightly modified by BWB to use RANF
283: instead of SUNIF.
284: For details see:
285: (Case R >= 1.0)
286: Ahrens, J.H. and Dieter, U.
287: Generating Gamma Variates by a
288: Modified Rejection Technique.
289: Comm. ACM, 25,1 (Jan. 1982), 47 - 54.
290: Algorithm GD
291: (Case 0.0 <= R <= 1.0)
292: Ahrens, J.H. and Dieter, U.
293: Computer Methods for Sampling from Gamma,
294: Beta, Poisson and Binomial Distributions.
295: Computing, 12 (1974), 223-246/
296: Adapted algorithm GS.
297: **********************************************************************
298: */
299: {
300: static float gengam;
301:
302: gengam = sgamma(r);
303: gengam /= a;
304: return gengam;
305: }
306: void genmn(float *parm,float *x,float *work)
307: /*
308: **********************************************************************
309: void genmn(float *parm,float *x,float *work)
310: GENerate Multivariate Normal random deviate
311: Arguments
312: parm --> Parameters needed to generate multivariate normal
313: deviates (MEANV and Cholesky decomposition of
314: COVM). Set by a previous call to SETGMN.
315: 1 : 1 - size of deviate, P
316: 2 : P + 1 - mean vector
317: P+2 : P*(P+3)/2 + 1 - upper half of cholesky
318: decomposition of cov matrix
319: x <-- Vector deviate generated.
320: work <--> Scratch array
321: Method
322: 1) Generate P independent standard normal deviates - Ei ~ N(0,1)
323: 2) Using Cholesky decomposition find A s.t. trans(A)*A = COVM
324: 3) trans(A)E + MEANV ~ N(MEANV,COVM)
325: **********************************************************************
326: */
327: {
328: static long i,icount,j,p,D1,D2,D3,D4;
329: static float ae;
330:
331: p = (long) (*parm);
332: /*
333: Generate P independent normal deviates - WORK ~ N(0,1)
334: */
335: for(i=1; i<=p; i++) *(work+i-1) = snorm();
336: for(i=1,D3=1,D4=(p-i+D3)/D3; D4>0; D4--,i+=D3) {
337: /*
338: PARM (P+2 : P*(P+3)/2 + 1) contains A, the Cholesky
339: decomposition of the desired covariance matrix.
340: trans(A)(1,1) = PARM(P+2)
341: trans(A)(2,1) = PARM(P+3)
342: trans(A)(2,2) = PARM(P+2+P)
343: trans(A)(3,1) = PARM(P+4)
344: trans(A)(3,2) = PARM(P+3+P)
345: trans(A)(3,3) = PARM(P+2-1+2P) ...
346: trans(A)*WORK + MEANV ~ N(MEANV,COVM)
347: */
348: icount = 0;
349: ae = 0.0;
350: for(j=1,D1=1,D2=(i-j+D1)/D1; D2>0; D2--,j+=D1) {
351: icount += (j-1);
352: ae += (*(parm+i+(j-1)*p-icount+p)**(work+j-1));
353: }
354: *(x+i-1) = ae+*(parm+i);
355: }
356: }
357: float gennch(float df,float xnonc)
358: /*
359: **********************************************************************
360: float gennch(float df,float xnonc)
361: Generate random value of Noncentral CHIsquare variable
362: Function
363: Generates random deviate from the distribution of a noncentral
364: chisquare with DF degrees of freedom and noncentrality parameter
365: xnonc.
366: Arguments
367: df --> Degrees of freedom of the chisquare
368: (Must be > 1.0)
369: xnonc --> Noncentrality parameter of the chisquare
370: (Must be >= 0.0)
371: Method
372: Uses fact that noncentral chisquare is the sum of a chisquare
373: deviate with DF-1 degrees of freedom plus the square of a normal
374: deviate with mean XNONC and standard deviation 1.
375: **********************************************************************
376: */
377: {
378: static float gennch;
379:
380: if(!(df <= 1.0 || xnonc < 0.0)) goto S10;
381: puts("DF <= 1 or XNONC < 0 in GENNCH - ABORT");
382: printf("Value of DF: %16.6E Value of XNONC%16.6E\n",df,xnonc);
383: exit(1);
384: S10:
385: gennch = genchi(df-1.0)+pow(gennor(sqrt(xnonc),1.0),2.0);
386: return gennch;
387: }
388: float gennf(float dfn,float dfd,float xnonc)
389: /*
390: **********************************************************************
391: float gennf(float dfn,float dfd,float xnonc)
392: GENerate random deviate from the Noncentral F distribution
393: Function
394: Generates a random deviate from the noncentral F (variance ratio)
395: distribution with DFN degrees of freedom in the numerator, and DFD
396: degrees of freedom in the denominator, and noncentrality parameter
397: XNONC.
398: Arguments
399: dfn --> Numerator degrees of freedom
400: (Must be >= 1.0)
401: dfd --> Denominator degrees of freedom
402: (Must be positive)
403: xnonc --> Noncentrality parameter
404: (Must be nonnegative)
405: Method
406: Directly generates ratio of noncentral numerator chisquare variate
407: to central denominator chisquare variate.
408: **********************************************************************
409: */
410: {
411: static float gennf,xden,xnum;
412: static long qcond;
413:
414: qcond = dfn <= 1.0 || dfd <= 0.0 || xnonc < 0.0;
415: if(!qcond) goto S10;
416: puts("In GENNF - Either (1) Numerator DF <= 1.0 or");
417: puts("(2) Denominator DF < 0.0 or ");
418: puts("(3) Noncentrality parameter < 0.0");
419: printf("DFN value: %16.6EDFD value: %16.6EXNONC value: \n%16.6E\n",dfn,dfd,
420: xnonc);
421: exit(1);
422: S10:
423: xnum = gennch(dfn,xnonc)/dfn;
424: /*
425: GENNF = ( GENNCH( DFN, XNONC ) / DFN ) / ( GENCHI( DFD ) / DFD )
426: */
427: xden = genchi(dfd)/dfd;
428: if(!(xden <= 9.999999999998E-39*xnum)) goto S20;
429: puts(" GENNF - generated numbers would cause overflow");
430: printf(" Numerator %16.6E Denominator %16.6E\n",xnum,xden);
431: puts(" GENNF returning 1.0E38");
432: gennf = 1.0E38;
433: goto S30;
434: S20:
435: gennf = xnum/xden;
436: S30:
437: return gennf;
438: }
439: float gennor(float av,float sd)
440: /*
441: **********************************************************************
442: float gennor(float av,float sd)
443: GENerate random deviate from a NORmal distribution
444: Function
445: Generates a single random deviate from a normal distribution
446: with mean, AV, and standard deviation, SD.
447: Arguments
448: av --> Mean of the normal distribution.
449: sd --> Standard deviation of the normal distribution.
450: Method
451: Renames SNORM from TOMS as slightly modified by BWB to use RANF
452: instead of SUNIF.
453: For details see:
454: Ahrens, J.H. and Dieter, U.
455: Extensions of Forsythe's Method for Random
456: Sampling from the Normal Distribution.
457: Math. Comput., 27,124 (Oct. 1973), 927 - 937.
458: **********************************************************************
459: */
460: {
461: static float gennor;
462:
463: gennor = sd*snorm()+av;
464: return gennor;
465: }
466: void genprm(long *iarray,int larray)
467: /*
468: **********************************************************************
469: void genprm(long *iarray,int larray)
470: GENerate random PeRMutation of iarray
471: Arguments
472: iarray <--> On output IARRAY is a random permutation of its
473: value on input
474: larray <--> Length of IARRAY
475: **********************************************************************
476: */
477: {
478: static long i,itmp,iwhich,D1,D2;
479:
480: for(i=1,D1=1,D2=(larray-i+D1)/D1; D2>0; D2--,i+=D1) {
481: iwhich = ignuin(i,larray);
482: itmp = *(iarray+iwhich-1);
483: *(iarray+iwhich-1) = *(iarray+i-1);
484: *(iarray+i-1) = itmp;
485: }
486: }
487: float genunf(float low,float high)
488: /*
489: **********************************************************************
490: float genunf(float low,float high)
491: GeNerate Uniform Real between LOW and HIGH
492: Function
493: Generates a real uniformly distributed between LOW and HIGH.
494: Arguments
495: low --> Low bound (exclusive) on real value to be generated
496: high --> High bound (exclusive) on real value to be generated
497: **********************************************************************
498: */
499: {
500: static float genunf;
501:
502: if(!(low > high)) goto S10;
503: printf("LOW > HIGH in GENUNF: LOW %16.6E HIGH: %16.6E\n",low,high);
504: puts("Abort");
505: exit(1);
506: S10:
507: genunf = low+(high-low)*ranf();
508: return genunf;
509: }
510: void gscgn(long getset,long *g)
511: /*
512: **********************************************************************
513: void gscgn(long getset,long *g)
514: Get/Set GeNerator
515: Gets or returns in G the number of the current generator
516: Arguments
517: getset --> 0 Get
518: 1 Set
519: g <-- Number of the current random number generator (1..32)
520: **********************************************************************
521: */
522: {
523: #define numg 32L
524: static long curntg = 1;
525: if(getset == 0) *g = curntg;
526: else {
527: if(*g < 0 || *g > numg) {
528: puts(" Generator number out of range in GSCGN");
529: exit(0);
530: }
531: curntg = *g;
532: }
533: #undef numg
534: }
535: void gsrgs(long getset,long *qvalue)
536: /*
537: **********************************************************************
538: void gsrgs(long getset,long *qvalue)
539: Get/Set Random Generators Set
540: Gets or sets whether random generators set (initialized).
541: Initially (data statement) state is not set
542: If getset is 1 state is set to qvalue
543: If getset is 0 state returned in qvalue
544: **********************************************************************
545: */
546: {
547: static long qinit = 0;
548:
549: if(getset == 0) *qvalue = qinit;
550: else qinit = *qvalue;
551: }
552: void gssst(long getset,long *qset)
553: /*
554: **********************************************************************
555: void gssst(long getset,long *qset)
556: Get or Set whether Seed is Set
557: Initialize to Seed not Set
558: If getset is 1 sets state to Seed Set
559: If getset is 0 returns T in qset if Seed Set
560: Else returns F in qset
561: **********************************************************************
562: */
563: {
564: static long qstate = 0;
565: if(getset != 0) qstate = 1;
566: else *qset = qstate;
567: }
568: long ignbin(long n,float pp)
569: /*
570: **********************************************************************
571: long ignbin(long n,float pp)
572: GENerate BINomial random deviate
573: Function
574: Generates a single random deviate from a binomial
575: distribution whose number of trials is N and whose
576: probability of an event in each trial is P.
577: Arguments
578: n --> The number of trials in the binomial distribution
579: from which a random deviate is to be generated.
580: p --> The probability of an event in each trial of the
581: binomial distribution from which a random deviate
582: is to be generated.
583: ignbin <-- A random deviate yielding the number of events
584: from N independent trials, each of which has
585: a probability of event P.
586: Method
587: This is algorithm BTPE from:
588: Kachitvichyanukul, V. and Schmeiser, B. W.
589: Binomial Random Variate Generation.
590: Communications of the ACM, 31, 2
591: (February, 1988) 216.
592: **********************************************************************
593: SUBROUTINE BTPEC(N,PP,ISEED,JX)
594: BINOMIAL RANDOM VARIATE GENERATOR
595: MEAN .LT. 30 -- INVERSE CDF
596: MEAN .GE. 30 -- ALGORITHM BTPE: ACCEPTANCE-REJECTION VIA
597: FOUR REGION COMPOSITION. THE FOUR REGIONS ARE A TRIANGLE
598: (SYMMETRIC IN THE CENTER), A PAIR OF PARALLELOGRAMS (ABOVE
599: THE TRIANGLE), AND EXPONENTIAL LEFT AND RIGHT TAILS.
600: BTPE REFERS TO BINOMIAL-TRIANGLE-PARALLELOGRAM-EXPONENTIAL.
601: BTPEC REFERS TO BTPE AND "COMBINED." THUS BTPE IS THE
602: RESEARCH AND BTPEC IS THE IMPLEMENTATION OF A COMPLETE
603: USABLE ALGORITHM.
604: REFERENCE: VORATAS KACHITVICHYANUKUL AND BRUCE SCHMEISER,
605: "BINOMIAL RANDOM VARIATE GENERATION,"
606: COMMUNICATIONS OF THE ACM, FORTHCOMING
607: WRITTEN: SEPTEMBER 1980.
608: LAST REVISED: MAY 1985, JULY 1987
609: REQUIRED SUBPROGRAM: RAND() -- A UNIFORM (0,1) RANDOM NUMBER
610: GENERATOR
611: ARGUMENTS
612: N : NUMBER OF BERNOULLI TRIALS (INPUT)
613: PP : PROBABILITY OF SUCCESS IN EACH TRIAL (INPUT)
614: ISEED: RANDOM NUMBER SEED (INPUT AND OUTPUT)
615: JX: RANDOMLY GENERATED OBSERVATION (OUTPUT)
616: VARIABLES
617: PSAVE: VALUE OF PP FROM THE LAST CALL TO BTPEC
618: NSAVE: VALUE OF N FROM THE LAST CALL TO BTPEC
619: XNP: VALUE OF THE MEAN FROM THE LAST CALL TO BTPEC
620: P: PROBABILITY USED IN THE GENERATION PHASE OF BTPEC
621: FFM: TEMPORARY VARIABLE EQUAL TO XNP + P
622: M: INTEGER VALUE OF THE CURRENT MODE
623: FM: FLOATING POINT VALUE OF THE CURRENT MODE
624: XNPQ: TEMPORARY VARIABLE USED IN SETUP AND SQUEEZING STEPS
625: P1: AREA OF THE TRIANGLE
626: C: HEIGHT OF THE PARALLELOGRAMS
627: XM: CENTER OF THE TRIANGLE
628: XL: LEFT END OF THE TRIANGLE
629: XR: RIGHT END OF THE TRIANGLE
630: AL: TEMPORARY VARIABLE
631: XLL: RATE FOR THE LEFT EXPONENTIAL TAIL
632: XLR: RATE FOR THE RIGHT EXPONENTIAL TAIL
633: P2: AREA OF THE PARALLELOGRAMS
634: P3: AREA OF THE LEFT EXPONENTIAL TAIL
635: P4: AREA OF THE RIGHT EXPONENTIAL TAIL
636: U: A U(0,P4) RANDOM VARIATE USED FIRST TO SELECT ONE OF THE
637: FOUR REGIONS AND THEN CONDITIONALLY TO GENERATE A VALUE
638: FROM THE REGION
639: V: A U(0,1) RANDOM NUMBER USED TO GENERATE THE RANDOM VALUE
640: (REGION 1) OR TRANSFORMED INTO THE VARIATE TO ACCEPT OR
641: REJECT THE CANDIDATE VALUE
642: IX: INTEGER CANDIDATE VALUE
643: X: PRELIMINARY CONTINUOUS CANDIDATE VALUE IN REGION 2 LOGIC
644: AND A FLOATING POINT IX IN THE ACCEPT/REJECT LOGIC
645: K: ABSOLUTE VALUE OF (IX-M)
646: F: THE HEIGHT OF THE SCALED DENSITY FUNCTION USED IN THE
647: ACCEPT/REJECT DECISION WHEN BOTH M AND IX ARE SMALL
648: ALSO USED IN THE INVERSE TRANSFORMATION
649: R: THE RATIO P/Q
650: G: CONSTANT USED IN CALCULATION OF PROBABILITY
651: MP: MODE PLUS ONE, THE LOWER INDEX FOR EXPLICIT CALCULATION
652: OF F WHEN IX IS GREATER THAN M
653: IX1: CANDIDATE VALUE PLUS ONE, THE LOWER INDEX FOR EXPLICIT
654: CALCULATION OF F WHEN IX IS LESS THAN M
655: I: INDEX FOR EXPLICIT CALCULATION OF F FOR BTPE
656: AMAXP: MAXIMUM ERROR OF THE LOGARITHM OF NORMAL BOUND
657: YNORM: LOGARITHM OF NORMAL BOUND
658: ALV: NATURAL LOGARITHM OF THE ACCEPT/REJECT VARIATE V
659: X1,F1,Z,W,Z2,X2,F2, AND W2 ARE TEMPORARY VARIABLES TO BE
660: USED IN THE FINAL ACCEPT/REJECT TEST
661: QN: PROBABILITY OF NO SUCCESS IN N TRIALS
662: REMARK
663: IX AND JX COULD LOGICALLY BE THE SAME VARIABLE, WHICH WOULD
664: SAVE A MEMORY POSITION AND A LINE OF CODE. HOWEVER, SOME
665: COMPILERS (E.G.,CDC MNF) OPTIMIZE BETTER WHEN THE ARGUMENTS
666: ARE NOT INVOLVED.
667: ISEED NEEDS TO BE DOUBLE PRECISION IF THE IMSL ROUTINE
668: GGUBFS IS USED TO GENERATE UNIFORM RANDOM NUMBER, OTHERWISE
669: TYPE OF ISEED SHOULD BE DICTATED BY THE UNIFORM GENERATOR
670: **********************************************************************
671: *****DETERMINE APPROPRIATE ALGORITHM AND WHETHER SETUP IS NECESSARY
672: */
673: {
674: static float psave = -1.0;
675: static long nsave = -1;
676: static long ignbin,i,ix,ix1,k,m,mp,T1;
677: static float al,alv,amaxp,c,f,f1,f2,ffm,fm,g,p,p1,p2,p3,p4,q,qn,r,u,v,w,w2,x,x1,
678: x2,xl,xll,xlr,xm,xnp,xnpq,xr,ynorm,z,z2;
679:
680: if(pp != psave) goto S10;
681: if(n != nsave) goto S20;
682: if(xnp < 30.0) goto S150;
683: goto S30;
684: S10:
685: /*
686: *****SETUP, PERFORM ONLY WHEN PARAMETERS CHANGE
687: */
688: psave = pp;
689: p = min(psave,1.0-psave);
690: q = 1.0-p;
691: S20:
692: xnp = n*p;
693: nsave = n;
694: if(xnp < 30.0) goto S140;
695: ffm = xnp+p;
696: m = ffm;
697: fm = m;
698: xnpq = xnp*q;
699: p1 = (long) (2.195*sqrt(xnpq)-4.6*q)+0.5;
700: xm = fm+0.5;
701: xl = xm-p1;
702: xr = xm+p1;
703: c = 0.134+20.5/(15.3+fm);
704: al = (ffm-xl)/(ffm-xl*p);
705: xll = al*(1.0+0.5*al);
706: al = (xr-ffm)/(xr*q);
707: xlr = al*(1.0+0.5*al);
708: p2 = p1*(1.0+c+c);
709: p3 = p2+c/xll;
710: p4 = p3+c/xlr;
711: S30:
712: /*
713: *****GENERATE VARIATE
714: */
715: u = ranf()*p4;
716: v = ranf();
717: /*
718: TRIANGULAR REGION
719: */
720: if(u > p1) goto S40;
721: ix = xm-p1*v+u;
722: goto S170;
723: S40:
724: /*
725: PARALLELOGRAM REGION
726: */
727: if(u > p2) goto S50;
728: x = xl+(u-p1)/c;
729: v = v*c+1.0-abs(xm-x)/p1;
730: if(v > 1.0 || v <= 0.0) goto S30;
731: ix = x;
732: goto S70;
733: S50:
734: /*
735: LEFT TAIL
736: */
737: if(u > p3) goto S60;
738: ix = xl+log(v)/xll;
739: if(ix < 0) goto S30;
740: v *= ((u-p2)*xll);
741: goto S70;
742: S60:
743: /*
744: RIGHT TAIL
745: */
746: ix = xr-log(v)/xlr;
747: if(ix > n) goto S30;
748: v *= ((u-p3)*xlr);
749: S70:
750: /*
751: *****DETERMINE APPROPRIATE WAY TO PERFORM ACCEPT/REJECT TEST
752: */
753: k = abs(ix-m);
754: if(k > 20 && k < xnpq/2-1) goto S130;
755: /*
756: EXPLICIT EVALUATION
757: */
758: f = 1.0;
759: r = p/q;
760: g = (n+1)*r;
761: T1 = m-ix;
762: if(T1 < 0) goto S80;
763: else if(T1 == 0) goto S120;
764: else goto S100;
765: S80:
766: mp = m+1;
767: for(i=mp; i<=ix; i++) f *= (g/i-r);
768: goto S120;
769: S100:
770: ix1 = ix+1;
771: for(i=ix1; i<=m; i++) f /= (g/i-r);
772: S120:
773: if(v <= f) goto S170;
774: goto S30;
775: S130:
776: /*
777: SQUEEZING USING UPPER AND LOWER BOUNDS ON ALOG(F(X))
778: */
779: amaxp = k/xnpq*((k*(k/3.0+0.625)+0.1666666666666)/xnpq+0.5);
780: ynorm = -(k*k/(2.0*xnpq));
781: alv = log(v);
782: if(alv < ynorm-amaxp) goto S170;
783: if(alv > ynorm+amaxp) goto S30;
784: /*
785: STIRLING'S FORMULA TO MACHINE ACCURACY FOR
786: THE FINAL ACCEPTANCE/REJECTION TEST
787: */
788: x1 = ix+1.0;
789: f1 = fm+1.0;
790: z = n+1.0-fm;
791: w = n-ix+1.0;
792: z2 = z*z;
793: x2 = x1*x1;
794: f2 = f1*f1;
795: w2 = w*w;
796: if(alv <= xm*log(f1/x1)+(n-m+0.5)*log(z/w)+(ix-m)*log(w*p/(x1*q))+(13860.0-
797: (462.0-(132.0-(99.0-140.0/f2)/f2)/f2)/f2)/f1/166320.0+(13860.0-(462.0-
798: (132.0-(99.0-140.0/z2)/z2)/z2)/z2)/z/166320.0+(13860.0-(462.0-(132.0-
799: (99.0-140.0/x2)/x2)/x2)/x2)/x1/166320.0+(13860.0-(462.0-(132.0-(99.0
800: -140.0/w2)/w2)/w2)/w2)/w/166320.0) goto S170;
801: goto S30;
802: S140:
803: /*
804: INVERSE CDF LOGIC FOR MEAN LESS THAN 30
805: */
806: qn = pow(q,(double)n);
807: r = p/q;
808: g = r*(n+1);
809: S150:
810: ix = 0;
811: f = qn;
812: u = ranf();
813: S160:
814: if(u < f) goto S170;
815: if(ix > 110) goto S150;
816: u -= f;
817: ix += 1;
818: f *= (g/ix-r);
819: goto S160;
820: S170:
821: if(psave > 0.5) ix = n-ix;
822: ignbin = ix;
823: return ignbin;
824: }
825: long ignpoi(float mu)
826: /*
827: **********************************************************************
828: long ignpoi(float mu)
829: GENerate POIsson random deviate
830: Function
831: Generates a single random deviate from a Poisson
832: distribution with mean AV.
833: Arguments
834: av --> The mean of the Poisson distribution from which
835: a random deviate is to be generated.
836: genexp <-- The random deviate.
837: Method
838: Renames KPOIS from TOMS as slightly modified by BWB to use RANF
839: instead of SUNIF.
840: For details see:
841: Ahrens, J.H. and Dieter, U.
842: Computer Generation of Poisson Deviates
843: From Modified Normal Distributions.
844: ACM Trans. Math. Software, 8, 2
845: (June 1982),163-179
846: **********************************************************************
847: **********************************************************************
848:
849:
850: P O I S S O N DISTRIBUTION
851:
852:
853: **********************************************************************
854: **********************************************************************
855:
856: FOR DETAILS SEE:
857:
858: AHRENS, J.H. AND DIETER, U.
859: COMPUTER GENERATION OF POISSON DEVIATES
860: FROM MODIFIED NORMAL DISTRIBUTIONS.
861: ACM TRANS. MATH. SOFTWARE, 8,2 (JUNE 1982), 163 - 179.
862:
863: (SLIGHTLY MODIFIED VERSION OF THE PROGRAM IN THE ABOVE ARTICLE)
864:
865: **********************************************************************
866: INTEGER FUNCTION IGNPOI(IR,MU)
867: INPUT: IR=CURRENT STATE OF BASIC RANDOM NUMBER GENERATOR
868: MU=MEAN MU OF THE POISSON DISTRIBUTION
869: OUTPUT: IGNPOI=SAMPLE FROM THE POISSON-(MU)-DISTRIBUTION
870: MUPREV=PREVIOUS MU, MUOLD=MU AT LAST EXECUTION OF STEP P OR B.
871: TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT
872: COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL
873: SEPARATION OF CASES A AND B
874: */
875: {
876: extern float fsign( float num, float sign );
877: static float a0 = -0.5;
878: static float a1 = 0.3333333;
879: static float a2 = -0.2500068;
880: static float a3 = 0.2000118;
881: static float a4 = -0.1661269;
882: static float a5 = 0.1421878;
883: static float a6 = -0.1384794;
884: static float a7 = 0.125006;
885: static float muold = 0.0;
886: static float muprev = 0.0;
887: static float fact[10] = {
888: 1.0,1.0,2.0,6.0,24.0,120.0,720.0,5040.0,40320.0,362880.0
889: };
890: static long ignpoi,j,k,kflag,l,m;
891: static float b1,b2,c,c0,c1,c2,c3,d,del,difmuk,e,fk,fx,fy,g,omega,p,p0,px,py,q,s,
892: t,u,v,x,xx,pp[35];
893:
894: if(mu == muprev) goto S10;
895: if(mu < 10.0) goto S120;
896: /*
897: C A S E A. (RECALCULATION OF S,D,L IF MU HAS CHANGED)
898: */
899: muprev = mu;
900: s = sqrt(mu);
901: d = 6.0*mu*mu;
902: /*
903: THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL
904: PROBABILITIES FK WHENEVER K >= M(MU). L=IFIX(MU-1.1484)
905: IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 .
906: */
907: l = (long) (mu-1.1484);
908: S10:
909: /*
910: STEP N. NORMAL SAMPLE - SNORM(IR) FOR STANDARD NORMAL DEVIATE
911: */
912: g = mu+s*snorm();
913: if(g < 0.0) goto S20;
914: ignpoi = (long) (g);
915: /*
916: STEP I. IMMEDIATE ACCEPTANCE IF IGNPOI IS LARGE ENOUGH
917: */
918: if(ignpoi >= l) return ignpoi;
919: /*
920: STEP S. SQUEEZE ACCEPTANCE - SUNIF(IR) FOR (0,1)-SAMPLE U
921: */
922: fk = (float)ignpoi;
923: difmuk = mu-fk;
924: u = ranf();
925: if(d*u >= difmuk*difmuk*difmuk) return ignpoi;
926: S20:
927: /*
928: STEP P. PREPARATIONS FOR STEPS Q AND H.
929: (RECALCULATIONS OF PARAMETERS IF NECESSARY)
930: .3989423=(2*PI)**(-.5) .416667E-1=1./24. .1428571=1./7.
931: THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE
932: APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK.
933: C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION.
934: */
935: if(mu == muold) goto S30;
936: muold = mu;
937: omega = 0.3989423/s;
938: b1 = 4.166667E-2/mu;
939: b2 = 0.3*b1*b1;
940: c3 = 0.1428571*b1*b2;
941: c2 = b2-15.0*c3;
942: c1 = b1-6.0*b2+45.0*c3;
943: c0 = 1.0-b1+3.0*b2-15.0*c3;
944: c = 0.1069/mu;
945: S30:
946: if(g < 0.0) goto S50;
947: /*
948: 'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)
949: */
950: kflag = 0;
951: goto S70;
952: S40:
953: /*
954: STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)
955: */
956: if(fy-u*fy <= py*exp(px-fx)) return ignpoi;
957: S50:
958: /*
959: STEP E. EXPONENTIAL SAMPLE - SEXPO(IR) FOR STANDARD EXPONENTIAL
960: DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'
961: (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)
962: */
963: e = sexpo();
964: u = ranf();
965: u += (u-1.0);
966: t = 1.8+fsign(e,u);
967: if(t <= -0.6744) goto S50;
968: ignpoi = (long) (mu+s*t);
969: fk = (float)ignpoi;
970: difmuk = mu-fk;
971: /*
972: 'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)
973: */
974: kflag = 1;
975: goto S70;
976: S60:
977: /*
978: STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)
979: */
980: if(c*fabs(u) > py*exp(px+e)-fy*exp(fx+e)) goto S50;
981: return ignpoi;
982: S70:
983: /*
984: STEP F. 'SUBROUTINE' F. CALCULATION OF PX,PY,FX,FY.
985: CASE IGNPOI .LT. 10 USES FACTORIALS FROM TABLE FACT
986: */
987: if(ignpoi >= 10) goto S80;
988: px = -mu;
989: py = pow(mu,(double)ignpoi)/ *(fact+ignpoi);
990: goto S110;
991: S80:
992: /*
993: CASE IGNPOI .GE. 10 USES POLYNOMIAL APPROXIMATION
994: A0-A7 FOR ACCURACY WHEN ADVISABLE
995: .8333333E-1=1./12. .3989423=(2*PI)**(-.5)
996: */
997: del = 8.333333E-2/fk;
998: del -= (4.8*del*del*del);
999: v = difmuk/fk;
1000: if(fabs(v) <= 0.25) goto S90;
1001: px = fk*log(1.0+v)-difmuk-del;
1002: goto S100;
1003: S90:
1004: px = fk*v*v*(((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0)-del;
1005: S100:
1006: py = 0.3989423/sqrt(fk);
1007: S110:
1008: x = (0.5-difmuk)/s;
1009: xx = x*x;
1010: fx = -0.5*xx;
1011: fy = omega*(((c3*xx+c2)*xx+c1)*xx+c0);
1012: if(kflag <= 0) goto S40;
1013: goto S60;
1014: S120:
1015: /*
1016: C A S E B. (START NEW TABLE AND CALCULATE P0 IF NECESSARY)
1017: */
1018: muprev = 0.0;
1019: if(mu == muold) goto S130;
1020: muold = mu;
1021: m = max(1L,(long) (mu));
1022: l = 0;
1023: p = exp(-mu);
1024: q = p0 = p;
1025: S130:
1026: /*
1027: STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
1028: */
1029: u = ranf();
1030: ignpoi = 0;
1031: if(u <= p0) return ignpoi;
1032: /*
1033: STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE
1034: PP-TABLE OF CUMULATIVE POISSON PROBABILITIES
1035: (0.458=PP(9) FOR MU=10)
1036: */
1037: if(l == 0) goto S150;
1038: j = 1;
1039: if(u > 0.458) j = min(l,m);
1040: for(k=j; k<=l; k++) {
1041: if(u <= *(pp+k-1)) goto S180;
1042: }
1043: if(l == 35) goto S130;
1044: S150:
1045: /*
1046: STEP C. CREATION OF NEW POISSON PROBABILITIES P
1047: AND THEIR CUMULATIVES Q=PP(K)
1048: */
1049: l += 1;
1050: for(k=l; k<=35; k++) {
1051: p = p*mu/(float)k;
1052: q += p;
1053: *(pp+k-1) = q;
1054: if(u <= q) goto S170;
1055: }
1056: l = 35;
1057: goto S130;
1058: S170:
1059: l = k;
1060: S180:
1061: ignpoi = k;
1062: return ignpoi;
1063: }
1064: long ignuin(long low,long high)
1065: /*
1066: **********************************************************************
1067: long ignuin(long low,long high)
1068: GeNerate Uniform INteger
1069: Function
1070: Generates an integer uniformly distributed between LOW and HIGH.
1071: Arguments
1072: low --> Low bound (inclusive) on integer value to be generated
1073: high --> High bound (inclusive) on integer value to be generated
1074: Note
1075: If (HIGH-LOW) > 2,147,483,561 prints error message on * unit and
1076: stops the program.
1077: **********************************************************************
1078: IGNLGI generates integers between 1 and 2147483562
1079: MAXNUM is 1 less than maximum generable value
1080: */
1081: {
1082: #define maxnum 2147483561L
1083: static long ignuin,ign,maxnow,range,ranp1;
1084:
1085: if(!(low > high)) goto S10;
1086: puts(" low > high in ignuin - ABORT");
1087: exit(1);
1088:
1089: S10:
1090: range = high-low;
1091: if(!(range > maxnum)) goto S20;
1092: puts(" high - low too large in ignuin - ABORT");
1093: exit(1);
1094:
1095: S20:
1096: if(!(low == high)) goto S30;
1097: ignuin = low;
1098: return ignuin;
1099:
1100: S30:
1101: /*
1102: Number to be generated should be in range 0..RANGE
1103: Set MAXNOW so that the number of integers in 0..MAXNOW is an
1104: integral multiple of the number in 0..RANGE
1105: */
1106: ranp1 = range+1;
1107: maxnow = maxnum/ranp1*ranp1;
1108: S40:
1109: ign = ignlgi()-1;
1110: if(!(ign <= maxnow)) goto S50;
1111: ignuin = low+ign%ranp1;
1112: return ignuin;
1113: S50:
1114: goto S40;
1115: #undef maxnum
1116: #undef err1
1117: #undef err2
1118: }
1119: long lennob( char *str )
1120: /*
1121: Returns the length of str ignoring trailing blanks but not
1122: other white space.
1123: */
1124: {
1125: long i, i_nb;
1126:
1127: for (i=0, i_nb= -1L; *(str+i); i++)
1128: if ( *(str+i) != ' ' ) i_nb = i;
1129: return (i_nb+1);
1130: }
1131: long mltmod(long a,long s,long m)
1132: /*
1133: **********************************************************************
1134: long mltmod(long a,long s,long m)
1135: Returns (A*S) MOD M
1136: This is a transcription from Pascal to Fortran of routine
1137: MULtMod_Decompos from the paper
1138: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
1139: with Splitting Facilities." ACM Transactions on Mathematical
1140: Software, 17:98-111 (1991)
1141: Arguments
1142: a, s, m -->
1143: **********************************************************************
1144: */
1145: {
1146: #define h 32768L
1147: static long mltmod,a0,a1,k,p,q,qh,rh;
1148: /*
1149: H = 2**((b-2)/2) where b = 32 because we are using a 32 bit
1150: machine. On a different machine recompute H
1151: */
1152: if(!(a <= 0 || a >= m || s <= 0 || s >= m)) goto S10;
1153: puts(" a, m, s out of order in mltmod - ABORT!");
1154: printf(" a = %12ld s = %12ld m = %12ld\n",a,s,m);
1155: puts(" mltmod requires: 0 < a < m; 0 < s < m");
1156: exit(1);
1157: S10:
1158: if(!(a < h)) goto S20;
1159: a0 = a;
1160: p = 0;
1161: goto S120;
1162: S20:
1163: a1 = a/h;
1164: a0 = a-h*a1;
1165: qh = m/h;
1166: rh = m-h*qh;
1167: if(!(a1 >= h)) goto S50;
1168: a1 -= h;
1169: k = s/qh;
1170: p = h*(s-k*qh)-k*rh;
1171: S30:
1172: if(!(p < 0)) goto S40;
1173: p += m;
1174: goto S30;
1175: S40:
1176: goto S60;
1177: S50:
1178: p = 0;
1179: S60:
1180: /*
1181: P = (A2*S*H)MOD M
1182: */
1183: if(!(a1 != 0)) goto S90;
1184: q = m/a1;
1185: k = s/q;
1186: p -= (k*(m-a1*q));
1187: if(p > 0) p -= m;
1188: p += (a1*(s-k*q));
1189: S70:
1190: if(!(p < 0)) goto S80;
1191: p += m;
1192: goto S70;
1193: S90:
1194: S80:
1195: k = p/qh;
1196: /*
1197: P = ((A2*H + A1)*S)MOD M
1198: */
1199: p = h*(p-k*qh)-k*rh;
1200: S100:
1201: if(!(p < 0)) goto S110;
1202: p += m;
1203: goto S100;
1204: S120:
1205: S110:
1206: if(!(a0 != 0)) goto S150;
1207: /*
1208: P = ((A2*H + A1)*H*S)MOD M
1209: */
1210: q = m/a0;
1211: k = s/q;
1212: p -= (k*(m-a0*q));
1213: if(p > 0) p -= m;
1214: p += (a0*(s-k*q));
1215: S130:
1216: if(!(p < 0)) goto S140;
1217: p += m;
1218: goto S130;
1219: S150:
1220: S140:
1221: mltmod = p;
1222: return mltmod;
1223: #undef h
1224: }
1225: void phrtsd(char* phrase,long *seed1,long *seed2)
1226: /*
1227: **********************************************************************
1228: void phrtsd(char* phrase,long *seed1,long *seed2)
1229: PHRase To SeeDs
1230:
1231: Function
1232:
1233: Uses a phrase (character string) to generate two seeds for the RGN
1234: random number generator.
1235: Arguments
1236: phrase --> Phrase to be used for random number generation
1237:
1238: seed1 <-- First seed for generator
1239:
1240: seed2 <-- Second seed for generator
1241:
1242: Note
1243:
1244: Trailing blanks are eliminated before the seeds are generated.
1245: Generated seed values will fall in the range 1..2^30
1246: (1..1,073,741,824)
1247: **********************************************************************
1248: */
1249: {
1250:
1251: static char table[] =
1252: "abcdefghijklmnopqrstuvwxyz\
1253: ABCDEFGHIJKLMNOPQRSTUVWXYZ\
1254: 0123456789\
1255: !@#$%^&*()_+[];:'\\\"<>?,./";
1256:
1257: long ix;
1258:
1259: static long twop30 = 1073741824L;
1260: static long shift[5] = {
1261: 1L,64L,4096L,262144L,16777216L
1262: };
1263: static long i,ichr,j,lphr,values[5];
1264: extern long lennob(char *str);
1265:
1266: *seed1 = 1234567890L;
1267: *seed2 = 123456789L;
1268: lphr = lennob(phrase);
1269: if(lphr < 1) return;
1270: for(i=0; i<=(lphr-1); i++) {
1271: for (ix=0; table[ix]; ix++) if (*(phrase+i) == table[ix]) break;
1272: if (!table[ix]) ix = 0;
1273: ichr = ix % 64;
1274: if(ichr == 0) ichr = 63;
1275: for(j=1; j<=5; j++) {
1276: *(values+j-1) = ichr-j;
1277: if(*(values+j-1) < 1) *(values+j-1) += 63;
1278: }
1279: for(j=1; j<=5; j++) {
1280: *seed1 = ( *seed1+*(shift+j-1)**(values+j-1) ) % twop30;
1281: *seed2 = ( *seed2+*(shift+j-1)**(values+6-j-1) ) % twop30;
1282: }
1283: }
1284: #undef twop30
1285: }
1286: float ranf(void)
1287: /*
1288: **********************************************************************
1289: float ranf(void)
1290: RANDom number generator as a Function
1291: Returns a random floating point number from a uniform distribution
1292: over 0 - 1 (endpoints of this interval are not returned) using the
1293: current generator
1294: This is a transcription from Pascal to Fortran of routine
1295: Uniform_01 from the paper
1296: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
1297: with Splitting Facilities." ACM Transactions on Mathematical
1298: Software, 17:98-111 (1991)
1299: **********************************************************************
1300: */
1301: {
1302: static float ranf;
1303: /*
1304: 4.656613057E-10 is 1/M1 M1 is set in a data statement in IGNLGI
1305: and is currently 2147483563. If M1 changes, change this also.
1306: */
1307: ranf = ignlgi()*4.656613057E-10;
1308: return ranf;
1309: }
1310: void setgmn(float *meanv,float *covm,long p,float *parm)
1311: /*
1312: **********************************************************************
1313: void setgmn(float *meanv,float *covm,long p,float *parm)
1314: SET Generate Multivariate Normal random deviate
1315: Function
1316: Places P, MEANV, and the Cholesky factoriztion of COVM
1317: in GENMN.
1318: Arguments
1319: meanv --> Mean vector of multivariate normal distribution.
1320: covm <--> (Input) Covariance matrix of the multivariate
1321: normal distribution
1322: (Output) Destroyed on output
1323: p --> Dimension of the normal, or length of MEANV.
1324: parm <-- Array of parameters needed to generate multivariate norma
1325: deviates (P, MEANV and Cholesky decomposition of
1326: COVM).
1327: 1 : 1 - P
1328: 2 : P + 1 - MEANV
1329: P+2 : P*(P+3)/2 + 1 - Cholesky decomposition of COVM
1330: Needed dimension is (p*(p+3)/2 + 1)
1331: **********************************************************************
1332: */
1333: {
1334: extern void spofa(float *a,long lda,long n,long *info);
1335: static long T1;
1336: static long i,icount,info,j,D2,D3,D4,D5;
1337: T1 = p*(p+3)/2+1;
1338: /*
1339: TEST THE INPUT
1340: */
1341: if(!(p <= 0)) goto S10;
1342: puts("P nonpositive in SETGMN");
1343: printf("Value of P: %12ld\n",p);
1344: exit(1);
1345: S10:
1346: *parm = p;
1347: /*
1348: PUT P AND MEANV INTO PARM
1349: */
1350: for(i=2,D2=1,D3=(p+1-i+D2)/D2; D3>0; D3--,i+=D2) *(parm+i-1) = *(meanv+i-2);
1351: /*
1352: Cholesky decomposition to find A s.t. trans(A)*(A) = COVM
1353: */
1354: spofa(covm,p,p,&info);
1355: if(!(info != 0)) goto S30;
1356: puts(" COVM not positive definite in SETGMN");
1357: exit(1);
1358: S30:
1359: icount = p+1;
1360: /*
1361: PUT UPPER HALF OF A, WHICH IS NOW THE CHOLESKY FACTOR, INTO PARM
1362: COVM(1,1) = PARM(P+2)
1363: COVM(1,2) = PARM(P+3)
1364: :
1365: COVM(1,P) = PARM(2P+1)
1366: COVM(2,2) = PARM(2P+2) ...
1367: */
1368: for(i=1,D4=1,D5=(p-i+D4)/D4; D5>0; D5--,i+=D4) {
1369: for(j=i-1; j<p; j++) {
1370: icount += 1;
1371: *(parm+icount-1) = *(covm+i-1+j*p);
1372: }
1373: }
1374: }
1375: float sexpo(void)
1376: /*
1377: **********************************************************************
1378:
1379:
1380: (STANDARD-) E X P O N E N T I A L DISTRIBUTION
1381:
1382:
1383: **********************************************************************
1384: **********************************************************************
1385:
1386: FOR DETAILS SEE:
1387:
1388: AHRENS, J.H. AND DIETER, U.
1389: COMPUTER METHODS FOR SAMPLING FROM THE
1390: EXPONENTIAL AND NORMAL DISTRIBUTIONS.
1391: COMM. ACM, 15,10 (OCT. 1972), 873 - 882.
1392:
1393: ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM
1394: 'SA' IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)
1395:
1396: Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
1397: SUNIF. The argument IR thus goes away.
1398:
1399: **********************************************************************
1400: Q(N) = SUM(ALOG(2.0)**K/K!) K=1,..,N , THE HIGHEST N
1401: (HERE 8) IS DETERMINED BY Q(N)=1.0 WITHIN STANDARD PRECISION
1402: */
1403: {
1404: static float q[8] = {
1405: 0.6931472,0.9333737,0.9888778,0.9984959,0.9998293,0.9999833,0.9999986,1.0
1406: };
1407: static long i;
1408: static float sexpo,a,u,ustar,umin;
1409: static float *q1 = q;
1410: a = 0.0;
1411: u = ranf();
1412: goto S30;
1413: S20:
1414: a += *q1;
1415: S30:
1416: u += u;
1417: if(u <= 1.0) goto S20;
1418: u -= 1.0;
1419: if(u > *q1) goto S60;
1420: sexpo = a+u;
1421: return sexpo;
1422: S60:
1423: i = 1;
1424: ustar = ranf();
1425: umin = ustar;
1426: S70:
1427: ustar = ranf();
1428: if(ustar < umin) umin = ustar;
1429: i += 1;
1430: if(u > *(q+i-1)) goto S70;
1431: sexpo = a+umin**q1;
1432: return sexpo;
1433: }
1434: float sgamma(float a)
1435: /*
1436: **********************************************************************
1437:
1438:
1439: (STANDARD-) G A M M A DISTRIBUTION
1440:
1441:
1442: **********************************************************************
1443: **********************************************************************
1444:
1445: PARAMETER A >= 1.0 !
1446:
1447: **********************************************************************
1448:
1449: FOR DETAILS SEE:
1450:
1451: AHRENS, J.H. AND DIETER, U.
1452: GENERATING GAMMA VARIATES BY A
1453: MODIFIED REJECTION TECHNIQUE.
1454: COMM. ACM, 25,1 (JAN. 1982), 47 - 54.
1455:
1456: STEP NUMBERS CORRESPOND TO ALGORITHM 'GD' IN THE ABOVE PAPER
1457: (STRAIGHTFORWARD IMPLEMENTATION)
1458:
1459: Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
1460: SUNIF. The argument IR thus goes away.
1461:
1462: **********************************************************************
1463:
1464: PARAMETER 0.0 < A < 1.0 !
1465:
1466: **********************************************************************
1467:
1468: FOR DETAILS SEE:
1469:
1470: AHRENS, J.H. AND DIETER, U.
1471: COMPUTER METHODS FOR SAMPLING FROM GAMMA,
1472: BETA, POISSON AND BINOMIAL DISTRIBUTIONS.
1473: COMPUTING, 12 (1974), 223 - 246.
1474:
1475: (ADAPTED IMPLEMENTATION OF ALGORITHM 'GS' IN THE ABOVE PAPER)
1476:
1477: **********************************************************************
1478: INPUT: A =PARAMETER (MEAN) OF THE STANDARD GAMMA DISTRIBUTION
1479: OUTPUT: SGAMMA = SAMPLE FROM THE GAMMA-(A)-DISTRIBUTION
1480: COEFFICIENTS Q(K) - FOR Q0 = SUM(Q(K)*A**(-K))
1481: COEFFICIENTS A(K) - FOR Q = Q0+(T*T/2)*SUM(A(K)*V**K)
1482: COEFFICIENTS E(K) - FOR EXP(Q)-1 = SUM(E(K)*Q**K)
1483: PREVIOUS A PRE-SET TO ZERO - AA IS A', AAA IS A"
1484: SQRT32 IS THE SQUAREROOT OF 32 = 5.656854249492380
1485: */
1486: {
1487: extern float fsign( float num, float sign );
1488: static float q1 = 4.166669E-2;
1489: static float q2 = 2.083148E-2;
1490: static float q3 = 8.01191E-3;
1491: static float q4 = 1.44121E-3;
1492: static float q5 = -7.388E-5;
1493: static float q6 = 2.4511E-4;
1494: static float q7 = 2.424E-4;
1495: static float a1 = 0.3333333;
1496: static float a2 = -0.250003;
1497: static float a3 = 0.2000062;
1498: static float a4 = -0.1662921;
1499: static float a5 = 0.1423657;
1500: static float a6 = -0.1367177;
1501: static float a7 = 0.1233795;
1502: static float e1 = 1.0;
1503: static float e2 = 0.4999897;
1504: static float e3 = 0.166829;
1505: static float e4 = 4.07753E-2;
1506: static float e5 = 1.0293E-2;
1507: static float aa = 0.0;
1508: static float aaa = 0.0;
1509: static float sqrt32 = 5.656854;
1510: static float sgamma,s2,s,d,t,x,u,r,q0,b,si,c,v,q,e,w,p;
1511: if(a == aa) goto S10;
1512: if(a < 1.0) goto S120;
1513: /*
1514: STEP 1: RECALCULATIONS OF S2,S,D IF A HAS CHANGED
1515: */
1516: aa = a;
1517: s2 = a-0.5;
1518: s = sqrt(s2);
1519: d = sqrt32-12.0*s;
1520: S10:
1521: /*
1522: STEP 2: T=STANDARD NORMAL DEVIATE,
1523: X=(S,1/2)-NORMAL DEVIATE.
1524: IMMEDIATE ACCEPTANCE (I)
1525: */
1526: t = snorm();
1527: x = s+0.5*t;
1528: sgamma = x*x;
1529: if(t >= 0.0) return sgamma;
1530: /*
1531: STEP 3: U= 0,1 -UNIFORM SAMPLE. SQUEEZE ACCEPTANCE (S)
1532: */
1533: u = ranf();
1534: if(d*u <= t*t*t) return sgamma;
1535: /*
1536: STEP 4: RECALCULATIONS OF Q0,B,SI,C IF NECESSARY
1537: */
1538: if(a == aaa) goto S40;
1539: aaa = a;
1540: r = 1.0/ a;
1541: q0 = ((((((q7*r+q6)*r+q5)*r+q4)*r+q3)*r+q2)*r+q1)*r;
1542: /*
1543: APPROXIMATION DEPENDING ON SIZE OF PARAMETER A
1544: THE CONSTANTS IN THE EXPRESSIONS FOR B, SI AND
1545: C WERE ESTABLISHED BY NUMERICAL EXPERIMENTS
1546: */
1547: if(a <= 3.686) goto S30;
1548: if(a <= 13.022) goto S20;
1549: /*
1550: CASE 3: A .GT. 13.022
1551: */
1552: b = 1.77;
1553: si = 0.75;
1554: c = 0.1515/s;
1555: goto S40;
1556: S20:
1557: /*
1558: CASE 2: 3.686 .LT. A .LE. 13.022
1559: */
1560: b = 1.654+7.6E-3*s2;
1561: si = 1.68/s+0.275;
1562: c = 6.2E-2/s+2.4E-2;
1563: goto S40;
1564: S30:
1565: /*
1566: CASE 1: A .LE. 3.686
1567: */
1568: b = 0.463+s-0.178*s2;
1569: si = 1.235;
1570: c = 0.195/s-7.9E-2+1.6E-2*s;
1571: S40:
1572: /*
1573: STEP 5: NO QUOTIENT TEST IF X NOT POSITIVE
1574: */
1575: if(x <= 0.0) goto S70;
1576: /*
1577: STEP 6: CALCULATION OF V AND QUOTIENT Q
1578: */
1579: v = t/(s+s);
1580: if(fabs(v) <= 0.25) goto S50;
1581: q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
1582: goto S60;
1583: S50:
1584: q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
1585: S60:
1586: /*
1587: STEP 7: QUOTIENT ACCEPTANCE (Q)
1588: */
1589: if(log(1.0-u) <= q) return sgamma;
1590: S70:
1591: /*
1592: STEP 8: E=STANDARD EXPONENTIAL DEVIATE
1593: U= 0,1 -UNIFORM DEVIATE
1594: T=(B,SI)-DOUBLE EXPONENTIAL (LAPLACE) SAMPLE
1595: */
1596: e = sexpo();
1597: u = ranf();
1598: u += (u-1.0);
1599: t = b+fsign(si*e,u);
1600: /*
1601: STEP 9: REJECTION IF T .LT. TAU(1) = -.71874483771719
1602: */
1603: if(t < -0.7187449) goto S70;
1604: /*
1605: STEP 10: CALCULATION OF V AND QUOTIENT Q
1606: */
1607: v = t/(s+s);
1608: if(fabs(v) <= 0.25) goto S80;
1609: q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
1610: goto S90;
1611: S80:
1612: q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
1613: S90:
1614: /*
1615: STEP 11: HAT ACCEPTANCE (H) (IF Q NOT POSITIVE GO TO STEP 8)
1616: */
1617: if(q <= 0.0) goto S70;
1618: if(q <= 0.5) goto S100;
1619: w = exp(q)-1.0;
1620: goto S110;
1621: S100:
1622: w = ((((e5*q+e4)*q+e3)*q+e2)*q+e1)*q;
1623: S110:
1624: /*
1625: IF T IS REJECTED, SAMPLE AGAIN AT STEP 8
1626: */
1627: if(c*fabs(u) > w*exp(e-0.5*t*t)) goto S70;
1628: x = s+0.5*t;
1629: sgamma = x*x;
1630: return sgamma;
1631: S120:
1632: /*
1633: ALTERNATE METHOD FOR PARAMETERS A BELOW 1 (.3678794=EXP(-1.))
1634: */
1635: aa = 0.0;
1636: b = 1.0+0.3678794*a;
1637: S130:
1638: p = b*ranf();
1639: if(p >= 1.0) goto S140;
1640: sgamma = exp(log(p)/ a);
1641: if(sexpo() < sgamma) goto S130;
1642: return sgamma;
1643: S140:
1644: sgamma = -log((b-p)/ a);
1645: if(sexpo() < (1.0-a)*log(sgamma)) goto S130;
1646: return sgamma;
1647: }
1648: float snorm(void)
1649: /*
1650: **********************************************************************
1651:
1652:
1653: (STANDARD-) N O R M A L DISTRIBUTION
1654:
1655:
1656: **********************************************************************
1657: **********************************************************************
1658:
1659: FOR DETAILS SEE:
1660:
1661: AHRENS, J.H. AND DIETER, U.
1662: EXTENSIONS OF FORSYTHE'S METHOD FOR RANDOM
1663: SAMPLING FROM THE NORMAL DISTRIBUTION.
1664: MATH. COMPUT., 27,124 (OCT. 1973), 927 - 937.
1665:
1666: ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM 'FL'
1667: (M=5) IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)
1668:
1669: Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
1670: SUNIF. The argument IR thus goes away.
1671:
1672: **********************************************************************
1673: THE DEFINITIONS OF THE CONSTANTS A(K), D(K), T(K) AND
1674: H(K) ARE ACCORDING TO THE ABOVEMENTIONED ARTICLE
1675: */
1676: {
1677: static float a[32] = {
1678: 0.0,3.917609E-2,7.841241E-2,0.11777,0.1573107,0.1970991,0.2372021,0.2776904,
1679: 0.3186394,0.36013,0.4022501,0.4450965,0.4887764,0.5334097,0.5791322,
1680: 0.626099,0.6744898,0.7245144,0.7764218,0.8305109,0.8871466,0.9467818,
1681: 1.00999,1.077516,1.150349,1.229859,1.318011,1.417797,1.534121,1.67594,
1682: 1.862732,2.153875
1683: };
1684: static float d[31] = {
1685: 0.0,0.0,0.0,0.0,0.0,0.2636843,0.2425085,0.2255674,0.2116342,0.1999243,
1686: 0.1899108,0.1812252,0.1736014,0.1668419,0.1607967,0.1553497,0.1504094,
1687: 0.1459026,0.14177,0.1379632,0.1344418,0.1311722,0.128126,0.1252791,
1688: 0.1226109,0.1201036,0.1177417,0.1155119,0.1134023,0.1114027,0.1095039
1689: };
1690: static float t[31] = {
1691: 7.673828E-4,2.30687E-3,3.860618E-3,5.438454E-3,7.0507E-3,8.708396E-3,
1692: 1.042357E-2,1.220953E-2,1.408125E-2,1.605579E-2,1.81529E-2,2.039573E-2,
1693: 2.281177E-2,2.543407E-2,2.830296E-2,3.146822E-2,3.499233E-2,3.895483E-2,
1694: 4.345878E-2,4.864035E-2,5.468334E-2,6.184222E-2,7.047983E-2,8.113195E-2,
1695: 9.462444E-2,0.1123001,0.136498,0.1716886,0.2276241,0.330498,0.5847031
1696: };
1697: static float h[31] = {
1698: 3.920617E-2,3.932705E-2,3.951E-2,3.975703E-2,4.007093E-2,4.045533E-2,
1699: 4.091481E-2,4.145507E-2,4.208311E-2,4.280748E-2,4.363863E-2,4.458932E-2,
1700: 4.567523E-2,4.691571E-2,4.833487E-2,4.996298E-2,5.183859E-2,5.401138E-2,
1701: 5.654656E-2,5.95313E-2,6.308489E-2,6.737503E-2,7.264544E-2,7.926471E-2,
1702: 8.781922E-2,9.930398E-2,0.11556,0.1404344,0.1836142,0.2790016,0.7010474
1703: };
1704: static long i;
1705: static float snorm,u,s,ustar,aa,w,y,tt;
1706: u = ranf();
1707: s = 0.0;
1708: if(u > 0.5) s = 1.0;
1709: u += (u-s);
1710: u = 32.0*u;
1711: i = (long) (u);
1712: if(i == 32) i = 31;
1713: if(i == 0) goto S100;
1714: /*
1715: START CENTER
1716: */
1717: ustar = u-(float)i;
1718: aa = *(a+i-1);
1719: S40:
1720: if(ustar <= *(t+i-1)) goto S60;
1721: w = (ustar-*(t+i-1))**(h+i-1);
1722: S50:
1723: /*
1724: EXIT (BOTH CASES)
1725: */
1726: y = aa+w;
1727: snorm = y;
1728: if(s == 1.0) snorm = -y;
1729: return snorm;
1730: S60:
1731: /*
1732: CENTER CONTINUED
1733: */
1734: u = ranf();
1735: w = u*(*(a+i)-aa);
1736: tt = (0.5*w+aa)*w;
1737: goto S80;
1738: S70:
1739: tt = u;
1740: ustar = ranf();
1741: S80:
1742: if(ustar > tt) goto S50;
1743: u = ranf();
1744: if(ustar >= u) goto S70;
1745: ustar = ranf();
1746: goto S40;
1747: S100:
1748: /*
1749: START TAIL
1750: */
1751: i = 6;
1752: aa = *(a+31);
1753: goto S120;
1754: S110:
1755: aa += *(d+i-1);
1756: i += 1;
1757: S120:
1758: u += u;
1759: if(u < 1.0) goto S110;
1760: u -= 1.0;
1761: S140:
1762: w = u**(d+i-1);
1763: tt = (0.5*w+aa)*w;
1764: goto S160;
1765: S150:
1766: tt = u;
1767: S160:
1768: ustar = ranf();
1769: if(ustar > tt) goto S50;
1770: u = ranf();
1771: if(ustar >= u) goto S150;
1772: u = ranf();
1773: goto S140;
1774: }
1775: float fsign( float num, float sign )
1776: /* Transfers sign of argument sign to argument num */
1777: {
1778: if ( ( sign>0.0f && num<0.0f ) || ( sign<0.0f && num>0.0f ) )
1779: return -num;
1780: else return num;
1781: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>