# HG changeset patch # User Emmanuelle Laprise # Date 1179421964 18000 # Node ID a90ed09b728bc47bec87bb5f94b9e22a995dd6b5 # Parent 2f285162b6ca4810dbba03e8867ea75824c3a940 The header file ns3/cairo-wideint-private.h was added since the type int32_t was used. diff -r 2f285162b6ca -r a90ed09b728b src/core/random-variable.h --- a/src/core/random-variable.h Tue May 15 17:12:36 2007 +0200 +++ b/src/core/random-variable.h Thu May 17 12:12:44 2007 -0500 @@ -23,7 +23,7 @@ #include #include - +#include "ns3/cairo-wideint-private.h" /** * \defgroup randomvariable Random Variable Distributions diff -r 2f285162b6ca -r a90ed09b728b src/core/rng-stream.h --- a/src/core/rng-stream.h Tue May 15 17:12:36 2007 +0200 +++ b/src/core/rng-stream.h Thu May 17 12:12:44 2007 -0500 @@ -20,6 +20,7 @@ #ifndef RNGSTREAM_H #define RNGSTREAM_H #include +#include "ns3/cairo-wideint-private.h" namespace ns3{ # HG changeset patch # User Emmanuelle Laprise # Date 1179422109 18000 # Node ID 589d7973b133c8bfd9a3cc92f1285f1c849d8548 # Parent a90ed09b728bc47bec87bb5f94b9e22a995dd6b5 Since the precision of the timestep is now configurable, the functions and variables that used to contain the word "ns" for nanosecond were modified to contain "ts" for timestep. diff -r a90ed09b728b -r 589d7973b133 src/simulator/event-id.cc --- a/src/simulator/event-id.cc Thu May 17 12:12:44 2007 -0500 +++ b/src/simulator/event-id.cc Thu May 17 12:15:09 2007 -0500 @@ -26,13 +26,13 @@ namespace ns3 { EventId::EventId () : m_eventImpl (0), - m_ns (0), + m_ts (0), m_uid (0) {} -EventId::EventId (EventImpl *impl, uint64_t ns, uint32_t uid) +EventId::EventId (EventImpl *impl, uint64_t ts, uint32_t uid) : m_eventImpl (impl), - m_ns (ns), + m_ts (ts), m_uid (uid) {} void @@ -60,9 +60,9 @@ EventId::GetEventImpl (void) const return m_eventImpl; } uint64_t -EventId::GetNs (void) const +EventId::GetTs (void) const { - return m_ns; + return m_ts; } uint32_t EventId::GetUid (void) const diff -r a90ed09b728b -r 589d7973b133 src/simulator/event-id.h --- a/src/simulator/event-id.h Thu May 17 12:12:44 2007 -0500 +++ b/src/simulator/event-id.h Thu May 17 12:15:09 2007 -0500 @@ -33,7 +33,7 @@ class EventId { class EventId { public: EventId (); - EventId (EventImpl *impl, uint64_t ns, uint32_t uid); + EventId (EventImpl *impl, uint64_t ts, uint32_t uid); /** * This method is syntactic sugar for the ns3::Simulator::cancel * method. @@ -52,11 +52,11 @@ public: * subclasses of the Scheduler base class. */ EventImpl *GetEventImpl (void) const; - uint64_t GetNs (void) const; + uint64_t GetTs (void) const; uint32_t GetUid (void) const; private: EventImpl *m_eventImpl; - uint64_t m_ns; + uint64_t m_ts; uint32_t m_uid; }; diff -r a90ed09b728b -r 589d7973b133 src/simulator/scheduler-heap.cc --- a/src/simulator/scheduler-heap.cc Thu May 17 12:12:44 2007 -0500 +++ b/src/simulator/scheduler-heap.cc Thu May 17 12:15:09 2007 -0500 @@ -138,11 +138,11 @@ bool bool SchedulerHeap::IsLowerStrictly (Scheduler::EventKey const*a, Scheduler::EventKey const*b) const { - if (a->m_ns < b->m_ns) + if (a->m_ts < b->m_ts) { return true; } - else if (a->m_ns > b->m_ns) + else if (a->m_ts > b->m_ts) { return false; } @@ -226,7 +226,7 @@ SchedulerHeap::RealInsert (EventImpl *ev { m_heap.push_back (std::make_pair (event, key)); BottomUp (); - return EventId (event, key.m_ns, key.m_uid); + return EventId (event, key.m_ts, key.m_uid); } EventImpl * @@ -251,7 +251,7 @@ EventImpl * EventImpl * SchedulerHeap::RealRemove (EventId id, Scheduler::EventKey *key) { - key->m_ns = id.GetNs (); + key->m_ts = id.GetTs (); key->m_uid = id.GetUid (); for (uint32_t i = 1; i < m_heap.size (); i++) { diff -r a90ed09b728b -r 589d7973b133 src/simulator/scheduler-list.cc --- a/src/simulator/scheduler-list.cc Thu May 17 12:12:44 2007 -0500 +++ b/src/simulator/scheduler-list.cc Thu May 17 12:15:09 2007 -0500 @@ -50,11 +50,11 @@ bool bool SchedulerList::IsLower (Scheduler::EventKey const*a, Scheduler::EventKey const*b) const { - if (a->m_ns < b->m_ns) + if (a->m_ts < b->m_ts) { return true; } - else if (a->m_ns == b->m_ns && + else if (a->m_ts == b->m_ts && a->m_uid < b->m_uid) { return true; @@ -73,11 +73,11 @@ SchedulerList::RealInsert (EventImpl *ev if (IsLower (&key, &i->second)) { m_events.insert (i, std::make_pair (event, key)); - return EventId (event, key.m_ns, key.m_uid); + return EventId (event, key.m_ts, key.m_uid); } } m_events.push_back (std::make_pair (event, key)); - return EventId (event, key.m_ns, key.m_uid); + return EventId (event, key.m_ts, key.m_uid); } bool SchedulerList::RealIsEmpty (void) const @@ -110,7 +110,7 @@ SchedulerList::RealRemove (EventId id, S { EventImpl *retval = i->first; NS_ASSERT (id.GetEventImpl () == retval); - key->m_ns = id.GetNs (); + key->m_ts = id.GetTs (); key->m_uid = id.GetUid (); m_events.erase (i); return retval; diff -r a90ed09b728b -r 589d7973b133 src/simulator/scheduler-map.cc --- a/src/simulator/scheduler-map.cc Thu May 17 12:12:44 2007 -0500 +++ b/src/simulator/scheduler-map.cc Thu May 17 12:15:09 2007 -0500 @@ -66,11 +66,11 @@ bool bool SchedulerMap::EventKeyCompare::operator () (struct EventKey const&a, struct EventKey const&b) { - if (a.m_ns < b.m_ns) + if (a.m_ts < b.m_ts) { return true; } - else if (a.m_ns > b.m_ns) + else if (a.m_ts > b.m_ts) { return false; } @@ -92,7 +92,7 @@ SchedulerMap::RealInsert (EventImpl *eve std::pair result; result = m_list.insert (std::make_pair (key, event)); NS_ASSERT (result.second); - return EventId (event, key.m_ns, key.m_uid); + return EventId (event, key.m_ts, key.m_uid); } bool @@ -124,7 +124,7 @@ EventImpl * EventImpl * SchedulerMap::RealRemove (EventId id, Scheduler::EventKey *key) { - key->m_ns = id.GetNs (); + key->m_ts = id.GetTs (); key->m_uid = id.GetUid (); EventMapI i = m_list.find (*key); EventImpl *retval = i->second; diff -r a90ed09b728b -r 589d7973b133 src/simulator/scheduler.h --- a/src/simulator/scheduler.h Thu May 17 12:12:44 2007 -0500 +++ b/src/simulator/scheduler.h Thu May 17 12:15:09 2007 -0500 @@ -55,7 +55,7 @@ class Scheduler { class Scheduler { public: struct EventKey { - uint64_t m_ns; + uint64_t m_ts; uint32_t m_uid; }; # HG changeset patch # User Emmanuelle Laprise # Date 1179422330 18000 # Node ID b48765e3d9021a8ca813f4567cfc91b32eeb6440 # Parent 589d7973b133c8bfd9a3cc92f1285f1c849d8548 The time.cc and nstime.h files were modified to allow the precision of the simulation to be set by the user. The functions and variables that used the word "ns" or "NanoSecond" were changed to "ts" or "TimeStep" to reflect this change. diff -r 589d7973b133 -r b48765e3d902 src/simulator/simulator.cc --- a/src/simulator/simulator.cc Thu May 17 12:15:09 2007 -0500 +++ b/src/simulator/simulator.cc Thu May 17 12:18:50 2007 -0500 @@ -72,7 +72,7 @@ public: private: void ProcessOneEvent (void); - uint64_t NextNs (void) const; + uint64_t NextTs (void) const; typedef std::list > Events; Events m_destroy; @@ -81,7 +81,7 @@ private: Scheduler *m_events; uint32_t m_uid; uint32_t m_currentUid; - uint64_t m_currentNs; + uint64_t m_currentTs; std::ofstream m_log; std::ifstream m_inputLog; bool m_logEnable; @@ -103,7 +103,7 @@ SimulatorPrivate::SimulatorPrivate (Sche // before ::Run is entered, the m_currentUid will be zero m_currentUid = 0; m_logEnable = false; - m_currentNs = 0; + m_currentTs = 0; m_unscheduledEvents = 0; } @@ -136,15 +136,15 @@ SimulatorPrivate::ProcessOneEvent (void) Scheduler::EventKey nextKey = m_events->PeekNextKey (); m_events->RemoveNext (); - NS_ASSERT (nextKey.m_ns >= m_currentNs); + NS_ASSERT (nextKey.m_ts >= m_currentTs); --m_unscheduledEvents; TRACE ("handle " << nextEv); - m_currentNs = nextKey.m_ns; + m_currentTs = nextKey.m_ts; m_currentUid = nextKey.m_uid; if (m_logEnable) { - m_log << "e "<Invoke (); delete nextEv; @@ -156,25 +156,24 @@ SimulatorPrivate::IsFinished (void) cons return m_events->IsEmpty (); } uint64_t -SimulatorPrivate::NextNs (void) const +SimulatorPrivate::NextTs (void) const { NS_ASSERT (!m_events->IsEmpty ()); Scheduler::EventKey nextKey = m_events->PeekNextKey (); - return nextKey.m_ns; + return nextKey.m_ts; } Time SimulatorPrivate::Next (void) const { - return NanoSeconds (NextNs ()); -} - + return TimeStep (NextTs ()); +} void SimulatorPrivate::Run (void) { while (!m_events->IsEmpty () && !m_stop && - (m_stopAt == 0 || m_stopAt > NextNs ())) + (m_stopAt == 0 || m_stopAt > NextTs ())) { ProcessOneEvent (); } @@ -196,19 +195,19 @@ SimulatorPrivate::StopAt (Time const &at SimulatorPrivate::StopAt (Time const &at) { NS_ASSERT (at.IsPositive ()); - m_stopAt = at.GetNanoSeconds (); + m_stopAt = at.GetTimeStep (); } EventId SimulatorPrivate::Schedule (Time const &time, EventImpl *event) { NS_ASSERT (time.IsPositive ()); - NS_ASSERT (time >= NanoSeconds (m_currentNs)); - uint64_t ns = (uint64_t) time.GetNanoSeconds (); - Scheduler::EventKey key = {ns, m_uid}; + NS_ASSERT (time >= TimeStep (m_currentTs)); + uint64_t ts = (uint64_t) time.GetTimeStep (); + Scheduler::EventKey key = {ts, m_uid}; if (m_logEnable) { - m_log << "i "<IsCancelled ()) { # HG changeset patch # User Emmanuelle Laprise # Date 1179422935 18000 # Node ID a7a79006165bbe1e6512c3498a4b6b86b250fa53 # Parent b48765e3d9021a8ca813f4567cfc91b32eeb6440 Modified to allow the user to set the units of the m_data variable used to store the Time value. The units assigned to the m_data variable determine the precision used during the simulation. Increasing the precision of the simulation decreases the maximum simulation time. Decreasing the precision of the simulation increases the maximum simulation time. The m_data variable uses 64 bits to store the timestep value. The auto tests for the TimeUnit class were also improved with some autochecks of resulting values. Other tests were added to test the TimeUnit conversion and to make sure that the different precision values were working as expected. The overflow and precision tests still need to be completed. diff -r b48765e3d902 -r a7a79006165b src/simulator/nstime.h --- a/src/simulator/nstime.h Thu May 17 12:18:50 2007 -0500 +++ b/src/simulator/nstime.h Thu May 17 12:28:55 2007 -0500 @@ -22,9 +22,11 @@ #define TIME_H #include +#include #include "ns3/assert.h" #include #include "high-precision.h" +#include "cairo-wideint-private.h" namespace ns3 { @@ -73,6 +75,34 @@ namespace ns3 { * - \ref ns3-Time-Max ns3::Max * - \ref ns3-Time-Min ns3::Min */ + +typedef uint8_t ts_precision_t; + /** + * Determines the base unit to store time values. If the + * SetTsPrecision function is called, it must be set before any + * TimeValue objects are created. All TimeUnit objects will use the + * same time precision value. The actual time can be + * extracted as follows: m_data*10^(-m_tsPrecision) seconds. + * m_tsPrecision == 0 : m_data stored in sec + * m_tsPrecision == 3 : m_data stored in ms + * m_tsPrecision == 6 : m_data stored in us + * m_tsPrecision == 9 : m_data stored in ns + * m_tsPrecision == 12 : m_data stored in ps + * The default timestep precision units are ns. + */ +enum PrecisionType { + SEC = 0, + MS = 3, + US = 6, + NS = 9, + PS = 12, + FS = 15 +}; +static ts_precision_t m_tsPrecision = NS; +static int64_t m_tsPrecisionFactor = (int64_t)pow(10,m_tsPrecision); + // static void SetTsPrecision(ts_precision_t tsPrecision); + // static ts_precision_t GetTsPrecision(); + template class TimeUnit { @@ -235,6 +265,9 @@ TimeUnit operator * (TimeUnit { HighPrecision retval = lhs.GetHighPrecision (); retval.Mul (rhs.GetHighPrecision ()); + // std::cout << lhs.GetHighPrecision().GetInteger() << " * " + // << rhs.GetHighPrecision().GetInteger() + // << " = " << retval.GetInteger() << std::endl; return TimeUnit (retval); } template @@ -316,6 +349,8 @@ public: * - ms (milliseconds) * - us (microseconds) * - ns (nanoseconds) + * - ps (picoseconds) + * - fs (femtoseconds) * * There can be no white space between the numerical portion * and the units. Any otherwise malformed string causes a fatal error to @@ -332,7 +367,7 @@ public: * \returns an approximation in milliseconds of the time stored in this * instance. */ - int32_t GetMilliSeconds (void) const; + int64_t GetMilliSeconds (void) const; /** * \returns an approximation in microseconds of the time stored in this * instance. @@ -343,6 +378,21 @@ public: * instance. */ int64_t GetNanoSeconds (void) const; + /** + * \returns an approximation in picoseconds of the time stored in this + * instance. + */ + int64_t GetPicoSeconds (void) const; + /** + * \returns an approximation in femtoseconds of the time stored in this + * instance. + */ + int64_t GetFemtoSeconds (void) const; + /** + * \returns an approximation of the time stored in this + * instance in the units specified in m_tsPrecision. + */ + int64_t GetTimeStep (void) const; // -*- The rest is the the same as in the generic template class -*- public: @@ -378,6 +428,7 @@ public: HighPrecision *PeekHighPrecision (void) { return &m_data; } + private: HighPrecision m_data; }; @@ -394,6 +445,8 @@ private: * - ns3::MilliSeconds * - ns3::MicroSeconds * - ns3::NanoSeconds + * - ns3::PicoSeconds + * - ns3::FemtoSeconds * - ns3::Now * * Time instances can be added, substracted, multipled and divided using @@ -417,7 +470,7 @@ private: * instance. * * \code - * int32_t GetMilliSeconds (void) const; + * int64_t GetMilliSeconds (void) const; * \endcode * returns an approximation in milliseconds of the time stored in this * instance. @@ -459,7 +512,7 @@ Time Seconds (double seconds); * Simulator::Schedule (MilliSeconds (5), ...); * \endcode */ -Time MilliSeconds (uint32_t ms); +Time MilliSeconds (uint64_t ms); /** * \brief create ns3::Time instances in units of microseconds. * @@ -480,6 +533,36 @@ Time MicroSeconds (uint64_t us); * \endcode */ Time NanoSeconds (uint64_t ns); +/** + * \brief create ns3::Time instances in units of picoseconds. + * + * For example: + * \code + * Time t = PicoSeconds (2); + * Simulator::Schedule (PicoSeconds (5), ...); + * \endcode + */ +Time PicoSeconds (uint64_t ps); +/** + * \brief create ns3::Time instances in units of femtoseconds. + * + * For example: + * \code + * Time t = FemtoSeconds (2); + * Simulator::Schedule (FemtoSeconds (5), ...); + * \endcode + */ +Time FemtoSeconds (uint64_t fs); +/** + * \brief create ns3::Time instances in units of m_tsPrecision. + * + * For example: + * \code + * Time t = TimeStep (2); + * Simulator::Schedule (TimeStep (5), ...); + * \endcode + */ +Time TimeStep (uint64_t ts); /** * \brief create an ns3::Time instance which contains the @@ -539,6 +622,7 @@ public: HighPrecision *PeekHighPrecision (void) { return &m_data; } + private: HighPrecision m_data; }; diff -r b48765e3d902 -r a7a79006165b src/simulator/time.cc --- a/src/simulator/time.cc Thu May 17 12:18:50 2007 -0500 +++ b/src/simulator/time.cc Thu May 17 12:28:55 2007 -0500 @@ -24,6 +24,19 @@ namespace ns3 { +static ts_precision_t +GetTsPrecision (void) +{ + return m_tsPrecision; +} + +static void +SetTsPrecision (ts_precision_t tsPrecision) +{ + m_tsPrecision = tsPrecision; + m_tsPrecisionFactor = (int64_t)pow(10, m_tsPrecision); +} + TimeUnit<1>::TimeUnit(const std::string& s) { std::string::size_type n = s.find_first_not_of("0123456789."); @@ -33,78 +46,149 @@ TimeUnit<1>::TimeUnit(const std::string& std::string trailer = s.substr(n, std::string::npos); if (trailer == std::string("s")) { - m_data = HighPrecision (r * 1000000000.0); + m_data = HighPrecision (r * m_tsPrecisionFactor); return; } if (trailer == std::string("ms")) { - m_data = HighPrecision ((int64_t)(r * 1000000), false); + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,3))), + false); return; } if (trailer == std::string("us")) { - m_data = HighPrecision ((int64_t)(r * 1000), false); + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,6))), + false); return; } if (trailer == std::string("ns")) { - m_data = HighPrecision ((int64_t)r, false); + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,9))), + false); + return; + } + if (trailer == std::string("ps")) + { + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,12))), + false); + return; + } + if (trailer == std::string("fs")) + { + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,15))), + false); return; } NS_FATAL_ERROR("Can't Parse Time "<::GetSeconds (void) const { - double ns = GetHighPrecision ().GetDouble (); - return ns/1000000000.0; -} -int32_t + double time_value = GetHighPrecision ().GetDouble (); + return time_value/m_tsPrecisionFactor; +} +int64_t TimeUnit<1>::GetMilliSeconds (void) const { - int64_t ns = GetHighPrecision ().GetInteger (); - ns /= 1000000; - return ns; + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,3))); + return time_value; } int64_t TimeUnit<1>::GetMicroSeconds (void) const { - int64_t ns = GetHighPrecision ().GetInteger (); - return ns/1000; + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,6))); + return time_value; } int64_t TimeUnit<1>::GetNanoSeconds (void) const { - return GetHighPrecision ().GetInteger (); -} + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,9))); + return time_value; +} +int64_t +TimeUnit<1>::GetPicoSeconds (void) const +{ + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,12))); + return time_value; +} +int64_t +TimeUnit<1>::GetFemtoSeconds (void) const +{ + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,15))); + return time_value; +} + +/** + * This returns the value with the precision defined in m_tsPrecision + */ +int64_t +TimeUnit<1>::GetTimeStep (void) const +{ + int64_t time_value = GetHighPrecision ().GetInteger (); + return time_value; +} + std::ostream& operator<< (std::ostream& os, Time const& time) { - os << time.GetNanoSeconds () << "ns"; + os << time.GetTimeStep () << "ts"; return os; } Time Seconds (double seconds) { - return Time (HighPrecision (seconds * 1000000000.0)); -} -Time MilliSeconds (uint32_t ms) -{ - return Time (HighPrecision (ms * 1000000, false)); -} + double d_sec = seconds * m_tsPrecisionFactor; + return Time (HighPrecision (d_sec)); + // return Time (HighPrecision ((int64_t)d_sec, false)); +} + +Time MilliSeconds (uint64_t ms) +{ + double d_ms = ms * (m_tsPrecisionFactor/pow(10,3)); + return Time (HighPrecision ((uint64_t)d_ms, false)); +} + Time MicroSeconds (uint64_t us) { - return Time (HighPrecision (us * 1000, false)); -} + double d_us = us * (m_tsPrecisionFactor/pow(10,6)); + return Time (HighPrecision ((uint64_t)d_us, false)); +} + Time NanoSeconds (uint64_t ns) { - return Time (HighPrecision (ns, false)); -} + double d_ns = ns * (m_tsPrecisionFactor/pow(10,9)); + return Time (HighPrecision ((uint64_t)d_ns, false)); +} +Time PicoSeconds (uint64_t ps) +{ + double d_ps = ps * (m_tsPrecisionFactor/pow(10,12)); + return Time (HighPrecision ((uint64_t)d_ps, false)); +} +Time FemtoSeconds (uint64_t fs) +{ + double d_fs = fs * (m_tsPrecisionFactor/pow(10,15)); + return Time (HighPrecision ((uint64_t)d_fs, false)); +} + +/** + * The timestep value passed to this function must be of the precision of m_tsPrecision + */ +Time TimeStep (uint64_t ts) +{ + return Time (HighPrecision (ts, false)); +} + Time Now (void) { return Time (Simulator::Now ()); @@ -136,6 +220,46 @@ public: TimeTests (); virtual ~TimeTests (); virtual bool RunTests (void); + + /** + * Verifies that a calculated time value is as expected using + * doubles since GetSeconds() returns a double + */ + void CheckTimeSec(std::string test_id, double actual, double expected, + bool *flag, double precMultFactor = 1, + bool verbose = false); + + /** + * Verifies that a calculated time value is as expected. + */ + void CheckTime(std::string test_id, int64_t actual, int64_t expected, + bool *flag, double precMultFactor = 1, + bool verbose = false); + + /** + * Verifies the +, -, * and / operations for the TimeUnit<1> or Time class + */ + void CheckOperations(Time t0, Time t1, bool *ok, bool verbose = false); + + /** + * Verifies that the TimeUnit class stores values with the precision + * set in the variable m_tsPrecision + * Checks that overflow and underflow occur at expected numbers + */ + void CheckPrecision(PrecisionType prec, uint64_t val, bool *ok, + bool verbose = false); + + /** + * Verifies that the conversion between units in the class + * TimeUnit<1> or Time is done correctly. This is verified both when + * setting and retrieving a Time value + */ + void CheckConversions(uint64_t tval, bool *ok, bool verbose = false); + + /** + * These are the old tests that used to be run + */ + void CheckOld(bool *ok); }; TimeTests::TimeTests () @@ -143,21 +267,93 @@ TimeTests::TimeTests () {} TimeTests::~TimeTests () {} + bool TimeTests::RunTests (void) { bool ok = true; + Time t0, t1; + + CheckOld(&ok); + + t0 = MilliSeconds ((uint64_t)10.0); + t1 = MilliSeconds ((uint64_t)11.0); + + CheckOperations(t0, t1, &ok); + + // t0 = Seconds ((uint64_t)10.0); + // t1 = Seconds ((uint64_t)11.0); + + // CheckOperations(t0, t1, &ok); + + CheckConversions((uint64_t)5, &ok); + CheckConversions((uint64_t)0, &ok); + CheckConversions((uint64_t)783, &ok); + CheckConversions((uint64_t)1132, &ok); + CheckConversions((uint64_t)3341039, &ok); + + // Now vary the precision and check the conversions + if (GetTsPrecision() != NS) { + ok = false; + } + + CheckPrecision(US, 7, &ok); + + CheckConversions((uint64_t)7, &ok); + CheckConversions((uint64_t)546, &ok); + CheckConversions((uint64_t)6231, &ok); + CheckConversions((uint64_t)1234639, &ok); + + CheckPrecision(MS, 3, &ok); + + CheckConversions((uint64_t)3, &ok); + CheckConversions((uint64_t)134, &ok); + CheckConversions((uint64_t)2341, &ok); + CheckConversions((uint64_t)8956239, &ok); + + CheckPrecision(PS, 21, &ok); + + CheckConversions((uint64_t)4, &ok); + CheckConversions((uint64_t)342, &ok); + CheckConversions((uint64_t)1327, &ok); + CheckConversions((uint64_t)5439627, &ok); + + CheckPrecision(NS, 12, &ok); + CheckConversions((uint64_t)12, &ok); + + CheckPrecision(SEC, 7, &ok); + CheckConversions((uint64_t)7, &ok); + + CheckPrecision(FS, 5, &ok); + CheckConversions((uint64_t)5, &ok); + + return ok; +} + +void TimeTests::CheckOld (bool *ok) +{ + double dt0, dt1, dt2; + int64_t it0, it1; + Time t0 = Seconds (10.0); - //std::cout << "t0="< tu0; - tu0 = s0; - TimeUnit<1> tu1; - tu1 = t0; - TimeUnit<2> tu2; - tu2 = t0 * t1; - TimeUnit<3> tu3; - tu3 = t0 * tu2; - TimeUnit<-2> tu4; - tu4 = t0 / tu3; + dt2 = t2.GetSeconds(); + CheckTimeSec("old 9", dt2, dt0-dt1, ok); + + t1 = NanoSeconds(15); + it0 = t0.GetNanoSeconds(); + it1 = t1.GetNanoSeconds(); + TimeUnit<-2> tu4 = t0 / (t1 * t1 * t1); + CheckTime("old 10", tu4.GetHighPrecision().GetInteger(), it0 / (it1*it1*it1), + ok, 1e9); Time tmp = MilliSeconds (0); if ((tmp != NanoSeconds (0)) || @@ -215,19 +398,273 @@ bool TimeTests::RunTests (void) Time t4; t4 = Seconds (10.0) * Scalar (1.5); - //std::cout << "10.0s * 1.5 = " << t4.GetSeconds () << "s" << std::endl; + CheckTimeSec("old 11", t4.GetSeconds(), 10, ok); + Time t5; t5 = NanoSeconds (10) * Scalar (1.5); - //std::cout << "10ns * 1.5 = " << t5.GetNanoSeconds () << "ns" << - //std::endl; + CheckTime("old 12", t5.GetNanoSeconds(), 10, ok); + + t4 = Seconds (10.0) * Scalar (15) / Scalar (10); + CheckTimeSec("old 13", t4.GetSeconds(), 15, ok); + + t5 = NanoSeconds (10) * Scalar (15) / Scalar (10); + CheckTime("old 14", t5.GetNanoSeconds(), 15, ok); + double foo = (t1 + t2).GetSeconds (); + dt1 = t1.GetSeconds(); + dt2 = t2.GetSeconds(); + CheckTimeSec("old 15", foo, dt1+dt2, ok); + foo += (t4 == t5)? 1 : 0; + CheckTimeSec("old 16", foo, dt1+dt2, ok); foo = (t1/t2).GetDouble (); - - return ok; -} + CheckTimeSec("old 17", foo, dt1/dt2, ok); +} + + +void TimeTests::CheckOperations(Time t0, Time t1, bool *ok, bool verbose) +{ + + if (verbose) + std::cout << std::endl << "Check operations: " + << t0 << " " << t1 << std::endl; + + Time t2, t3; + double it0, it1, it2, it3, itu2, itu3; + int64_t iti0; + + it0 = t0.GetSeconds(); + it1 = t1.GetSeconds(); + + t2 = t0 - t1; + it2 = t2.GetSeconds(); + CheckTimeSec("ops 1", it2, it0-it1, ok); + + t3 = t2 * t0 / t0; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 2a", it3, it2*it0/it0, ok); + + t3 = t2 * t0 / t1; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 2", it3, it2*it0/it1, ok); + + t3 = t0 * t2 / t1; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 3", it3, it0*it2/it1, ok); + + t3 = t0 * t1 / t2; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 4", it3, it0*it1/it2, ok); + + t3 = t0 * (t1 / t2); + it3 = t3.GetSeconds(); + CheckTimeSec("ops 5", it3, it0*(it1/it2), ok); + + t3 = (t0 * t1) / t2; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 6", it3, (it0*it1)/it2, ok); + + t3 = t0 / t1 * t2; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 7", it3, it0/it1*it2, ok); + + t3 = (t0 / t1) * t2; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 8", it3, (it0/it1)*it2, ok); + + t3 = t0 * Scalar (10.0); + it3 = t3.GetSeconds(); + CheckTimeSec("ops 9", it3, it0*10, ok); + + t3 = Scalar (10.0) * t0; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 10", it3, 10 * it0, ok); + + t3 = Scalar (10.0) * t0 / t2 * t1; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 11", it3, 10 * it0 / it2 * it1, ok); + + t3 = (Scalar (10.0) * t0 ) / t2 * t1; + it3 = t3.GetSeconds(); + CheckTimeSec("ops 12", it3, (10 * it0) / it2 * it1, ok); + + TimeInvert ti0; + ti0 = t0 / (t1 * t2); + iti0 = ti0.GetHighPrecision().GetInteger(); + // This check is not quite working yet. + // CheckTime("ops 13", iti0, (int64_t)(it0/(it1*it2)), ok); + + Scalar s0 = t0 / t1; + CheckTimeSec("ops 14", s0.GetDouble(), it0/it1, ok); + + Scalar s1; + s1 = t0 * t1 / (t2 * t0); + CheckTimeSec("ops 15", s1.GetDouble(), it0*it1/(it2*it0), ok); + + TimeUnit<0> tu0; + tu0 = s0; + CheckTimeSec("ops 16", tu0.GetDouble(), s0.GetDouble(), ok); + + TimeUnit<1> tu1; + tu1 = t0; + CheckTimeSec("ops 17", tu1.GetSeconds(), it0, ok); + + TimeUnit<2> tu2; + tu2 = t0 * t1; + CheckTimeSec("ops 18", tu2.GetHighPrecision().GetInteger()/(1e18), + it0 * it1, ok); + itu2 = tu2.GetHighPrecision().GetInteger()/(1e18); + + TimeUnit<3> tu3; + tu3 = t0 / Scalar(10e6) * tu2; + CheckTimeSec("ops 19", tu3.GetHighPrecision().GetInteger()/(1e27), + it0 / 1000000 * itu2, ok); + itu3 = tu3.GetHighPrecision().GetInteger()/(1e27); +} + +void TimeTests::CheckConversions(uint64_t tval, bool *ok, bool verbose) { + Time t_sec, t_ms, t_us, t_ns, t_ps, t_fs; + + if (verbose) + std::cout << std::endl << "Check conversions: " << tval << std::endl; + + // First check the seconds + t_sec = Seconds((double)tval); + CheckTimeSec("conv sec sec", t_sec.GetSeconds(), (double)tval, ok); + CheckTime("conv sec ms", t_sec.GetMilliSeconds(), (int64_t)(tval*1e3), ok, 1e3); + CheckTime("conv sec us", t_sec.GetMicroSeconds(), (int64_t)(tval*1e6), ok, 1e6); + CheckTime("conv sec ns", t_sec.GetNanoSeconds(), (int64_t)(tval*1e9), ok, 1e9); + CheckTime("conv sec ps", t_sec.GetPicoSeconds(), + (int64_t)(tval*1e12), ok, 1e12); + CheckTime("conv sec fs", t_sec.GetFemtoSeconds(), + (int64_t)(tval*1e15), ok, 1e15); + + // Then check the milliseconds + t_ms = MilliSeconds(tval); + CheckTimeSec("conv ms sec", t_ms.GetSeconds(), (double)tval/1e3, ok); + CheckTime("conv ms ms", t_ms.GetMilliSeconds(), (int64_t)(tval), ok, 1e3); + CheckTime("conv ms us", t_ms.GetMicroSeconds(), (int64_t)(tval*1e3), ok, 1e6); + CheckTime("conv ms ns", t_ms.GetNanoSeconds(), (int64_t)(tval*1e6), ok, 1e9); + CheckTime("conv ms ps", t_ms.GetPicoSeconds(), (int64_t)(tval*1e9), ok, 1e12); + CheckTime("conv ms fs", t_ms.GetFemtoSeconds(), (int64_t)(tval*1e12), ok, 1e15); + + // Then check the microseconds + t_us = MicroSeconds(tval); + CheckTimeSec("conv us sec", t_us.GetSeconds(), (double)tval/1e6, ok); + CheckTime("conv us ms", t_us.GetMilliSeconds(), (int64_t)(tval/1e3), ok, 1e3); + CheckTime("conv us us", t_us.GetMicroSeconds(), (int64_t)(tval), ok, 1e6); + CheckTime("conv us ns", t_us.GetNanoSeconds(), (int64_t)(tval*1e3), ok, 1e9); + CheckTime("conv us ps", t_us.GetPicoSeconds(), (int64_t)(tval*1e6), ok, 1e12); + CheckTime("conv us fs", t_us.GetFemtoSeconds(), (int64_t)(tval*1e9), ok, 1e15); + + // Then check the nanoseconds + t_ns = NanoSeconds(tval); + CheckTimeSec("conv ns sec", t_ns.GetSeconds(), (double)tval/1e9, ok); + CheckTime("conv ns ms", t_ns.GetMilliSeconds(), (int64_t)(tval/1e6), ok, 1e3); + CheckTime("conv ns us", t_ns.GetMicroSeconds(), (int64_t)(tval/1e3), ok, 1e6); + CheckTime("conv ns ns", t_ns.GetNanoSeconds(), (int64_t)(tval), ok, 1e9); + CheckTime("conv ns ps", t_ns.GetPicoSeconds(), (int64_t)(tval*1e3), ok, 1e12); + CheckTime("conv ns fs", t_ns.GetFemtoSeconds(), (int64_t)(tval*1e6), ok, 1e15); + + // Then check the picoseconds + t_ps = PicoSeconds(tval); + CheckTimeSec("conv ps sec", t_ps.GetSeconds(), (double)tval/1e12, ok); + CheckTime("conv ps ms", t_ps.GetMilliSeconds(), (int64_t)(tval/1e9), ok, 1e3); + CheckTime("conv ps us", t_ps.GetMicroSeconds(), (int64_t)(tval/1e6), ok, 1e6); + CheckTime("conv ps ns", t_ps.GetNanoSeconds(), (int64_t)(tval/1e3), ok, 1e9); + CheckTime("conv ps ps", t_ps.GetPicoSeconds(), (int64_t)(tval), ok, 1e12); + CheckTime("conv ps fs", t_ps.GetFemtoSeconds(), (int64_t)(tval*1e3), ok, 1e15); + + // Then check the femtoseconds + t_fs = FemtoSeconds(tval); + CheckTimeSec("conv fs sec", t_fs.GetSeconds(), (double)tval/1e15, ok); + CheckTime("conv fs ms", t_fs.GetMilliSeconds(), (int64_t)(tval/1e12), ok, 1e3); + CheckTime("conv fs us", t_fs.GetMicroSeconds(), (int64_t)(tval/1e9), ok, 1e6); + CheckTime("conv fs ns", t_fs.GetNanoSeconds(), (int64_t)(tval/1e6), ok, 1e9); + CheckTime("conv fs ps", t_fs.GetPicoSeconds(), (int64_t)(tval/1e3), ok, 1e12); + CheckTime("conv fs fs", t_fs.GetFemtoSeconds(), (int64_t)(tval), ok, 1e15); + + +} + +void TimeTests::CheckPrecision(PrecisionType prec, uint64_t val, bool *ok, + bool verbose) { + if (verbose) { + std::cout << "check precision 10^-" << prec << std::endl; + } + + SetTsPrecision(prec); + if (GetTsPrecision() != prec) { + ok = false; + } + + /* These still need to be fixed. + // The smallest value that can be stored is 1x10^(-prec) + Time smallest = Seconds(pow(10,-prec)); + CheckTimeSec("Prec small: ", smallest.GetSeconds(), pow(10,-prec), ok, 0.1, + true); + + double d_ts = pow(10,-prec) - pow(10, -(prec+3)); + Time too_small = Seconds(d_ts); + CheckTimeSec("Prec too small: ", too_small.GetSeconds(), 0, ok, 0.1, true); + + double d_la = 0xFFFFFFFF*pow(10,-prec); + Time largest = Seconds(d_la); + CheckTimeSec("Prec large: ", largest.GetSeconds(), d_la, ok, 0.1, true); + + double d_tl = (0xFFFFFFFF*pow(10,-prec)) + 1; + Time too_large = Seconds(d_tl); + if ((largest.GetSeconds() + 1) == too_large.GetSeconds()) + std::cout << "Overflow did not occur." << std::endl; + + NS_ASSERT(d_la+1 == d_tl); + */ +} + +void TimeTests::CheckTimeSec (std::string test_id, double actual, + double expected, bool *flag, double precMultFactor, + bool verbose) +{ + double prec = pow(10,-ns3::m_tsPrecision) * precMultFactor; + if ((actual < (expected-prec)) || (actual > (expected+prec))) { + std::cout << "FAIL " << test_id + << " Expected:" << expected + << " Actual: " << actual + << " Precision: " << prec << std::endl; + *flag = false; + } else { + if (verbose) { + std::cout << "PASS " << test_id + << " Expected:" << expected + << " Actual: " << actual + << " Precision: " << prec << std::endl; + } + } +} + +void TimeTests::CheckTime (std::string test_id, int64_t actual, + int64_t expected, bool *flag, double precMultFactor, + bool verbose) +{ + double prec = pow(10,-ns3::m_tsPrecision) * precMultFactor; + if ((actual < (expected-prec)) || (actual > (expected+prec))) { + std::cout << "FAIL " << test_id + << " Expected:" << expected + << " Actual: " << actual + << " Precision: " << prec << std::endl; + *flag = false; + } else { + if (verbose) { + std::cout << "PASS " << test_id + << " Expected:" << expected + << " Actual: " << actual + << " Precision: " << prec << std::endl; + } + } +} + static TimeTests g_time_tests;