• Main Page
  • Classes
  • Files
  • File List

/Users/yzchen/ns/ns-allinone-2.33/ns-2.33/tools/rng.h

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_ */

Generated on Tue Aug 10 2010 16:16:08 for ns-2.33 by  doxygen 1.7.1