diff --git a/src/applications/onoff/onoff-application.cc b/src/applications/onoff/onoff-application.cc index af5409893..f068ca429 100644 --- a/src/applications/onoff/onoff-application.cc +++ b/src/applications/onoff/onoff-application.cc @@ -91,8 +91,8 @@ OnOffApplication::Construct (Ptr n, m_socket = 0; m_peer = remote; m_connected = false; - m_onTime = onTime.Copy (); - m_offTime = offTime.Copy (); + m_onTime = onTime; + m_offTime = offTime; m_pktSize = size; m_residualBits = 0; m_lastStartTime = Seconds (0); @@ -136,12 +136,6 @@ OnOffApplication::DoDispose (void) NS_LOG_FUNCTION; m_socket = 0; - delete m_onTime; - delete m_offTime; - - m_onTime = 0; - m_offTime = 0; - // chain up Application::DoDispose (); } @@ -222,7 +216,7 @@ void OnOffApplication::ScheduleStartEvent() { // Schedules the event to start sending data (switch to the "On" state) NS_LOG_FUNCTION; - Time offInterval = Seconds(m_offTime->GetValue()); + Time offInterval = Seconds(m_offTime.GetValue()); NS_LOG_LOGIC ("start at " << offInterval); m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this); } @@ -231,7 +225,7 @@ void OnOffApplication::ScheduleStopEvent() { // Schedules the event to stop sending data (switch to "Off" state) NS_LOG_FUNCTION; - Time onInterval = Seconds(m_onTime->GetValue()); + Time onInterval = Seconds(m_onTime.GetValue()); Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this); } diff --git a/src/applications/onoff/onoff-application.h b/src/applications/onoff/onoff-application.h index 31ebb3c08..89a792cc5 100644 --- a/src/applications/onoff/onoff-application.h +++ b/src/applications/onoff/onoff-application.h @@ -30,6 +30,7 @@ #include "ns3/ptr.h" #include "ns3/data-rate.h" #include "ns3/callback-trace-source.h" +#include "ns3/random-variable.h" namespace ns3 { @@ -124,8 +125,8 @@ private: Ptr m_socket; // Associated socket Address m_peer; // Peer address bool m_connected; // True if connected - RandomVariable* m_onTime; // rng for On Time - RandomVariable* m_offTime; // rng for Off Time + RandomVariable m_onTime; // rng for On Time + RandomVariable m_offTime; // rng for Off Time DataRate m_cbrRate; // Rate that data is generated uint32_t m_pktSize; // Size of packets uint32_t m_residualBits; // Number of generated, but not sent, bits diff --git a/src/common/error-model.cc b/src/common/error-model.cc index c512aefb2..bfd18ec87 100644 --- a/src/common/error-model.cc +++ b/src/common/error-model.cc @@ -140,13 +140,12 @@ RateErrorModel::RateErrorModel () : { NS_LOG_FUNCTION; // Assume a uniform random variable if user does not specify - m_ranvar = new UniformVariable (); + m_ranvar = UniformVariable (); } RateErrorModel::~RateErrorModel () { NS_LOG_FUNCTION; - delete m_ranvar; } enum ErrorUnit @@ -181,8 +180,7 @@ void RateErrorModel::SetRandomVariable (const RandomVariable &ranvar) { NS_LOG_FUNCTION; - delete m_ranvar; - m_ranvar = ranvar.Copy (); + m_ranvar = ranvar; } bool @@ -212,7 +210,7 @@ bool RateErrorModel::DoCorruptPkt (Ptr p) { NS_LOG_FUNCTION; - return (m_ranvar->GetValue () < m_rate); + return (m_ranvar.GetValue () < m_rate); } bool @@ -221,7 +219,7 @@ RateErrorModel::DoCorruptByte (Ptr p) NS_LOG_FUNCTION; // compute pkt error rate, assume uniformly distributed byte error double per = 1 - pow (1.0 - m_rate, p->GetSize ()); - return (m_ranvar->GetValue () < per); + return (m_ranvar.GetValue () < per); } bool @@ -230,7 +228,7 @@ RateErrorModel::DoCorruptBit(Ptr p) NS_LOG_FUNCTION; // compute pkt error rate, assume uniformly distributed bit error double per = 1 - pow (1.0 - m_rate, (8 * p->GetSize ()) ); - return (m_ranvar->GetValue () < per); + return (m_ranvar.GetValue () < per); } void diff --git a/src/common/error-model.h b/src/common/error-model.h index 1791e56e5..5cd050548 100644 --- a/src/common/error-model.h +++ b/src/common/error-model.h @@ -23,11 +23,11 @@ #include #include "ns3/object.h" +#include "ns3/random-variable.h" namespace ns3 { class Packet; -class RandomVariable; /** * \brief General error model that can be used to corrupt packets @@ -174,7 +174,7 @@ private: enum ErrorUnit m_unit; double m_rate; - RandomVariable* m_ranvar; + RandomVariable m_ranvar; }; /** diff --git a/src/core/random-variable-default-value.cc b/src/core/random-variable-default-value.cc index 58597c545..395cfcfec 100644 --- a/src/core/random-variable-default-value.cc +++ b/src/core/random-variable-default-value.cc @@ -39,17 +39,17 @@ RandomVariableDefaultValue::RandomVariableDefaultValue (std::string name, DefaultValueList::Add (this); } -RandomVariable * -RandomVariableDefaultValue::GetCopy (void) +RandomVariable +RandomVariableDefaultValue::Get (void) const { - RandomVariable *variable; + RandomVariable variable; bool ok; ok = Parse (m_value, true, &variable); NS_ASSERT (ok); return variable; } double -RandomVariableDefaultValue::ReadAsDouble (std::string value, bool &ok) +RandomVariableDefaultValue::ReadAsDouble (std::string value, bool &ok) const { double v; std::istringstream iss; @@ -60,7 +60,7 @@ RandomVariableDefaultValue::ReadAsDouble (std::string value, bool &ok) } bool RandomVariableDefaultValue::Parse (const std::string &value, - bool mustCreate, RandomVariable **pVariable) + bool mustCreate, RandomVariable *pVariable) const { std::string::size_type pos = value.find_first_of(":"); if (pos == std::string::npos) @@ -76,7 +76,7 @@ RandomVariableDefaultValue::Parse (const std::string &value, if (mustCreate) { NS_LOG_LOGIC ("create Constant constant=" << constant); - *pVariable = new ConstantVariable (constant); + *pVariable = ConstantVariable (constant); } else { @@ -100,7 +100,7 @@ RandomVariableDefaultValue::Parse (const std::string &value, if (mustCreate) { NS_LOG_LOGIC ("create Uniform min=" << min << ", max=" << max); - *pVariable = new UniformVariable (minVal, maxVal); + *pVariable = UniformVariable (minVal, maxVal); } else { diff --git a/src/core/random-variable-default-value.h b/src/core/random-variable-default-value.h index 782c62331..43d77e74d 100644 --- a/src/core/random-variable-default-value.h +++ b/src/core/random-variable-default-value.h @@ -33,10 +33,10 @@ class RandomVariableDefaultValue : public DefaultValueBase std::string help, std::string defaultValue); - RandomVariable *GetCopy (void); + RandomVariable Get (void) const; private: - bool Parse (const std::string &value, bool mustCreate, RandomVariable **pVariable); - double ReadAsDouble (const std::string value, bool &ok); + bool Parse (const std::string &value, bool mustCreate, RandomVariable *pVariable) const; + double ReadAsDouble (const std::string value, bool &ok) const; virtual bool DoParseValue (const std::string &value); virtual std::string DoGetType (void) const; virtual std::string DoGetDefaultValue (void) const; diff --git a/src/core/random-variable.cc b/src/core/random-variable.cc index 2190b90e1..1b29fe312 100644 --- a/src/core/random-variable.cc +++ b/src/core/random-variable.cc @@ -30,6 +30,7 @@ #include +#include "assert.h" #include "random-variable.h" #include "rng-stream.h" #include "fatal-error.h" @@ -40,16 +41,51 @@ namespace ns3{ //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// RandomVariable methods +// RandomVariableBase methods -bool RandomVariable::initialized = false; // True if RngStream seed set -bool RandomVariable::useDevRandom = false; // True if use /dev/random -bool RandomVariable::globalSeedSet = false; // True if GlobalSeed called -int RandomVariable::devRandom = -1; -uint32_t RandomVariable::globalSeed[6]; -unsigned long RandomVariable::heuristic_sequence; -RngStream* RandomVariable::m_static_generator = 0; -uint32_t RandomVariable::runNumber = 0; + +class RandomVariableBase +{ +public: + RandomVariableBase (); + RandomVariableBase (const RandomVariableBase &o); + virtual ~RandomVariableBase(); + virtual double GetValue() = 0; + virtual uint32_t GetIntValue(); + virtual RandomVariableBase* Copy(void) const = 0; + virtual void GetSeed(uint32_t seed[6]); + + static void UseDevRandom(bool udr = true); + static void UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, + uint32_t s3, uint32_t s4, uint32_t s5); + static void SetRunNumber(uint32_t n); +private: + static void GetRandomSeeds(uint32_t seeds[6]); +private: + static bool useDevRandom; // True if using /dev/random desired + static bool globalSeedSet; // True if global seed has been specified + static int devRandom; // File handle for /dev/random + static uint32_t globalSeed[6]; // The global seed to use + friend class RandomVariableInitializer; +protected: + static unsigned long heuristic_sequence; + static RngStream* m_static_generator; + static uint32_t runNumber; + static void Initialize(); // Initialize the RNG system + static bool initialized; // True if package seed is set + RngStream* m_generator; //underlying generator being wrapped +}; + + + +bool RandomVariableBase::initialized = false; // True if RngStream seed set +bool RandomVariableBase::useDevRandom = false; // True if use /dev/random +bool RandomVariableBase::globalSeedSet = false; // True if GlobalSeed called +int RandomVariableBase::devRandom = -1; +uint32_t RandomVariableBase::globalSeed[6]; +unsigned long RandomVariableBase::heuristic_sequence; +RngStream* RandomVariableBase::m_static_generator = 0; +uint32_t RandomVariableBase::runNumber = 0; //the static object random_variable_initializer initializes the static members //of RandomVariable @@ -58,25 +94,25 @@ static class RandomVariableInitializer public: RandomVariableInitializer() { -// RandomVariable::Initialize(); // sets the static package seed -// RandomVariable::m_static_generator = new RngStream(); -// RandomVariable::m_static_generator->InitializeStream(); +// RandomVariableBase::Initialize(); // sets the static package seed +// RandomVariableBase::m_static_generator = new RngStream(); +// RandomVariableBase::m_static_generator->InitializeStream(); } ~RandomVariableInitializer() { - delete RandomVariable::m_static_generator; + delete RandomVariableBase::m_static_generator; } } random_variable_initializer; -RandomVariable::RandomVariable() +RandomVariableBase::RandomVariableBase() : m_generator(NULL) { // m_generator = new RngStream(); // m_generator->InitializeStream(); -// m_generator->ResetNthSubstream(RandomVariable::runNumber); +// m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } -RandomVariable::RandomVariable(const RandomVariable& r) +RandomVariableBase::RandomVariableBase(const RandomVariableBase& r) :m_generator(0) { if(r.m_generator) @@ -85,61 +121,61 @@ RandomVariable::RandomVariable(const RandomVariable& r) } } -RandomVariable::~RandomVariable() +RandomVariableBase::~RandomVariableBase() { delete m_generator; } -uint32_t RandomVariable::GetIntValue() +uint32_t RandomVariableBase::GetIntValue() { return (uint32_t)GetValue(); } -void RandomVariable::UseDevRandom(bool udr) +void RandomVariableBase::UseDevRandom(bool udr) { - RandomVariable::useDevRandom = udr; + RandomVariableBase::useDevRandom = udr; } -void RandomVariable::GetSeed(uint32_t seed[6]) +void RandomVariableBase::GetSeed(uint32_t seed[6]) { if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } m_generator->GetState(seed); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// RandomVariable static methods -void RandomVariable::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, +// RandomVariableBase static methods +void RandomVariableBase::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, uint32_t s3, uint32_t s4, uint32_t s5) { - if (RandomVariable::globalSeedSet) + if (RandomVariableBase::globalSeedSet) { cerr << "Random number generator already initialized!" << endl; - cerr << "Call to RandomVariable::UseGlobalSeed() ignored" << endl; + cerr << "Call to RandomVariableBase::UseGlobalSeed() ignored" << endl; return; } - RandomVariable::globalSeed[0] = s0; - RandomVariable::globalSeed[1] = s1; - RandomVariable::globalSeed[2] = s2; - RandomVariable::globalSeed[3] = s3; - RandomVariable::globalSeed[4] = s4; - RandomVariable::globalSeed[5] = s5; - if (!RngStream::CheckSeed(RandomVariable::globalSeed)) + RandomVariableBase::globalSeed[0] = s0; + RandomVariableBase::globalSeed[1] = s1; + RandomVariableBase::globalSeed[2] = s2; + RandomVariableBase::globalSeed[3] = s3; + RandomVariableBase::globalSeed[4] = s4; + RandomVariableBase::globalSeed[5] = s5; + if (!RngStream::CheckSeed(RandomVariableBase::globalSeed)) NS_FATAL_ERROR("Invalid seed"); - RandomVariable::globalSeedSet = true; + RandomVariableBase::globalSeedSet = true; } -void RandomVariable::Initialize() +void RandomVariableBase::Initialize() { - if (RandomVariable::initialized) return; // Already initialized and seeded - RandomVariable::initialized = true; - if (!RandomVariable::globalSeedSet) + if (RandomVariableBase::initialized) return; // Already initialized and seeded + RandomVariableBase::initialized = true; + if (!RandomVariableBase::globalSeedSet) { // No global seed, try a random one GetRandomSeeds(globalSeed); } @@ -147,20 +183,20 @@ void RandomVariable::Initialize() RngStream::SetPackageSeed(globalSeed); } -void RandomVariable::GetRandomSeeds(uint32_t seeds[6]) +void RandomVariableBase::GetRandomSeeds(uint32_t seeds[6]) { // Check if /dev/random exists - if (RandomVariable::useDevRandom && RandomVariable::devRandom < 0) + if (RandomVariableBase::useDevRandom && RandomVariableBase::devRandom < 0) { - RandomVariable::devRandom = open("/dev/random", O_RDONLY); + RandomVariableBase::devRandom = open("/dev/random", O_RDONLY); } - if (RandomVariable::devRandom > 0) + if (RandomVariableBase::devRandom > 0) { // Use /dev/random while(true) { for (int i = 0; i < 6; ++i) { - read(RandomVariable::devRandom, &seeds[i], sizeof(seeds[i])); + read(RandomVariableBase::devRandom, &seeds[i], sizeof(seeds[i])); } if (RngStream::CheckSeed(seeds)) break; // Got a valid one } @@ -194,205 +230,537 @@ void RandomVariable::GetRandomSeeds(uint32_t seeds[6]) } } -void RandomVariable::SetRunNumber(uint32_t n) +void RandomVariableBase::SetRunNumber(uint32_t n) { runNumber = n; } + + +RandomVariable::RandomVariable() + : m_variable (0) +{} +RandomVariable::RandomVariable(const RandomVariable&o) + : m_variable (o.m_variable->Copy ()) +{} +RandomVariable::RandomVariable (const RandomVariableBase &variable) + : m_variable (variable.Copy ()) +{} +RandomVariable & +RandomVariable::operator = (const RandomVariable &o) +{ + delete m_variable; + m_variable = o.m_variable->Copy (); + return *this; +} +RandomVariable::~RandomVariable() +{ + delete m_variable; +} +double +RandomVariable::GetValue (void) const +{ + return m_variable->GetValue (); +} + +uint32_t +RandomVariable::GetIntValue (void) const +{ + return m_variable->GetIntValue (); +} +void +RandomVariable::GetSeed(uint32_t seed[6]) const +{ + return m_variable->GetSeed (seed); +} +void +RandomVariable::UseDevRandom(bool udr) +{ + RandomVariableBase::UseDevRandom (udr); +} +void +RandomVariable::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2, + uint32_t s3, uint32_t s4, uint32_t s5) +{ + RandomVariableBase::UseGlobalSeed (s0, s1, s2, s3, s4, s5); +} +void +RandomVariable::SetRunNumber(uint32_t n) +{ + RandomVariableBase::SetRunNumber (n); +} +RandomVariableBase * +RandomVariable::Peek (void) +{ + return m_variable; +} + + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// UniformVariable -UniformVariable::UniformVariable() +// UniformVariableImpl + +class UniformVariableImpl : public RandomVariableBase { +public: + /** + * Creates a uniform random number generator in the + * range [0.0 .. 1.0). + */ + UniformVariableImpl(); + + /** + * Creates a uniform random number generator with the specified range + * \param s Low end of the range + * \param l High end of the range + */ + UniformVariableImpl(double s, double l); + + UniformVariableImpl(const UniformVariableImpl& c); + + /** + * \return A value between low and high values specified by the constructor + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; + +public: + /** + * \param s Low end of the range + * \param l High end of the range + * \return A uniformly distributed random number between s and l + */ + static double GetSingleValue(double s, double l); +private: + double m_min; + double m_max; +}; + +UniformVariableImpl::UniformVariableImpl() : m_min(0), m_max(1.0) { } -UniformVariable::UniformVariable(double s, double l) +UniformVariableImpl::UniformVariableImpl(double s, double l) : m_min(s), m_max(l) { } -UniformVariable::UniformVariable(const UniformVariable& c) - : RandomVariable(c), m_min(c.m_min), m_max(c.m_max) { } +UniformVariableImpl::UniformVariableImpl(const UniformVariableImpl& c) + : RandomVariableBase(c), m_min(c.m_min), m_max(c.m_max) { } -double UniformVariable::GetValue() +double UniformVariableImpl::GetValue() { - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } return m_min + m_generator->RandU01() * (m_max - m_min); } -RandomVariable* UniformVariable::Copy() const +RandomVariableBase* UniformVariableImpl::Copy() const { - return new UniformVariable(*this); + return new UniformVariableImpl(*this); } -double UniformVariable::GetSingleValue(double s, double l) +double UniformVariableImpl::GetSingleValue(double s, double l) { - if(!RandomVariable::m_static_generator) + if(!RandomVariableBase::m_static_generator) { - RandomVariable::Initialize(); // sets the static package seed - RandomVariable::m_static_generator = new RngStream(); - RandomVariable::m_static_generator->InitializeStream(); + RandomVariableBase::Initialize(); // sets the static package seed + RandomVariableBase::m_static_generator = new RngStream(); + RandomVariableBase::m_static_generator->InitializeStream(); } return s + m_static_generator->RandU01() * (l - s);; } +UniformVariable::UniformVariable() + : RandomVariable (UniformVariableImpl ()) +{} +UniformVariable::UniformVariable(double s, double l) + : RandomVariable (UniformVariableImpl (s, l)) +{} +double +UniformVariable::GetSingleValue(double s, double l) +{ + return UniformVariableImpl::GetSingleValue (s, l); +} + + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// ConstantVariable methods -ConstantVariable::ConstantVariable() +// ConstantVariableImpl methods + +class ConstantVariableImpl : public RandomVariableBase { + +public: + /** + * Construct a ConstantVariableImpl RNG that returns zero every sample + */ + ConstantVariableImpl(); + + /** + * Construct a ConstantVariableImpl RNG that returns the specified value + * every sample. + * \param c Unchanging value for this RNG. + */ + ConstantVariableImpl(double c); + + + ConstantVariableImpl(const ConstantVariableImpl& c) ; + + /** + * \brief Specify a new constant RNG for this generator. + * \param c New constant value for this RNG. + */ + void NewConstant(double c); + + /** + * \return The constant value specified + */ + virtual double GetValue(); + virtual uint32_t GetIntValue(); + virtual RandomVariableBase* Copy(void) const; +private: + double m_const; +}; + +ConstantVariableImpl::ConstantVariableImpl() : m_const(0) { } -ConstantVariable::ConstantVariable(double c) +ConstantVariableImpl::ConstantVariableImpl(double c) : m_const(c) { }; -ConstantVariable::ConstantVariable(const ConstantVariable& c) - : RandomVariable(c), m_const(c.m_const) { } +ConstantVariableImpl::ConstantVariableImpl(const ConstantVariableImpl& c) + : RandomVariableBase(c), m_const(c.m_const) { } -void ConstantVariable::NewConstant(double c) +void ConstantVariableImpl::NewConstant(double c) { m_const = c;} -double ConstantVariable::GetValue() +double ConstantVariableImpl::GetValue() { return m_const; } -uint32_t ConstantVariable::GetIntValue() +uint32_t ConstantVariableImpl::GetIntValue() { return (uint32_t)m_const; } -RandomVariable* ConstantVariable::Copy() const -{ - return new ConstantVariable(*this); -} -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// SequentialVariable methods -SequentialVariable::SequentialVariable(double f, double l, double i, uint32_t c) - : m_min(f), m_max(l), m_increment(ConstantVariable(i).Copy()), m_consecutive(c), - m_current(f), m_currentConsecutive(0) +RandomVariableBase* ConstantVariableImpl::Copy() const { + return new ConstantVariableImpl(*this); } -SequentialVariable::SequentialVariable(double f, double l, const RandomVariable& i, uint32_t c) - : m_min(f), m_max(l), m_increment(i.Copy()), m_consecutive(c), - m_current(f), m_currentConsecutive(0) +ConstantVariable::ConstantVariable() + : RandomVariable (ConstantVariableImpl ()) +{} +ConstantVariable::ConstantVariable(double c) + : RandomVariable (ConstantVariableImpl (c)) +{} +void +ConstantVariable::SetConstant(double c) { + *this = ConstantVariable (c); } -SequentialVariable::SequentialVariable(const SequentialVariable& c) - : RandomVariable(c), m_min(c.m_min), m_max(c.m_max), - m_increment(c.m_increment->Copy()), m_consecutive(c.m_consecutive), +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// SequentialVariableImpl methods + + +class SequentialVariableImpl : public RandomVariableBase { + +public: + /** + * \brief Constructor for the SequentialVariableImpl RNG. + * + * The four parameters define the sequence. For example + * SequentialVariableImpl(0,5,1,2) creates a RNG that has the sequence + * 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0 ... + * \param f First value of the sequence. + * \param l One more than the last value of the sequence. + * \param i Increment between sequence values + * \param c Number of times each member of the sequence is repeated + */ + SequentialVariableImpl(double f, double l, double i = 1, uint32_t c = 1); + + /** + * \brief Constructor for the SequentialVariableImpl RNG. + * + * Differs from the first only in that the increment parameter is a + * random variable + * \param f First value of the sequence. + * \param l One more than the last value of the sequence. + * \param i Reference to a RandomVariableBase for the sequence increment + * \param c Number of times each member of the sequence is repeated + */ + SequentialVariableImpl(double f, double l, const RandomVariable& i, uint32_t c = 1); + + SequentialVariableImpl(const SequentialVariableImpl& c); + + ~SequentialVariableImpl(); + /** + * \return The next value in the Sequence + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; +private: + double m_min; + double m_max; + RandomVariable m_increment; + uint32_t m_consecutive; + double m_current; + uint32_t m_currentConsecutive; +}; + +SequentialVariableImpl::SequentialVariableImpl(double f, double l, double i, uint32_t c) + : m_min(f), m_max(l), m_increment(ConstantVariable(i)), m_consecutive(c), + m_current(f), m_currentConsecutive(0) +{} + +SequentialVariableImpl::SequentialVariableImpl(double f, double l, const RandomVariable& i, uint32_t c) + : m_min(f), m_max(l), m_increment(i), m_consecutive(c), + m_current(f), m_currentConsecutive(0) +{} + +SequentialVariableImpl::SequentialVariableImpl(const SequentialVariableImpl& c) + : RandomVariableBase(c), m_min(c.m_min), m_max(c.m_max), + m_increment(c.m_increment), m_consecutive(c.m_consecutive), m_current(c.m_current), m_currentConsecutive(c.m_currentConsecutive) -{ -} +{} -SequentialVariable::~SequentialVariable() -{ - delete m_increment; -} +SequentialVariableImpl::~SequentialVariableImpl() +{} -double SequentialVariable::GetValue() +double SequentialVariableImpl::GetValue() { // Return a sequential series of values double r = m_current; if (++m_currentConsecutive == m_consecutive) { // Time to advance to next m_currentConsecutive = 0; - m_current += m_increment->GetValue(); + m_current += m_increment.GetValue(); if (m_current >= m_max) m_current = m_min + (m_current - m_max); } return r; } -RandomVariable* SequentialVariable::Copy() const +RandomVariableBase* SequentialVariableImpl::Copy() const { - return new SequentialVariable(*this); + return new SequentialVariableImpl(*this); } + +SequentialVariable::SequentialVariable(double f, double l, double i, uint32_t c) + : RandomVariable (SequentialVariableImpl (f, l, i, c)) +{} +SequentialVariable::SequentialVariable(double f, double l, const RandomVariable& i, uint32_t c) + : RandomVariable (SequentialVariableImpl (f, l, i, c)) +{} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// ExponentialVariable methods -ExponentialVariable::ExponentialVariable() +// ExponentialVariableImpl methods + +class ExponentialVariableImpl : public RandomVariableBase { +public: + /** + * Constructs an exponential random variable with a mean + * value of 1.0. + */ + ExponentialVariableImpl(); + + /** + * \brief Constructs an exponential random variable with a specified mean + * \param m Mean value for the random variable + */ + explicit ExponentialVariableImpl(double m); + + /** + * \brief Constructs an exponential random variable with spefified + * \brief mean and upper limit. + * + * Since exponential distributions can theoretically return unbounded values, + * it is sometimes useful to specify a fixed upper limit. Note however when + * the upper limit is specified, the true mean of the distribution is + * slightly smaller than the mean value specified. + * \param m Mean value of the random variable + * \param b Upper bound on returned values + */ + ExponentialVariableImpl(double m, double b); + + ExponentialVariableImpl(const ExponentialVariableImpl& c); + + /** + * \return A random value from this exponential distribution + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; +public: + /** + * \param m The mean of the distribution from which the return value is drawn + * \param b The upper bound value desired, beyond which values get clipped + * \return A random number from an exponential distribution with mean m + */ + static double GetSingleValue(double m, double b=0); +private: + double m_mean; // Mean value of RV + double m_bound; // Upper bound on value (if non-zero) +}; + +ExponentialVariableImpl::ExponentialVariableImpl() : m_mean(1.0), m_bound(0) { } -ExponentialVariable::ExponentialVariable(double m) +ExponentialVariableImpl::ExponentialVariableImpl(double m) : m_mean(m), m_bound(0) { } -ExponentialVariable::ExponentialVariable(double m, double b) +ExponentialVariableImpl::ExponentialVariableImpl(double m, double b) : m_mean(m), m_bound(b) { } -ExponentialVariable::ExponentialVariable(const ExponentialVariable& c) - : RandomVariable(c), m_mean(c.m_mean), m_bound(c.m_bound) { } +ExponentialVariableImpl::ExponentialVariableImpl(const ExponentialVariableImpl& c) + : RandomVariableBase(c), m_mean(c.m_mean), m_bound(c.m_bound) { } -double ExponentialVariable::GetValue() +double ExponentialVariableImpl::GetValue() { - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } double r = -m_mean*log(m_generator->RandU01()); if (m_bound != 0 && r > m_bound) return m_bound; return r; } -RandomVariable* ExponentialVariable::Copy() const +RandomVariableBase* ExponentialVariableImpl::Copy() const { - return new ExponentialVariable(*this); + return new ExponentialVariableImpl(*this); } -double ExponentialVariable::GetSingleValue(double m, double b/*=0*/) +double ExponentialVariableImpl::GetSingleValue(double m, double b/*=0*/) { - if(!RandomVariable::m_static_generator) + if(!RandomVariableBase::m_static_generator) { - RandomVariable::Initialize(); // sets the static package seed - RandomVariable::m_static_generator = new RngStream(); - RandomVariable::m_static_generator->InitializeStream(); + RandomVariableBase::Initialize(); // sets the static package seed + RandomVariableBase::m_static_generator = new RngStream(); + RandomVariableBase::m_static_generator->InitializeStream(); } double r = -m*log(m_static_generator->RandU01()); if (b != 0 && r > b) return b; return r; } + +ExponentialVariable::ExponentialVariable() + : RandomVariable (ExponentialVariableImpl ()) +{} +ExponentialVariable::ExponentialVariable(double m) + : RandomVariable (ExponentialVariableImpl (m)) +{} +ExponentialVariable::ExponentialVariable(double m, double b) + : RandomVariable (ExponentialVariableImpl (m, b)) +{} +double +ExponentialVariable::GetSingleValue(double m, double b) +{ + return ExponentialVariableImpl::GetSingleValue (m, b); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// ParetoVariable methods -ParetoVariable::ParetoVariable() +// ParetoVariableImpl methods +class ParetoVariableImpl : public RandomVariableBase { +public: + /** + * Constructs a pareto random variable with a mean of 1 and a shape + * parameter of 1.5 + */ + ParetoVariableImpl(); + + /** + * Constructs a pareto random variable with specified mean and shape + * parameter of 1.5 + * \param m Mean value of the distribution + */ + explicit ParetoVariableImpl(double m); + + /** + * Constructs a pareto random variable with the specified mean value and + * shape parameter. + * \param m Mean value of the distribution + * \param s Shape parameter for the distribution + */ + ParetoVariableImpl(double m, double s); + + /** + * \brief Constructs a pareto random variable with the specified mean + * \brief value, shape (alpha), and upper bound. + * + * Since pareto distributions can theoretically return unbounded values, + * it is sometimes useful to specify a fixed upper limit. Note however + * when the upper limit is specified, the true mean of the distribution + * is slightly smaller than the mean value specified. + * \param m Mean value + * \param s Shape parameter + * \param b Upper limit on returned values + */ + ParetoVariableImpl(double m, double s, double b); + + ParetoVariableImpl(const ParetoVariableImpl& c); + + /** + * \return A random value from this Pareto distribution + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy() const; +public: + /** + * \param m The mean value of the distribution from which the return value + * is drawn. + * \param s The shape parameter of the distribution from which the return + * value is drawn. + * \param b The upper bound to which to restrict return values + * \return A random number from a Pareto distribution with mean m and shape + * parameter s. + */ + static double GetSingleValue(double m, double s, double b=0); +private: + double m_mean; // Mean value of RV + double m_shape; // Shape parameter + double m_bound; // Upper bound on value (if non-zero) +}; + +ParetoVariableImpl::ParetoVariableImpl() : m_mean(1.0), m_shape(1.5), m_bound(0) { } -ParetoVariable::ParetoVariable(double m) +ParetoVariableImpl::ParetoVariableImpl(double m) : m_mean(m), m_shape(1.5), m_bound(0) { } -ParetoVariable::ParetoVariable(double m, double s) +ParetoVariableImpl::ParetoVariableImpl(double m, double s) : m_mean(m), m_shape(s), m_bound(0) { } -ParetoVariable::ParetoVariable(double m, double s, double b) +ParetoVariableImpl::ParetoVariableImpl(double m, double s, double b) : m_mean(m), m_shape(s), m_bound(b) { } -ParetoVariable::ParetoVariable(const ParetoVariable& c) - : RandomVariable(c), m_mean(c.m_mean), m_shape(c.m_shape), +ParetoVariableImpl::ParetoVariableImpl(const ParetoVariableImpl& c) + : RandomVariableBase(c), m_mean(c.m_mean), m_shape(c.m_shape), m_bound(c.m_bound) { } -double ParetoVariable::GetValue() +double ParetoVariableImpl::GetValue() { - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } double scale = m_mean * ( m_shape - 1.0) / m_shape; double r = (scale * ( 1.0 / pow(m_generator->RandU01(), 1.0 / m_shape))); @@ -400,49 +768,127 @@ double ParetoVariable::GetValue() return r; } -RandomVariable* ParetoVariable::Copy() const +RandomVariableBase* ParetoVariableImpl::Copy() const { - return new ParetoVariable(*this); + return new ParetoVariableImpl(*this); } -double ParetoVariable::GetSingleValue(double m, double s, double b/*=0*/) +double ParetoVariableImpl::GetSingleValue(double m, double s, double b/*=0*/) { - if(!RandomVariable::m_static_generator) + if(!RandomVariableBase::m_static_generator) { - RandomVariable::Initialize(); // sets the static package seed - RandomVariable::m_static_generator = new RngStream(); - RandomVariable::m_static_generator->InitializeStream(); + RandomVariableBase::Initialize(); // sets the static package seed + RandomVariableBase::m_static_generator = new RngStream(); + RandomVariableBase::m_static_generator->InitializeStream(); } double scale = m * ( s - 1.0) / s; double r = (scale * ( 1.0 / pow(m_static_generator->RandU01(), 1.0 / s))); if (b != 0 && r > b) return b; return r; } + +ParetoVariable::ParetoVariable () + : RandomVariable (ParetoVariableImpl ()) +{} +ParetoVariable::ParetoVariable(double m) + : RandomVariable (ParetoVariableImpl (m)) +{} +ParetoVariable::ParetoVariable(double m, double s) + : RandomVariable (ParetoVariableImpl (m, s)) +{} +ParetoVariable::ParetoVariable(double m, double s, double b) + : RandomVariable (ParetoVariableImpl (m, s, b)) +{} +double +ParetoVariable::GetSingleValue(double m, double s, double b) +{ + return ParetoVariableImpl::GetSingleValue (m, s, b); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// WeibullVariable methods -WeibullVariable::WeibullVariable() : m_mean(1.0), m_alpha(1), m_bound(0) { } -WeibullVariable::WeibullVariable(double m) +// WeibullVariableImpl methods + +class WeibullVariableImpl : public RandomVariableBase { +public: + /** + * Constructs a weibull random variable with a mean + * value of 1.0 and a shape (alpha) parameter of 1 + */ + WeibullVariableImpl(); + + + /** + * Constructs a weibull random variable with the specified mean + * value and a shape (alpha) parameter of 1.5. + * \param m mean value of the distribution + */ + WeibullVariableImpl(double m) ; + + /** + * Constructs a weibull random variable with the specified mean + * value and a shape (alpha). + * \param m Mean value for the distribution. + * \param s Shape (alpha) parameter for the distribution. + */ + WeibullVariableImpl(double m, double s); + + /** + * \brief Constructs a weibull random variable with the specified mean + * \brief value, shape (alpha), and upper bound. + * Since WeibullVariableImpl distributions can theoretically return unbounded values, + * it is sometimes usefull to specify a fixed upper limit. Note however + * that when the upper limit is specified, the true mean of the distribution + * is slightly smaller than the mean value specified. + * \param m Mean value for the distribution. + * \param s Shape (alpha) parameter for the distribution. + * \param b Upper limit on returned values + */ + WeibullVariableImpl(double m, double s, double b); + + WeibullVariableImpl(const WeibullVariableImpl& c); + + /** + * \return A random value from this Weibull distribution + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; +public: + /** + * \param m Mean value for the distribution. + * \param s Shape (alpha) parameter for the distribution. + * \param b Upper limit on returned values + * \return Random number from a distribution specified by m,s, and b + */ + static double GetSingleValue(double m, double s, double b=0); +private: + double m_mean; // Mean value of RV + double m_alpha; // Shape parameter + double m_bound; // Upper bound on value (if non-zero) +}; + +WeibullVariableImpl::WeibullVariableImpl() : m_mean(1.0), m_alpha(1), m_bound(0) { } +WeibullVariableImpl::WeibullVariableImpl(double m) : m_mean(m), m_alpha(1), m_bound(0) { } -WeibullVariable::WeibullVariable(double m, double s) +WeibullVariableImpl::WeibullVariableImpl(double m, double s) : m_mean(m), m_alpha(s), m_bound(0) { } -WeibullVariable::WeibullVariable(double m, double s, double b) +WeibullVariableImpl::WeibullVariableImpl(double m, double s, double b) : m_mean(m), m_alpha(s), m_bound(b) { }; -WeibullVariable::WeibullVariable(const WeibullVariable& c) - : RandomVariable(c), m_mean(c.m_mean), m_alpha(c.m_alpha), +WeibullVariableImpl::WeibullVariableImpl(const WeibullVariableImpl& c) + : RandomVariableBase(c), m_mean(c.m_mean), m_alpha(c.m_alpha), m_bound(c.m_bound) { } -double WeibullVariable::GetValue() +double WeibullVariableImpl::GetValue() { - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } double exponent = 1.0 / m_alpha; double r = m_mean * pow( -log(m_generator->RandU01()), exponent); @@ -450,52 +896,114 @@ double WeibullVariable::GetValue() return r; } -RandomVariable* WeibullVariable::Copy() const +RandomVariableBase* WeibullVariableImpl::Copy() const { - return new WeibullVariable(*this); + return new WeibullVariableImpl(*this); } -double WeibullVariable::GetSingleValue(double m, double s, double b/*=0*/) +double WeibullVariableImpl::GetSingleValue(double m, double s, double b/*=0*/) { - if(!RandomVariable::m_static_generator) + if(!RandomVariableBase::m_static_generator) { - RandomVariable::Initialize(); // sets the static package seed - RandomVariable::m_static_generator = new RngStream(); - RandomVariable::m_static_generator->InitializeStream(); + RandomVariableBase::Initialize(); // sets the static package seed + RandomVariableBase::m_static_generator = new RngStream(); + RandomVariableBase::m_static_generator->InitializeStream(); } double exponent = 1.0 / s; double r = m * pow( -log(m_static_generator->RandU01()), exponent); if (b != 0 && r > b) return b; return r; } -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// NormalVariable methods -bool NormalVariable::m_static_nextValid = false; -double NormalVariable::m_static_next; -const double NormalVariable::INFINITE_VALUE = 1e307; -NormalVariable::NormalVariable() +WeibullVariable::WeibullVariable() + : RandomVariable (WeibullVariableImpl ()) +{} +WeibullVariable::WeibullVariable(double m) + : RandomVariable (WeibullVariableImpl (m)) +{} +WeibullVariable::WeibullVariable(double m, double s) + : RandomVariable (WeibullVariableImpl (m, s)) +{} +WeibullVariable::WeibullVariable(double m, double s, double b) + : RandomVariable (WeibullVariableImpl (m, s, b)) +{} +double +WeibullVariable::GetSingleValue(double m, double s, double b) +{ + return WeibullVariableImpl::GetSingleValue (m, s, b); +} +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// NormalVariableImpl methods + +class NormalVariableImpl : public RandomVariableBase { // Normally Distributed random var + +public: + static const double INFINITE_VALUE; + /** + * Constructs an normal random variable with a mean + * value of 0 and variance of 1. + */ + NormalVariableImpl(); + + /** + * \brief Construct a normal random variable with specified mean and variance + * \param m Mean value + * \param v Variance + * \param b Bound. The NormalVariableImpl is bounded within +-bound. + */ + NormalVariableImpl(double m, double v, double b = INFINITE_VALUE); + + NormalVariableImpl(const NormalVariableImpl& c); + + /** + * \return A value from this normal distribution + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; +public: + /** + * \param m Mean value + * \param v Variance + * \param b Bound. The NormalVariableImpl is bounded within +-bound. + * \return A random number from a distribution specified by m,v, and b. + */ + static double GetSingleValue(double m, double v, double b = INFINITE_VALUE); +private: + double m_mean; // Mean value of RV + double m_variance; // Mean value of RV + double m_bound; // Bound on value (absolute value) + bool m_nextValid; // True if next valid + double m_next; // The algorithm produces two values at a time + static bool m_static_nextValid; + static double m_static_next; +}; + +bool NormalVariableImpl::m_static_nextValid = false; +double NormalVariableImpl::m_static_next; +const double NormalVariableImpl::INFINITE_VALUE = 1e307; + +NormalVariableImpl::NormalVariableImpl() : m_mean(0.0), m_variance(1.0), m_bound(INFINITE_VALUE), m_nextValid(false){} -NormalVariable::NormalVariable(double m, double v, double b/*=INFINITE_VALUE*/) +NormalVariableImpl::NormalVariableImpl(double m, double v, double b/*=INFINITE_VALUE*/) : m_mean(m), m_variance(v), m_bound(b), m_nextValid(false) { } -NormalVariable::NormalVariable(const NormalVariable& c) - : RandomVariable(c), m_mean(c.m_mean), m_variance(c.m_variance), +NormalVariableImpl::NormalVariableImpl(const NormalVariableImpl& c) + : RandomVariableBase(c), m_mean(c.m_mean), m_variance(c.m_variance), m_bound(c.m_bound) { } -double NormalVariable::GetValue() +double NormalVariableImpl::GetValue() { - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } if (m_nextValid) { // use previously generated @@ -523,18 +1031,18 @@ double NormalVariable::GetValue() } } -RandomVariable* NormalVariable::Copy() const +RandomVariableBase* NormalVariableImpl::Copy() const { - return new NormalVariable(*this); + return new NormalVariableImpl(*this); } -double NormalVariable::GetSingleValue(double m, double v, double b) +double NormalVariableImpl::GetSingleValue(double m, double v, double b) { - if(!RandomVariable::m_static_generator) + if(!RandomVariableBase::m_static_generator) { - RandomVariable::Initialize(); // sets the static package seed - RandomVariable::m_static_generator = new RngStream(); - RandomVariable::m_static_generator->InitializeStream(); + RandomVariableBase::Initialize(); // sets the static package seed + RandomVariableBase::m_static_generator = new RngStream(); + RandomVariableBase::m_static_generator->InitializeStream(); } if (m_static_nextValid) { // use previously generated @@ -562,39 +1070,89 @@ double NormalVariable::GetSingleValue(double m, double v, double b) } } +NormalVariable::NormalVariable() + : RandomVariable (NormalVariableImpl ()) +{} +NormalVariable::NormalVariable(double m, double v, double b) + : RandomVariable (NormalVariableImpl (m, v, b)) +{} +double +NormalVariable::GetSingleValue(double m, double v, double b) +{ + return NormalVariableImpl::GetSingleValue (m, v, b); +} + + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- +class EmpiricalVariableImpl : public RandomVariableBase { +public: + /** + * Constructor for the EmpiricalVariableImpl random variables. + */ + explicit EmpiricalVariableImpl(); + + virtual ~EmpiricalVariableImpl(); + EmpiricalVariableImpl(const EmpiricalVariableImpl& c); + /** + * \return A value from this empirical distribution + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; + /** + * \brief Specifies a point in the empirical distribution + * \param v The function value for this point + * \param c Probability that the function is less than or equal to v + */ + virtual void CDF(double v, double c); // Value, prob <= Value + +private: + class ValueCDF { + public: + ValueCDF(); + ValueCDF(double v, double c); + ValueCDF(const ValueCDF& c); + double value; + double cdf; + }; + virtual void Validate(); // Insure non-decreasing emiprical values + virtual double Interpolate(double, double, double, double, double); + bool validated; // True if non-decreasing validated + std::vector emp; // Empicical CDF +}; + + // ValueCDF methods -EmpiricalVariable::ValueCDF::ValueCDF() +EmpiricalVariableImpl::ValueCDF::ValueCDF() : value(0.0), cdf(0.0){ } -EmpiricalVariable::ValueCDF::ValueCDF(double v, double c) +EmpiricalVariableImpl::ValueCDF::ValueCDF(double v, double c) : value(v), cdf(c) { } -EmpiricalVariable::ValueCDF::ValueCDF(const ValueCDF& c) +EmpiricalVariableImpl::ValueCDF::ValueCDF(const ValueCDF& c) : value(c.value), cdf(c.cdf) { } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// EmpiricalVariable methods -EmpiricalVariable::EmpiricalVariable() +// EmpiricalVariableImpl methods +EmpiricalVariableImpl::EmpiricalVariableImpl() : validated(false) { } -EmpiricalVariable::EmpiricalVariable(const EmpiricalVariable& c) - : RandomVariable(c), validated(c.validated), emp(c.emp) { } +EmpiricalVariableImpl::EmpiricalVariableImpl(const EmpiricalVariableImpl& c) + : RandomVariableBase(c), validated(c.validated), emp(c.emp) { } -EmpiricalVariable::~EmpiricalVariable() { } +EmpiricalVariableImpl::~EmpiricalVariableImpl() { } -double EmpiricalVariable::GetValue() +double EmpiricalVariableImpl::GetValue() { // Return a value from the empirical distribution // This code based (loosely) on code by Bruce Mah (Thanks Bruce!) - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } if (emp.size() == 0) return 0.0; // HuH? No empirical data if (!validated) Validate(); // Insure in non-decreasing @@ -619,18 +1177,18 @@ double EmpiricalVariable::GetValue() } } -RandomVariable* EmpiricalVariable::Copy() const +RandomVariableBase* EmpiricalVariableImpl::Copy() const { - return new EmpiricalVariable(*this); + return new EmpiricalVariableImpl(*this); } -void EmpiricalVariable::CDF(double v, double c) +void EmpiricalVariableImpl::CDF(double v, double c) { // Add a new empirical datapoint to the empirical cdf // NOTE. These MUST be inserted in non-decreasing order emp.push_back(ValueCDF(v, c)); } -void EmpiricalVariable::Validate() +void EmpiricalVariableImpl::Validate() { ValueCDF prior; for (std::vector::size_type i = 0; i < emp.size(); ++i) @@ -650,66 +1208,156 @@ void EmpiricalVariable::Validate() validated = true; } -double EmpiricalVariable::Interpolate(double c1, double c2, +double EmpiricalVariableImpl::Interpolate(double c1, double c2, double v1, double v2, double r) { // Interpolate random value in range [v1..v2) based on [c1 .. r .. c2) return (v1 + ((v2 - v1) / (c2 - c1)) * (r - c1)); } -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Integer EmpiricalVariable methods -IntEmpiricalVariable::IntEmpiricalVariable() { } +EmpiricalVariable::EmpiricalVariable() + : RandomVariable (EmpiricalVariableImpl ()) +{} +EmpiricalVariable::EmpiricalVariable (const RandomVariableBase &variable) + : RandomVariable (variable) +{} +void +EmpiricalVariable::CDF(double v, double c) +{ + EmpiricalVariableImpl *impl = dynamic_cast (Peek ()); + NS_ASSERT (impl); + impl->CDF (v, c); +} -uint32_t IntEmpiricalVariable::GetIntValue() + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Integer EmpiricalVariableImpl methods +class IntEmpiricalVariableImpl : public EmpiricalVariableImpl { +public: + + IntEmpiricalVariableImpl(); + + virtual RandomVariableBase* Copy(void) const; + /** + * \return An integer value from this empirical distribution + */ + virtual uint32_t GetIntValue(); +private: + virtual double Interpolate(double, double, double, double, double); +}; + + +IntEmpiricalVariableImpl::IntEmpiricalVariableImpl() { } + +uint32_t IntEmpiricalVariableImpl::GetIntValue() { return (uint32_t)GetValue(); } -RandomVariable* IntEmpiricalVariable::Copy() const +RandomVariableBase* IntEmpiricalVariableImpl::Copy() const { - return new IntEmpiricalVariable(*this); + return new IntEmpiricalVariableImpl(*this); } -double IntEmpiricalVariable::Interpolate(double c1, double c2, +double IntEmpiricalVariableImpl::Interpolate(double c1, double c2, double v1, double v2, double r) { // Interpolate random value in range [v1..v2) based on [c1 .. r .. c2) return ceil(v1 + ((v2 - v1) / (c2 - c1)) * (r - c1)); } +IntEmpiricalVariable::IntEmpiricalVariable() + : EmpiricalVariable (IntEmpiricalVariableImpl ()) +{} //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// DeterministicVariable -DeterministicVariable::DeterministicVariable(double* d, uint32_t c) +// DeterministicVariableImpl +class DeterministicVariableImpl : public RandomVariableBase +{ + +public: + /** + * \brief Constructor + * + * Creates a generator that returns successive elements of the d array + * on successive calls to ::Value(). Note that the d pointer is copied + * for use by the generator (shallow-copy), not its contents, so the + * contents of the array d points to have to remain unchanged for the use + * of DeterministicVariableImpl to be meaningful. + * \param d Pointer to array of random values to return in sequence + * \param c Number of values in the array + */ + explicit DeterministicVariableImpl(double* d, uint32_t c); + + virtual ~DeterministicVariableImpl(); + /** + * \return The next value in the deterministic sequence + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; +private: + uint32_t count; + uint32_t next; + double* data; +}; + +DeterministicVariableImpl::DeterministicVariableImpl(double* d, uint32_t c) : count(c), next(c), data(d) { // Nothing else needed } -DeterministicVariable::~DeterministicVariable() { } +DeterministicVariableImpl::~DeterministicVariableImpl() { } -double DeterministicVariable::GetValue() +double DeterministicVariableImpl::GetValue() { if (next == count) next = 0; return data[next++]; } -RandomVariable* DeterministicVariable::Copy() const +RandomVariableBase* DeterministicVariableImpl::Copy() const { - return new DeterministicVariable(*this); + return new DeterministicVariableImpl(*this); } +DeterministicVariable::DeterministicVariable(double* d, uint32_t c) + : RandomVariable (DeterministicVariableImpl (d, c)) +{} //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// LogNormalVariable +// LogNormalVariableImpl +class LogNormalVariableImpl : public RandomVariableBase { +public: + /** + * \param mu mu parameter of the lognormal distribution + * \param sigma sigma parameter of the lognormal distribution + */ + LogNormalVariableImpl (double mu, double sigma); -RandomVariable* LogNormalVariable::Copy () const + /** + * \return A random value from this distribution + */ + virtual double GetValue (); + virtual RandomVariableBase* Copy(void) const; +public: + /** + * \param mu mu parameter of the underlying normal distribution + * \param sigma sigma parameter of the underlying normal distribution + * \return A random number from the distribution specified by mu and sigma + */ + static double GetSingleValue(double mu, double sigma); +private: + double m_mu; + double m_sigma; +}; + + +RandomVariableBase* LogNormalVariableImpl::Copy () const { - return new LogNormalVariable (m_mu, m_sigma); + return new LogNormalVariableImpl (m_mu, m_sigma); } -LogNormalVariable::LogNormalVariable (double mu, double sigma) +LogNormalVariableImpl::LogNormalVariableImpl (double mu, double sigma) :m_mu(mu), m_sigma(sigma) { } @@ -741,17 +1389,17 @@ LogNormalVariable::LogNormalVariable (double mu, double sigma) for x > 0. Lognormal random numbers are the exponentials of gaussian random numbers */ double -LogNormalVariable::GetValue () +LogNormalVariableImpl::GetValue () { - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } double u, v, r2, normal, z; @@ -774,13 +1422,13 @@ LogNormalVariable::GetValue () return z; } -double LogNormalVariable::GetSingleValue (double mu, double sigma) +double LogNormalVariableImpl::GetSingleValue (double mu, double sigma) { - if(!RandomVariable::m_static_generator) + if(!RandomVariableBase::m_static_generator) { - RandomVariable::Initialize(); // sets the static package seed - RandomVariable::m_static_generator = new RngStream(); - RandomVariable::m_static_generator->InitializeStream(); + RandomVariableBase::Initialize(); // sets the static package seed + RandomVariableBase::m_static_generator = new RngStream(); + RandomVariableBase::m_static_generator->InitializeStream(); } double u, v, r2, normal, z; do @@ -801,29 +1449,78 @@ double LogNormalVariable::GetSingleValue (double mu, double sigma) return z; } +LogNormalVariable::LogNormalVariable (double mu, double sigma) + : RandomVariable (LogNormalVariableImpl (mu, sigma)) +{} +double +LogNormalVariable::GetSingleValue(double mu, double sigma) +{ + return LogNormalVariableImpl::GetSingleValue (mu, sigma); +} + + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// TriangularVariable methods -TriangularVariable::TriangularVariable() +// TriangularVariableImpl methods +class TriangularVariableImpl : public RandomVariableBase { +public: + /** + * Creates a triangle distribution random number generator in the + * range [0.0 .. 1.0), with mean of 0.5 + */ + TriangularVariableImpl(); + + /** + * Creates a triangle distribution random number generator with the specified + * range + * \param s Low end of the range + * \param l High end of the range + * \param mean mean of the distribution + */ + TriangularVariableImpl(double s, double l, double mean); + + TriangularVariableImpl(const TriangularVariableImpl& c); + + /** + * \return A value from this distribution + */ + virtual double GetValue(); + virtual RandomVariableBase* Copy(void) const; +public: + /** + * \param s Low end of the range + * \param l High end of the range + * \param mean mean of the distribution + * \return A triangularly distributed random number between s and l + */ + static double GetSingleValue(double s, double l, double mean); +private: + double m_min; + double m_max; + double m_mode; //easier to work with the mode internally instead of the mean + //they are related by the simple: mean = (min+max+mode)/3 +}; + +TriangularVariableImpl::TriangularVariableImpl() : m_min(0), m_max(1), m_mode(0.5) { } -TriangularVariable::TriangularVariable(double s, double l, double mean) +TriangularVariableImpl::TriangularVariableImpl(double s, double l, double mean) : m_min(s), m_max(l), m_mode(3.0*mean-s-l) { } -TriangularVariable::TriangularVariable(const TriangularVariable& c) - : RandomVariable(c), m_min(c.m_min), m_max(c.m_max), m_mode(c.m_mode) { } +TriangularVariableImpl::TriangularVariableImpl(const TriangularVariableImpl& c) + : RandomVariableBase(c), m_min(c.m_min), m_max(c.m_max), m_mode(c.m_mode) { } -double TriangularVariable::GetValue() +double TriangularVariableImpl::GetValue() { - if(!RandomVariable::initialized) + if(!RandomVariableBase::initialized) { - RandomVariable::Initialize(); + RandomVariableBase::Initialize(); } if(!m_generator) { m_generator = new RngStream(); m_generator->InitializeStream(); - m_generator->ResetNthSubstream(RandomVariable::runNumber); + m_generator->ResetNthSubstream(RandomVariableBase::runNumber); } double u = m_generator->RandU01(); if(u <= (m_mode - m_min) / (m_max - m_min) ) @@ -832,18 +1529,18 @@ double TriangularVariable::GetValue() return m_max - sqrt( (1-u) * (m_max - m_min) * (m_max - m_mode) ); } -RandomVariable* TriangularVariable::Copy() const +RandomVariableBase* TriangularVariableImpl::Copy() const { - return new TriangularVariable(*this); + return new TriangularVariableImpl(*this); } -double TriangularVariable::GetSingleValue(double s, double l, double mean) +double TriangularVariableImpl::GetSingleValue(double s, double l, double mean) { - if(!RandomVariable::m_static_generator) + if(!RandomVariableBase::m_static_generator) { - RandomVariable::Initialize(); // sets the static package seed - RandomVariable::m_static_generator = new RngStream(); - RandomVariable::m_static_generator->InitializeStream(); + RandomVariableBase::Initialize(); // sets the static package seed + RandomVariableBase::m_static_generator = new RngStream(); + RandomVariableBase::m_static_generator->InitializeStream(); } double mode = 3.0*mean-s-l; double u = m_static_generator->RandU01(); @@ -853,6 +1550,19 @@ double TriangularVariable::GetSingleValue(double s, double l, double mean) return l - sqrt( (1-u) * (l - s) * (l - mode) ); } +TriangularVariable::TriangularVariable() + : RandomVariable (TriangularVariableImpl ()) +{} +TriangularVariable::TriangularVariable(double s, double l, double mean) + : RandomVariable (TriangularVariableImpl (s,l,mean)) +{} +double +TriangularVariable::GetSingleValue(double s, double l, double mean) +{ + return TriangularVariableImpl::GetSingleValue (s,l,mean); +} + + }//namespace ns3 diff --git a/src/core/random-variable.h b/src/core/random-variable.h index 67661f7d3..dd0280745 100644 --- a/src/core/random-variable.h +++ b/src/core/random-variable.h @@ -33,7 +33,7 @@ namespace ns3{ -class RngStream; +class RandomVariableBase; /** * \brief The basic RNG for NS-3. @@ -44,46 +44,31 @@ class RngStream; * the University of Montreal. * * NS-3 has a rich set of random number generators. - * Class RandomVariable defines the base class functionalty + * Class RandomVariableBase defines the base class functionalty * required for all random number generators. By default, the underlying * generator is seeded with the time of day, and then deterministically * creates a sequence of seeds for each subsequent generator that is created. * The rest of the documentation outlines how to change this behavior. */ -class RandomVariable { - +class RandomVariable +{ public: - /** - * \brief Constructor for a random number generator with a random seed. - */ RandomVariable(); - - /** - * \brief Copy constructor - */ - RandomVariable(const RandomVariable&); - - /** - * \brief Destructor for a random number generator with a random seed. - */ - virtual ~RandomVariable(); + RandomVariable(const RandomVariable&o); + RandomVariable &operator = (const RandomVariable &o); + ~RandomVariable(); /** * \brief Returns a random double from the underlying distribution * \return A floating point random value */ - virtual double GetValue() = 0; + double GetValue (void) const; /** * \brief Returns a random integer integer from the underlying distribution * \return Integer cast of ::GetValue() */ - virtual uint32_t GetIntValue(); - - /** - * \return A copy of this object - */ - virtual RandomVariable* Copy() const = 0; + uint32_t GetIntValue (void) const; /** * \brief Get the internal state of the RNG @@ -94,7 +79,7 @@ public: * \param seed Output parameter; gets overwritten with the internal state of * of the RNG. */ - virtual void GetSeed(uint32_t seed[6]); + void GetSeed(uint32_t seed[6]) const; /** * \brief Set seeding behavior @@ -104,7 +89,7 @@ public: * generator is seeded with data from /dev/random instead of * being seeded based upon the time of day. For this to be effective, * it must be called before the creation of the first instance of a - * RandomVariable or subclass. Example: + * RandomVariableBase or subclass. Example: * \code * RandomVariable::UseDevRandom(); * UniformVariable x(2,3); //these are seeded randomly @@ -174,23 +159,12 @@ public: */ static void SetRunNumber(uint32_t n); private: - static void GetRandomSeeds(uint32_t seeds[6]); -private: - static bool useDevRandom; // True if using /dev/random desired - static bool globalSeedSet; // True if global seed has been specified - static int devRandom; // File handle for /dev/random - static uint32_t globalSeed[6]; // The global seed to use - friend class RandomVariableInitializer; + RandomVariableBase *m_variable; protected: - static unsigned long heuristic_sequence; - static RngStream* m_static_generator; - static uint32_t runNumber; - static void Initialize(); // Initialize the RNG system - static bool initialized; // True if package seed is set - RngStream* m_generator; //underlying generator being wrapped + RandomVariable (const RandomVariableBase &variable); + RandomVariableBase *Peek (void); }; - /** * \brief The uniform distribution RNG for NS-3. * \ingroup randomvariable @@ -207,7 +181,8 @@ protected: * UniformVariable::GetSingleValue(100,1000); //returns a value [100,1000) * \endcode */ -class UniformVariable : public RandomVariable { +class UniformVariable : public RandomVariable +{ public: /** * Creates a uniform random number generator in the @@ -221,14 +196,6 @@ public: * \param l High end of the range */ UniformVariable(double s, double l); - - UniformVariable(const UniformVariable& c); - - /** - * \return A value between low and high values specified by the constructor - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; public: /** * \param s Low end of the range @@ -236,50 +203,36 @@ public: * \return A uniformly distributed random number between s and l */ static double GetSingleValue(double s, double l); -private: - double m_min; - double m_max; }; /** * \brief A random variable that returns a constant * \ingroup randomvariable * - * Class ConstantVariable defines a random number generator that + * Class ConstantVariableImpl defines a random number generator that * returns the same value every sample. */ class ConstantVariable : public RandomVariable { public: /** - * Construct a ConstantVariable RNG that returns zero every sample + * Construct a ConstantVariableImpl RNG that returns zero every sample */ ConstantVariable(); /** - * Construct a ConstantVariable RNG that returns the specified value + * Construct a ConstantVariableImpl RNG that returns the specified value * every sample. * \param c Unchanging value for this RNG. */ ConstantVariable(double c); - - ConstantVariable(const ConstantVariable& c) ; - /** * \brief Specify a new constant RNG for this generator. * \param c New constant value for this RNG. */ - void NewConstant(double c); + void SetConstant(double c); - /** - * \return The constant value specified - */ - virtual double GetValue(); - virtual uint32_t GetIntValue(); - virtual RandomVariable* Copy() const; -private: - double m_const; }; /** @@ -291,14 +244,14 @@ private: * increases for a period, then wraps around to the low value * and begins monotonicaly increasing again. */ -class SequentialVariable : public RandomVariable { - +class SequentialVariable : public RandomVariable +{ public: /** - * \brief Constructor for the SequentialVariable RNG. + * \brief Constructor for the SequentialVariableImpl RNG. * * The four parameters define the sequence. For example - * SequentialVariable(0,5,1,2) creates a RNG that has the sequence + * SequentialVariableImpl(0,5,1,2) creates a RNG that has the sequence * 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0 ... * \param f First value of the sequence. * \param l One more than the last value of the sequence. @@ -308,32 +261,17 @@ public: SequentialVariable(double f, double l, double i = 1, uint32_t c = 1); /** - * \brief Constructor for the SequentialVariable RNG. + * \brief Constructor for the SequentialVariableImpl RNG. * * Differs from the first only in that the increment parameter is a * random variable * \param f First value of the sequence. * \param l One more than the last value of the sequence. - * \param i Reference to a RandomVariable for the sequence increment + * \param i Reference to a RandomVariableBase for the sequence increment * \param c Number of times each member of the sequence is repeated */ SequentialVariable(double f, double l, const RandomVariable& i, uint32_t c = 1); - SequentialVariable(const SequentialVariable& c); - - ~SequentialVariable(); - /** - * \return The next value in the Sequence - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; -private: - double m_min; - double m_max; - RandomVariable* m_increment; - uint32_t m_consecutive; - double m_current; - uint32_t m_currentConsecutive; }; /** @@ -353,14 +291,15 @@ private: * \f$ \left\{ \begin{array}{cl} \alpha e^{-\alpha x} & x < bound \\ bound & x > bound \end{array}\right. \f$ * * \code - * ExponentialVariable x(3.14); + * ExponentialVariableImpl x(3.14); * x.GetValue(); //will always return with mean 3.14 - * ExponentialVariable::GetSingleValue(20.1); //returns with mean 20.1 - * ExponentialVariable::GetSingleValue(108); //returns with mean 108 + * ExponentialVariableImpl::GetSingleValue(20.1); //returns with mean 20.1 + * ExponentialVariableImpl::GetSingleValue(108); //returns with mean 108 * \endcode * */ -class ExponentialVariable : public RandomVariable { +class ExponentialVariable : public RandomVariable +{ public: /** * Constructs an exponential random variable with a mean @@ -387,27 +326,16 @@ public: */ ExponentialVariable(double m, double b); - ExponentialVariable(const ExponentialVariable& c); - - /** - * \return A random value from this exponential distribution - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; -public: /** * \param m The mean of the distribution from which the return value is drawn * \param b The upper bound value desired, beyond which values get clipped * \return A random number from an exponential distribution with mean m */ static double GetSingleValue(double m, double b=0); -private: - double m_mean; // Mean value of RV - double m_bound; // Upper bound on value (if non-zero) }; /** - * \brief ParetoVariable distributed random var + * \brief ParetoVariableImpl distributed random var * \ingroup randomvariable * * This class supports the creation of objects that return random numbers @@ -422,19 +350,20 @@ private: * with the equation \f$ x_m = mean \frac{k-1}{k}, k > 1\f$. * * \code - * ParetoVariable x(3.14); + * ParetoVariableImpl x(3.14); * x.GetValue(); //will always return with mean 3.14 - * ParetoVariable::GetSingleValue(20.1); //returns with mean 20.1 - * ParetoVariable::GetSingleValue(108); //returns with mean 108 + * ParetoVariableImpl::GetSingleValue(20.1); //returns with mean 20.1 + * ParetoVariableImpl::GetSingleValue(108); //returns with mean 108 * \endcode */ -class ParetoVariable : public RandomVariable { +class ParetoVariable : public RandomVariable +{ public: /** * Constructs a pareto random variable with a mean of 1 and a shape * parameter of 1.5 */ - ParetoVariable(); + ParetoVariable (); /** * Constructs a pareto random variable with specified mean and shape @@ -465,14 +394,6 @@ public: */ ParetoVariable(double m, double s, double b); - ParetoVariable(const ParetoVariable& c); - - /** - * \return A random value from this Pareto distribution - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; -public: /** * \param m The mean value of the distribution from which the return value * is drawn. @@ -483,14 +404,10 @@ public: * parameter s. */ static double GetSingleValue(double m, double s, double b=0); -private: - double m_mean; // Mean value of RV - double m_shape; // Shape parameter - double m_bound; // Upper bound on value (if non-zero) }; /** - * \brief WeibullVariable distributed random var + * \brief WeibullVariableImpl distributed random var * \ingroup randomvariable * * This class supports the creation of objects that return random numbers @@ -530,7 +447,7 @@ public: /** * \brief Constructs a weibull random variable with the specified mean * \brief value, shape (alpha), and upper bound. - * Since WeibullVariable distributions can theoretically return unbounded values, + * Since WeibullVariableImpl distributions can theoretically return unbounded values, * it is sometimes usefull to specify a fixed upper limit. Note however * that when the upper limit is specified, the true mean of the distribution * is slightly smaller than the mean value specified. @@ -539,15 +456,6 @@ public: * \param b Upper limit on returned values */ WeibullVariable(double m, double s, double b); - - WeibullVariable(const WeibullVariable& c); - - /** - * \return A random value from this Weibull distribution - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; -public: /** * \param m Mean value for the distribution. * \param s Shape (alpha) parameter for the distribution. @@ -555,14 +463,10 @@ public: * \return Random number from a distribution specified by m,s, and b */ static double GetSingleValue(double m, double s, double b=0); -private: - double m_mean; // Mean value of RV - double m_alpha; // Shape parameter - double m_bound; // Upper bound on value (if non-zero) }; /** - * \brief Class NormalVariable defines a random variable with a + * \brief Class NormalVariableImpl defines a random variable with a * normal (Gaussian) distribution. * \ingroup randomvariable * @@ -575,8 +479,8 @@ private: * where \f$ mean = \mu \f$ and \f$ variance = \sigma^2 \f$ * */ -class NormalVariable : public RandomVariable { // Normally Distributed random var - +class NormalVariable : public RandomVariable +{ public: static const double INFINITE_VALUE; /** @@ -589,37 +493,20 @@ public: * \brief Construct a normal random variable with specified mean and variance * \param m Mean value * \param v Variance - * \param b Bound. The NormalVariable is bounded within +-bound. + * \param b Bound. The NormalVariableImpl is bounded within +-bound. */ NormalVariable(double m, double v, double b = INFINITE_VALUE); - - NormalVariable(const NormalVariable& c); - - /** - * \return A value from this normal distribution - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; -public: /** * \param m Mean value * \param v Variance - * \param b Bound. The NormalVariable is bounded within +-bound. + * \param b Bound. The NormalVariableImpl is bounded within +-bound. * \return A random number from a distribution specified by m,v, and b. */ static double GetSingleValue(double m, double v, double b = INFINITE_VALUE); -private: - double m_mean; // Mean value of RV - double m_variance; // Mean value of RV - double m_bound; // Bound on value (absolute value) - bool m_nextValid; // True if next valid - double m_next; // The algorithm produces two values at a time - static bool m_static_nextValid; - static double m_static_next; }; /** - * \brief EmpiricalVariable distribution random var + * \brief EmpiricalVariableImpl distribution random var * \ingroup randomvariable * * Defines a random variable that has a specified, empirical @@ -634,37 +521,18 @@ private: class EmpiricalVariable : public RandomVariable { public: /** - * Constructor for the EmpiricalVariable random variables. + * Constructor for the EmpiricalVariableImpl random variables. */ explicit EmpiricalVariable(); - virtual ~EmpiricalVariable(); - EmpiricalVariable(const EmpiricalVariable& c); - /** - * \return A value from this empirical distribution - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; /** * \brief Specifies a point in the empirical distribution * \param v The function value for this point * \param c Probability that the function is less than or equal to v */ - virtual void CDF(double v, double c); // Value, prob <= Value - -private: - class ValueCDF { - public: - ValueCDF(); - ValueCDF(double v, double c); - ValueCDF(const ValueCDF& c); - double value; - double cdf; - }; - virtual void Validate(); // Insure non-decreasing emiprical values - virtual double Interpolate(double, double, double, double, double); - bool validated; // True if non-decreasing validated - std::vector emp; // Empicical CDF + void CDF(double v, double c); // Value, prob <= Value +protected: + EmpiricalVariable (const RandomVariableBase &variable); }; /** @@ -672,20 +540,13 @@ private: * \ingroup randomvariable * * Defines an empirical distribution where all values are integers. - * Indentical to EmpiricalVariable, but with slightly different + * Indentical to EmpiricalVariableImpl, but with slightly different * interpolation between points. */ -class IntEmpiricalVariable : public EmpiricalVariable { +class IntEmpiricalVariable : public EmpiricalVariable +{ public: - IntEmpiricalVariable(); - - virtual RandomVariable* Copy() const; - /** - * \return An integer value from this empirical distribution - */ - virtual uint32_t GetIntValue(); - virtual double Interpolate(double, double, double, double, double); }; /** @@ -697,8 +558,8 @@ public: * the RNG to return a known sequence, perhaps to * compare NS-3 to some other simulator */ -class DeterministicVariable : public RandomVariable { - +class DeterministicVariable : public RandomVariable +{ public: /** * \brief Constructor @@ -707,22 +568,11 @@ public: * on successive calls to ::Value(). Note that the d pointer is copied * for use by the generator (shallow-copy), not its contents, so the * contents of the array d points to have to remain unchanged for the use - * of DeterministicVariable to be meaningful. + * of DeterministicVariableImpl to be meaningful. * \param d Pointer to array of random values to return in sequence * \param c Number of values in the array */ explicit DeterministicVariable(double* d, uint32_t c); - - virtual ~DeterministicVariable(); - /** - * \return The next value in the deterministic sequence - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; -private: - uint32_t count; - uint32_t next; - double* data; }; @@ -730,7 +580,7 @@ private: * \brief Log-normal Distributed random var * \ingroup randomvariable * - * LogNormalVariable defines a random variable with log-normal + * LogNormalVariableImpl defines a random variable with log-normal * distribution. If one takes the natural logarithm of random * variable following the log-normal distribution, the obtained values * follow a normal distribution. @@ -748,7 +598,8 @@ private: * \f$ \mu = ln(mean) - \frac{1}{2}ln\left(1+\frac{stddev}{mean^2}\right)\f$, and, * \f$ \sigma = \sqrt{ln\left(1+\frac{stddev}{mean^2}\right)}\f$ */ -class LogNormalVariable : public RandomVariable { +class LogNormalVariable : public RandomVariable +{ public: /** * \param mu mu parameter of the lognormal distribution @@ -756,21 +607,12 @@ public: */ LogNormalVariable (double mu, double sigma); - /** - * \return A random value from this distribution - */ - virtual double GetValue (); - virtual RandomVariable* Copy() const; -public: /** * \param mu mu parameter of the underlying normal distribution * \param sigma sigma parameter of the underlying normal distribution * \return A random number from the distribution specified by mu and sigma */ static double GetSingleValue(double mu, double sigma); -private: - double m_mu; - double m_sigma; }; /** @@ -780,7 +622,8 @@ private: * This distribution is a triangular distribution. The probablility density * is in the shape of a triangle. */ -class TriangularVariable : public RandomVariable { +class TriangularVariable : public RandomVariable +{ public: /** * Creates a triangle distribution random number generator in the @@ -796,15 +639,6 @@ public: * \param mean mean of the distribution */ TriangularVariable(double s, double l, double mean); - - TriangularVariable(const TriangularVariable& c); - - /** - * \return A value from this distribution - */ - virtual double GetValue(); - virtual RandomVariable* Copy() const; -public: /** * \param s Low end of the range * \param l High end of the range @@ -812,11 +646,6 @@ public: * \return A triangularly distributed random number between s and l */ static double GetSingleValue(double s, double l, double mean); -private: - double m_min; - double m_max; - double m_mode; //easier to work with the mode internally instead of the mean - //they are related by the simple: mean = (min+max+mode)/3 }; }//namespace ns3 diff --git a/src/devices/wifi/propagation-delay-model.cc b/src/devices/wifi/propagation-delay-model.cc index e62edf12c..b55154766 100644 --- a/src/devices/wifi/propagation-delay-model.cc +++ b/src/devices/wifi/propagation-delay-model.cc @@ -69,20 +69,18 @@ PropagationDelayModel::CreateDefault (void) } RandomPropagationDelayModel::RandomPropagationDelayModel () - : m_variable (g_random.GetCopy ()) + : m_variable (g_random.Get ()) {} RandomPropagationDelayModel::RandomPropagationDelayModel (const RandomVariable &variable) - : m_variable (variable.Copy ()) + : m_variable (variable) {} RandomPropagationDelayModel::~RandomPropagationDelayModel () -{ - delete m_variable; -} +{} Time RandomPropagationDelayModel::GetDelay (Ptr a, Ptr b) const { - return Seconds (m_variable->GetValue ()); + return Seconds (m_variable.GetValue ()); } ConstantSpeedPropagationDelayModel::ConstantSpeedPropagationDelayModel (double speed) diff --git a/src/devices/wifi/propagation-delay-model.h b/src/devices/wifi/propagation-delay-model.h index e1fd752f2..4fb80f685 100644 --- a/src/devices/wifi/propagation-delay-model.h +++ b/src/devices/wifi/propagation-delay-model.h @@ -23,13 +23,12 @@ #include "ns3/ptr.h" #include "ns3/object.h" #include "ns3/nstime.h" +#include "ns3/random-variable.h" namespace ns3 { class MobilityModel; -class RandomVariable; - /** * \brief calculate a propagation delay. */ @@ -71,7 +70,7 @@ public: virtual ~RandomPropagationDelayModel (); virtual Time GetDelay (Ptr a, Ptr b) const; private: - RandomVariable *m_variable; + RandomVariable m_variable; }; /** diff --git a/src/devices/wifi/propagation-loss-model.cc b/src/devices/wifi/propagation-loss-model.cc index c74e258b7..29f3475e8 100644 --- a/src/devices/wifi/propagation-loss-model.cc +++ b/src/devices/wifi/propagation-loss-model.cc @@ -104,23 +104,21 @@ PropagationLossModel::CreateDefault (void) } } RandomPropagationLossModel::RandomPropagationLossModel () - : m_variable (g_random.GetCopy ()) + : m_variable (g_random.Get ()) {} RandomPropagationLossModel::RandomPropagationLossModel (const RandomVariable &variable) - : m_variable (variable.Copy ()) + : m_variable (variable) {} RandomPropagationLossModel::~RandomPropagationLossModel () -{ - delete m_variable; -} +{} double RandomPropagationLossModel::GetRxPower (double txPowerDbm, Ptr a, Ptr b) const { - double rxPower = txPowerDbm - m_variable->GetValue (); + double rxPower = txPowerDbm - m_variable.GetValue (); NS_LOG_DEBUG ("tx power="< a, Ptr b) const; private: - RandomVariable *m_variable; + RandomVariable m_variable; }; /** diff --git a/src/mobility/random-direction-2d-mobility-model.cc b/src/mobility/random-direction-2d-mobility-model.cc index 9f13588dc..fb6703d3d 100644 --- a/src/mobility/random-direction-2d-mobility-model.cc +++ b/src/mobility/random-direction-2d-mobility-model.cc @@ -54,8 +54,8 @@ static RectangleDefaultValue RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters () : m_bounds (g_bounds.GetValue ()), - m_speedVariable (g_speedVariable.GetCopy ()), - m_pauseVariable (g_pauseVariable.GetCopy ()) + m_speedVariable (g_speedVariable.Get ()), + m_pauseVariable (g_pauseVariable.Get ()) {} RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters @@ -63,29 +63,22 @@ RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParamete const RandomVariable &speedVariable, const RandomVariable &pauseVariable) : m_bounds (bounds), - m_speedVariable (speedVariable.Copy ()), - m_pauseVariable (pauseVariable.Copy ()) + m_speedVariable (speedVariable), + m_pauseVariable (pauseVariable) {} RandomDirection2dMobilityModelParameters::~RandomDirection2dMobilityModelParameters () -{ - delete m_speedVariable; - delete m_pauseVariable; - m_speedVariable = 0; - m_pauseVariable = 0; -} +{} void RandomDirection2dMobilityModelParameters::SetSpeed (const RandomVariable &speedVariable) { - delete m_speedVariable; - m_speedVariable = speedVariable.Copy (); + m_speedVariable = speedVariable; } void RandomDirection2dMobilityModelParameters::SetPause (const RandomVariable &pauseVariable) { - delete m_pauseVariable; - m_pauseVariable = pauseVariable.Copy (); + m_pauseVariable = pauseVariable; } void RandomDirection2dMobilityModelParameters::SetBounds (const Rectangle &bounds) @@ -149,7 +142,7 @@ RandomDirection2dMobilityModel::Start (void) void RandomDirection2dMobilityModel::BeginPause (void) { - Time pause = Seconds (m_parameters->m_pauseVariable->GetValue ()); + Time pause = Seconds (m_parameters->m_pauseVariable.GetValue ()); m_helper.Pause (); m_event = Simulator::Schedule (pause, &RandomDirection2dMobilityModel::ResetDirectionAndSpeed, this); NotifyCourseChange (); @@ -159,7 +152,7 @@ void RandomDirection2dMobilityModel::SetDirectionAndSpeed (double direction) { NS_LOG_FUNCTION; - double speed = m_parameters->m_speedVariable->GetValue (); + double speed = m_parameters->m_speedVariable.GetValue (); const Vector vector (std::cos (direction) * speed, std::sin (direction) * speed, 0.0); diff --git a/src/mobility/random-direction-2d-mobility-model.h b/src/mobility/random-direction-2d-mobility-model.h index 14fd06611..f12e5b8cb 100644 --- a/src/mobility/random-direction-2d-mobility-model.h +++ b/src/mobility/random-direction-2d-mobility-model.h @@ -26,13 +26,12 @@ #include "ns3/nstime.h" #include "ns3/event-id.h" #include "ns3/rectangle.h" +#include "ns3/random-variable.h" #include "mobility-model.h" #include "static-speed-helper.h" namespace ns3 { -class RandomVariable; - /** * \brief the parameters to control a RandomDirection mobility model. */ @@ -73,8 +72,8 @@ class RandomDirection2dMobilityModelParameters : public Object static Ptr GetCurrent (void); Rectangle m_bounds; - RandomVariable *m_speedVariable; - RandomVariable *m_pauseVariable; + RandomVariable m_speedVariable; + RandomVariable m_pauseVariable; }; /** diff --git a/src/mobility/random-position.cc b/src/mobility/random-position.cc index 8823b2262..5db9f89f0 100644 --- a/src/mobility/random-position.cc +++ b/src/mobility/random-position.cc @@ -88,26 +88,21 @@ RandomRectanglePosition::GetTypeId (void) } RandomRectanglePosition::RandomRectanglePosition () - : m_x (g_rectangleX.GetCopy ()), - m_y (g_rectangleY.GetCopy ()) + : m_x (g_rectangleX.Get ()), + m_y (g_rectangleY.Get ()) {} RandomRectanglePosition::RandomRectanglePosition (const RandomVariable &x, const RandomVariable &y) - : m_x (x.Copy ()), - m_y (y.Copy ()) + : m_x (x), + m_y (y) {} RandomRectanglePosition::~RandomRectanglePosition () -{ - delete m_x; - delete m_y; - m_x = 0; - m_y = 0; -} +{} Vector RandomRectanglePosition::Get (void) const { - double x = m_x->GetValue (); - double y = m_y->GetValue (); + double x = m_x.GetValue (); + double y = m_y.GetValue (); return Vector (x, y, 0.0); } @@ -123,31 +118,26 @@ RandomDiscPosition::GetTypeId (void) } RandomDiscPosition::RandomDiscPosition () - : m_theta (g_discTheta.GetCopy ()), - m_rho (g_discRho.GetCopy ()), + : m_theta (g_discTheta.Get ()), + m_rho (g_discRho.Get ()), m_x (g_discX.GetValue ()), m_y (g_discY.GetValue ()) {} RandomDiscPosition::RandomDiscPosition (const RandomVariable &theta, const RandomVariable &rho, double x, double y) - : m_theta (theta.Copy ()), - m_rho (rho.Copy ()), + : m_theta (theta), + m_rho (rho), m_x (0.0), m_y (0.0) {} RandomDiscPosition::~RandomDiscPosition () -{ - delete m_theta; - delete m_rho; - m_theta = 0; - m_rho = 0; -} +{} Vector RandomDiscPosition::Get (void) const { - double theta = m_theta->GetValue (); - double rho = m_rho->GetValue (); + double theta = m_theta.GetValue (); + double rho = m_rho.GetValue (); double x = m_x + std::cos (theta) * rho; double y = m_y + std::sin (theta) * rho; NS_LOG_DEBUG ("Disc position x=" << x << ", y=" << y); diff --git a/src/mobility/random-position.h b/src/mobility/random-position.h index c9f0c65f8..2e4fc28cc 100644 --- a/src/mobility/random-position.h +++ b/src/mobility/random-position.h @@ -21,12 +21,11 @@ #define RANDOM_POSITION_H #include "ns3/object.h" +#include "ns3/random-variable.h" #include "vector.h" namespace ns3 { -class RandomVariable; - /** * \brief choose a position at random. * @@ -69,8 +68,8 @@ public: virtual ~RandomRectanglePosition (); virtual Vector Get (void) const; private: - RandomVariable *m_x; - RandomVariable *m_y; + RandomVariable m_x; + RandomVariable m_y; }; /** @@ -107,8 +106,8 @@ public: virtual ~RandomDiscPosition (); virtual Vector Get (void) const; private: - RandomVariable *m_theta; - RandomVariable *m_rho; + RandomVariable m_theta; + RandomVariable m_rho; double m_x; double m_y; }; diff --git a/src/mobility/random-walk-2d-mobility-model.cc b/src/mobility/random-walk-2d-mobility-model.cc index 5210f9d7d..bf488ece6 100644 --- a/src/mobility/random-walk-2d-mobility-model.cc +++ b/src/mobility/random-walk-2d-mobility-model.cc @@ -69,30 +69,23 @@ RandomWalk2dMobilityModelParameters::RandomWalk2dMobilityModelParameters () : m_mode (g_mode.GetValue ()), m_modeDistance (g_modeDistance.GetValue ()), m_modeTime (g_modeTime.GetValue ()), - m_speed (g_speed.GetCopy ()), - m_direction (g_direction.GetCopy ()), + m_speed (g_speed.Get ()), + m_direction (g_direction.Get ()), m_bounds (g_rectangle.GetValue ()) {} RandomWalk2dMobilityModelParameters::~RandomWalk2dMobilityModelParameters () -{ - delete m_speed; - delete m_direction; - m_speed = 0; - m_direction = 0; -} +{} void RandomWalk2dMobilityModelParameters::SetSpeed (const RandomVariable &speed) { - delete m_speed; - m_speed = speed.Copy (); + m_speed = speed; } void RandomWalk2dMobilityModelParameters::SetDirection (const RandomVariable &direction) { - delete m_direction; - m_direction = direction.Copy (); + m_direction = direction; } void RandomWalk2dMobilityModelParameters::SetModeDistance (double distance) @@ -154,8 +147,8 @@ RandomWalk2dMobilityModel::RandomWalk2dMobilityModel (Ptrm_speed->GetValue (); - double direction = m_parameters->m_direction->GetValue (); + double speed = m_parameters->m_speed.GetValue (); + double direction = m_parameters->m_direction.GetValue (); Vector vector (std::cos (direction) * speed, std::sin (direction) * speed, 0.0); diff --git a/src/mobility/random-walk-2d-mobility-model.h b/src/mobility/random-walk-2d-mobility-model.h index 376152d52..600ed1435 100644 --- a/src/mobility/random-walk-2d-mobility-model.h +++ b/src/mobility/random-walk-2d-mobility-model.h @@ -25,12 +25,12 @@ #include "ns3/nstime.h" #include "ns3/event-id.h" #include "ns3/rectangle.h" +#include "ns3/random-variable.h" #include "mobility-model.h" #include "static-speed-helper.h" namespace ns3 { -class RandomVariable; /** * \brief parameters to control a random walk 2d model @@ -93,8 +93,8 @@ class RandomWalk2dMobilityModelParameters : public Object enum Mode m_mode; double m_modeDistance; Time m_modeTime; - RandomVariable *m_speed; - RandomVariable *m_direction; + RandomVariable m_speed; + RandomVariable m_direction; Rectangle m_bounds; }; diff --git a/src/mobility/random-waypoint-mobility-model.cc b/src/mobility/random-waypoint-mobility-model.cc index 408a6f38d..1fb9bb91a 100644 --- a/src/mobility/random-waypoint-mobility-model.cc +++ b/src/mobility/random-waypoint-mobility-model.cc @@ -47,16 +47,16 @@ g_position ("RandomWaypointPosition", RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters () - : m_speed (g_speed.GetCopy ()), - m_pause (g_pause.GetCopy ()) + : m_speed (g_speed.Get ()), + m_pause (g_pause.Get ()) { m_position = g_position.GetValue ().CreateObject ()->QueryInterface (); } RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters (Ptr randomPosition, const RandomVariable &speed, const RandomVariable &pause) - : m_speed (speed.Copy ()), - m_pause (pause.Copy ()), + : m_speed (speed), + m_pause (pause), m_position (randomPosition) {} void @@ -67,23 +67,17 @@ RandomWaypointMobilityModelParameters::SetWaypointPositionModel (Ptr @@ -128,7 +122,7 @@ RandomWaypointMobilityModel::BeginWalk (void) { Vector m_current = m_helper.GetCurrentPosition (); Vector destination = m_parameters->m_position->Get (); - double speed = m_parameters->m_speed->GetValue (); + double speed = m_parameters->m_speed.GetValue (); double dx = (destination.x - m_current.x); double dy = (destination.y - m_current.y); double dz = (destination.z - m_current.z); @@ -144,7 +138,7 @@ RandomWaypointMobilityModel::BeginWalk (void) void RandomWaypointMobilityModel::Start (void) { - Time pause = Seconds (m_parameters->m_pause->GetValue ()); + Time pause = Seconds (m_parameters->m_pause.GetValue ()); m_helper.Pause (); NotifyCourseChange (); m_event = Simulator::Schedule (pause, &RandomWaypointMobilityModel::BeginWalk, this); diff --git a/src/mobility/random-waypoint-mobility-model.h b/src/mobility/random-waypoint-mobility-model.h index d6dd0ac53..7b3288177 100644 --- a/src/mobility/random-waypoint-mobility-model.h +++ b/src/mobility/random-waypoint-mobility-model.h @@ -25,11 +25,10 @@ #include "mobility-model.h" #include "random-position.h" #include "ns3/ptr.h" +#include "ns3/random-variable.h" namespace ns3 { -class RandomVariable; - /** * \brief the parameters which control the behavior of a random waypoint * mobility model. @@ -66,8 +65,8 @@ private: friend class RandomWaypointMobilityModel; static Ptr GetCurrent (void); virtual void DoDispose (void); - RandomVariable *m_speed; - RandomVariable *m_pause; + RandomVariable m_speed; + RandomVariable m_pause; Ptr m_position; }; diff --git a/src/node/application.cc b/src/node/application.cc index 3346da3c2..73d8b47ed 100644 --- a/src/node/application.cc +++ b/src/node/application.cc @@ -59,9 +59,8 @@ void Application::Start(const Time& startTime) void Application::Start(const RandomVariable& startVar) { - RandomVariable *v = startVar.Copy (); - ScheduleStart (Seconds (v->GetValue ())); - delete v; + RandomVariable v = startVar; + ScheduleStart (Seconds (v.GetValue ())); } @@ -72,9 +71,8 @@ void Application::Stop(const Time& stopTime) void Application::Stop(const RandomVariable& stopVar) { - RandomVariable *v = stopVar.Copy (); - ScheduleStop (Seconds (v->GetValue ())); - delete v; + RandomVariable v = stopVar; + ScheduleStop (Seconds (v.GetValue ())); } Ptr Application::GetNode() const