The header file ns3/cairo-wideint-private.h was added since the type int32_t was used.
authorEmmanuelle Laprise
Thu, 17 May 2007 12:12:44 -0500
changeset 675 a5878de7d71c
parent 674 8e8d5e913b6a
child 676 0cf407300fa6
The header file ns3/cairo-wideint-private.h was added since the type int32_t was used.
src/core/random-variable.h
src/core/rng-stream.h
src/simulator/event-id.cc
src/simulator/event-id.h
src/simulator/nstime.h
src/simulator/scheduler-heap.cc
src/simulator/scheduler-list.cc
src/simulator/scheduler-map.cc
src/simulator/scheduler.h
src/simulator/simulator.cc
src/simulator/time.cc
--- a/src/core/random-variable.h	Thu May 24 08:34:41 2007 +0200
+++ b/src/core/random-variable.h	Thu May 17 12:12:44 2007 -0500
@@ -23,7 +23,7 @@
 
 #include <vector>
 #include <algorithm>
-
+#include "ns3/cairo-wideint-private.h"
 
 /**
  * \defgroup randomvariable Random Variable Distributions
--- a/src/core/rng-stream.h	Thu May 24 08:34:41 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 <string>
+#include "ns3/cairo-wideint-private.h"
 
 namespace ns3{
 
--- a/src/simulator/event-id.cc	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/event-id.cc	Thu May 17 12:12:44 2007 -0500
@@ -26,13 +26,13 @@
 
 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 @@
   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
--- a/src/simulator/event-id.h	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/event-id.h	Thu May 17 12:12:44 2007 -0500
@@ -33,7 +33,7 @@
 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 @@
    * 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;
 };
 
--- a/src/simulator/nstime.h	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/nstime.h	Thu May 17 12:12:44 2007 -0500
@@ -22,9 +22,11 @@
 #define TIME_H
 
 #include <stdint.h>
+#include <math.h>
 #include "ns3/assert.h"
 #include <ostream>
 #include "high-precision.h"
+#include "cairo-wideint-private.h"
 
 namespace ns3 {
 
@@ -73,6 +75,34 @@
  *  - \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 <int N>
 class TimeUnit
 {
@@ -235,6 +265,9 @@
 {
   HighPrecision retval = lhs.GetHighPrecision ();
   retval.Mul (rhs.GetHighPrecision ());
+  //    std::cout << lhs.GetHighPrecision().GetInteger() << " * " 
+  //              << rhs.GetHighPrecision().GetInteger() 
+  //              << " = " << retval.GetInteger() << std::endl;
   return TimeUnit<N1+N2> (retval);
 }
 template <int N1, int N2>
@@ -316,6 +349,8 @@
    * - 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 @@
    * \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 @@
    *          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 @@
   HighPrecision *PeekHighPrecision (void) {
     return &m_data;
   }
+
 private:
   HighPrecision m_data;
 };
@@ -394,6 +445,8 @@
  *  - 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 @@
  *          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 @@
  * 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 @@
  * \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 @@
   HighPrecision *PeekHighPrecision (void) {
     return &m_data;
   }
+
 private:
   HighPrecision m_data;
 };
--- a/src/simulator/scheduler-heap.cc	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/scheduler-heap.cc	Thu May 17 12:12:44 2007 -0500
@@ -139,11 +139,11 @@
 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;
     } 
@@ -227,7 +227,7 @@
 {
   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 *
@@ -252,7 +252,7 @@
 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++)
     {
--- a/src/simulator/scheduler-list.cc	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/scheduler-list.cc	Thu May 17 12:12:44 2007 -0500
@@ -51,11 +51,11 @@
 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;
@@ -74,11 +74,11 @@
       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
@@ -111,7 +111,7 @@
         {
           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;
--- a/src/simulator/scheduler-map.cc	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/scheduler-map.cc	Thu May 17 12:12:44 2007 -0500
@@ -67,11 +67,11 @@
 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;
     } 
@@ -93,7 +93,7 @@
   std::pair<EventMapI,bool> 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
@@ -125,7 +125,7 @@
 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;
--- a/src/simulator/scheduler.h	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/scheduler.h	Thu May 17 12:12:44 2007 -0500
@@ -55,7 +55,7 @@
 class Scheduler {
  public:
   struct EventKey {
-      uint64_t m_ns;
+      uint64_t m_ts;
       uint32_t m_uid;
   };
 
--- a/src/simulator/simulator.cc	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/simulator.cc	Thu May 17 12:12:44 2007 -0500
@@ -72,7 +72,7 @@
 
 private:
   void ProcessOneEvent (void);
-  uint64_t NextNs (void) const;
+  uint64_t NextTs (void) const;
 
   typedef std::list<std::pair<EventImpl *,uint32_t> > Events;
   Events m_destroy;
@@ -81,7 +81,7 @@
   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 @@
   // 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 @@
   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 "<<nextKey.m_uid << " " << nextKey.m_ns << std::endl;
+      m_log << "e "<<nextKey.m_uid << " " << nextKey.m_ts << std::endl;
     }
   nextEv->Invoke ();
   delete nextEv;
@@ -156,25 +156,24 @@
   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)
 {
   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 "<<m_currentUid<<" "<<m_currentNs<<" "
-            <<m_uid<<" "<<time.GetNanoSeconds () << std::endl;
+      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
+            <<m_uid<<" "<<time.GetTimeStep () << std::endl;
     }
   m_uid++;
   ++m_unscheduledEvents;
@@ -217,12 +216,12 @@
 void 
 SimulatorPrivate::ScheduleNow (EventImpl *event)
 {
-  uint64_t ns = m_currentNs;
-  Scheduler::EventKey key = {ns, m_uid};
+  uint64_t ts = m_currentTs;
+  Scheduler::EventKey key = {ts, m_uid};
   if (m_logEnable) 
     {
-      m_log << "i "<<m_currentUid<<" "<<m_currentNs<<" "
-            <<m_uid<<" "<<ns << std::endl;
+      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
+            <<m_uid<<" "<<ts << std::endl;
     }
   m_uid++;
   ++m_unscheduledEvents;
@@ -234,7 +233,7 @@
   m_destroy.push_back (std::make_pair (event, m_uid));  
   if (m_logEnable) 
   {
-    m_log << "id " << m_currentUid << " " << Now ().GetNanoSeconds () << " "
+    m_log << "id " << m_currentUid << " " << Now ().GetTimeStep () << " "
           << m_uid << std::endl;
   }
   m_uid++;
@@ -243,7 +242,7 @@
 Time
 SimulatorPrivate::Now (void) const
 {
-  return NanoSeconds (m_currentNs);
+  return TimeStep (m_currentTs);
 }
 
 void
@@ -254,8 +253,8 @@
   delete impl;
   if (m_logEnable) 
     {
-      m_log << "r " << m_currentUid << " " << m_currentNs << " "
-            << key.m_uid << " " << key.m_ns << std::endl;
+      m_log << "r " << m_currentUid << " " << m_currentTs << " "
+            << key.m_uid << " " << key.m_ts << std::endl;
     }
   --m_unscheduledEvents;
 }
@@ -270,8 +269,8 @@
 SimulatorPrivate::IsExpired (EventId ev)
 {
   if (ev.GetEventImpl () == 0 ||
-      ev.GetNs () < m_currentNs ||
-      (ev.GetNs () == m_currentNs &&
+      ev.GetTs () < m_currentTs ||
+      (ev.GetTs () == m_currentTs &&
        ev.GetUid () <= m_currentUid) ||
       ev.GetEventImpl ()->IsCancelled ()) 
     {
--- a/src/simulator/time.cc	Thu May 24 08:34:41 2007 +0200
+++ b/src/simulator/time.cc	Thu May 17 12:12:44 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 @@
     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 "<<s);
   }
   //else
   //they didn't provide units, assume seconds
-  m_data = HighPrecision (atof(s.c_str()) * 1000000000.0);
+  m_data = HighPrecision (atof(s.c_str()) * m_tsPrecisionFactor);
 }
+
 double 
 TimeUnit<1>::GetSeconds (void) const
 {
-  double ns = GetHighPrecision ().GetDouble ();
-  return ns/1000000000.0;
+  double time_value = GetHighPrecision ().GetDouble ();
+  return time_value/m_tsPrecisionFactor;
 }
-int32_t 
+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));
+  double d_sec = seconds * m_tsPrecisionFactor;
+  return Time (HighPrecision (d_sec));
+  //  return Time (HighPrecision ((int64_t)d_sec, false));
 }
-Time MilliSeconds (uint32_t ms)
+
+Time MilliSeconds (uint64_t ms)
 {
-  return Time (HighPrecision (ms * 1000000, false));
+  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 @@
   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 ()
 {}
+
 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="<<t0.GetSeconds ()<<" (expected 10.0)"<<std::endl;
+  CheckTimeSec("old 1", t0.GetSeconds(), 10.0, ok);
+
   Time t1 = Seconds (11.0);
-  //std::cout << "t1="<<t1.GetSeconds ()<<" (expected 11.0)"<<std::endl;
+  CheckTimeSec("old 2", t1.GetSeconds(), 11.0, ok);
+
   t0 = Seconds (1.5);
-  //std::cout << "t0="<<t0.GetSeconds ()<<" (expected +1.5)"<<std::endl;
+  CheckTimeSec("old 3", t0.GetSeconds(), 1.5, ok);
+
   t0 = Seconds (-1.5);
-  //std::cout << "t0="<<t0.GetSeconds ()<<" (expected -1.5)"<<std::endl;
+  CheckTimeSec("old 4", t0.GetSeconds(), -1.5, ok);
 
-  t0 = Seconds (10.0);
-  t1 = Seconds (11.0);
+  t0 = MilliSeconds ((uint64_t)10.0);
+  dt0 = t0.GetSeconds();
+  CheckTimeSec("old 5", dt0, 0.01, ok);
+
+  t1 = MilliSeconds ((uint64_t)11.0);
+  dt1 = t1.GetSeconds();
+  CheckTimeSec("old 6", dt1, 0.011, ok);
 
   Time t2, t3;
 
@@ -166,44 +362,31 @@
     {
       ok = false;
     }
+  dt2 = t2.GetSeconds();
+  CheckTimeSec("old 7", dt2, dt1-dt0, ok);
+
   t2 = t1 - t1;
   if (!t2.IsZero ())
     {
       ok = false;
     }
+  dt2 = t2.GetSeconds();
+  CheckTimeSec("old 8", dt2, dt1-dt1, ok);
+
   t2 = t0 - t1;
   if (!t2.IsStrictlyNegative ())
     {
       ok = false;
     }
+  dt2 = t2.GetSeconds();
+  CheckTimeSec("old 9", dt2, dt0-dt1, ok);
 
-  t2 = t0 - t1;
-  t3 = t2 * t0 / t1;
-  t3 = t0 * t2 / t1;
-  t3 = t0 * t1 / t2;
-  t3 = t0 * (t1 / t2);
-  t3 = (t0 * t1) / t2;
-  t3 = t0 / t1 * t2;
-  t3 = (t0 / t1) * t2;
-  TimeInvert ti0;
-  ti0 = t0 / (t1 * t2);
-  t3 = t0 * Scalar (10.0);
-  t3 = Scalar (10.0) * t0;
-  t3 = Scalar (10.0) * t0 / t2 * t1;
-  t3 = (Scalar (10.0) * t0 ) / t2 * t1;
-  Scalar s0 = t0 / t1;
-  Scalar s1;
-  s1 = t0 * t1 / (t2 * t0);
-  TimeUnit<0> 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;
+  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,20 +398,274 @@
 
   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 ();
+  CheckTimeSec("old 17", foo, dt1/dt2, ok);
+}
 
-  return 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;
   
 };