Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

linrdist.cpp

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 //#define EPS 1.2e-7
00031 //#define RNMX (1.0-EPS)
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   /* q[k-1] = sum(alog(2.0)**k/k!) k=1,..,n, */
00195   /* The highest n (here 8) is determined by q[n-1] = 1.0 */
00196   /* within standard precision */
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) //a = shape parameter
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     /* alternate method for parameters a below 1 */
00458     /* 0.36787944117144232159 = exp(-1) */
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   /* Step 1: Recalculations of s2, s, d if a has changed */
00476   if (a != aa) {
00477     aa = a;
00478     s2 = a - 0.5;
00479     s = sqrt(s2);
00480     d = sqrt32 - s * 12.0;
00481   }
00482   /* Step 2: t = standard normal deviate, */
00483   /* x = (s,1/2)-normal deviate. */
00484   /* immediate acceptance (i) */
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   /* Step 3: u = 0,1 - uniform sample. squeeze acceptance (s) */
00493   u = runif(idum);
00494   if (d * u <= t * t * t) {
00495     return scale * ret_val;
00496   }
00497   /* Step 4: recalculations of q0, b, si, c if necessary */
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     /* Approximation depending on size of parameter a */
00506     /* The constants in the expressions for b, si and */
00507     /* c were established by numerical experiments */
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   /* Step 5: no quotient test if x not positive */
00524 
00525   if (x > 0.0) {
00526     /* Step 6: calculation of v and quotient q */
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     /* Step 7: quotient acceptance (q) */
00538 
00539     if (log(1.0 - u) <= q)
00540       return scale * ret_val;
00541   }
00542   /* Step 8: e = standard exponential deviate */
00543   /* u= 0,1 -uniform deviate */
00544   /* t=(b,si)-double exponential (laplace) sample */
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     /* Step  9:  rejection if t < tau(1) = -0.71874483771719 */
00555     if (t >= -0.71874483771719) {
00556       /* Step 10:  calculation of v and quotient q */
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       /* Step 11:  hat acceptance (h) */
00566       /* (if q not positive go to step 8) */
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         /* if t is rejected */
00574         /* sample again at step 8 */
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 

Generated on Tue Feb 14 16:05:52 2006 for estfunc by doxygen 1.3.6