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/com.c +373 -0
- data/lib/ext/extconf.rb +7 -0
- data/lib/ext/linpack.c +91 -0
- data/lib/ext/randlib.c +2162 -0
- data/lib/ext/randlib.h +38 -0
- data/lib/ext/random_variable.c +414 -0
- data/lib/ext/xrandlib.c +28 -0
- data/lib/ext/xrandlib.h +22 -0
- data/lib/random_variable.rb +76 -0
- data/lib/test/test_poisson_rv.rb +33 -0
- data/lib/test.rb +8 -0
- metadata +57 -0
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
|
+
}
|