bug 133: automate RandomVariable memory management.
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 15 Feb 2008 20:03:48 +0100
changeset 2336 28ce210b91bb
parent 2335 854dbe96e04c
child 2337 604a3bc1fbb3
bug 133: automate RandomVariable memory management.
src/applications/onoff/onoff-application.cc
src/applications/onoff/onoff-application.h
src/common/error-model.cc
src/common/error-model.h
src/core/random-variable-default-value.cc
src/core/random-variable-default-value.h
src/core/random-variable.cc
src/core/random-variable.h
src/devices/wifi/propagation-delay-model.cc
src/devices/wifi/propagation-delay-model.h
src/devices/wifi/propagation-loss-model.cc
src/devices/wifi/propagation-loss-model.h
src/mobility/random-direction-2d-mobility-model.cc
src/mobility/random-direction-2d-mobility-model.h
src/mobility/random-position.cc
src/mobility/random-position.h
src/mobility/random-walk-2d-mobility-model.cc
src/mobility/random-walk-2d-mobility-model.h
src/mobility/random-waypoint-mobility-model.cc
src/mobility/random-waypoint-mobility-model.h
src/node/application.cc
--- a/src/applications/onoff/onoff-application.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/applications/onoff/onoff-application.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -91,8 +91,8 @@
   m_socket = 0;
   m_peer = remote;
   m_connected = false;
-  m_onTime = onTime.Copy ();
-  m_offTime = offTime.Copy ();
+  m_onTime = onTime;
+  m_offTime = offTime;
   m_pktSize = size;
   m_residualBits = 0;
   m_lastStartTime = Seconds (0);
@@ -136,12 +136,6 @@
   NS_LOG_FUNCTION;
 
   m_socket = 0;
-  delete m_onTime;
-  delete m_offTime;
-
-  m_onTime = 0;
-  m_offTime = 0;
-
   // chain up
   Application::DoDispose ();
 }
@@ -223,7 +217,7 @@
 {  // Schedules the event to start sending data (switch to the "On" state)
   NS_LOG_FUNCTION;
 
-  Time offInterval = Seconds(m_offTime->GetValue());
+  Time offInterval = Seconds(m_offTime.GetValue());
   NS_LOG_LOGIC ("start at " << offInterval);
   m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this);
 }
@@ -232,7 +226,7 @@
 {  // Schedules the event to stop sending data (switch to "Off" state)
   NS_LOG_FUNCTION;
 
-  Time onInterval = Seconds(m_onTime->GetValue());
+  Time onInterval = Seconds(m_onTime.GetValue());
   Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this);
 }
 
--- a/src/applications/onoff/onoff-application.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/applications/onoff/onoff-application.h	Fri Feb 15 20:03:48 2008 +0100
@@ -30,6 +30,7 @@
 #include "ns3/ptr.h"
 #include "ns3/data-rate.h"
 #include "ns3/callback-trace-source.h"
+#include "ns3/random-variable.h"
 
 namespace ns3 {
 
@@ -128,8 +129,8 @@
   Ptr<Socket>     m_socket;       // Associated socket
   Address         m_peer;         // Peer address
   bool            m_connected;    // True if connected
-  RandomVariable* m_onTime;       // rng for On Time
-  RandomVariable* m_offTime;      // rng for Off Time
+  RandomVariable m_onTime;       // rng for On Time
+  RandomVariable m_offTime;      // rng for Off Time
   DataRate        m_cbrRate;      // Rate that data is generated
   uint32_t        m_pktSize;      // Size of packets
   uint32_t        m_residualBits; // Number of generated, but not sent, bits
--- a/src/common/error-model.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/common/error-model.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -140,13 +140,12 @@
 {
   NS_LOG_FUNCTION;
   // Assume a uniform random variable if user does not specify
-  m_ranvar = new UniformVariable ();
+  m_ranvar = UniformVariable ();
 }
 
 RateErrorModel::~RateErrorModel () 
 {
   NS_LOG_FUNCTION;
-  delete m_ranvar;
 }
 
 enum ErrorUnit 
@@ -181,8 +180,7 @@
 RateErrorModel::SetRandomVariable (const RandomVariable &ranvar)
 {
   NS_LOG_FUNCTION;
-  delete m_ranvar;
-  m_ranvar = ranvar.Copy ();
+  m_ranvar = ranvar;
 }
 
 bool 
@@ -212,7 +210,7 @@
 RateErrorModel::DoCorruptPkt (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION;
-  return (m_ranvar->GetValue () < m_rate);
+  return (m_ranvar.GetValue () < m_rate);
 }
 
 bool
@@ -221,7 +219,7 @@
   NS_LOG_FUNCTION;
   // compute pkt error rate, assume uniformly distributed byte error
   double per = 1 - pow (1.0 - m_rate, p->GetSize ());
-  return (m_ranvar->GetValue () < per);
+  return (m_ranvar.GetValue () < per);
 }
 
 bool
@@ -230,7 +228,7 @@
   NS_LOG_FUNCTION;
   // compute pkt error rate, assume uniformly distributed bit error
   double per = 1 - pow (1.0 - m_rate, (8 * p->GetSize ()) );
-  return (m_ranvar->GetValue () < per);
+  return (m_ranvar.GetValue () < per);
 }
 
 void 
--- a/src/common/error-model.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/common/error-model.h	Fri Feb 15 20:03:48 2008 +0100
@@ -23,11 +23,11 @@
 
 #include <list>
 #include "ns3/object.h"
