Port remaining RandomVariable implementations to RandomVariableStream
authorMitch Watrous <watrous@u.washington.edu>
Tue, 10 Jul 2012 21:47:16 -0700
changeset 8872 32d1fa5dfb9f
parent 8871 60846d2741c0
child 8873 4060c0782a7e
Port remaining RandomVariable implementations to RandomVariableStream
src/core/model/random-variable-stream.cc
src/core/model/random-variable-stream.h
--- a/src/core/model/random-variable-stream.cc	Tue Jul 10 21:31:47 2012 -0700
+++ b/src/core/model/random-variable-stream.cc	Tue Jul 10 21:47:16 2012 -0700
@@ -186,4 +186,1322 @@
   return (uint32_t)GetValue (m_min, m_max + 1);
 }
 
+NS_OBJECT_ENSURE_REGISTERED(ConstantRandomVariable);
+
+TypeId 
+ConstantRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ConstantRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<ConstantRandomVariable> ()
+    .AddAttribute("Constant", "The constant value returned by this RNG stream.",
+		  DoubleValue(0),
+		  MakeDoubleAccessor(&ConstantRandomVariable::m_constant),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+ConstantRandomVariable::ConstantRandomVariable ()
+{
+  // m_constant is initialized after constructor by attributes
+}
+
+double 
+ConstantRandomVariable::GetConstant (void) const
+{
+  return m_constant;
+}
+
+double 
+ConstantRandomVariable::GetValue (double constant)
+{
+  return constant;
+}
+uint32_t 
+ConstantRandomVariable::GetInteger (uint32_t constant)
+{
+  return constant;
+}
+
+double 
+ConstantRandomVariable::GetValue (void)
+{
+  return GetValue (m_constant);
+}
+uint32_t 
+ConstantRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_constant);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(SequentialRandomVariable);
+
+TypeId 
+SequentialRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SequentialRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<SequentialRandomVariable> ()
+    .AddAttribute("Min", "The first value of the sequence.",
+		  DoubleValue(0),
+		  MakeDoubleAccessor(&SequentialRandomVariable::m_min),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Max", "One more than the last value of the sequence.",
+		  DoubleValue(0),
+		  MakeDoubleAccessor(&SequentialRandomVariable::m_max),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Increment", "The sequence random variable increment.",
+                  StringValue("ns3::ConstantRandomVariable[Contant=1]"),
+                  MakePointerAccessor (&SequentialRandomVariable::m_increment),
+                  MakePointerChecker<RandomVariableStream> ())
+    .AddAttribute("Consecutive", "The number of times each member of the sequence is repeated.",
+                  IntegerValue(1),
+                  MakeIntegerAccessor(&SequentialRandomVariable::m_consecutive),
+                  MakeIntegerChecker<uint32_t>());
+     ;
+  return tid;
+}
+SequentialRandomVariable::SequentialRandomVariable ()
+    :
+    m_current            (0),
+    m_currentConsecutive (0),
+    m_isCurrentSet       (false)
+{
+  // m_min, m_max, m_increment, and m_consecutive are initialized
+  // after constructor by attributes.
+}
+
+double 
+SequentialRandomVariable::GetMin (void) const
+{
+  return m_min;
+}
+
+double 
+SequentialRandomVariable::GetMax (void) const
+{
+  return m_max;
+}
+
+Ptr<RandomVariableStream> 
+SequentialRandomVariable::GetIncrement (void) const
+{
+  return m_increment;
+}
+
+uint32_t 
+SequentialRandomVariable::GetConsecutive (void) const
+{
+  return m_consecutive;
+}
+
+double 
+SequentialRandomVariable::GetValue (void)
+{
+  // Set the current sequence value if it hasn't been set.
+  if (!m_isCurrentSet)
+    {
+      // Start the sequence at its minimium value.
+      m_current = m_min;
+      m_isCurrentSet = true;
+    }
+
+ // Return a sequential series of values
+  double r = m_current;
+  if (++m_currentConsecutive == m_consecutive)
+    { // Time to advance to next
+      m_currentConsecutive = 0;
+      m_current += m_increment->GetValue ();
+      if (m_current >= m_max)
+        {
+          m_current = m_min + (m_current - m_max);
+        }
+    }
+  return r;
+}
+
+uint32_t 
+SequentialRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ExponentialRandomVariable);
+
+TypeId 
+ExponentialRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ExponentialRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<ExponentialRandomVariable> ()
+    .AddAttribute("Mean", "The mean of the values returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&ExponentialRandomVariable::m_mean),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
+		  DoubleValue(0.0),
+		  MakeDoubleAccessor(&ExponentialRandomVariable::m_bound),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+ExponentialRandomVariable::ExponentialRandomVariable ()
+{
+  // m_mean and m_bound are initialized after constructor by attributes
+}
+
+double 
+ExponentialRandomVariable::GetMean (void) const
+{
+  return m_mean;
+}
+double 
+ExponentialRandomVariable::GetBound (void) const
+{
+  return m_bound;
+}
+
+double 
+ExponentialRandomVariable::GetValue (double mean, double bound)
+{
+  while (1)
+    {
+      // Get a uniform random variable in [0,1].
+      double v = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          v = (1 - v);
+        }
+
+      // Calculate the exponential random variable.
+      double r = -mean*std::log (v);
+
+      // Use this value if it's acceptable.
+      if (bound == 0 || r <= bound)
+        {
+          return r;
+        }
+    }
+}
+uint32_t 
+ExponentialRandomVariable::GetInteger (uint32_t mean, uint32_t bound)
+{
+  return static_cast<uint32_t> ( GetValue (mean, bound) );
+}
+
+double 
+ExponentialRandomVariable::GetValue (void)
+{
+  return GetValue (m_mean, m_bound);
+}
+uint32_t 
+ExponentialRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_mean, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ParetoRandomVariable);
+
+TypeId 
+ParetoRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ParetoRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<ParetoRandomVariable> ()
+    .AddAttribute("Mean", "The mean parameter for the Pareto distribution returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&ParetoRandomVariable::m_mean),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Shape", "The shape parameter for the Pareto distribution returned by this RNG stream.",
+		  DoubleValue(2.0),
+		  MakeDoubleAccessor(&ParetoRandomVariable::m_shape),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
+		  DoubleValue(0.0),
+		  MakeDoubleAccessor(&ParetoRandomVariable::m_bound),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+ParetoRandomVariable::ParetoRandomVariable ()
+{
+  // m_mean, m_shape, and m_bound are initialized after constructor
+  // by attributes
+}
+
+double 
+ParetoRandomVariable::GetMean (void) const
+{
+  return m_mean;
+}
+double 
+ParetoRandomVariable::GetShape (void) const
+{
+  return m_shape;
+}
+double 
+ParetoRandomVariable::GetBound (void) const
+{
+  return m_bound;
+}
+
+double 
+ParetoRandomVariable::GetValue (double mean, double shape, double bound)
+{
+  // Calculate the scale parameter.
+  double scale = mean * (shape - 1.0) / shape;
+
+  while (1)
+    {
+      // Get a uniform random variable in [0,1].
+      double v = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          v = (1 - v);
+        }
+
+      // Calculate the Pareto random variable.
+      double r = (scale * ( 1.0 / std::pow (v, 1.0 / shape)));
+
+      // Use this value if it's acceptable.
+      if (bound == 0 || r <= bound)
+        {
+          return r;
+        }
+    }
+}
+uint32_t 
+ParetoRandomVariable::GetInteger (uint32_t mean, uint32_t shape, uint32_t bound)
+{
+  return static_cast<uint32_t> ( GetValue (mean, shape, bound) );
+}
+
+double 
+ParetoRandomVariable::GetValue (void)
+{
+  return GetValue (m_mean, m_shape, m_bound);
+}
+uint32_t 
+ParetoRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_mean, m_shape, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(WeibullRandomVariable);
+
+TypeId 
+WeibullRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::WeibullRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<WeibullRandomVariable> ()
+    .AddAttribute("Scale", "The scale parameter for the Weibull distribution returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&WeibullRandomVariable::m_scale),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Shape", "The shape parameter for the Weibull distribution returned by this RNG stream.",
+		  DoubleValue(1),
+		  MakeDoubleAccessor(&WeibullRandomVariable::m_shape),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
+		  DoubleValue(0.0),
+		  MakeDoubleAccessor(&WeibullRandomVariable::m_bound),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+WeibullRandomVariable::WeibullRandomVariable ()
+{
+  // m_scale, m_shape, and m_bound are initialized after constructor
+  // by attributes
+}
+
+double 
+WeibullRandomVariable::GetScale (void) const
+{
+  return m_scale;
+}
+double 
+WeibullRandomVariable::GetShape (void) const
+{
+  return m_shape;
+}
+double 
+WeibullRandomVariable::GetBound (void) const
+{
+  return m_bound;
+}
+
+double 
+WeibullRandomVariable::GetValue (double scale, double shape, double bound)
+{
+  double exponent = 1.0 / shape;
+  while (1)
+    {
+      // Get a uniform random variable in [0,1].
+      double v = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          v = (1 - v);
+        }
+
+      // Calculate the Weibull random variable.
+      double r = scale * std::pow ( -std::log (v), exponent);
+
+      // Use this value if it's acceptable.
+      if (bound == 0 || r <= bound)
+        {
+          return r;
+        }
+    }
+}
+uint32_t 
+WeibullRandomVariable::GetInteger (uint32_t scale, uint32_t shape, uint32_t bound)
+{
+  return static_cast<uint32_t> ( GetValue (scale, shape, bound) );
+}
+
+double 
+WeibullRandomVariable::GetValue (void)
+{
+  return GetValue (m_scale, m_shape, m_bound);
+}
+uint32_t 
+WeibullRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_scale, m_shape, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(NormalRandomVariable);
+
+const double NormalRandomVariable::INFINITE_VALUE = 1e307;
+
+TypeId 
+NormalRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::NormalRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<NormalRandomVariable> ()
+    .AddAttribute("Mean", "The mean value for the normal distribution returned by this RNG stream.",
+		  DoubleValue(0.0),
+		  MakeDoubleAccessor(&NormalRandomVariable::m_mean),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Variance", "The variance value for the normal distribution returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&NormalRandomVariable::m_variance),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Bound", "The bound on the values returned by this RNG stream.",
+		  DoubleValue(INFINITE_VALUE),
+		  MakeDoubleAccessor(&NormalRandomVariable::m_bound),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+NormalRandomVariable::NormalRandomVariable ()
+  :
+  m_nextValid (false)
+{
+  // m_mean, m_variance, and m_bound are initialized after constructor
+  // by attributes
+}
+
+double 
+NormalRandomVariable::GetMean (void) const
+{
+  return m_mean;
+}
+double 
+NormalRandomVariable::GetVariance (void) const
+{
+  return m_variance;
+}
+double 
+NormalRandomVariable::GetBound (void) const
+{
+  return m_bound;
+}
+
+double 
+NormalRandomVariable::GetValue (double mean, double variance, double bound)
+{
+  if (m_nextValid)
+    { // use previously generated
+      m_nextValid = false;
+      return m_next;
+    }
+  while (1)
+    { // See Simulation Modeling and Analysis p. 466 (Averill Law)
+      // for algorithm; basically a Box-Muller transform:
+      // http://en.wikipedia.org/wiki/Box-Muller_transform
+      double u1 = Peek ()->RandU01 ();
+      double u2 = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          u1 = (1 - u1);
+          u2 = (1 - u2);
+        }
+      double v1 = 2 * u1 - 1;
+      double v2 = 2 * u2 - 1;
+      double w = v1 * v1 + v2 * v2;
+      if (w <= 1.0)
+        { // Got good pair
+          double y = sqrt ((-2 * log (w)) / w);
+          m_next = mean + v2 * y * sqrt (variance);
+          // if next is in bounds, it is valid
+          m_nextValid = fabs (m_next - mean) <= bound;
+          double x1 = mean + v1 * y * sqrt (variance);
+          // if x1 is in bounds, return it
+          if (fabs (x1 - mean) <= bound)
+            {
+              return x1;
+            }
+          // otherwise try and return m_next if it is valid
+          else if (m_nextValid)
+            {
+              m_nextValid = false;
+              return m_next;
+            }
+          // otherwise, just run this loop again
+        }
+    }
+}
+
+uint32_t 
+NormalRandomVariable::GetInteger (uint32_t mean, uint32_t variance, uint32_t bound)
+{
+  return static_cast<uint32_t> ( GetValue (mean, variance, bound) );
+}
+
+double 
+NormalRandomVariable::GetValue (void)
+{
+  return GetValue (m_mean, m_variance, m_bound);
+}
+uint32_t 
+NormalRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_mean, m_variance, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(LogNormalRandomVariable);
+
+TypeId 
+LogNormalRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LogNormalRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<LogNormalRandomVariable> ()
+    .AddAttribute("Mu", "The mu value for the log-normal distribution returned by this RNG stream.",
+		  DoubleValue(0.0),
+		  MakeDoubleAccessor(&LogNormalRandomVariable::m_mu),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Sigma", "The sigma value for the log-normal distribution returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&LogNormalRandomVariable::m_sigma),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+LogNormalRandomVariable::LogNormalRandomVariable ()
+{
+  // m_mu and m_sigma are initialized after constructor by
+  // attributes
+}
+
+double 
+LogNormalRandomVariable::GetMu (void) const
+{
+  return m_mu;
+}
+double 
+LogNormalRandomVariable::GetSigma (void) const
+{
+  return m_sigma;
+}
+
+// The code from this function was adapted from the GNU Scientific
+// Library 1.8:
+/* randist/lognormal.c
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* The lognormal distribution has the form
+
+   p(x) dx = 1/(x * sqrt(2 pi sigma^2)) exp(-(ln(x) - zeta)^2/2 sigma^2) dx
+
+   for x > 0. Lognormal random numbers are the exponentials of
+   gaussian random numbers */
+double 
+LogNormalRandomVariable::GetValue (double mu, double sigma)
+{
+  double v1, v2, r2, normal, x;
+
+  do
+    {
+      /* choose x,y in uniform square (-1,-1) to (+1,+1) */
+
+      double u1 = Peek ()->RandU01 ();
+      double u2 = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          u1 = (1 - u1);
+          u2 = (1 - u2);
+        }
+
+      v1 = -1 + 2 * u1;
+      v2 = -1 + 2 * u2;
+
+      /* see if it is in the unit circle */
+      r2 = v1 * v1 + v2 * v2;
+    }
+  while (r2 > 1.0 || r2 == 0);
+
+  normal = v1 * std::sqrt (-2.0 * std::log (r2) / r2);
+
+  x =  std::exp (sigma * normal + mu);
+
+  return x;
+}
+
+uint32_t 
+LogNormalRandomVariable::GetInteger (uint32_t mu, uint32_t sigma)
+{
+  return static_cast<uint32_t> ( GetValue (mu, sigma));
+}
+
+double 
+LogNormalRandomVariable::GetValue (void)
+{
+  return GetValue (m_mu, m_sigma);
+}
+uint32_t 
+LogNormalRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_mu, m_sigma);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(GammaRandomVariable);
+
+TypeId 
+GammaRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::GammaRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<GammaRandomVariable> ()
+    .AddAttribute("Alpha", "The alpha value for the gamma distribution returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&GammaRandomVariable::m_alpha),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Beta", "The beta value for the gamma distribution returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&GammaRandomVariable::m_beta),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+GammaRandomVariable::GammaRandomVariable ()
+  :
+  m_nextValid (false)
+{
+  // m_alpha and m_beta are initialized after constructor by
+  // attributes
+}
+
+double 
+GammaRandomVariable::GetAlpha (void) const
+{
+  return m_alpha;
+}
+double 
+GammaRandomVariable::GetBeta (void) const
+{
+  return m_beta;
+}
+
+/*
+  The code for the following generator functions was adapted from ns-2
+  tools/ranvar.cc
+
+  Originally the algorithm was devised by Marsaglia in 2000:
+  G. Marsaglia, W. W. Tsang: A simple method for gereating Gamma variables
+  ACM Transactions on mathematical software, Vol. 26, No. 3, Sept. 2000
+
+  The Gamma distribution density function has the form
+
+                             x^(alpha-1) * exp(-x/beta)
+        p(x; alpha, beta) = ----------------------------
+                             beta^alpha * Gamma(alpha)
+
+  for x > 0.
+*/
+double 
+GammaRandomVariable::GetValue (double alpha, double beta)
+{
+  if (alpha < 1)
+    {
+      double u = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          u = (1 - u);
+        }
+      return GetValue (1.0 + alpha, beta) * std::pow (u, 1.0 / alpha);
+    }
+
+  double x, v, u;
+  double d = alpha - 1.0 / 3.0;
+  double c = (1.0 / 3.0) / sqrt (d);
+
+  while (1)
+    {
+      do
+        {
+          // Get a value from a normal distribution that has mean
+          // zero, variance 1, and no bound.
+          double mean = 0.0;
+          double variance = 1.0;
+          double bound = NormalRandomVariable::INFINITE_VALUE;
+          x = GetNormalValue (mean, variance, bound);
+
+          v = 1.0 + c * x;
+        }
+      while (v <= 0);
+
+      v = v * v * v;
+      u = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          u = (1 - u);
+        }
+      if (u < 1 - 0.0331 * x * x * x * x)
+        {
+          break;
+        }
+      if (log (u) < 0.5 * x * x + d * (1 - v + log (v)))
+        {
+          break;
+        }
+    }
+
+  return beta * d * v;
+}
+
+uint32_t 
+GammaRandomVariable::GetInteger (uint32_t alpha, uint32_t beta)
+{
+  return static_cast<uint32_t> ( GetValue (alpha, beta));
+}
+
+double 
+GammaRandomVariable::GetValue (void)
+{
+  return GetValue (m_alpha, m_beta);
+}
+uint32_t 
+GammaRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_alpha, m_beta);
+}
+
+double 
+GammaRandomVariable::GetNormalValue (double mean, double variance, double bound)
+{
+  if (m_nextValid)
+    { // use previously generated
+      m_nextValid = false;
+      return m_next;
+    }
+  while (1)
+    { // See Simulation Modeling and Analysis p. 466 (Averill Law)
+      // for algorithm; basically a Box-Muller transform:
+      // http://en.wikipedia.org/wiki/Box-Muller_transform
+      double u1 = Peek ()->RandU01 ();
+      double u2 = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          u1 = (1 - u1);
+          u2 = (1 - u2);
+        }
+      double v1 = 2 * u1 - 1;
+      double v2 = 2 * u2 - 1;
+      double w = v1 * v1 + v2 * v2;
+      if (w <= 1.0)
+        { // Got good pair
+          double y = sqrt ((-2 * log (w)) / w);
+          m_next = mean + v2 * y * sqrt (variance);
+          // if next is in bounds, it is valid
+          m_nextValid = fabs (m_next - mean) <= bound;
+          double x1 = mean + v1 * y * sqrt (variance);
+          // if x1 is in bounds, return it
+          if (fabs (x1 - mean) <= bound)
+            {
+              return x1;
+            }
+          // otherwise try and return m_next if it is valid
+          else if (m_nextValid)
+            {
+              m_nextValid = false;
+              return m_next;
+            }
+          // otherwise, just run this loop again
+        }
+    }
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ErlangRandomVariable);
+
+TypeId 
+ErlangRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ErlangRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<ErlangRandomVariable> ()
+    .AddAttribute("K", "The k value for the Erlang distribution returned by this RNG stream.",
+		  IntegerValue(1),
+		  MakeIntegerAccessor(&ErlangRandomVariable::m_k),
+		  MakeIntegerChecker<uint32_t>())
+    .AddAttribute("Lambda", "The lambda value for the Erlang distribution returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&ErlangRandomVariable::m_lambda),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+ErlangRandomVariable::ErlangRandomVariable ()
+{
+  // m_k and m_lambda are initialized after constructor by attributes
+}
+
+uint32_t 
+ErlangRandomVariable::GetK (void) const
+{
+  return m_k;
+}
+double 
+ErlangRandomVariable::GetLambda (void) const
+{
+  return m_lambda;
+}
+
+/*
+  The code for the following generator functions was adapted from ns-2
+  tools/ranvar.cc
+
+  The Erlang distribution density function has the form
+
+                           x^(k-1) * exp(-x/lambda)
+        p(x; k, lambda) = ---------------------------
+                             lambda^k * (k-1)!
+
+  for x > 0.
+*/
+double 
+ErlangRandomVariable::GetValue (uint32_t k, double lambda)
+{
+  double mean = lambda;
+  double bound = 0.0;
+
+  double result = 0;
+  for (unsigned int i = 0; i < k; ++i)
+    {
+      result += GetExponentialValue (mean, bound);
+
+    }
+
+  return result;
+}
+
+uint32_t 
+ErlangRandomVariable::GetInteger (uint32_t k, uint32_t lambda)
+{
+  return static_cast<uint32_t> ( GetValue (k, lambda));
+}
+
+double 
+ErlangRandomVariable::GetValue (void)
+{
+  return GetValue (m_k, m_lambda);
+}
+uint32_t 
+ErlangRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_k, m_lambda);
+}
+
+double 
+ErlangRandomVariable::GetExponentialValue (double mean, double bound)
+{
+  while (1)
+    {
+      // Get a uniform random variable in [0,1].
+      double v = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          v = (1 - v);
+        }
+
+      // Calculate the exponential random variable.
+      double r = -mean*std::log (v);
+
+      // Use this value if it's acceptable.
+      if (bound == 0 || r <= bound)
+        {
+          return r;
+        }
+    }
+}
+
+NS_OBJECT_ENSURE_REGISTERED(TriangularRandomVariable);
+
+TypeId 
+TriangularRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TriangularRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<TriangularRandomVariable> ()
+    .AddAttribute("Mean", "The mean value for the triangular distribution returned by this RNG stream.",
+		  DoubleValue(0.5),
+		  MakeDoubleAccessor(&TriangularRandomVariable::m_mean),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Min", "The lower bound on the values returned by this RNG stream.",
+		  DoubleValue(0.0),
+		  MakeDoubleAccessor(&TriangularRandomVariable::m_min),
+		  MakeDoubleChecker<double>())
+    .AddAttribute("Max", "The upper bound on the values returned by this RNG stream.",
+		  DoubleValue(1.0),
+		  MakeDoubleAccessor(&TriangularRandomVariable::m_max),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+TriangularRandomVariable::TriangularRandomVariable ()
+  :
+  m_mode (0.5)
+{
+  // m_mean, m_min, and m_max are initialized after constructor by
+  // attributes
+}
+
+double 
+TriangularRandomVariable::GetMean (void) const
+{
+  return m_mean;
+}
+double 
+TriangularRandomVariable::GetMin (void) const
+{
+  return m_min;
+}
+double 
+TriangularRandomVariable::GetMax (void) const
+{
+  return m_max;
+}
+
+double 
+TriangularRandomVariable::GetValue (double mean, double min, double max)
+{
+  // Calculate the mode.
+  double mode = 3.0 * mean - min - max;
+
+  // Get a uniform random variable in [0,1].
+  double u = Peek ()->RandU01 ();
+  if (IsAntithetic ())
+    {
+      u = (1 - u);
+    }
+
+  // Calculate the triangular random variable.
+  if (u <= (mode - min) / (max - min) )
+    {
+      return min + sqrt (u * (max - min) * (mode - min) );
+    }
+  else
+    {
+      return max - sqrt ( (1 - u) * (max - min) * (max - mode) );
+    }
+}
+
+uint32_t 
+TriangularRandomVariable::GetInteger (uint32_t mean, uint32_t min, uint32_t max)
+{
+  return static_cast<uint32_t> ( GetValue (mean, min, max) );
+}
+
+double 
+TriangularRandomVariable::GetValue (void)
+{
+  return GetValue (m_mean, m_min, m_max);
+}
+uint32_t 
+TriangularRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_mean, m_min, m_max);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ZipfRandomVariable);
+
+TypeId 
+ZipfRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ZipfRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<ZipfRandomVariable> ()
+    .AddAttribute("N", "The n value for the Zipf distribution returned by this RNG stream.",
+		  IntegerValue(1),
+		  MakeIntegerAccessor(&ZipfRandomVariable::m_n),
+		  MakeIntegerChecker<uint32_t>())
+    .AddAttribute("Alpha", "The alpha value for the Zipf distribution returned by this RNG stream.",
+		  DoubleValue(0.0),
+		  MakeDoubleAccessor(&ZipfRandomVariable::m_alpha),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+ZipfRandomVariable::ZipfRandomVariable ()
+{
+  // m_n and m_alpha are initialized after constructor by attributes
+}
+
+uint32_t 
+ZipfRandomVariable::GetN (void) const
+{
+  return m_n;
+}
+double 
+ZipfRandomVariable::GetAlpha (void) const
+{
+  return m_alpha;
+}
+
+double 
+ZipfRandomVariable::GetValue (uint32_t n, double alpha)
+{
+  // Calculate the normalization constant c.
+  m_c = 0.0;
+  for (uint32_t i = 1; i <= n; i++)
+    {
+      m_c += (1.0 / std::pow ((double)i,alpha));
+    }
+  m_c = 1.0 / m_c;
+
+  // Get a uniform random variable in [0,1].
+  double u = Peek ()->RandU01 ();
+  if (IsAntithetic ())
+    {
+      u = (1 - u);
+    }
+
+  double sum_prob = 0,zipf_value = 0;
+  for (uint32_t i = 1; i <= m_n; i++)
+    {
+      sum_prob += m_c / std::pow ((double)i,m_alpha);
+      if (sum_prob > u)
+        {
+          zipf_value = i;
+          break;
+        }
+    }
+  return zipf_value;
+}
+
+uint32_t 
+ZipfRandomVariable::GetInteger (uint32_t n, uint32_t alpha)
+{
+  return static_cast<uint32_t> ( GetValue (n, alpha));
+}
+
+double 
+ZipfRandomVariable::GetValue (void)
+{
+  return GetValue (m_n, m_alpha);
+}
+uint32_t 
+ZipfRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_n, m_alpha);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ZetaRandomVariable);
+
+TypeId 
+ZetaRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ZetaRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<ZetaRandomVariable> ()
+    .AddAttribute("Alpha", "The alpha value for the zeta distribution returned by this RNG stream.",
+		  DoubleValue(3.14),
+		  MakeDoubleAccessor(&ZetaRandomVariable::m_alpha),
+		  MakeDoubleChecker<double>())
+    ;
+  return tid;
+}
+ZetaRandomVariable::ZetaRandomVariable ()
+{
+  // m_alpha is initialized after constructor by attributes
+}
+
+double 
+ZetaRandomVariable::GetAlpha (void) const
+{
+  return m_alpha;
+}
+
+double 
+ZetaRandomVariable::GetValue (double alpha)
+{
+  m_b = std::pow (2.0, alpha - 1.0);
+
+  double u, v;
+  double X, T;
+  double test;
+
+  do
+    {
+      // Get a uniform random variable in [0,1].
+      u = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          u = (1 - u);
+        }
+
+      // Get a uniform random variable in [0,1].
+      v = Peek ()->RandU01 ();
+      if (IsAntithetic ())
+        {
+          v = (1 - v);
+        }
+
+      X = std::floor (std::pow (u, -1.0 / (m_alpha - 1.0)));
+      T = std::pow (1.0 + 1.0 / X, m_alpha - 1.0);
+      test = v * X * (T - 1.0) / (m_b - 1.0);
+    }
+  while ( test > (T / m_b) );
+
+  return X;
+}
+
+uint32_t 
+ZetaRandomVariable::GetInteger (uint32_t alpha)
+{
+  return static_cast<uint32_t> ( GetValue (alpha));
+}
+
+double 
+ZetaRandomVariable::GetValue (void)
+{
+  return GetValue (m_alpha);
+}
+uint32_t 
+ZetaRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue (m_alpha);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(DeterministicRandomVariable);
+
+TypeId 
+DeterministicRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::DeterministicRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<DeterministicRandomVariable> ()
+    ;
+  return tid;
+}
+DeterministicRandomVariable::DeterministicRandomVariable ()
+  :
+  m_count (0),
+  m_next (0),
+  m_data (0)
+{
+}
+DeterministicRandomVariable::~DeterministicRandomVariable ()
+{
+  // Delete any values currently set.
+  if (m_data != 0)
+  {
+    delete[] m_data;
+  }
+}
+
+void
+DeterministicRandomVariable::SetValueArray (double* values, uint64_t length)
+{
+  // Delete any values currently set.
+  if (m_data != 0)
+  {
+    delete[] m_data;
+  }
+
+  // Make room for the values being set.
+  m_data = new double[length];
+  m_count = length;
+  m_next = length;
+
+  // Copy the values.
+  for (uint64_t i = 0; i < m_count; i++)
+    {
+      m_data[i] = values[i];
+    }
+}
+
+double 
+DeterministicRandomVariable::GetValue (void)
+{
+  // Make sure the array has been set.
+  NS_ASSERT (m_count > 0);
+
+  if (m_next == m_count)
+    {
+      m_next = 0;
+    }
+  return m_data[m_next++];
+}
+
+uint32_t 
+DeterministicRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED(EmpiricalRandomVariable);
+
+// ValueCDF methods
+EmpiricalRandomVariable::ValueCDF::ValueCDF ()
+  : value (0.0),
+    cdf (0.0)
+{
+}
+EmpiricalRandomVariable::ValueCDF::ValueCDF (double v, double c)
+  : value (v),
+    cdf (c)
+{
+}
+EmpiricalRandomVariable::ValueCDF::ValueCDF (const ValueCDF& c)
+  : value (c.value),
+    cdf (c.cdf)
+{
+}
+
+TypeId 
+EmpiricalRandomVariable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::EmpiricalRandomVariable")
+    .SetParent<RandomVariableStream>()
+    .AddConstructor<EmpiricalRandomVariable> ()
+    ;
+  return tid;
+}
+EmpiricalRandomVariable::EmpiricalRandomVariable ()
+  :
+  validated (false)
+{
+}
+
+double 
+EmpiricalRandomVariable::GetValue (void)
+{
+  // Return a value from the empirical distribution
+  // This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
+  if (emp.size () == 0)
+    {
+      return 0.0; // HuH? No empirical data
+    }
+  if (!validated)
+    {
+      Validate ();      // Insure in non-decreasing
+    }
+
+  // Get a uniform random variable in [0,1].
+  double r = Peek ()->RandU01 ();
+  if (IsAntithetic ())
+    {
+      r = (1 - r);
+    }
+
+  if (r <= emp.front ().cdf)
+    {
+      return emp.front ().value; // Less than first
+    }
+  if (r >= emp.back ().cdf)
+    {
+      return emp.back ().value;  // Greater than last
+    }
+  // Binary search
+  std::vector<ValueCDF>::size_type bottom = 0;
+  std::vector<ValueCDF>::size_type top = emp.size () - 1;
+  while (1)
+    {
+      std::vector<ValueCDF>::size_type c = (top + bottom) / 2;
+      if (r >= emp[c].cdf && r < emp[c + 1].cdf)
+        { // Found it
+          return Interpolate (emp[c].cdf, emp[c + 1].cdf,
+                              emp[c].value, emp[c + 1].value,
+                              r);
+        }
+      // Not here, adjust bounds
+      if (r < emp[c].cdf)
+        {
+          top    = c - 1;
+        }
+      else
+        {
+          bottom = c + 1;
+        }
+    }
+}
+
+uint32_t 
+EmpiricalRandomVariable::GetInteger (void)
+{
+  return (uint32_t)GetValue ();
+}
+
+void EmpiricalRandomVariable::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 EmpiricalRandomVariable::Validate ()
+{
+  ValueCDF prior;
+  for (std::vector<ValueCDF>::size_type i = 0; i < emp.size (); ++i)
+    {
+      ValueCDF& current = emp[i];
+      if (current.value < prior.value || current.cdf < prior.cdf)
+        { // Error
+          std::cerr << "Empirical Dist error,"
+               << " current value " << current.value
+               << " prior value "   << prior.value
+               << " current cdf "   << current.cdf
+                    << " prior cdf "     << prior.cdf << std::endl;
+          NS_FATAL_ERROR ("Empirical Dist error");
+        }
+      prior = current;
+    }
+  validated = true;
+}
+
+double EmpiricalRandomVariable::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));
+}
+
 } // namespace ns3
