1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
|
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* File: RngStream.h for multiple streams of Random Numbers
* Copyright (C) 2001 Pierre L'Ecuyer (lecuyer@iro.umontreal.ca)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Linking this random number generator statically or dynamically with
* other modules is making a combined work based on this random number
* generator. Thus, the terms and conditions of the GNU General Public
* License cover the whole combination.
*
* In addition, as a special exception, the copyright holders of this
* random number generator give you permission to combine this random
* number generator program with free software programs or libraries
* that are released under the GNU LGPL and with code included in the
* standard release of ns-2 under the Apache 2.0 license or under
* otherwise-compatible licenses with advertising requirements (or
* modified versions of such code, with unchanged license). You may
* copy and distribute such a system following the terms of the GNU GPL
* for this random number generator and the licenses of the other code
* concerned, provided that you include the source code of that other
* code when and as the GNU GPL requires distribution of source code.
*
* Note that people who make modified versions of this random number
* generator are not obligated to grant this special exception for
* their modified versions; it is their choice whether to do so.
* The GNU General Public License gives permission to release a
* modified version without this exception; this exception also makes
* it possible to release a modified version which carries forward
* this exception.
*
* Incorporated into rng.h and modified to maintain backward
* compatibility with ns-2.1b8. Users can use their current scripts
* unmodified with the new RNG. To get the same results as with the
* previous RNG, define OLD_RNG when compiling (e.g., make -D OLD_RNG).
* - Michele Weigle, University of North Carolina (mcweigle@cs.unc.edu)
* October 10, 2001
*
* "@(#) $Header: /cvsroot/nsnam/nam-1/rng.h,v 1.7 2007/02/12 07:18:09 tom_henderson Exp $ (LBL)";
*/
/* new random number generator */
#ifndef _rng_h_
#define _rng_h_
// Define rng_test to build the test harness.
#define rng_test
#include <math.h>
#include <stdlib.h> // for atoi
#ifndef rng_stand_alone
#include "config.h"
#endif /* rng_stand_alone */
#include <tclcl.h>
#ifndef MAXINT
#define MAXINT 2147483647 // XX [for now]
#endif
#ifdef OLD_RNG
/*
* RNGImplementation is internal---do not use it, use RNG.
*/
class RNGImplementation {
public:
RNGImplementation(long seed = 1L) {
seed_ = seed;
};
void set_seed(long seed) { seed_ = seed; }
long seed() { return seed_; }
long next(); // return the next one
double next_double();
private:
long seed_;
};
#endif /* OLD_RNG */
/*
* Use class RNG in real programs.
*/
class RNG
#ifndef rng_stand_alone
: public TclObject
#endif /* rng_stand_alone */
{
public:
enum RNGSources { RAW_SEED_SOURCE, PREDEF_SEED_SOURCE, HEURISTIC_SEED_SOURCE };
#ifdef OLD_RNG
RNG() : stream_(1L) {};
inline int seed() { return stream_.seed(); }
#else
RNG(const char* name = "");
RNG(long seed);
void init();
long seed();
void set_seed (long seed);
long next();
double next_double();
#endif /* OLD_RNG */
RNG(RNGSources source, int seed = 1) { set_seed(source, seed); };
void set_seed(RNGSources source, int seed = 1);
inline static RNG* defaultrng() { return (default_); }
#ifndef OLD_RNG
/*
* Added for new RNG
*/
static void set_package_seed (const unsigned long seed[6]);
/*
Sets the initial seed s 0 of the package to the six integers in the
vector seed. The first 3 integers in the seed must all be less than
m 1 = 4294967087, and not all 0; and the last 3 integers must all be
less than m 2 = 4294944443, and not all 0. If this method is not
called, the default initial seed is (12345, 12345, 12345, 12345,
12345, 12345).
*/
void reset_start_stream ();
/*
Reinitializes the stream to its initial state: C g and B g are set
to I g
*/
void reset_start_substream ();
/*
Reinitializes the stream to the beginning of its current substream:
C g is set to B g.
*/
void reset_next_substream ();
/*
Reinitializes the stream to the beginning of its next substream: N g
is computed, and C g and B g are set to N g .
*/
void set_antithetic (bool a);
/*
If a = true, the stream will start generating antithetic variates,
i.e., 1 - U instead of U,until this method is called again with a =
false.
*/
void increased_precis (bool incp);
/*
After calling this method with incp = true, each call to the
generator (direct or indirect) for this stream will return a uniform
random number with more bits of resolution (53 bits if machine
follows IEEE 754 standard) instead of 32 bits, and will advance the
state of the stream by 2 steps instead of 1. More precisely, if s is
a stream of the class RngStream, in the non antithetic case, the
instruction ``u = s.RandU01()'' will be equivalent to ``u =
(s.RandU01() + s.RandU01() * fact) % 1.0'' where the constant fact
is equal to 2 -24 . This also applies when calling RandU01
indirectly (e.g., via RandInt, etc.). By default, or if this method
is called again with incp = false, each to call RandU01 for this
stream advances the state by 1 step and returns a number with 32
bits of resolution.
*/
void set_seed (const unsigned long seed[6]);
/*
Sets the initial seed I g of the stream to the vector seed. The
vector seed should contain valid seed values as described in
SetPackageSeed. The state of the stream is then reset to this
initial seed. The states and seeds of the other streams are not
modified. As a result, after calling this method, the initial seeds
of the streams are no longer spaced Z values apart. We discourage
the use of this method; proper use of the Reset* methods is
preferable.
*/
void advance_state (long e, long c);
/*
Advances the state by n steps (see below for the meaning of n),
without modifying the states of other streams or the values of B g
and I g in the current object. If e > 0, then n =2 e + c;if e < 0,
then n = -2 -e + c;and if e = 0,then n = c. Note:c is allowed to
take negative values. We discourage the use of this method.
*/
void get_state (unsigned long seed[6]) const;
/*
Returns in seed[0..5] the current state C g of this stream. This is
convenient if we want to save the state for subsequent use.
*/
void write_state () const;
/*
Writes (to standard output) the current state C g of this stream.
*/
void write_state_full () const;
/*
Writes (to standard output) the value of all the internal variables
of this stream: name, anti, incPrec, Ig, Bg, Cg.
*/
double rand_u01 ();
/*
Normally, returns a (pseudo)random number from the uniform
distribution over the interval (0, 1), after advancing the state by
one step. The returned number has 32 bits of precision in the sense
that it is always a multiple of 1/(2 32 - 208). However, if
IncreasedPrecis(true) has been called for this stream, the state is
advanced by two steps and the returned number has 53 bits of
precision.
*/
long rand_int (long i, long j);
/*
Returns a (pseudo)random number from the discrete uniform distribution
over the integers {i, i +1,...,j}. Makes one call to RandU01.
*/
#endif /* !OLD_RNG */
#ifndef rng_stand_alone
int command(int argc, const char*const* argv);
#endif /* rng_stand_alone */
// These are primitive but maybe useful.
inline int uniform_positive_int() { // range [0, MAXINT]
#ifdef OLD_RNG
return (int)(stream_.next());
#else
return (int)(next());
#endif /* OLD_RNG */
}
inline double uniform_double() { // range [0.0, 1.0)
#ifdef OLD_RNG
return stream_.next_double();
#else
return next_double();
#endif /* OLD_RNG */
}
// these are for backwards compatibility
// don't use them in new code
inline int random() { return uniform_positive_int(); }
inline double uniform() {return uniform_double();}
// these are probably what you want to use
inline int uniform(int k)
{ return (uniform_positive_int() % (unsigned)k); }
inline double uniform(double r)
{ return (r * uniform());}
inline double uniform(double a, double b)
{ return (a + uniform(b - a)); }
inline double exponential()
{ return (-log(uniform())); }
inline double exponential(double r)
{ return (r * exponential());}
// See "Wide-area traffic: the failure of poisson modeling", Vern
// Paxson and Sally Floyd, IEEE/ACM Transaction on Networking, 3(3),
// pp. 226-244, June 1995, on characteristics of counting processes
// with Pareto interarrivals.
inline double pareto(double scale, double shape) {
// When 1 < shape < 2, its mean is scale**shape, its
// variance is infinite.
return (scale * (1.0/pow(uniform(), 1.0/shape)));
}
inline double paretoII(double scale, double shape) {
return (scale * ((1.0/pow(uniform(), 1.0/shape)) - 1));
}
double normal(double avg, double std);
inline double lognormal(double avg, double std)
{ return (exp(normal(avg, std))); }
protected: // need to be public?
#ifdef OLD_RNG
RNGImplementation stream_;
#else
double Cg_[6], Bg_[6], Ig_[6];
/*
Vectors to store the current seed, the beginning of the current block
(substream) and the beginning of the current stream.
*/
bool anti_, inc_prec_;
/*
Variables to indicate whether to generate antithetic or increased
precision random numbers.
*/
char name_[100];
/*
String to store the optional name of the current RngStream object.
*/
static double next_seed_[6];
/*
Static vector to store the beginning state of the next RngStream to
be created (instantiated).
*/
double U01 ();
/*
The backbone uniform random number generator.
*/
double U01d ();
/*
The backbone uniform random number generator with increased
precision.
*/
#endif /* OLD_RNG */
static RNG* default_;
};
/*
* Create an instance of this class to test RNGImplementation.
* Do .verbose() for even more.
*/
#ifdef rng_test
class RNGTest {
public:
RNGTest();
void verbose();
void first_n(RNG::RNGSources source, long seed, int n);
};
#endif /* rng_test */
#endif /* _rng_h_ */
|