Logo Search packages:      
Sourcecode: nam version File versions  Download package


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

#ifdef OLD_RNG
 * RNGImplementation is internal---do not use it, use RNG.
class RNGImplementation {
      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();    
      long seed_;
#endif /* OLD_RNG */

 * Use class RNG in real programs.
class RNG
#ifndef rng_stand_alone
      : public TclObject
#endif  /* rng_stand_alone */

#ifdef OLD_RNG
      RNG() : stream_(1L) {};
      inline int seed() { return stream_.seed(); }
      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 =

      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

      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

      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());
            return (int)(next());
#endif /* OLD_RNG */
      inline double uniform_double() { // range [0.0, 1.0)
#ifdef OLD_RNG
            return stream_.next_double();
            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_;
      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 
#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 {
      void verbose();
      void first_n(RNG::RNGSources source, long seed, int n);
#endif /* rng_test */

#endif /* _rng_h_ */

Generated by  Doxygen 1.6.0   Back to index