inline new high precision implementation

This commit is contained in:
Mathieu Lacage
2010-07-04 17:07:07 +02:00
parent c444b8b4f0
commit e13d7187e4
2 changed files with 76 additions and 69 deletions

View File

@@ -2,61 +2,21 @@
#include "ns3/fatal-error.h"
#include <math.h>
#define MAX_64 18446744073709551615.0
namespace ns3 {
HighPrecision::HighPrecision ()
: m_value (0)
{}
HighPrecision::HighPrecision (int64_t value, bool dummy)
: m_value (value)
{
m_value <<= 64;
}
#define HP128_MAX_64 18446744073709551615.0
HighPrecision::HighPrecision (double value)
{
bool is_negative = value < 0;
value = is_negative?-value:value;
double hi = floor (value);
double lo = (value - hi) * MAX_64;
double lo = (value - hi) * HP128_MAX_64;
m_value = hi;
m_value <<= 64;
m_value += lo;
m_value = is_negative?-m_value:m_value;
}
int64_t HighPrecision::GetInteger (void) const
{
int128_t v = m_value >> 64;
return v;
}
double
HighPrecision::GetDouble (void) const
{
bool is_negative = m_value < 0;
uint128_t value = is_negative ? -m_value:m_value;
uint64_t hi = value >> 64;
uint64_t lo = value;
double flo = lo;
flo /= MAX_64;
double retval = hi;
retval += flo;
retval = is_negative ? -retval : retval;
return retval;
}
bool
HighPrecision::Add (HighPrecision const &o)
{
m_value += o.m_value;
return true;
}
bool
HighPrecision::Sub (HighPrecision const &o)
{
m_value -= o.m_value;
return true;
}
#define MASK_LO ((((uint128_t)1)<<64)-1)
#define MASK_HI (~MASK_LO)
bool
@@ -141,16 +101,4 @@ HighPrecision::Div (HighPrecision const &o)
return true;
}
int
HighPrecision::Compare (HighPrecision const &o) const
{
return (m_value < o.m_value)?-1:(m_value == o.m_value)?0:1;
}
HighPrecision
HighPrecision::Zero (void)
{
return HighPrecision ();
}
} // namespace ns3

View File

@@ -28,31 +28,90 @@ typedef __uint128_t uint128_t;
typedef __int128_t int128_t;
#endif
//#define HP_INLINE inline
#define HP_INLINE
namespace ns3 {
class HighPrecision
{
public:
HP_INLINE HighPrecision ();
HP_INLINE HighPrecision (int64_t value, bool dummy);
HP_INLINE HighPrecision (double value);
inline HighPrecision ();
inline HighPrecision (int64_t value, bool dummy);
HighPrecision (double value);
HP_INLINE int64_t GetInteger (void) const;
HP_INLINE double GetDouble (void) const;
HP_INLINE bool Add (HighPrecision const &o);
HP_INLINE bool Sub (HighPrecision const &o);
HP_INLINE bool Mul (HighPrecision const &o);
HP_INLINE bool Div (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);
bool Mul (HighPrecision const &o);
bool Div (HighPrecision const &o);
HP_INLINE int Compare (HighPrecision const &o) const;
HP_INLINE static HighPrecision Zero (void);
inline int Compare (HighPrecision const &o) const;
inline static HighPrecision Zero (void);
private:
int128_t m_value;
};
} // namespace ns3
namespace ns3 {
HighPrecision::HighPrecision ()
: m_value (0)
{}
HighPrecision::HighPrecision (int64_t value, bool dummy)
: m_value (value)
{
m_value <<= 64;
}
double
HighPrecision::GetDouble (void) const
{
#define HP128_MAX_64 18446744073709551615.0
bool is_negative = m_value < 0;
uint128_t value = is_negative ? -m_value:m_value;
uint64_t hi = value >> 64;
uint64_t lo = value;
double flo = lo;
flo /= HP128_MAX_64;
double retval = hi;
retval += flo;
retval = is_negative ? -retval : retval;
return retval;
#undef HP128_MAX_64
}
int64_t HighPrecision::GetInteger (void) const
{
int128_t v = m_value >> 64;
return v;
}
bool
HighPrecision::Add (HighPrecision const &o)
{
m_value += o.m_value;
return true;
}
bool
HighPrecision::Sub (HighPrecision const &o)
{
m_value -= o.m_value;
return true;
}
int
HighPrecision::Compare (HighPrecision const &o) const
{
return (m_value < o.m_value)?-1:(m_value == o.m_value)?0:1;
}
HighPrecision
HighPrecision::Zero (void)
{
return HighPrecision ();
}
} // namespace ns3
#endif /* HIGH_PRECISION_128_H */