+#include "ns3/random-variable.h"
 
 namespace ns3 {
 
 class Packet;
-class RandomVariable;
 
 /**
  * \brief General error model that can be used to corrupt packets
@@ -174,7 +174,7 @@
   enum ErrorUnit m_unit;
   double m_rate;
 
-  RandomVariable* m_ranvar;
+  RandomVariable m_ranvar;
 };
 
 /**
--- a/src/core/random-variable-default-value.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/core/random-variable-default-value.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -39,17 +39,17 @@
   DefaultValueList::Add (this);
 }
 
-RandomVariable *
-RandomVariableDefaultValue::GetCopy (void)
+RandomVariable
+RandomVariableDefaultValue::Get (void) const
 {
-  RandomVariable *variable;
+  RandomVariable variable;
   bool ok;
   ok = Parse (m_value, true, &variable);
   NS_ASSERT (ok);
   return variable;
 }
 double
-RandomVariableDefaultValue::ReadAsDouble (std::string value, bool &ok)
+RandomVariableDefaultValue::ReadAsDouble (std::string value, bool &ok) const
 {
   double v;
   std::istringstream iss;
@@ -60,7 +60,7 @@
 }
 bool
 RandomVariableDefaultValue::Parse (const std::string &value, 
-				   bool mustCreate, RandomVariable **pVariable)
+				   bool mustCreate, RandomVariable *pVariable) const
 {
   std::string::size_type pos = value.find_first_of(":");
   if (pos == std::string::npos)
@@ -76,7 +76,7 @@
       if (mustCreate)
 	{
           NS_LOG_LOGIC ("create Constant constant=" << constant);
-	  *pVariable = new ConstantVariable (constant);
+	  *pVariable = ConstantVariable (constant);
 	}
       else
         {
@@ -100,7 +100,7 @@
       if (mustCreate)
 	{
           NS_LOG_LOGIC ("create Uniform min=" << min << ", max=" << max);
-	  *pVariable = new UniformVariable (minVal, maxVal);
+	  *pVariable = UniformVariable (minVal, maxVal);
 	}
       else
         {
--- a/src/core/random-variable-default-value.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/core/random-variable-default-value.h	Fri Feb 15 20:03:48 2008 +0100
@@ -33,10 +33,10 @@
 			      std::string help,
 			      std::string defaultValue);
 
-  RandomVariable *GetCopy (void);
+  RandomVariable Get (void) const;
 private:
-  bool Parse (const std::string &value, bool mustCreate, RandomVariable **pVariable);
-  double ReadAsDouble (const std::string value, bool &ok);
+  bool Parse (const std::string &value, bool mustCreate, RandomVariable *pVariable) const;
+  double ReadAsDouble (const std::string value, bool &ok) const;
   virtual bool DoParseValue (const std::string &value);
   virtual std::string DoGetType (void) const;
   virtual std::string DoGetDefaultValue (void) const;
--- a/src/core/random-variable.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/core/random-variable.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -30,6 +30,7 @@
 #include <fcntl.h>       
 
 
+#include "assert.h"
 #include "random-variable.h"
 #include "rng-stream.h"
 #include "fatal-error.h"
@@ -40,16 +41,51 @@
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// RandomVariable methods
+// RandomVariableBase methods
+
+
+class RandomVariableBase 
+{
+public:
+  RandomVariableBase ();
+  RandomVariableBase (const RandomVariableBase &o);
+  virtual ~RandomVariableBase();
+  virtual double  GetValue() = 0;
+  virtual uint32_t GetIntValue();
+  virtual RandomVariableBase*   Copy(void) const = 0;
+  virtual void GetSeed(uint32_t seed[6]);
 
-bool          RandomVariable::initialized = false;   // True if RngStream seed set 
-bool          RandomVariable::useDevRandom = false;  // True if use /dev/random
-bool          RandomVariable::globalSeedSet = false; // True if GlobalSeed called
-int           RandomVariable::devRandom = -1;
-uint32_t      RandomVariable::globalSeed[6];
-unsigned long RandomVariable::heuristic_sequence;
-RngStream*    RandomVariable::m_static_generator = 0;
-uint32_t      RandomVariable::runNumber = 0;
+  static  void UseDevRandom(bool udr = true);
+  static void UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, 
+                            uint32_t s3, uint32_t s4, uint32_t s5);
+  static void SetRunNumber(uint32_t n);
+private:
+  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
+  friend class RandomVariableInitializer;
+protected:
+  static unsigned long heuristic_sequence;
+  static RngStream* m_static_generator;
+  static uint32_t runNumber;
+  static void Initialize();    // Initialize  the RNG system
+  static bool initialized;     // True if package seed is set 
+  RngStream* m_generator;  //underlying generator being wrapped
+};
+
+
+
+bool          RandomVariableBase::initialized = false;   // True if RngStream seed set 
+bool          RandomVariableBase::useDevRandom = false;  // True if use /dev/random
+bool          RandomVariableBase::globalSeedSet = false; // True if GlobalSeed called
+int           RandomVariableBase::devRandom = -1;
+uint32_t      RandomVariableBase::globalSeed[6];
+unsigned long RandomVariableBase::heuristic_sequence;
+RngStream*    RandomVariableBase::m_static_generator = 0;
+uint32_t      RandomVariableBase::runNumber = 0;
 
 //the static object random_variable_initializer initializes the static members
 //of RandomVariable
@@ -58,25 +94,25 @@
   public:
   RandomVariableInitializer()
   {
-//     RandomVariable::Initialize(); // sets the static package seed
-//     RandomVariable::m_static_generator = new RngStream();
-//     RandomVariable::m_static_generator->InitializeStream();
+//     RandomVariableBase::Initialize(); // sets the static package seed
+//     RandomVariableBase::m_static_generator = new RngStream();
+//     RandomVariableBase::m_static_generator->InitializeStream();
   }
   ~RandomVariableInitializer()
   {
-    delete RandomVariable::m_static_generator;
+    delete RandomVariableBase::m_static_generator;
   }
 } random_variable_initializer;
 
-RandomVariable::RandomVariable() 
+RandomVariableBase::RandomVariableBase() 
   : m_generator(NULL)
 {
 //   m_generator = new RngStream();
 //   m_generator->InitializeStream();
-//   m_generator->ResetNthSubstream(RandomVariable::runNumber);
+//   m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
 }
 
-RandomVariable::RandomVariable(const RandomVariable& r)
+RandomVariableBase::RandomVariableBase(const RandomVariableBase& r)
   :m_generator(0)
 {
   if(r.m_generator)
@@ -85,61 +121,61 @@
   }
 }
 
-RandomVariable::~RandomVariable()
+RandomVariableBase::~RandomVariableBase()
 {
   delete m_generator;
 }
 
-uint32_t RandomVariable::GetIntValue() 
+uint32_t RandomVariableBase::GetIntValue() 
 {
   return (uint32_t)GetValue();
 }
 
-void RandomVariable::UseDevRandom(bool udr) 
+void RandomVariableBase::UseDevRandom(bool udr) 
 {
-  RandomVariable::useDevRandom = udr;
+  RandomVariableBase::useDevRandom = udr;
 }
 
-void RandomVariable::GetSeed(uint32_t seed[6])
+void RandomVariableBase::GetSeed(uint32_t seed[6])
 {
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   m_generator->GetState(seed);
 }
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// RandomVariable static methods
-void RandomVariable::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, 
+// RandomVariableBase static methods
+void RandomVariableBase::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, 
                                    uint32_t s3, uint32_t s4, uint32_t s5)
 {
-  if (RandomVariable::globalSeedSet)
+  if (RandomVariableBase::globalSeedSet)
     {
       cerr << "Random number generator already initialized!" << endl;
-      cerr << "Call to RandomVariable::UseGlobalSeed() ignored" << endl;
+      cerr << "Call to RandomVariableBase::UseGlobalSeed() ignored" << endl;
       return;
     }
-  RandomVariable::globalSeed[0] = s0;
-  RandomVariable::globalSeed[1] = s1;
-  RandomVariable::globalSeed[2] = s2;
-  RandomVariable::globalSeed[3] = s3;
-  RandomVariable::globalSeed[4] = s4;
-  RandomVariable::globalSeed[5] = s5;
-  if (!RngStream::CheckSeed(RandomVariable::globalSeed))
+  RandomVariableBase::globalSeed[0] = s0;
+  RandomVariableBase::globalSeed[1] = s1;
+  RandomVariableBase::globalSeed[2] = s2;
+  RandomVariableBase::globalSeed[3] = s3;
+  RandomVariableBase::globalSeed[4] = s4;
+  RandomVariableBase::globalSeed[5] = s5;
+  if (!RngStream::CheckSeed(RandomVariableBase::globalSeed))
     NS_FATAL_ERROR("Invalid seed");
   
-  RandomVariable::globalSeedSet = true;
+  RandomVariableBase::globalSeedSet = true;
 }
 
-void RandomVariable::Initialize()
+void RandomVariableBase::Initialize()
 { 
-  if (RandomVariable::initialized) return; // Already initialized and seeded
-  RandomVariable::initialized = true;
-  if (!RandomVariable::globalSeedSet)
+  if (RandomVariableBase::initialized) return; // Already initialized and seeded
+  RandomVariableBase::initialized = true;
+  if (!RandomVariableBase::globalSeedSet)
     { // No global seed, try a random one
       GetRandomSeeds(globalSeed);
     }
@@ -147,20 +183,20 @@
   RngStream::SetPackageSeed(globalSeed);
 }
 
-void RandomVariable::GetRandomSeeds(uint32_t seeds[6])
+void RandomVariableBase::GetRandomSeeds(uint32_t seeds[6])
 {
   // Check if /dev/random exists
-  if (RandomVariable::useDevRandom && RandomVariable::devRandom < 0)
+  if (RandomVariableBase::useDevRandom && RandomVariableBase::devRandom < 0)
     {
-      RandomVariable::devRandom = open("/dev/random", O_RDONLY);
+      RandomVariableBase::devRandom = open("/dev/random", O_RDONLY);
     }
-  if (RandomVariable::devRandom > 0)
+  if (RandomVariableBase::devRandom > 0)
     { // Use /dev/random
       while(true)
         {
           for (int i = 0; i < 6; ++i)
             {
-              read(RandomVariable::devRandom, &seeds[i], sizeof(seeds[i]));
+              read(RandomVariableBase::devRandom, &seeds[i], sizeof(seeds[i]));
             }
           if (RngStream::CheckSeed(seeds)) break; // Got a valid one
         }
@@ -194,205 +230,537 @@
     }
 }
 
-void RandomVariable::SetRunNumber(uint32_t n)
+void RandomVariableBase::SetRunNumber(uint32_t n)
 {
   runNumber = n;
 }
 
+
+
+RandomVariable::RandomVariable()
+  : m_variable (0)
+{}
+RandomVariable::RandomVariable(const RandomVariable&o)
+  : m_variable (o.m_variable->Copy ())
+{}
+RandomVariable::RandomVariable (const RandomVariableBase &variable)
+  : m_variable (variable.Copy ())
+{}
+RandomVariable &
+RandomVariable::operator = (const RandomVariable &o)
+{
+  delete m_variable;
+  m_variable = o.m_variable->Copy ();
+  return *this;
+}
+RandomVariable::~RandomVariable()
+{
+  delete m_variable;
+}
+double  
+RandomVariable::GetValue (void) const
+{
+  return m_variable->GetValue ();
+}
+
+uint32_t 
+RandomVariable::GetIntValue (void) const
+{
+  return m_variable->GetIntValue ();
+}
+void 
+RandomVariable::GetSeed(uint32_t seed[6]) const
+{
+  return m_variable->GetSeed (seed);
+}
+void 
+RandomVariable::UseDevRandom(bool udr)
+{
+  RandomVariableBase::UseDevRandom (udr);
+}
+void 
+RandomVariable::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, 
+                              uint32_t s3, uint32_t s4, uint32_t s5)
+{
+  RandomVariableBase::UseGlobalSeed (s0, s1, s2, s3, s4, s5);
+}
+void 
+RandomVariable::SetRunNumber(uint32_t n)
+{
+  RandomVariableBase::SetRunNumber (n);
+}
+RandomVariableBase *
+RandomVariable::Peek (void)
+{
+  return m_variable;
+}
+
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// UniformVariable
-UniformVariable::UniformVariable() 
+// UniformVariableImpl
+
+class UniformVariableImpl : public RandomVariableBase {
+public:
+  /**
+   * Creates a uniform random number generator in the
+   * range [0.0 .. 1.0).
+   */
+  UniformVariableImpl();
+
+  /**
+   * Creates a uniform random number generator with the specified range
+   * \param s Low end of the range
+   * \param l High end of the range
+   */
+  UniformVariableImpl(double s, double l);
+
+  UniformVariableImpl(const UniformVariableImpl& c);
+  
+  /**
+   * \return A value between low and high values specified by the constructor
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase*  Copy(void) const;
+
+public:
+  /**
+   * \param s Low end of the range
+   * \param l High end of the range
+   * \return A uniformly distributed random number between s and l
+   */
+  static double GetSingleValue(double s, double l);
+private:
+  double m_min;
+  double m_max;
+};
+
+UniformVariableImpl::UniformVariableImpl() 
   : m_min(0), m_max(1.0) { }
   
-UniformVariable::UniformVariable(double s, double l) 
+UniformVariableImpl::UniformVariableImpl(double s, double l) 
   : m_min(s), m_max(l) { }
 
-UniformVariable::UniformVariable(const UniformVariable& c) 
-  : RandomVariable(c), m_min(c.m_min), m_max(c.m_max) { }
+UniformVariableImpl::UniformVariableImpl(const UniformVariableImpl& c) 
+  : RandomVariableBase(c), m_min(c.m_min), m_max(c.m_max) { }
 
-double UniformVariable::GetValue()
+double UniformVariableImpl::GetValue()
 {
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   return m_min + m_generator->RandU01() * (m_max - m_min);
 }
 
-RandomVariable* UniformVariable::Copy() const
+RandomVariableBase* UniformVariableImpl::Copy() const
+{
+  return new UniformVariableImpl(*this);
+}
+
+double UniformVariableImpl::GetSingleValue(double s, double l)
 {
-  return new UniformVariable(*this);
+  if(!RandomVariableBase::m_static_generator)
+  {
+    RandomVariableBase::Initialize(); // sets the static package seed
+    RandomVariableBase::m_static_generator = new RngStream();
+    RandomVariableBase::m_static_generator->InitializeStream();
+  }
+  return s + m_static_generator->RandU01() * (l - s);;
+}
+
+UniformVariable::UniformVariable()
+  : RandomVariable (UniformVariableImpl ())
+{}
+UniformVariable::UniformVariable(double s, double l)
+  : RandomVariable (UniformVariableImpl (s, l))
+{}
+double 
+UniformVariable::GetSingleValue(double s, double l)
+{
+  return UniformVariableImpl::GetSingleValue (s, l);
 }
 
