implement 128 bit arithmetic with cairo's internal types

This commit is contained in:
Mathieu Lacage
2006-12-04 10:33:02 +01:00
parent 54003d6fd0
commit 16e62faea8
8 changed files with 86 additions and 58 deletions

View File

@@ -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 = []

View File

@@ -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)

View File

@@ -22,6 +22,7 @@
#define HIGH_PRECISION_128_H
#include <stdint.h>
#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

View File

@@ -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

View File

@@ -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);

View File

@@ -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
{

View File

@@ -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<N> 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<N> type.
*/
HighPrecision GetHighPrecision (void) const;
private:
HighPrecision m_data;
};

View File

@@ -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 ()