00001 #include <fstream>
00002 #include "linrdist.h"
00003
00004 int static const RANTYPE=2;
00005 int SIMSTART;
00006
00007 #define IA 16807
00008 #define IM 2147483647
00009 #define AM (1.0/IM)
00010 #define IQ 127773
00011 #define IR 2836
00012 #define NTAB 32
00013 #define NDIV (1+(IM-1)/NTAB)
00014 #define EPS 1.2e-7
00015 #define RNMX (1.0-EPS)
00016
00017
00018 #define IM1 2147483563
00019 #define IM2 2147483399
00020 #define AMran2 (1.0/IM1)
00021 #define IMM1 (IM1-1)
00022 #define IA1 40014
00023 #define IA2 40692
00024 #define IQ1 53668
00025 #define IQ2 52774
00026 #define IR1 12211
00027 #define IR2 3791
00028 #define NTAB 32
00029 #define NDIVran2 (1+IMM1/NTAB)
00030
00031
00032
00033
00034 #define MBIG 1000000000
00035 #define MSEED 161803398
00036 #define MZ 0
00037 #define FAC (1.0/MBIG)
00038
00039
00040 double ran1(long *idum)
00041 {
00042 int j;
00043 long k;
00044 static long iy=0;
00045 static long iv[NTAB];
00046 double temp;
00047
00048 if (*idum <= 0 || !iy) {
00049 if (-(*idum) < 1) *idum=1;
00050 else *idum = -(*idum);
00051 for (j=NTAB+7;j>=0;j--) {
00052 k=(*idum)/IQ;
00053 *idum=IA*(*idum-k*IQ)-IR*k;
00054 if (*idum < 0) *idum += IM;
00055 if (j < NTAB) iv[j] = *idum;
00056 }
00057 iy=iv[0];
00058 }
00059 k=(*idum)/IQ;
00060 *idum=IA*(*idum-k*IQ)-IR*k;
00061 if (*idum < 0) *idum += IM;
00062 j=iy/NDIV;
00063 iy=iv[j];
00064 iv[j] = *idum;
00065 if ((temp=AM*iy) > RNMX) return RNMX;
00066 else return temp;
00067 }
00068
00069
00070 double ran2(long *idum)
00071 {
00072 int j;
00073 long k;
00074 static long idum2=123456789;
00075 static long iy=0;
00076 static long iv[NTAB];
00077 double temp;
00078
00079 if (*idum <= 0) {
00080 if (-(*idum) < 1) *idum=1;
00081 else *idum = -(*idum);
00082 idum2=(*idum);
00083 for (j=NTAB+7;j>=0;j--) {
00084 k=(*idum)/IQ1;
00085 *idum=IA1*(*idum-k*IQ1)-k*IR1;
00086 if (*idum < 0) *idum += IM1;
00087 if (j < NTAB) iv[j] = *idum;
00088 }
00089 iy=iv[0];
00090 }
00091 k=(*idum)/IQ1;
00092 *idum=IA1*(*idum-k*IQ1)-k*IR1;
00093 if (*idum < 0) *idum += IM1;
00094 k=idum2/IQ2;
00095 idum2=IA2*(idum2-k*IQ2)-k*IR2;
00096 if (idum2 < 0) idum2 += IM2;
00097 j=iy/NDIVran2;
00098 iy=iv[j]-idum2;
00099 iv[j] = *idum;
00100 if (iy < 1) iy += IMM1;
00101 if ((temp=AMran2*iy) > RNMX) return RNMX;
00102 else return temp;
00103 }
00104
00105
00106
00107 double ran3(long *idum)
00108 {
00109 static int inext,inextp;
00110 static long ma[56];
00111 static int iff=0;
00112 long mj,mk;
00113 int i,ii,k;
00114
00115 if (*idum < 0 || iff == 0) {
00116 iff=1;
00117 mj=MSEED-(*idum < 0 ? -*idum : *idum);
00118 mj %= MBIG;
00119 ma[55]=mj;
00120 mk=1;
00121 for (i=1;i<=54;i++) {
00122 ii=(21*i) % 55;
00123 ma[ii]=mk;
00124 mk=mj-mk;
00125 if (mk < MZ) mk += MBIG;
00126 mj=ma[ii];
00127 }
00128 for (k=1;k<=4;k++)
00129 for (i=1;i<=55;i++) {
00130 ma[i] -= ma[1+(i+30) % 55];
00131 if (ma[i] < MZ) ma[i] += MBIG;
00132 }
00133 inext=0;
00134 inextp=31;
00135 *idum=1;
00136 }
00137 if (++inext == 56) inext=1;
00138 if (++inextp == 56) inextp=1;
00139 mj=ma[inext]-ma[inextp];
00140 if (mj < MZ) mj += MBIG;
00141 ma[inext]=mj;
00142 return mj*FAC;
00143 }
00144
00145
00146 #undef IA
00147 #undef IM
00148 #undef AM
00149 #undef IQ
00150 #undef IR
00151 #undef NTAB
00152 #undef NDIV
00153 #undef EPS
00154 #undef RNMX
00155
00156 #undef IM1
00157 #undef IM2
00158 #undef AMran2
00159 #undef IMM1
00160 #undef IA1
00161 #undef IA2
00162 #undef IQ1
00163 #undef IQ2
00164 #undef IR1
00165 #undef IR2
00166 #undef NTAB
00167 #undef NDIVran2
00168 #undef EPS
00169 #undef RNMX
00170
00171 #undef MBIG
00172 #undef MSEED
00173 #undef MZ
00174 #undef FAC
00175
00176 double runif(long *idum)
00177 {
00178 double ran;
00179
00180 switch(RANTYPE)
00181 {
00182 case 1: ran = ran1(idum); break;
00183 case 2: ran = ran2(idum); break;
00184 case 3: ran = ran3(idum); break;
00185 default: std::cout << "Wrong input in runif (linrdist.h)"; break;
00186 }
00187
00188 return(ran);
00189 }
00190
00191
00192 double rexp(long *idum)
00193 {
00194
00195
00196
00197 static double q[] =
00198 {
00199 0.6931471805599453,
00200 0.9333736875190459,
00201 0.9888777961838675,
00202 0.9984959252914960,
00203 0.9998292811061389,
00204 0.9999833164100727,
00205 0.9999985691438767,
00206 0.9999998906925558,
00207 0.9999999924734159,
00208 0.9999999995283275,
00209 0.9999999999728814,
00210 0.9999999999985598,
00211 0.9999999999999289,
00212 0.9999999999999968,
00213 0.9999999999999999,
00214 1.0000000000000000
00215 };
00216 double a, u, ustar, umin;
00217 int i;
00218
00219 a = 0.0;
00220 u = runif(idum);
00221 for (;;) {
00222 u = u + u;
00223 if (u > 1.0)
00224 break;
00225 a = a + q[0];
00226 }
00227 u = u - 1.0;
00228
00229 if (u <= q[0])
00230 return a + u;
00231
00232 i = 0;
00233 ustar = runif(idum);
00234 umin = ustar;
00235 do {
00236 ustar = runif(idum);
00237 if (ustar < umin)
00238 umin = ustar;
00239 i = i + 1;
00240 }
00241 while (u > q[i]);
00242 return a + umin * q[0];
00243 }
00244
00245
00246 static double a[32] =
00247 {
00248 0.0000000, 0.03917609, 0.07841241, 0.1177699,
00249 0.1573107, 0.19709910, 0.23720210, 0.2776904,
00250 0.3186394, 0.36012990, 0.40225010, 0.4450965,
00251 0.4887764, 0.53340970, 0.57913220, 0.6260990,
00252 0.6744898, 0.72451440, 0.77642180, 0.8305109,
00253 0.8871466, 0.94678180, 1.00999000, 1.0775160,
00254 1.1503490, 1.22985900, 1.31801100, 1.4177970,
00255 1.5341210, 1.67594000, 1.86273200, 2.1538750
00256 };
00257
00258 static double d[31] =
00259 {
00260 0.0000000, 0.0000000, 0.0000000, 0.0000000,
00261 0.0000000, 0.2636843, 0.2425085, 0.2255674,
00262 0.2116342, 0.1999243, 0.1899108, 0.1812252,
00263 0.1736014, 0.1668419, 0.1607967, 0.1553497,
00264 0.1504094, 0.1459026, 0.1417700, 0.1379632,
00265 0.1344418, 0.1311722, 0.1281260, 0.1252791,
00266 0.1226109, 0.1201036, 0.1177417, 0.1155119,
00267 0.1134023, 0.1114027, 0.1095039
00268 };
00269
00270 static double t[31] =
00271 {
00272 7.673828e-4, 0.002306870, 0.003860618, 0.005438454,
00273 0.007050699, 0.008708396, 0.010423570, 0.012209530,
00274 0.014081250, 0.016055790, 0.018152900, 0.020395730,
00275 0.022811770, 0.025434070, 0.028302960, 0.031468220,
00276 0.034992330, 0.038954830, 0.043458780, 0.048640350,
00277 0.054683340, 0.061842220, 0.070479830, 0.081131950,
00278 0.094624440, 0.112300100, 0.136498000, 0.171688600,
00279 0.227624100, 0.330498000, 0.584703100
00280 };
00281
00282 static double h[31] =
00283 {
00284 0.03920617, 0.03932705, 0.03950999, 0.03975703,
00285 0.04007093, 0.04045533, 0.04091481, 0.04145507,
00286 0.04208311, 0.04280748, 0.04363863, 0.04458932,
00287 0.04567523, 0.04691571, 0.04833487, 0.04996298,
00288 0.05183859, 0.05401138, 0.05654656, 0.05953130,
00289 0.06308489, 0.06737503, 0.07264544, 0.07926471,
00290 0.08781922, 0.09930398, 0.11555990, 0.14043440,
00291 0.18361420, 0.27900160, 0.70104740
00292 };
00293
00294 #define repeat for(;;)
00295
00296 double rnorm1(long *idum)
00297 {
00298 double s, u, w, y, ustar, aa, tt;
00299 int i;
00300
00301 u = runif(idum);
00302 s = 0.0;
00303 if (u > 0.5)
00304 s = 1.0;
00305 u = u + u - s;
00306 u *= 32.0;
00307 i = (int) u;
00308 if (i == 32)
00309 i = 31;
00310 if (i != 0) {
00311 ustar = u - i;
00312 aa = a[i - 1];
00313 while (ustar <= t[i - 1]) {
00314 u = runif(idum);
00315 w = u * (a[i] - aa);
00316 tt = (w * 0.5 + aa) * w;
00317 repeat {
00318 if (ustar > tt)
00319 goto deliver;
00320 u = runif(idum);
00321 if (ustar < u)
00322 break;
00323 tt = u;
00324 ustar = runif(idum);
00325 }
00326 ustar = runif(idum);
00327 }
00328 w = (ustar - t[i - 1]) * h[i - 1];
00329 }
00330 else {
00331 i = 6;
00332 aa = a[31];
00333 repeat {
00334 u = u + u;
00335 if (u >= 1.0)
00336 break;
00337 aa = aa + d[i - 1];
00338 i = i + 1;
00339 }
00340 u = u - 1.0;
00341 repeat {
00342 w = u * d[i - 1];
00343 tt = (w * 0.5 + aa) * w;
00344 repeat {
00345 ustar = runif(idum);
00346 if (ustar > tt)
00347 goto jump;
00348 u = runif(idum);
00349 if (ustar < u)
00350 break;
00351 tt = u;
00352 }
00353 u = runif(idum);
00354 }
00355 jump:;
00356 }
00357
00358 deliver:
00359 y = aa + w;
00360 return (s == 1.0) ? -y : y;
00361
00362 }
00363
00364 double rnorm2(long *idum)
00365 {
00366 static int iset = 0;
00367 static double gset;
00368 double fac,rsq,v1,v2;
00369
00370 if (SIMSTART == 1) {
00371 iset = 0;
00372 SIMSTART = 0;
00373 }
00374
00375 if (iset == 0) {
00376 do {
00377 v1 = 2.0*runif(idum) - 1.0;
00378 v2 = 2.0*runif(idum) - 1.0;
00379 rsq = v1*v1 + v2*v2;
00380 } while (rsq >= 1.0 || rsq == 0.0);
00381 fac = sqrt(-2.0*log(rsq)/rsq);
00382 gset = v1*fac;
00383 iset = 1;
00384 return v2*fac;
00385 }
00386 else {
00387 iset = 0;
00388 return gset;
00389 }
00390 }
00391
00392 double ranexp(long *idum)
00393 {
00394
00395 double dum;
00396
00397 do
00398 dum = runif(idum);
00399 while (dum == 0.0);
00400 return -log(dum);
00401 }
00402
00403 double rangamma(double a, long *idum)
00404 {
00405 double e, u1, u2, x=0;
00406
00407 e = exp(1.0);
00408
00409 if (a < 1) {
00410 do {
00411 u1 = runif(idum);
00412 u2 = runif(idum);
00413 if (u1 < e/(a+e)) x = -log((a+e)*u1/e);
00414 } while (u1 < 1);
00415 }
00416 else if (a > 1) {
00417
00418 }
00419 else x = ranexp(idum);
00420 return x;
00421 }
00422
00423
00424 static double a1 = 0.3333333;
00425 static double a2 = -0.250003;
00426 static double a3 = 0.2000062;
00427 static double a4 = -0.1662921;
00428 static double a5 = 0.1423657;
00429 static double a6 = -0.1367177;
00430 static double a7 = 0.1233795;
00431 static double e1 = 1.0;
00432 static double e2 = 0.4999897;
00433 static double e3 = 0.166829;
00434 static double e4 = 0.0407753;
00435 static double e5 = 0.010293;
00436 static double q1 = 0.04166669;
00437 static double q2 = 0.02083148;
00438 static double q3 = 0.00801191;
00439 static double q4 = 0.00144121;
00440 static double q5 = -7.388e-5;
00441 static double q6 = 2.4511e-4;
00442 static double q7 = 2.424e-4;
00443 static double sqrt32 = 5.656854;
00444
00445 static double aa = 0.;
00446 static double aaa = 0.;
00447
00448 #define repeat for(;;)
00449
00450 double rgamma(double a, double scale, long *idum)
00451 {
00452 static double b, c, d, e, p, q, r, s, t, u, v, w, x;
00453 static double q0, s2, si;
00454 double ret_val;
00455
00456 if (a < 1.0) {
00457
00458
00459 aa = 0.0;
00460 b = 1.0 + 0.36787944117144232159 * a;
00461 repeat {
00462 p = b * runif(idum);
00463 if (p >= 1.0) {
00464 ret_val = -log((b - p) / a);
00465 if (rexp(idum) >= (1.0 - a) * log(ret_val))
00466 break;
00467 } else {
00468 ret_val = exp(log(p) / a);
00469 if (rexp(idum) >= ret_val)
00470 break;
00471 }
00472 }
00473 return scale * ret_val;
00474 }
00475
00476 if (a != aa) {
00477 aa = a;
00478 s2 = a - 0.5;
00479 s = sqrt(s2);
00480 d = sqrt32 - s * 12.0;
00481 }
00482
00483
00484
00485
00486 t = rnorm2(idum);
00487 x = s + 0.5 * t;
00488 ret_val = x * x;
00489 if (t >= 0.0)
00490 return scale * ret_val;
00491
00492
00493 u = runif(idum);
00494 if (d * u <= t * t * t) {
00495 return scale * ret_val;
00496 }
00497
00498
00499 if (a != aaa) {
00500 aaa = a;
00501 r = 1.0 / a;
00502 q0 = ((((((q7 * r + q6) * r + q5) * r + q4)
00503 * r + q3) * r + q2) * r + q1) * r;
00504
00505
00506
00507
00508
00509 if (a <= 3.686) {
00510 b = 0.463 + s + 0.178 * s2;
00511 si = 1.235;
00512 c = 0.195 / s - 0.079 + 0.16 * s;
00513 } else if (a <= 13.022) {
00514 b = 1.654 + 0.0076 * s2;
00515 si = 1.68 / s + 0.275;
00516 c = 0.062 / s + 0.024;
00517 } else {
00518 b = 1.77;
00519 si = 0.75;
00520 c = 0.1515 / s;
00521 }
00522 }
00523
00524
00525 if (x > 0.0) {
00526
00527 v = t / (s + s);
00528 if (fabs(v) <= 0.25)
00529 q = q0 + 0.5 * t * t * ((((((a7 * v + a6)
00530 * v + a5) * v + a4) * v + a3)
00531 * v + a2) * v + a1) * v;
00532 else
00533 q = q0 - s * t + 0.25 * t * t + (s2 + s2)
00534 * log(1.0 + v);
00535
00536
00537
00538
00539 if (log(1.0 - u) <= q)
00540 return scale * ret_val;
00541 }
00542
00543
00544
00545
00546 repeat {
00547 e = rexp(idum);
00548 u = runif(idum);
00549 u = u + u - 1.0;
00550 if (u < 0.0)
00551 t = b - si * e;
00552 else
00553 t = b + si * e;
00554
00555 if (t >= -0.71874483771719) {
00556
00557 v = t / (s + s);
00558 if (fabs(v) <= 0.25)
00559 q = q0 + 0.5 * t * t * ((((((a7 * v + a6)
00560 * v + a5) * v + a4) * v + a3)
00561 * v + a2) * v + a1) * v;
00562 else
00563 q = q0 - s * t + 0.25 * t * t + (s2 + s2)
00564 * log(1.0 + v);
00565
00566
00567 if (q > 0.0) {
00568 if (q <= 0.5)
00569 w = ((((e5 * q + e4) * q + e3)
00570 * q + e2) * q + e1) * q;
00571 else
00572 w = exp(q) - 1.0;
00573
00574
00575 if (c * fabs(u) <= w * exp(e - 0.5 * t * t))
00576 break;
00577 }
00578 }
00579 }
00580 x = s + 0.5 * t;
00581 return scale* x*x;
00582
00583 }
00584
00585
00586 #ifdef TEST
00587
00588 #include <iostream>
00589 #include <cstdlib>
00590
00591 int main() {
00592 try {
00593
00594
00595
00596 long idum = 12345213;
00597 double ran1(long *idum);
00598
00599 for (unsigned i=0; i<100; i++) {
00600 double val = ran1(&idum);
00601 std::cerr << val << std::endl;
00602 }
00603
00604
00605
00606
00607 std::cerr << "All tests in linrdist.cpp were successful.\n";
00608 } catch(std::string const& err) {
00609 std::cerr << err << std::endl;
00610 return EXIT_FAILURE;
00611 }
00612 return EXIT_SUCCESS;
00613 }
00614
00615
00616 #endif//TEST
00617