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