Add random number files, base class Application
authorTom Henderson <tomh@tomh.org>
Sat, 17 Mar 2007 22:32:08 -0700
changeset 346 4a76f247e7dc
parent 341 126f5110aaf4
child 347 874c95c66c28
Add random number files, base class Application
SConstruct
src/core/random-variable.cc
src/core/random-variable.h
src/core/rng-stream.cc
src/core/rng-stream.h
src/node/application.cc
src/node/application.h
src/node/node-reference.h
--- a/SConstruct	Thu Mar 15 13:26:30 2007 +0100
+++ b/SConstruct	Sat Mar 17 22:32:08 2007 -0700
@@ -22,6 +22,8 @@
     'assert.cc',
     'ptr.cc',
     'test.cc',
+    'random-variable.cc',
+    'rng-stream.cc',
     ])
 env = Environment()
 if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin':
@@ -44,7 +46,9 @@
     'debug.h',
     'assert.h',
     'fatal-error.h',
-    'test.h'
+    'test.h',
+    'random-variable.h',
+    'rng-stream.h'
     ])
 
 def config_core (env, config):
@@ -184,6 +188,7 @@
     'udp-socket.cc',
     'udp.cc',
     'arp-header.cc',
+    'application.cc',
     'arp-cache.cc',
     'arp-ipv4-interface.cc',
     'arp.cc',
@@ -200,6 +205,7 @@
     'ipv4-checksum.h',
     'udp.h',
     'ipv4-l4-protocol.h',
+    'application.h',
     'arp-header.h',
     'arp-cache-cache.h',
     'arp.h',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/random-variable.cc	Sat Mar 17 22:32:08 2007 -0700
