random_variable 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ext/randlib.c ADDED
@@ -0,0 +1,2162 @@
1
+ #include "randlib.h"
2
+ #include <stdio.h>
3
+ #include <math.h>
4
+ #include <stdlib.h>
5
+ #define ABS(x) ((x) >= 0 ? (x) : -(x))
6
+ #define min(a,b) ((a) <= (b) ? (a) : (b))
7
+ #define max(a,b) ((a) >= (b) ? (a) : (b))
8
+ void ftnstop(const char*);
9
+
10
+ double genbet(double aa,double bb)
11
+ /*
12
+ **********************************************************************
13
+ double genbet(double aa,double bb)
14
+ GeNerate BETa random deviate
15
+ Function
16
+ Returns a single random deviate from the beta distribution with
17
+ parameters A and B. The density of the beta is
18
+ x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1
19
+ Arguments
20
+ aa --> First parameter of the beta distribution
21
+
22
+ bb --> Second parameter of the beta distribution
23
+
24
+ Method
25
+ R. C. H. Cheng
26
+ Generating Beta Variates with Nonintegral Shape Parameters
27
+ Communications of the ACM, 21:317-322 (1978)
28
+ (Algorithms BB and BC)
29
+ **********************************************************************
30
+ */
31
+ {
32
+ /* JJV changed expmax (log(1.0E38)==87.49823), and added minlog */
33
+ #define expmax 87.4982335337737
34
+ #define infnty 1.0E38
35
+ #define minlog 1.0E-37
36
+ static double olda = -1.0E37;
37
+ static double oldb = -1.0E37;
38
+ static double genbet,a,alpha,b,beta,delta,gamma,k1,k2,r,s,t,u1,u2,v,w,y,z;
39
+ static long qsame;
40
+
41
+ qsame = olda == aa && oldb == bb;
42
+ if(qsame) goto S20;
43
+ if(!(aa < minlog || bb < minlog)) goto S10;
44
+ fputs(" AA or BB < 1.0E-37 in GENBET - Abort!\n",stderr);
45
+ fprintf(stderr," AA: %16.6E BB %16.6E\n",aa,bb);
46
+ exit(1);
47
+ S10:
48
+ olda = aa;
49
+ oldb = bb;
50
+ S20:
51
+ if(!(min(aa,bb) > 1.0)) goto S100;
52
+ /*
53
+ Algorithm BB
54
+ Initialize
55
+ */
56
+ if(qsame) goto S30;
57
+ a = min(aa,bb);
58
+ b = max(aa,bb);
59
+ alpha = a+b;
60
+ beta = sqrt((alpha-2.0)/(2.0*a*b-alpha));
61
+ gamma = a+1.0/beta;
62
+ S30:
63
+ u1 = ranf();
64
+ /*
65
+ Step 1
66
+ */
67
+ u2 = ranf();
68
+ v = beta*log(u1/(1.0-u1));
69
+ /* JJV altered this */
70
+ if(v > expmax) goto S55;
71
+ /*
72
+ * JJV added checker to see if a*exp(v) will overflow
73
+ * JJV S50 _was_ w = a*exp(v); also note here a > 1.0
74
+ */
75
+ w = exp(v);
76
+ if(w > infnty/a) goto S55;
77
+ w *= a;
78
+ goto S60;
79
+ S55:
80
+ w = infnty;
81
+ S60:
82
+ z = pow(u1,2.0)*u2;
83
+ r = gamma*v-1.38629436111989;
84
+ s = a+r-w;
85
+ /*
86
+ Step 2
87
+ */
88
+ if(s+2.60943791243410 >= 5.0*z) goto S70;
89
+ /*
90
+ Step 3
91
+ */
92
+ t = log(z);
93
+ if(s > t) goto S70;
94
+ /*
95
+ * Step 4
96
+ *
97
+ * JJV added checker to see if log(alpha/(b+w)) will
98
+ * JJV overflow. If so, we count the log as -INF, and
99
+ * JJV consequently evaluate conditional as true, i.e.
100
+ * JJV the algorithm rejects the trial and starts over
101
+ * JJV May not need this here since alpha > 2.0
102
+ */
103
+ if(alpha/(b+w) < minlog) goto S30;
104
+ if(r+alpha*log(alpha/(b+w)) < t) goto S30;
105
+ S70:
106
+ /*
107
+ Step 5
108
+ */
109
+ if(aa == a) {
110
+ genbet = w/(b+w);
111
+ } else {
112
+ genbet = b/(b+w);
113
+ }
114
+ goto S230;
115
+ S100:
116
+ /*
117
+ Algorithm BC
118
+ Initialize
119
+ */
120
+ if(qsame) goto S110;
121
+ a = max(aa,bb);
122
+ b = min(aa,bb);
123
+ alpha = a+b;
124
+ beta = 1.0/b;
125
+ delta = 1.0+a-b;
126
+ k1 = delta*(1.38888888888889E-2+4.16666666666667E-2*b) /
127
+ (a*beta-0.777777777777778);
128
+ k2 = 0.25+(0.5+0.25/delta)*b;
129
+ S110:
130
+ S120:
131
+ u1 = ranf();
132
+ /*
133
+ Step 1
134
+ */
135
+ u2 = ranf();
136
+ if(u1 >= 0.5) goto S130;
137
+ /*
138
+ Step 2
139
+ */
140
+ y = u1*u2;
141
+ z = u1*y;
142
+ if(0.25*u2+z-y >= k1) goto S120;
143
+ goto S170;
144
+ S130:
145
+ /*
146
+ Step 3
147
+ */
148
+ z = pow(u1,2.0)*u2;
149
+ if(!(z <= 0.25)) goto S160;
150
+ v = beta*log(u1/(1.0-u1));
151
+ /*
152
+ * JJV instead of checking v > expmax at top, I will check
153
+ * JJV if a < 1, then check the appropriate values
154
+ */
155
+ if(a > 1.0) goto S135;
156
+ /* JJV a < 1 so it can help out if exp(v) would overflow */
157
+ if(v > expmax) goto S132;
158
+ w = a*exp(v);
159
+ goto S200;
160
+ S132:
161
+ w = v + log(a);
162
+ if(w > expmax) goto S140;
163
+ w = exp(w);
164
+ goto S200;
165
+ S135:
166
+ /* JJV in this case a > 1 */
167
+ if(v > expmax) goto S140;
168
+ w = exp(v);
169
+ if(w > infnty/a) goto S140;
170
+ w *= a;
171
+ goto S200;
172
+ S140:
173
+ w = infnty;
174
+ goto S200;
175
+ /*
176
+ * JJV old code
177
+ * if(!(v > expmax)) goto S140;
178
+ * w = infnty;
179
+ * goto S150;
180
+ *S140:
181
+ * w = a*exp(v);
182
+ *S150:
183
+ * goto S200;
184
+ */
185
+ S160:
186
+ if(z >= k2) goto S120;
187
+ S170:
188
+ /*
189
+ Step 4
190
+ Step 5
191
+ */
192
+ v = beta*log(u1/(1.0-u1));
193
+ /* JJV same kind of checking as above */
194
+ if(a > 1.0) goto S175;
195
+ /* JJV a < 1 so it can help out if exp(v) would overflow */
196
+ if(v > expmax) goto S172;
197
+ w = a*exp(v);
198
+ goto S190;
199
+ S172:
200
+ w = v + log(a);
201
+ if(w > expmax) goto S180;
202
+ w = exp(w);
203
+ goto S190;
204
+ S175:
205
+ /* JJV in this case a > 1.0 */
206
+ if(v > expmax) goto S180;
207
+ w = exp(v);
208
+ if(w > infnty/a) goto S180;
209
+ w *= a;
210
+ goto S190;
211
+ S180:
212
+ w = infnty;
213
+ /*
214
+ * JJV old code
215
+ * if(!(v > expmax)) goto S180;
216
+ * w = infnty;
217
+ * goto S190;
218
+ *S180:
219
+ * w = a*exp(v);
220
+ */
221
+ S190:
222
+ /*
223
+ * JJV here we also check to see if log overlows; if so, we treat it
224
+ * JJV as -INF, which means condition is true, i.e. restart
225
+ */
226
+ if(alpha/(b+w) < minlog) goto S120;
227
+ if(alpha*(log(alpha/(b+w))+v)-1.38629436111989 < log(z)) goto S120;
228
+ S200:
229
+ /*
230
+ Step 6
231
+ */
232
+ if(a == aa) {
233
+ genbet = w/(b+w);
234
+ } else {
235
+ genbet = b/(b+w);
236
+ }
237
+ S230:
238
+ return genbet;
239
+ #undef expmax
240
+ #undef infnty
241
+ #undef minlog
242
+ }
243
+
244
+ double genchi(double df)
245
+ /*
246
+ **********************************************************************
247
+ double genchi(double df)
248
+ Generate random value of CHIsquare variable
249
+ Function
250
+ Generates random deviate from the distribution of a chisquare
251
+ with DF degrees of freedom random variable.
252
+ Arguments
253
+ df --> Degrees of freedom of the chisquare
254
+ (Must be positive)
255
+
256
+ Method
257
+ Uses relation between chisquare and gamma.
258
+ **********************************************************************
259
+ */
260
+ {
261
+ static double genchi;
262
+
263
+ if(!(df <= 0.0)) goto S10;
264
+ fputs(" DF <= 0 in GENCHI - ABORT\n",stderr);
265
+ fprintf(stderr," Value of DF: %16.6E\n",df);
266
+ exit(1);
267
+ S10:
268
+ /*
269
+ * JJV changed the code to call SGAMMA directly
270
+ * genchi = 2.0*gengam(1.0,df/2.0); <- OLD
271
+ */
272
+ genchi = 2.0*sgamma(df/2.0);
273
+ return genchi;
274
+ }
275
+
276
+ double genexp(double av)
277
+ /*
278
+ **********************************************************************
279
+ double genexp(double av)
280
+ GENerate EXPonential random deviate
281
+ Function
282
+ Generates a single random deviate from an exponential
283
+ distribution with mean AV.
284
+ Arguments
285
+ av --> The mean of the exponential distribution from which
286
+ a random deviate is to be generated.
287
+ JJV (av >= 0)
288
+ Method
289
+ Renames SEXPO from TOMS as slightly modified by BWB to use RANF
290
+ instead of SUNIF.
291
+ For details see:
292
+ Ahrens, J.H. and Dieter, U.
293
+ Computer Methods for Sampling From the
294
+ Exponential and Normal Distributions.
295
+ Comm. ACM, 15,10 (Oct. 1972), 873 - 882.
296
+ **********************************************************************
297
+ */
298
+ {
299
+ static double genexp;
300
+
301
+ /* JJV added check that av >= 0 */
302
+ if(av >= 0.0) goto S10;
303
+ fputs(" AV < 0 in GENEXP - ABORT\n",stderr);
304
+ fprintf(stderr," Value of AV: %16.6E\n",av);
305
+ exit(1);
306
+ S10:
307
+ genexp = sexpo()*av;
308
+ return genexp;
309
+ }
310
+
311
+ double genf(double dfn,double dfd)
312
+ /*
313
+ **********************************************************************
314
+ double genf(double dfn,double dfd)
315
+ GENerate random deviate from the F distribution
316
+ Function
317
+ Generates a random deviate from the F (variance ratio)
318
+ distribution with DFN degrees of freedom in the numerator
319
+ and DFD degrees of freedom in the denominator.
320
+ Arguments
321
+ dfn --> Numerator degrees of freedom
322
+ (Must be positive)
323
+ dfd --> Denominator degrees of freedom
324
+ (Must be positive)
325
+ Method
326
+ Directly generates ratio of chisquare variates
327
+ **********************************************************************
328
+ */
329
+ {
330
+ static double genf,xden,xnum;
331
+
332
+ if(!(dfn <= 0.0 || dfd <= 0.0)) goto S10;
333
+ fputs(" Degrees of freedom nonpositive in GENF - abort!\n",stderr);
334
+ fprintf(stderr," DFN value: %16.6E DFD value: %16.6E\n",dfn,dfd);
335
+ exit(1);
336
+ S10:
337
+ /*
338
+ * JJV changed this to call SGAMMA directly
339
+ *
340
+ * GENF = ( GENCHI( DFN ) / DFN ) / ( GENCHI( DFD ) / DFD )
341
+ * xnum = genchi(dfn)/dfn; <- OLD
342
+ * xden = genchi(dfd)/dfd; <- OLD
343
+ */
344
+ xnum = 2.0*sgamma(dfn/2.0)/dfn;
345
+ xden = 2.0*sgamma(dfd/2.0)/dfd;
346
+ /*
347
+ * JJV changed constant to prevent underflow at compile time.
348
+ * if(!(xden <= 9.999999999998E-39*xnum)) goto S20;
349
+ */
350
+ if(!(xden <= 1.0E-37*xnum)) goto S20;
351
+ fputs(" GENF - generated numbers would cause overflow\n",stderr);
352
+ fprintf(stderr," Numerator %16.6E Denominator %16.6E\n",xnum,xden);
353
+ /*
354
+ * JJV changed next 2 lines to reflect constant change above in the
355
+ * JJV truncated value returned.
356
+ * fputs(" GENF returning 1.0E38\n",stderr);
357
+ * genf = 1.0E38;
358
+ */
359
+ fputs(" GENF returning 1.0E37\n",stderr);
360
+ genf = 1.0E37;
361
+ goto S30;
362
+ S20:
363
+ genf = xnum/xden;
364
+ S30:
365
+ return genf;
366
+ }
367
+
368
+ double gengam(double a,double r)
369
+ /*
370
+ **********************************************************************
371
+ double gengam(double a,double r)
372
+ GENerates random deviates from GAMma distribution
373
+ Function
374
+ Generates random deviates from the gamma distribution whose
375
+ density is
376
+ (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X)
377
+ Arguments
378
+ a --> Location parameter of Gamma distribution
379
+ JJV (a > 0)
380
+ r --> Shape parameter of Gamma distribution
381
+ JJV (r > 0)
382
+ Method
383
+ Renames SGAMMA from TOMS as slightly modified by BWB to use RANF
384
+ instead of SUNIF.
385
+ For details see:
386
+ (Case R >= 1.0)
387
+ Ahrens, J.H. and Dieter, U.
388
+ Generating Gamma Variates by a
389
+ Modified Rejection Technique.
390
+ Comm. ACM, 25,1 (Jan. 1982), 47 - 54.
391
+ Algorithm GD
392
+ JJV altered following to reflect argument ranges
393
+ (Case 0.0 < R < 1.0)
394
+ Ahrens, J.H. and Dieter, U.
395
+ Computer Methods for Sampling from Gamma,
396
+ Beta, Poisson and Binomial Distributions.
397
+ Computing, 12 (1974), 223-246/
398
+ Adapted algorithm GS.
399
+ **********************************************************************
400
+ */
401
+ {
402
+ static double gengam;
403
+ /* JJV added argument checker */
404
+ if(a > 0.0 && r > 0.0) goto S10;
405
+ fputs(" A or R nonpositive in GENGAM - abort!\n",stderr);
406
+ fprintf(stderr," A value: %16.6E R value: %16.6E\n",a,r);
407
+ exit(1);
408
+ S10:
409
+ gengam = sgamma(r);
410
+ gengam /= a;
411
+ return gengam;
412
+ }
413
+
414
+ void genmn(double *parm,double *x,double *work)
415
+ /*
416
+ **********************************************************************
417
+ void genmn(double *parm,double *x,double *work)
418
+ GENerate Multivariate Normal random deviate
419
+ Arguments
420
+ parm --> Parameters needed to generate multivariate normal
421
+ deviates (MEANV and Cholesky decomposition of
422
+ COVM). Set by a previous call to SETGMN.
423
+ 1 : 1 - size of deviate, P
424
+ 2 : P + 1 - mean vector
425
+ P+2 : P*(P+3)/2 + 1 - upper half of cholesky
426
+ decomposition of cov matrix
427
+ x <-- Vector deviate generated.
428
+ work <--> Scratch array
429
+ Method
430
+ 1) Generate P independent standard normal deviates - Ei ~ N(0,1)
431
+ 2) Using Cholesky decomposition find A s.t. trans(A)*A = COVM
432
+ 3) trans(A)E + MEANV ~ N(MEANV,COVM)
433
+ **********************************************************************
434
+ */
435
+ {
436
+ static long i,icount,j,p,D1,D2,D3,D4;
437
+ static double ae;
438
+
439
+ p = (long) (*parm);
440
+ /*
441
+ Generate P independent normal deviates - WORK ~ N(0,1)
442
+ */
443
+ for(i=1; i<=p; i++) *(work+i-1) = snorm();
444
+ for(i=1,D3=1,D4=(p-i+D3)/D3; D4>0; D4--,i+=D3) {
445
+ /*
446
+ PARM (P+2 : P*(P+3)/2 + 1) contains A, the Cholesky
447
+ decomposition of the desired covariance matrix.
448
+ trans(A)(1,1) = PARM(P+2)
449
+ trans(A)(2,1) = PARM(P+3)
450
+ trans(A)(2,2) = PARM(P+2+P)
451
+ trans(A)(3,1) = PARM(P+4)
452
+ trans(A)(3,2) = PARM(P+3+P)
453
+ trans(A)(3,3) = PARM(P+2-1+2P) ...
454
+ trans(A)*WORK + MEANV ~ N(MEANV,COVM)
455
+ */
456
+ icount = 0;
457
+ ae = 0.0;
458
+ for(j=1,D1=1,D2=(i-j+D1)/D1; D2>0; D2--,j+=D1) {
459
+ icount += (j-1);
460
+ ae += (*(parm+i+(j-1)*p-icount+p)**(work+j-1));
461
+ }
462
+ *(x+i-1) = ae+*(parm+i);
463
+ }
464
+ }
465
+
466
+ void genmul(long n,double *p,long ncat,long *ix)
467
+ /*
468
+ **********************************************************************
469
+
470
+ void genmul(int n,double *p,int ncat,int *ix)
471
+ GENerate an observation from the MULtinomial distribution
472
+ Arguments
473
+ N --> Number of events that will be classified into one of
474
+ the categories 1..NCAT
475
+ P --> Vector of probabilities. P(i) is the probability that
476
+ an event will be classified into category i. Thus, P(i)
477
+ must be [0,1]. Only the first NCAT-1 P(i) must be defined
478
+ since P(NCAT) is 1.0 minus the sum of the first
479
+ NCAT-1 P(i).
480
+ NCAT --> Number of categories. Length of P and IX.
481
+ IX <-- Observation from multinomial distribution. All IX(i)
482
+ will be nonnegative and their sum will be N.
483
+ Method
484
+ Algorithm from page 559 of
485
+
486
+ Devroye, Luc
487
+
488
+ Non-Uniform Random Variate Generation. Springer-Verlag,
489
+ New York, 1986.
490
+
491
+ **********************************************************************
492
+ */
493
+ {
494
+ static double prob,ptot,sum;
495
+ static long i,icat,ntot;
496
+ if(n < 0) ftnstop("N < 0 in GENMUL");
497
+ if(ncat <= 1) ftnstop("NCAT <= 1 in GENMUL");
498
+ ptot = 0.0F;
499
+ for(i=0; i<ncat-1; i++) {
500
+ if(*(p+i) < 0.0F) ftnstop("Some P(i) < 0 in GENMUL");
501
+ if(*(p+i) > 1.0F) ftnstop("Some P(i) > 1 in GENMUL");
502
+ ptot += *(p+i);
503
+ }
504
+ if(ptot > 0.99999F) ftnstop("Sum of P(i) > 1 in GENMUL");
505
+ /*
506
+ Initialize variables
507
+ */
508
+ ntot = n;
509
+ sum = 1.0F;
510
+ for(i=0; i<ncat; i++) ix[i] = 0;
511
+ /*
512
+ Generate the observation
513
+ */
514
+ for(icat=0; icat<ncat-1; icat++) {
515
+ prob = *(p+icat)/sum;
516
+ *(ix+icat) = ignbin(ntot,prob);
517
+ ntot -= *(ix+icat);
518
+ if(ntot <= 0) return;
519
+ sum -= *(p+icat);
520
+ }
521
+ *(ix+ncat-1) = ntot;
522
+ /*
523
+ Finished
524
+ */
525
+ return;
526
+ }
527
+
528
+ double gennch(double df,double xnonc)
529
+ /*
530
+ **********************************************************************
531
+ double gennch(double df,double xnonc)
532
+ Generate random value of Noncentral CHIsquare variable
533
+ Function
534
+ Generates random deviate from the distribution of a noncentral
535
+ chisquare with DF degrees of freedom and noncentrality parameter
536
+ xnonc.
537
+ Arguments
538
+ df --> Degrees of freedom of the chisquare
539
+ (Must be >= 1.0)
540
+ xnonc --> Noncentrality parameter of the chisquare
541
+ (Must be >= 0.0)
542
+ Method
543
+ Uses fact that noncentral chisquare is the sum of a chisquare
544
+ deviate with DF-1 degrees of freedom plus the square of a normal
545
+ deviate with mean XNONC and standard deviation 1.
546
+ **********************************************************************
547
+ */
548
+ {
549
+ static double gennch;
550
+
551
+ if(!(df < 1.0 || xnonc < 0.0)) goto S10;
552
+ fputs("DF < 1 or XNONC < 0 in GENNCH - ABORT\n",stderr);
553
+ fprintf(stderr,"Value of DF: %16.6E Value of XNONC: %16.6E\n",df,xnonc);
554
+ exit(1);
555
+ /* JJV changed code to call SGAMMA, SNORM directly */
556
+ S10:
557
+ if(df >= 1.000000001) goto S20;
558
+ /*
559
+ * JJV case df == 1.0
560
+ * gennch = pow(gennor(sqrt(xnonc),1.0),2.0); <- OLD
561
+ */
562
+ gennch = pow(snorm()+sqrt(xnonc),2.0);
563
+ goto S30;
564
+ S20:
565
+ /*
566
+ * JJV case df > 1.0
567
+ * gennch = genchi(df-1.0)+pow(gennor(sqrt(xnonc),1.0),2.0); <- OLD
568
+ */
569
+ gennch = 2.0*sgamma((df-1.0)/2.0)+pow(snorm()+sqrt(xnonc),2.0);
570
+ S30:
571
+ return gennch;
572
+ }
573
+
574
+ double gennf(double dfn,double dfd,double xnonc)
575
+ /*
576
+ **********************************************************************
577
+ double gennf(double dfn,double dfd,double xnonc)
578
+ GENerate random deviate from the Noncentral F distribution
579
+ Function
580
+ Generates a random deviate from the noncentral F (variance ratio)
581
+ distribution with DFN degrees of freedom in the numerator, and DFD
582
+ degrees of freedom in the denominator, and noncentrality parameter
583
+ XNONC.
584
+ Arguments
585
+ dfn --> Numerator degrees of freedom
586
+ (Must be >= 1.0)
587
+ dfd --> Denominator degrees of freedom
588
+ (Must be positive)
589
+ xnonc --> Noncentrality parameter
590
+ (Must be nonnegative)
591
+ Method
592
+ Directly generates ratio of noncentral numerator chisquare variate
593
+ to central denominator chisquare variate.
594
+ **********************************************************************
595
+ */
596
+ {
597
+ static double gennf,xden,xnum;
598
+ static long qcond;
599
+
600
+ /* JJV changed qcond, error message to allow dfn == 1.0 */
601
+ qcond = dfn < 1.0 || dfd <= 0.0 || xnonc < 0.0;
602
+ if(!qcond) goto S10;
603
+ fputs("In GENNF - Either (1) Numerator DF < 1.0 or\n",stderr);
604
+ fputs(" (2) Denominator DF <= 0.0 or\n",stderr);
605
+ fputs(" (3) Noncentrality parameter < 0.0\n",stderr);
606
+ fprintf(stderr,
607
+ "DFN value: %16.6E DFD value: %16.6E XNONC value: \n%16.6E\n",dfn,dfd,
608
+ xnonc);
609
+ exit(1);
610
+ S10:
611
+ /*
612
+ * JJV changed the code to call SGAMMA and SNORM directly
613
+ * GENNF = ( GENNCH( DFN, XNONC ) / DFN ) / ( GENCHI( DFD ) / DFD )
614
+ * xnum = gennch(dfn,xnonc)/dfn; <- OLD
615
+ * xden = genchi(dfd)/dfd; <- OLD
616
+ */
617
+ if(dfn >= 1.000001) goto S20;
618
+ /* JJV case dfn == 1.0, dfn is counted as exactly 1.0 */
619
+ xnum = pow(snorm()+sqrt(xnonc),2.0);
620
+ goto S30;
621
+ S20:
622
+ /* JJV case df > 1.0 */
623
+ xnum = (2.0*sgamma((dfn-1.0)/2.0)+pow(snorm()+sqrt(xnonc),2.0))/dfn;
624
+ S30:
625
+ xden = 2.0*sgamma(dfd/2.0)/dfd;
626
+ /*
627
+ * JJV changed constant to prevent underflow at compile time.
628
+ * if(!(xden <= 9.999999999998E-39*xnum)) goto S40;
629
+ */
630
+ if(!(xden <= 1.0E-37*xnum)) goto S40;
631
+ fputs(" GENNF - generated numbers would cause overflow\n",stderr);
632
+ fprintf(stderr," Numerator %16.6E Denominator %16.6E\n",xnum,xden);
633
+ /*
634
+ * JJV changed next 2 lines to reflect constant change above in the
635
+ * JJV truncated value returned.
636
+ * fputs(" GENNF returning 1.0E38\n",stderr);
637
+ * gennf = 1.0E38;
638
+ */
639
+ fputs(" GENNF returning 1.0E37\n",stderr);
640
+ gennf = 1.0E37;
641
+ goto S50;
642
+ S40:
643
+ gennf = xnum/xden;
644
+ S50:
645
+ return gennf;
646
+ }
647
+
648
+ double gennor(double av,double sd)
649
+ /*
650
+ **********************************************************************
651
+ double gennor(double av,double sd)
652
+ GENerate random deviate from a NORmal distribution
653
+ Function
654
+ Generates a single random deviate from a normal distribution
655
+ with mean, AV, and standard deviation, SD.
656
+ Arguments
657
+ av --> Mean of the normal distribution.
658
+ sd --> Standard deviation of the normal distribution.
659
+ JJV (sd >= 0)
660
+ Method
661
+ Renames SNORM from TOMS as slightly modified by BWB to use RANF
662
+ instead of SUNIF.
663
+ For details see:
664
+ Ahrens, J.H. and Dieter, U.
665
+ Extensions of Forsythe's Method for Random
666
+ Sampling from the Normal Distribution.
667
+ Math. Comput., 27,124 (Oct. 1973), 927 - 937.
668
+ **********************************************************************
669
+ */
670
+ {
671
+ static double gennor;
672
+
673
+ /* JJV added argument checker */
674
+ if(sd >= 0.0) goto S10;
675
+ fputs(" SD < 0 in GENNOR - ABORT\n",stderr);
676
+ fprintf(stderr," Value of SD: %16.6E\n",sd);
677
+ exit(1);
678
+ S10:
679
+ gennor = sd*snorm()+av;
680
+ return gennor;
681
+ }
682
+
683
+ void genprm(long *iarray,int larray)
684
+ /*
685
+ **********************************************************************
686
+ void genprm(long *iarray,int larray)
687
+ GENerate random PeRMutation of iarray
688
+ Arguments
689
+ iarray <--> On output IARRAY is a random permutation of its
690
+ value on input
691
+ larray <--> Length of IARRAY
692
+ **********************************************************************
693
+ */
694
+ {
695
+ static long i,itmp,iwhich,D1,D2;
696
+
697
+ for(i=1,D1=1,D2=(larray-i+D1)/D1; D2>0; D2--,i+=D1) {
698
+ iwhich = ignuin(i,larray);
699
+ itmp = *(iarray+iwhich-1);
700
+ *(iarray+iwhich-1) = *(iarray+i-1);
701
+ *(iarray+i-1) = itmp;
702
+ }
703
+ }
704
+
705
+ double genunf(double low,double high)
706
+ /*
707
+ **********************************************************************
708
+ double genunf(double low,double high)
709
+ GeNerate Uniform Real between LOW and HIGH
710
+ Function
711
+ Generates a real uniformly distributed between LOW and HIGH.
712
+ Arguments
713
+ low --> Low bound (exclusive) on real value to be generated
714
+ high --> High bound (exclusive) on real value to be generated
715
+ **********************************************************************
716
+ */
717
+ {
718
+ static double genunf;
719
+
720
+ if(!(low > high)) goto S10;
721
+ fprintf(stderr,"LOW > HIGH in GENUNF: LOW %16.6E HIGH: %16.6E\n",low,high);
722
+ fputs("Abort\n",stderr);
723
+ exit(1);
724
+ S10:
725
+ genunf = low+(high-low)*ranf();
726
+ return genunf;
727
+ }
728
+
729
+ void gscgn(long getset,long *g)
730
+ /*
731
+ **********************************************************************
732
+ void gscgn(long getset,long *g)
733
+ Get/Set GeNerator
734
+ Gets or returns in G the number of the current generator
735
+ Arguments
736
+ getset --> 0 Get
737
+ 1 Set
738
+ g <-- Number of the current random number generator (1..32)
739
+ **********************************************************************
740
+ */
741
+ {
742
+ #define numg 32L
743
+ static long curntg = 1;
744
+ if(getset == 0) *g = curntg;
745
+ else {
746
+ if(*g < 0 || *g > numg) {
747
+ fputs(" Generator number out of range in GSCGN\n",stderr);
748
+ exit(0);
749
+ }
750
+ curntg = *g;
751
+ }
752
+ #undef numg
753
+ }
754
+
755
+ void gsrgs(long getset,long *qvalue)
756
+ /*
757
+ **********************************************************************
758
+ void gsrgs(long getset,long *qvalue)
759
+ Get/Set Random Generators Set
760
+ Gets or sets whether random generators set (initialized).
761
+ Initially (data statement) state is not set
762
+ If getset is 1 state is set to qvalue
763
+ If getset is 0 state returned in qvalue
764
+ **********************************************************************
765
+ */
766
+ {
767
+ static long qinit = 0;
768
+
769
+ if(getset == 0) *qvalue = qinit;
770
+ else qinit = *qvalue;
771
+ }
772
+
773
+ void gssst(long getset,long *qset)
774
+ /*
775
+ **********************************************************************
776
+ void gssst(long getset,long *qset)
777
+ Get or Set whether Seed is Set
778
+ Initialize to Seed not Set
779
+ If getset is 1 sets state to Seed Set
780
+ If getset is 0 returns T in qset if Seed Set
781
+ Else returns F in qset
782
+ **********************************************************************
783
+ */
784
+ {
785
+ static long qstate = 0;
786
+ if(getset != 0) qstate = 1;
787
+ else *qset = qstate;
788
+ }
789
+
790
+ long ignbin(long n,double pp)
791
+ /*
792
+ **********************************************************************
793
+ long ignbin(long n,double pp)
794
+ GENerate BINomial random deviate
795
+ Function
796
+ Generates a single random deviate from a binomial
797
+ distribution whose number of trials is N and whose
798
+ probability of an event in each trial is P.
799
+ Arguments
800
+ n --> The number of trials in the binomial distribution
801
+ from which a random deviate is to be generated.
802
+ JJV (N >= 0)
803
+ pp --> The probability of an event in each trial of the
804
+ binomial distribution from which a random deviate
805
+ is to be generated.
806
+ JJV (0.0 <= PP <= 1.0)
807
+ ignbin <-- A random deviate yielding the number of events
808
+ from N independent trials, each of which has
809
+ a probability of event P.
810
+ Method
811
+ This is algorithm BTPE from:
812
+ Kachitvichyanukul, V. and Schmeiser, B. W.
813
+ Binomial Random Variate Generation.
814
+ Communications of the ACM, 31, 2
815
+ (February, 1988) 216.
816
+ **********************************************************************
817
+ SUBROUTINE BTPEC(N,PP,ISEED,JX)
818
+ BINOMIAL RANDOM VARIATE GENERATOR
819
+ MEAN .LT. 30 -- INVERSE CDF
820
+ MEAN .GE. 30 -- ALGORITHM BTPE: ACCEPTANCE-REJECTION VIA
821
+ FOUR REGION COMPOSITION. THE FOUR REGIONS ARE A TRIANGLE
822
+ (SYMMETRIC IN THE CENTER), A PAIR OF PARALLELOGRAMS (ABOVE
823
+ THE TRIANGLE), AND EXPONENTIAL LEFT AND RIGHT TAILS.
824
+ BTPE REFERS TO BINOMIAL-TRIANGLE-PARALLELOGRAM-EXPONENTIAL.
825
+ BTPEC REFERS TO BTPE AND "COMBINED." THUS BTPE IS THE
826
+ RESEARCH AND BTPEC IS THE IMPLEMENTATION OF A COMPLETE
827
+ USABLE ALGORITHM.
828
+ REFERENCE: VORATAS KACHITVICHYANUKUL AND BRUCE SCHMEISER,
829
+ "BINOMIAL RANDOM VARIATE GENERATION,"
830
+ COMMUNICATIONS OF THE ACM, FORTHCOMING
831
+ WRITTEN: SEPTEMBER 1980.
832
+ LAST REVISED: MAY 1985, JULY 1987
833
+ REQUIRED SUBPROGRAM: RAND() -- A UNIFORM (0,1) RANDOM NUMBER
834
+ GENERATOR
835
+ ARGUMENTS
836
+ N : NUMBER OF BERNOULLI TRIALS (INPUT)
837
+ PP : PROBABILITY OF SUCCESS IN EACH TRIAL (INPUT)
838
+ ISEED: RANDOM NUMBER SEED (INPUT AND OUTPUT)
839
+ JX: RANDOMLY GENERATED OBSERVATION (OUTPUT)
840
+ VARIABLES
841
+ PSAVE: VALUE OF PP FROM THE LAST CALL TO BTPEC
842
+ NSAVE: VALUE OF N FROM THE LAST CALL TO BTPEC
843
+ XNP: VALUE OF THE MEAN FROM THE LAST CALL TO BTPEC
844
+ P: PROBABILITY USED IN THE GENERATION PHASE OF BTPEC
845
+ FFM: TEMPORARY VARIABLE EQUAL TO XNP + P
846
+ M: INTEGER VALUE OF THE CURRENT MODE
847
+ FM: FLOATING POINT VALUE OF THE CURRENT MODE
848
+ XNPQ: TEMPORARY VARIABLE USED IN SETUP AND SQUEEZING STEPS
849
+ P1: AREA OF THE TRIANGLE
850
+ C: HEIGHT OF THE PARALLELOGRAMS
851
+ XM: CENTER OF THE TRIANGLE
852
+ XL: LEFT END OF THE TRIANGLE
853
+ XR: RIGHT END OF THE TRIANGLE
854
+ AL: TEMPORARY VARIABLE
855
+ XLL: RATE FOR THE LEFT EXPONENTIAL TAIL
856
+ XLR: RATE FOR THE RIGHT EXPONENTIAL TAIL
857
+ P2: AREA OF THE PARALLELOGRAMS
858
+ P3: AREA OF THE LEFT EXPONENTIAL TAIL
859
+ P4: AREA OF THE RIGHT EXPONENTIAL TAIL
860
+ U: A U(0,P4) RANDOM VARIATE USED FIRST TO SELECT ONE OF THE
861
+ FOUR REGIONS AND THEN CONDITIONALLY TO GENERATE A VALUE
862
+ FROM THE REGION
863
+ V: A U(0,1) RANDOM NUMBER USED TO GENERATE THE RANDOM VALUE
864
+ (REGION 1) OR TRANSFORMED INTO THE VARIATE TO ACCEPT OR
865
+ REJECT THE CANDIDATE VALUE
866
+ IX: INTEGER CANDIDATE VALUE
867
+ X: PRELIMINARY CONTINUOUS CANDIDATE VALUE IN REGION 2 LOGIC
868
+ AND A FLOATING POINT IX IN THE ACCEPT/REJECT LOGIC
869
+ K: ABSOLUTE VALUE OF (IX-M)
870
+ F: THE HEIGHT OF THE SCALED DENSITY FUNCTION USED IN THE
871
+ ACCEPT/REJECT DECISION WHEN BOTH M AND IX ARE SMALL
872
+ ALSO USED IN THE INVERSE TRANSFORMATION
873
+ R: THE RATIO P/Q
874
+ G: CONSTANT USED IN CALCULATION OF PROBABILITY
875
+ MP: MODE PLUS ONE, THE LOWER INDEX FOR EXPLICIT CALCULATION
876
+ OF F WHEN IX IS GREATER THAN M
877
+ IX1: CANDIDATE VALUE PLUS ONE, THE LOWER INDEX FOR EXPLICIT
878
+ CALCULATION OF F WHEN IX IS LESS THAN M
879
+ I: INDEX FOR EXPLICIT CALCULATION OF F FOR BTPE
880
+ AMAXP: MAXIMUM ERROR OF THE LOGARITHM OF NORMAL BOUND
881
+ YNORM: LOGARITHM OF NORMAL BOUND
882
+ ALV: NATURAL LOGARITHM OF THE ACCEPT/REJECT VARIATE V
883
+ X1,F1,Z,W,Z2,X2,F2, AND W2 ARE TEMPORARY VARIABLES TO BE
884
+ USED IN THE FINAL ACCEPT/REJECT TEST
885
+ QN: PROBABILITY OF NO SUCCESS IN N TRIALS
886
+ REMARK
887
+ IX AND JX COULD LOGICALLY BE THE SAME VARIABLE, WHICH WOULD
888
+ SAVE A MEMORY POSITION AND A LINE OF CODE. HOWEVER, SOME
889
+ COMPILERS (E.G.,CDC MNF) OPTIMIZE BETTER WHEN THE ARGUMENTS
890
+ ARE NOT INVOLVED.
891
+ ISEED NEEDS TO BE DOUBLE PRECISION IF THE IMSL ROUTINE
892
+ GGUBFS IS USED TO GENERATE UNIFORM RANDOM NUMBER, OTHERWISE
893
+ TYPE OF ISEED SHOULD BE DICTATED BY THE UNIFORM GENERATOR
894
+ **********************************************************************
895
+ *****DETERMINE APPROPRIATE ALGORITHM AND WHETHER SETUP IS NECESSARY
896
+ */
897
+ {
898
+ /* JJV changed initial values to ridiculous values */
899
+ static double psave = -1.0E37;
900
+ static long nsave = -214748365;
901
+ static long ignbin,i,ix,ix1,k,m,mp,T1;
902
+ static double al,alv,amaxp,c,f,f1,f2,ffm,fm,g,p,p1,p2,p3,p4,q,qn,r,u,v,w,w2,x,x1,
903
+ x2,xl,xll,xlr,xm,xnp,xnpq,xr,ynorm,z,z2;
904
+
905
+ if(pp != psave) goto S10;
906
+ if(n != nsave) goto S20;
907
+ if(xnp < 30.0) goto S150;
908
+ goto S30;
909
+ S10:
910
+ /*
911
+ *****SETUP, PERFORM ONLY WHEN PARAMETERS CHANGE
912
+ JJV added checks to ensure 0.0 <= PP <= 1.0
913
+ */
914
+ if(pp < 0.0F) ftnstop("PP < 0.0 in IGNBIN");
915
+ if(pp > 1.0F) ftnstop("PP > 1.0 in IGNBIN");
916
+ psave = pp;
917
+ p = min(psave,1.0-psave);
918
+ q = 1.0-p;
919
+ S20:
920
+ /*
921
+ JJV added check to ensure N >= 0
922
+ */
923
+ if(n < 0L) ftnstop("N < 0 in IGNBIN");
924
+ xnp = n*p;
925
+ nsave = n;
926
+ if(xnp < 30.0) goto S140;
927
+ ffm = xnp+p;
928
+ m = ffm;
929
+ fm = m;
930
+ xnpq = xnp*q;
931
+ p1 = (long) (2.195*sqrt(xnpq)-4.6*q)+0.5;
932
+ xm = fm+0.5;
933
+ xl = xm-p1;
934
+ xr = xm+p1;
935
+ c = 0.134+20.5/(15.3+fm);
936
+ al = (ffm-xl)/(ffm-xl*p);
937
+ xll = al*(1.0+0.5*al);
938
+ al = (xr-ffm)/(xr*q);
939
+ xlr = al*(1.0+0.5*al);
940
+ p2 = p1*(1.0+c+c);
941
+ p3 = p2+c/xll;
942
+ p4 = p3+c/xlr;
943
+ S30:
944
+ /*
945
+ *****GENERATE VARIATE
946
+ */
947
+ u = ranf()*p4;
948
+ v = ranf();
949
+ /*
950
+ TRIANGULAR REGION
951
+ */
952
+ if(u > p1) goto S40;
953
+ ix = xm-p1*v+u;
954
+ goto S170;
955
+ S40:
956
+ /*
957
+ PARALLELOGRAM REGION
958
+ */
959
+ if(u > p2) goto S50;
960
+ x = xl+(u-p1)/c;
961
+ v = v*c+1.0-ABS(xm-x)/p1;
962
+ if(v > 1.0 || v <= 0.0) goto S30;
963
+ ix = x;
964
+ goto S70;
965
+ S50:
966
+ /*
967
+ LEFT TAIL
968
+ */
969
+ if(u > p3) goto S60;
970
+ ix = xl+log(v)/xll;
971
+ if(ix < 0) goto S30;
972
+ v *= ((u-p2)*xll);
973
+ goto S70;
974
+ S60:
975
+ /*
976
+ RIGHT TAIL
977
+ */
978
+ ix = xr-log(v)/xlr;
979
+ if(ix > n) goto S30;
980
+ v *= ((u-p3)*xlr);
981
+ S70:
982
+ /*
983
+ *****DETERMINE APPROPRIATE WAY TO PERFORM ACCEPT/REJECT TEST
984
+ */
985
+ k = ABS(ix-m);
986
+ if(k > 20 && k < xnpq/2-1) goto S130;
987
+ /*
988
+ EXPLICIT EVALUATION
989
+ */
990
+ f = 1.0;
991
+ r = p/q;
992
+ g = (n+1)*r;
993
+ T1 = m-ix;
994
+ if(T1 < 0) goto S80;
995
+ else if(T1 == 0) goto S120;
996
+ else goto S100;
997
+ S80:
998
+ mp = m+1;
999
+ for(i=mp; i<=ix; i++) f *= (g/i-r);
1000
+ goto S120;
1001
+ S100:
1002
+ ix1 = ix+1;
1003
+ for(i=ix1; i<=m; i++) f /= (g/i-r);
1004
+ S120:
1005
+ if(v <= f) goto S170;
1006
+ goto S30;
1007
+ S130:
1008
+ /*
1009
+ SQUEEZING USING UPPER AND LOWER BOUNDS ON ALOG(F(X))
1010
+ */
1011
+ amaxp = k/xnpq*((k*(k/3.0+0.625)+0.1666666666666)/xnpq+0.5);
1012
+ ynorm = -(k*k/(2.0*xnpq));
1013
+ alv = log(v);
1014
+ if(alv < ynorm-amaxp) goto S170;
1015
+ if(alv > ynorm+amaxp) goto S30;
1016
+ /*
1017
+ STIRLING'S FORMULA TO MACHINE ACCURACY FOR
1018
+ THE FINAL ACCEPTANCE/REJECTION TEST
1019
+ */
1020
+ x1 = ix+1.0;
1021
+ f1 = fm+1.0;
1022
+ z = n+1.0-fm;
1023
+ w = n-ix+1.0;
1024
+ z2 = z*z;
1025
+ x2 = x1*x1;
1026
+ f2 = f1*f1;
1027
+ w2 = w*w;
1028
+ if(alv <= xm*log(f1/x1)+(n-m+0.5)*log(z/w)+(ix-m)*log(w*p/(x1*q))+(13860.0-
1029
+ (462.0-(132.0-(99.0-140.0/f2)/f2)/f2)/f2)/f1/166320.0+(13860.0-(462.0-
1030
+ (132.0-(99.0-140.0/z2)/z2)/z2)/z2)/z/166320.0+(13860.0-(462.0-(132.0-
1031
+ (99.0-140.0/x2)/x2)/x2)/x2)/x1/166320.0+(13860.0-(462.0-(132.0-(99.0
1032
+ -140.0/w2)/w2)/w2)/w2)/w/166320.0) goto S170;
1033
+ goto S30;
1034
+ S140:
1035
+ /*
1036
+ INVERSE CDF LOGIC FOR MEAN LESS THAN 30
1037
+ */
1038
+ /* The following change was recommended by Paul B. to get around an
1039
+ error when using gcc under AIX. 2006-09-12. */
1040
+ /** qn = pow(q,(double)n); <- OLD **/
1041
+ qn = exp( (double)n * log(q) );
1042
+ r = p/q;
1043
+ g = r*(n+1);
1044
+ S150:
1045
+ ix = 0;
1046
+ f = qn;
1047
+ u = ranf();
1048
+ S160:
1049
+ if(u < f) goto S170;
1050
+ if(ix > 110) goto S150;
1051
+ u -= f;
1052
+ ix += 1;
1053
+ f *= (g/ix-r);
1054
+ goto S160;
1055
+ S170:
1056
+ if(psave > 0.5) ix = n-ix;
1057
+ ignbin = ix;
1058
+ return ignbin;
1059
+ }
1060
+
1061
+ long ignnbn(long n,double p)
1062
+ /*
1063
+ **********************************************************************
1064
+
1065
+ long ignnbn(long n,double p)
1066
+ GENerate Negative BiNomial random deviate
1067
+ Function
1068
+ Generates a single random deviate from a negative binomial
1069
+ distribution.
1070
+ Arguments
1071
+ N --> The number of trials in the negative binomial distribution
1072
+ from which a random deviate is to be generated.
1073
+ JJV (N > 0)
1074
+ P --> The probability of an event.
1075
+ JJV (0.0 < P < 1.0)
1076
+ Method
1077
+ Algorithm from page 480 of
1078
+
1079
+ Devroye, Luc
1080
+
1081
+ Non-Uniform Random Variate Generation. Springer-Verlag,
1082
+ New York, 1986.
1083
+ **********************************************************************
1084
+ */
1085
+ {
1086
+ static long ignnbn;
1087
+ static double y,a,r;
1088
+ /*
1089
+ ..
1090
+ .. Executable Statements ..
1091
+ */
1092
+ /*
1093
+ Check Arguments
1094
+ */
1095
+ if(n <= 0L) ftnstop("N <= 0 in IGNNBN");
1096
+ if(p <= 0.0F) ftnstop("P <= 0.0 in IGNNBN");
1097
+ if(p >= 1.0F) ftnstop("P >= 1.0 in IGNNBN");
1098
+ /*
1099
+ Generate Y, a random gamma (n,(1-p)/p) variable
1100
+ JJV Note: the above parametrization is consistent with Devroye,
1101
+ JJV but gamma (p/(1-p),n) is the equivalent in our code
1102
+ */
1103
+ r = (double)n;
1104
+ a = p/(1.0F-p);
1105
+ /*
1106
+ * JJV changed this to call SGAMMA directly
1107
+ * y = gengam(a,r); <- OLD
1108
+ */
1109
+ y = sgamma(r)/a;
1110
+ /*
1111
+ Generate a random Poisson(y) variable
1112
+ */
1113
+ ignnbn = ignpoi(y);
1114
+ return ignnbn;
1115
+ }
1116
+
1117
+ long ignpoi(double mu)
1118
+ /*
1119
+ **********************************************************************
1120
+ long ignpoi(double mu)
1121
+ GENerate POIsson random deviate
1122
+ Function
1123
+ Generates a single random deviate from a Poisson
1124
+ distribution with mean MU.
1125
+ Arguments
1126
+ mu --> The mean of the Poisson distribution from which
1127
+ a random deviate is to be generated.
1128
+ (mu >= 0.0)
1129
+ ignpoi <-- The random deviate.
1130
+ Method
1131
+ Renames KPOIS from TOMS as slightly modified by BWB to use RANF
1132
+ instead of SUNIF.
1133
+ For details see:
1134
+ Ahrens, J.H. and Dieter, U.
1135
+ Computer Generation of Poisson Deviates
1136
+ From Modified Normal Distributions.
1137
+ ACM Trans. Math. Software, 8, 2
1138
+ (June 1982),163-179
1139
+ **********************************************************************
1140
+ **********************************************************************
1141
+
1142
+
1143
+ P O I S S O N DISTRIBUTION
1144
+
1145
+
1146
+ **********************************************************************
1147
+ **********************************************************************
1148
+
1149
+ FOR DETAILS SEE:
1150
+
1151
+ AHRENS, J.H. AND DIETER, U.
1152
+ COMPUTER GENERATION OF POISSON DEVIATES
1153
+ FROM MODIFIED NORMAL DISTRIBUTIONS.
1154
+ ACM TRANS. MATH. SOFTWARE, 8,2 (JUNE 1982), 163 - 179.
1155
+
1156
+ (SLIGHTLY MODIFIED VERSION OF THE PROGRAM IN THE ABOVE ARTICLE)
1157
+
1158
+ **********************************************************************
1159
+ INTEGER FUNCTION IGNPOI(IR,MU)
1160
+ INPUT: IR=CURRENT STATE OF BASIC RANDOM NUMBER GENERATOR
1161
+ MU=MEAN MU OF THE POISSON DISTRIBUTION
1162
+ OUTPUT: IGNPOI=SAMPLE FROM THE POISSON-(MU)-DISTRIBUTION
1163
+ MUPREV=PREVIOUS MU, MUOLD=MU AT LAST EXECUTION OF STEP P OR B.
1164
+ TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT
1165
+ COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL
1166
+ SEPARATION OF CASES A AND B
1167
+ */
1168
+ {
1169
+ extern double fsign( double num, double sign );
1170
+ static double a0 = -0.5;
1171
+ static double a1 = 0.3333333343;
1172
+ static double a2 = -0.2499998565;
1173
+ static double a3 = 0.1999997049;
1174
+ static double a4 = -0.1666848753;
1175
+ static double a5 = 0.1428833286;
1176
+ static double a6 = -0.1241963125;
1177
+ static double a7 = 0.1101687109;
1178
+ static double a8 = -0.1142650302;
1179
+ static double a9 = 0.1055093006;
1180
+ /* JJV changed the initial values of MUPREV and MUOLD */
1181
+ static double muold = -1.0E37;
1182
+ static double muprev = -1.0E37;
1183
+ static double fact[10] = {
1184
+ 1.0,1.0,2.0,6.0,24.0,120.0,720.0,5040.0,40320.0,362880.0
1185
+ };
1186
+ /* JJV added ll to the list, for Case A */
1187
+ static long ignpoi,j,k,kflag,l,ll,m;
1188
+ static double b1,b2,c,c0,c1,c2,c3,d,del,difmuk,e,fk,fx,fy,g,omega,p,p0,px,py,q,s,
1189
+ t,u,v,x,xx,pp[35];
1190
+
1191
+ if(mu == muprev) goto S10;
1192
+ if(mu < 10.0) goto S120;
1193
+ /*
1194
+ C A S E A. (RECALCULATION OF S,D,LL IF MU HAS CHANGED)
1195
+ JJV changed l in Case A to ll
1196
+ */
1197
+ muprev = mu;
1198
+ s = sqrt(mu);
1199
+ d = 6.0*mu*mu;
1200
+ /*
1201
+ THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL
1202
+ PROBABILITIES FK WHENEVER K >= M(MU). LL=IFIX(MU-1.1484)
1203
+ IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 .
1204
+ */
1205
+ ll = (long) (mu-1.1484);
1206
+ S10:
1207
+ /*
1208
+ STEP N. NORMAL SAMPLE - SNORM(IR) FOR STANDARD NORMAL DEVIATE
1209
+ */
1210
+ g = mu+s*snorm();
1211
+ if(g < 0.0) goto S20;
1212
+ ignpoi = (long) (g);
1213
+ /*
1214
+ STEP I. IMMEDIATE ACCEPTANCE IF IGNPOI IS LARGE ENOUGH
1215
+ */
1216
+ if(ignpoi >= ll) return ignpoi;
1217
+ /*
1218
+ STEP S. SQUEEZE ACCEPTANCE - SUNIF(IR) FOR (0,1)-SAMPLE U
1219
+ */
1220
+ fk = (double)ignpoi;
1221
+ difmuk = mu-fk;
1222
+ u = ranf();
1223
+ if(d*u >= difmuk*difmuk*difmuk) return ignpoi;
1224
+ S20:
1225
+ /*
1226
+ STEP P. PREPARATIONS FOR STEPS Q AND H.
1227
+ (RECALCULATIONS OF PARAMETERS IF NECESSARY)
1228
+ .3989423=(2*PI)**(-.5) .416667E-1=1./24. .1428571=1./7.
1229
+ THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE
1230
+ APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK.
1231
+ C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION.
1232
+ */
1233
+ if(mu == muold) goto S30;
1234
+ muold = mu;
1235
+ omega = 0.398942280401433/s;
1236
+ b1 = 4.16666666666667E-2/mu;
1237
+ b2 = 0.3*b1*b1;
1238
+ c3 = 0.142857142857143*b1*b2;
1239
+ c2 = b2-15.0*c3;
1240
+ c1 = b1-6.0*b2+45.0*c3;
1241
+ c0 = 1.0-b1+3.0*b2-15.0*c3;
1242
+ c = 0.1069/mu;
1243
+ S30:
1244
+ if(g < 0.0) goto S50;
1245
+ /*
1246
+ 'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)
1247
+ */
1248
+ kflag = 0;
1249
+ goto S70;
1250
+ S40:
1251
+ /*
1252
+ STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)
1253
+ */
1254
+ if(fy-u*fy <= py*exp(px-fx)) return ignpoi;
1255
+ S50:
1256
+ /*
1257
+ STEP E. EXPONENTIAL SAMPLE - SEXPO(IR) FOR STANDARD EXPONENTIAL
1258
+ DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'
1259
+ (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)
1260
+ */
1261
+ e = sexpo();
1262
+ u = ranf();
1263
+ u += (u-1.0);
1264
+ t = 1.8+fsign(e,u);
1265
+ if(t <= -0.6744) goto S50;
1266
+ ignpoi = (long) (mu+s*t);
1267
+ fk = (double)ignpoi;
1268
+ difmuk = mu-fk;
1269
+ /*
1270
+ 'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)
1271
+ */
1272
+ kflag = 1;
1273
+ goto S70;
1274
+ S60:
1275
+ /*
1276
+ STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)
1277
+ */
1278
+ if(c*fabs(u) > py*exp(px+e)-fy*exp(fx+e)) goto S50;
1279
+ return ignpoi;
1280
+ S70:
1281
+ /*
1282
+ STEP F. 'SUBROUTINE' F. CALCULATION OF PX,PY,FX,FY.
1283
+ CASE IGNPOI .LT. 10 USES FACTORIALS FROM TABLE FACT
1284
+ */
1285
+ if(ignpoi >= 10) goto S80;
1286
+ px = -mu;
1287
+ py = pow(mu,(double)ignpoi)/ *(fact+ignpoi);
1288
+ goto S110;
1289
+ S80:
1290
+ /*
1291
+ CASE IGNPOI .GE. 10 USES POLYNOMIAL APPROXIMATION
1292
+ A0-A7 FOR ACCURACY WHEN ADVISABLE
1293
+ .8333333E-1=1./12. .3989423=(2*PI)**(-.5)
1294
+ */
1295
+ del = 8.33333333E-2/fk;
1296
+ del -= (4.8*del*del*del);
1297
+ v = difmuk/fk;
1298
+ if(fabs(v) <= 0.25) goto S90;
1299
+ px = fk*log(1.0+v)-difmuk-del;
1300
+ goto S100;
1301
+ S90:
1302
+ px = fk*v*v*((((((((a8*v+a7)*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0)-del;
1303
+ S100:
1304
+ py = 0.398942280401433/sqrt(fk);
1305
+ S110:
1306
+ x = (0.5-difmuk)/s;
1307
+ xx = x*x;
1308
+ fx = -0.5*xx;
1309
+ fy = omega*(((c3*xx+c2)*xx+c1)*xx+c0);
1310
+ if(kflag <= 0) goto S40;
1311
+ goto S60;
1312
+ S120:
1313
+ /*
1314
+ C A S E B. (START NEW TABLE AND CALCULATE P0 IF NECESSARY)
1315
+ JJV changed MUPREV assignment to initial value
1316
+ */
1317
+ muprev = -1.0E37;
1318
+ if(mu == muold) goto S130;
1319
+ /* JJV added argument checker here */
1320
+ if(mu >= 0.0) goto S125;
1321
+ fprintf(stderr,"MU < 0 in IGNPOI: MU %16.6E\n",mu);
1322
+ fputs("Abort\n",stderr);
1323
+ exit(1);
1324
+ S125:
1325
+ muold = mu;
1326
+ m = max(1L,(long) (mu));
1327
+ l = 0;
1328
+ p = exp(-mu);
1329
+ q = p0 = p;
1330
+ S130:
1331
+ /*
1332
+ STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
1333
+ */
1334
+ u = ranf();
1335
+ ignpoi = 0;
1336
+ if(u <= p0) return ignpoi;
1337
+ /*
1338
+ STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE
1339
+ PP-TABLE OF CUMULATIVE POISSON PROBABILITIES
1340
+ (0.458=PP(9) FOR MU=10)
1341
+ */
1342
+ if(l == 0) goto S150;
1343
+ j = 1;
1344
+ if(u > 0.458) j = min(l,m);
1345
+ for(k=j; k<=l; k++) {
1346
+ if(u <= *(pp+k-1)) goto S180;
1347
+ }
1348
+ if(l == 35) goto S130;
1349
+ S150:
1350
+ /*
1351
+ STEP C. CREATION OF NEW POISSON PROBABILITIES P
1352
+ AND THEIR CUMULATIVES Q=PP(K)
1353
+ */
1354
+ l += 1;
1355
+ for(k=l; k<=35; k++) {
1356
+ p = p*mu/(double)k;
1357
+ q += p;
1358
+ *(pp+k-1) = q;
1359
+ if(u <= q) goto S170;
1360
+ }
1361
+ l = 35;
1362
+ goto S130;
1363
+ S170:
1364
+ l = k;
1365
+ S180:
1366
+ ignpoi = k;
1367
+ return ignpoi;
1368
+ }
1369
+
1370
+ long ignuin(long low,long high)
1371
+ /*
1372
+ **********************************************************************
1373
+ long ignuin(long low,long high)
1374
+ GeNerate Uniform INteger
1375
+ Function
1376
+ Generates an integer uniformly distributed between LOW and HIGH.
1377
+ Arguments
1378
+ low --> Low bound (inclusive) on integer value to be generated
1379
+ high --> High bound (inclusive) on integer value to be generated
1380
+ Note
1381
+ If (HIGH-LOW) > 2,147,483,561 prints error message on * unit and
1382
+ stops the program.
1383
+ **********************************************************************
1384
+ IGNLGI generates integers between 1 and 2147483562
1385
+ MAXNUM is 1 less than maximum generable value
1386
+ */
1387
+ {
1388
+ #define maxnum 2147483561L
1389
+ static long ignuin,ign,maxnow,range,ranp1;
1390
+
1391
+ if(!(low > high)) goto S10;
1392
+ fputs(" low > high in ignuin - ABORT\n",stderr);
1393
+ exit(1);
1394
+
1395
+ S10:
1396
+ range = high-low;
1397
+ if(!(range > maxnum)) goto S20;
1398
+ fputs(" high - low too large in ignuin - ABORT\n",stderr);
1399
+ exit(1);
1400
+
1401
+ S20:
1402
+ if(!(low == high)) goto S30;
1403
+ ignuin = low;
1404
+ return ignuin;
1405
+
1406
+ S30:
1407
+ /*
1408
+ Number to be generated should be in range 0..RANGE
1409
+ Set MAXNOW so that the number of integers in 0..MAXNOW is an
1410
+ integral multiple of the number in 0..RANGE
1411
+ */
1412
+ ranp1 = range+1;
1413
+ maxnow = maxnum/ranp1*ranp1;
1414
+ S40:
1415
+ ign = ignlgi()-1;
1416
+ if(!(ign <= maxnow)) goto S40;
1417
+ ignuin = low+ign%ranp1;
1418
+ return ignuin;
1419
+ #undef maxnum
1420
+ #undef err1
1421
+ #undef err2
1422
+ }
1423
+
1424
+ long lennob( char *str )
1425
+ /*
1426
+ Returns the length of str ignoring trailing blanks but not
1427
+ other white space.
1428
+ */
1429
+ {
1430
+ long i, i_nb;
1431
+
1432
+ for (i=0, i_nb= -1L; *(str+i); i++)
1433
+ if ( *(str+i) != ' ' ) i_nb = i;
1434
+ return (i_nb+1);
1435
+ }
1436
+
1437
+ long mltmod(long a,long s,long m)
1438
+ /*
1439
+ **********************************************************************
1440
+ long mltmod(long a,long s,long m)
1441
+ Returns (A*S) MOD M
1442
+ This is a transcription from Pascal to C of routine
1443
+ MultMod_Decompos from the paper
1444
+ L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
1445
+ with Splitting Facilities." ACM Transactions on Mathematical
1446
+ Software, 17:98-111 (1991)
1447
+ Arguments
1448
+ a, s, m -->
1449
+ WGR, 12/19/00: replaced S10, S20, etc. with C blocks {} per
1450
+ original paper.
1451
+ **********************************************************************
1452
+ */
1453
+ {
1454
+ #define h 32768L
1455
+ static long a0,a1,k,p,q,qh,rh;
1456
+ /*
1457
+ H = 2**((b-2)/2) where b = 32 because we are using a 32 bit
1458
+ machine. On a different machine recompute H.
1459
+ */
1460
+ if (a <= 0 || a >= m || s <= 0 || s >= m) {
1461
+ fputs(" a, m, s out of order in mltmod - ABORT!\n",stderr);
1462
+ fprintf(stderr," a = %12ld s = %12ld m = %12ld\n",a,s,m);
1463
+ fputs(" mltmod requires: 0 < a < m; 0 < s < m\n",stderr);
1464
+ exit(1);
1465
+ }
1466
+
1467
+ if (a < h) {
1468
+ a0 = a;
1469
+ p = 0;
1470
+ } else {
1471
+ a1 = a/h;
1472
+ a0 = a - h*a1;
1473
+ qh = m/h;
1474
+ rh = m - h*qh;
1475
+ if (a1 >= h) { /* A2=1 */
1476
+ a1 -= h;
1477
+ k = s/qh;
1478
+ p = h*(s-k*qh) - k*rh;
1479
+ while (p < 0) { p += m; }
1480
+ } else {
1481
+ p = 0;
1482
+ }
1483
+ /*
1484
+ P = (A2*S*H)MOD M
1485
+ */
1486
+ if (a1 != 0) {
1487
+ q = m/a1;
1488
+ k = s/q;
1489
+ p -= k*(m - a1*q);
1490
+ if (p > 0) { p -= m; }
1491
+ p += a1*(s - k*q);
1492
+ while (p < 0) { p += m; }
1493
+ }
1494
+ /*
1495
+ P = ((A2*H + A1)*S)MOD M
1496
+ */
1497
+ k = p/qh;
1498
+ p = h*(p-k*qh) - k*rh;
1499
+ while (p < 0) { p += m; }
1500
+ }
1501
+ /*
1502
+ P = ((A2*H + A1)*H*S)MOD M
1503
+ */
1504
+ if (a0 != 0) {
1505
+ q = m/a0;
1506
+ k = s/q;
1507
+ p -= k*(m-a0*q);
1508
+ if (p > 0) { p -= m; }
1509
+ p += a0*(s-k*q);
1510
+ while (p < 0) { p += m; }
1511
+ }
1512
+ return p;
1513
+ #undef h
1514
+ }
1515
+
1516
+ void phrtsd(char* phrase,long *seed1,long *seed2)
1517
+ /*
1518
+ **********************************************************************
1519
+ void phrtsd(char* phrase,long *seed1,long *seed2)
1520
+ PHRase To SeeDs
1521
+
1522
+ Function
1523
+
1524
+ Uses a phrase (character string) to generate two seeds for the RGN
1525
+ random number generator.
1526
+ Arguments
1527
+ phrase --> Phrase to be used for random number generation
1528
+
1529
+ seed1 <-- First seed for generator
1530
+
1531
+ seed2 <-- Second seed for generator
1532
+
1533
+ Note
1534
+
1535
+ Trailing blanks are eliminated before the seeds are generated.
1536
+ Generated seed values will fall in the range 1..2^30
1537
+ (1..1,073,741,824)
1538
+ **********************************************************************
1539
+ */
1540
+ {
1541
+
1542
+ static char table[] =
1543
+ "abcdefghijklmnopqrstuvwxyz\
1544
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ\
1545
+ 0123456789\
1546
+ !@#$%^&*()_+[];:'\\\"<>?,./ "; /* WGR added space, 5/19/1999 */
1547
+
1548
+ long ix;
1549
+
1550
+ static long twop30 = 1073741824L;
1551
+ static long shift[5] = {
1552
+ 1L,64L,4096L,262144L,16777216L
1553
+ };
1554
+
1555
+ #ifdef PHRTSD_ORIG
1556
+ /*----------------------------- Original phrtsd */
1557
+ static long i,ichr,j,lphr,values[5];
1558
+ extern long lennob(char *str);
1559
+
1560
+ *seed1 = 1234567890L;
1561
+ *seed2 = 123456789L;
1562
+ lphr = lennob(phrase);
1563
+ if(lphr < 1) return;
1564
+ for(i=0; i<=(lphr-1); i++) {
1565
+ for (ix=0; table[ix]; ix++) if (*(phrase+i) == table[ix]) break;
1566
+ /* JJV added ix++; to bring index in line with fortran's index*/
1567
+ ix++;
1568
+ if (!table[ix]) ix = 0;
1569
+ ichr = ix % 64;
1570
+ if(ichr == 0) ichr = 63;
1571
+ for(j=1; j<=5; j++) {
1572
+ *(values+j-1) = ichr-j;
1573
+ if(*(values+j-1) < 1) *(values+j-1) += 63;
1574
+ }
1575
+ for(j=1; j<=5; j++) {
1576
+ *seed1 = ( *seed1+*(shift+j-1)**(values+j-1) ) % twop30;
1577
+ *seed2 = ( *seed2+*(shift+j-1)**(values+6-j-1) ) % twop30;
1578
+ }
1579
+ }
1580
+ #else
1581
+ /*----------------------------- New phrtsd */
1582
+ static long i,j, ichr,lphr;
1583
+ static long values[8] = { 8521739, 5266711, 3254959, 2011673,
1584
+ 1243273, 768389, 474899, 293507 };
1585
+ extern long lennob(char *str);
1586
+
1587
+ *seed1 = 1234567890L;
1588
+ *seed2 = 123456789L;
1589
+ lphr = lennob(phrase);
1590
+ if(lphr < 1) return;
1591
+ for(i=0; i<(lphr-1); i++) {
1592
+ ichr = phrase[i];
1593
+ j = i % 8;
1594
+ *seed1 = ( *seed1 + (values[j] * ichr) ) % twop30;
1595
+ *seed2 = ( *seed2 + (values[7-j] * ichr) ) % twop30;
1596
+ }
1597
+ #endif
1598
+ }
1599
+
1600
+ double ranf(void)
1601
+ /*
1602
+ **********************************************************************
1603
+ double ranf(void)
1604
+ RANDom number generator as a Function
1605
+ Returns a random floating point number from a uniform distribution
1606
+ over 0 - 1 (endpoints of this interval are not returned) using the
1607
+ current generator.
1608
+ This is a transcription from Pascal to C of routine
1609
+ Uniform_01 from the paper
1610
+ L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
1611
+ with Splitting Facilities." ACM Transactions on Mathematical
1612
+ Software, 17:98-111 (1991)
1613
+ WGR, 2/12/01: increased precision.
1614
+ **********************************************************************
1615
+ */
1616
+ {
1617
+ static double ranf;
1618
+ /*
1619
+ 4.656613057E-10 is 1/M1 M1 is set in a data statement in IGNLGI
1620
+ and is currently 2147483563. If M1 changes, change this also.
1621
+ */
1622
+ ranf = ignlgi()*4.65661305739177E-10;
1623
+ return ranf;
1624
+ }
1625
+
1626
+ void setgmn(double *meanv,double *covm,long p,double *parm)
1627
+ /*
1628
+ **********************************************************************
1629
+ void setgmn(double *meanv,double *covm,long p,double *parm)
1630
+ SET Generate Multivariate Normal random deviate
1631
+ Function
1632
+ Places P, MEANV, and the Cholesky factorization of COVM
1633
+ in GENMN.
1634
+ Arguments
1635
+ meanv --> Mean vector of multivariate normal distribution.
1636
+ covm <--> (Input) Covariance matrix of the multivariate
1637
+ normal distribution
1638
+ (Output) Destroyed on output
1639
+ p --> Dimension of the normal, or length of MEANV.
1640
+ parm <-- Array of parameters needed to generate multivariate norma
1641
+ deviates (P, MEANV and Cholesky decomposition of
1642
+ COVM).
1643
+ 1 : 1 - P
1644
+ 2 : P + 1 - MEANV
1645
+ P+2 : P*(P+3)/2 + 1 - Cholesky decomposition of COVM
1646
+ Needed dimension is (p*(p+3)/2 + 1)
1647
+ **********************************************************************
1648
+ */
1649
+ {
1650
+ extern void spofa(double *a,long lda,long n,long *info);
1651
+ static long T1;
1652
+ static long i,icount,info,j,D2,D3,D4,D5;
1653
+ T1 = p*(p+3)/2+1;
1654
+ /*
1655
+ TEST THE INPUT
1656
+ */
1657
+ if(!(p <= 0)) goto S10;
1658
+ fputs("P nonpositive in SETGMN\n",stderr);
1659
+ fprintf(stderr,"Value of P: %12ld\n",p);
1660
+ exit(1);
1661
+ S10:
1662
+ *parm = p;
1663
+ /*
1664
+ PUT P AND MEANV INTO PARM
1665
+ */
1666
+ for(i=2,D2=1,D3=(p+1-i+D2)/D2; D3>0; D3--,i+=D2) *(parm+i-1) = *(meanv+i-2);
1667
+ /*
1668
+ Cholesky decomposition to find A s.t. trans(A)*(A) = COVM
1669
+ */
1670
+ spofa(covm,p,p,&info);
1671
+ if(!(info != 0)) goto S30;
1672
+ fputs(" COVM not positive definite in SETGMN\n",stderr);
1673
+ exit(1);
1674
+ S30:
1675
+ icount = p+1;
1676
+ /*
1677
+ PUT UPPER HALF OF A, WHICH IS NOW THE CHOLESKY FACTOR, INTO PARM
1678
+ COVM(1,1) = PARM(P+2)
1679
+ COVM(1,2) = PARM(P+3)
1680
+ :
1681
+ COVM(1,P) = PARM(2P+1)
1682
+ COVM(2,2) = PARM(2P+2) ...
1683
+ */
1684
+ for(i=1,D4=1,D5=(p-i+D4)/D4; D5>0; D5--,i+=D4) {
1685
+ for(j=i-1; j<p; j++) {
1686
+ icount += 1;
1687
+ *(parm+icount-1) = *(covm+i-1+j*p);
1688
+ }
1689
+ }
1690
+ }
1691
+
1692
+ double sexpo(void)
1693
+ /*
1694
+ **********************************************************************
1695
+
1696
+
1697
+ (STANDARD-) E X P O N E N T I A L DISTRIBUTION
1698
+
1699
+
1700
+ **********************************************************************
1701
+ **********************************************************************
1702
+
1703
+ FOR DETAILS SEE:
1704
+
1705
+ AHRENS, J.H. AND DIETER, U.
1706
+ COMPUTER METHODS FOR SAMPLING FROM THE
1707
+ EXPONENTIAL AND NORMAL DISTRIBUTIONS.
1708
+ COMM. ACM, 15,10 (OCT. 1972), 873 - 882.
1709
+
1710
+ ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM
1711
+ 'SA' IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)
1712
+
1713
+ Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
1714
+ SUNIF. The argument IR thus goes away.
1715
+
1716
+ **********************************************************************
1717
+ Q(N) = SUM(ALOG(2.0)**K/K!) K=1,..,N , THE HIGHEST N
1718
+ (HERE 8) IS DETERMINED BY Q(N)=1.0 WITHIN STANDARD PRECISION
1719
+ */
1720
+ {
1721
+ static double q[8] = {
1722
+ 0.69314718055995, 0.93337368751905, 0.98887779618387, 0.99849592529150,
1723
+ 0.99982928110614, 0.99998331641007, 0.99999856914388, 0.99999989069256
1724
+ };
1725
+ static long i;
1726
+ static double sexpo,a,u,ustar,umin;
1727
+ static double *q1 = q;
1728
+ a = 0.0;
1729
+ u = ranf();
1730
+ goto S30;
1731
+ S20:
1732
+ a += *q1;
1733
+ S30:
1734
+ u += u;
1735
+ /*
1736
+ * JJV changed the following to reflect the true algorithm and prevent
1737
+ * JJV unpredictable behavior if U is initially 0.5.
1738
+ * if(u <= 1.0) goto S20;
1739
+ */
1740
+ if(u < 1.0) goto S20;
1741
+ u -= 1.0;
1742
+ if(u > *q1) goto S60;
1743
+ sexpo = a+u;
1744
+ return sexpo;
1745
+ S60:
1746
+ i = 1;
1747
+ ustar = ranf();
1748
+ umin = ustar;
1749
+ S70:
1750
+ ustar = ranf();
1751
+ if(ustar < umin) umin = ustar;
1752
+ i += 1;
1753
+ if(u > *(q+i-1)) goto S70;
1754
+ sexpo = a+umin**q1;
1755
+ return sexpo;
1756
+ }
1757
+
1758
+ double sgamma(double a)
1759
+ /*
1760
+ **********************************************************************
1761
+
1762
+
1763
+ (STANDARD-) G A M M A DISTRIBUTION
1764
+
1765
+
1766
+ **********************************************************************
1767
+ **********************************************************************
1768
+
1769
+ PARAMETER A >= 1.0 !
1770
+
1771
+ **********************************************************************
1772
+
1773
+ FOR DETAILS SEE:
1774
+
1775
+ AHRENS, J.H. AND DIETER, U.
1776
+ GENERATING GAMMA VARIATES BY A
1777
+ MODIFIED REJECTION TECHNIQUE.
1778
+ COMM. ACM, 25,1 (JAN. 1982), 47 - 54.
1779
+
1780
+ STEP NUMBERS CORRESPOND TO ALGORITHM 'GD' IN THE ABOVE PAPER
1781
+ (STRAIGHTFORWARD IMPLEMENTATION)
1782
+
1783
+ Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
1784
+ SUNIF. The argument IR thus goes away.
1785
+
1786
+ **********************************************************************
1787
+
1788
+ PARAMETER 0.0 < A < 1.0 !
1789
+
1790
+ **********************************************************************
1791
+
1792
+ FOR DETAILS SEE:
1793
+
1794
+ AHRENS, J.H. AND DIETER, U.
1795
+ COMPUTER METHODS FOR SAMPLING FROM GAMMA,
1796
+ BETA, POISSON AND BINOMIAL DISTRIBUTIONS.
1797
+ COMPUTING, 12 (1974), 223 - 246.
1798
+
1799
+ (ADAPTED IMPLEMENTATION OF ALGORITHM 'GS' IN THE ABOVE PAPER)
1800
+
1801
+ **********************************************************************
1802
+ INPUT: A =PARAMETER (MEAN) OF THE STANDARD GAMMA DISTRIBUTION
1803
+ OUTPUT: SGAMMA = SAMPLE FROM THE GAMMA-(A)-DISTRIBUTION
1804
+ COEFFICIENTS Q(K) - FOR Q0 = SUM(Q(K)*A**(-K))
1805
+ COEFFICIENTS A(K) - FOR Q = Q0+(T*T/2)*SUM(A(K)*V**K)
1806
+ COEFFICIENTS E(K) - FOR EXP(Q)-1 = SUM(E(K)*Q**K)
1807
+ PREVIOUS A PRE-SET TO ZERO - AA IS A', AAA IS A"
1808
+ SQRT32 IS THE SQUAREROOT OF 32 = 5.656854249492380
1809
+ */
1810
+ {
1811
+ extern double fsign( double num, double sign );
1812
+ static double q1 = 4.16666664E-2;
1813
+ static double q2 = 2.08333723E-2;
1814
+ static double q3 = 7.9849875E-3;
1815
+ static double q4 = 1.5746717E-3;
1816
+ static double q5 = -3.349403E-4;
1817
+ static double q6 = 3.340332E-4;
1818
+ static double q7 = 6.053049E-4;
1819
+ static double q8 = -4.701849E-4;
1820
+ static double q9 = 1.710320E-4;
1821
+ static double a1 = 0.333333333;
1822
+ static double a2 = -0.249999949;
1823
+ static double a3 = 0.199999867;
1824
+ static double a4 = -0.166677482;
1825
+ static double a5 = 0.142873973;
1826
+ static double a6 = -0.124385581;
1827
+ static double a7 = 0.110368310;
1828
+ static double a8 = -0.112750886;
1829
+ static double a9 = 0.104089866;
1830
+ static double e1 = 1.0;
1831
+ static double e2 = 0.499999994;
1832
+ static double e3 = 0.166666848;
1833
+ static double e4 = 4.1664508E-2;
1834
+ static double e5 = 8.345522E-3;
1835
+ static double e6 = 1.353826E-3;
1836
+ static double e7 = 2.47453E-4;
1837
+ static double aa = 0.0;
1838
+ static double aaa = 0.0;
1839
+ static double sqrt32 = 5.65685424949238;
1840
+ /* JJV added b0 to fix rare and subtle bug */
1841
+ static double sgamma,s2,s,d,t,x,u,r,q0,b,b0,si,c,v,q,e,w,p;
1842
+ if(a == aa) goto S10;
1843
+ if(a < 1.0) goto S120;
1844
+ /*
1845
+ STEP 1: RECALCULATIONS OF S2,S,D IF A HAS CHANGED
1846
+ */
1847
+ aa = a;
1848
+ s2 = a-0.5;
1849
+ s = sqrt(s2);
1850
+ d = sqrt32-12.0*s;
1851
+ S10:
1852
+ /*
1853
+ STEP 2: T=STANDARD NORMAL DEVIATE,
1854
+ X=(S,1/2)-NORMAL DEVIATE.
1855
+ IMMEDIATE ACCEPTANCE (I)
1856
+ */
1857
+ t = snorm();
1858
+ x = s+0.5*t;
1859
+ sgamma = x*x;
1860
+ if(t >= 0.0) return sgamma;
1861
+ /*
1862
+ STEP 3: U= 0,1 -UNIFORM SAMPLE. SQUEEZE ACCEPTANCE (S)
1863
+ */
1864
+ u = ranf();
1865
+ if(d*u <= t*t*t) return sgamma;
1866
+ /*
1867
+ STEP 4: RECALCULATIONS OF Q0,B,SI,C IF NECESSARY
1868
+ */
1869
+ if(a == aaa) goto S40;
1870
+ aaa = a;
1871
+ r = 1.0/a;
1872
+ q0 = ((((((((q9*r+q8)*r+q7)*r+q6)*r+q5)*r+q4)*r+q3)*r+q2)*r+q1)*r;
1873
+ /*
1874
+ APPROXIMATION DEPENDING ON SIZE OF PARAMETER A
1875
+ THE CONSTANTS IN THE EXPRESSIONS FOR B, SI AND
1876
+ C WERE ESTABLISHED BY NUMERICAL EXPERIMENTS
1877
+ */
1878
+ if(a <= 3.686) goto S30;
1879
+ if(a <= 13.022) goto S20;
1880
+ /*
1881
+ CASE 3: A .GT. 13.022
1882
+ */
1883
+ b = 1.77;
1884
+ si = 0.75;
1885
+ c = 0.1515/s;
1886
+ goto S40;
1887
+ S20:
1888
+ /*
1889
+ CASE 2: 3.686 .LT. A .LE. 13.022
1890
+ */
1891
+ b = 1.654+7.6E-3*s2;
1892
+ si = 1.68/s+0.275;
1893
+ c = 6.2E-2/s+2.4E-2;
1894
+ goto S40;
1895
+ S30:
1896
+ /*
1897
+ CASE 1: A .LE. 3.686
1898
+ */
1899
+ b = 0.463+s+0.178*s2;
1900
+ si = 1.235;
1901
+ c = 0.195/s-7.9E-2+1.6E-1*s;
1902
+ S40:
1903
+ /*
1904
+ STEP 5: NO QUOTIENT TEST IF X NOT POSITIVE
1905
+ */
1906
+ if(x <= 0.0) goto S70;
1907
+ /*
1908
+ STEP 6: CALCULATION OF V AND QUOTIENT Q
1909
+ */
1910
+ v = t/(s+s);
1911
+ if(fabs(v) <= 0.25) goto S50;
1912
+ q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
1913
+ goto S60;
1914
+ S50:
1915
+ q = q0+0.5*t*t*((((((((a9*v+a8)*v+a7)*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
1916
+ S60:
1917
+ /*
1918
+ STEP 7: QUOTIENT ACCEPTANCE (Q)
1919
+ */
1920
+ if(log(1.0-u) <= q) return sgamma;
1921
+ S70:
1922
+ /*
1923
+ STEP 8: E=STANDARD EXPONENTIAL DEVIATE
1924
+ U= 0,1 -UNIFORM DEVIATE
1925
+ T=(B,SI)-DOUBLE EXPONENTIAL (LAPLACE) SAMPLE
1926
+ */
1927
+ e = sexpo();
1928
+ u = ranf();
1929
+ u += (u-1.0);
1930
+ t = b+fsign(si*e,u);
1931
+ /*
1932
+ STEP 9: REJECTION IF T .LT. TAU(1) = -.71874483771719
1933
+ */
1934
+ if(t < -0.71874483771719) goto S70;
1935
+ /*
1936
+ STEP 10: CALCULATION OF V AND QUOTIENT Q
1937
+ */
1938
+ v = t/(s+s);
1939
+ if(fabs(v) <= 0.25) goto S80;
1940
+ q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
1941
+ goto S90;
1942
+ S80:
1943
+ q = q0+0.5*t*t*((((((((a9*v+a8)*v+a7)*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
1944
+ S90:
1945
+ /*
1946
+ STEP 11: HAT ACCEPTANCE (H) (IF Q NOT POSITIVE GO TO STEP 8)
1947
+ */
1948
+ if(q <= 0.0) goto S70;
1949
+ if(q <= 0.5) goto S100;
1950
+ /*
1951
+ * JJV modified the code through line 115 to handle large Q case
1952
+ */
1953
+ if(q < 15.0) goto S95;
1954
+ /*
1955
+ * JJV Here Q is large enough that Q = log(exp(Q) - 1.0) (for real Q)
1956
+ * JJV so reformulate test at 110 in terms of one EXP, if not too big
1957
+ * JJV 87.49823 is close to the largest real which can be
1958
+ * JJV exponentiated (87.49823 = log(1.0E38))
1959
+ */
1960
+ if((q+e-0.5*t*t) > 87.4982335337737) goto S115;
1961
+ if(c*fabs(u) > exp(q+e-0.5*t*t)) goto S70;
1962
+ goto S115;
1963
+ S95:
1964
+ w = exp(q)-1.0;
1965
+ goto S110;
1966
+ S100:
1967
+ w = ((((((e7*q+e6)*q+e5)*q+e4)*q+e3)*q+e2)*q+e1)*q;
1968
+ S110:
1969
+ /*
1970
+ IF T IS REJECTED, SAMPLE AGAIN AT STEP 8
1971
+ */
1972
+ if(c*fabs(u) > w*exp(e-0.5*t*t)) goto S70;
1973
+ S115:
1974
+ x = s+0.5*t;
1975
+ sgamma = x*x;
1976
+ return sgamma;
1977
+ S120:
1978
+ /*
1979
+ ALTERNATE METHOD FOR PARAMETERS A BELOW 1 (.3678794=EXP(-1.))
1980
+
1981
+ JJV changed B to B0 (which was added to declarations for this)
1982
+ JJV in 120 to END to fix rare and subtle bug.
1983
+ JJV Line: 'aa = 0.0' was removed (unnecessary, wasteful).
1984
+ JJV Reasons: the state of AA only serves to tell the A >= 1.0
1985
+ JJV case if certain A-dependent constants need to be recalculated.
1986
+ JJV The A < 1.0 case (here) no longer changes any of these, and
1987
+ JJV the recalculation of B (which used to change with an
1988
+ JJV A < 1.0 call) is governed by the state of AAA anyway.
1989
+ aa = 0.0;
1990
+ */
1991
+ b0 = 1.0+ 0.3678794411714423*a;
1992
+ S130:
1993
+ p = b0*ranf();
1994
+ if(p >= 1.0) goto S140;
1995
+ sgamma = exp(log(p)/ a);
1996
+ if(sexpo() < sgamma) goto S130;
1997
+ return sgamma;
1998
+ S140:
1999
+ sgamma = -log((b0-p)/ a);
2000
+ if(sexpo() < (1.0-a)*log(sgamma)) goto S130;
2001
+ return sgamma;
2002
+ }
2003
+
2004
+ double snorm(void)
2005
+ /*
2006
+ **********************************************************************
2007
+
2008
+
2009
+ (STANDARD-) N O R M A L DISTRIBUTION
2010
+
2011
+
2012
+ **********************************************************************
2013
+ **********************************************************************
2014
+
2015
+ FOR DETAILS SEE:
2016
+
2017
+ AHRENS, J.H. AND DIETER, U.
2018
+ EXTENSIONS OF FORSYTHE'S METHOD FOR RANDOM
2019
+ SAMPLING FROM THE NORMAL DISTRIBUTION.
2020
+ MATH. COMPUT., 27,124 (OCT. 1973), 927 - 937.
2021
+
2022
+ ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM 'FL'
2023
+ (M=5) IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)
2024
+
2025
+ Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
2026
+ SUNIF. The argument IR thus goes away.
2027
+
2028
+ **********************************************************************
2029
+ THE DEFINITIONS OF THE CONSTANTS A(K), D(K), T(K) AND
2030
+ H(K) ARE ACCORDING TO THE ABOVEMENTIONED ARTICLE
2031
+ */
2032
+ {
2033
+ static double a[32] = {
2034
+ 0.0, 0.03917608550309, 0.07841241273311, 0.11776987457909,
2035
+ 0.15731068461017, 0.19709908429430, 0.23720210932878, 0.27769043982157,
2036
+ 0.31863936396437, 0.36012989178957, 0.40225006532172, 0.44509652498551,
2037
+ 0.48877641111466, 0.53340970624127, 0.57913216225555, 0.62609901234641,
2038
+ 0.67448975019607, 0.72451438349236, 0.77642176114792, 0.83051087820539,
2039
+ 0.88714655901887, 0.94678175630104, 1.00999016924958, 1.07751556704027,
2040
+ 1.15034938037600, 1.22985875921658, 1.31801089730353, 1.41779713799625,
2041
+ 1.53412054435253, 1.67593972277344, 1.86273186742164, 2.15387469406144
2042
+ };
2043
+ static double d[31] = {
2044
+ 0.0, 0.0, 0.0, 0.0,
2045
+ 0.0, 0.26368432217502, 0.24250845238097, 0.22556744380930,
2046
+ 0.21163416577204, 0.19992426749317, 0.18991075842246, 0.18122518100691,
2047
+ 0.17360140038056, 0.16684190866667, 0.16079672918053, 0.15534971747692,
2048
+ 0.15040938382813, 0.14590257684509, 0.14177003276856, 0.13796317369537,
2049
+ 0.13444176150074, 0.13117215026483, 0.12812596512583, 0.12527909006226,
2050
+ 0.12261088288608, 0.12010355965651, 0.11774170701949, 0.11551189226063,
2051
+ 0.11340234879117, 0.11140272044119, 0.10950385201710
2052
+ };
2053
+ static double t[31] = {
2054
+ 7.6738283767E-4, 2.30687039764E-3, 3.86061844387E-3, 5.43845406707E-3,
2055
+ 7.05069876857E-3, 8.70839582019E-3, 1.042356984914E-2, 1.220953194966E-2,
2056
+ 1.408124734637E-2, 1.605578804548E-2, 1.815290075142E-2, 2.039573175398E-2,
2057
+ 2.281176732513E-2, 2.543407332319E-2, 2.830295595118E-2, 3.146822492920E-2,
2058
+ 3.499233438388E-2, 3.895482964836E-2, 4.345878381672E-2, 4.864034918076E-2,
2059
+ 5.468333844273E-2, 6.184222395816E-2, 7.047982761667E-2, 8.113194985866E-2,
2060
+ 9.462443534514E-2, 0.11230007889456, 0.13649799954975, 0.17168856004707,
2061
+ 0.22762405488269, 0.33049802776911, 0.58470309390507
2062
+ };
2063
+ static double h[31] = {
2064
+ 3.920617164634E-2, 3.932704963665E-2, 3.950999486086E-2, 3.975702679515E-2,
2065
+ 4.007092772490E-2, 4.045532602655E-2, 4.091480886081E-2, 4.145507115859E-2,
2066
+ 4.208311051344E-2, 4.280748137995E-2, 4.363862733472E-2, 4.458931789605E-2,
2067
+ 4.567522779560E-2, 4.691571371696E-2, 4.833486978119E-2, 4.996298427702E-2,
2068
+ 5.183858644724E-2, 5.401138183398E-2, 5.654656186515E-2, 5.953130423884E-2,
2069
+ 6.308488965373E-2, 6.737503494905E-2, 7.264543556657E-2, 7.926471414968E-2,
2070
+ 8.781922325338E-2, 9.930398323927E-2, 0.11555994154118, 0.14043438342816,
2071
+ 0.18361418337460, 0.27900163464163, 0.70104742502766
2072
+ };
2073
+ static long i;
2074
+ static double snorm,u,s,ustar,aa,w,y,tt;
2075
+ u = ranf();
2076
+ s = 0.0;
2077
+ if(u > 0.5) s = 1.0;
2078
+ u += (u-s);
2079
+ u = 32.0*u;
2080
+ i = (long) (u);
2081
+ if(i == 32) i = 31;
2082
+ if(i == 0) goto S100;
2083
+ /*
2084
+ START CENTER
2085
+ */
2086
+ ustar = u-(double)i;
2087
+ aa = *(a+i-1);
2088
+ S40:
2089
+ if(ustar <= *(t+i-1)) goto S60;
2090
+ w = (ustar-*(t+i-1))**(h+i-1);
2091
+ S50:
2092
+ /*
2093
+ EXIT (BOTH CASES)
2094
+ */
2095
+ y = aa+w;
2096
+ snorm = y;
2097
+ if(s == 1.0) snorm = -y;
2098
+ return snorm;
2099
+ S60:
2100
+ /*
2101
+ CENTER CONTINUED
2102
+ */
2103
+ u = ranf();
2104
+ w = u*(*(a+i)-aa);
2105
+ tt = (0.5*w+aa)*w;
2106
+ goto S80;
2107
+ S70:
2108
+ tt = u;
2109
+ ustar = ranf();
2110
+ S80:
2111
+ if(ustar > tt) goto S50;
2112
+ u = ranf();
2113
+ if(ustar >= u) goto S70;
2114
+ ustar = ranf();
2115
+ goto S40;
2116
+ S100:
2117
+ /*
2118
+ START TAIL
2119
+ */
2120
+ i = 6;
2121
+ aa = *(a+31);
2122
+ goto S120;
2123
+ S110:
2124
+ aa += *(d+i-1);
2125
+ i += 1;
2126
+ S120:
2127
+ u += u;
2128
+ if(u < 1.0) goto S110;
2129
+ u -= 1.0;
2130
+ S140:
2131
+ w = u**(d+i-1);
2132
+ tt = (0.5*w+aa)*w;
2133
+ goto S160;
2134
+ S150:
2135
+ tt = u;
2136
+ S160:
2137
+ ustar = ranf();
2138
+ if(ustar > tt) goto S50;
2139
+ u = ranf();
2140
+ if(ustar >= u) goto S150;
2141
+ u = ranf();
2142
+ goto S140;
2143
+ }
2144
+
2145
+ double fsign( double num, double sign )
2146
+ /* Transfers sign of argument sign to argument num */
2147
+ {
2148
+ if ( ( sign>0.0f && num<0.0f ) || ( sign<0.0f && num>0.0f ) )
2149
+ return -num;
2150
+ else return num;
2151
+ }
2152
+
2153
+ /************************************************************************
2154
+ FTNSTOP:
2155
+ Prints msg to standard error and then exits
2156
+ ************************************************************************/
2157
+ void ftnstop(const char* msg)
2158
+ /* msg - error message */
2159
+ {
2160
+ if (msg != NULL) fprintf(stderr,"%s\n",msg);
2161
+ exit(0);
2162
+ }