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
00047
00048
00049
00050
00051
00052
00053
00054
00055 #ifndef lint
00056 static const char rcsid[] =
00057 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tools/rng.cc,v 1.30 2005/07/30 22:34:46 tomh Exp $ (LBL)";
00058 #endif
00059
00060
00061
00062 #ifndef WIN32
00063 #include <sys/time.h>
00064 #include <unistd.h>
00065 #endif
00066
00067 #include <stdio.h>
00068 #ifndef OLD_RNG
00069 #include <string.h>
00070 #endif
00071 #include "rng.h"
00072
00073 #ifdef OLD_RNG
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 #define A 16807L
00148 #define M 2147483647L
00149 #define INVERSE_M ((double)4.656612875e-10)
00150
00151 long
00152 RNGImplementation::next()
00153 {
00154 long L, H;
00155 L = A * (seed_ & 0xffff);
00156 H = A * (seed_ >> 16);
00157
00158 seed_ = ((H & 0x7fff) << 16) + L;
00159 seed_ -= 0x7fffffff;
00160 seed_ += H >> 15;
00161
00162 if (seed_ <= 0) {
00163 seed_ += 0x7fffffff;
00164 }
00165 return(seed_);
00166 }
00167
00168 double
00169 RNGImplementation::next_double()
00170 {
00171 long i = next();
00172 return i * INVERSE_M;
00173 }
00174 #endif
00175
00176
00177
00178
00179 #ifndef stand_alone
00180 static class RNGClass : public TclClass {
00181 public:
00182 RNGClass() : TclClass("RNG") {}
00183 TclObject* create(int, const char*const*) {
00184 return(new RNG());
00185 }
00186 } class_rng;
00187 #endif
00188
00189
00190
00191 RNG* RNG::default_ = NULL;
00192
00193 double
00194 RNG::normal(double avg, double std)
00195 {
00196 static int parity = 0;
00197 static double nextresult;
00198 double sam1, sam2, rad;
00199
00200 if (std == 0) return avg;
00201 if (parity == 0) {
00202 sam1 = 2*uniform() - 1;
00203 sam2 = 2*uniform() - 1;
00204 while ((rad = sam1*sam1 + sam2*sam2) >= 1) {
00205 sam1 = 2*uniform() - 1;
00206 sam2 = 2*uniform() - 1;
00207 }
00208 rad = sqrt((-2*log(rad))/rad);
00209 nextresult = sam2 * rad;
00210 parity = 1;
00211 return (sam1 * rad * std + avg);
00212 }
00213 else {
00214 parity = 0;
00215 return (nextresult * std + avg);
00216 }
00217 }
00218
00219 #ifndef stand_alone
00220 int
00221 RNG::command(int argc, const char*const* argv)
00222 {
00223 Tcl& tcl = Tcl::instance();
00224
00225 if (argc == 3) {
00226 if (strcmp(argv[1], "testint") == 0) {
00227 int n = atoi(argv[2]);
00228 tcl.resultf("%d", uniform(n));
00229 return (TCL_OK);
00230 }
00231 if (strcmp(argv[1], "testdouble") == 0) {
00232 double d = atof(argv[2]);
00233 tcl.resultf("%6e", uniform(d));
00234 return (TCL_OK);
00235 }
00236 if (strcmp(argv[1], "seed") == 0) {
00237 int s = atoi(argv[2]);
00238
00239 if (s) {
00240 if (s <= 0 || (unsigned int)s >= MAXINT) {
00241 tcl.resultf("Setting random number seed to known bad value.");
00242 return TCL_ERROR;
00243 };
00244 set_seed(RAW_SEED_SOURCE, s);
00245 } else set_seed(HEURISTIC_SEED_SOURCE, 0);
00246 return(TCL_OK);
00247 }
00248 } else if (argc == 2) {
00249 if (strcmp(argv[1], "next-random") == 0) {
00250 tcl.resultf("%u", uniform_positive_int());
00251 return(TCL_OK);
00252 }
00253 if (strcmp(argv[1], "seed") == 0) {
00254 #ifdef OLD_RNG
00255 tcl.resultf("%u", stream_.seed());
00256 #else
00257 tcl.resultf("%u", seed());
00258 #endif
00259 return(TCL_OK);
00260 }
00261 #ifndef OLD_RNG
00262 if (strcmp (argv[1], "next-substream") == 0) {
00263 reset_next_substream();
00264 return (TCL_OK);
00265 }
00266 if (strcmp (argv[1], "all-seeds") == 0) {
00267 unsigned long seeds[6];
00268 get_state (seeds);
00269 tcl.resultf ("%lu %lu %lu %lu %lu %lu",
00270 seeds[0], seeds[1], seeds[2],
00271 seeds[3], seeds[4], seeds[5]);
00272 return (TCL_OK);
00273 }
00274 if (strcmp (argv[1], "reset-start-substream") == 0) {
00275 reset_start_substream();
00276 return (TCL_OK);
00277 }
00278 #endif
00279 if (strcmp(argv[1], "default") == 0) {
00280 default_ = this;
00281 return(TCL_OK);
00282 }
00283
00284 if (strcmp(argv[1], "test") == 0) {
00285 RNGTest test; test.verbose_mil();
00286
00287
00288
00289
00290 return(TCL_OK);
00291 }
00292
00293 } else if (argc == 4) {
00294 if (strcmp(argv[1], "seed") == 0) {
00295 int s = atoi(argv[3]);
00296 if (strcmp(argv[2], "raw") == 0) {
00297 set_seed(RNG::RAW_SEED_SOURCE, s);
00298 } else if (strcmp(argv[2], "predef") == 0) {
00299 set_seed(RNG::PREDEF_SEED_SOURCE, s);
00300
00301
00302 } else if (strcmp(argv[2], "heuristic") == 0) {
00303 set_seed(RNG::HEURISTIC_SEED_SOURCE, 0);
00304 }
00305 return(TCL_OK);
00306 }
00307 if (strcmp(argv[1], "normal") == 0) {
00308 double avg = strtod(argv[2], NULL);
00309 double std = strtod(argv[3], NULL);
00310 tcl.resultf("%g", normal(avg, std));
00311 return (TCL_OK);
00312 }
00313 if (strcmp(argv[1], "lognormal") == 0) {
00314 double avg = strtod(argv[2], NULL);
00315 double std = strtod(argv[3], NULL);
00316 tcl.resultf("%g", lognormal(avg, std));
00317 return (TCL_OK);
00318 }
00319 }
00320 return(TclObject::command(argc, argv));
00321 }
00322 #endif
00323
00324 void
00325 RNG::set_seed(RNGSources source, int seed)
00326 {
00327
00328
00329
00330
00331 #define N_SEEDS_ 64
00332 static long predef_seeds[N_SEEDS_] = {
00333 1973272912L, 188312339L, 1072664641L, 694388766L,
00334 2009044369L, 934100682L, 1972392646L, 1936856304L,
00335 1598189534L, 1822174485L, 1871883252L, 558746720L,
00336 605846893L, 1384311643L, 2081634991L, 1644999263L,
00337 773370613L, 358485174L, 1996632795L, 1000004583L,
00338 1769370802L, 1895218768L, 186872697L, 1859168769L,
00339 349544396L, 1996610406L, 222735214L, 1334983095L,
00340 144443207L, 720236707L, 762772169L, 437720306L,
00341 939612284L, 425414105L, 1998078925L, 981631283L,
00342 1024155645L, 822780843L, 701857417L, 960703545L,
00343 2101442385L, 2125204119L, 2041095833L, 89865291L,
00344 898723423L, 1859531344L, 764283187L, 1349341884L,
00345 678622600L, 778794064L, 1319566104L, 1277478588L,
00346 538474442L, 683102175L, 999157082L, 985046914L,
00347 722594620L, 1695858027L, 1700738670L, 1995749838L,
00348 1147024708L, 346983590L, 565528207L, 513791680L
00349 };
00350 static long heuristic_sequence = 0;
00351
00352 switch (source) {
00353 case RAW_SEED_SOURCE:
00354 if (seed <= 0 || (unsigned int)seed >= MAXINT)
00355 abort();
00356
00357 break;
00358 case PREDEF_SEED_SOURCE:
00359 if (seed < 0 || seed >= N_SEEDS_)
00360 abort();
00361 seed = predef_seeds[seed];
00362 break;
00363 case HEURISTIC_SEED_SOURCE:
00364 timeval tv;
00365 gettimeofday(&tv, 0);
00366 heuristic_sequence++;
00367 seed = (tv.tv_sec ^ tv.tv_usec ^ (heuristic_sequence << 8)) & 0x7fffffff;
00368 break;
00369 };
00370
00371
00372
00373 if (seed < 0)
00374 seed = -seed;
00375 #ifdef OLD_RNG
00376 stream_.set_seed(seed);
00377 #else
00378 set_seed(seed);
00379 #endif
00380
00381
00382
00383
00384
00385
00386
00387
00388 if (source == HEURISTIC_SEED_SOURCE) {
00389 int i;
00390 for (i = 0; i < 128; i++) {
00391 #ifdef OLD_RNG
00392 stream_.next();
00393 #else
00394 next();
00395 #endif
00396 };
00397 };
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 #ifdef rng_stand_alone
00411 int main() { RNGTest test; test.verbose(); }
00412 #endif
00413
00414 #ifdef rng_test
00415 RNGTest::RNGTest()
00416 {
00417 RNG rng(RNG::RAW_SEED_SOURCE, 1L);
00418
00419 int i;
00420 long r;
00421 for (i = 0; i < 10000; i++)
00422 r = rng.uniform_positive_int();
00423
00424 #ifdef OLD_RNG
00425 if (r != 1043618065L) {
00426 fprintf (stderr, "r (%lu) != 1043618065L\n", r);
00427 exit(-1);
00428 }
00429 #else
00430 if (r != 1179983147L) {
00431 fprintf (stderr, "r (%lu) != 1179983147L\n", r);
00432 exit(-1);
00433 }
00434 #endif
00435
00436 for (i = 10000; i < 551246; i++)
00437 r = rng.uniform_positive_int();
00438
00439 #ifdef OLD_RNG
00440 if (r != 1003L) {
00441 fprintf (stderr, "r (%lu) != 1003L\n", r);
00442 exit(-1);
00443 }
00444 #else
00445 if (r != 817829295L) {
00446 fprintf (stderr, "r (%lu) != 817829295L\n", r);
00447 exit(-1);
00448 }
00449 #endif
00450
00451 }
00452
00453 void
00454 RNGTest::first_n(RNG::RNGSources source, long seed, int n)
00455 {
00456 RNG rng(source, seed);
00457
00458 for (int i = 0; i < n; i++) {
00459 long r = rng.uniform_positive_int();
00460 printf("%10lu ", r);
00461 };
00462 printf("\n");
00463 }
00464
00465 void
00466 RNGTest::first_n_mil(RNG::RNGSources source, long seed, int n, FILE *outfile)
00467 {
00468 RNG rng(source, seed);
00469
00470 long m = n * 1000000;
00471 for (int i = 0; i < m; i++) {
00472 long r = rng.uniform_positive_int();
00473 if (i < 100 || (i % 1000000 == 0))
00474 fprintf(outfile, "%10lu ", r);
00475 };
00476 fprintf(outfile, "\n");
00477 }
00478
00479 void
00480 RNGTest::verbose_mil()
00481 {
00482 FILE *outfile = NULL;
00483 outfile = fopen("temp.rands", "w");
00484
00485 if (outfile == NULL)
00486 fprintf(stderr, "Cannot create temp.rands\n");
00487
00488 fprintf (outfile, "default: ");
00489 first_n_mil(RNG::RAW_SEED_SOURCE, 188312339, 5, outfile);
00490 int i = 1;
00491 fprintf (outfile, "predef source %2u: ", i);
00492 first_n_mil(RNG::PREDEF_SEED_SOURCE, i, 5, outfile);
00493
00494 }
00495
00496 void
00497 RNGTest::verbose()
00498 {
00499 printf ("default: ");
00500 first_n(RNG::RAW_SEED_SOURCE, 1L, 5);
00501
00502 int i;
00503 for (i = 0; i < 64; i++) {
00504 printf ("predef source %2u: ", i);
00505 first_n(RNG::PREDEF_SEED_SOURCE, i, 5);
00506 };
00507
00508 printf("heuristic seeds should be different from each other and on each run.\n");
00509 for (i = 0; i < 64; i++) {
00510 printf ("heuristic source %2u: ", i);
00511 first_n(RNG::HEURISTIC_SEED_SOURCE, i, 5);
00512 };
00513 }
00514
00515 #endif
00516
00517 #ifndef OLD_RNG
00518 using namespace std;
00519 namespace
00520 {
00521 const double m1 = 4294967087.0;
00522 const double m2 = 4294944443.0;
00523 const double norm = 1.0 / (m1 + 1.0);
00524 const double a12 = 1403580.0;
00525 const double a13n = 810728.0;
00526 const double a21 = 527612.0;
00527 const double a23n = 1370589.0;
00528 const double two17 = 131072.0;
00529 const double two53 = 9007199254740992.0;
00530 const double fact = 5.9604644775390625e-8;
00531
00532
00533
00534
00535
00536 const double InvA1[3][3] = {
00537 { 184888585.0, 0.0, 1945170933.0 },
00538 { 1.0, 0.0, 0.0 },
00539 { 0.0, 1.0, 0.0 }
00540 };
00541
00542 const double InvA2[3][3] = {
00543 { 0.0, 360363334.0, 4225571728.0 },
00544 { 1.0, 0.0, 0.0 },
00545 { 0.0, 1.0, 0.0 }
00546 };
00547
00548 const double A1p0[3][3] = {
00549 { 0.0, 1.0, 0.0 },
00550 { 0.0, 0.0, 1.0 },
00551 { -810728.0, 1403580.0, 0.0 }
00552 };
00553
00554 const double A2p0[3][3] = {
00555 { 0.0, 1.0, 0.0 },
00556 { 0.0, 0.0, 1.0 },
00557 { -1370589.0, 0.0, 527612.0 }
00558 };
00559
00560 const double A1p76[3][3] = {
00561 { 82758667.0, 1871391091.0, 4127413238.0 },
00562 { 3672831523.0, 69195019.0, 1871391091.0 },
00563 { 3672091415.0, 3528743235.0, 69195019.0 }
00564 };
00565
00566 const double A2p76[3][3] = {
00567 { 1511326704.0, 3759209742.0, 1610795712.0 },
00568 { 4292754251.0, 1511326704.0, 3889917532.0 },
00569 { 3859662829.0, 4292754251.0, 3708466080.0 }
00570 };
00571
00572 const double A1p127[3][3] = {
00573 { 2427906178.0, 3580155704.0, 949770784.0 },
00574 { 226153695.0, 1230515664.0, 3580155704.0 },
00575 { 1988835001.0, 986791581.0, 1230515664.0 }
00576 };
00577
00578 const double A2p127[3][3] = {
00579 { 1464411153.0, 277697599.0, 1610723613.0 },
00580 { 32183930.0, 1464411153.0, 1022607788.0 },
00581 { 2824425944.0, 32183930.0, 2093834863.0 }
00582 };
00583
00584
00585
00586
00587
00588 double MultModM (double a, double s, double c, double m)
00589 {
00590 double v;
00591 long a1;
00592 v=a*s+c;
00593
00594 if (v >= two53 || v <= -two53) {
00595 a1 = static_cast<long> (a / two17); a -= a1 * two17;
00596 v =a1*s;
00597 a1 = static_cast<long> (v / m); v -= a1 * m;
00598 v = v * two17 + a * s + c;
00599 }
00600 a1 = static_cast<long> (v / m);
00601
00602 if ((v -= a1 * m) < 0.0) return v += m; else return v;
00603 }
00604
00605
00606
00607
00608
00609 void MatVecModM (const double A[3][3], const double s[3], double v[3],
00610 double m)
00611 {
00612 int i;
00613 double x[3];
00614 for (i = 0; i < 3; ++i) {
00615 x[i] = MultModM (A[i][0], s[0], 0.0, m);
00616 x[i] = MultModM (A[i][1], s[1], x[i], m);
00617 x[i] = MultModM (A[i][2], s[2], x[i], m);
00618 }
00619 for (i = 0; i < 3; ++i)
00620 v[i] = x[i];
00621 }
00622
00623
00624
00625
00626
00627 void MatMatModM (const double A[3][3], const double B[3][3],
00628 double C[3][3], double m)
00629 {
00630 int i, j;
00631 double V[3], W[3][3];
00632 for (i = 0; i < 3; ++i) {
00633 for (j = 0; j < 3; ++j)
00634 V[j] = B[j][i];
00635 MatVecModM (A, V, V, m);
00636 for (j = 0; j < 3; ++j)
00637
00638 W[j][i] = V[j];
00639 }
00640 for (i = 0; i < 3; ++i)
00641 for (j = 0; j < 3; ++j)
00642 C[i][j] = W[i][j];
00643 }
00644
00645
00646
00647
00648 void MatTwoPowModM (const double A[3][3], double B[3][3], double m,
00649 long e)
00650 {
00651 int i, j;
00652
00653 if (A != B) {
00654 for (i = 0; i < 3; ++i)
00655 for (j = 0; j < 3; ++j)
00656 B[i][j] = A[i][j];
00657 }
00658
00659 for (i = 0; i < e; i++)
00660 MatMatModM (B, B, B, m);
00661 }
00662
00663
00664
00665
00666 void MatPowModM (const double A[3][3], double B[3][3], double m,
00667 long n)
00668 {
00669 int i, j;
00670 double W[3][3];
00671
00672 for (i = 0; i < 3; ++i)
00673 for (j = 0; j < 3; ++j) {
00674 W[i][j] = A[i][j];
00675 B[i][j] = 0.0;
00676 }
00677 for (j = 0; j < 3; ++j)
00678 B[j][j] = 1.0;
00679
00680 while (n > 0) {
00681 if (n % 2) MatMatModM (W, B, B, m);
00682 MatMatModM (W, W, W, m);
00683
00684 n/=2;
00685 }
00686 }
00687
00688
00689
00690
00691
00692 int CheckSeed (const unsigned long seed[6])
00693 {
00694 int i;
00695 for (i = 0; i < 3; ++i) {
00696 if (seed[i] >= m1) {
00697 fprintf (stderr, "****************************************\n\n");
00698 fprintf (stderr, "ERROR: Seed[%d] >= 4294967087, Seed is not set.", i);
00699 fprintf (stderr, "\n\n****************************************\n\n");
00700 return (-1);
00701 }
00702 }
00703 for (i = 3; i < 6; ++i) {
00704 if (seed[i] >= m2) {
00705 fprintf (stderr, "****************************************\n\n");
00706 fprintf (stderr, "ERROR: Seed[%d] >= 429444443, Seed is not set.", i);
00707 fprintf (stderr, "\n\n****************************************\n\n");
00708 return (-1);
00709 }
00710 }
00711 if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
00712 fprintf (stderr, "****************************************\n\n");
00713 fprintf (stderr, "ERROR: First 3 seeds = 0.\n\n");
00714 fprintf (stderr, "****************************************\n\n");
00715 return (-1);
00716 }
00717 if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {
00718 fprintf (stderr, "****************************************\n\n");
00719 fprintf (stderr, "ERROR: Last 3 seeds = 0.\n\n");
00720 fprintf (stderr, "****************************************\n\n");
00721 return (-1);
00722 }
00723 return 0;
00724 }
00725 }
00726
00727
00728
00729
00730 double RNG::U01 ()
00731 {
00732 long k;
00733 double p1, p2, u;
00734
00735 p1 = a12 * Cg_[1] - a13n * Cg_[0];
00736 k = static_cast<long> (p1 / m1);
00737 p1 -= k * m1;
00738 if (p1 < 0.0) p1 += m1;
00739 Cg_[0] = Cg_[1]; Cg_[1] = Cg_[2]; Cg_[2] = p1;
00740
00741 p2 = a21 * Cg_[5] - a23n * Cg_[3];
00742 k = static_cast<long> (p2 / m2);
00743 p2 -= k * m2;
00744 if (p2 < 0.0) p2 += m2;
00745 Cg_[3] = Cg_[4]; Cg_[4] = Cg_[5]; Cg_[5] = p2;
00746
00747 u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm);
00748 return (anti_ == false) ? u : (1 - u);
00749 }
00750
00751
00752
00753
00754 double RNG::U01d ()
00755 {
00756 double u;
00757 u = U01();
00758 if (anti_) {
00759
00760
00761 u += (U01() - 1.0) * fact;
00762 return (u < 0.0) ? u + 1.0 : u;
00763 } else {
00764 u += U01() * fact;
00765 return (u < 1.0) ? u : (u - 1.0);
00766 }
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 RNG::RNG (long seed)
00783 {
00784 set_seed (seed);
00785 init();
00786 }
00787
00788 void RNG::init()
00789 {
00790 anti_ = false;
00791 inc_prec_ = false;
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 for (int i = 0; i < 6; ++i) {
00802 Bg_[i] = Cg_[i] = Ig_[i] = next_seed_[i];
00803 }
00804 MatVecModM (A1p127, next_seed_, next_seed_, m1);
00805 MatVecModM (A2p127, &next_seed_[3], &next_seed_[3], m2);
00806 }
00807
00808 void RNG::set_seed (long seed)
00809 {
00810 if (seed == 0) {
00811 set_seed (HEURISTIC_SEED_SOURCE, seed);
00812 }
00813 else {
00814 unsigned long seed_vec[6] = {0, 0, 0, 0, 0, 0};
00815 for (int i=0; i<6; i++) {
00816 seed_vec[i] = (unsigned long) seed;
00817 }
00818 set_package_seed (seed_vec);
00819 init();
00820 }
00821 }
00822
00823 long RNG::seed()
00824 {
00825 unsigned long seed[6];
00826 get_state(seed);
00827 return ((long) seed[0]);
00828 }
00829
00830 long RNG::next()
00831 {
00832 return (rand_int(0, MAXINT));
00833 }
00834
00835 double RNG::next_double()
00836 {
00837 return (rand_u01());
00838 }
00839
00840
00841
00842
00843
00844 double RNG::next_seed_[6] =
00845 {
00846 12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0
00847 };
00848
00849
00850
00851
00852 RNG::RNG (const char *s)
00853 {
00854 if (strlen (s) > 99) {
00855 strncpy (name_, s, 99);
00856 name_[100] = 0;
00857 }
00858 else
00859 strcpy (name_, s);
00860
00861 init();
00862 }
00863
00864
00865
00866
00867
00868 void RNG::reset_start_stream ()
00869 {
00870 for (int i = 0; i < 6; ++i)
00871 Cg_[i] = Bg_[i] = Ig_[i];
00872 }
00873
00874
00875
00876
00877 void RNG::reset_start_substream ()
00878 {
00879 for (int i = 0; i < 6; ++i)
00880 Cg_[i] = Bg_[i];
00881 }
00882
00883
00884
00885
00886 void RNG::reset_next_substream ()
00887 {
00888 MatVecModM(A1p76, Bg_, Bg_, m1);
00889 MatVecModM(A2p76, &Bg_[3], &Bg_[3], m2);
00890 for (int i = 0; i < 6; ++i)
00891 Cg_[i] = Bg_[i];
00892 }
00893
00894
00895 void RNG::set_package_seed (const unsigned long seed[6])
00896 {
00897 if (CheckSeed (seed))
00898 abort();
00899 for (int i = 0; i < 6; ++i)
00900 next_seed_[i] = seed[i];
00901 }
00902
00903
00904 void RNG::set_seed (const unsigned long seed[6])
00905 {
00906 if (CheckSeed (seed))
00907 abort();
00908 for (int i = 0; i < 6; ++i)
00909 Cg_[i] = Bg_[i] = Ig_[i] = seed[i];
00910 }
00911
00912
00913
00914
00915
00916
00917
00918 void RNG::advance_state (long e, long c)
00919 {
00920 double B1[3][3], C1[3][3], B2[3][3], C2[3][3];
00921 if (e > 0) {
00922 MatTwoPowModM (A1p0, B1, m1, e);
00923 MatTwoPowModM (A2p0, B2, m2, e);
00924 } else if (e < 0) {
00925 MatTwoPowModM (InvA1, B1, m1, -e);
00926 MatTwoPowModM (InvA2, B2, m2, -e);
00927 }
00928 if (c >= 0) {
00929 MatPowModM (A1p0, C1, m1, c);
00930 MatPowModM (A2p0, C2, m2, c);
00931 } else {
00932 MatPowModM (InvA1, C1, m1, -c);
00933 MatPowModM (InvA2, C2, m2, -c);
00934 }
00935 if (e) {
00936 MatMatModM (B1, C1, C1, m1);
00937 MatMatModM (B2, C2, C2, m2);
00938 }
00939 MatVecModM (C1, Cg_, Cg_, m1);
00940 MatVecModM (C2, &Cg_[3], &Cg_[3], m2);
00941 }
00942
00943
00944 void RNG::get_state (unsigned long seed[6]) const
00945 {
00946 for (int i = 0; i < 6; ++i)
00947 seed[i] = static_cast<unsigned long> (Cg_[i]);
00948 }
00949
00950
00951 void RNG::write_state () const
00952 {
00953 printf ("The current state of the Rngstream %s:\n", name_);
00954 printf (" Cg_ = { ");
00955 for(int i=0;i<5;i++) {
00956 printf ("%lu, ", (unsigned long) Cg_[i]);
00957 }
00958 printf ("%lu }\n\n", (unsigned long) Cg_[5]);
00959 }
00960
00961
00962 void RNG::write_state_full () const
00963 {
00964 int i;
00965 printf ("The RNG %s:\n", name_);
00966 printf (" anti_ = %s", (anti_ ? "true" : "false"));
00967 printf (" inc_prec_ = %s\n", (inc_prec_ ? "true" : "false"));
00968
00969 printf (" Ig_ = { ");
00970 for (i = 0; i < 5; i++) {
00971 printf ("%lu, ", (unsigned long) Ig_[i]);
00972 }
00973 printf ("%lu }\n", (unsigned long) Ig_[5]);
00974
00975 printf (" Bg_ = { ");
00976 for (i = 0; i < 5; i++) {
00977 printf ("%lu, ", (unsigned long) Bg_[i]);
00978 }
00979 printf ("%lu }\n", (unsigned long) Bg_[5]);
00980
00981 printf (" Cg_ = { ");
00982 for (i = 0; i < 5; i++) {
00983 printf ("%lu, ", (unsigned long) Cg_[i]);
00984 }
00985 printf ("%lu }\n\n", (unsigned long) Cg_[5]);
00986 }
00987
00988
00989 void RNG::increased_precis (bool incp)
00990 {
00991 inc_prec_ = incp;
00992 }
00993
00994
00995 void RNG::set_antithetic (bool a)
00996 {
00997 anti_ = a;
00998 }
00999
01000
01001
01002
01003 double RNG::rand_u01 ()
01004 {
01005 if (inc_prec_)
01006 return U01d();
01007 else
01008 return U01();
01009 }
01010
01011
01012
01013
01014 long RNG::rand_int (long low, long high)
01015 {
01016
01017 return ((long) (low + (unsigned long) (((unsigned long)
01018 (high-low+1)) * rand_u01())));
01019 };
01020 #endif