optimize Time arithmetic operations.
This commit is contained in:
@@ -20,48 +20,101 @@
|
||||
*/
|
||||
#include "high-precision-128.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
int HighPrecision::m_nfastadds = 0;
|
||||
int HighPrecision::m_nfastsubs = 0;
|
||||
int HighPrecision::m_nfastmuls = 0;
|
||||
int HighPrecision::m_nfastcmps = 0;
|
||||
int HighPrecision::m_nfastgets = 0;
|
||||
int HighPrecision::m_nslowadds = 0;
|
||||
int HighPrecision::m_nslowsubs = 0;
|
||||
int HighPrecision::m_nslowmuls = 0;
|
||||
int HighPrecision::m_nslowcmps = 0;
|
||||
int HighPrecision::m_nslowgets = 0;
|
||||
int HighPrecision::m_ndivs = 0;
|
||||
int HighPrecision::m_nconversions = 0;
|
||||
|
||||
void
|
||||
HighPrecision::PrintStats (void)
|
||||
{
|
||||
double nadds = m_nfastadds + m_nslowadds;
|
||||
double nsubs = m_nfastsubs + m_nslowsubs;
|
||||
double ncmps = m_nfastcmps + m_nslowcmps;
|
||||
double nmuls = m_nfastmuls + m_nslowmuls;
|
||||
double ngets = m_nfastgets + m_nslowgets;
|
||||
double fast_add_ratio = m_nfastadds / nadds;
|
||||
double fast_sub_ratio = m_nfastsubs / nsubs;
|
||||
double fast_cmp_ratio = m_nfastcmps / ncmps;
|
||||
double fast_mul_ratio = m_nfastmuls / nmuls;
|
||||
double fast_get_ratio = m_nfastgets / ngets;
|
||||
|
||||
std::cout <<
|
||||
"add="<<fast_add_ratio<<std::endl<<
|
||||
"sub="<<fast_sub_ratio<<std::endl<<
|
||||
"cmp="<<fast_cmp_ratio<<std::endl<<
|
||||
"mul="<<fast_mul_ratio<<std::endl<<
|
||||
"get="<<fast_get_ratio<<std::endl<<
|
||||
"nadds="<<nadds<<std::endl<<
|
||||
"nsubs="<<nsubs<<std::endl<<
|
||||
"ncmps="<<ncmps<<std::endl<<
|
||||
"nmuls="<<nmuls<<std::endl<<
|
||||
"ngets="<<ngets<<std::endl<<
|
||||
"ndivs="<<m_ndivs<<std::endl<<
|
||||
"nconversions="<<m_nconversions<<std::endl
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
const double HighPrecision::MAX_64 = 18446744073709551615.0;
|
||||
|
||||
HighPrecision::HighPrecision ()
|
||||
{
|
||||
m_value = _cairo_int32_to_int128 (0);
|
||||
// the following statement is not really needed but it
|
||||
// is here for the sake of symetry. I doubt we will
|
||||
// ever see this code in the profiles...
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (lo == 0)
|
||||
{
|
||||
m_isFast = true;
|
||||
m_fastValue = hi;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_isFast = false;
|
||||
m_slowValue = _cairo_int64_to_int128 (hi);
|
||||
m_slowValue = _cairo_int128_lsl (m_slowValue, 64);
|
||||
cairo_int128_t clo = _cairo_uint128_to_int128 (_cairo_uint64_to_uint128 (lo));
|
||||
m_slowValue = _cairo_int128_add (m_slowValue, clo);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HighPrecision::EnsureSlow (void)
|
||||
{
|
||||
if (m_isFast)
|
||||
{
|
||||
HP128INC (m_nconversions++);
|
||||
m_slowValue = _cairo_int64_to_int128 (m_fastValue);
|
||||
m_slowValue = _cairo_int128_lsl (m_slowValue, 64);
|
||||
m_isFast = false;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
HighPrecision::GetInteger (void) const
|
||||
HighPrecision::SlowGetInteger (void) const
|
||||
{
|
||||
cairo_int128_t value = _cairo_int128_rsa (m_value, 64);
|
||||
cairo_int128_t value = _cairo_int128_rsa (m_slowValue, 64);
|
||||
return _cairo_int128_to_int64 (value);
|
||||
}
|
||||
|
||||
double
|
||||
HighPrecision::GetDouble (void) const
|
||||
HighPrecision::SlowGetDouble (void) const
|
||||
{
|
||||
bool is_negative = _cairo_int128_negative (m_value);
|
||||
cairo_int128_t value = is_negative?_cairo_int128_negate (m_value):m_value;
|
||||
bool is_negative = _cairo_int128_negative (m_slowValue);
|
||||
cairo_int128_t value = is_negative?_cairo_int128_negate (m_slowValue):m_slowValue;
|
||||
cairo_int128_t hi = _cairo_int128_rsa (value, 64);
|
||||
cairo_uint128_t lo = _cairo_int128_sub (value, _cairo_uint128_lsl (hi, 64));
|
||||
double flo = _cairo_uint128_to_uint64 (lo);
|
||||
@@ -72,50 +125,52 @@ HighPrecision::GetDouble (void) const
|
||||
return retval;
|
||||
}
|
||||
bool
|
||||
HighPrecision::Add (HighPrecision const &o)
|
||||
HighPrecision::SlowAdd (HighPrecision const &o)
|
||||
{
|
||||
m_value = _cairo_int128_add (m_value, o.m_value);
|
||||
EnsureSlow ();
|
||||
const_cast<HighPrecision &> (o).EnsureSlow ();
|
||||
m_slowValue = _cairo_int128_add (m_slowValue, o.m_slowValue);
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
HighPrecision::Sub (HighPrecision const &o)
|
||||
HighPrecision::SlowSub (HighPrecision const &o)
|
||||
{
|
||||
m_value = _cairo_int128_sub (m_value, o.m_value);
|
||||
EnsureSlow ();
|
||||
const_cast<HighPrecision &> (o).EnsureSlow ();
|
||||
m_slowValue = _cairo_int128_sub (m_slowValue, o.m_slowValue);
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
HighPrecision::Mul (HighPrecision const &o)
|
||||
HighPrecision::SlowMul (HighPrecision const &o)
|
||||
{
|
||||
cairo_int128_t other = _cairo_int128_rsa (o.m_value, 64);
|
||||
m_value = _cairo_int128_mul (m_value, other);
|
||||
EnsureSlow ();
|
||||
const_cast<HighPrecision &> (o).EnsureSlow ();
|
||||
cairo_int128_t other = _cairo_int128_rsa (o.m_slowValue, 64);
|
||||
m_slowValue = _cairo_int128_mul (m_slowValue, other);
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
HighPrecision::Div (HighPrecision const &o)
|
||||
{
|
||||
#if 1
|
||||
cairo_int128_t div = _cairo_int128_rsa (o.m_value, 64);
|
||||
HP128INC (m_ndivs++);
|
||||
EnsureSlow ();
|
||||
const_cast<HighPrecision &> (o).EnsureSlow ();
|
||||
cairo_int128_t div = _cairo_int128_rsa (o.m_slowValue, 64);
|
||||
cairo_quorem128_t qr;
|
||||
qr = _cairo_int128_divrem (m_value, div);
|
||||
m_value = qr.quo;
|
||||
#else
|
||||
cairo_quorem128_t qr;
|
||||
qr = _cairo_int128_divrem (m_value, o.m_value);
|
||||
m_value = qr.quo;
|
||||
m_value = _cairo_int128_lsl (m_value, 64);
|
||||
cairo_int128_t rem = _cairo_int128_rsa (qr.rem, 64);
|
||||
m_value = _cairo_int128_add (m_value, rem);
|
||||
#endif
|
||||
qr = _cairo_int128_divrem (m_slowValue, div);
|
||||
m_slowValue = qr.quo;
|
||||
return false;
|
||||
}
|
||||
int
|
||||
HighPrecision::Compare (HighPrecision const &o) const
|
||||
HighPrecision::SlowCompare (HighPrecision const &o) const
|
||||
{
|
||||
if (_cairo_int128_lt (m_value, o.m_value))
|
||||
const_cast<HighPrecision *> (this)->EnsureSlow ();
|
||||
const_cast<HighPrecision &> (o).EnsureSlow ();
|
||||
if (_cairo_int128_lt (m_slowValue, o.m_slowValue))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (_cairo_int128_eq (m_value, o.m_value))
|
||||
else if (_cairo_int128_eq (m_slowValue, o.m_slowValue))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -124,12 +179,6 @@ HighPrecision::Compare (HighPrecision const &o) const
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
HighPrecision
|
||||
HighPrecision::Zero (void)
|
||||
{
|
||||
return HighPrecision (0,0);
|
||||
}
|
||||
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
@@ -283,7 +332,7 @@ HighPrecision128Tests::RunTests (void)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static HighPrecision128Tests g_int128_tests;
|
||||
static HighPrecision128Tests g_int128Tests;
|
||||
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
@@ -24,34 +24,179 @@
|
||||
#include <stdint.h>
|
||||
#include "cairo-wideint-private.h"
|
||||
|
||||
#define HP128INC(x)
|
||||
//#define HP128INC(x) x++
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This should be a high-precision 128bit integer version of
|
||||
* HighPrecision class. It should also be able to report
|
||||
* overflow and underflow.
|
||||
*/
|
||||
class HighPrecision
|
||||
{
|
||||
public:
|
||||
HighPrecision ();
|
||||
HighPrecision (int64_t value, bool dummy);
|
||||
inline HighPrecision ();
|
||||
inline HighPrecision (int64_t value, bool dummy);
|
||||
HighPrecision (double value);
|
||||
|
||||
static void PrintStats (void);
|
||||
|
||||
int64_t GetInteger (void) const;
|
||||
double GetDouble (void) const;
|
||||
bool Add (HighPrecision const &o);
|
||||
bool Sub (HighPrecision const &o);
|
||||
bool Mul (HighPrecision const &o);
|
||||
inline int64_t GetInteger (void) const;
|
||||
inline double GetDouble (void) const;
|
||||
inline bool Add (HighPrecision const &o);
|
||||
inline bool Sub (HighPrecision const &o);
|
||||
inline bool Mul (HighPrecision const &o);
|
||||
bool Div (HighPrecision const &o);
|
||||
|
||||
int Compare (HighPrecision const &o) const;
|
||||
static HighPrecision Zero (void);
|
||||
inline int Compare (HighPrecision const &o) const;
|
||||
inline static HighPrecision Zero (void);
|
||||
private:
|
||||
int64_t SlowGetInteger (void) const;
|
||||
double SlowGetDouble (void) const;
|
||||
bool SlowAdd (HighPrecision const &o);
|
||||
bool SlowSub (HighPrecision const &o);
|
||||
bool SlowMul (HighPrecision const &o);
|
||||
int SlowCompare (HighPrecision const &o) const;
|
||||
inline void EnsureSlow (void);
|
||||
|
||||
static const double MAX_64;
|
||||
cairo_int128_t m_value;
|
||||
bool m_isFast;
|
||||
int64_t m_fastValue;
|
||||
cairo_int128_t m_slowValue;
|
||||
|
||||
static int m_nfastadds;
|
||||
static int m_nfastsubs;
|
||||
static int m_nfastmuls;
|
||||
static int m_nfastcmps;
|
||||
static int m_nfastgets;
|
||||
static int m_nslowadds;
|
||||
static int m_nslowsubs;
|
||||
static int m_nslowmuls;
|
||||
static int m_nslowcmps;
|
||||
static int m_nslowgets;
|
||||
static int m_ndivs;
|
||||
static int m_nconversions;
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
HighPrecision::HighPrecision ()
|
||||
: m_isFast (true),
|
||||
m_fastValue (0)
|
||||
{}
|
||||
|
||||
HighPrecision::HighPrecision (int64_t value, bool dummy)
|
||||
: m_isFast (true),
|
||||
m_fastValue (value)
|
||||
{}
|
||||
|
||||
|
||||
int64_t
|
||||
HighPrecision::GetInteger (void) const
|
||||
{
|
||||
if (m_isFast)
|
||||
{
|
||||
HP128INC (m_nfastgets);
|
||||
return m_fastValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
HP128INC (m_nslowgets);
|
||||
return SlowGetInteger ();
|
||||
}
|
||||
}
|
||||
double HighPrecision::GetDouble (void) const
|
||||
{
|
||||
if (m_isFast)
|
||||
{
|
||||
HP128INC (m_nfastgets);
|
||||
double retval = m_fastValue;
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
HP128INC (m_nslowgets);
|
||||
return SlowGetDouble ();
|
||||
}
|
||||
}
|
||||
bool
|
||||
HighPrecision::Add (HighPrecision const &o)
|
||||
{
|
||||
if (m_isFast && o.m_isFast)
|
||||
{
|
||||
HP128INC (m_nfastadds);
|
||||
m_fastValue += o.m_fastValue;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
HP128INC (m_nslowadds);
|
||||
return SlowAdd (o);
|
||||
}
|
||||
}
|
||||
bool
|
||||
HighPrecision::Sub (HighPrecision const &o)
|
||||
{
|
||||
if (m_isFast && o.m_isFast)
|
||||
{
|
||||
HP128INC (m_nfastsubs);
|
||||
m_fastValue -= o.m_fastValue;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
HP128INC (m_nslowsubs);
|
||||
return SlowSub (o);
|
||||
}
|
||||
}
|
||||
bool
|
||||
HighPrecision::Mul (HighPrecision const &o)
|
||||
{
|
||||
if (m_isFast && o.m_isFast)
|
||||
{
|
||||
HP128INC (m_nfastmuls);
|
||||
m_fastValue *= o.m_fastValue;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
HP128INC (m_nslowmuls);
|
||||
return SlowMul (o);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
HighPrecision::Compare (HighPrecision const &o) const
|
||||
{
|
||||
if (m_isFast && o.m_isFast)
|
||||
{
|
||||
HP128INC (m_nfastcmps);
|
||||
if (m_fastValue < o.m_fastValue)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (m_fastValue == o.m_fastValue)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return +1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HP128INC (m_nslowcmps);
|
||||
return SlowCompare (o);
|
||||
}
|
||||
|
||||
}
|
||||
HighPrecision
|
||||
HighPrecision::Zero (void)
|
||||
{
|
||||
return HighPrecision ();
|
||||
}
|
||||
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
#endif /* HIGH_PRECISION_128_H */
|
||||
|
||||
Reference in New Issue
Block a user