@@ -0,0 +1,574 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+#include <iostream>
+
+#include <math.h>
+#include <stdlib.h>
+#include <sys/time.h>			// for gettimeofday
+#include <unistd.h>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>       
+
+
+#include "random-variable.h"
+#include "rng-stream.h"
+#include "fatal-error.h"
+
+using namespace std;
+
+namespace ns3{
+// Seed methods
+
+Seed::~Seed()
+{
+}
+
+RandomSeed::RandomSeed()
+{
+}
+
+RandomSeed::~RandomSeed()
+{
+}
+
+bool RandomSeed::IsRandom() const 
+{
+  return true;
+}
+
+ConstantSeed::~ConstantSeed()
+{
+}
+
+bool ConstantSeed::IsRandom() const 
+{
+  return false;
+}
+
+ConstantSeed::ConstantSeed(uint32_t s)
+{
+  seeds[0] = s;
+  seeds[1] = s;
+  seeds[2] = s;
+  seeds[3] = s;
+  seeds[4] = s;
+  seeds[5] = s;
+}
+
+ConstantSeed::ConstantSeed(uint32_t s0, uint32_t s1, uint32_t s2,
+                           uint32_t s3, uint32_t s4, uint32_t s5)
+{
+  seeds[0] = s0;
+  seeds[1] = s1;
+  seeds[2] = s2;
+  seeds[3] = s3;
+  seeds[4] = s4;
+  seeds[5] = s5;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// RandomVariable methods
+
+bool          RandomVariable::initialized = false;   // True if RngStream seed set 
+bool          RandomVariable::useDevRandom = false;  // True if use /dev/random desired
+bool          RandomVariable::globalSeedSet = false; // True if GlobalSeed called
+int           RandomVariable::devRandom = -1;
+uint32_t        RandomVariable::globalSeed[6];
+unsigned long RandomVariable::heuristic_sequence;
+
+RandomVariable::RandomVariable() 
+{
+  m_generator = new RngStream();
+  RandomVariable::Initialize(); // sets the seed for the static object
+  m_generator->InitializeStream();
+}
+
+RandomVariable::~RandomVariable()
+{
+  delete m_generator;
+}
+
+uint32_t RandomVariable::GetIntValue() 
+{
+  return (uint32_t)GetValue();
+}
+
+void RandomVariable::UseDevRandom(bool udr) 
+{
+  RandomVariable::useDevRandom = udr;
+}
+
+bool RandomVariable::SetSeed(const Seed& s)
+{
+  // Seed this stream with the specified seed
+  if (s.IsRandom())
+    {
+      uint32_t seeds[6];
+      while(true)
+        { // Insure seeds are valid
+          GetRandomSeeds(seeds);
+          if (RngStream::CheckSeed(seeds)) break;
+        }
+      m_generator->SetSeeds(seeds);
+      return true;
+    }
+  // Not random seed, use specified
+  const ConstantSeed& cs = (ConstantSeed&)s;
+  if (!RngStream::CheckSeed(cs.seeds))
+    {
+      cout << "Constant seed failed valid check" << endl;
+      return false; // Seed is not valid
+    }
+  m_generator->SetSeeds(cs.seeds);
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// RandomVariable static methods
+void RandomVariable::UseGlobalSeed(const Seed& s)
+{
+  if (RandomVariable::globalSeedSet)
+    {
+      cout << "Random number generator already initialized!" << endl;
+      cout << "Call to RandomVariable::UseGlobalSeed() ignored" << endl;
+      return;
+    }
+  if (s.IsRandom()) return; // Random seed is the default
+  const ConstantSeed& cs = (ConstantSeed&)s;
+  RandomVariable::globalSeed[0] = cs.seeds[0];
+  RandomVariable::globalSeed[1] = cs.seeds[1];
+  RandomVariable::globalSeed[2] = cs.seeds[2];
+  RandomVariable::globalSeed[3] = cs.seeds[3];
+  RandomVariable::globalSeed[4] = cs.seeds[4];
+  RandomVariable::globalSeed[5] = cs.seeds[5];
+  if (!RngStream::CheckSeed(RandomVariable::globalSeed))
+  	NS_FATAL_ERROR("Invalid seed");
+  
+  RandomVariable::globalSeedSet = true;
+}
+
+void RandomVariable::Initialize()
+{ 
+  if (RandomVariable::initialized) return; // Already initialized and seeded
+  RandomVariable::initialized = true;
+  if (!RandomVariable::globalSeedSet)
+    { // No global seed, try a random one
+      GetRandomSeeds(globalSeed);
+    }
+  // Seed the RngStream package
+  RngStream::SetPackageSeed(globalSeed);
+}
+
+void RandomVariable::GetRandomSeeds(uint32_t seeds[6])
+{
+  // Check if /dev/random exists
+  if (RandomVariable::useDevRandom && RandomVariable::devRandom < 0)
+    {
+      RandomVariable::devRandom = open("/dev/random", O_RDONLY);
+    }
+  if (RandomVariable::devRandom > 0)
+    { // Use /dev/random
+      while(true)
+        {
+          for (int i = 0; i < 6; ++i)
+            {
+              read(RandomVariable::devRandom, &seeds[i], sizeof(seeds[i]));
+            }
+          if (RngStream::CheckSeed(seeds)) break; // Got a valid one
+        }
+    }
+  else
+    { // Seed from time of day (code borrowed from ns2 random seeding)
+      // Thanks to John Heidemann for this technique
+      while(true)
+        {
+          timeval tv;
+          gettimeofday(&tv, 0);
+          seeds[0] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
+              & 0x7fffffff;
+          gettimeofday(&tv, 0);
+          seeds[1] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
+              & 0x7fffffff;
+          gettimeofday(&tv, 0);
+          seeds[2] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
+              & 0x7fffffff;
+          gettimeofday(&tv, 0);
+          seeds[3] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
+              & 0x7fffffff;
+          gettimeofday(&tv, 0);
+          seeds[4] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
+              & 0x7fffffff;
+          gettimeofday(&tv, 0);
+          seeds[5] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
+              & 0x7fffffff;
+          if (RngStream::CheckSeed(seeds)) break; // Got a valid one
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// UniformVariable methods
+UniformVariable::UniformVariable() 
+  : m_min(0), m_max(1.0) { }
+  
+UniformVariable::UniformVariable(double s, double l) 
+  : m_min(s), m_max(l) { }
+
+UniformVariable::UniformVariable(const UniformVariable& c) 
+  : m_min(c.m_min), m_max(c.m_max) { }
+
+double UniformVariable::GetValue()
+{
+  return m_min + m_generator->RandU01() * (m_max - m_min);
+}
+
+RandomVariable* UniformVariable::Copy() const
+{
+  return new UniformVariable(*this);
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ConstantVariable methods
+ConstantVariable::ConstantVariable() 
+  : m_const(0) { }
+
+ConstantVariable::ConstantVariable(double c) 
+  : m_const(c) { };
+  
+ConstantVariable::ConstantVariable(const ConstantVariable& c) 
+  : m_const(c.m_const) { }
+
+void ConstantVariable::NewConstant(double c) 
+  { m_const = c;}
+  
+double ConstantVariable::GetValue()
+{
+  return m_const;
+}
+
+uint32_t ConstantVariable::GetIntValue()
+{
+  return (uint32_t)m_const;
+}
+
+RandomVariable* ConstantVariable::Copy() const
+{
+  return new ConstantVariable(*this);
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// SequentialVariable methods
+SequentialVariable::SequentialVariable(double f, double l, double i, uint32_t c)
+  : m_min(f), m_max(l), m_increment(ConstantVariable(i).Copy()), m_consecutive(c),
+    m_current(f), m_currentConsecutive(0)
+{
+}
+
+SequentialVariable::SequentialVariable(double f, double l, const RandomVariable& i, uint32_t c)
+  : m_min(f), m_max(l), m_increment(i.Copy()), m_consecutive(c),
+    m_current(f), m_currentConsecutive(0)
+{
+}
+
+SequentialVariable::SequentialVariable(const SequentialVariable& c)
+  : m_min(c.m_min), m_max(c.m_max),
+    m_increment(c.m_increment->Copy()), m_consecutive(c.m_consecutive),
+    m_current(c.m_current), m_currentConsecutive(c.m_currentConsecutive)
+{
+}
+
+double SequentialVariable::GetValue()
+{ // Return a sequential series of values
+  double r = m_current;
+  if (++m_currentConsecutive == m_consecutive)
+    { // Time to advance to next
+      m_currentConsecutive = 0;
+      m_current += m_increment->GetValue();
+      if (m_current >= m_max)
+        m_current = m_min + (m_current - m_max);
+    }
+  return r;
+}
+
+RandomVariable* SequentialVariable::Copy() const
+{
+  return new SequentialVariable(*this);
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ExponentialVariable methods
+ExponentialVariable::ExponentialVariable() 
+  : m_mean(1.0), m_bound(0) { }
+  
+ExponentialVariable::ExponentialVariable(double m) 
+  : m_mean(m), m_bound(0) { }
+  
+ExponentialVariable::ExponentialVariable(double m, double b) 
+  : m_mean(m), m_bound(b) { }
+  
+ExponentialVariable::ExponentialVariable(const ExponentialVariable& c) 
+  : m_mean(c.m_mean), m_bound(c.m_bound) { }
+
+double ExponentialVariable::GetValue()
+{
+  double r = -m_mean*log(m_generator->RandU01());
+  if (m_bound != 0 && r > m_bound) return m_bound;
+  return r;
+}
+
+RandomVariable* ExponentialVariable::Copy() const
+{
+  return new ExponentialVariable(*this);
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ParetoVariable methods
+ParetoVariable::ParetoVariable() 
+  : m_mean(1.0), m_shape(1.5), m_bound(0) { }
+
+ParetoVariable::ParetoVariable(double m) 
+  : m_mean(m), m_shape(1.5), m_bound(0) { }
+
+ParetoVariable::ParetoVariable(double m, double s) 
+    : m_mean(m), m_shape(s), m_bound(0) { }
+
+ParetoVariable::ParetoVariable(double m, double s, double b) 
+  : m_mean(m), m_shape(s), m_bound(b) { }
+
+ParetoVariable::ParetoVariable(const ParetoVariable& c) 
+  : m_mean(c.m_mean), m_shape(c.m_shape), m_bound(c.m_bound) { }
+
+double ParetoVariable::GetValue()
+{
+  double scale = m_mean * ( m_shape - 1.0) / m_shape;
+  double r = (scale * ( 1.0 / pow(m_generator->RandU01(), 1.0 / m_shape)));
+  if (m_bound != 0 && r > m_bound) return m_bound;
+  return r;
+}
+
+RandomVariable* ParetoVariable::Copy() const
+{
+  return new ParetoVariable(*this);
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// WeibullVariable methods
+WeibullVariable::WeibullVariable() : m_mean(1.0), m_alpha(1), m_bound(0) { }
+WeibullVariable::WeibullVariable(double m) 
+  : m_mean(m), m_alpha(1), m_bound(0) { }
+WeibullVariable::WeibullVariable(double m, double s) 
+  : m_mean(m), m_alpha(s), m_bound(0) { }
+WeibullVariable::WeibullVariable(double m, double s, double b) 
+  : m_mean(m), m_alpha(s), m_bound(b) { };
+WeibullVariable::WeibullVariable(const WeibullVariable& c) 
+  : m_mean(c.m_mean), m_alpha(c.m_alpha), m_bound(c.m_bound) { }
+
+double WeibullVariable::GetValue()
+{
+  double exponent = 1.0 / m_alpha;
+  double r = m_mean * pow( -log(m_generator->RandU01()), exponent);
+  if (m_bound != 0 && r > m_bound) return m_bound;
+  return r;
+}
+
+RandomVariable* WeibullVariable::Copy() const
+{
+  return new WeibullVariable(*this);
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// NormalVariable methods
+NormalVariable::NormalVariable() 
+  : m_mean(0.0), m_variance(1.0), m_bound(INFINITE_VALUE), m_nextValid(false){}
+
+NormalVariable::NormalVariable(double m, double v, double b)
+  : m_mean(m), m_variance(v), m_bound(b), m_nextValid(false) { }
+
+NormalVariable::NormalVariable(const NormalVariable& c)
+  : m_mean(c.m_mean), m_variance(c.m_variance), m_bound(c.m_bound) { }
+
+double NormalVariable::GetValue()
+{
+  if (m_nextValid)
+    { // use previously generated
+      m_nextValid = false;
+      return m_next;
+    }
+  while(1)
+    { // See Simulation Modeling and Analysis p. 466 (Averill Law)
+      // for algorithm
+      double u1 = m_generator->RandU01();
+      double u2 = m_generator->RandU01();;
+      double v1 = 2 * u1 - 1;
+      double v2 = 2 * u2 - 1;
+      double w = v1 * v1 + v2 * v2;
+      if (w <= 1.0)
+        { // Got good pair
+          double y = sqrt((-2 * log(w))/w);
+          m_next = m_mean + v2 * y * sqrt(m_variance);
+          if (fabs(m_next) > m_bound) m_next = m_bound * (m_next)/fabs(m_next);
+          m_nextValid = true;
+          double x1 = m_mean + v1 * y * sqrt(m_variance);
+          if (fabs(x1) > m_bound) x1 = m_bound * (x1)/fabs(x1);
+          return x1;
+        }
+    }
+}
+
+RandomVariable* NormalVariable::Copy() const
+{
+  return new NormalVariable(*this);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ValueCDF methods
+ValueCDF::ValueCDF() 
+  : value(0.0), cdf(0.0){ }
+ValueCDF::ValueCDF(double v, double c) 
+  : value(v), cdf(c) { }
+ValueCDF::ValueCDF(const ValueCDF& c) 
+  : value(c.value), cdf(c.cdf) { }
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// EmpiricalVariable methods
+EmpiricalVariable::EmpiricalVariable() 
+  : validated(false) { }
+
+EmpiricalVariable::EmpiricalVariable(const EmpiricalVariable& c) 
+  : validated(c.validated), emp(c.emp) { }
+
+EmpiricalVariable::~EmpiricalVariable() { }
+
+double EmpiricalVariable::GetValue()
+{ // Return a value from the empirical distribution
+  // This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
+  if (emp.size() == 0) return 0.0; // HuH? No empirical data
+  if (!validated) Validate();      // Insure in non-decreasing
+  double r = m_generator->RandU01();
+  if (r <= emp.front().cdf)return emp.front().value; // Less than first
+  if (r >= emp.back().cdf) return emp.back().value;  // Greater than last
+  // Binary search
+  std::vector<ValueCDF>::size_type bottom = 0;
+  std::vector<ValueCDF>::size_type top = emp.size() - 1;
+  while(1)
+    {
+      std::vector<ValueCDF>::size_type c = (top + bottom) / 2;
+      if (r >= emp[c].cdf && r < emp[c+1].cdf)
+        { // Found it
+          return Interpolate(emp[c].cdf, emp[c+1].cdf,
+                             emp[c].value, emp[c+1].value,
+                             r);
+        }
+      // Not here, adjust bounds
+      if (r < emp[c].cdf) top    = c - 1;
+      else                bottom = c + 1;
+    }
+}
+
+RandomVariable* EmpiricalVariable::Copy() const
+{
+  return new EmpiricalVariable(*this);
+}
+
+void EmpiricalVariable::CDF(double v, double c)
+{ // Add a new empirical datapoint to the empirical cdf
+  // NOTE.   These MUST be inserted in non-decreasing order
+  emp.push_back(ValueCDF(v, c));
+}
+
+void EmpiricalVariable::Validate()
+{
+  ValueCDF prior;
+  for (std::vector<ValueCDF>::size_type i = 0; i < emp.size(); ++i)
+    {
+      ValueCDF& current = emp[i];
+      if (current.value < prior.value || current.cdf < prior.cdf)
+        { // Error
+          cout << "Empirical Dist error,"
+               << " current value " << current.value
+               << " prior value "   << prior.value
+               << " current cdf "   << current.cdf
+               << " prior cdf "     << prior.cdf << endl;
+          NS_FATAL_ERROR("Empirical Dist error");
+        }
+      prior = current;
+    }
+  validated = true;
+}
+
+double EmpiricalVariable::Interpolate(double c1, double c2,
+                                double v1, double v2, double r)
+{ // Interpolate random value in range [v1..v2) based on [c1 .. r .. c2)
+  return (v1 + ((v2 - v1) / (c2 - c1)) * (r - c1));
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Integer EmpiricalVariable methods
+IntEmpiricalVariable::IntEmpiricalVariable() { }
+
+uint32_t IntEmpiricalVariable::GetIntValue()
+{
+  return (uint32_t)GetValue();
+}
+
+RandomVariable* IntEmpiricalVariable::Copy() const
+{
+  return new IntEmpiricalVariable(*this);
+}
+
+
+double IntEmpiricalVariable::Interpolate(double c1, double c2,
+                                   double v1, double v2, double r)
+{ // Interpolate random value in range [v1..v2) based on [c1 .. r .. c2)
+  return ceil(v1 + ((v2 - v1) / (c2 - c1)) * (r - c1));
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// DeterministicVariable
+DeterministicVariable::DeterministicVariable(double* d, uint32_t c)
+    : count(c), next(c), data(d)
+{ // Nothing else needed
+}
+
+DeterministicVariable::~DeterministicVariable() { }
+  
+double DeterministicVariable::GetValue()
+{
+  if (next == count) next = 0;
+  return data[next++];
+}
+
+RandomVariable* DeterministicVariable::Copy() const
+{
+  return new DeterministicVariable(*this);
+}
+
+}//namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/random-variable.h	Sat Mar 17 22:32:08 2007 -0700
@@ -0,0 +1,584 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+#ifndef __random_variable_h__
+#define __random_variable_h__
+
+#include <vector>
+#include <algorithm>
+
+
+#define INFINITE_VALUE 1e307
+namespace ns3{
+
+class RngStream;
+
+/**
+ * \brief Pure virtual base class for RNG seeds
+ */
+class Seed {
+  // Seed is used to seed the random number generator(s)
+  // This is a base class for RandomSeed and ConstantSeed
+public:
+  virtual ~Seed();
+  virtual bool IsRandom() const = 0;
+};
+
+/**
+ * \brief random RNG seeds
+ */
+class RandomSeed : public Seed {
+public:
+  RandomSeed();
+  ~RandomSeed();
+  bool IsRandom() const;
+};
+
+/**
+ * \brief constant RNG seeds
+ */
+class ConstantSeed : public Seed 
+{
+public:
+  ConstantSeed(uint32_t); // Use six copies of the specified value
+  ConstantSeed(uint32_t,uint32_t,uint32_t,uint32_t,uint32_t,uint32_t);  // Six seeds
+  bool IsRandom() const;
+  ~ConstantSeed();
+public:
+  uint32_t seeds[6];
+};
+
+/**
+ * \brief The basic RNG for NS-3.
+ *
+ * Note: The underlying random number generation method used
+ * by NS-3 is the RngStream code by Pierre L'Ecuyer at
+ * the University of Montreal.
+ * 
+ * NS-3 has a rich set of  random number generators.
+ * Class RandomVariable defines the base class functionalty
+ * required for all random number generators.  By default, the underlying
+ * generator is seeded with the time of day, and then deterministically
+ * creates a sequence of seeds for each subsequent generator that is created.
+ * The rest of the documentation outlines how to change this behavior.
+ */
+class RandomVariable { 
+
+public:
+  /**
+   * \brief Constructor for a random number generator with a random seed.
+   */
+  RandomVariable();
+  
+  /**
+   * \brief Destructor for a random number generator with a random seed.
+   */
+  virtual ~RandomVariable();
+  
+  /**
+   * \brief Returns a random double from the underlying distribution
+   * \return A floating point random value
+   */
+  virtual double  GetValue() = 0;     
+
+  /**
+   * \brief Returns a random integer integer from the underlying distribution
+   * \return  Integer cast of ::GetValue()
+   */
+  virtual uint32_t GetIntValue();
+
+  /**
+   * \return A copy of this object
+   */  
+  virtual RandomVariable*   Copy() const = 0;
+
+  /**
+   * \brief Use a private seed and private stream for this generator.
+   * 
+   * This function explicitly overrides all other seeding behavior for
+   * this object.  For example, even if another seeding method has been
+   * used (either by default or calls to UseDevRandom, UseGlobalSeed, etc.)
+   * a call to SetSeed explicitly re-seeds this generator. Example:
+   * \code
+   * UniformVariable x(0,10);//with no other code, defaults to time of day seed
+   * x.SetSeed(...); //overrides time of day seed
+   * \endcode
+   * \param s Seed to use.  Can either be a RandomSeed or ConstantSeed.
+   * \return true if valid seed.
+   */
+  bool SetSeed(const Seed& s);
+  
+  /**
+   * \brief Set seeding behavior
+   * 
+   * Specify whether the POSIX device /dev/random is to
+   * be used for seeding.  When this is used, the underlying
+   * generator is seeded with data from /dev/random instead of
+   * being seeded based upon the time of day.  For this to be effective,
+   * it must be called before the creation of the first instance of a 
+   * RandomVariable or subclass.  Example:
+   * \code
+   * RandomVariable::UseDevRandom();
+   * UniformVariable x(2,3);  //these are seeded randomly
+   * ExponentialVariable y(120); //etc
+   * \endcode
+   * \param udr True if /dev/random desired.
+   */
+  static  void UseDevRandom(bool udr = true);
+
+   /**
+   * \brief Use the global seed to force precisely reproducible results.
+   * It is often desirable to create a simulation that uses random
+   * numbers, while at the same time is completely reproducible.
+   * Specifying this set of six random seeds initializes the
+   * random number generator with the specified seed.
+   * Once this is set, all generators will produce fixed output
+   * from run to run.  This is because each time a new generator is created,
+   * the underlying RngStream deterministically creates a new seed based upon
+   * the old one, hence a "stream" of RNGs.  Example:
+   * \code
+   * RandomVariable::UseGlobalSeed(...);
+   * UniformVariable x(2,3);     //these will give the same output everytime
+   * ExponentialVariable y(120); //as long as the seed stays the same
+   * \endcode
+   * \param s
+   * \return True if seed is valid.
+   */ 
+  static void UseGlobalSeed(const Seed& s);
+
+private:
+  static bool initialized;     // True if package seed is set 
+  static void Initialize();    // Initialize  the RNG system
+  static void GetRandomSeeds(uint32_t seeds[6]);
+private:
+  static bool useDevRandom;    // True if using /dev/random desired
+  static bool globalSeedSet;   // True if global seed has been specified
+  static int  devRandom;       // File handle for /dev/random
+  static uint32_t globalSeed[6]; // The global seed to use
+protected:
+  static unsigned long heuristic_sequence;
+  RngStream* m_generator;  //underlying generator being wrapped
+};
+
+
+/**
+ * \brief The uniform distribution RNG for NS-3.
+ */
+class UniformVariable : public RandomVariable {
+public:
+  /**
+   * Creates a uniform random number generator in the
+   * range [0.0 .. 1.0)
+   */
+  UniformVariable();
+
+  /**
+   * Creates a uniform random number generator with the specified range
+   * \param s Low end of the range
+   * \param l High end of the range
+   */
+  UniformVariable(double s, double l);
+
+  UniformVariable(const UniformVariable& c);
+  
+  /**
+   * \return A value between low and high values specified by the constructor
+   */
+  virtual double GetValue();
+  virtual RandomVariable*  Copy() const;
+private:
+  double m_min;
+  double m_max;
+};
+
+/**
+ * \brief A random variable that returns a constant
+ * Class ConstantVariable defines a random number generator that
+ * returns the same value every sample.
+ */
+class ConstantVariable : public RandomVariable { 
+
+public:
+  /**
+   * \brief Construct a ConstantVariable RNG that returns zero every sample
+   */
+  ConstantVariable();
+  
+  /**
+   * Construct a ConstantVariable RNG that returns the specified value
+   * every sample.
+   * \param c Unchanging value for this RNG.
+   */
+  ConstantVariable(double c);
+
+
+  ConstantVariable(const ConstantVariable& c) ;
+
+  /**
+   * \brief Specify a new constant RNG for this generator.
+   * \param c New constant value for this RNG.
+   */
+  void    NewConstant(double c);
+
+  /**
+   * \return The constant value specified
+   */
+  virtual double  GetValue();
+  virtual uint32_t GetIntValue();
+  virtual RandomVariable*   Copy() const;
+private:
+  double m_const;
+};
+
+/**
+ * \brief Return a sequential list of values
+ * Class SequentialVariable defines a random number generator that
+ * returns a sequential sequence.  The sequence monotonically
+ * increases for a period, then wraps around to the low value 
+ * and begins monotonicaly increasing again.
+ */
+class SequentialVariable : public RandomVariable {
+
+public:
+  /**
+   * \brief Constructor for the SequentialVariable RNG.
+   * The four parameters define the sequence.  For example
+   * SequentialVariable(0,5,1,2) creates a RNG that has the sequence
+   * 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0 ...
+   * \param f First value of the sequence.
+   * \param l One more than the last value of the sequence.
+   * \param i Increment between sequence values
+   * \param c Number of times each member of the sequence is repeated
+   */
+  SequentialVariable(double f, double l, double i = 1, uint32_t c = 1);
+
+  /**
+   * \brief Constructor for the SequentialVariable RNG.
+   * Differs from the first only in that the increment parameter is a
+   * random variable
+   * \param f First value of the sequence.
+   * \param l One more than the last value of the sequence.
+   * \param i Reference to a Random variable for the sequence increment
+   * \param c Number of times each member of the sequence is repeated
+   */
+  SequentialVariable(double f, double l, const RandomVariable& i, uint32_t c = 1);
+
+  SequentialVariable(const SequentialVariable& c);
+  /**
+   * \return The next value in the Sequence
+   */
+  virtual double GetValue();
+  virtual RandomVariable*  Copy() const;
+private:
+  double m_min;
+  double m_max;
+  RandomVariable*  m_increment;
+  uint32_t  m_consecutive;
+  double m_current;
+  uint32_t  m_currentConsecutive;
+};
+
+/**
+ * \brief Exponentially Distributed random var
+ * ExponentialVariable defines a random variable with an exponential distribution
+ */
+class ExponentialVariable : public RandomVariable { 
+public:
+  /**
+   * Constructs an exponential random variable  with a mean
+   * value of 1.0.
+   */
+  ExponentialVariable();
+
+  /**
+   * \brief Constructs an exponential random variable with a specified mean
+   * \param m Mean value for the random variable
+   */
+  explicit ExponentialVariable(double m);
+
+  /**
+   * \brief Constructs an exponential random variable with spefified
+   * \brief mean and upper limit.
+   * Since exponential distributions can theoretically return unbounded values,
+   * it is sometimes useful to specify a fixed upper limit.  Note however when
+   * the upper limit is specified, the true mean of the distribution is 
+   * slightly smaller than the mean value specified.
+   * \param m Mean value of the random variable
+   * \param b Upper bound on returned values
+   */
+  ExponentialVariable(double m, double b);
+
+  ExponentialVariable(const ExponentialVariable& c);
+  
+  /**
+   * \return A random value from this exponential distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariable* Copy() const;
+private:
+  double m_mean;  // Mean value of RV
+  double m_bound; // Upper bound on value (if non-zero)
+};
+
+/**
+ * \brief ParetoVariable distributed random var
+ */
+class ParetoVariable : public RandomVariable { // 
+public:
+  /**
+   * Constructs a pareto random variable with a mean of 1 and a shape
+   * parameter of 1.5
+   */
+  ParetoVariable();
+
+  /**
+   * Constructs a pareto random variable with specified mean and shape
+   * parameter of 1.5
+   * \param m Mean value of the distribution
+   */
+  explicit ParetoVariable(double m);
+
+  /**
+   * Constructs a pareto random variable with the specified mean value and
+   * shape parameter.
+   * \param m Mean value of the distribution
+   * \param s Shape parameter for the distribution
+   */
+  ParetoVariable(double m, double s);
+
+  /**
+   * \brief Constructs a pareto random variable with the specified mean
+   * \brief value, shape (alpha), and upper bound.
+   * Since pareto distributions can theoretically return unbounded values,
+   * it is sometimes useful to specify a fixed upper limit.  Note however
+   * when the upper limit is specified, the true mean of the distribution
+   * is slightly smaller than the mean value specified.
+   * \param m Mean value
+   * \param s Shape parameter
+   * \param b Upper limit on returned values
+   */
+  ParetoVariable(double m, double s, double b);
+
+  ParetoVariable(const ParetoVariable& c);
+  
+  /**
+   * \return A random value from this Pareto distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariable* Copy() const;
+private:
+  double m_mean;  // Mean value of RV
+  double m_shape; // Shape parameter
+  double m_bound; // Upper bound on value (if non-zero)
+};
+
+/**
+ * \brief WeibullVariable distributed random var
+ */
+class WeibullVariable : public RandomVariable {
+public:
+  /**
+   * Constructs a weibull random variable  with a mean
+   * value of 1.0 and a shape (alpha) parameter of 1
+   */
+  WeibullVariable();
+
+
+  /**
+   * Constructs a weibull random variable with the specified mean
+   * value and a shape (alpha) parameter of 1.5.
+   * \param m mean value of the distribution
+   */
+   WeibullVariable(double m) ;
+
+  /**
+   * Constructs a weibull random variable with the specified mean
+   * value and a shape (alpha).
+   * \param m Mean value for the distribution.
+   * \param s Shape (alpha) parameter for the distribution.
+   */
+  WeibullVariable(double m, double s);
+
+   /**
+   * \brief Constructs a weibull random variable with the specified mean
+   * \brief value, shape (alpha), and upper bound.
+   * Since WeibullVariable distributions can theoretically return unbounded values,
+   * it is sometimes usefull to specify a fixed upper limit.  Note however
+   * that when the upper limit is specified, the true mean of the distribution
+   * is slightly smaller than the mean value specified.
+   * \param m Mean value for the distribution.
+   * \param s Shape (alpha) parameter for the distribution.
+   * \param b Upper limit on returned values
+   */
+  WeibullVariable(double m, double s, double b);
+
+  WeibullVariable(const WeibullVariable& c);
+  
+  /**
+   * \return A random value from this Weibull distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariable* Copy() const;
+private:
+  double m_mean;  // Mean value of RV
+  double m_alpha; // Shape parameter
+  double m_bound; // Upper bound on value (if non-zero)
+};
+
+/**
+ * Class NormalVariable defines a random variable with a
+ * normal (Gaussian) distribution.
+ */
+class NormalVariable : public RandomVariable { // Normally Distributed random var
+
+public:
+  /**
+   * Constructs an normal random variable  with a mean
+   * value of 0 and variance of 1.
+   */ 
+  NormalVariable();
+
+
+  /**
+   * \brief Construct a normal random variable with specified mean and variance
+   * \param m Mean value
+   * \param v Variance
+   * \param b Bound.  The NormalVariable is bounded within +-bound.
+   */ 
+  NormalVariable(double m, double v, double b = INFINITE_VALUE);
+
+  NormalVariable(const NormalVariable& c);
+  
+  /**
+   * \return A value from this normal distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariable* Copy() const;
+private:
+  double m_mean;      // Mean value of RV
+  double m_variance;  // Mean value of RV
+  double m_bound;     // Bound on value (absolute value)
+  bool     m_nextValid; // True if next valid
+  double m_next;      // The algorithm produces two values at a time
+};
+
+// Value/CDF pair class for Emiprical Distributions
+//Doc:ClassXRef
+class ValueCDF {
+public:
+  ValueCDF();
+  ValueCDF(double v, double c);
+  ValueCDF(const ValueCDF& c);
+  double value;
+  double    cdf;
+};
+
+/**
+ * \brief EmpiricalVariable distribution random var
+ * Defines a random variable  that has a specified, empirical 
+ * distribution.  The distribution is specified by a
+ * series of calls the the CDF member function, specifying a
+ * value and the probability that the function value is less than
+ * the specified value.  When values are requested,
+ * a uniform random variable is used to select a probabililty,
+ * and the return value is interpreted linerarly between the
+ * two appropriate points in the CDF
+ */
+class EmpiricalVariable : public RandomVariable {
+public:
+  /**
+   * Constructor for the EmpiricalVariable random variables.
+   */
+  explicit EmpiricalVariable();
+
+  virtual ~EmpiricalVariable();
+  EmpiricalVariable(const EmpiricalVariable& c);
+  /**
+   * \return A value from this empirical distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariable* Copy() const;
+  /**
+   * \brief Specifies a point in the empirical distribution
+   * \param v The function value for this point
+   * \param c Probability that the function is less than or equal to v
+   */
+  virtual void CDF(double v, double c);  // Value, prob <= Value
+
+private:
+  virtual void Validate();  // Insure non-decreasing emiprical values
+  virtual double Interpolate(double, double, double, double, double);
+  bool validated; // True if non-decreasing validated
+  std::vector<ValueCDF> emp;       // Empicical CDF
+};
+
+/**
+ * Defines an empirical distribution where all values are integers.
+ * Indentical to {\tt EmpiricalVariable}, but with slightly different
+ * interpolation between points.
+ */
+class IntEmpiricalVariable : public EmpiricalVariable {
+public:
+
+  IntEmpiricalVariable();
+
+  virtual RandomVariable* Copy() const;
+  /**
+   * \return An integer value from this empirical distribution
+   */
+  virtual uint32_t GetIntValue();
+  virtual double Interpolate(double, double, double, double, double);
+};
+
+/**
+  * Defines a random variable  that has a specified, predetermined
+  * sequence.  This would be useful when trying to force
+  * the RNG to return a known sequence, perhaps to
+  * compare NS-3 to some other simulator
+  */
+class DeterministicVariable : public RandomVariable {
+
+public:
+  /**
+   * \brief Constructor
+   * Creates a generator that returns successive elements of the d array
+   * on successive calls to ::Value().  Note that the d pointer is copied
+   * for use by the generator (shallow-copy), not its contents, so the 
+   * contents of the array d points to have to remain unchanged for the use 
+   * of DeterministicVariable to be meaningful.
+   * \param d Pointer to array of random values to return in sequence
+   * \param c Number of values in the array
+   */
+  explicit DeterministicVariable(double* d, uint32_t c);
+
+  virtual ~DeterministicVariable();
+  /**
+   * \return The next value in the deterministic sequence
+   */
+  virtual double GetValue();
+  virtual RandomVariable* Copy() const;
+private:
+  uint32_t   count;
+  uint32_t   next;
+  double* data;
+};
+
+}//namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/rng-stream.cc	Sat Mar 17 22:32:08 2007 -0700
@@ -0,0 +1,468 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+//  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 version 2 as
+// published by the Free Software Foundation;
+//
+// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Modified for ns-3 by: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+#include <cstdlib>
+#include <iostream>
+#include "rng-stream.h"
+using namespace std;
+
+namespace
+{
+const double m1   =       4294967087.0;
+const double m2   =       4294944443.0;
+const double norm =       1.0 / (m1 + 1.0);
+const double a12  =       1403580.0;
+const double a13n =       810728.0;
+const double a21  =       527612.0;
+const double a23n =       1370589.0;
+const double two17 =      131072.0;
+const double two53 =      9007199254740992.0;
+const double fact =       5.9604644775390625e-8;     /* 1 / 2^24  */
+
+// The following are the transition matrices of the two MRG components
+// (in matrix form), raised to the powers -1, 1, 2^76, and 2^127, resp.
+
+const double InvA1[3][3] = {          // Inverse of A1p0
+       { 184888585.0,   0.0,  1945170933.0 },
+       {         1.0,   0.0,           0.0 },
+       {         0.0,   1.0,           0.0 }
+       };
+
+const double InvA2[3][3] = {          // Inverse of A2p0
+       {      0.0,  360363334.0,  4225571728.0 },
+       {      1.0,          0.0,           0.0 },
+       {      0.0,          1.0,           0.0 }
+       };
+
+const double A1p0[3][3] = {
+       {       0.0,        1.0,       0.0 },
+       {       0.0,        0.0,       1.0 },
+       { -810728.0,  1403580.0,       0.0 }
+       };
+
+const double A2p0[3][3] = {
+       {        0.0,        1.0,       0.0 },
+       {        0.0,        0.0,       1.0 },
+       { -1370589.0,        0.0,  527612.0 }
+       };
+
+const double A1p76[3][3] = {
+       {      82758667.0, 1871391091.0, 4127413238.0 },
+       {    3672831523.0,   69195019.0, 1871391091.0 },
+       {    3672091415.0, 3528743235.0,   69195019.0 }
+       };
+
+const double A2p76[3][3] = {
+       {    1511326704.0, 3759209742.0, 1610795712.0 },
+       {    4292754251.0, 1511326704.0, 3889917532.0 },
+       {    3859662829.0, 4292754251.0, 3708466080.0 }
+       };
+
+const double A1p127[3][3] = {
+       {    2427906178.0, 3580155704.0,  949770784.0 },
+       {     226153695.0, 1230515664.0, 3580155704.0 },
+       {    1988835001.0,  986791581.0, 1230515664.0 }
+       };
+
+const double A2p127[3][3] = {
+       {    1464411153.0,  277697599.0, 1610723613.0 },
+       {      32183930.0, 1464411153.0, 1022607788.0 },
+       {    2824425944.0,   32183930.0, 2093834863.0 }
+       };
+
+
+
+//-------------------------------------------------------------------------
+// Return (a*s + c) MOD m; a, s, c and m must be < 2^35
+//
+double MultModM (double a, double s, double c, double m)
+{
+    double v;
+    int32_t a1;
+
+    v = a * s + c;
+
+    if (v >= two53 || v <= -two53) {
+        a1 = static_cast<int32_t> (a / two17);    a -= a1 * two17;
+        v  = a1 * s;
+        a1 = static_cast<int32_t> (v / m);     v -= a1 * m;
+        v = v * two17 + a * s + c;
+    }
+
+    a1 = static_cast<int32_t> (v / m);
+    /* in case v < 0)*/
+    if ((v -= a1 * m) < 0.0) return v += m;   else return v;
+}
+
+
+//-------------------------------------------------------------------------
+// Compute the vector v = A*s MOD m. Assume that -m < s[i] < m.
+// Works also when v = s.
+//
+void MatVecModM (const double A[3][3], const double s[3], double v[3],
+                 double m)
+{
+    int i;
+    double x[3];               // Necessary if v = s
+
+    for (i = 0; i < 3; ++i) {
+        x[i] = MultModM (A[i][0], s[0], 0.0, m);
+        x[i] = MultModM (A[i][1], s[1], x[i], m);
+        x[i] = MultModM (A[i][2], s[2], x[i], m);
+    }
+    for (i = 0; i < 3; ++i)
+        v[i] = x[i];
+}
+
+
+//-------------------------------------------------------------------------
+// Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m.
+// Note: works also if A = C or B = C or A = B = C.
+//
+void MatMatModM (const double A[3][3], const double B[3][3],
+                 double C[3][3], double m)
+{
+    int i, j;
+    double V[3], W[3][3];
+
+    for (i = 0; i < 3; ++i) {
+        for (j = 0; j < 3; ++j)
+            V[j] = B[j][i];
+        MatVecModM (A, V, V, m);
+        for (j = 0; j < 3; ++j)
+            W[j][i] = V[j];
+    }
+    for (i = 0; i < 3; ++i)
+        for (j = 0; j < 3; ++j)
+            C[i][j] = W[i][j];
+}
+
+
+//-------------------------------------------------------------------------
+// Compute the matrix B = (A^(2^e) Mod m);  works also if A = B. 
+//
+void MatTwoPowModM (const double A[3][3], double B[3][3], double m, int32_t e)
+{
+   int i, j;
+
+   /* initialize: B = A */
+   if (A != B) {
+      for (i = 0; i < 3; ++i)
+         for (j = 0; j < 3; ++j)
+            B[i][j] = A[i][j];
+   }
+   /* Compute B = A^(2^e) mod m */
+   for (i = 0; i < e; i++)
+      MatMatModM (B, B, B, m);
+}
+
+
+//-------------------------------------------------------------------------
+// Compute the matrix B = (A^n Mod m);  works even if A = B.
+//
+void MatPowModM (const double A[3][3], double B[3][3], double m, int32_t n)
+{
+    int i, j;
+    double W[3][3];
+
+    /* initialize: W = A; B = I */
+    for (i = 0; i < 3; ++i)
+        for (j = 0; j < 3; ++j) {
+            W[i][j] = A[i][j];
+            B[i][j] = 0.0;
+        }
+    for (j = 0; j < 3; ++j)
+        B[j][j] = 1.0;
+
+    /* Compute B = A^n mod m using the binary decomposition of n */
+    while (n > 0) {
+        if (n % 2) MatMatModM (W, B, B, m);
+        MatMatModM (W, W, W, m);
+        n /= 2;
+    }
+}
+
+
+
+} // end of anonymous namespace
+
+
+namespace ns3{
+//-------------------------------------------------------------------------
+// Generate the next random number.
+//
+double RngStream::U01 ()
+{
+    int32_t k;
+    double p1, p2, u;
+
+    /* Component 1 */
+    p1 = a12 * Cg[1] - a13n * Cg[0];
+    k = static_cast<int32_t> (p1 / m1);
+    p1 -= k * m1;
+    if (p1 < 0.0) p1 += m1;
+    Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1;
+
+    /* Component 2 */
+    p2 = a21 * Cg[5] - a23n * Cg[3];
+    k = static_cast<int32_t> (p2 / m2);
+    p2 -= k * m2;
+    if (p2 < 0.0) p2 += m2;
+    Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2;
+
+    /* Combination */
+    u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm);
+
+    return (anti == false) ? u : (1 - u);
+}
+
+
+//-------------------------------------------------------------------------
+// Generate the next random number with extended (53 bits) precision.
+//
+double RngStream::U01d ()
+{
+    double u;
+    u = U01();
+    if (anti) {
+        // Don't forget that U01() returns 1 - u in the antithetic case
+        u += (U01() - 1.0) * fact;
+        return (u < 0.0) ? u + 1.0 : u;
+    } else {
+        u += U01() * fact;
+        return (u < 1.0) ? u : (u - 1.0);
+    }
+}
+
+//-------------------------------------------------------------------------
+// Check that the seeds are legitimate values. Returns true if legal seeds,
+// false otherwise.
+//
+bool RngStream::CheckSeed (const uint32_t seed[6])
+{
+    int i;
+
+    for (i = 0; i < 3; ++i) {
+        if (seed[i] >= m1) {
+            cerr << "****************************************\n\n"
+                 << "ERROR: Seed[" << i << "] >= 4294967087, Seed is not set."
+                 << "\n\n****************************************\n\n";
+            return (false);
+        }
+    }
+    for (i = 3; i < 6; ++i) {
+        if (seed[i] >= m2) {
+	  cout << "Seed[" << i << "] = " << seed[i] << endl; 
+            cerr << "*****************************************\n\n"
+                 << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set."
+                 << "\n\n*****************************************\n\n";
+            return (false);
+        }
+    }
+    if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
+         cerr << "****************************\n\n"
+              << "ERROR: First 3 seeds = 0.\n\n"
+              << "****************************\n\n";
+         return (false);
+    }
+    if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {
+         cerr << "****************************\n\n"
+              << "ERROR: Last 3 seeds = 0.\n\n"
+              << "****************************\n\n";
+         return (false);
+    }
+    return true;
+}
+
+
+
+//*************************************************************************
+// Public members of the class start here
+
+
+//-------------------------------------------------------------------------
+// The default seed of the package; will be the seed of the first
+// declared RngStream, unless SetPackageSeed is called.
+//
+double RngStream::nextSeed[6] =
+{
+   12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0
+};
+
+//-------------------------------------------------------------------------
+// constructor
+//
+RngStream::RngStream ()
+{
+   anti = false;
+   incPrec = false;
+   // Stream initialization moved to separate method.
+}
+
+void RngStream::InitializeStream()
+{ // Moved from the RngStream constructor above to allow seeding
+  // AFTER the global package seed has been set in the Random
+  // object constructor.
+   /* Information on a stream. The arrays {Cg, Bg, Ig} contain the current
+   state of the stream, the starting state of the current SubStream, and the
+   starting state of the stream. This stream generates antithetic variates
+   if anti = true. It also generates numbers with extended precision (53
+   bits if machine follows IEEE 754 standard) if incPrec = true. nextSeed
+   will be the seed of the next declared RngStream. */
+
+   for (int i = 0; i < 6; ++i) {
+      Bg[i] = Cg[i] = Ig[i] = nextSeed[i];
+   }
+
+   MatVecModM (A1p127, nextSeed, nextSeed, m1);
+   MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2);
+}
+
+//-------------------------------------------------------------------------
+// Reset Stream to beginning of Stream.
+//
+void RngStream::ResetStartStream ()
+{
+   for (int i = 0; i < 6; ++i)
+      Cg[i] = Bg[i] = Ig[i];
+}
+
+
+//-------------------------------------------------------------------------
+// Reset Stream to beginning of SubStream.
+//
+void RngStream::ResetStartSubstream ()
+{
+   for (int i = 0; i < 6; ++i)
+      Cg[i] = Bg[i];
+}
+
+
+//-------------------------------------------------------------------------
+// Reset Stream to NextSubStream.
+//
+void RngStream::ResetNextSubstream ()
+{
+   MatVecModM(A1p76, Bg, Bg, m1);
+   MatVecModM(A2p76, &Bg[3], &Bg[3], m2);
+   for (int i = 0; i < 6; ++i)
+       Cg[i] = Bg[i];
+}
+
+
+//-------------------------------------------------------------------------
+bool RngStream::SetPackageSeed (const uint32_t seed[6])
+{
+  if (!CheckSeed (seed)) return false;
+  for (int i = 0; i < 6; ++i)
+    nextSeed[i] = seed[i];
+  return true;
+}
+
+
+//-------------------------------------------------------------------------
+bool RngStream::SetSeeds (const uint32_t seed[6])
+{
+  if (!CheckSeed (seed)) return false;
+   for (int i = 0; i < 6; ++i)
+      Cg[i] = Bg[i] = Ig[i] = seed[i];
+   return true;
+}
+
+
+//-------------------------------------------------------------------------
+// if e > 0, let n = 2^e + c;
+// if e < 0, let n = -2^(-e) + c;
+// if e = 0, let n = c.
+// Jump n steps forward if n > 0, backwards if n < 0.
+//
+void RngStream::AdvanceState (int32_t e, int32_t c)
+{
+    double B1[3][3], C1[3][3], B2[3][3], C2[3][3];
+
+    if (e > 0) {
+        MatTwoPowModM (A1p0, B1, m1, e);
+        MatTwoPowModM (A2p0, B2, m2, e);
+    } else if (e < 0) {
+        MatTwoPowModM (InvA1, B1, m1, -e);
+        MatTwoPowModM (InvA2, B2, m2, -e);
+    }
+
+    if (c >= 0) {
+        MatPowModM (A1p0, C1, m1, c);
+        MatPowModM (A2p0, C2, m2, c);
+    } else {
+        MatPowModM (InvA1, C1, m1, -c);
+        MatPowModM (InvA2, C2, m2, -c);
+    }
+
+    if (e) {
+        MatMatModM (B1, C1, C1, m1);
+        MatMatModM (B2, C2, C2, m2);
+    }
+
+    MatVecModM (C1, Cg, Cg, m1);
+    MatVecModM (C2, &Cg[3], &Cg[3], m2);
+}
+
+
+//-------------------------------------------------------------------------
+void RngStream::GetState (uint32_t seed[6]) const
+{
+   for (int i = 0; i < 6; ++i)
+      seed[i] = static_cast<uint32_t> (Cg[i]);
+}
+
+
+//-------------------------------------------------------------------------
+void RngStream::IncreasedPrecis (bool incp)
+{
+   incPrec = incp;
+}
+
+
+//-------------------------------------------------------------------------
+void RngStream::SetAntithetic (bool a)
+{
+   anti = a;
+}
+
+
+//-------------------------------------------------------------------------
+// Generate the next random number.
+//
+double RngStream::RandU01 ()
+{
+   if (incPrec)
+      return U01d();
+   else
+      return U01();
+}
+
+
+//-------------------------------------------------------------------------
+// Generate the next random integer.
+//
+int32_t RngStream::RandInt (int32_t low, int32_t high)
+{
+    return low + static_cast<int32_t> ((high - low + 1) * RandU01 ());
+};
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/rng-stream.h	Sat Mar 17 22:32:08 2007 -0700
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+//  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 version 2 as
+// published by the Free Software Foundation;
+//
+// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Modified for ns-3 by: Rajib Bhattacharjea<raj.b@gatech.edu>
+
+#ifndef RNGSTREAM_H
+#define RNGSTREAM_H
+#include <string>
+
+namespace ns3{
+
+/**
+ * \brief RngStream by Pierre L'Ecuyer, University of Montreal
+ * Adapted to NS3 by Rajib Bhattacharjea, Georgia Tech.
+ */
+class RngStream {
+public:  //public api
+  RngStream ();
+  void InitializeStream(); // Separate initialization
+  void ResetStartStream ();
+  void ResetStartSubstream ();
+  void ResetNextSubstream ();
+  void SetAntithetic (bool a);
+  void IncreasedPrecis (bool incp);
+  bool SetSeeds (const uint32_t seed[6]);
+  void AdvanceState (int32_t e, int32_t c);
+  void GetState (uint32_t seed[6]) const;
+  double RandU01 ();
+  int32_t RandInt (int32_t i, int32_t j);
+public: //public static api
+  static bool SetPackageSeed (const uint32_t seed[6]);
+  static bool CheckSeed(const uint32_t seed[6]);
+private: //members
+  double Cg[6], Bg[6], Ig[6];
+  bool anti, incPrec;
+  double U01 ();
+  double U01d ();
+private: //static data
+  static double nextSeed[6];
+};
+
+};//namespace ns3
+
+#endif
+ 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/application.cc	Sat Mar 17 22:32:08 2007 -0700
@@ -0,0 +1,173 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: George F. Riley<riley@ece.gatech.edu>
+ */
+
+// Implementation for ns3 Application base class.
+// George F. Riley, Georgia Tech, Fall 2006
+
+#include "application.h"
+#include "node.h"
+#include "node-reference.h"
+#include "ns3/nstime.h"
+#include "ns3/random-variable.h"
+#include "ns3/simulator.h"
+
+using namespace std;
+
+namespace ns3 {
+
+#define nil 0
+
+// Application Methods
+
+// \brief Application Constructor
+  Application::Application() : m_node(nil), m_startVar(nil), m_stopVar(nil),
+                               m_start(false), m_stop(false)
+{
+}
+
+Application::Application(const Application& o)
+    : m_node(nil), m_startVar(nil), m_stopVar(nil),
+      m_start(false), m_stop(false)
+{ // Copy constructor
+  if (o.GetNode())m_node = new NodeReference(*o.GetNode());
+  // Copy the start and stop random variables if they exist
+  if (o.m_startVar) m_startVar = o.m_startVar->Copy();
+  if (o.m_stopVar)  m_stopVar  = o.m_stopVar->Copy();
+  if (o.m_start)    ScheduleStart();
+  if (o.m_stop)     ScheduleStop();
+}
+
+  
+// \brief Application Destructor
+Application::~Application()
+{
+  delete m_node;
+  // Cancel the start/stop events if scheduled
+  if (m_start) Simulator::Cancel(m_startEvent);
+  if (m_stop)  Simulator::Cancel(m_stopEvent);
+  // Delete the random variablse
+  delete m_startVar;
+  delete m_stopVar;
+}
+  
+Application& Application::operator=(const Application& rhs)
+{
+  if (this == &rhs) return *this; // Self assignment
+  delete m_node;
+  m_node = nil;
+  if (rhs.GetNode())m_node = new NodeReference(*rhs.GetNode());
+
+  delete m_startVar;
+  m_startVar = nil;
+  if (rhs.m_startVar) m_startVar = rhs.m_startVar->Copy();
+  
+  delete m_stopVar;
+  m_stopVar = nil;
+  if (rhs.m_stopVar) m_stopVar = rhs.m_stopVar->Copy();
+  
+  m_start = false;
+  if (rhs.m_start) ScheduleStart();
+  if (rhs.m_stop)  ScheduleStop();
+  return *this;
+}
+  
+   
+// \brief Specify application start time
+// The virtual method STartApp will be called at the time
+// specified by startTime.
+// \param Time to start application (absolute time, from start of simulation)
+void Application::Start(const Time& startTime)
+{
+  delete m_startVar;
+  m_startVar = new ConstantVariable(startTime.GetSeconds());
+  ScheduleStart();
+}
+
+void Application::Start(const RandomVariable& startVar)
+{ // Start at random time
+  delete m_startVar;
+  m_startVar = startVar.Copy();
+  ScheduleStart();
+}
+
+   
+// \brief Specify application stop time
+// The virtual method StopApp will be called at the time
+// specified by stopTime.
+// \param Time to stop application (absolute time, from start of simulation)
+void Application::Stop(const Time& stopTime)
+{
+  delete m_stopVar;
+  m_stopVar = new ConstantVariable(stopTime.GetSeconds());
+  ScheduleStop();
+}
+
+void Application::Stop(const RandomVariable& stopVar)
+{ // Stop at random time
+  delete m_stopVar;
+  m_stopVar = stopVar.Copy();
+  ScheduleStop();
+}
+
+// \brief Assign this application to a given node
+// Called by the application manager capability when adding
+// an application to a node.
+void Application::SetNode(const Node& n)
+{
+  delete m_node;
+  m_node = new NodeReference(n);
+}
+  
+Node* Application::GetNode() const
+{
+  return m_node->GetNode();
+}
+
+// Protected methods
+// StartApp and StopApp will likely be overridden by application subclasses
+void Application::StartApplication()
+{ // Provide null functionality in case subclass is not interested
+}
+
+void Application::StopApplication()
+{ // Provide null functionality in case subclass is not interested
+}
+
+
+// Private helpers
+void Application::ScheduleStart()
+{
+  m_startEvent = Simulator::Schedule(Seconds(m_startVar->GetValue()) -
+                                     Simulator::Now(),
+                                     &Application::StartApplication, this);
+  m_start = true;
+}
+
+void Application::ScheduleStop()
+{
+  m_stopEvent = Simulator::Schedule(Seconds(m_stopVar->GetValue()) -
+                                     Simulator::Now(),
+                                     &Application::StopApplication, this);
+  m_stop = true;
+}
+
+} //namespace ns3
+      
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/application.h	Sat Mar 17 22:32:08 2007 -0700
@@ -0,0 +1,136 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: George F. Riley<riley@ece.gatech.edu>
+ */
+
+#ifndef __APPLICATION_H__
+#define __APPLICATION_H__
+
+//
+// \brief The base class for all ns3 applicationes
+//
+// Class Application is the base class for all ns3 applications.
+// Applications are associated with individual nodes, and are created
+// using the AddApplication method in the ApplicationManager capability.
+// 
+// Conceptually, an application has zero or more Socket
+// objects associated with it, that are created using the Socket
+// creation API of the Kernel capability.  The Socket object
+// API is modeled after the
+// well-known BSD sockets interface, although it is somewhat 
+// simplified for use with ns3.  Further, any socket call that
+// would normally "block" in normal sockets will return immediately
+// in ns3.  A set of "upcalls" are defined that will be called when
+// the previous blocking call would normally exit.  THis is documented
+// in more detail Socket class in socket.h.
+// 
+// There is a second application class in ns3, called "ThreadedApplication"
+// that implements a true sockets interface, which should be used
+// when porting existing sockets code to ns3.  The true
+// sockets approach is significantly
+// less memory--efficient using private stacks for each defined application,
+// so that approach should be used with care.  The design and implementation
+// of the ThreadedApplication are still being discussed.
+
+#include "ns3/event-id.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+class Node;
+class NodeReference;
+class RandomVariable;
+  
+class Application {
+public:
+  Application();
+  Application(const Application&);  // Copy constructor
+  Application& operator=(const Application&); // Assignment operator
+  virtual ~Application();
+  
+  virtual Application* Copy() const = 0; // All applications must provide
+  
+  // \brief Specify application start time
+  // Applications start at various times in the simulation scenario.
+  // The Start method specifies when the application should be
+  // started.  The application subclasses should override the
+  // private "StartApplication" method defined below, which is called at the
+  // time specified, to cause the application to begin.
+  // \param Start time for this application, relative to the
+  // current simulation time.
+  void Start(const Time&);
+
+  // \brief Same as above, but uses a random variable for start time
+  // The random variable returns the desired start time in units of
+  // Seconds.
+  
+void Start(const RandomVariable&);
+  
+  // \brief Specify application stop time
+  // Once an application has started, it is sometimes useful
+  // to stop the application.  The Stop method specifies when an
+  // application is to stop.  The application subclasses should override
+  // the private StopApplication method defined below, to cause the application
+  // to stop.
+  // \param Stop time for this application, relative to the
+  // current simulation time.
+  void Stop(const Time&);
+
+  // \brief Same as above, but uses a random variable for stop time
+  // The random variable returns the desired stop time in units of
+  // Seconds.
+  void Stop(const RandomVariable&);
+  
+  // \brief Attaches an application to a specific node
+  // Specifies which node object this application is associated with.
+  // \param Node object to associate with this application.
+  void SetNode(const Node&);
+
+  // \brief Returns the pointer to the attached node.
+  Node* GetNode() const;
+  
+  // Members
+  NodeReference*  m_node;      // All applications have an associated node
+  RandomVariable* m_startVar;  // Random variable for start time
+  RandomVariable* m_stopVar;   // Random variable for stop time
+  EventId         m_startEvent;// Event identifier for start event
+  EventId         m_stopEvent; // Event identifier for the stop event
+  bool            m_start;     // True if start event scheduled
+  bool            m_stop;      // True if stop event scheduled
+  
+protected:
+  // \brief Application specific startup code
+  // The StartApplication method is called at the start time specifed by Start
+  // This method should be overridden by all or most application
+  // subclasses.
+  virtual void StartApplication();
+
+  // \brief Application specific shutdown code
+  // The StopApplication method is called at the stop time specifed by Stop
+  // This method should be overridden by all or most application
+  // subclasses.
+  virtual void StopApplication();
+
+private:
+  // Helpers
+  void ScheduleStart();
+  void ScheduleStop();
+};
+
+} //namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/node-reference.h	Sat Mar 17 22:32:08 2007 -0700
@@ -0,0 +1,45 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: George F. Riley<riley@ece.gatech.edu>
+//
+
+// Define a class that wraps a node pointer.  This allows numerous ns3
+// objects to have access to a node, but without ambiguity of whether
+// the owner should "delete" it.
+
+// George F. Riley, Georgia Tech, Spring 2007
+
+#ifndef __NODE_REFERENCE_H__
+#define __NODE_REFERENCE_H__
+
+namespace ns3 {
+
+class Node;
+
+class NodeReference {
+public:
+  NodeReference(const Node& n)
+    : m_node(n) {}
+  Node* GetNode() const { return (Node*)&m_node;}
+public:
+  const Node& m_node;
+};
+
+} // namespace ns3
+
+#endif