00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cstdlib>
00022 #include <iostream>
00023 #include "rng-stream.h"
00024 using namespace std;
00025
00026 namespace
00027 {
00028 const double m1 = 4294967087.0;
00029 const double m2 = 4294944443.0;
00030 const double norm = 1.0 / (m1 + 1.0);
00031 const double a12 = 1403580.0;
00032 const double a13n = 810728.0;
00033 const double a21 = 527612.0;
00034 const double a23n = 1370589.0;
00035 const double two17 = 131072.0;
00036 const double two53 = 9007199254740992.0;
00037 const double fact = 5.9604644775390625e-8;
00038
00039
00040
00041
00042 const double InvA1[3][3] = {
00043 { 184888585.0, 0.0, 1945170933.0 },
00044 { 1.0, 0.0, 0.0 },
00045 { 0.0, 1.0, 0.0 }
00046 };
00047
00048 const double InvA2[3][3] = {
00049 { 0.0, 360363334.0, 4225571728.0 },
00050 { 1.0, 0.0, 0.0 },
00051 { 0.0, 1.0, 0.0 }
00052 };
00053
00054 const double A1p0[3][3] = {
00055 { 0.0, 1.0, 0.0 },
00056 { 0.0, 0.0, 1.0 },
00057 { -810728.0, 1403580.0, 0.0 }
00058 };
00059
00060 const double A2p0[3][3] = {
00061 { 0.0, 1.0, 0.0 },
00062 { 0.0, 0.0, 1.0 },
00063 { -1370589.0, 0.0, 527612.0 }
00064 };
00065
00066 const double A1p76[3][3] = {
00067 { 82758667.0, 1871391091.0, 4127413238.0 },
00068 { 3672831523.0, 69195019.0, 1871391091.0 },
00069 { 3672091415.0, 3528743235.0, 69195019.0 }
00070 };
00071
00072 const double A2p76[3][3] = {
00073 { 1511326704.0, 3759209742.0, 1610795712.0 },
00074 { 4292754251.0, 1511326704.0, 3889917532.0 },
00075 { 3859662829.0, 4292754251.0, 3708466080.0 }
00076 };
00077
00078 const double A1p127[3][3] = {
00079 { 2427906178.0, 3580155704.0, 949770784.0 },
00080 { 226153695.0, 1230515664.0, 3580155704.0 },
00081 { 1988835001.0, 986791581.0, 1230515664.0 }
00082 };
00083
00084 const double A2p127[3][3] = {
00085 { 1464411153.0, 277697599.0, 1610723613.0 },
00086 { 32183930.0, 1464411153.0, 1022607788.0 },
00087 { 2824425944.0, 32183930.0, 2093834863.0 }
00088 };
00089
00090
00091
00092
00093
00094
00095 double MultModM (double a, double s, double c, double m)
00096 {
00097 double v;
00098 int32_t a1;
00099
00100 v = a * s + c;
00101
00102 if (v >= two53 || v <= -two53) {
00103 a1 = static_cast<int32_t> (a / two17); a -= a1 * two17;
00104 v = a1 * s;
00105 a1 = static_cast<int32_t> (v / m); v -= a1 * m;
00106 v = v * two17 + a * s + c;
00107 }
00108
00109 a1 = static_cast<int32_t> (v / m);
00110
00111 if ((v -= a1 * m) < 0.0) return v += m; else return v;
00112 }
00113
00114
00115
00116
00117
00118
00119 void MatVecModM (const double A[3][3], const double s[3], double v[3],
00120 double m)
00121 {
00122 int i;
00123 double x[3];
00124
00125 for (i = 0; i < 3; ++i) {
00126 x[i] = MultModM (A[i][0], s[0], 0.0, m);
00127 x[i] = MultModM (A[i][1], s[1], x[i], m);
00128 x[i] = MultModM (A[i][2], s[2], x[i], m);
00129 }
00130 for (i = 0; i < 3; ++i)
00131 v[i] = x[i];
00132 }
00133
00134
00135
00136
00137
00138
00139 void MatMatModM (const double A[3][3], const double B[3][3],
00140 double C[3][3], double m)
00141 {
00142 int i, j;
00143 double V[3], W[3][3];
00144
00145 for (i = 0; i < 3; ++i) {
00146 for (j = 0; j < 3; ++j)
00147 V[j] = B[j][i];
00148 MatVecModM (A, V, V, m);
00149 for (j = 0; j < 3; ++j)
00150 W[j][i] = V[j];
00151 }
00152 for (i = 0; i < 3; ++i)
00153 for (j = 0; j < 3; ++j)
00154 C[i][j] = W[i][j];
00155 }
00156
00157
00158
00159
00160
00161 void MatTwoPowModM (const double A[3][3], double B[3][3], double m, int32_t e)
00162 {
00163 int i, j;
00164
00165
00166 if (A != B) {
00167 for (i = 0; i < 3; ++i)
00168 for (j = 0; j < 3; ++j)
00169 B[i][j] = A[i][j];
00170 }
00171
00172 for (i = 0; i < e; i++)
00173 MatMatModM (B, B, B, m);
00174 }
00175
00176
00177
00178
00179
00180 void MatPowModM (const double A[3][3], double B[3][3], double m, int32_t n)
00181 {
00182 int i, j;
00183 double W[3][3];
00184
00185
00186 for (i = 0; i < 3; ++i)
00187 for (j = 0; j < 3; ++j) {
00188 W[i][j] = A[i][j];
00189 B[i][j] = 0.0;
00190 }
00191 for (j = 0; j < 3; ++j)
00192 B[j][j] = 1.0;
00193
00194
00195 while (n > 0) {
00196 if (n % 2) MatMatModM (W, B, B, m);
00197 MatMatModM (W, W, W, m);
00198 n /= 2;
00199 }
00200 }
00201
00202
00203
00204 }
00205
00206
00207 namespace ns3{
00208
00209
00210
00211 double RngStream::U01 ()
00212 {
00213 int32_t k;
00214 double p1, p2, u;
00215
00216
00217 p1 = a12 * Cg[1] - a13n * Cg[0];
00218 k = static_cast<int32_t> (p1 / m1);
00219 p1 -= k * m1;
00220 if (p1 < 0.0) p1 += m1;
00221 Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1;
00222
00223
00224 p2 = a21 * Cg[5] - a23n * Cg[3];
00225 k = static_cast<int32_t> (p2 / m2);
00226 p2 -= k * m2;
00227 if (p2 < 0.0) p2 += m2;
00228 Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2;
00229
00230
00231 u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm);
00232
00233 return (anti == false) ? u : (1 - u);
00234 }
00235
00236
00237
00238
00239
00240 double RngStream::U01d ()
00241 {
00242 double u;
00243 u = U01();
00244 if (anti) {
00245
00246 u += (U01() - 1.0) * fact;
00247 return (u < 0.0) ? u + 1.0 : u;
00248 } else {
00249 u += U01() * fact;
00250 return (u < 1.0) ? u : (u - 1.0);
00251 }
00252 }
00253
00254
00255
00256
00257
00258 bool RngStream::CheckSeed (const uint32_t seed[6])
00259 {
00260 int i;
00261
00262 for (i = 0; i < 3; ++i) {
00263 if (seed[i] >= m1) {
00264 cerr << "****************************************\n\n"
00265 << "ERROR: Seed[" << i << "] >= 4294967087, Seed is not set."
00266 << "\n\n****************************************\n\n";
00267 return (false);
00268 }
00269 }
00270 for (i = 3; i < 6; ++i) {
00271 if (seed[i] >= m2) {
00272 cerr << "Seed[" << i << "] = " << seed[i] << endl;
00273 cerr << "*****************************************\n\n"
00274 << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set."
00275 << "\n\n*****************************************\n\n";
00276 return (false);
00277 }
00278 }
00279 if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
00280 cerr << "****************************\n\n"
00281 << "ERROR: First 3 seeds = 0.\n\n"
00282 << "****************************\n\n";
00283 return (false);
00284 }
00285 if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {
00286 cerr << "****************************\n\n"
00287 << "ERROR: Last 3 seeds = 0.\n\n"
00288 << "****************************\n\n";
00289 return (false);
00290 }
00291 return true;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 double RngStream::nextSeed[6] =
00305 {
00306 12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0
00307 };
00308
00309
00310
00311
00312 RngStream::RngStream ()
00313 {
00314 anti = false;
00315 incPrec = false;
00316
00317 }
00318
00319 RngStream::RngStream(const RngStream& r)
00320 {
00321 anti = r.anti;
00322 incPrec = r.incPrec;
00323 for (int i = 0; i < 6; ++i) {
00324 Cg[i] = r.Cg[i];
00325 Bg[i] = r.Bg[i];
00326 Ig[i] = r.Ig[i];
00327 }
00328 }
00329
00330
00331 void RngStream::InitializeStream()
00332 {
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 for (int i = 0; i < 6; ++i) {
00343 Bg[i] = Cg[i] = Ig[i] = nextSeed[i];
00344 }
00345
00346 MatVecModM (A1p127, nextSeed, nextSeed, m1);
00347 MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2);
00348 }
00349
00350
00351
00352
00353 void RngStream::ResetStartStream ()
00354 {
00355 for (int i = 0; i < 6; ++i)
00356 Cg[i] = Bg[i] = Ig[i];
00357 }
00358
00359
00360
00361
00362
00363 void RngStream::ResetStartSubstream ()
00364 {
00365 for (int i = 0; i < 6; ++i)
00366 Cg[i] = Bg[i];
00367 }
00368
00369
00370
00371
00372
00373 void RngStream::ResetNextSubstream ()
00374 {
00375 MatVecModM(A1p76, Bg, Bg, m1);
00376 MatVecModM(A2p76, &Bg[3], &Bg[3], m2);
00377 for (int i = 0; i < 6; ++i)
00378 Cg[i] = Bg[i];
00379 }
00380
00381
00382
00383
00384 void RngStream::ResetNthSubstream (uint32_t N)
00385 {
00386 if(N==0) return;
00387 for(uint32_t i=0;i<N;++i) {
00388 MatVecModM(A1p76, Bg, Bg, m1);
00389 MatVecModM(A2p76, &Bg[3], &Bg[3], m2);
00390 }
00391 for (int i = 0; i < 6; ++i)
00392 Cg[i] = Bg[i];
00393 }
00394
00395
00396 bool RngStream::SetPackageSeed (const uint32_t seed[6])
00397 {
00398 if (!CheckSeed (seed)) return false;
00399 for (int i = 0; i < 6; ++i)
00400 nextSeed[i] = seed[i];
00401 return true;
00402 }
00403
00404
00405
00406 bool RngStream::SetSeeds (const uint32_t seed[6])
00407 {
00408 if (!CheckSeed (seed)) return false;
00409 for (int i = 0; i < 6; ++i)
00410 Cg[i] = Bg[i] = Ig[i] = seed[i];
00411 return true;
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421 void RngStream::AdvanceState (int32_t e, int32_t c)
00422 {
00423 double B1[3][3], C1[3][3], B2[3][3], C2[3][3];
00424
00425 if (e > 0) {
00426 MatTwoPowModM (A1p0, B1, m1, e);
00427 MatTwoPowModM (A2p0, B2, m2, e);
00428 } else if (e < 0) {
00429 MatTwoPowModM (InvA1, B1, m1, -e);
00430 MatTwoPowModM (InvA2, B2, m2, -e);
00431 }
00432
00433 if (c >= 0) {
00434 MatPowModM (A1p0, C1, m1, c);
00435 MatPowModM (A2p0, C2, m2, c);
00436 } else {
00437 MatPowModM (InvA1, C1, m1, -c);
00438 MatPowModM (InvA2, C2, m2, -c);
00439 }
00440
00441 if (e) {
00442 MatMatModM (B1, C1, C1, m1);
00443 MatMatModM (B2, C2, C2, m2);
00444 }
00445
00446 MatVecModM (C1, Cg, Cg, m1);
00447 MatVecModM (C2, &Cg[3], &Cg[3], m2);
00448 }
00449
00450
00451
00452 void RngStream::GetState (uint32_t seed[6]) const
00453 {
00454 for (int i = 0; i < 6; ++i)
00455 seed[i] = static_cast<uint32_t> (Cg[i]);
00456 }
00457
00458
00459
00460 void RngStream::IncreasedPrecis (bool incp)
00461 {
00462 incPrec = incp;
00463 }
00464
00465
00466
00467 void RngStream::SetAntithetic (bool a)
00468 {
00469 anti = a;
00470 }
00471
00472
00473
00474
00475
00476 double RngStream::RandU01 ()
00477 {
00478 if (incPrec)
00479 return U01d();
00480 else
00481 return U01();
00482 }
00483
00484
00485
00486
00487
00488 int32_t RngStream::RandInt (int32_t low, int32_t high)
00489 {
00490 return low + static_cast<int32_t> ((high - low + 1) * RandU01 ());
00491 };
00492
00493 }