1 /* 2 * Scythe Statistical Library 3 * Copyright (C) 2000-2002 Andrew D. Martin and Kevin M. Quinn; 4 * 2002-present Andrew D. Martin, Kevin M. Quinn, and Daniel 5 * Pemstein. All Rights Reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * under the terms of the GNU General Public License as published by 9 * Free Software Foundation; either version 2 of the License, or (at 10 * your option) any later version. See the text files COPYING 11 * and LICENSE, distributed with this source code, for further 12 * information. 13 * -------------------------------------------------------------------- 14 * scythestat/rng/lecuyer.h 15 * 16 * Provides the class definition for the L'Ecuyer random number 17 * generator, a rng capable of generating many independent substreams. 18 * This class extends the abstract rng class by implementing runif(). 19 * Based on RngStream.cpp, by Pierre L'Ecuyer. 20 * 21 * Pierre L'Ecuyer agreed to the following dual-licensing terms in an 22 * email received 7 August 2004. This dual-license was prompted by 23 * the Debian maintainers of R and MCMCpack. 24 * 25 * This software is Copyright (C) 2004 Pierre L'Ecuyer. 26 * 27 * License: this code can be used freely for personal, academic, or 28 * non-commercial purposes. For commercial licensing, please contact 29 * P. L'Ecuyer at lecuyer@iro.umontreal.ca. 30 * 31 * This code may also be redistributed and modified under the terms of 32 * the GNU General Public License as published by the Free Software 33 * Foundation; either version 2 of the License, or (at your option) any 34 * later version. 35 * 36 * This program is distributed in the hope that it will be useful, but 37 * WITHOUT ANY WARRANTY; without even the implied warranty of 38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 39 * General Public License for more details. 40 * 41 * You should have received a copy of the GNU General Public License 42 * along with this program; if not, write to the Free Software 43 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 44 * USA. 45 * 46 */ 47 /*! \file lecuyer.h 48 * \brief The L'Ecuyer random number generator. 49 * 50 * This file contains the lecuyer class, a class that extends Scythe's 51 * base random number generation class (scythe::rng) by providing an 52 * implementation of scythe::rng::runif(), using L'Ecuyer's algorithm. 53 * 54 */ 55 #ifndef SCYTHE_LECUYER_H 56 #define SCYTHE_LECUYER_H 57 58 #include<cstdlib> 59 #include<iostream> 60 #include<string> 61 62 #ifdef SCYTHE_COMPILE_DIRECT 63 #include "rng.h" 64 #else 65 #include "scythestat/rng.h" 66 #endif 67 68 /* We want to use an anonymous namespace to make the following consts 69 * and functions local to this file, but mingw doesn't play nice with 70 * anonymous namespaces so we do things differently when using the 71 * cross-compiler. 72 */ 73 #ifdef __MINGW32__ 74 #define SCYTHE_MINGW32_STATIC static 75 #else 76 #define SCYTHE_MINGW32_STATIC 77 #endif 78 79 namespace scythe { 80 #ifndef __MINGW32__ 81 namespace { 82 #endif 83 84 SCYTHE_MINGW32_STATIC const double m1 = 4294967087.0; 85 SCYTHE_MINGW32_STATIC const double m2 = 4294944443.0; 86 SCYTHE_MINGW32_STATIC const double norm = 1.0 / (m1 + 1.0); 87 SCYTHE_MINGW32_STATIC const double a12 = 1403580.0; 88 SCYTHE_MINGW32_STATIC const double a13n = 810728.0; 89 SCYTHE_MINGW32_STATIC const double a21 = 527612.0; 90 SCYTHE_MINGW32_STATIC const double a23n = 1370589.0; 91 SCYTHE_MINGW32_STATIC const double two17 =131072.0; 92 SCYTHE_MINGW32_STATIC const double two53 =9007199254740992.0; 93 /* 1/2^24 */ 94 SCYTHE_MINGW32_STATIC const double fact = 5.9604644775390625e-8; 95 96 // The following are the transition matrices of the two MRG 97 // components (in matrix form), raised to the powers -1, 1, 2^76, 98 // and 2^127, resp. 99 100 SCYTHE_MINGW32_STATIC const double InvA1[3][3] = { // Inverse of A1p0 101 { 184888585.0, 0.0, 1945170933.0 }, 102 { 1.0, 0.0, 0.0 }, 103 { 0.0, 1.0, 0.0 } }; 104 105 SCYTHE_MINGW32_STATIC const double InvA2[3][3] = { // Inverse of A2p0 106 { 0.0, 360363334.0, 4225571728.0 }, 107 { 1.0, 0.0, 0.0 }, 108 { 0.0, 1.0, 0.0 } }; 109 110 SCYTHE_MINGW32_STATIC const double A1p0[3][3] = { 111 { 0.0, 1.0, 0.0 }, 112 { 0.0, 0.0, 1.0 }, 113 { -810728.0, 1403580.0, 0.0 } }; 114 115 SCYTHE_MINGW32_STATIC const double A2p0[3][3] = { 116 { 0.0, 1.0, 0.0 }, 117 { 0.0, 0.0, 1.0 }, 118 { -1370589.0, 0.0, 527612.0 } }; 119 120 SCYTHE_MINGW32_STATIC const double A1p76[3][3] = { 121 { 82758667.0, 1871391091.0, 4127413238.0 }, 122 { 3672831523.0, 69195019.0, 1871391091.0 }, 123 { 3672091415.0, 3528743235.0, 69195019.0 } }; 124 125 SCYTHE_MINGW32_STATIC const double A2p76[3][3] = { 126 { 1511326704.0, 3759209742.0, 1610795712.0 }, 127 { 4292754251.0, 1511326704.0, 3889917532.0 }, 128 { 3859662829.0, 4292754251.0, 3708466080.0 } }; 129 130 SCYTHE_MINGW32_STATIC const double A1p127[3][3] = { 131 { 2427906178.0, 3580155704.0, 949770784.0 }, 132 { 226153695.0, 1230515664.0, 3580155704.0 }, 133 { 1988835001.0, 986791581.0, 1230515664.0 } }; 134 135 SCYTHE_MINGW32_STATIC const double A2p127[3][3] = { 136 { 1464411153.0, 277697599.0, 1610723613.0 }, 137 { 32183930.0, 1464411153.0, 1022607788.0 }, 138 { 2824425944.0, 32183930.0, 2093834863.0 } }; 139 140 // Return (a*s + c) MOD m; a, s, c and m must be < 2^35 141 SCYTHE_MINGW32_STATIC double MultModM(double a,double s,double c,double m)142 MultModM (double a, double s, double c, double m) 143 { 144 double v; 145 long a1; 146 147 v = a * s + c; 148 149 if (v >= two53 || v <= -two53) { 150 a1 = static_cast<long> (a / two17); a -= a1 * two17; 151 v = a1 * s; 152 a1 = static_cast<long> (v / m); v -= a1 * m; 153 v = v * two17 + a * s + c; 154 } 155 156 a1 = static_cast<long> (v / m); 157 /* in case v < 0)*/ 158 if ((v -= a1 * m) < 0.0) return v += m; else return v; 159 } 160 161 // Compute the vector v = A*s MOD m. Assume that -m < s[i] < m. 162 // Works also when v = s. 163 SCYTHE_MINGW32_STATIC void MatVecModM(const double A[3][3],const double s[3],double v[3],double m)164 MatVecModM (const double A[3][3], const double s[3], 165 double v[3], double m) 166 { 167 int i; 168 double x[3]; // Necessary if v = s 169 170 for (i = 0; i < 3; ++i) { 171 x[i] = MultModM (A[i][0], s[0], 0.0, m); 172 x[i] = MultModM (A[i][1], s[1], x[i], m); 173 x[i] = MultModM (A[i][2], s[2], x[i], m); 174 } 175 for (i = 0; i < 3; ++i) 176 v[i] = x[i]; 177 } 178 179 // Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m. 180 // Note: works also if A = C or B = C or A = B = C. 181 SCYTHE_MINGW32_STATIC void MatMatModM(const double A[3][3],const double B[3][3],double C[3][3],double m)182 MatMatModM (const double A[3][3], const double B[3][3], 183 double C[3][3], double m) 184 { 185 int i, j; 186 double V[3], W[3][3]; 187 188 for (i = 0; i < 3; ++i) { 189 for (j = 0; j < 3; ++j) 190 V[j] = B[j][i]; 191 MatVecModM (A, V, V, m); 192 for (j = 0; j < 3; ++j) 193 W[j][i] = V[j]; 194 } 195 for (i = 0; i < 3; ++i) 196 for (j = 0; j < 3; ++j) 197 C[i][j] = W[i][j]; 198 } 199 200 // Compute the matrix B = (A^(2^e) Mod m); works also if A = B. 201 SCYTHE_MINGW32_STATIC void MatTwoPowModM(const double A[3][3],double B[3][3],double m,long e)202 MatTwoPowModM(const double A[3][3], double B[3][3], 203 double m, long e) 204 { 205 int i, j; 206 207 /* initialize: B = A */ 208 if (A != B) { 209 for (i = 0; i < 3; ++i) 210 for (j = 0; j < 3; ++j) 211 B[i][j] = A[i][j]; 212 } 213 /* Compute B = A^(2^e) mod m */ 214 for (i = 0; i < e; i++) 215 MatMatModM (B, B, B, m); 216 } 217 218 // Compute the matrix B = (A^n Mod m); works even if A = B. 219 SCYTHE_MINGW32_STATIC void MatPowModM(const double A[3][3],double B[3][3],double m,long n)220 MatPowModM (const double A[3][3], double B[3][3], double m, 221 long n) 222 { 223 int i, j; 224 double W[3][3]; 225 226 /* initialize: W = A; B = I */ 227 for (i = 0; i < 3; ++i) 228 for (j = 0; j < 3; ++j) { 229 W[i][j] = A[i][j]; 230 B[i][j] = 0.0; 231 } 232 for (j = 0; j < 3; ++j) 233 B[j][j] = 1.0; 234 235 /* Compute B = A^n mod m using the binary decomposition of n */ 236 while (n > 0) { 237 if (n % 2) MatMatModM (W, B, B, m); 238 MatMatModM (W, W, W, m); 239 n /= 2; 240 } 241 } 242 243 // Check that the seeds are legitimate values. Returns 0 if legal 244 // seeds, -1 otherwise. 245 SCYTHE_MINGW32_STATIC int CheckSeed(const unsigned long seed[6])246 CheckSeed (const unsigned long seed[6]) 247 { 248 int i; 249 250 for (i = 0; i < 3; ++i) { 251 if (seed[i] >= m1) { 252 SCYTHE_THROW(scythe_randseed_error, 253 "Seed[" << i << "] >= 4294967087, Seed is not set"); 254 return -1; 255 } 256 } 257 for (i = 3; i < 6; ++i) { 258 if (seed[i] >= m2) { 259 SCYTHE_THROW(scythe_randseed_error, 260 "Seed[" << i << "] >= 4294944443, Seed is not set"); 261 return -1; 262 } 263 } 264 if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) { 265 SCYTHE_THROW(scythe_randseed_error, "First 3 seeds = 0"); 266 return -1; 267 } 268 if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) { 269 SCYTHE_THROW(scythe_randseed_error, "Last 3 seeds = 0"); 270 return -1; 271 } 272 273 return 0; 274 } 275 276 #ifndef __MINGW32__ 277 } // end anonymous namespace 278 #endif 279 280 /*! \brief The L'Ecuyer random number generator. 281 * 282 * This class defines a random number generator, using Pierre 283 * L'Ecuyer's algorithm (2000) and source code (2001) for 284 * generating multiple simultaneous streams of random uniform 285 * variates. The period of the underlying single-stream generator 286 * is approximately \f$3.1 \times 10^{57}\f$. Each individual 287 * stream is implemented in terms of a sequence of substreams (see 288 * L'Ecuyer et al (2000) for details). 289 * 290 * The lecuyer class extends Scythe's basic random number 291 * generating class, scythe::rng, implementing the interface that 292 * it defines. 293 * 294 * \see rng 295 * \see mersenne 296 * 297 */ 298 class lecuyer : public rng<lecuyer> 299 { 300 public: 301 302 // Constructor 303 /*! \brief Constructor 304 * 305 * This constructor creates an object encapsulating a random 306 * number stream, with an optional name. It also sets the seed 307 * of the stream to the package (default or user-specified) seed 308 * if this is the first stream generated, or, otherwise, to a 309 * value \f$2^{127}\f$ steps ahead of the seed of the previously 310 * constructed stream. 311 * 312 * \param streamname The optional name for the stream. 313 * 314 * \see SetPackageSeed(unsigned long seed[6]) 315 * \see SetSeed(unsigned long seed[6]) 316 * \see SetAntithetic(bool) 317 * \see IncreasedPrecis(bool) 318 * \see name() 319 */ 320 lecuyer (std::string streamname = "") 321 : rng<lecuyer> (), 322 streamname_ (streamname) 323 { 324 anti = false; 325 incPrec = false; 326 327 /* Information on a stream. The arrays {Cg, Bg, Ig} contain 328 * the current state of the stream, the starting state of the 329 * current SubStream, and the starting state of the stream. 330 * This stream generates antithetic variates if anti = true. 331 * It also generates numbers with extended precision (53 bits 332 * if machine follows IEEE 754 standard) if incPrec = true. 333 * nextSeed will be the seed of the next declared RngStream. 334 */ 335 336 for (int i = 0; i < 6; ++i) { 337 Bg[i] = Cg[i] = Ig[i] = nextSeed[i]; 338 } 339 340 MatVecModM (A1p127, nextSeed, nextSeed, m1); 341 MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2); 342 } 343 344 /*! \brief Get the stream's name. 345 * 346 * This method returns a stream's name string. 347 * 348 * \see lecuyer(const char*) 349 */ 350 std::string name()351 name() const 352 { 353 return streamname_; 354 } 355 356 /*! \brief Reset the stream. 357 * 358 * This method resets the stream to its initial seeded state. 359 * 360 * \see ResetStartSubstream() 361 * \see ResetNextSubstream() 362 * \see SetSeed(unsigned long seed[6]) 363 */ 364 void ResetStartStream()365 ResetStartStream () 366 { 367 for (int i = 0; i < 6; ++i) 368 Cg[i] = Bg[i] = Ig[i]; 369 } 370 371 /*! \brief Reset the current substream. 372 * 373 * 374 * This method resets the stream to the first state of its 375 * current substream. 376 * 377 * \see ResetStartStream() 378 * \see ResetNextSubstream() 379 * \see SetSeed(unsigned long seed[6]) 380 * 381 */ 382 void ResetStartSubstream()383 ResetStartSubstream () 384 { 385 for (int i = 0; i < 6; ++i) 386 Cg[i] = Bg[i]; 387 } 388 389 /*! \brief Jump to the next substream. 390 * 391 * This method resets the stream to the first state of its next 392 * substream. 393 * 394 * \see ResetStartStream() 395 * \see ResetStartSubstream() 396 * \see SetSeed(unsigned long seed[6]) 397 * 398 */ 399 void ResetNextSubstream()400 ResetNextSubstream () 401 { 402 MatVecModM(A1p76, Bg, Bg, m1); 403 MatVecModM(A2p76, &Bg[3], &Bg[3], m2); 404 for (int i = 0; i < 6; ++i) 405 Cg[i] = Bg[i]; 406 } 407 408 /*! \brief Set the package seed. 409 * 410 * This method sets the overall package seed. The default 411 * initial seed is (12345, 12345, 12345, 12345, 12345, 12345). 412 * The package seed is the seed used to initialize the first 413 * constructed random number stream in a given program. 414 * 415 * \param seed An array of six integers to seed the package. 416 * The first three values cannot all equal 0 and must all be 417 * less than 4294967087 while the second trio of integers must 418 * all be less than 4294944443 and not all 0. 419 * 420 * \see SetSeed(unsigned long seed[6]) 421 * 422 * \throw scythe_randseed_error (Level 0) 423 */ 424 static void SetPackageSeed(unsigned long seed[6])425 SetPackageSeed (unsigned long seed[6]) 426 { 427 if (CheckSeed (seed)) return; 428 for (int i = 0; i < 6; ++i) 429 nextSeed[i] = seed[i]; 430 } 431 432 /*! \brief Set the stream seed. 433 * 434 * This method sets the stream seed which is used to initialize 435 * the state of the given stream. 436 * 437 * \warning This method sets the stream seed in isolation and 438 * does not coordinate with any other streams. Therefore, 439 * using this method without care can result in multiple 440 * streams that overlap in the course of their runs. 441 * 442 * \param seed An array of six integers to seed the stream. 443 * The first three values cannot all equal 0 and must all be 444 * less than 4294967087 while the second trio of integers must 445 * all be less than 4294944443 and not all 0. 446 * 447 * \see SetPackageSeed(unsigned long seed[6]) 448 * \see ResetStartStream() 449 * \see ResetStartSubstream() 450 * \see ResetNextSubstream() 451 * 452 * \throw scythe_randseed_error (Level 0) 453 */ 454 void SetSeed(unsigned long seed[6])455 SetSeed (unsigned long seed[6]) 456 { 457 if (CheckSeed (seed)) return; 458 for (int i = 0; i < 6; ++i) 459 Cg[i] = Bg[i] = Ig[i] = seed[i]; 460 } 461 462 // XXX: get the cases formula working! 463 /*! \brief Advances the state of the stream. 464 * 465 * This method advances the input \f$n\f$ steps, using the rule: 466 * \f[ 467 * n = 468 * \begin{cases} 469 * 2^e + c \quad if~e > 0, \\ 470 * -2^{-e} + c \quad if~e < 0, \\ 471 * c \quad if~e = 0. 472 * \end{cases} 473 * \f] 474 * 475 * \param e This parameter controls state advancement. 476 * \param c This parameter also controls state advancement. 477 * 478 * \see GetState() 479 * \see ResetStartStream() 480 * \see ResetStartSubstream() 481 * \see ResetNextSubstream() 482 */ 483 void AdvanceState(long e,long c)484 AdvanceState (long e, long c) 485 { 486 double B1[3][3], C1[3][3], B2[3][3], C2[3][3]; 487 488 if (e > 0) { 489 MatTwoPowModM (A1p0, B1, m1, e); 490 MatTwoPowModM (A2p0, B2, m2, e); 491 } else if (e < 0) { 492 MatTwoPowModM (InvA1, B1, m1, -e); 493 MatTwoPowModM (InvA2, B2, m2, -e); 494 } 495 496 if (c >= 0) { 497 MatPowModM (A1p0, C1, m1, c); 498 MatPowModM (A2p0, C2, m2, c); 499 } else { 500 MatPowModM (InvA1, C1, m1, -c); 501 MatPowModM (InvA2, C2, m2, -c); 502 } 503 504 if (e) { 505 MatMatModM (B1, C1, C1, m1); 506 MatMatModM (B2, C2, C2, m2); 507 } 508 509 MatVecModM (C1, Cg, Cg, m1); 510 MatVecModM (C2, &Cg[3], &Cg[3], m2); 511 } 512 513 /*! \brief Get the current state. 514 * 515 * This method places the current state of the stream, as 516 * represented by six integers, into the array argument. This 517 * is useful for saving and restoring streams across program 518 * runs. 519 * 520 * \param seed An array of six integers that will hold the state values on return. 521 * 522 * \see AdvanceState() 523 */ 524 void GetState(unsigned long seed[6])525 GetState (unsigned long seed[6]) const 526 { 527 for (int i = 0; i < 6; ++i) 528 seed[i] = static_cast<unsigned long> (Cg[i]); 529 } 530 531 /*! \brief Toggle generator precision. 532 * 533 * This method sets the precision level of the given stream. By 534 * default, streams generate random numbers with 32 bit 535 * resolution. If the user invokes this method with \a incp = 536 * true, then the stream will begin to generate variates with 537 * greater precision (53 bits on machines following the IEEE 754 538 * standard). Calling this method again with \a incp = false 539 * will return the precision of generated numbers to 32 bits. 540 * 541 * \param incp A boolean value where true implies high (most 542 * likely 53 bit) precision and false implies low (32 bit) 543 * precision. 544 * 545 * \see SetAntithetic(bool) 546 */ 547 void IncreasedPrecis(bool incp)548 IncreasedPrecis (bool incp) 549 { 550 incPrec = incp; 551 } 552 553 /*! \brief Toggle the orientation of generated random numbers. 554 * 555 * This methods causes the given stream to generate antithetic 556 * (1 - U, where U is the default number generated) when called 557 * with \a a = true. Calling this method with \a a = false will 558 * return generated numbers to their default orientation. 559 * 560 * \param a A boolean value that selects regular or antithetic 561 * variates. 562 * 563 * \see IncreasedPrecis(bool) 564 */ 565 void SetAntithetic(bool a)566 SetAntithetic (bool a) 567 { 568 anti = a; 569 } 570 571 /*! \brief Generate a random uniform variate on (0, 1). 572 * 573 * This routine returns a random double precision floating point 574 * number from the uniform distribution on the interval (0, 575 * 1). This method overloads the pure virtual method of the 576 * same name in the rng base class. 577 * 578 * \see runif(unsigned int, unsigned int) 579 * \see RandInt(long, long) 580 * \see rng 581 */ 582 double runif()583 runif () 584 { 585 if (incPrec) 586 return U01d(); 587 else 588 return U01(); 589 } 590 591 /* We have to override the overloaded form of runif because 592 * overloading the no-arg runif() hides the base class 593 * definition; C++ stops looking once it finds the above. 594 */ 595 /*! \brief Generate a Matrix of random uniform variates. 596 * 597 * This routine returns a Matrix of double precision random 598 * uniform variates. on the interval (0, 1). This method 599 * overloads the virtual method of the same name in the rng base 600 * class. 601 * 602 * This is the general template version of this method and 603 * is called through explicit template instantiation. 604 * 605 * \param rows The number of rows in the returned Matrix. 606 * \param cols The number of columns in the returned Matrix. 607 * 608 * \see runif() 609 * \see rng 610 * 611 * \note We are forced to override this overloaded method 612 * because the 1-arg version of runif() hides the base class's 613 * definition of this method from the compiler, although it 614 * probably should not. 615 */ 616 template <matrix_order O, matrix_style S> runif(unsigned int rows,unsigned int cols)617 Matrix<double,O,S> runif(unsigned int rows, unsigned int cols) 618 { 619 return rng<lecuyer>::runif<O,S>(rows,cols); 620 } 621 622 /*! \brief Generate a Matrix of random uniform variates. 623 * 624 * This routine returns a Matrix of double precision random 625 * uniform variates on the interval (0, 1). This method 626 * overloads the virtual method of the same name in the rng base 627 * class. 628 * 629 * This is the default template version of this method and 630 * is called through implicit template instantiation. 631 * 632 * \param rows The number of rows in the returned Matrix. 633 * \param cols The number of columns in the returned Matrix. 634 * 635 * \see runif() 636 * \see rng 637 * 638 * \note We are forced to override this overloaded method 639 * because the 1-arg version of runif() hides the base class's 640 * definition of this method from the compiler, although it 641 * probably should not. 642 */ runif(unsigned int rows,unsigned int cols)643 Matrix<double,Col,Concrete> runif(unsigned int rows, 644 unsigned int cols) 645 { 646 return rng<lecuyer>::runif<Col,Concrete>(rows, cols); 647 } 648 649 /*! \brief Generate the next random integer. 650 * 651 * This method generates a random integer from the discrete 652 * uniform distribution on the interval [\a low, \a high]. 653 * 654 * \param low The lower bound of the interval to evaluate. 655 * \param high the upper bound of the interval to evaluate. 656 * 657 * \see runif() 658 */ 659 long RandInt(long low,long high)660 RandInt (long low, long high) 661 { 662 return low + static_cast<long> ((high - low + 1) * runif ()); 663 } 664 665 protected: 666 // Generate the next random number. 667 // 668 double U01()669 U01 () 670 { 671 long k; 672 double p1, p2, u; 673 674 /* Component 1 */ 675 p1 = a12 * Cg[1] - a13n * Cg[0]; 676 k = static_cast<long> (p1 / m1); 677 p1 -= k * m1; 678 if (p1 < 0.0) p1 += m1; 679 Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1; 680 681 /* Component 2 */ 682 p2 = a21 * Cg[5] - a23n * Cg[3]; 683 k = static_cast<long> (p2 / m2); 684 p2 -= k * m2; 685 if (p2 < 0.0) p2 += m2; 686 Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2; 687 688 /* Combination */ 689 u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm); 690 691 return (anti == false) ? u : (1 - u); 692 } 693 694 // Generate the next random number with extended (53 bits) precision. 695 double U01d()696 U01d () 697 { 698 double u; 699 u = U01(); 700 if (anti) { 701 // Don't forget that U01() returns 1 - u in the antithetic case 702 u += (U01() - 1.0) * fact; 703 return (u < 0.0) ? u + 1.0 : u; 704 } else { 705 u += U01() * fact; 706 return (u < 1.0) ? u : (u - 1.0); 707 } 708 } 709 710 711 // Public members of the class start here 712 713 // The default seed of the package; will be the seed of the first 714 // declared RngStream, unless SetPackageSeed is called. 715 static double nextSeed[6]; 716 717 /* Instance variables */ 718 double Cg[6], Bg[6], Ig[6]; 719 720 721 bool anti, incPrec; 722 723 724 std::string streamname_; 725 726 }; 727 728 #ifndef SCYTHE_RPACK 729 /* Default seed definition */ 730 double lecuyer::nextSeed[6] = 731 { 732 12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0 733 }; 734 #endif 735 736 } 737 738 #endif /* SCYTHE_LECUYER_H */ 739