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