-double UniformVariable::GetSingleValue(double s, double l)
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ConstantVariableImpl methods
+
+class ConstantVariableImpl : public RandomVariableBase { 
+
+public:
+  /**
+   * Construct a ConstantVariableImpl RNG that returns zero every sample
+   */
+  ConstantVariableImpl();
+  
+  /**
+   * Construct a ConstantVariableImpl RNG that returns the specified value
+   * every sample.
+   * \param c Unchanging value for this RNG.
+   */
+  ConstantVariableImpl(double c);
+
+
+  ConstantVariableImpl(const ConstantVariableImpl& 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 RandomVariableBase*   Copy(void) const;
+private:
+  double m_const;
+};
+
+ConstantVariableImpl::ConstantVariableImpl() 
+  : m_const(0) { }
+
+ConstantVariableImpl::ConstantVariableImpl(double c) 
+  : m_const(c) { };
+  
+ConstantVariableImpl::ConstantVariableImpl(const ConstantVariableImpl& c) 
+  : RandomVariableBase(c), m_const(c.m_const) { }
+
+void ConstantVariableImpl::NewConstant(double c) 
+  { m_const = c;}
+  
+double ConstantVariableImpl::GetValue()
 {
-  if(!RandomVariable::m_static_generator)
-  {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
-  }
-  return s + m_static_generator->RandU01() * (l - s);;
+  return m_const;
+}
+
+uint32_t ConstantVariableImpl::GetIntValue()
+{
+  return (uint32_t)m_const;
+}
+
+RandomVariableBase* ConstantVariableImpl::Copy() const
+{
+  return new ConstantVariableImpl(*this);
+}
+
+ConstantVariable::ConstantVariable()
+  : RandomVariable (ConstantVariableImpl ())
+{}
+ConstantVariable::ConstantVariable(double c)
+  : RandomVariable (ConstantVariableImpl (c))
+{}
+void 
+ConstantVariable::SetConstant(double c)
+{
+  *this = ConstantVariable (c);
 }
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// ConstantVariable methods
-ConstantVariable::ConstantVariable() 
-  : m_const(0) { }
+// SequentialVariableImpl methods
 
-ConstantVariable::ConstantVariable(double c) 
-  : m_const(c) { };
-  
-ConstantVariable::ConstantVariable(const ConstantVariable& c) 
-  : RandomVariable(c), m_const(c.m_const) { }
+
+class SequentialVariableImpl : public RandomVariableBase {
 
-void ConstantVariable::NewConstant(double c) 
-  { m_const = c;}
-  
-double ConstantVariable::GetValue()
-{
-  return m_const;
-}
+public:
+  /**
+   * \brief Constructor for the SequentialVariableImpl RNG.
+   *
+   * The four parameters define the sequence.  For example
+   * SequentialVariableImpl(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
+   */
+  SequentialVariableImpl(double f, double l, double i = 1, uint32_t c = 1);
 
-uint32_t ConstantVariable::GetIntValue()
-{
-  return (uint32_t)m_const;
-}
+  /**
+   * \brief Constructor for the SequentialVariableImpl 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 RandomVariableBase for the sequence increment
+   * \param c Number of times each member of the sequence is repeated
+   */
+  SequentialVariableImpl(double f, double l, const RandomVariable& i, uint32_t c = 1);
 
-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)
-{
-}
+  SequentialVariableImpl(const SequentialVariableImpl& c);
+  
+  ~SequentialVariableImpl();
+  /**
+   * \return The next value in the Sequence
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase*  Copy(void) const;
+private:
+  double m_min;
+  double m_max;
+  RandomVariable  m_increment;
+  uint32_t  m_consecutive;
+  double m_current;
+  uint32_t  m_currentConsecutive;
+};
 
-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),
+SequentialVariableImpl::SequentialVariableImpl(double f, double l, double i, uint32_t c)
+  : m_min(f), m_max(l), m_increment(ConstantVariable(i)), m_consecutive(c),
     m_current(f), m_currentConsecutive(0)
-{
-}
+{}
 
-SequentialVariable::SequentialVariable(const SequentialVariable& c)
-  : RandomVariable(c), m_min(c.m_min), m_max(c.m_max),
-    m_increment(c.m_increment->Copy()), m_consecutive(c.m_consecutive),
+SequentialVariableImpl::SequentialVariableImpl(double f, double l, const RandomVariable& i, uint32_t c)
+  : m_min(f), m_max(l), m_increment(i), m_consecutive(c),
+    m_current(f), m_currentConsecutive(0)
+{}
+
+SequentialVariableImpl::SequentialVariableImpl(const SequentialVariableImpl& c)
+  : RandomVariableBase(c), m_min(c.m_min), m_max(c.m_max),
+    m_increment(c.m_increment), m_consecutive(c.m_consecutive),
     m_current(c.m_current), m_currentConsecutive(c.m_currentConsecutive)
-{
-}
+{}
 
-SequentialVariable::~SequentialVariable()
-{
-  delete m_increment;
-}
+SequentialVariableImpl::~SequentialVariableImpl()
+{}
 
-double SequentialVariable::GetValue()
+double SequentialVariableImpl::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();
+      m_current += m_increment.GetValue();
       if (m_current >= m_max)
         m_current = m_min + (m_current - m_max);
     }
   return r;
 }
 
-RandomVariable* SequentialVariable::Copy() const
+RandomVariableBase* SequentialVariableImpl::Copy() const
 {
-  return new SequentialVariable(*this);
+  return new SequentialVariableImpl(*this);
 }
+
+SequentialVariable::SequentialVariable(double f, double l, double i, uint32_t c)
+  : RandomVariable (SequentialVariableImpl (f, l, i, c))
+{}
+SequentialVariable::SequentialVariable(double f, double l, const RandomVariable& i, uint32_t c)
+  : RandomVariable (SequentialVariableImpl (f, l, i, c))
+{}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// ExponentialVariable methods
-ExponentialVariable::ExponentialVariable() 
+// ExponentialVariableImpl methods
+
+class ExponentialVariableImpl : public RandomVariableBase { 
+public:
+  /**
+   * Constructs an exponential random variable  with a mean
+   * value of 1.0.
+   */
+  ExponentialVariableImpl();
+
+  /**
+   * \brief Constructs an exponential random variable with a specified mean
+   * \param m Mean value for the random variable
+   */
+  explicit ExponentialVariableImpl(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
+   */
+  ExponentialVariableImpl(double m, double b);
+
+  ExponentialVariableImpl(const ExponentialVariableImpl& c);
+  
+  /**
+   * \return A random value from this exponential distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase* Copy(void) const;
+public:
+  /**
+   * \param m The mean of the distribution from which the return value is drawn
+   * \param b The upper bound value desired, beyond which values get clipped
+   * \return A random number from an exponential distribution with mean m
+   */
+  static double GetSingleValue(double m, double b=0);
+private:
+  double m_mean;  // Mean value of RV
+  double m_bound; // Upper bound on value (if non-zero)
+};
+
+ExponentialVariableImpl::ExponentialVariableImpl() 
   : m_mean(1.0), m_bound(0) { }
   
-ExponentialVariable::ExponentialVariable(double m) 
+ExponentialVariableImpl::ExponentialVariableImpl(double m) 
   : m_mean(m), m_bound(0) { }
   
-ExponentialVariable::ExponentialVariable(double m, double b) 
+ExponentialVariableImpl::ExponentialVariableImpl(double m, double b) 
   : m_mean(m), m_bound(b) { }
   
-ExponentialVariable::ExponentialVariable(const ExponentialVariable& c) 
-  : RandomVariable(c), m_mean(c.m_mean), m_bound(c.m_bound) { }
+ExponentialVariableImpl::ExponentialVariableImpl(const ExponentialVariableImpl& c) 
+  : RandomVariableBase(c), m_mean(c.m_mean), m_bound(c.m_bound) { }
 
-double ExponentialVariable::GetValue()
+double ExponentialVariableImpl::GetValue()
 {
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   double r = -m_mean*log(m_generator->RandU01());
   if (m_bound != 0 && r > m_bound) return m_bound;
   return r;
 }
 
-RandomVariable* ExponentialVariable::Copy() const
+RandomVariableBase* ExponentialVariableImpl::Copy() const
 {
-  return new ExponentialVariable(*this);
+  return new ExponentialVariableImpl(*this);
 }
-double ExponentialVariable::GetSingleValue(double m, double b/*=0*/)
+double ExponentialVariableImpl::GetSingleValue(double m, double b/*=0*/)
 {
-  if(!RandomVariable::m_static_generator)
+  if(!RandomVariableBase::m_static_generator)
   {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
+    RandomVariableBase::Initialize(); // sets the static package seed
+    RandomVariableBase::m_static_generator = new RngStream();
+    RandomVariableBase::m_static_generator->InitializeStream();
   }
   double r = -m*log(m_static_generator->RandU01());
   if (b != 0 && r > b) return b;
   return r;
 }
+
+ExponentialVariable::ExponentialVariable()
+  : RandomVariable (ExponentialVariableImpl ())
+{}
+ExponentialVariable::ExponentialVariable(double m)
+  : RandomVariable (ExponentialVariableImpl (m))
+{}
+ExponentialVariable::ExponentialVariable(double m, double b)
+  : RandomVariable (ExponentialVariableImpl (m, b))
+{}
+double 
+ExponentialVariable::GetSingleValue(double m, double b)
+{
+  return ExponentialVariableImpl::GetSingleValue (m, b);
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// ParetoVariable methods
-ParetoVariable::ParetoVariable() 
+// ParetoVariableImpl methods
+class ParetoVariableImpl : public RandomVariableBase {
+public:
+  /**
+   * Constructs a pareto random variable with a mean of 1 and a shape
+   * parameter of 1.5
+   */
+  ParetoVariableImpl();
+
+  /**
+   * Constructs a pareto random variable with specified mean and shape
+   * parameter of 1.5
+   * \param m Mean value of the distribution
+   */
+  explicit ParetoVariableImpl(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
+   */
+  ParetoVariableImpl(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
+   */
+  ParetoVariableImpl(double m, double s, double b);
+
+  ParetoVariableImpl(const ParetoVariableImpl& c);
+  
+  /**
+   * \return A random value from this Pareto distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase* Copy() const;
+public:
+  /**
+   * \param m The mean value of the distribution from which the return value
+   * is drawn.
+   * \param s The shape parameter of the distribution from which the return
+   * value is drawn.
+   * \param b The upper bound to which to restrict return values
+   * \return A random number from a Pareto distribution with mean m and shape
+   * parameter s.
+   */
+  static double GetSingleValue(double m, double s, double b=0);
+private:
+  double m_mean;  // Mean value of RV
+  double m_shape; // Shape parameter
+  double m_bound; // Upper bound on value (if non-zero)
+};
+
+ParetoVariableImpl::ParetoVariableImpl() 
   : m_mean(1.0), m_shape(1.5), m_bound(0) { }
 
-ParetoVariable::ParetoVariable(double m) 
+ParetoVariableImpl::ParetoVariableImpl(double m) 
   : m_mean(m), m_shape(1.5), m_bound(0) { }
 
-ParetoVariable::ParetoVariable(double m, double s) 
+ParetoVariableImpl::ParetoVariableImpl(double m, double s) 
     : m_mean(m), m_shape(s), m_bound(0) { }
 
-ParetoVariable::ParetoVariable(double m, double s, double b) 
+ParetoVariableImpl::ParetoVariableImpl(double m, double s, double b) 
   : m_mean(m), m_shape(s), m_bound(b) { }
 
-ParetoVariable::ParetoVariable(const ParetoVariable& c) 
-  : RandomVariable(c), m_mean(c.m_mean), m_shape(c.m_shape), 
+ParetoVariableImpl::ParetoVariableImpl(const ParetoVariableImpl& c) 
+  : RandomVariableBase(c), m_mean(c.m_mean), m_shape(c.m_shape), 
     m_bound(c.m_bound) { }
 
-double ParetoVariable::GetValue()
+double ParetoVariableImpl::GetValue()
 {
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   double scale = m_mean * ( m_shape - 1.0) / m_shape;
   double r = (scale * ( 1.0 / pow(m_generator->RandU01(), 1.0 / m_shape)));
@@ -400,49 +768,127 @@
   return r;
 }
 
-RandomVariable* ParetoVariable::Copy() const
+RandomVariableBase* ParetoVariableImpl::Copy() const
 {
-  return new ParetoVariable(*this);
+  return new ParetoVariableImpl(*this);
 }
 
-double ParetoVariable::GetSingleValue(double m, double s, double b/*=0*/)
+double ParetoVariableImpl::GetSingleValue(double m, double s, double b/*=0*/)
 {
-  if(!RandomVariable::m_static_generator)
+  if(!RandomVariableBase::m_static_generator)
   {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
+    RandomVariableBase::Initialize(); // sets the static package seed
+    RandomVariableBase::m_static_generator = new RngStream();
+    RandomVariableBase::m_static_generator->InitializeStream();
   }
   double scale = m * ( s - 1.0) / s;
   double r = (scale * ( 1.0 / pow(m_static_generator->RandU01(), 1.0 / s)));
   if (b != 0 && r > b) return b;
   return r;
 }
+
+ParetoVariable::ParetoVariable ()
+  : RandomVariable (ParetoVariableImpl ())
+{}
+ParetoVariable::ParetoVariable(double m)
+  : RandomVariable (ParetoVariableImpl (m))
+{}
+ParetoVariable::ParetoVariable(double m, double s)
+  : RandomVariable (ParetoVariableImpl (m, s))
+{}
+ParetoVariable::ParetoVariable(double m, double s, double b)
+  : RandomVariable (ParetoVariableImpl (m, s, b))
+{}
+double 
+ParetoVariable::GetSingleValue(double m, double s, double b)
+{
+  return ParetoVariableImpl::GetSingleValue (m, s, b);
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// WeibullVariable methods
-WeibullVariable::WeibullVariable() : m_mean(1.0), m_alpha(1), m_bound(0) { }
-WeibullVariable::WeibullVariable(double m) 
+// WeibullVariableImpl methods
+
+class WeibullVariableImpl : public RandomVariableBase {
+public:
+  /**
+   * Constructs a weibull random variable  with a mean
+   * value of 1.0 and a shape (alpha) parameter of 1
+   */
+  WeibullVariableImpl();
+
+
+  /**
+   * 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
+   */
+   WeibullVariableImpl(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.
+   */
+  WeibullVariableImpl(double m, double s);
+
+   /**
+   * \brief Constructs a weibull random variable with the specified mean
+   * \brief value, shape (alpha), and upper bound.
+   * Since WeibullVariableImpl 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
+   */
+  WeibullVariableImpl(double m, double s, double b);
+
+  WeibullVariableImpl(const WeibullVariableImpl& c);
+  
+  /**
+   * \return A random value from this Weibull distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase* Copy(void) const;
+public:
+  /**
+   * \param m Mean value for the distribution.
+   * \param s Shape (alpha) parameter for the distribution.
+   * \param b Upper limit on returned values
+   * \return Random number from a distribution specified by m,s, and b
+   */
+  static double GetSingleValue(double m, double s, double b=0);
+private:
+  double m_mean;  // Mean value of RV
+  double m_alpha; // Shape parameter
+  double m_bound; // Upper bound on value (if non-zero)
+};
+
+WeibullVariableImpl::WeibullVariableImpl() : m_mean(1.0), m_alpha(1), m_bound(0) { }
+WeibullVariableImpl::WeibullVariableImpl(double m) 
   : m_mean(m), m_alpha(1), m_bound(0) { }
-WeibullVariable::WeibullVariable(double m, double s) 
+WeibullVariableImpl::WeibullVariableImpl(double m, double s) 
   : m_mean(m), m_alpha(s), m_bound(0) { }
-WeibullVariable::WeibullVariable(double m, double s, double b) 
+WeibullVariableImpl::WeibullVariableImpl(double m, double s, double b) 
   : m_mean(m), m_alpha(s), m_bound(b) { };
-WeibullVariable::WeibullVariable(const WeibullVariable& c) 
-  : RandomVariable(c), m_mean(c.m_mean), m_alpha(c.m_alpha),
+WeibullVariableImpl::WeibullVariableImpl(const WeibullVariableImpl& c) 
+  : RandomVariableBase(c), m_mean(c.m_mean), m_alpha(c.m_alpha),
     m_bound(c.m_bound) { }
 
-double WeibullVariable::GetValue()
+double WeibullVariableImpl::GetValue()
 {
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   double exponent = 1.0 / m_alpha;
   double r = m_mean * pow( -log(m_generator->RandU01()), exponent);
@@ -450,52 +896,114 @@
   return r;
 }
 
-RandomVariable* WeibullVariable::Copy() const
+RandomVariableBase* WeibullVariableImpl::Copy() const
 {
-  return new WeibullVariable(*this);
+  return new WeibullVariableImpl(*this);
 }
 
-double WeibullVariable::GetSingleValue(double m, double s, double b/*=0*/)
+double WeibullVariableImpl::GetSingleValue(double m, double s, double b/*=0*/)
 {
-  if(!RandomVariable::m_static_generator)
+  if(!RandomVariableBase::m_static_generator)
   {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
+    RandomVariableBase::Initialize(); // sets the static package seed
+    RandomVariableBase::m_static_generator = new RngStream();
+    RandomVariableBase::m_static_generator->InitializeStream();
   }
   double exponent = 1.0 / s;
   double r = m * pow( -log(m_static_generator->RandU01()), exponent);
   if (b != 0 && r > b) return b;
   return r;
 }
+
+WeibullVariable::WeibullVariable()
+  : RandomVariable (WeibullVariableImpl ())
+{}
+WeibullVariable::WeibullVariable(double m)
+  : RandomVariable (WeibullVariableImpl (m))
+{}
+WeibullVariable::WeibullVariable(double m, double s)
+  : RandomVariable (WeibullVariableImpl (m, s))
+{}
+WeibullVariable::WeibullVariable(double m, double s, double b)
+  : RandomVariable (WeibullVariableImpl (m, s, b))
+{}
+double 
+WeibullVariable::GetSingleValue(double m, double s, double b)
+{
+  return WeibullVariableImpl::GetSingleValue (m, s, b);
+}
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// NormalVariable methods
-bool         NormalVariable::m_static_nextValid = false;
-double       NormalVariable::m_static_next;
-const double NormalVariable::INFINITE_VALUE = 1e307;
+// NormalVariableImpl methods
+
+class NormalVariableImpl : public RandomVariableBase { // Normally Distributed random var
+
+public:
+   static const double INFINITE_VALUE;
+  /**
+   * Constructs an normal random variable  with a mean
+   * value of 0 and variance of 1.
+   */ 
+  NormalVariableImpl();
+
+  /**
+   * \brief Construct a normal random variable with specified mean and variance
+   * \param m Mean value
+   * \param v Variance
+   * \param b Bound.  The NormalVariableImpl is bounded within +-bound.
+   */ 
+  NormalVariableImpl(double m, double v, double b = INFINITE_VALUE);
 
-NormalVariable::NormalVariable() 
+  NormalVariableImpl(const NormalVariableImpl& c);
+  
+  /**
+   * \return A value from this normal distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase* Copy(void) const;
+public:
+  /**
+   * \param m Mean value
+   * \param v Variance
+   * \param b Bound.  The NormalVariableImpl is bounded within +-bound.
+   * \return A random number from a distribution specified by m,v, and b.
+   */ 
+  static double GetSingleValue(double m, double v, double b = INFINITE_VALUE);
+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
+  static bool   m_static_nextValid;
+  static double m_static_next;
+};
+
+bool         NormalVariableImpl::m_static_nextValid = false;
+double       NormalVariableImpl::m_static_next;
+const double NormalVariableImpl::INFINITE_VALUE = 1e307;
+
+NormalVariableImpl::NormalVariableImpl() 
   : m_mean(0.0), m_variance(1.0), m_bound(INFINITE_VALUE), m_nextValid(false){}
 
-NormalVariable::NormalVariable(double m, double v, double b/*=INFINITE_VALUE*/)
+NormalVariableImpl::NormalVariableImpl(double m, double v, double b/*=INFINITE_VALUE*/)
   : m_mean(m), m_variance(v), m_bound(b), m_nextValid(false) { }
 
-NormalVariable::NormalVariable(const NormalVariable& c)
-  : RandomVariable(c), m_mean(c.m_mean), m_variance(c.m_variance),
+NormalVariableImpl::NormalVariableImpl(const NormalVariableImpl& c)
+  : RandomVariableBase(c), m_mean(c.m_mean), m_variance(c.m_variance),
     m_bound(c.m_bound) { }
 
-double NormalVariable::GetValue()
+double NormalVariableImpl::GetValue()
 {
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   if (m_nextValid)
     { // use previously generated
@@ -523,18 +1031,18 @@
     }
 }
 
-RandomVariable* NormalVariable::Copy() const
+RandomVariableBase* NormalVariableImpl::Copy() const
 {
-  return new NormalVariable(*this);
+  return new NormalVariableImpl(*this);
 }
 
-double NormalVariable::GetSingleValue(double m, double v, double b)
+double NormalVariableImpl::GetSingleValue(double m, double v, double b)
 {
-  if(!RandomVariable::m_static_generator)
+  if(!RandomVariableBase::m_static_generator)
   {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
+    RandomVariableBase::Initialize(); // sets the static package seed
+    RandomVariableBase::m_static_generator = new RngStream();
+    RandomVariableBase::m_static_generator->InitializeStream();
   }
   if (m_static_nextValid)
     { // use previously generated
@@ -562,39 +1070,89 @@
     }
 }
 
+NormalVariable::NormalVariable()
+  : RandomVariable (NormalVariableImpl ())
+{}
+NormalVariable::NormalVariable(double m, double v, double b)
+  : RandomVariable (NormalVariableImpl (m, v, b))
+{}
+double 
+NormalVariable::GetSingleValue(double m, double v, double b)
+{
+  return NormalVariableImpl::GetSingleValue (m, v, b);
+}
+
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
+class EmpiricalVariableImpl : public RandomVariableBase {
+public:
+  /**
+   * Constructor for the EmpiricalVariableImpl random variables.
+   */
+  explicit EmpiricalVariableImpl();
+
+  virtual ~EmpiricalVariableImpl();
+  EmpiricalVariableImpl(const EmpiricalVariableImpl& c);
+  /**
+   * \return A value from this empirical distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase* Copy(void) 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:
+  class ValueCDF {
+  public:
+    ValueCDF();
+    ValueCDF(double v, double c);
+    ValueCDF(const ValueCDF& c);
+    double value;
+    double    cdf;
+  };
+  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
+};
+
+
 // ValueCDF methods
-EmpiricalVariable::ValueCDF::ValueCDF() 
+EmpiricalVariableImpl::ValueCDF::ValueCDF() 
   : value(0.0), cdf(0.0){ }
-EmpiricalVariable::ValueCDF::ValueCDF(double v, double c) 
+EmpiricalVariableImpl::ValueCDF::ValueCDF(double v, double c) 
   : value(v), cdf(c) { }
-EmpiricalVariable::ValueCDF::ValueCDF(const ValueCDF& c) 
+EmpiricalVariableImpl::ValueCDF::ValueCDF(const ValueCDF& c) 
   : value(c.value), cdf(c.cdf) { }
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// EmpiricalVariable methods
-EmpiricalVariable::EmpiricalVariable() 
+// EmpiricalVariableImpl methods
+EmpiricalVariableImpl::EmpiricalVariableImpl() 
   : validated(false) { }
 
-EmpiricalVariable::EmpiricalVariable(const EmpiricalVariable& c)
-  : RandomVariable(c), validated(c.validated), emp(c.emp) { }
+EmpiricalVariableImpl::EmpiricalVariableImpl(const EmpiricalVariableImpl& c)
+  : RandomVariableBase(c), validated(c.validated), emp(c.emp) { }
 
-EmpiricalVariable::~EmpiricalVariable() { }
+EmpiricalVariableImpl::~EmpiricalVariableImpl() { }
 
-double EmpiricalVariable::GetValue()
+double EmpiricalVariableImpl::GetValue()
 { // Return a value from the empirical distribution
   // This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   if (emp.size() == 0) return 0.0; // HuH? No empirical data
   if (!validated) Validate();      // Insure in non-decreasing
@@ -619,18 +1177,18 @@
     }
 }
 
-RandomVariable* EmpiricalVariable::Copy() const
+RandomVariableBase* EmpiricalVariableImpl::Copy() const
 {
-  return new EmpiricalVariable(*this);
+  return new EmpiricalVariableImpl(*this);
 }
 
-void EmpiricalVariable::CDF(double v, double c)
+void EmpiricalVariableImpl::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()
+void EmpiricalVariableImpl::Validate()
 {
   ValueCDF prior;
   for (std::vector<ValueCDF>::size_type i = 0; i < emp.size(); ++i)
@@ -650,66 +1208,156 @@
   validated = true;
 }
 
-double EmpiricalVariable::Interpolate(double c1, double c2,
+double EmpiricalVariableImpl::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()
+EmpiricalVariable::EmpiricalVariable()
+  : RandomVariable (EmpiricalVariableImpl ())
+{}
+EmpiricalVariable::EmpiricalVariable (const RandomVariableBase &variable)
+  : RandomVariable (variable)
+{}
+void 
+EmpiricalVariable::CDF(double v, double c)
 {
-  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));
+  EmpiricalVariableImpl *impl = dynamic_cast<EmpiricalVariableImpl *> (Peek ());
+  NS_ASSERT (impl);
+  impl->CDF (v, c);
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// DeterministicVariable
-DeterministicVariable::DeterministicVariable(double* d, uint32_t c)
+// Integer EmpiricalVariableImpl methods
+class IntEmpiricalVariableImpl : public EmpiricalVariableImpl {
+public:
+
+  IntEmpiricalVariableImpl();
+  
+  virtual RandomVariableBase* Copy(void) const;
+  /**
+   * \return An integer value from this empirical distribution
+   */
+  virtual uint32_t GetIntValue();
+private:
+  virtual double Interpolate(double, double, double, double, double);
+};
+
+
+IntEmpiricalVariableImpl::IntEmpiricalVariableImpl() { }
+
+uint32_t IntEmpiricalVariableImpl::GetIntValue()
+{
+  return (uint32_t)GetValue();
+}
+
+RandomVariableBase* IntEmpiricalVariableImpl::Copy() const
+{
+  return new IntEmpiricalVariableImpl(*this);
+}
+
+double IntEmpiricalVariableImpl::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));
+}
+
+IntEmpiricalVariable::IntEmpiricalVariable()
+  : EmpiricalVariable (IntEmpiricalVariableImpl ())
+{}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// DeterministicVariableImpl
+class DeterministicVariableImpl : public RandomVariableBase 
+{
+
+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 DeterministicVariableImpl to be meaningful.
+   * \param d Pointer to array of random values to return in sequence
+   * \param c Number of values in the array
+   */
+  explicit DeterministicVariableImpl(double* d, uint32_t c);
+
+  virtual ~DeterministicVariableImpl();
+  /**
+   * \return The next value in the deterministic sequence
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase* Copy(void) const;
+private:
+  uint32_t   count;
+  uint32_t   next;
+  double* data;
+};
+
+DeterministicVariableImpl::DeterministicVariableImpl(double* d, uint32_t c)
     : count(c), next(c), data(d)
 { // Nothing else needed
 }
 
-DeterministicVariable::~DeterministicVariable() { }
+DeterministicVariableImpl::~DeterministicVariableImpl() { }
   
-double DeterministicVariable::GetValue()
+double DeterministicVariableImpl::GetValue()
 {
   if (next == count) next = 0;
   return data[next++];
 }
 
-RandomVariable* DeterministicVariable::Copy() const
+RandomVariableBase* DeterministicVariableImpl::Copy() const
 {
-  return new DeterministicVariable(*this);
+  return new DeterministicVariableImpl(*this);
 }
 
+DeterministicVariable::DeterministicVariable(double* d, uint32_t c)
+  : RandomVariable (DeterministicVariableImpl (d, c))
+{}
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// LogNormalVariable
+// LogNormalVariableImpl
+class LogNormalVariableImpl : public RandomVariableBase { 
+public:
+  /**
+   * \param mu mu parameter of the lognormal distribution
+   * \param sigma sigma parameter of the lognormal distribution
+   */
+  LogNormalVariableImpl (double mu, double sigma);
 
-RandomVariable* LogNormalVariable::Copy () const
+  /**
+   * \return A random value from this distribution
+   */
+  virtual double GetValue ();
+  virtual RandomVariableBase* Copy(void) const;
+public:
+  /**
+   * \param mu mu parameter of the underlying normal distribution
+   * \param sigma sigma parameter of the underlying normal distribution
+   * \return A random number from the distribution specified by mu and sigma
+   */
+  static double GetSingleValue(double mu, double sigma);
+private:
+  double m_mu;
+  double m_sigma;
+};
+
+
+RandomVariableBase* LogNormalVariableImpl::Copy () const
 {
-  return new LogNormalVariable (m_mu, m_sigma);
+  return new LogNormalVariableImpl (m_mu, m_sigma);
 }
 
-LogNormalVariable::LogNormalVariable (double mu, double sigma)
+LogNormalVariableImpl::LogNormalVariableImpl (double mu, double sigma)
     :m_mu(mu), m_sigma(sigma) 
 {
 }
@@ -741,17 +1389,17 @@
    for x > 0. Lognormal random numbers are the exponentials of
    gaussian random numbers */
 double
-LogNormalVariable::GetValue ()
+LogNormalVariableImpl::GetValue ()
 {
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   double u, v, r2, normal, z;
 
@@ -774,13 +1422,13 @@
   return z;
 }
 
-double LogNormalVariable::GetSingleValue (double mu, double sigma)
+double LogNormalVariableImpl::GetSingleValue (double mu, double sigma)
 {
-  if(!RandomVariable::m_static_generator)
+  if(!RandomVariableBase::m_static_generator)
   {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
+    RandomVariableBase::Initialize(); // sets the static package seed
+    RandomVariableBase::m_static_generator = new RngStream();
+    RandomVariableBase::m_static_generator->InitializeStream();
   }
   double u, v, r2, normal, z;
   do
@@ -801,29 +1449,78 @@
   return z;
 }
 
+LogNormalVariable::LogNormalVariable (double mu, double sigma)
+  : RandomVariable (LogNormalVariableImpl (mu, sigma))
+{}
+double 
+LogNormalVariable::GetSingleValue(double mu, double sigma)
+{
+  return LogNormalVariableImpl::GetSingleValue (mu, sigma);
+}
+
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// TriangularVariable methods
-TriangularVariable::TriangularVariable() 
+// TriangularVariableImpl methods
+class TriangularVariableImpl : public RandomVariableBase {
+public:
+  /**
+   * Creates a triangle distribution random number generator in the
+   * range [0.0 .. 1.0), with mean of 0.5
+   */
+  TriangularVariableImpl();
+
+  /**
+   * Creates a triangle distribution random number generator with the specified
+   * range
+   * \param s Low end of the range
+   * \param l High end of the range
+   * \param mean mean of the distribution
+   */
+  TriangularVariableImpl(double s, double l, double mean);
+
+  TriangularVariableImpl(const TriangularVariableImpl& c);
+  
+  /**
+   * \return A value from this distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariableBase*  Copy(void) const;
+public:
+  /**
+   * \param s Low end of the range
+   * \param l High end of the range
+   * \param mean mean of the distribution
+   * \return A triangularly distributed random number between s and l
+   */
+  static double GetSingleValue(double s, double l, double mean);
+private:
+  double m_min;
+  double m_max;
+  double m_mode;  //easier to work with the mode internally instead of the mean
+                  //they are related by the simple: mean = (min+max+mode)/3
+};
+
+TriangularVariableImpl::TriangularVariableImpl() 
   : m_min(0), m_max(1), m_mode(0.5) { }
   
-TriangularVariable::TriangularVariable(double s, double l, double mean) 
+TriangularVariableImpl::TriangularVariableImpl(double s, double l, double mean) 
   : m_min(s), m_max(l), m_mode(3.0*mean-s-l) { }
   
-TriangularVariable::TriangularVariable(const TriangularVariable& c) 
-  : RandomVariable(c), m_min(c.m_min), m_max(c.m_max), m_mode(c.m_mode) { }
+TriangularVariableImpl::TriangularVariableImpl(const TriangularVariableImpl& c) 
+  : RandomVariableBase(c), m_min(c.m_min), m_max(c.m_max), m_mode(c.m_mode) { }
 
-double TriangularVariable::GetValue()
+double TriangularVariableImpl::GetValue()
 {
-  if(!RandomVariable::initialized)
+  if(!RandomVariableBase::initialized)
   {
-    RandomVariable::Initialize();
+    RandomVariableBase::Initialize();
   }
   if(!m_generator)
   {
     m_generator = new RngStream();
     m_generator->InitializeStream();
-    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+    m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
   }
   double u = m_generator->RandU01();
   if(u <= (m_mode - m_min) / (m_max - m_min) )
@@ -832,18 +1529,18 @@
     return m_max - sqrt( (1-u) * (m_max - m_min) * (m_max - m_mode) );
 }
 
-RandomVariable* TriangularVariable::Copy() const
+RandomVariableBase* TriangularVariableImpl::Copy() const
 {
-  return new TriangularVariable(*this);
+  return new TriangularVariableImpl(*this);
 }
 
-double TriangularVariable::GetSingleValue(double s, double l, double mean)
+double TriangularVariableImpl::GetSingleValue(double s, double l, double mean)
 {
-  if(!RandomVariable::m_static_generator)
+  if(!RandomVariableBase::m_static_generator)
   {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
+    RandomVariableBase::Initialize(); // sets the static package seed
+    RandomVariableBase::m_static_generator = new RngStream();
+    RandomVariableBase::m_static_generator->InitializeStream();
   }
   double mode = 3.0*mean-s-l;
   double u = m_static_generator->RandU01();
@@ -853,6 +1550,19 @@
     return l - sqrt( (1-u) * (l - s) * (l - mode) );
 }
 
+TriangularVariable::TriangularVariable()
+  : RandomVariable (TriangularVariableImpl ())
+{}
+TriangularVariable::TriangularVariable(double s, double l, double mean)
+  : RandomVariable (TriangularVariableImpl (s,l,mean))
+{}
+double 
+TriangularVariable::GetSingleValue(double s, double l, double mean)
+{
+  return TriangularVariableImpl::GetSingleValue (s,l,mean);
+}
+
+
 
 }//namespace ns3
 
--- a/src/core/random-variable.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/core/random-variable.h	Fri Feb 15 20:03:48 2008 +0100
@@ -33,7 +33,7 @@
 
 namespace ns3{
 
-class RngStream;
+class RandomVariableBase;
 
 /**
  * \brief The basic RNG for NS-3.
@@ -44,46 +44,31 @@
  * the University of Montreal.
  * 
  * NS-3 has a rich set of  random number generators.
- * Class RandomVariable defines the base class functionalty
+ * Class RandomVariableBase 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 { 
-
+class RandomVariable
+{ 
 public:
-  /**
-   * \brief Constructor for a random number generator with a random seed.
-   */
   RandomVariable();
-  
-  /**
-   * \brief Copy constructor
-   */  
-  RandomVariable(const RandomVariable&);
-  
-  /**
-   * \brief Destructor for a random number generator with a random seed.
-   */
-  virtual ~RandomVariable();
+  RandomVariable(const RandomVariable&o);
+  RandomVariable &operator = (const RandomVariable &o);
+  ~RandomVariable();
   
   /**
    * \brief Returns a random double from the underlying distribution
    * \return A floating point random value
    */
-  virtual double  GetValue() = 0;
+  double GetValue (void) const;
 
   /**
    * \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;
+  uint32_t GetIntValue (void) const;
   
   /**
    * \brief Get the internal state of the RNG
@@ -94,7 +79,7 @@
    * \param seed Output parameter; gets overwritten with the internal state of
    * of the RNG.
    */
-  virtual void GetSeed(uint32_t seed[6]);
+  void GetSeed(uint32_t seed[6]) const;
   
   /**
    * \brief Set seeding behavior
@@ -104,7 +89,7 @@
    * 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:
+   * RandomVariableBase or subclass.  Example:
    * \code
    * RandomVariable::UseDevRandom();
    * UniformVariable x(2,3);  //these are seeded randomly
@@ -174,23 +159,12 @@
    */
   static void SetRunNumber(uint32_t n);
 private:
-  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
-  friend class RandomVariableInitializer;
+  RandomVariableBase *m_variable;
 protected:
-  static unsigned long heuristic_sequence;
-  static RngStream* m_static_generator;
-  static uint32_t runNumber;
-  static void Initialize();    // Initialize  the RNG system
-  static bool initialized;     // True if package seed is set 
-  RngStream* m_generator;  //underlying generator being wrapped
+  RandomVariable (const RandomVariableBase &variable);
+  RandomVariableBase *Peek (void);
 };
 
-
 /**
  * \brief The uniform distribution RNG for NS-3.
  * \ingroup randomvariable
@@ -207,7 +181,8 @@
  * UniformVariable::GetSingleValue(100,1000); //returns a value [100,1000)
  * \endcode
  */
-class UniformVariable : public RandomVariable {
+class UniformVariable : public RandomVariable 
+{
 public:
   /**
    * Creates a uniform random number generator in the
@@ -221,14 +196,6 @@
    * \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;
 public:
   /**
    * \param s Low end of the range
@@ -236,50 +203,36 @@
    * \return A uniformly distributed random number between s and l
    */
   static double GetSingleValue(double s, double l);
-private:
-  double m_min;
-  double m_max;
 };
 
 /**
  * \brief A random variable that returns a constant
  * \ingroup randomvariable
  *
- * Class ConstantVariable defines a random number generator that
+ * Class ConstantVariableImpl defines a random number generator that
  * returns the same value every sample.
  */
 class ConstantVariable : public RandomVariable { 
 
 public:
   /**
-   * Construct a ConstantVariable RNG that returns zero every sample
+   * Construct a ConstantVariableImpl RNG that returns zero every sample
    */
   ConstantVariable();
   
   /**
-   * Construct a ConstantVariable RNG that returns the specified value
+   * Construct a ConstantVariableImpl 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);
+  void SetConstant(double c);
 
-  /**
-   * \return The constant value specified
-   */
-  virtual double  GetValue();
-  virtual uint32_t GetIntValue();
-  virtual RandomVariable*   Copy() const;
-private:
-  double m_const;
 };
 
 /**
@@ -291,14 +244,14 @@
  * increases for a period, then wraps around to the low value 
  * and begins monotonicaly increasing again.
  */
-class SequentialVariable : public RandomVariable {
-
+class SequentialVariable : public RandomVariable 
+{
 public:
   /**
-   * \brief Constructor for the SequentialVariable RNG.
+   * \brief Constructor for the SequentialVariableImpl RNG.
    *
    * The four parameters define the sequence.  For example
-   * SequentialVariable(0,5,1,2) creates a RNG that has the sequence
+   * SequentialVariableImpl(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.
@@ -308,32 +261,17 @@
   SequentialVariable(double f, double l, double i = 1, uint32_t c = 1);
 
   /**
-   * \brief Constructor for the SequentialVariable RNG.
+   * \brief Constructor for the SequentialVariableImpl 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 RandomVariable for the sequence increment
+   * \param i Reference to a RandomVariableBase 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);
-  
-  ~SequentialVariable();
-  /**
-   * \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;
 };
 
 /**
@@ -353,14 +291,15 @@
  * \f$ \left\{ \begin{array}{cl} \alpha  e^{-\alpha x} & x < bound \\ bound & x > bound \end{array}\right. \f$
  * 
  * \code
- * ExponentialVariable x(3.14);
+ * ExponentialVariableImpl x(3.14);
  * x.GetValue();  //will always return with mean 3.14
- * ExponentialVariable::GetSingleValue(20.1); //returns with mean 20.1
- * ExponentialVariable::GetSingleValue(108); //returns with mean 108
+ * ExponentialVariableImpl::GetSingleValue(20.1); //returns with mean 20.1
+ * ExponentialVariableImpl::GetSingleValue(108); //returns with mean 108
  * \endcode
  *
  */
-class ExponentialVariable : public RandomVariable { 
+class ExponentialVariable : public RandomVariable 
+{ 
 public:
   /**
    * Constructs an exponential random variable  with a mean
@@ -387,27 +326,16 @@
    */
   ExponentialVariable(double m, double b);
 
-  ExponentialVariable(const ExponentialVariable& c);
-  
-  /**
-   * \return A random value from this exponential distribution
-   */
-  virtual double GetValue();
-  virtual RandomVariable* Copy() const;
-public:
   /**
    * \param m The mean of the distribution from which the return value is drawn
    * \param b The upper bound value desired, beyond which values get clipped
    * \return A random number from an exponential distribution with mean m
    */
   static double GetSingleValue(double m, double b=0);
-private:
-  double m_mean;  // Mean value of RV
-  double m_bound; // Upper bound on value (if non-zero)
 };
 
 /**
- * \brief ParetoVariable distributed random var
+ * \brief ParetoVariableImpl distributed random var
  * \ingroup randomvariable
  *
  * This class supports the creation of objects that return random numbers
@@ -422,19 +350,20 @@
  * with the equation \f$ x_m = mean \frac{k-1}{k},  k > 1\f$.
  *
  * \code
- * ParetoVariable x(3.14);
+ * ParetoVariableImpl x(3.14);
  * x.GetValue();  //will always return with mean 3.14
- * ParetoVariable::GetSingleValue(20.1); //returns with mean 20.1
- * ParetoVariable::GetSingleValue(108); //returns with mean 108
+ * ParetoVariableImpl::GetSingleValue(20.1); //returns with mean 20.1
+ * ParetoVariableImpl::GetSingleValue(108); //returns with mean 108
  * \endcode
  */
-class ParetoVariable : public RandomVariable {
+class ParetoVariable : public RandomVariable
+{
 public:
   /**
    * Constructs a pareto random variable with a mean of 1 and a shape
    * parameter of 1.5
    */
-  ParetoVariable();
+  ParetoVariable ();
 
   /**
    * Constructs a pareto random variable with specified mean and shape
@@ -465,14 +394,6 @@
    */
   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;
-public:
   /**
    * \param m The mean value of the distribution from which the return value
    * is drawn.
@@ -483,14 +404,10 @@
    * parameter s.
    */
   static double GetSingleValue(double m, double s, double b=0);
-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
+ * \brief WeibullVariableImpl distributed random var
  * \ingroup randomvariable
  *
  * This class supports the creation of objects that return random numbers
@@ -530,7 +447,7 @@
    /**
    * \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,
+   * Since WeibullVariableImpl 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.
@@ -539,15 +456,6 @@
    * \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;
-public:
   /**
    * \param m Mean value for the distribution.
    * \param s Shape (alpha) parameter for the distribution.
@@ -555,14 +463,10 @@
    * \return Random number from a distribution specified by m,s, and b
    */
   static double GetSingleValue(double m, double s, double b=0);
-private:
-  double m_mean;  // Mean value of RV
-  double m_alpha; // Shape parameter
-  double m_bound; // Upper bound on value (if non-zero)
 };
 
 /**
- * \brief Class NormalVariable defines a random variable with a
+ * \brief Class NormalVariableImpl defines a random variable with a
  * normal (Gaussian) distribution.
  * \ingroup randomvariable
  * 
@@ -575,8 +479,8 @@
  * where \f$ mean = \mu \f$ and \f$ variance = \sigma^2 \f$
  *
  */
-class NormalVariable : public RandomVariable { // Normally Distributed random var
-
+class NormalVariable : public RandomVariable
+{
 public:
    static const double INFINITE_VALUE;
   /**
@@ -589,37 +493,20 @@
    * \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.
+   * \param b Bound.  The NormalVariableImpl 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;
-public:
   /**
    * \param m Mean value
    * \param v Variance
-   * \param b Bound.  The NormalVariable is bounded within +-bound.
+   * \param b Bound.  The NormalVariableImpl is bounded within +-bound.
    * \return A random number from a distribution specified by m,v, and b.
    */ 
   static double GetSingleValue(double m, double v, double b = INFINITE_VALUE);
-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
-  static bool   m_static_nextValid;
-  static double m_static_next;
 };
 
 /**
- * \brief EmpiricalVariable distribution random var
+ * \brief EmpiricalVariableImpl distribution random var
  * \ingroup randomvariable
  *
  * Defines a random variable  that has a specified, empirical 
@@ -634,37 +521,18 @@
 class EmpiricalVariable : public RandomVariable {
 public:
   /**
-   * Constructor for the EmpiricalVariable random variables.
+   * Constructor for the EmpiricalVariableImpl 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:
-  class ValueCDF {
-  public:
-    ValueCDF();
-    ValueCDF(double v, double c);
-    ValueCDF(const ValueCDF& c);
-    double value;
-    double    cdf;
-  };
-  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
+  void CDF(double v, double c);  // Value, prob <= Value
+protected:
+  EmpiricalVariable (const RandomVariableBase &variable);
 };
 
 /**
@@ -672,20 +540,13 @@
  * \ingroup randomvariable
  *
  * Defines an empirical distribution where all values are integers.
- * Indentical to EmpiricalVariable, but with slightly different
+ * Indentical to EmpiricalVariableImpl, but with slightly different
  * interpolation between points.
  */
-class IntEmpiricalVariable : public EmpiricalVariable {
+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);
 };
 
 /**
@@ -697,8 +558,8 @@
  * the RNG to return a known sequence, perhaps to
  * compare NS-3 to some other simulator
  */
-class DeterministicVariable : public RandomVariable {
-
+class DeterministicVariable : public RandomVariable
+{
 public:
   /**
    * \brief Constructor
@@ -707,22 +568,11 @@
    * 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.
+   * of DeterministicVariableImpl 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;
 };
 
 
@@ -730,7 +580,7 @@
  * \brief Log-normal Distributed random var
  * \ingroup randomvariable
  *
- * LogNormalVariable defines a random variable with log-normal
+ * LogNormalVariableImpl defines a random variable with log-normal
  * distribution.  If one takes the natural logarithm of random
  * variable following the log-normal distribution, the obtained values
  * follow a normal distribution.
@@ -748,7 +598,8 @@
  * \f$ \mu = ln(mean) - \frac{1}{2}ln\left(1+\frac{stddev}{mean^2}\right)\f$, and,
  * \f$ \sigma = \sqrt{ln\left(1+\frac{stddev}{mean^2}\right)}\f$
  */
-class LogNormalVariable : public RandomVariable { 
+class LogNormalVariable : public RandomVariable 
+{
 public:
   /**
    * \param mu mu parameter of the lognormal distribution
@@ -757,20 +608,11 @@
   LogNormalVariable (double mu, double sigma);
 
   /**
-   * \return A random value from this distribution
-   */
-  virtual double GetValue ();
-  virtual RandomVariable* Copy() const;
-public:
-  /**
    * \param mu mu parameter of the underlying normal distribution
    * \param sigma sigma parameter of the underlying normal distribution
    * \return A random number from the distribution specified by mu and sigma
    */
   static double GetSingleValue(double mu, double sigma);
-private:
-  double m_mu;
-  double m_sigma;
 };
 
 /**
@@ -780,7 +622,8 @@
  * This distribution is a triangular distribution.  The probablility density
  * is in the shape of a triangle.
  */
-class TriangularVariable : public RandomVariable {
+class TriangularVariable : public RandomVariable 
+{
 public:
   /**
    * Creates a triangle distribution random number generator in the
@@ -796,15 +639,6 @@
    * \param mean mean of the distribution
    */
   TriangularVariable(double s, double l, double mean);
-
-  TriangularVariable(const TriangularVariable& c);
-  
-  /**
-   * \return A value from this distribution
-   */
-  virtual double GetValue();
-  virtual RandomVariable*  Copy() const;
-public:
   /**
    * \param s Low end of the range
    * \param l High end of the range
@@ -812,11 +646,6 @@
    * \return A triangularly distributed random number between s and l
    */
   static double GetSingleValue(double s, double l, double mean);
-private:
-  double m_min;
-  double m_max;
-  double m_mode;  //easier to work with the mode internally instead of the mean
-                  //they are related by the simple: mean = (min+max+mode)/3
 };
 
 }//namespace ns3
--- a/src/devices/wifi/propagation-delay-model.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/devices/wifi/propagation-delay-model.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -69,20 +69,18 @@
 }
 
 RandomPropagationDelayModel::RandomPropagationDelayModel ()
-  : m_variable (g_random.GetCopy ())
+  : m_variable (g_random.Get ())
 {}
 
 RandomPropagationDelayModel::RandomPropagationDelayModel (const RandomVariable &variable)
-  : m_variable (variable.Copy ())
+  : m_variable (variable)
 {}
 RandomPropagationDelayModel::~RandomPropagationDelayModel ()
-{
-  delete m_variable;
-}
+{}
 Time 
 RandomPropagationDelayModel::GetDelay (Ptr<MobilityModel> a, Ptr<MobilityModel> b) const
 {
-  return Seconds (m_variable->GetValue ());
+  return Seconds (m_variable.GetValue ());
 }
 
 ConstantSpeedPropagationDelayModel::ConstantSpeedPropagationDelayModel (double speed)
--- a/src/devices/wifi/propagation-delay-model.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/devices/wifi/propagation-delay-model.h	Fri Feb 15 20:03:48 2008 +0100
@@ -23,13 +23,12 @@
 #include "ns3/ptr.h"
 #include "ns3/object.h"
 #include "ns3/nstime.h"
+#include "ns3/random-variable.h"
 
 namespace ns3 {
 
 class MobilityModel;
 
-class RandomVariable;
-
 /**
  * \brief calculate a propagation delay.
  */
@@ -71,7 +70,7 @@
   virtual ~RandomPropagationDelayModel ();
   virtual Time GetDelay (Ptr<MobilityModel> a, Ptr<MobilityModel> b) const;
 private:
-  RandomVariable *m_variable;
+  RandomVariable m_variable;
 };
 
 /**
--- a/src/devices/wifi/propagation-loss-model.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/devices/wifi/propagation-loss-model.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -104,23 +104,21 @@
   }
 }
 RandomPropagationLossModel::RandomPropagationLossModel ()
-  : m_variable (g_random.GetCopy ())
+  : m_variable (g_random.Get ())
 {}
 
 RandomPropagationLossModel::RandomPropagationLossModel (const RandomVariable &variable)
-  : m_variable (variable.Copy ())
+  : m_variable (variable)
 {}
 RandomPropagationLossModel::~RandomPropagationLossModel ()
-{
-  delete m_variable;
-}
+{}
 
 double 
 RandomPropagationLossModel::GetRxPower (double txPowerDbm,
 					Ptr<MobilityModel> a,
 					Ptr<MobilityModel> b) const
 {
-  double rxPower = txPowerDbm - m_variable->GetValue ();
+  double rxPower = txPowerDbm - m_variable.GetValue ();
   NS_LOG_DEBUG ("tx power="<<txPowerDbm<<"dbm, rx power="<<rxPower<<"Dbm");
   return rxPower;
 }
--- a/src/devices/wifi/propagation-loss-model.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/devices/wifi/propagation-loss-model.h	Fri Feb 15 20:03:48 2008 +0100
@@ -21,13 +21,12 @@
 #define PROPAGATION_LOSS_MODEL_H
 
 #include "ns3/object.h"
+#include "ns3/random-variable.h"
 
 namespace ns3 {
 
 class MobilityModel;
 
-class RandomVariable;
-
 /**
  * \brief Modelize the propagation loss through a transmission medium
  *
@@ -76,7 +75,7 @@
 			     Ptr<MobilityModel> a,
 			     Ptr<MobilityModel> b) const;
 private:
-  RandomVariable *m_variable;
+  RandomVariable m_variable;
 };
 
 /**
--- a/src/mobility/random-direction-2d-mobility-model.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-direction-2d-mobility-model.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -54,8 +54,8 @@
 
 RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters ()
   : m_bounds (g_bounds.GetValue ()),
-    m_speedVariable (g_speedVariable.GetCopy ()),
-    m_pauseVariable (g_pauseVariable.GetCopy ())
+    m_speedVariable (g_speedVariable.Get ()),
+    m_pauseVariable (g_pauseVariable.Get ())
     
 {}
 RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters 
@@ -63,29 +63,22 @@
  const RandomVariable &speedVariable,
  const RandomVariable &pauseVariable)
   : m_bounds (bounds),
-    m_speedVariable (speedVariable.Copy ()),
-    m_pauseVariable (pauseVariable.Copy ())
+    m_speedVariable (speedVariable),
+    m_pauseVariable (pauseVariable)
 {}
 
 RandomDirection2dMobilityModelParameters::~RandomDirection2dMobilityModelParameters ()
-{
-  delete m_speedVariable;
-  delete m_pauseVariable;
-  m_speedVariable = 0;
-  m_pauseVariable = 0;
-}
+{}
 
 void 
 RandomDirection2dMobilityModelParameters::SetSpeed (const RandomVariable &speedVariable)
 {
-  delete m_speedVariable;
-  m_speedVariable = speedVariable.Copy ();
+  m_speedVariable = speedVariable;
 }
 void 
 RandomDirection2dMobilityModelParameters::SetPause (const RandomVariable &pauseVariable)
 {
-  delete m_pauseVariable;
-  m_pauseVariable = pauseVariable.Copy ();
+  m_pauseVariable = pauseVariable;
 }
 void 
 RandomDirection2dMobilityModelParameters::SetBounds (const Rectangle &bounds)
@@ -149,7 +142,7 @@
 void
 RandomDirection2dMobilityModel::BeginPause (void)
 {
-  Time pause = Seconds (m_parameters->m_pauseVariable->GetValue ());
+  Time pause = Seconds (m_parameters->m_pauseVariable.GetValue ());
   m_helper.Pause ();
   m_event = Simulator::Schedule (pause, &RandomDirection2dMobilityModel::ResetDirectionAndSpeed, this);
   NotifyCourseChange ();
@@ -159,7 +152,7 @@
 RandomDirection2dMobilityModel::SetDirectionAndSpeed (double direction)
 {
   NS_LOG_FUNCTION;
-  double speed = m_parameters->m_speedVariable->GetValue ();
+  double speed = m_parameters->m_speedVariable.GetValue ();
   const Vector vector (std::cos (direction) * speed,
                        std::sin (direction) * speed,
                        0.0);
--- a/src/mobility/random-direction-2d-mobility-model.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-direction-2d-mobility-model.h	Fri Feb 15 20:03:48 2008 +0100
@@ -26,13 +26,12 @@
 #include "ns3/nstime.h"
 #include "ns3/event-id.h"
 #include "ns3/rectangle.h"
+#include "ns3/random-variable.h"
 #include "mobility-model.h"
 #include "static-speed-helper.h"
 
 namespace ns3 {
 
-class RandomVariable;
-
 /**
  * \brief the parameters to control a RandomDirection mobility model.
  */
@@ -73,8 +72,8 @@
   static Ptr<RandomDirection2dMobilityModelParameters> GetCurrent (void);
 
   Rectangle m_bounds;
-  RandomVariable *m_speedVariable;
-  RandomVariable *m_pauseVariable;
+  RandomVariable m_speedVariable;
+  RandomVariable m_pauseVariable;
 };
 
 /**
--- a/src/mobility/random-position.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-position.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -88,26 +88,21 @@
 }
 
 RandomRectanglePosition::RandomRectanglePosition ()
-  : m_x (g_rectangleX.GetCopy ()),
-    m_y (g_rectangleY.GetCopy ())
+  : m_x (g_rectangleX.Get ()),
+    m_y (g_rectangleY.Get ())
 {}
 RandomRectanglePosition::RandomRectanglePosition (const RandomVariable &x,
 						  const RandomVariable &y)
-  : m_x (x.Copy ()),
-    m_y (y.Copy ())
+  : m_x (x),
+    m_y (y)
 {}
 RandomRectanglePosition::~RandomRectanglePosition ()
-{
-  delete m_x;
-  delete m_y;
-  m_x = 0;
-  m_y = 0;
-}
+{}
 Vector
 RandomRectanglePosition::Get (void) const
 {
-  double x = m_x->GetValue ();
-  double y = m_y->GetValue ();
+  double x = m_x.GetValue ();
+  double y = m_y.GetValue ();
   return Vector (x, y, 0.0);
 }
 
@@ -124,31 +119,26 @@
 }   
 
 RandomDiscPosition::RandomDiscPosition ()
-  : m_theta (g_discTheta.GetCopy ()),
-    m_rho (g_discRho.GetCopy ()),
+  : m_theta (g_discTheta.Get ()),
+    m_rho (g_discRho.Get ()),
     m_x (g_discX.GetValue ()),
     m_y (g_discY.GetValue ())
 {}
 RandomDiscPosition::RandomDiscPosition (const RandomVariable &theta,
 					const RandomVariable &rho,
 					double x, double y)
-  : m_theta (theta.Copy ()),
-    m_rho (rho.Copy ()),
+  : m_theta (theta),
+    m_rho (rho),
     m_x (0.0),
     m_y (0.0)
 {}
 RandomDiscPosition::~RandomDiscPosition ()
-{
-  delete m_theta;
-  delete m_rho;
-  m_theta = 0;
-  m_rho = 0;
-}
+{}
 Vector
 RandomDiscPosition::Get (void) const
 {
-  double theta = m_theta->GetValue ();
-  double rho = m_rho->GetValue ();
+  double theta = m_theta.GetValue ();
+  double rho = m_rho.GetValue ();
   double x = m_x + std::cos (theta) * rho;
   double y = m_y + std::sin (theta) * rho;
   NS_LOG_DEBUG ("Disc position x=" << x << ", y=" << y);
--- a/src/mobility/random-position.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-position.h	Fri Feb 15 20:03:48 2008 +0100
@@ -21,12 +21,11 @@
 #define RANDOM_POSITION_H
 
 #include "ns3/object.h"
+#include "ns3/random-variable.h"
 #include "vector.h"
 
 namespace ns3 {
 
-class RandomVariable;
-
 /**
  * \brief choose a position at random.
  *
@@ -69,8 +68,8 @@
   virtual ~RandomRectanglePosition ();
   virtual Vector Get (void) const;
 private:
-  RandomVariable *m_x;
-  RandomVariable *m_y;
+  RandomVariable m_x;
+  RandomVariable m_y;
 };
 
 /**
@@ -107,8 +106,8 @@
   virtual ~RandomDiscPosition ();
   virtual Vector Get (void) const;
 private:
-  RandomVariable *m_theta;
-  RandomVariable *m_rho;
+  RandomVariable m_theta;
+  RandomVariable m_rho;
   double m_x;
   double m_y;
 };
--- a/src/mobility/random-walk-2d-mobility-model.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-walk-2d-mobility-model.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -69,30 +69,23 @@
   : m_mode (g_mode.GetValue ()),
     m_modeDistance (g_modeDistance.GetValue ()),
     m_modeTime (g_modeTime.GetValue ()),
-    m_speed (g_speed.GetCopy ()),
-    m_direction (g_direction.GetCopy ()),
+    m_speed (g_speed.Get ()),
+    m_direction (g_direction.Get ()),
     m_bounds (g_rectangle.GetValue ())
 {}
 
 RandomWalk2dMobilityModelParameters::~RandomWalk2dMobilityModelParameters ()
-{
-  delete m_speed;
-  delete m_direction;
-  m_speed = 0;
-  m_direction = 0;
-}
+{}
 
 void 
 RandomWalk2dMobilityModelParameters::SetSpeed (const RandomVariable &speed)
 {
-  delete m_speed;
-  m_speed = speed.Copy ();
+  m_speed = speed;
 }
 void 
 RandomWalk2dMobilityModelParameters::SetDirection (const RandomVariable &direction)
 {
-  delete m_direction;
-  m_direction = direction.Copy ();
+  m_direction = direction;
 }
 void 
 RandomWalk2dMobilityModelParameters::SetModeDistance (double distance)
@@ -154,8 +147,8 @@
 void
 RandomWalk2dMobilityModel::Start (void)
 {
-  double speed = m_parameters->m_speed->GetValue ();
-  double direction = m_parameters->m_direction->GetValue ();
+  double speed = m_parameters->m_speed.GetValue ();
+  double direction = m_parameters->m_direction.GetValue ();
   Vector vector (std::cos (direction) * speed,
                  std::sin (direction) * speed,
                  0.0);
--- a/src/mobility/random-walk-2d-mobility-model.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-walk-2d-mobility-model.h	Fri Feb 15 20:03:48 2008 +0100
@@ -25,12 +25,12 @@
 #include "ns3/nstime.h"
 #include "ns3/event-id.h"
 #include "ns3/rectangle.h"
+#include "ns3/random-variable.h"
 #include "mobility-model.h"
 #include "static-speed-helper.h"
 
 namespace ns3 {
 
-class RandomVariable;
 
 /**
  * \brief parameters to control a random walk 2d model
@@ -93,8 +93,8 @@
   enum Mode m_mode;
   double m_modeDistance;
   Time m_modeTime;
-  RandomVariable *m_speed;
-  RandomVariable *m_direction;
+  RandomVariable m_speed;
+  RandomVariable m_direction;
   Rectangle m_bounds;
 };
 
--- a/src/mobility/random-waypoint-mobility-model.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-waypoint-mobility-model.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -47,16 +47,16 @@
 
 
 RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters ()
-  : m_speed (g_speed.GetCopy ()),
-    m_pause (g_pause.GetCopy ())
+  : m_speed (g_speed.Get ()),
+    m_pause (g_pause.Get ())
 {
   m_position = g_position.GetValue ().CreateObject ()->GetObject<RandomPosition> ();
 }
 RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters (Ptr<RandomPosition> randomPosition,
 									      const RandomVariable &speed,
 									      const RandomVariable &pause)
-  : m_speed (speed.Copy ()),
-    m_pause (pause.Copy ()),
+  : m_speed (speed),
+    m_pause (pause),
     m_position (randomPosition)
 {}
 void 
@@ -67,23 +67,17 @@
 void 
 RandomWaypointMobilityModelParameters::SetSpeed (const RandomVariable &speed)
 {
-  delete m_speed;
-  m_speed = speed.Copy ();
+  m_speed = speed;
 }
 void 
 RandomWaypointMobilityModelParameters::SetPause (const RandomVariable &pause)
 {
-  delete m_pause;
-  m_pause = pause.Copy ();
+  m_pause = pause;
 }
 void 
 RandomWaypointMobilityModelParameters::DoDispose (void)
 {
   m_position = 0;
-  delete m_pause;
-  delete m_speed;
-  m_pause = 0;
-  m_speed = 0;  
 }
 
 Ptr<RandomWaypointMobilityModelParameters>
@@ -128,7 +122,7 @@
 {
   Vector m_current = m_helper.GetCurrentPosition ();
   Vector destination = m_parameters->m_position->Get ();
-  double speed = m_parameters->m_speed->GetValue ();
+  double speed = m_parameters->m_speed.GetValue ();
   double dx = (destination.x - m_current.x);
   double dy = (destination.y - m_current.y);
   double dz = (destination.z - m_current.z);
@@ -144,7 +138,7 @@
 void
 RandomWaypointMobilityModel::Start (void)
 {
-  Time pause = Seconds (m_parameters->m_pause->GetValue ());
+  Time pause = Seconds (m_parameters->m_pause.GetValue ());
   m_helper.Pause ();
   NotifyCourseChange ();
   m_event = Simulator::Schedule (pause, &RandomWaypointMobilityModel::BeginWalk, this);
--- a/src/mobility/random-waypoint-mobility-model.h	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/mobility/random-waypoint-mobility-model.h	Fri Feb 15 20:03:48 2008 +0100
@@ -25,11 +25,10 @@
 #include "mobility-model.h"
 #include "random-position.h"
 #include "ns3/ptr.h"
+#include "ns3/random-variable.h"
 
 namespace ns3 {
 
-class RandomVariable;
-
 /**
  * \brief the parameters which control the behavior of a random waypoint
  *        mobility model.
@@ -66,8 +65,8 @@
   friend class RandomWaypointMobilityModel;
   static Ptr<RandomWaypointMobilityModelParameters> GetCurrent (void);
   virtual void DoDispose (void);
-  RandomVariable *m_speed;
-  RandomVariable *m_pause;
+  RandomVariable m_speed;
+  RandomVariable m_pause;
   Ptr<RandomPosition> m_position;
 };
 
--- a/src/node/application.cc	Fri Feb 15 19:14:35 2008 +0100
+++ b/src/node/application.cc	Fri Feb 15 20:03:48 2008 +0100
@@ -59,9 +59,8 @@
 
 void Application::Start(const RandomVariable& startVar)
 {
-  RandomVariable *v = startVar.Copy ();
-  ScheduleStart (Seconds (v->GetValue ()));
-  delete v;
+  RandomVariable v = startVar;
+  ScheduleStart (Seconds (v.GetValue ()));
 }
 
    
@@ -72,9 +71,8 @@
 
 void Application::Stop(const RandomVariable& stopVar)
 {
-  RandomVariable *v = stopVar.Copy ();
-  ScheduleStop (Seconds (v->GetValue ()));
-  delete v;
+  RandomVariable v = stopVar;
+  ScheduleStop (Seconds (v.GetValue ()));
 }
   
 Ptr<Node> Application::GetNode() const