--- a/src/core/model/random-variable-stream.h	Tue Jul 10 21:31:47 2012 -0700
+++ b/src/core/model/random-variable-stream.h	Tue Jul 10 21:47:16 2012 -0700
@@ -264,6 +264,2172 @@
   double m_max;
 };
 
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that returns a constant.
+ *
+ * Class ConstantRandomVariable returns the same value for every sample.
+ */
+class ConstantRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a constant RNG with the default constant value.
+   */
+  ConstantRandomVariable ();
+
+  /**
+   * \brief Returns the constant value returned by this RNG stream.
+   * \return The constant value returned by this RNG stream.
+   */
+  double GetConstant (void) const;
+
+  /**
+   * \brief Returns the value passed in.
+   * \return The floating point value passed in.
+   */
+  double GetValue (double constant);
+  /**
+   * \brief Returns the value passed in.
+   * \return The integer value passed in.
+   */
+  uint32_t GetInteger (uint32_t constant);
+
+  /**
+   * \brief Returns the constant value returned by this RNG stream.
+   * \return The constant value returned by this RNG stream.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns an integer cast of the constant value returned by this RNG stream.
+   * \return Integer cast of the constant value returned by this RNG stream.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The constant value returned by this RNG stream.
+  double m_constant;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that returns a sequential
+ * list of values
+ *
+ * Class SequentialRandomVariable defines a random number generator
+ * that returns a sequence of values.  The sequence monotonically
+ * increases for a period, then wraps around to the low value and
+ * begins monotonically increasing again.
+ */
+class SequentialRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a sequential RNG with the default values for the sequence parameters.
+   */
+  SequentialRandomVariable ();
+
+  /**
+   * \brief Returns the first value of the sequence.
+   * \return The first value of the sequence.
+   */
+  double GetMin (void) const;
+
+  /**
+   * \brief Returns one more than the last value of the sequence.
+   * \return One more than the last value of the sequence.
+   */
+  double GetMax (void) const;
+
+  /**
+   * \brief Returns the random variable increment for the sequence.
+   * \return The random variable increment for the sequence.
+   */
+  Ptr<RandomVariableStream> GetIncrement (void) const;
+
+  /**
+   * \brief Returns the number of times each member of the sequence is repeated.
+   * \return The number of times each member of the sequence is repeated.
+   */
+  uint32_t GetConsecutive (void) const;
+
+  /**
+   * \brief Returns the next value in the sequence returned by this RNG stream.
+   * \return The next value in the sequence returned by this RNG stream.
+   *
+   * The following four parameters define the sequence.  For example,
+   *
+   *   - m_min         = 0   (First value of the sequence)
+   *   - m_max         = 5   (One more than the last value of the sequence)
+   *   - m_increment   = 1   (Random variable increment between sequence values)
+   *   - m_consecutive = 2   (Number of times each member of the sequence is repeated)
+   *
+   * creates a RNG that has the sequence 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0 ...
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns an integer cast of the next value in the sequence returned by this RNG stream.
+   * \return Integer cast of the next value in the sequence returned by this RNG stream.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The first value of the sequence.
+  double m_min;
+
+  /// One more than the last value of the sequence.
+  double m_max;
+
+  /// The sequence random variable increment.
+  Ptr<RandomVariableStream> m_increment;
+
+  /// The number of times each member of the sequence is repeated.
+  uint32_t m_consecutive;
+
+  /// The current sequence value.
+  double m_current;
+
+  /// The number of times the sequence has been repeated.
+  uint32_t m_currentConsecutive;
+
+  /// Indicates if the current sequence value has been set.
+  bool m_isCurrentSet;
+
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The exponential distribution Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed exponential distribution.  It also supports the generation of
+ * single random numbers from various exponential distributions.
+ *
+ * The probability density function of an exponential variable
+ * is defined over the interval [0, \f$+\infty\f$) as:
+ * \f$ \alpha  e^{-\alpha x} \f$
+ * where \f$ \alpha = \frac{1}{mean} \f$
+ *
+ * Since exponential distributions can theoretically return unbounded
+ * values, it is sometimes useful to specify a fixed upper limit.  The
+ * bounded version is defined over the interval [0,b] as: \f$ \alpha
+ * e^{-\alpha x} \quad x \in [0,b] \f$.  Note that in this case the
+ * true mean of the distribution is slightly smaller than the mean
+ * value specified: \f$ 1/\alpha - b/(e^{\alpha \, b}-1) \f$.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double mean = 3.14;
+ *   double bound = 0.0;
+ *  
+ *   Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
+ *   x->SetAttribute ("Mean", DoubleValue (mean));
+ *   x->SetAttribute ("Bound", DoubleValue (bound));
+ * 
+ *   // The expected value for the mean of the values returned by an
+ *   // exponentially distributed random variable is equal to mean.
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class ExponentialRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a exponential distribution RNG with the default
+   * values for the mean and upper bound.
+   */
+  ExponentialRandomVariable ();
+
+  /**
+   * \brief Returns the mean value of the random variables returned by this RNG stream.
+   * \return The mean value of the random variables returned by this RNG stream.
+   */
+  double GetMean (void) const;
+
+  /**
+   * \brief Returns the upper bound on values that can be returned by this RNG stream.
+   * \return The upper bound on values that can be returned by this RNG stream.
+   */
+  double GetBound (void) const;
+
+  /**
+   * \brief Returns a random double from an exponential distribution with the specified mean and upper bound.
+   * \param mean Mean value of the random variables.
+   * \param bound Upper bound on values returned.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = - mean * \log(u) 
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = - mean * \log(1 - u), 
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from the 1.
+   */
+  double GetValue (double mean, double bound);
+
+  /**
+   * \brief Returns a random unsigned integer from an exponential distribution with the specified mean and upper bound.
+   * \param mean Mean value of the random variables.
+   * \param bound Upper bound on values returned.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = - mean * \log(u) 
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = - mean * \log(1 - u), 
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from the 1.
+   */
+  uint32_t GetInteger (uint32_t mean, uint32_t bound);
+
+  /**
+   * \brief Returns a random double from an exponential distribution with the current mean and upper bound.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = - mean * \log(u) 
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = - mean * \log(1 - u), 
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from the 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from an exponential distribution with the current mean and upper bound.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = - mean * \log(u) 
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = - mean * \log(1 - u), 
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from the 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The mean value of the random variables returned by this RNG stream.
+  double m_mean;
+
+  /// The upper bound on values that can be returned by this RNG stream.
+  double m_bound;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Pareto distribution Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Pareto distribution.  It also supports the generation of
+ * single random numbers from various Pareto distributions.
+ *
+ * The probability density function of a Pareto variable is defined
+ * over the range [\f$x_m\f$,\f$+\infty\f$) as: \f$ k \frac{x_m^k}{x^{k+1}}\f$
+ * where \f$x_m > 0\f$ is called the scale parameter and \f$ k > 0\f$
+ * is called the pareto index or shape.
+ *
+ * The parameter \f$ x_m \f$ can be infered from the mean and the parameter \f$ k \f$
+ * with the equation \f$ x_m = mean \frac{k-1}{k},  k > 1\f$.
+ *
+ * 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.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double mean = 5.0;
+ *   double shape = 2.0;
+ * 
+ *   Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
+ *   x->SetAttribute ("Mean", DoubleValue (mean));
+ *   x->SetAttribute ("Shape", DoubleValue (shape));
+ * 
+ *   // The expected value for the mean of the values returned by a
+ *   // Pareto distributed random variable is
+ *   //
+ *   //                   shape * scale
+ *   //     E[value]  =  ---------------  ,
+ *   //                     shape - 1
+ *   // 
+ *   // where
+ *   // 
+ *   //     scale  =  mean * (shape - 1.0) / shape .
+ *   //
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class ParetoRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a Pareto distribution RNG with the default
+   * values for the mean, the shape, and upper bound.
+   */
+  ParetoRandomVariable ();
+
+  /**
+   * \brief Returns the mean parameter for the Pareto distribution returned by this RNG stream.
+   * \return The mean parameter for the Pareto distribution returned by this RNG stream.
+   */
+  double GetMean (void) const;
+
+  /**
+   * \brief Returns the shape parameter for the Pareto distribution returned by this RNG stream.
+   * \return The shape parameter for the Pareto distribution returned by this RNG stream.
+   */
+  double GetShape (void) const;
+
+  /**
+   * \brief Returns the upper bound on values that can be returned by this RNG stream.
+   * \return The upper bound on values that can be returned by this RNG stream.
+   */
+  double GetBound (void) const;
+
+  /**
+   * \brief Returns a random double from a Pareto distribution with the specified mean, shape, and upper bound.
+   * \param mean Mean parameter for the Pareto distribution.
+   * \param shape Shape parameter for the Pareto distribution.
+   * \param bound Upper bound on values returned.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = \frac{scale}{u^{\frac{1}{shape}}}
+   *    \f]
+   *
+   * is a value that would be returned normally, where
+   *     
+   *    \f[
+   *         scale  =  mean * (shape - 1.0) / shape  .
+   *    \f]
+   *    
+   * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *         x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+   *    \f]
+   *
+   * which now involves the distance \f$u\f$ is from 1 in the denonator.
+   */
+  double GetValue (double mean, double shape, double bound);
+
+  /**
+   * \brief Returns a random unsigned integer from a Pareto distribution with the specified mean, shape, and upper bound.
+   * \param mean Mean parameter for the Pareto distribution.
+   * \param shape Shape parameter for the Pareto distribution.
+   * \param bound Upper bound on values returned.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = \frac{scale}{u^{\frac{1}{shape}}}
+   *    \f]
+   *
+   * is a value that would be returned normally, where
+   *     
+   *    \f[
+   *         scale  =  mean * (shape - 1.0) / shape  .
+   *    \f]
+   *    
+   * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *         x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+   *    \f]
+   *
+   * which now involves the distance \f$u\f$ is from 1 in the denonator.
+   */
+  uint32_t GetInteger (uint32_t mean, uint32_t shape, uint32_t bound);
+
+  /**
+   * \brief Returns a random double from a Pareto distribution with the current mean, shape, and upper bound.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = \frac{scale}{u^{\frac{1}{shape}}}
+   *    \f]
+   *
+   * is a value that would be returned normally, where
+   *     
+   *    \f[
+   *         scale  =  mean * (shape - 1.0) / shape  .
+   *    \f]
+   *    
+   * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *         x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+   *    \f]
+   *
+   * which now involves the distance \f$u\f$ is from 1 in the denonator.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the three-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a Pareto distribution with the current mean, shape, and upper bound.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = \frac{scale}{u^{\frac{1}{shape}}}
+   *    \f]
+   *
+   * is a value that would be returned normally, where
+   *     
+   *    \f[
+   *         scale  =  mean * (shape - 1.0) / shape  .
+   *    \f]
+   *    
+   * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *         x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+   *    \f]
+   *
+   * which now involves the distance \f$u\f$ is from 1 in the denonator.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The mean parameter for the Pareto distribution returned by this RNG stream.
+  double m_mean;
+
+  /// The shape parameter for the Pareto distribution returned by this RNG stream.
+  double m_shape;
+
+  /// The upper bound on values that can be returned by this RNG stream.
+  double m_bound;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Weibull distribution Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Weibull distribution.  It also supports the generation of
+ * single random numbers from various Weibull distributions.
+ *
+ * The probability density function is defined over the interval [0, \f$+\infty\f$]
+ * as: \f$ \frac{k}{\lambda}\left(\frac{x}{\lambda}\right)^{k-1}e^{-\left(\frac{x}{\lambda}\right)^k} \f$
+ * where \f$ k > 0\f$ is the shape parameter and \f$ \lambda > 0\f$  is the scale parameter. The
+ * specified mean is related to the scale and shape parameters by the following relation:
+ * \f$ mean = \lambda\Gamma\left(1+\frac{1}{k}\right) \f$ where \f$ \Gamma \f$ is the Gamma function.
+ *
+ * Since Weibull 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.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double scale = 5.0;
+ *   double shape = 1.0;
+ * 
+ *   Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
+ *   x->SetAttribute ("Scale", DoubleValue (scale));
+ *   x->SetAttribute ("Shape", DoubleValue (shape));
+ * 
+ *   // The expected value for the mean of the values returned by a
+ *   // Weibull distributed random variable is
+ *   //
+ *   //     E[value]  =  scale * Gamma(1 + 1 / shape)  ,
+ *   //               
+ *   // where Gamma() is the Gamma function.  Note that 
+ *   //               
+ *   //     Gamma(n)  =  (n - 1)!
+ *   //               
+ *   // if n is a positive integer.
+ *   //
+ *   // For this example,
+ *   //
+ *   //     Gamma(1 + 1 / shape)  =  Gamma(1 + 1 / 1)
+ *   //                           =  Gamma(2)
+ *   //                           =  (2 - 1)!
+ *   //                           =  1
+ *   //
+ *   // which means
+ *   //
+ *   //     E[value]  =  scale  .
+ *   //               
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class WeibullRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a Weibull distribution RNG with the default
+   * values for the scale, shape, and upper bound.
+   */
+  WeibullRandomVariable ();
+
+  /**
+   * \brief Returns the scale parameter for the Weibull distribution returned by this RNG stream.
+   * \return The scale parameter for the Weibull distribution returned by this RNG stream.
+   */
+  double GetScale (void) const;
+
+  /**
+   * \brief Returns the shape parameter for the Weibull distribution returned by this RNG stream.
+   * \return The shape parameter for the Weibull distribution returned by this RNG stream.
+   */
+  double GetShape (void) const;
+
+  /**
+   * \brief Returns the upper bound on values that can be returned by this RNG stream.
+   * \return The upper bound on values that can be returned by this RNG stream.
+   */
+  double GetBound (void) const;
+
+  /**
+   * \brief Returns a random double from a Weibull distribution with the specified scale, shape, and upper bound.
+   * \param scale Scale parameter for the Weibull distribution.
+   * \param shape Shape parameter for the Weibull distribution.
+   * \param bound Upper bound on values returned.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = scale * {(-\log(u))}^{\frac{1}{shape}}
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from 1.
+   */
+  double GetValue (double scale, double shape, double bound);
+
+  /**
+   * \brief Returns a random unsigned integer from a Weibull distribution with the specified scale, shape, and upper bound.
+   * \param scale Scale parameter for the Weibull distribution.
+   * \param shape Shape parameter for the Weibull distribution.
+   * \param bound Upper bound on values returned.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = scale * {(-\log(u))}^{\frac{1}{shape}}
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from 1.
+   */
+  uint32_t GetInteger (uint32_t scale, uint32_t shape, uint32_t bound);
+
+  /**
+   * \brief Returns a random double from a Weibull distribution with the current scale, shape, and upper bound.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = scale * {(-\log(u))}^{\frac{1}{shape}}
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the three-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a Weibull distribution with the current scale, shape, and upper bound.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = scale * {(-\log(u))}^{\frac{1}{shape}}
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The scale parameter for the Weibull distribution returned by this RNG stream.
+  double m_scale;
+
+  /// The shape parameter for the Weibull distribution returned by this RNG stream.
+  double m_shape;
+
+  /// The upper bound on values that can be returned by this RNG stream.
+  double m_bound;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The normal (Gaussian) distribution Random Number Generator
+ * (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed normal distribution.  It also supports the generation of
+ * single random numbers from various normal distributions.
+ *
+ * The density probability function is defined over the interval (\f$-\infty\f$,\f$+\infty\f$)
+ * as: \f$ \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{s\sigma^2}}\f$
+ * where \f$ mean = \mu \f$ and \f$ variance = \sigma^2 \f$
+ *
+ * Since normal distributions can theoretically return unbounded
+ * values, it is sometimes useful to specify a fixed bound.  The
+ * NormalRandomVariable is bounded symmetrically about the mean by
+ * this bound, i.e. its values are confined to the interval
+ * [\f$mean-bound\f$,\f$mean+bound\f$].
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double mean = 5.0;
+ *   double variance = 2.0;
+ *   
+ *   Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
+ *   x->SetAttribute ("Mean", DoubleValue (mean));
+ *   x->SetAttribute ("Variance", DoubleValue (variance));
+ *   
+ *   // The expected value for the mean of the values returned by a
+ *   // normally distributed random variable is equal to mean.
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class NormalRandomVariable : public RandomVariableStream
+{
+public:
+  static const double INFINITE_VALUE;
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a normal distribution RNG with the default
+   * values for the mean, variance, and bound.
+   */
+  NormalRandomVariable ();
+
+  /**
+   * \brief Returns the mean value for the normal distribution returned by this RNG stream.
+   * \return The mean value for the normal distribution returned by this RNG stream.
+   */
+  double GetMean (void) const;
+
+  /**
+   * \brief Returns the variance value for the normal distribution returned by this RNG stream.
+   * \return The variance value for the normal distribution returned by this RNG stream.
+   */
+  double GetVariance (void) const;
+
+  /**
+   * \brief Returns the bound on values that can be returned by this RNG stream.
+   * \return The bound on values that can be returned by this RNG stream.
+   */
+  double GetBound (void) const;
+
+  /**
+   * \brief Returns a random double from a normal distribution with the specified mean, variance, and bound.
+   * \param mean Mean value for the normal distribution.
+   * \param variance Variance value for the normal distribution.
+   * \param bound Bound on values returned.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & 2 * u1 - 1     \\
+   *         v2 & = & 2 * u2 - 1     \\
+   *         w & = & v1 * v1 + v2 * v2     \\
+   *         y & = & \sqrt{\frac{-2 * \log(w)}{w}}     \\
+   *         x1 & = & mean + v1 * y * \sqrt{variance}     \\
+   *         x2 & = & mean + v2 * y * \sqrt{variance}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+   * calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & 2 * (1 - u1) - 1     \\
+   *         v2' & = & 2 * (1 - u2) - 1     \\
+   *         w' & = & v1' * v1' + v2' * v2'     \\
+   *         y' & = & \sqrt{\frac{-2 * \log(w')}{w'}}     \\
+   *         x1' & = & mean + v1' * y' * \sqrt{variance}     \\
+   *         x2' & = & mean + v2' * y' * \sqrt{variance}  ,
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   */
+  double GetValue (double mean, double variance, double bound);
+
+  /**
+   * \brief Returns a random unsigned integer from a normal distribution with the specified mean, variance, and bound.
+   * \param mean Mean value for the normal distribution.
+   * \param variance Variance value for the normal distribution.
+   * \param bound Bound on values returned.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & 2 * u1 - 1     \\
+   *         v2 & = & 2 * u2 - 1     \\
+   *         w & = & v1 * v1 + v2 * v2     \\
+   *         y & = & \sqrt{\frac{-2 * \log(w)}{w}}     \\
+   *         x1 & = & mean + v1 * y * \sqrt{variance}     \\
+   *         x2 & = & mean + v2 * y * \sqrt{variance}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+   * calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & 2 * (1 - u1) - 1     \\
+   *         v2' & = & 2 * (1 - u2) - 1     \\
+   *         w' & = & v1' * v1' + v2' * v2'     \\
+   *         y' & = & \sqrt{\frac{-2 * \log(w')}{w'}}     \\
+   *         x1' & = & mean + v1' * y' * \sqrt{variance}     \\
+   *         x2' & = & mean + v2' * y' * \sqrt{variance}  ,
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   */
+  uint32_t GetInteger (uint32_t mean, uint32_t variance, uint32_t bound);
+
+  /**
+   * \brief Returns a random double from a normal distribution with the current mean, variance, and bound.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & 2 * u1 - 1     \\
+   *         v2 & = & 2 * u2 - 1     \\
+   *         w & = & v1 * v1 + v2 * v2     \\
+   *         y & = & \sqrt{\frac{-2 * \log(w)}{w}}     \\
+   *         x1 & = & mean + v1 * y * \sqrt{variance}     \\
+   *         x2 & = & mean + v2 * y * \sqrt{variance}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+   * calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & 2 * (1 - u1) - 1     \\
+   *         v2' & = & 2 * (1 - u2) - 1     \\
+   *         w' & = & v1' * v1' + v2' * v2'     \\
+   *         y' & = & \sqrt{\frac{-2 * \log(w')}{w'}}     \\
+   *         x1' & = & mean + v1' * y' * \sqrt{variance}     \\
+   *         x2' & = & mean + v2' * y' * \sqrt{variance}  ,
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the three-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a normal distribution with the current mean, variance, and bound.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & 2 * u1 - 1     \\
+   *         v2 & = & 2 * u2 - 1     \\
+   *         w & = & v1 * v1 + v2 * v2     \\
+   *         y & = & \sqrt{\frac{-2 * \log(w)}{w}}     \\
+   *         x1 & = & mean + v1 * y * \sqrt{variance}     \\
+   *         x2 & = & mean + v2 * y * \sqrt{variance}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+   * calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & 2 * (1 - u1) - 1     \\
+   *         v2' & = & 2 * (1 - u2) - 1     \\
+   *         w' & = & v1' * v1' + v2' * v2'     \\
+   *         y' & = & \sqrt{\frac{-2 * \log(w')}{w'}}     \\
+   *         x1' & = & mean + v1' * y' * \sqrt{variance}     \\
+   *         x2' & = & mean + v2' * y' * \sqrt{variance}  ,
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The mean value for the normal distribution returned by this RNG stream.
+  double m_mean;
+
+  /// The variance value for the normal distribution returned by this RNG stream.
+  double m_variance;
+
+  /// The bound on values that can be returned by this RNG stream.
+  double m_bound;
+
+  /// True if the next value is valid.
+  bool m_nextValid;
+
+  /// The algorithm produces two values at a time.
+  double m_next;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The log-normal distribution Random Number Generator
+ * (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed log-normal distribution.  It also supports the generation of
+ * single random numbers from various log-normal distributions.
+ *
+ * LogNormalRandomVariable defines a random variable with a log-normal
+ * distribution.  If one takes the natural logarithm of random
+ * variable following the log-normal distribution, the obtained values
+ * follow a normal distribution.
+ *
+ * The probability density function is defined over the interval [0,\f$+\infty\f$) as:
+ * \f$ \frac{1}{x\sigma\sqrt{2\pi}} e^{-\frac{(ln(x) - \mu)^2}{2\sigma^2}}\f$
+ * where \f$ mean = e^{\mu+\frac{\sigma^2}{2}} \f$ and
+ * \f$ variance = (e^{\sigma^2}-1)e^{2\mu+\sigma^2}\f$
+ *
+ * The \f$ \mu \f$ and \f$ \sigma \f$ parameters can be calculated instead if
+ * the mean and variance are known with the following equations:
+ * \f$ \mu = ln(mean) - \frac{1}{2}ln\left(1+\frac{variance}{mean^2}\right)\f$, and,
+ * \f$ \sigma = \sqrt{ln\left(1+\frac{variance}{mean^2}\right)}\f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double mu = 5.0;
+ *   double sigma = 2.0;
+ *   
+ *   Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
+ *   x->SetAttribute ("Mu", DoubleValue (mu));
+ *   x->SetAttribute ("Sigma", DoubleValue (sigma));
+ *   
+ *   // The expected value for the mean of the values returned by a
+ *   // log-normally distributed random variable is equal to 
+ *   //
+ *   //                             2
+ *   //                   mu + sigma  / 2
+ *   //     E[value]  =  e                 .
+ *   //
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class LogNormalRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a log-normal distribution RNG with the default
+   * values for mu and sigma.
+   */
+  LogNormalRandomVariable ();
+
+  /**
+   * \brief Returns the mu value for the log-normal distribution returned by this RNG stream.
+   * \return The mu value for the log-normal distribution returned by this RNG stream.
+   */
+  double GetMu (void) const;
+
+  /**
+   * \brief Returns the sigma value for the log-normal distribution returned by this RNG stream.
+   * \return The sigma value for the log-normal distribution returned by this RNG stream.
+   */
+  double GetSigma (void) const;
+
+  /**
+   * \brief Returns a random double from a log-normal distribution with the specified mu and sigma.
+   * \param mu Mu value for the log-normal distribution.
+   * \param sigma Sigma value for the log-normal distribution.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & -1 + 2 * u1       \\
+   *         v2 & = & -1 + 2 * u2       \\
+   *         r2 & = & v1 * v1 + v2 * v2       \\
+   *         normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}}       \\
+   *         x & = &  \exp{sigma * normal + mu}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic value returned, \f$x'\f$, is calculated as
+   * follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & -1 + 2 * (1 - u1)       \\
+   *         v2' & = & -1 + 2 * (1 - u2)       \\
+   *         r2' & = & v1' * v1' + v2' * v2'       \\
+   *         normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}}       \\
+   *         x' & = &  \exp{sigma * normal' + mu}  .
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   */
+  double GetValue (double mu, double sigma);
+
+  /**
+   * \brief Returns a random unsigned integer from a log-normal distribution with the specified mu and sigma.
+   * \param mu Mu value for the log-normal distribution.
+   * \param sigma Sigma value for the log-normal distribution.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & -1 + 2 * u1       \\
+   *         v2 & = & -1 + 2 * u2       \\
+   *         r2 & = & v1 * v1 + v2 * v2       \\
+   *         normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}}       \\
+   *         x & = &  \exp{sigma * normal + mu}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic value returned, \f$x'\f$, is calculated as
+   * follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & -1 + 2 * (1 - u1)       \\
+   *         v2' & = & -1 + 2 * (1 - u2)       \\
+   *         r2' & = & v1' * v1' + v2' * v2'       \\
+   *         normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}}       \\
+   *         x' & = &  \exp{sigma * normal' + mu}  .
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   */
+  uint32_t GetInteger (uint32_t mu, uint32_t sigma);
+
+  /**
+   * \brief Returns a random double from a log-normal distribution with the current mu and sigma.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & -1 + 2 * u1       \\
+   *         v2 & = & -1 + 2 * u2       \\
+   *         r2 & = & v1 * v1 + v2 * v2       \\
+   *         normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}}       \\
+   *         x & = &  \exp{sigma * normal + mu}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic value returned, \f$x'\f$, is calculated as
+   * follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & -1 + 2 * (1 - u1)       \\
+   *         v2' & = & -1 + 2 * (1 - u2)       \\
+   *         r2' & = & v1' * v1' + v2' * v2'       \\
+   *         normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}}       \\
+   *         x' & = &  \exp{sigma * normal' + mu}  .
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a log-normal distribution with the current mu and sigma.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & -1 + 2 * u1       \\
+   *         v2 & = & -1 + 2 * u2       \\
+   *         r2 & = & v1 * v1 + v2 * v2       \\
+   *         normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}}       \\
+   *         x & = &  \exp{sigma * normal + mu}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic value returned, \f$x'\f$, is calculated as
+   * follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & -1 + 2 * (1 - u1)       \\
+   *         v2' & = & -1 + 2 * (1 - u2)       \\
+   *         r2' & = & v1' * v1' + v2' * v2'       \\
+   *         normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}}       \\
+   *         x' & = &  \exp{sigma * normal' + mu}  .
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The mu value for the log-normal distribution returned by this RNG stream.
+  double m_mu;
+
+  /// The sigma value for the log-normal distribution returned by this RNG stream.
+  double m_sigma;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The gamma distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed gamma distribution.  It also supports the generation of
+ * single random numbers from various gamma distributions.
+ *
+ * The probability density function is defined over the interval [0,\f$+\infty\f$) as:
+ * \f$ x^{\alpha-1} \frac{e^{-\frac{x}{\beta}}}{\beta^\alpha \Gamma(\alpha)}\f$
+ * where \f$ mean = \alpha\beta \f$ and
+ * \f$ variance = \alpha \beta^2\f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double alpha = 5.0;
+ *   double beta = 2.0;
+ *   
+ *   Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
+ *   x->SetAttribute ("Alpha", DoubleValue (alpha));
+ *   x->SetAttribute ("Beta", DoubleValue (beta));
+ *   
+ *   // The expected value for the mean of the values returned by a
+ *   // gammaly distributed random variable is equal to 
+ *   //
+ *   //     E[value]  =  alpha * beta  .
+ *   //
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class GammaRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a gamma distribution RNG with the default values
+   * for alpha and beta.
+   */
+  GammaRandomVariable ();
+
+  /**
+   * \brief Returns the alpha value for the gamma distribution returned by this RNG stream.
+   * \return The alpha value for the gamma distribution returned by this RNG stream.
+   */
+  double GetAlpha (void) const;
+
+  /**
+   * \brief Returns the beta value for the gamma distribution returned by this RNG stream.
+   * \return The beta value for the gamma distribution returned by this RNG stream.
+   */
+  double GetBeta (void) const;
+
+  /**
+   * \brief Returns a random double from a gamma distribution with the specified alpha and beta.
+   * \param alpha Alpha value for the gamma distribution.
+   * \param beta Beta value for the gamma distribution.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  double GetValue (double alpha, double beta);
+
+  /**
+   * \brief Returns a random unsigned integer from a gamma distribution with the specified alpha and beta.
+   * \param alpha Alpha value for the gamma distribution.
+   * \param beta Beta value for the gamma distribution.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  uint32_t GetInteger (uint32_t alpha, uint32_t beta);
+
+  /**
+   * \brief Returns a random double from a gamma distribution with the current alpha and beta.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a gamma distribution with the current alpha and beta.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /**
+   * \brief Returns a random double from a normal distribution with the specified mean, variance, and bound.
+   * \param mean Mean value for the normal distribution.
+   * \param variance Variance value for the normal distribution.
+   * \param bound Bound on values returned.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u1\f$ and \f$u2\f$ are uniform variables
+   * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1 & = & 2 * u1 - 1     \\
+   *         v2 & = & 2 * u2 - 1     \\
+   *         w & = & v1 * v1 + v2 * v2     \\
+   *         y & = & \sqrt{\frac{-2 * \log(w)}{w}}     \\
+   *         x1 & = & mean + v1 * y * \sqrt{variance}     \\
+   *         x2 & = & mean + v2 * y * \sqrt{variance}  .
+   *    \f}
+   *
+   * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+   * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+   * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+   * calculated as follows:
+   *
+   *    \f{eqnarray*}{
+   *         v1' & = & 2 * (1 - u1) - 1     \\
+   *         v2' & = & 2 * (1 - u2) - 1     \\
+   *         w' & = & v1' * v1' + v2' * v2'     \\
+   *         y' & = & \sqrt{\frac{-2 * \log(w')}{w'}}     \\
+   *         x1' & = & mean + v1' * y' * \sqrt{variance}     \\
+   *         x2' & = & mean + v2' * y' * \sqrt{variance}  ,
+   *    \f}
+   *
+   * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+   */
+  double GetNormalValue (double mean, double variance, double bound);
+
+  /// The alpha value for the gamma distribution returned by this RNG stream.
+  double m_alpha;
+
+  /// The beta value for the gamma distribution returned by this RNG stream.
+  double m_beta;
+
+  /// True if the next normal value is valid.
+  bool m_nextValid;
+
+  /// The algorithm produces two normal values at a time.
+  double m_next;
+
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Erlang distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Erlang distribution.  It also supports the generation of
+ * single random numbers from various Erlang distributions.
+ *
+ * The Erlang distribution is a special case of the Gamma distribution where k
+ * (= alpha) is a non-negative integer. Erlang distributed variables can be
+ * generated using a much faster algorithm than gamma variables.
+ *
+ * The probability density function is defined over the interval [0,\f$+\infty\f$) as:
+ * \f$ \frac{x^{k-1} e^{-\frac{x}{\lambda}}}{\lambda^k (k-1)!}\f$
+ * where \f$ mean = k \lambda \f$ and
+ * \f$ variance = k \lambda^2\f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   uint32_t k = 5;
+ *   double lambda = 2.0;
+ *   
+ *   Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
+ *   x->SetAttribute ("K", IntegerValue (k));
+ *   x->SetAttribute ("Lambda", DoubleValue (lambda));
+ *   
+ *   // The expected value for the mean of the values returned by a
+ *   // Erlangly distributed random variable is equal to 
+ *   //
+ *   //     E[value]  =  k * lambda  .
+ *   //
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class ErlangRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates an Erlang distribution RNG with the default values
+   * for k and lambda.
+   */
+  ErlangRandomVariable ();
+
+  /**
+   * \brief Returns the k value for the Erlang distribution returned by this RNG stream.
+   * \return The k value for the Erlang distribution returned by this RNG stream.
+   */
+  uint32_t GetK (void) const;
+
+  /**
+   * \brief Returns the lambda value for the Erlang distribution returned by this RNG stream.
+   * \return The lambda value for the Erlang distribution returned by this RNG stream.
+   */
+  double GetLambda (void) const;
+
+  /**
+   * \brief Returns a random double from an Erlang distribution with the specified k and lambda.
+   * \param k K value for the Erlang distribution.
+   * \param lambda Lambda value for the Erlang distribution.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  double GetValue (uint32_t k, double lambda);
+
+  /**
+   * \brief Returns a random unsigned integer from an Erlang distribution with the specified k and lambda.
+   * \param k K value for the Erlang distribution.
+   * \param lambda Lambda value for the Erlang distribution.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  uint32_t GetInteger (uint32_t k, uint32_t lambda);
+
+  /**
+   * \brief Returns a random double from an Erlang distribution with the current k and lambda.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from an Erlang distribution with the current k and lambda.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /**
+   * \brief Returns a random double from an exponential distribution with the specified mean and upper bound.
+   * \param mean Mean value of the random variables.
+   * \param bound Upper bound on values returned.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *         x = - mean * \log(u) 
+   *    \f]
+   *
+   * is a value that would be returned normally, then \f$(1 - u\f$) is
+   * the distance that \f$u\f$ would be from \f$1\f$.  The value
+   * returned in the antithetic case, \f$x'\f$, is calculated as
+   *
+   *    \f[
+   *         x' = - mean * \log(1 - u), 
+   *    \f]
+   *
+   * which now involves the log of the distance \f$u\f$ is from the 1.
+   */
+  double GetExponentialValue (double mean, double bound);
+
+  /// The k value for the Erlang distribution returned by this RNG stream.
+  uint32_t m_k;
+
+  /// The lambda value for the Erlang distribution returned by this RNG stream.
+  double m_lambda;
+
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The triangular distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed triangular distribution.  It also supports the generation of
+ * single random numbers from various triangular distributions.
+ *
+ * This distribution is a triangular distribution.  The probability density
+ * is in the shape of a triangle.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double mean = 5.0;
+ *   double min = 2.0;
+ *   double max = 10.0;
+ *   
+ *   Ptr<TriangularRandomVariable> x = CreateObject<TriangularRandomVariable> ();
+ *   x->SetAttribute ("Mean", DoubleValue (mean));
+ *   x->SetAttribute ("Min", DoubleValue (min));
+ *   x->SetAttribute ("Max", DoubleValue (max));
+ *   
+ *   // The expected value for the mean of the values returned by a
+ *   // triangularly distributed random variable is equal to mean.
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class TriangularRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a triangular distribution RNG with the default
+   * values for the mean, lower bound, and upper bound.
+   */
+  TriangularRandomVariable ();
+
+  /**
+   * \brief Returns the mean value for the triangular distribution returned by this RNG stream.
+   * \return The mean value for the triangular distribution returned by this RNG stream.
+   */
+  double GetMean (void) const;
+
+  /**
+   * \brief Returns the lower bound for the triangular distribution returned by this RNG stream.
+   * \return The lower bound for the triangular distribution returned by this RNG stream.
+   */
+  double GetMin (void) const;
+
+  /**
+   * \brief Returns the upper bound on values that can be returned by this RNG stream.
+   * \return The upper bound on values that can be returned by this RNG stream.
+   */
+  double GetMax (void) const;
+
+  /**
+   * \brief Returns a random double from a triangular distribution with the specified mean, min, and max.
+   * \param mean Mean value for the triangular distribution.
+   * \param min Low end of the range.
+   * \param max High end of the range.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *        x = \left\{ \begin{array}{rl}
+   *           min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *    \f]
+   *
+   * is a value that would be returned normally, where the mode or
+   * peak of the triangle is calculated as
+   *
+   *    \f[
+   *         mode =  3.0 * mean - min - max  .
+   *    \f]
+   *
+   * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *        x' = \left\{ \begin{array}{rl}
+   *           min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *     \f]
+   *
+   * which now involves the distance \f$u\f$ is from the 1.
+   */
+  double GetValue (double mean, double min, double max);
+
+  /**
+   * \brief Returns a random unsigned integer from a triangular distribution with the specified mean, min, and max.
+   * \param mean Mean value for the triangular distribution.
+   * \param min Low end of the range.
+   * \param max High end of the range.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *        x = \left\{ \begin{array}{rl}
+   *           min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *    \f]
+   *
+   * is a value that would be returned normally, where the mode or
+   * peak of the triangle is calculated as
+   *
+   *    \f[
+   *         mode =  3.0 * mean - min - max  .
+   *    \f]
+   *
+   * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *        x' = \left\{ \begin{array}{rl}
+   *           min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *     \f]
+   *
+   * which now involves the distance \f$u\f$ is from the 1.
+   */
+  uint32_t GetInteger (uint32_t mean, uint32_t min, uint32_t max);
+
+  /**
+   * \brief Returns a random double from a triangular distribution with the current mean, min, and max.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *        x = \left\{ \begin{array}{rl}
+   *           min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *    \f]
+   *
+   * is a value that would be returned normally, where the mode or
+   * peak of the triangle is calculated as
+   *
+   *    \f[
+   *         mode =  3.0 * mean - min - max  .
+   *    \f]
+   *
+   * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *        x' = \left\{ \begin{array}{rl}
+   *           min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *     \f]
+   *
+   * which now involves the distance \f$u\f$ is from the 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the three-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a triangular distribution with the current mean, min, and max.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if
+   * m_isAntithetic is equal to true.  If \f$u\f$ is a uniform variable
+   * over [0,1] and
+   *
+   *    \f[
+   *        x = \left\{ \begin{array}{rl}
+   *           min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *    \f]
+   *
+   * is a value that would be returned normally, where the mode or
+   * peak of the triangle is calculated as
+   *
+   *    \f[
+   *         mode =  3.0 * mean - min - max  .
+   *    \f]
+   *
+   * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+   * \f$1\f$.  The value returned in the antithetic case, \f$x'\f$, is
+   * calculated as
+   *
+   *    \f[
+   *        x' = \left\{ \begin{array}{rl}
+   *           min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+   *           max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+   *                 \end{array} \right.
+   *     \f]
+   *
+   * which now involves the distance \f$u\f$ is from the 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The mean value for the triangular distribution returned by this RNG stream.
+  double m_mean;
+
+  /// The lower bound on values that can be returned by this RNG stream.
+  double m_min;
+
+  /// The upper bound on values that can be returned by this RNG stream.
+  double m_max;
+
+  /// It's easier to work with the mode internally instead of the
+  /// mean.  They are related by the simple: mean = (min+max+mode)/3.
+  double m_mode;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Zipf distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Zipf distribution.  It also supports the generation of
+ * single random numbers from various Zipf distributions.
+ *
+ * The Zipf's law states that given some corpus of natural language
+ * utterances, the frequency of any word is inversely proportional
+ * to its rank in the frequency table.
+ *
+ * Zipf's distribution has two parameters, alpha and N, where:
+ * \f$ \alpha > 0 \f$ (real) and \f$ N \in \{1,2,3 \dots\}\f$ (integer).
+ * Probability Mass Function is \f$ f(k; \alpha, N) = k^{-\alpha}/ H_{N,\alpha} \f$
+ * where \f$ H_{N,\alpha} = \sum_{m=1}^N m^{-\alpha} \f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   uint32_t n = 1;
+ *   double alpha = 2.0;
+ *   
+ *   Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
+ *   x->SetAttribute ("N", IntegerValue (n));
+ *   x->SetAttribute ("Alpha", DoubleValue (alpha));
+ *   
+ *   // The expected value for the mean of the values returned by a
+ *   // Zipfly distributed random variable is equal to 
+ *   //
+ *   //                   H
+ *   //                    N, alpha - 1
+ *   //     E[value]  =  ---------------
+ *   //                     H
+ *   //                      N, alpha
+ *   //                          
+ *   // where
+ *   //
+ *   //                    N   
+ *   //                   ---    
+ *   //                   \     -alpha
+ *   //     H          =  /    m        .
+ *   //      N, alpha     ---
+ *   //                   m=1    
+ *   //                 
+ *   // For this test,
+ *   //
+ *   //                      -(alpha - 1)
+ *   //                     1
+ *   //     E[value]  =  ---------------
+ *   //                      -alpha
+ *   //                     1
+ *   //
+ *   //               =  1  .
+ *   //               
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class ZipfRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a Zipf distribution RNG with the default values
+   * for n and alpha.
+   */
+  ZipfRandomVariable ();
+
+  /**
+   * \brief Returns the n value for the Zipf distribution returned by this RNG stream.
+   * \return The n value for the Zipf distribution returned by this RNG stream.
+   */
+  uint32_t GetN (void) const;
+
+  /**
+   * \brief Returns the alpha value for the Zipf distribution returned by this RNG stream.
+   * \return The alpha value for the Zipf distribution returned by this RNG stream.
+   */
+  double GetAlpha (void) const;
+
+  /**
+   * \brief Returns a random double from a Zipf distribution with the specified n and alpha.
+   * \param n N value for the Zipf distribution.
+   * \param alpha Alpha value for the Zipf distribution.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  double GetValue (uint32_t n, double alpha);
+
+  /**
+   * \brief Returns a random unsigned integer from a Zipf distribution with the specified n and alpha.
+   * \param n N value for the Zipf distribution.
+   * \param alpha Alpha value for the Zipf distribution.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  uint32_t GetInteger (uint32_t n, uint32_t alpha);
+
+  /**
+   * \brief Returns a random double from a Zipf distribution with the current n and alpha.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a Zipf distribution with the current n and alpha.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The n value for the Zipf distribution returned by this RNG stream.
+  uint32_t m_n;
+
+  /// The alpha value for the Zipf distribution returned by this RNG stream.
+  double m_alpha;
+
+  /// The normalization constant.
+  double m_c;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The zeta distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed zeta distribution.  It also supports the generation of
+ * single random numbers from various zeta distributions.
+ *
+ * The Zeta distribution is closely related to Zipf distribution when
+ * N goes to infinity.
+ *
+ * Zeta distribution has one parameter, alpha, \f$ \alpha > 1 \f$ (real).
+ * Probability Mass Function is \f$ f(k; \alpha) = k^{-\alpha}/\zeta(\alpha) \f$
+ * where \f$ \zeta(\alpha) \f$ is the Riemann zeta function ( \f$ \sum_{n=1}^\infty n^{-\alpha} ) \f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   double alpha = 2.0;
+ *   
+ *   Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
+ *   x->SetAttribute ("Alpha", DoubleValue (alpha));
+ *   
+ *   // The expected value for the mean of the values returned by a
+ *   // zetaly distributed random variable is equal to 
+ *   //
+ *   //                   zeta(alpha - 1)
+ *   //     E[value]  =  ---------------   for alpha > 2 ,
+ *   //                     zeta(alpha)
+ *   //                          
+ *   // where zeta(alpha) is the Riemann zeta function.
+ *   //                 
+ *   // There are no simple analytic forms for the Riemann zeta
+ *   // function, which is the reason the known mean of the values
+ *   // cannot be calculated in this example.
+ *   //               
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class ZetaRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a zeta distribution RNG with the default value for
+   * alpha.
+   */
+  ZetaRandomVariable ();
+
+  /**
+   * \brief Returns the alpha value for the zeta distribution returned by this RNG stream.
+   * \return The alpha value for the zeta distribution returned by this RNG stream.
+   */
+  double GetAlpha (void) const;
+
+  /**
+   * \brief Returns a random double from a zeta distribution with the specified alpha.
+   * \param alpha Alpha value for the zeta distribution.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  double GetValue (double alpha);
+
+  /**
+   * \brief Returns a random unsigned integer from a zeta distribution with the specified alpha.
+   * \param alpha Alpha value for the zeta distribution.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  uint32_t GetInteger (uint32_t alpha);
+
+  /**
+   * \brief Returns a random double from a zeta distribution with the current alpha.
+   * \return A floating point random value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   *
+   * Note that we have to re-implement this method here because the method is
+   * overloaded above for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns a random unsigned integer from a zeta distribution with the current alpha.
+   * \return A random unsigned integer value.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// The alpha value for the zeta distribution returned by this RNG stream.
+  double m_alpha;
+
+  /// Just for calculus simplifications.
+  double m_b;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that returns a predetermined sequence.
+ *
+ * Defines a random variable that has a specified, predetermined
+ * sequence.  This would be useful when trying to force the RNG to
+ * return a known sequence, perhaps to compare NS-3 to some other
+ * simulator
+ *
+ * Creates a generator that returns successive elements of the values
+ * array on successive calls to RandomVariableStream::GetValue.  Note
+ * that the values in the array are copied and stored by the generator
+ * (deep-copy).  Also note that the sequence repeats if more values
+ * are requested than are present in the array.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   Ptr<DeterministicRandomVariable> s = CreateObject<DeterministicRandomVariable> ();
+ * 
+ *   // The following array should give the sequence
+ *   //
+ *   //    4, 4, 7, 7, 10, 10 .
+ *   //
+ *   double array [] = { 4, 4, 7, 7, 10, 10};
+ *   uint64_t count = 6;
+ *   s->SetValueArray (array, count);
+ * 
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class DeterministicRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates a deterministic RNG that will have a predetermined
+   * sequence of values.
+   */
+  DeterministicRandomVariable ();
+  virtual ~DeterministicRandomVariable ();
+
+  /**
+   * \brief Sets the array of values that holds the predetermined sequence.
+   * \param values Array of random values to return in sequence.
+   * \param length Number of values in the array.
+   *
+   * Note that the values in the array are copied and stored
+   * (deep-copy).
+   */
+  void SetValueArray (double* values, uint64_t length);
+
+  /**
+   * \brief Returns the next value in the sequence.
+   * \return The floating point next value in the sequence.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns the next value in the sequence.
+   * \return The integer next value in the sequence.
+   */
+  virtual uint32_t GetInteger (void);
+
+private:
+  /// Position in the array of values.
+  uint64_t   m_count;
+
+  /// Position of the next value in the array of values.
+  uint64_t   m_next;
+
+  /// Array of values to return in sequence.
+  double* m_data;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that has a specified empirical distribution.
+ *
+ * Defines a random variable  that has a specified, empirical
+ * distribution.  The distribution is specified by a
+ * series of calls to the CDF member function, specifying a
+ * value and the probability that the function value is less than
+ * the specified value.  When values are requested,
+ * a uniform random variable is used to select a probability,
+ * and the return value is interpreted linearly between the
+ * two appropriate points in the CDF.  The method is known
+ * as inverse transform sampling:
+ * (http://en.wikipedia.org/wiki/Inverse_transform_sampling).
+ *
+ * Here is an example of how to use this class:
+ * \code
+ *   // Create the RNG with a uniform distribution between 0 and 10.
+ *   Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
+ *   x->CDF ( 0.0,  0.0);
+ *   x->CDF ( 5.0,  0.5);
+ *   x->CDF (10.0,  1.0);
+ * 
+ *   // The expected value for the mean of the values returned by this
+ *   // empirical distribution is the midpoint of the distribution
+ *   //
+ *   //     E[value]  =  5 .
+ *   //                          
+ *   double value = x->GetValue ();
+ * \endcode
+ */
+class EmpiricalRandomVariable : public RandomVariableStream
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Creates an empirical RNG that has a specified, empirical
+   * distribution.
+   */
+  EmpiricalRandomVariable ();
+
+  /**
+   * \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
+   */
+  void CDF (double v, double c);  // Value, prob <= Value
+
+  /**
+   * \brief Returns the next value in the empirical distribution.
+   * \return The floating point next value in the empirical distribution.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  virtual double GetValue (void);
+
+  /**
+   * \brief Returns the next value in the empirical distribution.
+   * \return The integer next value in the empirical distribution.
+   *
+   * Note that antithetic values are being generated if m_isAntithetic
+   * is equal to true.  If \f$u\f$ is a uniform variable over [0,1]
+   * and \f$x\f$ is a value that would be returned normally, then
+   * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+   * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+   * which is the distance \f$u\f$ is from the 1.
+   */
+  virtual uint32_t GetInteger (void);
+
+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
+};
+
 } // namespace ns3
 
 #endif /* RANDOM_VARIABLE_STREAM_H */