rng.h

Go to the documentation of this file.
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: /nfs/jade/vint/CVSROOT/ns-2/tools/rng.h,v 1.25 2005/07/30 22:34:46 tomh 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 protected:   // need to be public?
00292 #ifdef OLD_RNG
00293     RNGImplementation stream_;
00294 #else
00295     double Cg_[6], Bg_[6], Ig_[6]; 
00296     /*
00297       Vectors to store the current seed, the beginning of the current block
00298       (substream) and the beginning of the current stream.
00299     */
00300 
00301     bool anti_, inc_prec_; 
00302     /*
00303       Variables to indicate whether to generate antithetic or increased
00304       precision random numbers.
00305     */
00306 
00307     char name_[100]; 
00308     /*
00309       String to store the optional name of the current RngStream object. 
00310     */
00311 
00312     static double next_seed_[6]; 
00313     /*
00314       Static vector to store the beginning state of the next RngStream to 
00315       be created (instantiated).
00316     */
00317 
00318     double U01 (); 
00319     /*
00320       The backbone uniform random number generator. 
00321     */
00322 
00323     double U01d (); 
00324     /*
00325       The backbone uniform random number generator with increased 
00326       precision. 
00327     */  
00328 #endif /* OLD_RNG */
00329     static RNG* default_;
00330 }; 
00331 
00332 /*
00333  * Create an instance of this class to test RNGImplementation.
00334  * Do .verbose() for even more.
00335  */
00336 #ifdef rng_test
00337 class RNGTest {
00338 public:
00339     RNGTest();
00340     void verbose();
00341     void verbose_mil();
00342     void first_n(RNG::RNGSources source, long seed, int n);
00343     void first_n_mil(RNG::RNGSources source, long seed, int n, FILE *out);
00344 };
00345 #endif /* rng_test */
00346 
00347 #endif /* _rng_h_ */

Generated on Tue Mar 6 16:47:50 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6