implement 128 bit arithmetic with cairo's internal types
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Mon, 04 Dec 2006 10:33:02 +0100
changeset 170 9f68cb694f40
parent 169 bc06726969af
child 171 64cafe7b7baf
implement 128 bit arithmetic with cairo's internal types
SConstruct
src/simulator/high-precision-128.cc
src/simulator/high-precision-128.h
src/simulator/high-precision-double.cc
src/simulator/high-precision-double.h
src/simulator/high-precision.cc
src/simulator/nstime.h
src/simulator/time.cc
--- a/SConstruct	Mon Dec 04 10:17:53 2006 +0100
+++ b/SConstruct	Mon Dec 04 10:33:02 2006 +0100
@@ -49,7 +49,6 @@
 simu.add_dep('core')
 simu.add_sources([
     'high-precision.cc',
-    'cairo-wideint.c',
     'time.cc',
     'event-id.cc',
     'scheduler.cc',
@@ -61,7 +60,6 @@
     'simulator.cc',
     ])
 simu.add_headers([
-    'cairo-wideint-private.h',
     'scheduler-heap.h',
     'scheduler-map.h',
     'scheduler-list.h'
@@ -76,12 +74,16 @@
     '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 = []
--- a/src/simulator/high-precision-128.cc	Mon Dec 04 10:17:53 2006 +0100
+++ b/src/simulator/high-precision-128.cc	Mon Dec 04 10:33:02 2006 +0100
@@ -19,64 +19,93 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "high-precision-128.h"
+#include <math.h>
 
 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)
--- a/src/simulator/high-precision-128.h	Mon Dec 04 10:17:53 2006 +0100
+++ b/src/simulator/high-precision-128.h	Mon Dec 04 10:33:02 2006 +0100
@@ -22,6 +22,7 @@
 #define HIGH_PRECISION_128_H
 
 #include <stdint.h>
+#include "cairo-wideint-private.h"
 
 namespace ns3 {
 
@@ -34,11 +35,10 @@
 {
 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 @@
   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
--- a/src/simulator/high-precision-double.cc	Mon Dec 04 10:17:53 2006 +0100
+++ b/src/simulator/high-precision-double.cc	Mon Dec 04 10:33:02 2006 +0100
@@ -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 @@
 {}
 
 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
--- a/src/simulator/high-precision-double.h	Mon Dec 04 10:17:53 2006 +0100
+++ b/src/simulator/high-precision-double.h	Mon Dec 04 10:33:02 2006 +0100
@@ -36,11 +36,10 @@
 {
 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);
--- a/src/simulator/high-precision.cc	Mon Dec 04 10:17:53 2006 +0100
+++ b/src/simulator/high-precision.cc	Mon Dec 04 10:33:02 2006 +0100
@@ -30,7 +30,9 @@
 {
   if (value.Compare (HighPrecision::Zero ()) <= 0)
     {
-      return HighPrecision::Zero ().Sub (value);
+      HighPrecision v = HighPrecision::Zero ();
+      v.Sub (value);
+      return v;
     }
   else
     {
--- a/src/simulator/nstime.h	Mon Dec 04 10:17:53 2006 +0100
+++ b/src/simulator/nstime.h	Mon Dec 04 10:33:02 2006 +0100
@@ -82,12 +82,6 @@
   TimeUnit (HighPrecision data);
 
   /**
-   * \return the ns3::HighPrecision object which holds the value 
-   *         stored in this Time<N> type.
-   */
-  HighPrecision GetHighPrecision (void) const;
-
-  /**
    * \return true if the time is zero, false otherwise.
    */
   bool IsZero (void) const;
@@ -108,6 +102,15 @@
    */
   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<N> type.
+   */
+  HighPrecision GetHighPrecision (void) const;
+
 private:
   HighPrecision m_data;
 };
--- a/src/simulator/time.cc	Mon Dec 04 10:17:53 2006 +0100
+++ b/src/simulator/time.cc	Mon Dec 04 10:33:02 2006 +0100
@@ -34,27 +34,27 @@
 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 @@
   : 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 ()