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