rng.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:27k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  *  File:  RngStream.cc for multiple streams of Random Numbers
  4.  *  Copyright (C) 2001  Pierre L'Ecuyer (lecuyer@iro.umontreal.ca)
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  19.  *  02110-1301 USA
  20.  *
  21.  *  Linking this random number generator statically or dynamically with
  22.  *  other modules is making a combined work based on this random number
  23.  *  generator.  Thus, the terms and conditions of the GNU General Public
  24.  *  License cover the whole combination.
  25.  *
  26.  *  In addition, as a special exception, the copyright holders of this
  27.  *  random number generator give you permission to combine this random
  28.  *  number generator program with free software programs or libraries
  29.  *  that are released under the GNU LGPL and with code included in the
  30.  *  standard release of ns-2 under the Apache 2.0 license or under
  31.  *  otherwise-compatible licenses with advertising requirements (or
  32.  *  modified versions of such code, with unchanged license).  You may
  33.  *  copy and distribute such a system following the terms of the GNU GPL
  34.  *  for this random number generator and the licenses of the other code
  35.  *  concerned, provided  that you include the source code of that other
  36.  *  code when and as the GNU GPL requires distribution of source code.
  37.  *
  38.  *  Note that people who make modified versions of this random number
  39.  *  generator are not obligated to grant this special exception for
  40.  *  their modified versions; it is their choice whether to do so.
  41.  *  The GNU General Public License gives permission to release a
  42.  *  modified  version without this exception; this exception also makes
  43.  *  it possible to release a modified version which carries forward
  44.  *  this exception.
  45.  *
  46.  * Incorporated into rng.h and modified to maintain backward 
  47.  * compatibility with ns-2.1b8.  Users can use their current scripts 
  48.  * unmodified with the new RNG.  To get the same results as with the 
  49.  * previous RNG, define OLD_RNG when compiling (e.g., make -D OLD_RNG).
  50.  * - Michele Weigle, University of North Carolina (mcweigle@cs.unc.edu)
  51.  * October 10, 2001
  52.  *
  53.  */
  54. #ifndef lint
  55. static const char rcsid[] =
  56.     "@(#) $Header: /cvsroot/nsnam/nam-1/rng.cc,v 1.8 2007/02/12 07:18:09 tom_henderson Exp $ (LBL)";
  57. #endif
  58. /* new random number generator */
  59.   
  60. #ifndef WIN32
  61. #include <sys/time.h> // for gettimeofday
  62. #include <unistd.h>
  63. #endif
  64. #include <stdio.h>
  65. #ifndef OLD_RNG
  66. #include <string.h>
  67. #endif /* !OLD_RNG */
  68. #include "rng.h"
  69. #ifdef OLD_RNG
  70. /*
  71.  * RNGImplementation
  72.  */
  73. /*
  74.  * Generate a periodic sequence of pseudo-random numbers with
  75.  * a period of 2^31 - 2.  The generator is the "minimal standard"
  76.  * multiplicative linear congruential generator of Park, S.K. and
  77.  * Miller, K.W., "Random Number Generators: Good Ones are Hard to Find,"
  78.  * CACM 31:10, Oct. 88, pp. 1192-1201.
  79.  *
  80.  * The algorithm implemented is:  Sn = (a*s) mod m.
  81.  *   The modulus m can be approximately factored as: m = a*q + r,
  82.  *   where q = m div a and r = m mod a.
  83.  *
  84.  * Then Sn = g(s) + m*d(s)
  85.  *   where g(s) = a(s mod q) - r(s div q)
  86.  *   and d(s) = (s div q) - ((a*s) div m)
  87.  *
  88.  * Observations:
  89.  *   - d(s) is either 0 or 1.
  90.  *   - both terms of g(s) are in 0, 1, 2, . . ., m - 1.
  91.  *   - |g(s)| <= m - 1.
  92.  *   - if g(s) > 0, d(s) = 0, else d(s) = 1.
  93.  *   - s mod q = s - k*q, where k = s div q.
  94.  *
  95.  * Thus Sn = a(s - k*q) - r*k,
  96.  *   if (Sn <= 0), then Sn += m.
  97.  *
  98.  * To test an implementation for A = 16807, M = 2^31-1, you should
  99.  *   get the following sequences for the given starting seeds:
  100.  *
  101.  *   s0, s1,    s2,        s3,          . . . , s10000,     . . . , s551246 
  102.  *    1, 16807, 282475249, 1622650073,  . . . , 1043618065, . . . , 1003 
  103.  *    1973272912, 1207871363, 531082850, 967423018
  104.  *
  105.  * It is important to check for s10000 and s551246 with s0=1, to guard 
  106.  * against overflow.
  107. */
  108. /*
  109.  * The sparc assembly code [no longer here] is based on Carta, D.G., "Two Fast
  110.  * Implementations of the 'Minimal Standard' Random Number
  111.  * Generator," CACM 33:1, Jan. 90, pp. 87-88.
  112.  *
  113.  * ASSUME that "the product of two [signed 32-bit] integers (a, sn)
  114.  *        will occupy two [32-bit] registers (p, q)."
  115.  * Thus: a*s = (2^31)p + q
  116.  *
  117.  * From the observation that: x = y mod z is but
  118.  *   x = z * the fraction part of (y/z),
  119.  * Let: sn = m * Frac(as/m)
  120.  *
  121.  * For m = 2^31 - 1,
  122.  *   sn = (2^31 - 1) * Frac[as/(2^31 -1)]
  123.  *      = (2^31 - 1) * Frac[as(2^-31 + 2^-2(31) + 2^-3(31) + . . .)]
  124.  *      = (2^31 - 1) * Frac{[(2^31)p + q] [2^-31 + 2^-2(31) + 2^-3(31) + . . 
  125. .]}
  126.  *      = (2^31 - 1) * Frac[p+(p+q)2^-31+(p+q)2^-2(31)+(p+q)3^(-31)+ . . .]
  127.  *
  128.  * if p+q < 2^31:
  129.  *   sn = (2^31 - 1) * Frac[p + a fraction + a fraction + a fraction + . . .]
  130.  *      = (2^31 - 1) * [(p+q)2^-31 + (p+q)2^-2(31) + (p+q)3^(-31) + . . .]
  131.  *      = p + q
  132.  *
  133.  * otherwise:
  134.  *   sn = (2^31 - 1) * Frac[p + 1.frac . . .]
  135.  *      = (2^31 - 1) * (-1 + 1.frac . . .)
  136.  *      = (2^31 - 1) * [-1 + (p+q)2^-31 + (p+q)2^-2(31) + (p+q)3^(-31) + . . .]
  137.  *      = p + q - 2^31 + 1
  138.  */
  139.  
  140. #define A 16807L /* multiplier, 7**5 */
  141. #define M 2147483647L /* modulus, 2**31 - 1; both used in random */
  142. #define INVERSE_M ((double)4.656612875e-10) /* (1.0/(double)M) */
  143. long
  144. RNGImplementation::next()
  145. {
  146. long L, H;
  147. L = A * (seed_ & 0xffff);
  148. H = A * (seed_ >> 16);
  149. seed_ = ((H & 0x7fff) << 16) + L;
  150. seed_ -= 0x7fffffff;
  151. seed_ += H >> 15;
  152. if (seed_ <= 0) {
  153. seed_ += 0x7fffffff;
  154. }
  155. return(seed_);
  156. }
  157. double
  158. RNGImplementation::next_double()
  159. {
  160. long i = next();
  161. return i * INVERSE_M;
  162. }
  163. #endif /* OLD_RNG */
  164. /*
  165.  * RNG implements a nice front-end around RNGImplementation
  166.  */
  167. #ifndef stand_alone
  168. static class RNGClass : public TclClass {
  169. public:
  170. RNGClass() : TclClass("RNG") {}
  171. TclObject* create(int, const char*const*) {
  172. return(new RNG());
  173. }
  174. } class_rng;
  175. #endif /* stand_alone */
  176. /* default RNG */
  177. RNG* RNG::default_ = NULL;
  178. double
  179. RNG::normal(double avg, double std)
  180. {
  181.         static int parity = 0;
  182.         static double nextresult;
  183.         double sam1, sam2, rad;
  184.    
  185.         if (std == 0) return avg;
  186.         if (parity == 0) {
  187.                 sam1 = 2*uniform() - 1;
  188.                 sam2 = 2*uniform() - 1;
  189.                 while ((rad = sam1*sam1 + sam2*sam2) >= 1) {
  190.                         sam1 = 2*uniform() - 1;
  191.                         sam2 = 2*uniform() - 1;
  192.                 }
  193.                 rad = sqrt((-2*log(rad))/rad);
  194.                 nextresult = sam2 * rad;
  195.                 parity = 1;
  196.                 return (sam1 * rad * std + avg);
  197.         }
  198.         else {
  199.                 parity = 0;
  200.                 return (nextresult * std + avg);
  201.         }
  202. }
  203. #ifndef stand_alone
  204. int
  205. RNG::command(int argc, const char*const* argv)
  206. {
  207. Tcl& tcl = Tcl::instance();
  208. if (argc == 3) {
  209. if (strcmp(argv[1], "testint") == 0) {
  210. int n = atoi(argv[2]);
  211. tcl.resultf("%d", uniform(n));
  212. return (TCL_OK);
  213. }
  214. if (strcmp(argv[1], "testdouble") == 0) {
  215. double d = atof(argv[2]);
  216. tcl.resultf("%6e", uniform(d));
  217. return (TCL_OK);
  218. }
  219. if (strcmp(argv[1], "seed") == 0) {
  220. int s = atoi(argv[2]);
  221. // NEEDSWORK: should be a way to set seed to PRDEF_SEED_SORUCE
  222. if (s) {
  223. if (s <= 0 || (unsigned int)s >= MAXINT) {
  224. // MAXINT on freebsd is a ``black hole'' (it says at MAXINT).
  225. tcl.resultf("Setting random number seed to known bad value.");
  226. return TCL_ERROR;
  227. };
  228. set_seed(RAW_SEED_SOURCE, s);
  229. } else set_seed(HEURISTIC_SEED_SOURCE, 0);
  230. return(TCL_OK);
  231. }
  232. }else if (argc == 2) {
  233. if (strcmp(argv[1], "next-random") == 0) {
  234. tcl.resultf("%u", uniform_positive_int());
  235. return(TCL_OK);
  236. }
  237. if (strcmp(argv[1], "seed") == 0) {
  238. #ifdef OLD_RNG
  239. tcl.resultf("%u", stream_.seed());
  240. #else
  241. tcl.resultf("%u", seed());
  242. #endif /* OLD_RNG */
  243. return(TCL_OK);
  244. }
  245. #ifndef OLD_RNG
  246. if (strcmp (argv[1], "next-substream") == 0) {
  247. reset_next_substream();
  248. return (TCL_OK);
  249. }
  250. if (strcmp (argv[1], "all-seeds") == 0) {
  251. unsigned long seeds[6];
  252. get_state (seeds);
  253. tcl.resultf ("%lu %lu %lu %lu %lu %lu",
  254.      seeds[0], seeds[1], seeds[2], 
  255.      seeds[3], seeds[4], seeds[5]);
  256. return (TCL_OK);
  257. }
  258. if (strcmp (argv[1], "reset-start-substream") == 0) {
  259. reset_start_substream();
  260. return (TCL_OK);
  261. }
  262. #endif /* !OLD_RNG */
  263. if (strcmp(argv[1], "default") == 0) {
  264. default_ = this;
  265. return(TCL_OK);
  266. }
  267. #if 0
  268. if (strcmp(argv[1], "test") == 0) {
  269. if (test())
  270. tcl.resultf("RNG test failed");
  271. else
  272. tcl.resultf("RNG test passed");
  273. return(TCL_OK);
  274. }
  275. #endif
  276. } else if (argc == 4) {
  277.                 if (strcmp(argv[1], "seed") == 0) {
  278.                         int s = atoi(argv[3]);
  279.                         if (strcmp(argv[2], "raw") == 0) {
  280.                                 set_seed(RNG::RAW_SEED_SOURCE, s);
  281.                         } else if (strcmp(argv[2], "predef") == 0) {
  282.                                 set_seed(RNG::PREDEF_SEED_SOURCE, s);
  283.                                 // s is the index in predefined seed array
  284.                                 // 0 <= s < 64
  285.                         } else if (strcmp(argv[2], "heuristic") == 0) {
  286.                                 set_seed(RNG::HEURISTIC_SEED_SOURCE, 0);
  287.                         }
  288.                         return(TCL_OK);
  289.                 }
  290.                 if (strcmp(argv[1], "normal") == 0) {
  291.                         double avg = strtod(argv[2], NULL);
  292.                         double std = strtod(argv[3], NULL);
  293.                         tcl.resultf("%g", normal(avg, std));
  294.                         return (TCL_OK);
  295.                 }
  296.                 if (strcmp(argv[1], "lognormal") == 0) {
  297.                         double avg = strtod(argv[2], NULL);
  298.                         double std = strtod(argv[3], NULL);
  299.                         tcl.resultf("%g", lognormal(avg, std));
  300.                         return (TCL_OK);
  301.                 }
  302. }
  303. return(TclObject::command(argc, argv));
  304. }
  305. #endif /* stand_alone */
  306. void
  307. RNG::set_seed(RNGSources source, int seed)
  308. {
  309. /* The following predefined seeds are evenly spaced around
  310.  * the 2^31 cycle.  Each is approximately 33,000,000 elements
  311.  * apart.
  312.  */
  313. #define N_SEEDS_ 64
  314. static long predef_seeds[N_SEEDS_] = {
  315. 1973272912L,  188312339L, 1072664641L,  694388766L,
  316. 2009044369L,  934100682L, 1972392646L, 1936856304L,
  317. 1598189534L, 1822174485L, 1871883252L,  558746720L,
  318. 605846893L, 1384311643L, 2081634991L, 1644999263L,
  319. 773370613L,  358485174L, 1996632795L, 1000004583L,
  320. 1769370802L, 1895218768L,  186872697L, 1859168769L,
  321. 349544396L, 1996610406L,  222735214L, 1334983095L,
  322. 144443207L,  720236707L,  762772169L,  437720306L,
  323. 939612284L,  425414105L, 1998078925L,  981631283L,
  324. 1024155645L,  822780843L,  701857417L,  960703545L,
  325. 2101442385L, 2125204119L, 2041095833L,   89865291L,
  326. 898723423L, 1859531344L,  764283187L, 1349341884L,
  327. 678622600L,  778794064L, 1319566104L, 1277478588L,
  328. 538474442L,  683102175L,  999157082L,  985046914L,
  329. 722594620L, 1695858027L, 1700738670L, 1995749838L,
  330. 1147024708L,  346983590L,  565528207L,  513791680L
  331. };
  332. static long heuristic_sequence = 0;
  333. switch (source) {
  334. case RAW_SEED_SOURCE:
  335. if (seed <= 0 || (unsigned int)seed >= MAXINT) // Wei Ye
  336. abort();
  337. // use it as it is
  338. break;
  339. case PREDEF_SEED_SOURCE:
  340. if (seed < 0 || seed >= N_SEEDS_)
  341. abort();
  342. seed = predef_seeds[seed];
  343. break;
  344. case HEURISTIC_SEED_SOURCE:
  345. timeval tv;
  346. gettimeofday(&tv, 0);
  347. heuristic_sequence++;   // Always make sure we're different than last time.
  348. seed = (tv.tv_sec ^ tv.tv_usec ^ (heuristic_sequence << 8)) & 0x7fffffff;
  349. break;
  350. };
  351. // set it
  352. // NEEDSWORK: should we throw out known bad seeds?
  353. // (are there any?)
  354. if (seed < 0)
  355. seed = -seed;
  356. #ifdef OLD_RNG
  357. stream_.set_seed(seed);
  358. #else
  359. set_seed(seed);
  360. #endif /* OLD_RNG */
  361. // Toss away the first few values of heuristic seed.
  362. // In practice this makes sequential heuristic seeds
  363. // generate different first values.
  364. //
  365. // How many values to throw away should be the subject
  366. // of careful analysis.  Until then, I just throw away
  367. // ``a bunch''.  --johnh
  368. if (source == HEURISTIC_SEED_SOURCE) {
  369. int i;
  370. for (i = 0; i < 128; i++) {
  371. #ifdef OLD_RNG
  372. stream_.next();
  373. #else
  374. next();
  375. #endif /* OLD_RNG */
  376. };
  377. };
  378. }
  379. /*
  380.  * RNGTest:
  381.  * Make sure the RNG makes known values.
  382.  * Optionally, print out some stuff.
  383.  *
  384.  * Simple test program:
  385.  *
  386.  * gcc rng.cc -Drng_stand_alone -o rng_test -lm
  387.  *
  388.  */
  389. #ifdef rng_stand_alone
  390. int main() { RNGTest test; test.verbose(); }
  391. #endif
  392. #ifdef rng_test
  393. RNGTest::RNGTest()
  394. {
  395. RNG rng(RNG::RAW_SEED_SOURCE, 1L);
  396. int i;
  397. long r;
  398. for (i = 0; i < 10000; i++) 
  399. r = rng.uniform_positive_int();
  400. #ifdef OLD_RNG
  401. if (r != 1043618065L) {
  402. fprintf (stderr, "r (%lu) != 1043618065Ln", r);
  403. abort();
  404. }
  405. #else
  406.   if (r != 582989707L) {
  407.   fprintf (stderr, "r (%lu) != 582989707n", r);
  408.   abort();
  409.   }
  410. #endif /* OLD_RNG */
  411. for (i = 10000; i < 551246; i++)
  412. r = rng.uniform_positive_int();
  413. #ifdef OLD_RNG
  414. if (r != 1003L) {
  415. fprintf (stderr, "r (%lu) != 1003Ln", r);
  416. abort();
  417. }
  418. #else
  419.   if (r != 1625334359L) {
  420.   fprintf (stderr, "r (%lu) != 1625334359Ln", r);
  421.   abort();
  422.   }
  423. #endif /* OLD_RNG */
  424. }
  425. void
  426. RNGTest::first_n(RNG::RNGSources source, long seed, int n)
  427. {
  428. RNG rng(source, seed);
  429. for (int i = 0; i < n; i++) {
  430. long r = rng.uniform_positive_int();
  431. printf("%10lu ", r);
  432. };
  433. printf("n");
  434. }
  435. void
  436. RNGTest::verbose()
  437. {
  438. printf ("default: ");
  439. first_n(RNG::RAW_SEED_SOURCE, 1L, 5);
  440. int i;
  441. for (i = 0; i < 64; i++) {
  442. printf ("predef source %2u: ", i);
  443. first_n(RNG::PREDEF_SEED_SOURCE, i, 5);
  444. };
  445. printf("heuristic seeds should be different from each other and on each run.n");
  446. for (i = 0; i < 64; i++) {
  447. printf ("heuristic source %2u: ", i);
  448. first_n(RNG::HEURISTIC_SEED_SOURCE, i, 5);
  449. };
  450. }
  451. #endif /* rng_test */
  452. #ifndef OLD_RNG
  453. namespace 
  454. const double m1 = 4294967087.0; 
  455. const double m2 = 4294944443.0; 
  456. const double norm = 1.0 / (m1 + 1.0); 
  457. const double a12 = 1403580.0; 
  458. const double a13n = 810728.0; 
  459. const double a21 = 527612.0; 
  460. const double a23n = 1370589.0; 
  461. const double two17 = 131072.0; 
  462. const double two53 = 9007199254740992.0; 
  463. const double fact = 5.9604644775390625e-8; /* 1 / 2^24 */ 
  464. // The following are the transition matrices of the two MRG 
  465. // components (in matrix form), raised to the powers -1, 1, 
  466. // 2^76, and 2^127, resp. 
  467. const double InvA1[3][3] = { // Inverse of A1p0 
  468. { 184888585.0, 0.0, 1945170933.0 }, 
  469. { 1.0, 0.0, 0.0 }, 
  470. { 0.0, 1.0, 0.0 } 
  471. }; 
  472. const double InvA2[3][3] = { // Inverse of A2p0 
  473. { 0.0, 360363334.0, 4225571728.0 }, 
  474. { 1.0, 0.0, 0.0 }, 
  475. { 0.0, 1.0, 0.0 } 
  476. }; 
  477. const double A1p0[3][3] = { 
  478. { 0.0, 1.0, 0.0 }, 
  479. { 0.0, 0.0, 1.0 }, 
  480. { -810728.0, 1403580.0, 0.0 } 
  481. }; 
  482. const double A2p0[3][3] = { 
  483. { 0.0, 1.0, 0.0 }, 
  484. { 0.0, 0.0, 1.0 }, 
  485. { -1370589.0, 0.0, 527612.0 } 
  486. }; 
  487. const double A1p76[3][3] = { 
  488. { 82758667.0, 1871391091.0, 4127413238.0 }, 
  489. { 3672831523.0, 69195019.0, 1871391091.0 }, 
  490. { 3672091415.0, 3528743235.0, 69195019.0 } 
  491. }; 
  492. const double A2p76[3][3] = { 
  493. { 1511326704.0, 3759209742.0, 1610795712.0 }, 
  494. { 4292754251.0, 1511326704.0, 3889917532.0 }, 
  495. { 3859662829.0, 4292754251.0, 3708466080.0 } 
  496. }; 
  497. const double A1p127[3][3] = { 
  498. { 2427906178.0, 3580155704.0, 949770784.0 }, 
  499. { 226153695.0, 1230515664.0, 3580155704.0 }, 
  500. { 1988835001.0, 986791581.0, 1230515664.0 } 
  501. }; 
  502. const double A2p127[3][3] = { 
  503. { 1464411153.0, 277697599.0, 1610723613.0 }, 
  504. { 32183930.0, 1464411153.0, 1022607788.0 }, 
  505. { 2824425944.0, 32183930.0, 2093834863.0 } 
  506. }; 
  507. //------------------------------------------------------------------- 
  508. // Return (a*s + c) MOD m; a, s, c and m must be < 2^35 
  509. // 
  510. double MultModM (double a, double s, double c, double m) 
  511. double v; 
  512. long a1; 
  513. v=a*s+c; 
  514. if (v >= two53 || v <= -two53) { 
  515. a1 = static_cast<long> (a / two17); a -= a1 * two17; 
  516. v =a1*s; 
  517. a1 = static_cast<long> (v / m); v -= a1 * m; 
  518. v = v * two17 + a * s + c; 
  519. a1 = static_cast<long> (v / m); 
  520. /* in case v < 0)*/ 
  521. if ((v -= a1 * m) < 0.0) return v += m; else return v; 
  522. //------------------------------------------------------------------- 
  523. // Compute the vector v = A*s MOD m. Assume that -m < s[i] < m. 
  524. // Works also when v = s. 
  525. // 
  526. void MatVecModM (const double A[3][3], const double s[3], double v[3], 
  527.  double m) 
  528. int i; 
  529. double x[3]; // Necessary if v = s 
  530. for (i = 0; i < 3; ++i) { 
  531. x[i] = MultModM (A[i][0], s[0], 0.0, m); 
  532. x[i] = MultModM (A[i][1], s[1], x[i], m); 
  533. x[i] = MultModM (A[i][2], s[2], x[i], m); 
  534. for (i = 0; i < 3; ++i) 
  535. v[i] = x[i]; 
  536. //------------------------------------------------------------------- 
  537. // Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m. 
  538. // Note: works also if A = C or B = C or A = B = C. 
  539. // 
  540. void MatMatModM (const double A[3][3], const double B[3][3], 
  541.  double C[3][3], double m) 
  542. int i, j; 
  543. double V[3], W[3][3]; 
  544. for (i = 0; i < 3; ++i) { 
  545. for (j = 0; j < 3; ++j) 
  546. V[j] = B[j][i]; 
  547. MatVecModM (A, V, V, m); 
  548. for (j = 0; j < 3; ++j) 
  549. W[j][i] = V[j]; 
  550. for (i = 0; i < 3; ++i) 
  551. for (j = 0; j < 3; ++j) 
  552. C[i][j] = W[i][j]; 
  553. //------------------------------------------------------------------- 
  554. // Compute the matrix B = (A^(2^e) Mod m); works also if A = B. 
  555. // 
  556. void MatTwoPowModM (const double A[3][3], double B[3][3], double m, 
  557.     long e) 
  558. int i, j; 
  559. /* initialize: B = A */ 
  560. if (A != B) { 
  561. for (i = 0; i < 3; ++i) 
  562. for (j = 0; j < 3; ++j) 
  563. B[i][j] = A[i][j]; 
  564. /* Compute B = A^(2^e) mod m */ 
  565. for (i = 0; i < e; i++) 
  566. MatMatModM (B, B, B, m); 
  567. //------------------------------------------------------------------- 
  568. // Compute the matrix B = (A^n Mod m); works even if A = B. 
  569. // 
  570. void MatPowModM (const double A[3][3], double B[3][3], double m, 
  571.  long n) 
  572. int i, j; 
  573. double W[3][3]; 
  574. /* initialize: W = A; B = I */ 
  575. for (i = 0; i < 3; ++i) 
  576. for (j = 0; j < 3; ++j) { 
  577. W[i][j] = A[i][j]; 
  578. B[i][j] = 0.0; 
  579. for (j = 0; j < 3; ++j) 
  580. B[j][j] = 1.0; 
  581. /* Compute B = A^n mod m using the binary decomposition of n */
  582. while (n > 0) { 
  583. if (n % 2) MatMatModM (W, B, B, m); 
  584. MatMatModM (W, W, W, m); 
  585. n/=2; 
  586. //-------------------------------------------------------------------- 
  587. // Check that the seeds are legitimate values. Returns 0 if legal 
  588. // seeds, -1 otherwise. 
  589. // 
  590. int CheckSeed (const unsigned long seed[6]) 
  591. int i; 
  592. for (i = 0; i < 3; ++i) { 
  593. if (seed[i] >= m1) { 
  594. fprintf (stderr, "****************************************nn");
  595. fprintf (stderr, "ERROR: Seed[%d] >= 4294967087, Seed is not set.", i);
  596. fprintf (stderr, "nn****************************************nn");
  597. return (-1); 
  598. for (i = 3; i < 6; ++i) { 
  599. if (seed[i] >= m2) { 
  600. fprintf (stderr, "****************************************nn");
  601. fprintf (stderr, "ERROR: Seed[%d] >= 429444443, Seed is not set.", i);
  602. fprintf (stderr, "nn****************************************nn");
  603. return (-1); 
  604. if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) { 
  605. fprintf (stderr, "****************************************nn");
  606. fprintf (stderr, "ERROR: First 3 seeds = 0.nn");
  607. fprintf (stderr, "****************************************nn");
  608. return (-1); 
  609. if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) { 
  610. fprintf (stderr, "****************************************nn");
  611. fprintf (stderr, "ERROR: Last 3 seeds = 0.nn");
  612. fprintf (stderr, "****************************************nn");
  613. return (-1); 
  614. return 0; 
  615. } // end of anonymous namespace 
  616. //------------------------------------------------------------------------- 
  617. // Generate the next random number. 
  618. // 
  619. double RNG::U01 () 
  620. long k; 
  621. double p1, p2, u; 
  622. /* Component 1 */ 
  623. p1 = a12 * Cg_[1] - a13n * Cg_[0]; 
  624. k = static_cast<long> (p1 / m1); 
  625. p1 -= k * m1; 
  626. if (p1 < 0.0) p1 += m1; 
  627. Cg_[0] = Cg_[1]; Cg_[1] = Cg_[2]; Cg_[2] = p1; 
  628. /* Component 2 */ 
  629. p2 = a21 * Cg_[5] - a23n * Cg_[3]; 
  630. k = static_cast<long> (p2 / m2); 
  631. p2 -= k * m2; 
  632. if (p2 < 0.0) p2 += m2; 
  633. Cg_[3] = Cg_[4]; Cg_[4] = Cg_[5]; Cg_[5] = p2; 
  634. /* Combination */ 
  635. u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm); 
  636. return (anti_ == false) ? u : (1 - u); 
  637. //------------------------------------------------------------------------- 
  638. // Generate the next random number with extended (53 bits) precision. 
  639. // 
  640. double RNG::U01d () 
  641. double u; 
  642. u = U01(); 
  643. if (anti_) { 
  644. // Don't forget that U01() returns 1 - u in 
  645. // the antithetic case 
  646. u += (U01() - 1.0) * fact; 
  647. return (u < 0.0) ? u + 1.0 : u; 
  648. } else { 
  649. u += U01() * fact; 
  650. return (u < 1.0) ? u : (u - 1.0); 
  651. //************************************************************************* 
  652. // Public members of the class start here 
  653. //------------------------------------------------------------------------- 
  654. /*
  655.  * Functions for backward compatibility:
  656.  *
  657.  *   RNG (long seed)
  658.  *   void set_seed (long seed)
  659.  *   long seed()
  660.  *   long next()
  661.  *   double next_double()
  662.  */
  663. RNG::RNG (long seed) 
  664. {
  665. set_seed (seed);
  666. init();
  667. }
  668. void RNG::init()
  669. {
  670. anti_ = false; 
  671. inc_prec_ = false; 
  672. /* Information on a stream. The arrays {Cg_, Bg_, Ig_} contain the
  673.    current state of the stream, the starting state of the current
  674.    SubStream, and the starting state of the stream. This stream
  675.    generates antithetic variates if anti_ = true. It also generates
  676.    numbers with extended precision (53 bits if machine follows IEEE
  677.    754 standard) if inc_prec_ = true. next_seed_ will be the seed of
  678.    the next declared RngStream. */
  679. for (int i = 0; i < 6; ++i) { 
  680. Bg_[i] = Cg_[i] = Ig_[i] = next_seed_[i]; 
  681. MatVecModM (A1p127, next_seed_, next_seed_, m1); 
  682. MatVecModM (A2p127, &next_seed_[3], &next_seed_[3], m2); 
  683. }
  684. void RNG::set_seed (long seed) 
  685. {
  686. unsigned long seed_vec[6] = {0, 0, 0, 0, 0, 0};
  687. for (int i=0; i<6; i++) {
  688. seed_vec[i] = (unsigned long) seed;
  689. }
  690. set_package_seed (seed_vec);
  691. init();
  692. }
  693. long RNG::seed() 
  694. {
  695. unsigned long seed[6];
  696. get_state(seed);
  697. return ((long) seed[0]);
  698. }
  699. long RNG::next()
  700. {
  701. return (rand_int(0, MAXINT));
  702. }
  703. double RNG::next_double()
  704. {
  705. return (rand_u01());
  706. }
  707. /* End of backward compatibility functions */
  708. // The default seed of the package; will be the seed of the first 
  709. // declared RNG, unless set_package_seed is called. 
  710. // 
  711. double RNG::next_seed_[6] = 
  712. 12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0 
  713. }; 
  714. //------------------------------------------------------------------------- 
  715. // constructor 
  716. // 
  717. RNG::RNG (const char *s) 
  718. if (strlen (s) > 99) {
  719. strncpy (name_, s, 99);
  720. name_[100] = 0;
  721. }
  722. else 
  723. strcpy (name_, s);
  724. init();
  725. }
  726. //------------------------------------------------------------------------- 
  727. // Reset Stream to beginning of Stream. 
  728. // 
  729. void RNG::reset_start_stream () 
  730. for (int i = 0; i < 6; ++i) 
  731. Cg_[i] = Bg_[i] = Ig_[i]; 
  732. //------------------------------------------------------------------------- 
  733. // Reset Stream to beginning of SubStream. 
  734. // 
  735. void RNG::reset_start_substream () 
  736. for (int i = 0; i < 6; ++i) 
  737. Cg_[i] = Bg_[i]; 
  738. //------------------------------------------------------------------------- 
  739. // Reset Stream to NextSubStream. 
  740. // 
  741. void RNG::reset_next_substream () 
  742. MatVecModM(A1p76, Bg_, Bg_, m1); 
  743. MatVecModM(A2p76, &Bg_[3], &Bg_[3], m2); 
  744. for (int i = 0; i < 6; ++i) 
  745. Cg_[i] = Bg_[i]; 
  746. //------------------------------------------------------------------------- 
  747. void RNG::set_package_seed (const unsigned long seed[6]) 
  748. if (CheckSeed (seed)) 
  749. abort();
  750. for (int i = 0; i < 6; ++i) 
  751. next_seed_[i] = seed[i]; 
  752. //------------------------------------------------------------------------- 
  753. void RNG::set_seed (const unsigned long seed[6]) 
  754. if (CheckSeed (seed)) 
  755. abort();
  756. for (int i = 0; i < 6; ++i) 
  757. Cg_[i] = Bg_[i] = Ig_[i] = seed[i]; 
  758. //------------------------------------------------------------------------- 
  759. // if e > 0, let n = 2^e + c; 
  760. // if e < 0, let n = -2^(-e) + c; 
  761. // if e = 0, let n = c. 
  762. // Jump n steps forward if n > 0, backwards if n < 0. 
  763. // 
  764. void RNG::advance_state (long e, long c) 
  765. double B1[3][3], C1[3][3], B2[3][3], C2[3][3]; 
  766. if (e > 0) { 
  767. MatTwoPowModM (A1p0, B1, m1, e); 
  768. MatTwoPowModM (A2p0, B2, m2, e); 
  769. } else if (e < 0) { 
  770. MatTwoPowModM (InvA1, B1, m1, -e); 
  771. MatTwoPowModM (InvA2, B2, m2, -e); 
  772. if (c >= 0) { 
  773. MatPowModM (A1p0, C1, m1, c); 
  774. MatPowModM (A2p0, C2, m2, c); 
  775. } else { 
  776. MatPowModM (InvA1, C1, m1, -c); 
  777. MatPowModM (InvA2, C2, m2, -c); 
  778. if (e) { 
  779. MatMatModM (B1, C1, C1, m1); 
  780. MatMatModM (B2, C2, C2, m2); 
  781. MatVecModM (C1, Cg_, Cg_, m1); 
  782. MatVecModM (C2, &Cg_[3], &Cg_[3], m2); 
  783. //------------------------------------------------------------------------- 
  784. void RNG::get_state (unsigned long seed[6]) const 
  785. for (int i = 0; i < 6; ++i) 
  786. seed[i] = static_cast<unsigned long> (Cg_[i]); 
  787. //------------------------------------------------------------------------- 
  788. void RNG::write_state () const 
  789. printf ("The current state of the Rngstream %s:n", name_);
  790. printf (" Cg_ = { ");
  791. for(int i=0;i<5;i++) { 
  792. printf ("%lu, ", (unsigned long) Cg_[i]);
  793. printf ("%lu }nn", (unsigned long) Cg_[5]);
  794. //------------------------------------------------------------------------- 
  795. void RNG::write_state_full () const 
  796. int i; 
  797. printf ("The RNG %s:n", name_);
  798. printf (" anti_ = %s", (anti_ ? "true" : "false")); 
  799. printf (" inc_prec_ = %sn", (inc_prec_ ? "true" : "false")); 
  800. printf (" Ig_ = { ");
  801. for (i = 0; i < 5; i++) { 
  802. printf ("%lu, ", (unsigned long) Ig_[i]);
  803. printf ("%lu }n", (unsigned long) Ig_[5]);
  804. printf (" Bg_ = { ");
  805. for (i = 0; i < 5; i++) { 
  806. printf ("%lu, ", (unsigned long) Bg_[i]);
  807. printf ("%lu }n", (unsigned long) Bg_[5]);
  808. printf (" Cg_ = { ");
  809. for (i = 0; i < 5; i++) { 
  810. printf ("%lu, ", (unsigned long) Cg_[i]);
  811. printf ("%lu }nn", (unsigned long) Cg_[5]);
  812. //------------------------------------------------------------------------- 
  813. void RNG::increased_precis (bool incp) 
  814. inc_prec_ = incp; 
  815. //------------------------------------------------------------------------- 
  816. void RNG::set_antithetic (bool a) 
  817. anti_ = a; 
  818. //------------------------------------------------------------------------- 
  819. // Generate the next random number. 
  820. // 
  821. double RNG::rand_u01 () 
  822. if (inc_prec_) 
  823. return U01d(); 
  824. else 
  825. return U01(); 
  826. //------------------------------------------------------------------------- 
  827. // Generate the next random integer. 
  828. // 
  829. long RNG::rand_int (long low, long high) 
  830. // return (long) low + (long) (((double) (high-low) * drn) + 0.5);
  831. return ((long) (low + (unsigned long) (((unsigned long) 
  832. (high-low+1)) * rand_u01())));
  833. }; 
  834. #endif /* !OLD_RNG */