diff --git a/SConstruct b/SConstruct index 199f845be..0451abe38 100644 --- a/SConstruct +++ b/SConstruct @@ -49,7 +49,6 @@ ns3.add(simu) simu.add_dep('core') simu.add_sources([ 'high-precision.cc', - 'cairo-wideint.c', 'time.cc', 'event-id.cc', 'scheduler.cc', @@ -61,7 +60,6 @@ simu.add_sources([ 'simulator.cc', ]) simu.add_headers([ - 'cairo-wideint-private.h', 'scheduler-heap.h', 'scheduler-map.h', 'scheduler-list.h' @@ -76,12 +74,16 @@ simu.add_inst_headers([ 'scheduler-factory.h', ]) high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n') -if high_precision_as_double == 1: +if high_precision_as_double == 'y': simu.add_inst_header ('high-precision-double.h') simu.add_source ('high-precision-double.cc') else: simu.add_inst_header ('high-precision-128.h') - simu.add_source ('high-precision-128.cc') + simu.add_header ('cairo-wideint-private.h') + simu.add_sources ([ + 'high-precision-128.cc', + 'cairo-wideint.c', + ]) def config_simulator (env, config): retval = [] diff --git a/src/simulator/high-precision-128.cc b/src/simulator/high-precision-128.cc index f50ade548..1546fa052 100644 --- a/src/simulator/high-precision-128.cc +++ b/src/simulator/high-precision-128.cc @@ -19,64 +19,93 @@ * Author: Mathieu Lacage */ #include "high-precision-128.h" +#include namespace ns3 { -HighPrecision::HighPrecision () - : m_high (0), - m_low (0) -{} +const double HighPrecision::MAX_64 = 18446744073709551615.0; -HighPrecision::HighPrecision (int64_t high, int64_t low) - : m_high (high), - m_low (low) -{} +HighPrecision::HighPrecision () +{ + m_value = _cairo_int32_to_int128 (0); + m_value = _cairo_int128_lsl (m_value, 64); +} + +HighPrecision::HighPrecision (int64_t value, bool dummy) +{ + m_value = _cairo_int64_to_int128 (value); + m_value = _cairo_int128_lsl (m_value, 64); +} HighPrecision::HighPrecision (double value) - : m_high (0), // XXX - m_low (0) // XXX -{} +{ + int64_t hi = (int64_t) floor (value); + uint64_t lo = (uint64_t) ((value - floor (value)) * MAX_64); + m_value = _cairo_int64_to_int128 (hi); + m_value = _cairo_int128_lsl (m_value, 64); + cairo_int128_t clo = _cairo_uint128_to_int128 (_cairo_uint64_to_uint128 (lo)); + m_value = _cairo_int128_add (m_value, clo); +} int64_t -HighPrecision::GetHigh (void) const +HighPrecision::GetInteger (void) const { - return m_high; -} -int64_t -HighPrecision::GetLow (void) const -{ - return m_low; + cairo_int128_t value = _cairo_int128_rsa (m_value, 64); + return _cairo_int128_to_int64 (value); } double HighPrecision::GetDouble (void) const { - return 0.0; + cairo_int128_t value = _cairo_int128_rsa (m_value, 64); + cairo_int128_t rem = _cairo_int128_sub (m_value, value); + double frem = _cairo_int128_to_int64 (rem); + frem /= MAX_64; + double retval = _cairo_int128_to_int64 (value); + retval += frem; + return retval; } bool HighPrecision::Add (HighPrecision const &o) { + m_value = _cairo_int128_add (m_value, o.m_value); return false; } bool HighPrecision::Sub (HighPrecision const &o) { + m_value = _cairo_int128_sub (m_value, o.m_value); return false; } bool HighPrecision::Mul (HighPrecision const &o) { + m_value = _cairo_int128_mul (m_value, o.m_value); return false; } bool HighPrecision::Div (HighPrecision const &o) { + cairo_quorem128_t qr; + qr = _cairo_int128_divrem (m_value, o.m_value); + m_value = qr.quo; return false; } int HighPrecision::Compare (HighPrecision const &o) const { - return 0; + if (_cairo_int128_lt (m_value, o.m_value)) + { + return -1; + } + else if (_cairo_int128_eq (m_value, o.m_value)) + { + return 0; + } + else + { + return 1; + } } HighPrecision HighPrecision::Zero (void) diff --git a/src/simulator/high-precision-128.h b/src/simulator/high-precision-128.h index 5cf75a081..755cd7802 100644 --- a/src/simulator/high-precision-128.h +++ b/src/simulator/high-precision-128.h @@ -22,6 +22,7 @@ #define HIGH_PRECISION_128_H #include +#include "cairo-wideint-private.h" namespace ns3 { @@ -34,11 +35,10 @@ class HighPrecision { public: HighPrecision (); - HighPrecision (int64_t high, int64_t low); + HighPrecision (int64_t value, bool dummy); HighPrecision (double value); - int64_t GetHigh (void) const; - int64_t GetLow (void) const; + int64_t GetInteger (void) const; double GetDouble (void) const; bool Add (HighPrecision const &o); bool Sub (HighPrecision const &o); @@ -48,8 +48,8 @@ public: int Compare (HighPrecision const &o) const; static HighPrecision Zero (void); private: - int64_t m_high; - int64_t m_low; + static const double MAX_64; + cairo_int128_t m_value; }; }; // namespace ns3 diff --git a/src/simulator/high-precision-double.cc b/src/simulator/high-precision-double.cc index 44b8ae202..86e2d62cd 100644 --- a/src/simulator/high-precision-double.cc +++ b/src/simulator/high-precision-double.cc @@ -26,14 +26,12 @@ namespace ns3 { -const double HighPrecision::MAX_64 = 18446744073709551615.0; - HighPrecision::HighPrecision () : m_value (0.0) {} -HighPrecision::HighPrecision (int64_t high, int64_t low) - : m_value (((double)high) + (((double)low)/MAX_64)) +HighPrecision::HighPrecision (int64_t value, bool dummy) + : m_value ((double)value) {} HighPrecision::HighPrecision (double value) @@ -41,15 +39,10 @@ HighPrecision::HighPrecision (double value) {} int64_t -HighPrecision::GetHigh (void) const +HighPrecision::GetInteger (void) const { return (int64_t)floor (m_value); } -int64_t -HighPrecision::GetLow (void) const -{ - return (int64_t)((m_value - floor (m_value)) * MAX_64); -} double HighPrecision::GetDouble (void) const diff --git a/src/simulator/high-precision-double.h b/src/simulator/high-precision-double.h index 5e96b2fb3..16f3d05d0 100644 --- a/src/simulator/high-precision-double.h +++ b/src/simulator/high-precision-double.h @@ -36,11 +36,10 @@ class HighPrecision { public: HighPrecision (); - HighPrecision (int64_t high, int64_t low); + HighPrecision (int64_t value, bool dummy); HighPrecision (double value); - int64_t GetHigh (void) const; - int64_t GetLow (void) const; + int64_t GetInteger (void) const; double GetDouble (void) const; bool Add (HighPrecision const &o); bool Sub (HighPrecision const &o); diff --git a/src/simulator/high-precision.cc b/src/simulator/high-precision.cc index f8ab9c83e..27ecf2a10 100644 --- a/src/simulator/high-precision.cc +++ b/src/simulator/high-precision.cc @@ -30,7 +30,9 @@ HighPrecision Abs (HighPrecision const &value) { if (value.Compare (HighPrecision::Zero ()) <= 0) { - return HighPrecision::Zero ().Sub (value); + HighPrecision v = HighPrecision::Zero (); + v.Sub (value); + return v; } else { diff --git a/src/simulator/nstime.h b/src/simulator/nstime.h index 7691695cf..d5a6380c5 100644 --- a/src/simulator/nstime.h +++ b/src/simulator/nstime.h @@ -81,12 +81,6 @@ public: TimeUnit operator = (TimeUnit const &o); TimeUnit (HighPrecision data); - /** - * \return the ns3::HighPrecision object which holds the value - * stored in this Time type. - */ - HighPrecision GetHighPrecision (void) const; - /** * \return true if the time is zero, false otherwise. */ @@ -108,6 +102,15 @@ public: */ bool IsStrictlyPositive (void) const; + /** + * This is really an internal method exported for the needs of + * the implementation. Please, Do not try to use this method, ever. + * + * \return the ns3::HighPrecision object which holds the value + * stored in this Time type. + */ + HighPrecision GetHighPrecision (void) const; + private: HighPrecision m_data; }; diff --git a/src/simulator/time.cc b/src/simulator/time.cc index e91e38838..77edf3bfc 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -34,27 +34,27 @@ double Time::GetSeconds (void) const { HighPrecision seconds = GetHighPrecision (); - seconds.Div (HighPrecision (1000000000, 0)); + seconds.Div (HighPrecision (1000000000, false)); return seconds.GetDouble (); } int32_t Time::GetMilliSeconds (void) const { HighPrecision ms = GetHighPrecision (); - ms.Div (HighPrecision (1000000, 0)); - return (int32_t) ms.GetHigh (); + ms.Div (HighPrecision (1000000, false)); + return (int32_t) ms.GetInteger (); } int64_t Time::GetMicroSeconds (void) const { HighPrecision us = GetHighPrecision (); - us.Div (HighPrecision (1000, 0)); - return us.GetHigh (); + us.Div (HighPrecision (1000, false)); + return us.GetInteger (); } int64_t Time::GetNanoSeconds (void) const { - return GetHighPrecision ().GetHigh (); + return GetHighPrecision ().GetInteger (); } @@ -68,19 +68,19 @@ MilliSeconds::MilliSeconds () : TimeUnit<1> () {} MilliSeconds::MilliSeconds (uint32_t ms) - : TimeUnit<1> (HighPrecision (ms * 1000000, 0)) + : TimeUnit<1> (HighPrecision (ms * 1000000, false)) {} MicroSeconds::MicroSeconds () : TimeUnit<1> () {} MicroSeconds::MicroSeconds (uint32_t us) - : TimeUnit<1> (HighPrecision (us * 1000, 0)) + : TimeUnit<1> (HighPrecision (us * 1000, false)) {} NanoSeconds::NanoSeconds () : TimeUnit<1> () {} NanoSeconds::NanoSeconds (uint32_t ns) - : TimeUnit<1> (HighPrecision (ns, 0)) + : TimeUnit<1> (HighPrecision (ns, false)) {} Now::Now ()