00001 /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ 00002 /* 00003 * File: RngStream.h for multiple streams of Random Numbers 00004 * Copyright (C) 2001 Pierre L'Ecuyer (lecuyer@iro.umontreal.ca) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00019 * 02110-1301 USA 00020 * 00021 * Linking this random number generator statically or dynamically with 00022 * other modules is making a combined work based on this random number 00023 * generator. Thus, the terms and conditions of the GNU General Public 00024 * License cover the whole combination. 00025 * 00026 * In addition, as a special exception, the copyright holders of this 00027 * random number generator give you permission to combine this random 00028 * number generator program with free software programs or libraries 00029 * that are released under the GNU LGPL and with code included in the 00030 * standard release of ns-2 under the Apache 2.0 license or under 00031 * otherwise-compatible licenses with advertising requirements (or 00032 * modified versions of such code, with unchanged license). You may 00033 * copy and distribute such a system following the terms of the GNU GPL 00034 * for this random number generator and the licenses of the other code 00035 * concerned, provided that you include the source code of that other 00036 * code when and as the GNU GPL requires distribution of source code. 00037 * 00038 * Note that people who make modified versions of this random number 00039 * generator are not obligated to grant this special exception for 00040 * their modified versions; it is their choice whether to do so. 00041 * The GNU General Public License gives permission to release a 00042 * modified version without this exception; this exception also makes 00043 * it possible to release a modified version which carries forward 00044 * this exception. 00045 * 00046 * //Incorporated into rng.h and modified to maintain backward 00047 * //compatibility with ns-2.1b8. Users can use their current scripts 00048 * //unmodified with the new RNG. To get the same results as with the 00049 * //previous RNG, define OLD_RNG when compiling (e.g., 00050 * //make -D OLD_RNG). 00051 * // - Michele Weigle, University of North Carolina 00052 * // (mcweigle@cs.unc.edu) October 10, 2001 00053 * 00054 * "@(#) $Header: /cvsroot/nsnam/ns-2/tools/rng.h,v 1.26 2006/02/02 18:19:44 mweigle Exp $ (LBL)"; 00055 */ 00056 00057 /* new random number generator */ 00058 00059 #ifndef _rng_h_ 00060 #define _rng_h_ 00061 00062 00063 #ifdef rng_stand_alone 00064 #define stand_alone 00065 #define rng_test 00066 #endif 00067 00068 #include <math.h> 00069 #include <stdlib.h> // for atoi 00070 00071 #ifndef stand_alone 00072 #include "config.h" 00073 #endif /* stand_alone */ 00074 00075 #ifndef MAXINT 00076 #define MAXINT 2147483647 // XX [for now] 00077 #endif 00078 00079 #ifdef OLD_RNG 00080 /* 00081 * RNGImplementation is internal---do not use it, use RNG. 00082 */ 00083 class RNGImplementation { 00084 public: 00085 RNGImplementation(long seed = 1L) { 00086 seed_ = seed; 00087 }; 00088 void set_seed(long seed) { seed_ = seed; } 00089 long seed() { return seed_; } 00090 long next(); // return the next one 00091 double next_double(); 00092 private: 00093 long seed_; 00094 }; 00095 #endif /* OLD_RNG */ 00096 00097 /* 00098 * Use class RNG in real programs. 00099 */ 00100 class RNG 00101 #ifndef stand_alone 00102 : public TclObject 00103 #endif /* stand_alone */ 00104 { 00105 00106 public: 00107 enum RNGSources { RAW_SEED_SOURCE, PREDEF_SEED_SOURCE, HEURISTIC_SEED_SOURCE }; 00108 00109 #ifdef OLD_RNG 00110 RNG() : stream_(1L) {}; 00111 inline int seed() { return stream_.seed(); } 00112 #else 00113 RNG(const char* name = ""); 00114 RNG(long seed); 00115 void init(); 00116 long seed(); 00117 void set_seed (long seed); 00118 long next(); 00119 double next_double(); 00120 #endif /* OLD_RNG */ 00121 00122 RNG(RNGSources source, int seed = 1) { set_seed(source, seed); }; 00123 void set_seed(RNGSources source, int seed = 1); 00124 inline static RNG* defaultrng() { return (default_); } 00125 00126 #ifndef OLD_RNG 00127 /* 00128 * Added for new RNG 00129 */ 00130 static void set_package_seed (const unsigned long seed[6]); 00131 /* 00132 Sets the initial seed s 0 of the package to the six integers in the 00133 vector seed. The first 3 integers in the seed must all be less than 00134 m 1 = 4294967087, and not all 0; and the last 3 integers must all be 00135 less than m 2 = 4294944443, and not all 0. If this method is not 00136 called, the default initial seed is (12345, 12345, 12345, 12345, 00137 12345, 12345). 00138 */ 00139 00140 void reset_start_stream (); 00141 /* 00142 Reinitializes the stream to its initial state: C g and B g are set 00143 to I g 00144 */ 00145 00146 void reset_start_substream (); 00147 /* 00148 Reinitializes the stream to the beginning of its current substream: 00149 C g is set to B g. 00150 */ 00151 00152 void reset_next_substream (); 00153 /* 00154 Reinitializes the stream to the beginning of its next substream: N g 00155 is computed, and C g and B g are set to N g . 00156 */ 00157 00158 void set_antithetic (bool a); 00159 /* 00160 If a = true, the stream will start generating antithetic variates, 00161 i.e., 1 - U instead of U,until this method is called again with a = 00162 false. 00163 */ 00164 00165 void increased_precis (bool incp); 00166 /* 00167 After calling this method with incp = true, each call to the 00168 generator (direct or indirect) for this stream will return a uniform 00169 random number with more bits of resolution (53 bits if machine 00170 follows IEEE 754 standard) instead of 32 bits, and will advance the 00171 state of the stream by 2 steps instead of 1. More precisely, if s is 00172 a stream of the class RngStream, in the non antithetic case, the 00173 instruction ``u = s.RandU01()'' will be equivalent to ``u = 00174 (s.RandU01() + s.RandU01() * fact) % 1.0'' where the constant fact 00175 is equal to 2 -24 . This also applies when calling RandU01 00176 indirectly (e.g., via RandInt, etc.). By default, or if this method 00177 is called again with incp = false, each to call RandU01 for this 00178 stream advances the state by 1 step and returns a number with 32 00179 bits of resolution. 00180 */ 00181 00182 void set_seed (const unsigned long seed[6]); 00183 /* 00184 Sets the initial seed I g of the stream to the vector seed. The 00185 vector seed should contain valid seed values as described in 00186 SetPackageSeed. The state of the stream is then reset to this 00187 initial seed. The states and seeds of the other streams are not 00188 modified. As a result, after calling this method, the initial seeds 00189 of the streams are no longer spaced Z values apart. We discourage 00190 the use of this method; proper use of the Reset* methods is 00191 preferable. 00192 */ 00193 00194 void advance_state (long e, long c); 00195 /* 00196 Advances the state by n steps (see below for the meaning of n), 00197 without modifying the states of other streams or the values of B g 00198 and I g in the current object. If e > 0, then n =2 e + c;if e < 0, 00199 then n = -2 -e + c;and if e = 0,then n = c. Note:c is allowed to 00200 take negative values. We discourage the use of this method. 00201 */ 00202 00203 void get_state (unsigned long seed[6]) const; 00204 /* 00205 Returns in seed[0..5] the current state C g of this stream. This is 00206 convenient if we want to save the state for subsequent use. 00207 */ 00208 00209 void write_state () const; 00210 /* 00211 Writes (to standard output) the current state C g of this stream. 00212 */ 00213 00214 void write_state_full () const; 00215 /* 00216 Writes (to standard output) the value of all the internal variables 00217 of this stream: name, anti, incPrec, Ig, Bg, Cg. 00218 */ 00219 00220 double rand_u01 (); 00221 /* 00222 Normally, returns a (pseudo)random number from the uniform 00223 distribution over the interval (0, 1), after advancing the state by 00224 one step. The returned number has 32 bits of precision in the sense 00225 that it is always a multiple of 1/(2 32 - 208). However, if 00226 IncreasedPrecis(true) has been called for this stream, the state is 00227 advanced by two steps and the returned number has 53 bits of 00228 precision. 00229 */ 00230 00231 long rand_int (long i, long j); 00232 /* 00233 Returns a (pseudo)random number from the discrete uniform distribution 00234 over the integers {i, i +1,...,j}. Makes one call to RandU01. 00235 */ 00236 #endif /* !OLD_RNG */ 00237 00238 #ifndef stand_alone 00239 int command(int argc, const char*const* argv); 00240 #endif /* stand_alone */ 00241 00242 // These are primitive but maybe useful. 00243 inline int uniform_positive_int() { // range [0, MAXINT] 00244 #ifdef OLD_RNG 00245 return (int)(stream_.next()); 00246 #else 00247 return (int)(next()); 00248 #endif /* OLD_RNG */ 00249 } 00250 inline double uniform_double() { // range [0.0, 1.0) 00251 #ifdef OLD_RNG 00252 return stream_.next_double(); 00253 #else 00254 return next_double(); 00255 #endif /* OLD_RNG */ 00256 } 00257 00258 // these are for backwards compatibility 00259 // don't use them in new code 00260 inline int random() { return uniform_positive_int(); } 00261 inline double uniform() {return uniform_double();} 00262 00263 // these are probably what you want to use 00264 inline int uniform(int k) 00265 { return (uniform_positive_int() % (unsigned)k); } 00266 inline double uniform(double r) 00267 { return (r * uniform());} 00268 inline double uniform(double a, double b) 00269 { return (a + uniform(b - a)); } 00270 inline double exponential() 00271 { return (-log(uniform())); } 00272 inline double exponential(double r) 00273 { return (r * exponential());} 00274 // See "Wide-area traffic: the failure of poisson modeling", Vern 00275 // Paxson and Sally Floyd, IEEE/ACM Transaction on Networking, 3(3), 00276 // pp. 226-244, June 1995, on characteristics of counting processes 00277 // with Pareto interarrivals. 00278 inline double pareto(double scale, double shape) { 00279 // When 1 < shape < 2, its mean is scale**shape, its 00280 // variance is infinite. 00281 return (scale * (1.0/pow(uniform(), 1.0/shape))); 00282 } 00283 inline double paretoII(double scale, double shape) { 00284 return (scale * ((1.0/pow(uniform(), 1.0/shape)) - 1)); 00285 } 00286 double normal(double avg, double std); 00287 inline double lognormal(double avg, double std) { 00288 return (exp (normal(avg, std))); 00289 } 00290 00291 inline double rweibull(double shape, double scale) { 00292 return (pow (-log (uniform()), 1/shape) * scale); 00293 } 00294 inline double qweibull(double p, double shape, double scale) { 00295 return (pow (-log(1-p), 1/shape) * scale); 00296 } 00297 00298 #define LOG2 0.6931471806 00299 inline double logit(double x_) { 00300 return log(x_/(1-x_))/LOG2; 00301 } 00302 inline double logitinv(double x_) { 00303 return pow(2, x_)/(1+pow(2.0, x_)); 00304 } 00305 00306 /* 00307 Declarations for random variables used in PackMime 00308 Definitions are in packmime/packmime_HTTP_rng.cc 00309 */ 00310 double gammln(double xx); 00311 double pnorm(double q); 00312 double rnorm(); 00313 int rbernoulli(double p); 00314 double rgamma(double a, double scale); 00315 double exp_rand(); 00316 00317 protected: // need to be public? 00318 #ifdef OLD_RNG 00319 RNGImplementation stream_; 00320 #else 00321 double Cg_[6], Bg_[6], Ig_[6]; 00322 /* 00323 Vectors to store the current seed, the beginning of the current block 00324 (substream) and the beginning of the current stream. 00325 */ 00326 00327 bool anti_, inc_prec_; 00328 /* 00329 Variables to indicate whether to generate antithetic or increased 00330 precision random numbers. 00331 */ 00332 00333 char name_[100]; 00334 /* 00335 String to store the optional name of the current RngStream object. 00336 */ 00337 00338 static double next_seed_[6]; 00339 /* 00340 Static vector to store the beginning state of the next RngStream to 00341 be created (instantiated). 00342 */ 00343 00344 double U01 (); 00345 /* 00346 The backbone uniform random number generator. 00347 */ 00348 00349 double U01d (); 00350 /* 00351 The backbone uniform random number generator with increased 00352 precision. 00353 */ 00354 #endif /* OLD_RNG */ 00355 static RNG* default_; 00356 }; 00357 00358 /* 00359 * Create an instance of this class to test RNGImplementation. 00360 * Do .verbose() for even more. 00361 */ 00362 #ifdef rng_test 00363 class RNGTest { 00364 public: 00365 RNGTest(); 00366 void verbose(); 00367 void verbose_mil(); 00368 void first_n(RNG::RNGSources source, long seed, int n); 00369 void first_n_mil(RNG::RNGSources source, long seed, int n, FILE *out); 00370 }; 00371 #endif /* rng_test */ 00372 00373 #endif /* _rng_h_ */