implement 128 bit arithmetic with cairo's internal types
This commit is contained in:
10
SConstruct
10
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 = []
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
Reference in New Issue
Block a user