00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00055 #ifndef SCYTHE_LECUYER_H
00056 #define SCYTHE_LECUYER_H
00057
00058 #include<cstdlib>
00059 #include<iostream>
00060 #include<string>
00061
00062 #ifdef SCYTHE_COMPILE_DIRECT
00063 #include "rng.h"
00064 #else
00065 #include "scythestat/rng.h"
00066 #endif
00067
00068
00069
00070
00071
00072
00073 #ifdef __MINGW32__
00074 #define SCYTHE_MINGW32_STATIC static
00075 #else
00076 #define SCYTHE_MINGW32_STATIC
00077 #endif
00078
00079 namespace scythe {
00080 #ifndef __MINGW32__
00081 namespace {
00082 #endif
00083
00084 SCYTHE_MINGW32_STATIC const double m1 = 4294967087.0;
00085 SCYTHE_MINGW32_STATIC const double m2 = 4294944443.0;
00086 SCYTHE_MINGW32_STATIC const double norm = 1.0 / (m1 + 1.0);
00087 SCYTHE_MINGW32_STATIC const double a12 = 1403580.0;
00088 SCYTHE_MINGW32_STATIC const double a13n = 810728.0;
00089 SCYTHE_MINGW32_STATIC const double a21 = 527612.0;
00090 SCYTHE_MINGW32_STATIC const double a23n = 1370589.0;
00091 SCYTHE_MINGW32_STATIC const double two17 =131072.0;
00092 SCYTHE_MINGW32_STATIC const double two53 =9007199254740992.0;
00093
00094 SCYTHE_MINGW32_STATIC const double fact = 5.9604644775390625e-8;
00095
00096
00097
00098
00099
00100 SCYTHE_MINGW32_STATIC const double InvA1[3][3] = {
00101 { 184888585.0, 0.0, 1945170933.0 },
00102 { 1.0, 0.0, 0.0 },
00103 { 0.0, 1.0, 0.0 } };
00104
00105 SCYTHE_MINGW32_STATIC const double InvA2[3][3] = {
00106 { 0.0, 360363334.0, 4225571728.0 },
00107 { 1.0, 0.0, 0.0 },
00108 { 0.0, 1.0, 0.0 } };
00109
00110 SCYTHE_MINGW32_STATIC const double A1p0[3][3] = {
00111 { 0.0, 1.0, 0.0 },
00112 { 0.0, 0.0, 1.0 },
00113 { -810728.0, 1403580.0, 0.0 } };
00114
00115 SCYTHE_MINGW32_STATIC const double A2p0[3][3] = {
00116 { 0.0, 1.0, 0.0 },
00117 { 0.0, 0.0, 1.0 },
00118 { -1370589.0, 0.0, 527612.0 } };
00119
00120 SCYTHE_MINGW32_STATIC const double A1p76[3][3] = {
00121 { 82758667.0, 1871391091.0, 4127413238.0 },
00122 { 3672831523.0, 69195019.0, 1871391091.0 },
00123 { 3672091415.0, 3528743235.0, 69195019.0 } };
00124
00125 SCYTHE_MINGW32_STATIC const double A2p76[3][3] = {
00126 { 1511326704.0, 3759209742.0, 1610795712.0 },
00127 { 4292754251.0, 1511326704.0, 3889917532.0 },
00128 { 3859662829.0, 4292754251.0, 3708466080.0 } };
00129
00130 SCYTHE_MINGW32_STATIC const double A1p127[3][3] = {
00131 { 2427906178.0, 3580155704.0, 949770784.0 },
00132 { 226153695.0, 1230515664.0, 3580155704.0 },
00133 { 1988835001.0, 986791581.0, 1230515664.0 } };
00134
00135 SCYTHE_MINGW32_STATIC const double A2p127[3][3] = {
00136 { 1464411153.0, 277697599.0, 1610723613.0 },
00137 { 32183930.0, 1464411153.0, 1022607788.0 },
00138 { 2824425944.0, 32183930.0, 2093834863.0 } };
00139
00140
00141 SCYTHE_MINGW32_STATIC double
00142 MultModM (double a, double s, double c, double m)
00143 {
00144 double v;
00145 long a1;
00146
00147 v = a * s + c;
00148
00149 if (v >= two53 || v <= -two53) {
00150 a1 = static_cast<long> (a / two17); a -= a1 * two17;
00151 v = a1 * s;
00152 a1 = static_cast<long> (v / m); v -= a1 * m;
00153 v = v * two17 + a * s + c;
00154 }
00155
00156 a1 = static_cast<long> (v / m);
00157
00158 if ((v -= a1 * m) < 0.0) return v += m; else return v;
00159 }
00160
00161
00162
00163 SCYTHE_MINGW32_STATIC void
00164 MatVecModM (const double A[3][3], const double s[3],
00165 double v[3], double m)
00166 {
00167 int i;
00168 double x[3];
00169
00170 for (i = 0; i < 3; ++i) {
00171 x[i] = MultModM (A[i][0], s[0], 0.0, m);
00172 x[i] = MultModM (A[i][1], s[1], x[i], m);
00173 x[i] = MultModM (A[i][2], s[2], x[i], m);
00174 }
00175 for (i = 0; i < 3; ++i)
00176 v[i] = x[i];
00177 }
00178
00179
00180
00181 SCYTHE_MINGW32_STATIC void
00182 MatMatModM (const double A[3][3], const double B[3][3],
00183 double C[3][3], double m)
00184 {
00185 int i, j;
00186 double V[3], W[3][3];
00187
00188 for (i = 0; i < 3; ++i) {
00189 for (j = 0; j < 3; ++j)
00190 V[j] = B[j][i];
00191 MatVecModM (A, V, V, m);
00192 for (j = 0; j < 3; ++j)
00193 W[j][i] = V[j];
00194 }
00195 for (i = 0; i < 3; ++i)
00196 for (j = 0; j < 3; ++j)
00197 C[i][j] = W[i][j];
00198 }
00199
00200
00201 SCYTHE_MINGW32_STATIC void
00202 MatTwoPowModM(const double A[3][3], double B[3][3],
00203 double m, long e)
00204 {
00205 int i, j;
00206
00207
00208 if (A != B) {
00209 for (i = 0; i < 3; ++i)
00210 for (j = 0; j < 3; ++j)
00211 B[i][j] = A[i][j];
00212 }
00213
00214 for (i = 0; i < e; i++)
00215 MatMatModM (B, B, B, m);
00216 }
00217
00218
00219 SCYTHE_MINGW32_STATIC void
00220 MatPowModM (const double A[3][3], double B[3][3], double m,
00221 long n)
00222 {
00223 int i, j;
00224 double W[3][3];
00225
00226
00227 for (i = 0; i < 3; ++i)
00228 for (j = 0; j < 3; ++j) {
00229 W[i][j] = A[i][j];
00230 B[i][j] = 0.0;
00231 }
00232 for (j = 0; j < 3; ++j)
00233 B[j][j] = 1.0;
00234
00235
00236 while (n > 0) {
00237 if (n % 2) MatMatModM (W, B, B, m);
00238 MatMatModM (W, W, W, m);
00239 n /= 2;
00240 }
00241 }
00242
00243
00244
00245 SCYTHE_MINGW32_STATIC int
00246 CheckSeed (const unsigned long seed[6])
00247 {
00248 int i;
00249
00250 for (i = 0; i < 3; ++i) {
00251 if (seed[i] >= m1) {
00252 SCYTHE_THROW(scythe_randseed_error,
00253 "Seed[" << i << "] >= 4294967087, Seed is not set");
00254 return -1;
00255 }
00256 }
00257 for (i = 3; i < 6; ++i) {
00258 if (seed[i] >= m2) {
00259 SCYTHE_THROW(scythe_randseed_error,
00260 "Seed[" << i << "] >= 4294944443, Seed is not set");
00261 return -1;
00262 }
00263 }
00264 if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
00265 SCYTHE_THROW(scythe_randseed_error, "First 3 seeds = 0");
00266 return -1;
00267 }
00268 if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {
00269 SCYTHE_THROW(scythe_randseed_error, "Last 3 seeds = 0");
00270 return -1;
00271 }
00272
00273 return 0;
00274 }
00275
00276 #ifndef __MINGW32__
00277 }
00278 #endif
00279
00298 class lecuyer : public rng<lecuyer>
00299 {
00300 public:
00301
00302
00320 lecuyer (std::string streamname = "")
00321 : rng<lecuyer> (),
00322 streamname_ (streamname)
00323 {
00324 anti = false;
00325 incPrec = false;
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 for (int i = 0; i < 6; ++i) {
00337 Bg[i] = Cg[i] = Ig[i] = nextSeed[i];
00338 }
00339
00340 MatVecModM (A1p127, nextSeed, nextSeed, m1);
00341 MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2);
00342 }
00343
00350 std::string
00351 name() const
00352 {
00353 return streamname_;
00354 }
00355
00364 void
00365 ResetStartStream ()
00366 {
00367 for (int i = 0; i < 6; ++i)
00368 Cg[i] = Bg[i] = Ig[i];
00369 }
00370
00382 void
00383 ResetStartSubstream ()
00384 {
00385 for (int i = 0; i < 6; ++i)
00386 Cg[i] = Bg[i];
00387 }
00388
00399 void
00400 ResetNextSubstream ()
00401 {
00402 MatVecModM(A1p76, Bg, Bg, m1);
00403 MatVecModM(A2p76, &Bg[3], &Bg[3], m2);
00404 for (int i = 0; i < 6; ++i)
00405 Cg[i] = Bg[i];
00406 }
00407
00424 static void
00425 SetPackageSeed (unsigned long seed[6])
00426 {
00427 if (CheckSeed (seed)) return;
00428 for (int i = 0; i < 6; ++i)
00429 nextSeed[i] = seed[i];
00430 }
00431
00454 void
00455 SetSeed (unsigned long seed[6])
00456 {
00457 if (CheckSeed (seed)) return;
00458 for (int i = 0; i < 6; ++i)
00459 Cg[i] = Bg[i] = Ig[i] = seed[i];
00460 }
00461
00462
00483 void
00484 AdvanceState (long e, long c)
00485 {
00486 double B1[3][3], C1[3][3], B2[3][3], C2[3][3];
00487
00488 if (e > 0) {
00489 MatTwoPowModM (A1p0, B1, m1, e);
00490 MatTwoPowModM (A2p0, B2, m2, e);
00491 } else if (e < 0) {
00492 MatTwoPowModM (InvA1, B1, m1, -e);
00493 MatTwoPowModM (InvA2, B2, m2, -e);
00494 }
00495
00496 if (c >= 0) {
00497 MatPowModM (A1p0, C1, m1, c);
00498 MatPowModM (A2p0, C2, m2, c);
00499 } else {
00500 MatPowModM (InvA1, C1, m1, -c);
00501 MatPowModM (InvA2, C2, m2, -c);
00502 }
00503
00504 if (e) {
00505 MatMatModM (B1, C1, C1, m1);
00506 MatMatModM (B2, C2, C2, m2);
00507 }
00508
00509 MatVecModM (C1, Cg, Cg, m1);
00510 MatVecModM (C2, &Cg[3], &Cg[3], m2);
00511 }
00512
00524 void
00525 GetState (unsigned long seed[6]) const
00526 {
00527 for (int i = 0; i < 6; ++i)
00528 seed[i] = static_cast<unsigned long> (Cg[i]);
00529 }
00530
00547 void
00548 IncreasedPrecis (bool incp)
00549 {
00550 incPrec = incp;
00551 }
00552
00565 void
00566 SetAntithetic (bool a)
00567 {
00568 anti = a;
00569 }
00570
00582 double
00583 runif ()
00584 {
00585 if (incPrec)
00586 return U01d();
00587 else
00588 return U01();
00589 }
00590
00591
00592
00593
00594
00616 template <matrix_order O, matrix_style S>
00617 Matrix<double,O,S> runif(unsigned int rows, unsigned int cols)
00618 {
00619 return rng<lecuyer>::runif<O,S>(rows,cols);
00620 }
00621
00643 Matrix<double,Col,Concrete> runif(unsigned int rows,
00644 unsigned int cols)
00645 {
00646 return rng<lecuyer>::runif<Col,Concrete>(rows, cols);
00647 }
00648
00659 long
00660 RandInt (long low, long high)
00661 {
00662 return low + static_cast<long> ((high - low + 1) * runif ());
00663 }
00664
00665 protected:
00666
00667
00668 double
00669 U01 ()
00670 {
00671 long k;
00672 double p1, p2, u;
00673
00674
00675 p1 = a12 * Cg[1] - a13n * Cg[0];
00676 k = static_cast<long> (p1 / m1);
00677 p1 -= k * m1;
00678 if (p1 < 0.0) p1 += m1;
00679 Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1;
00680
00681
00682 p2 = a21 * Cg[5] - a23n * Cg[3];
00683 k = static_cast<long> (p2 / m2);
00684 p2 -= k * m2;
00685 if (p2 < 0.0) p2 += m2;
00686 Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2;
00687
00688
00689 u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm);
00690
00691 return (anti == false) ? u : (1 - u);
00692 }
00693
00694
00695 double
00696 U01d ()
00697 {
00698 double u;
00699 u = U01();
00700 if (anti) {
00701
00702 u += (U01() - 1.0) * fact;
00703 return (u < 0.0) ? u + 1.0 : u;
00704 } else {
00705 u += U01() * fact;
00706 return (u < 1.0) ? u : (u - 1.0);
00707 }
00708 }
00709
00710
00711
00712
00713
00714
00715 static double nextSeed[6];
00716
00717
00718 double Cg[6], Bg[6], Ig[6];
00719
00720
00721 bool anti, incPrec;
00722
00723
00724 std::string streamname_;
00725
00726 };
00727
00728
00729 double lecuyer::nextSeed[6] =
00730 {
00731 12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0
00732 };
00733
00734 }
00735
00736 #endif