--- a/src/simulator/high-precision-128.cc Fri Aug 13 13:28:38 2010 +0200
+++ b/src/simulator/high-precision-128.cc Fri Aug 13 13:30:14 2010 +0200
@@ -33,6 +33,29 @@
#define MASK_LO ((((uint128_t)1)<<64)-1)
#define MASK_HI (~MASK_LO)
+HighPrecision::HighPrecision (int64_t high, uint64_t low)
+{
+ bool is_negative = high<0;
+ m_value = is_negative?-high:high;
+ m_value <<= 64;
+ m_value += low;
+ m_value = is_negative?-m_value:m_value;
+}
+int64_t
+HighPrecision::GetHigh (void) const
+{
+ return GetInteger ();
+}
+uint64_t
+HighPrecision::GetLow (void) const
+{
+ bool negative = m_value < 0;
+ int128_t v = negative?-m_value:m_value;
+ int128_t low = v & MASK_LO;
+ uint64_t retval = low;
+ return retval;
+}
+
void
HighPrecision::Mul (HighPrecision const &o)
{
@@ -154,4 +177,238 @@
return result;
}
+static uint8_t MostSignificantDigit (uint64_t value)
+{
+ uint8_t n = 0;
+ do
+ {
+ n++;
+ value /= 10;
+ } while (value != 0);
+ return n;
+}
+
+static uint128_t PowerOfTen (uint8_t n)
+{
+ uint128_t retval = 1;
+ while (n > 0)
+ {
+ retval *= 10;
+ n--;
+ }
+ return retval;
+}
+
+std::ostream &operator << (std::ostream &os, const HighPrecision &hp)
+{
+ int64_t hi = hp.GetHigh ();
+ os << ((hi<0)?"-":"+") << ((hi<0)?-hi:hi) << ".";
+ uint128_t low = hp.GetLow ();
+ uint8_t msd = MostSignificantDigit (~((uint64_t)0));
+ do
+ {
+ msd--;
+ uint128_t pow = PowerOfTen (msd);
+ uint8_t digit = low / pow;
+ NS_ASSERT (digit < 10);
+ os << (uint16_t) digit;
+ low -= digit * pow;
+ } while (msd > 0 && low > 0);
+ return os;
+}
+
+static uint64_t ReadDigits (std::string str)
+{
+ const char *buf = str.c_str ();
+ uint64_t retval = 0;
+ while (*buf != 0)
+ {
+ retval *= 10;
+ retval += *buf - 0x30;
+ buf++;
+ }
+ return retval;
+}
+
+std::istream &operator >> (std::istream &is, HighPrecision &hp)
+{
+ std::string str;
+
+ is >> str;
+ bool negative;
+ // skip heading spaces
+ std::string::size_type cur;
+ cur = str.find_first_not_of (" ");
+ std::string::size_type next;
+ // first, remove the sign.
+ next = str.find ("-", cur);
+ if (next != std::string::npos)
+ {
+ negative = true;
+ next++;
+ }
+ else
+ {
+ next = str.find ("+", cur);
+ if (next != std::string::npos)
+ {
+ next++;
+ }
+ else
+ {
+ next = cur;
+ }
+ negative = false;
+ }
+ cur = next;
+ int64_t hi;
+ uint64_t lo;
+ next = str.find(".", cur);
+ if (next != std::string::npos)
+ {
+ hi = ReadDigits (str.substr (cur, next-cur));
+ lo = ReadDigits (str.substr (next+1, str.size()-(next+1)));
+ }
+ else
+ {
+ hi = ReadDigits (str.substr (cur, str.size ()-cur));
+ lo = 0;
+ }
+ hi = negative?-hi:hi;
+ hp = HighPrecision (hi, lo);
+ return is;
+}
+
} // namespace ns3
+
+#include "ns3/test.h"
+
+namespace ns3
+{
+
+class HpFracTestCase : public TestCase
+{
+public:
+ HpFracTestCase ();
+ virtual bool DoRun (void);
+ void CheckFrac (int64_t hi, uint64_t lo);
+};
+
+void
+HpFracTestCase::CheckFrac (int64_t hi, uint64_t lo)
+{
+ HighPrecision tmp = HighPrecision (hi,lo);
+ NS_TEST_EXPECT_MSG_EQ (tmp.GetHigh (), hi,
+ "High part does not match");
+ NS_TEST_EXPECT_MSG_EQ (tmp.GetLow (), lo,
+ "Low part does not match");
+}
+
+HpFracTestCase::HpFracTestCase ()
+ : TestCase ("Check that we can manipulate the high and low part of every number")
+{
+}
+bool
+HpFracTestCase::DoRun (void)
+{
+ CheckFrac (1, 0);
+ CheckFrac (1, 1);
+ CheckFrac (-1, 0);
+ CheckFrac (-1, 1);
+ return GetErrorStatus ();
+}
+
+
+class HpInputTestCase : public TestCase
+{
+public:
+ HpInputTestCase ();
+ virtual bool DoRun (void);
+ void CheckString (std::string str, int64_t hi, uint64_t lo);
+};
+HpInputTestCase::HpInputTestCase ()
+ : TestCase ("Check that we parse HighPrecision numbers as strings")
+{
+}
+void
+HpInputTestCase::CheckString (std::string str, int64_t hi, uint64_t lo)
+{
+ std::istringstream iss;
+ iss.str (str);
+ HighPrecision hp;
+ iss >> hp;
+ NS_TEST_EXPECT_MSG_EQ (hp.GetHigh (), hi, "High parts do not match for input string " << str);
+ NS_TEST_EXPECT_MSG_EQ (hp.GetLow (), lo, "Low parts do not match for input string " << str);
+}
+bool
+HpInputTestCase::DoRun (void)
+{
+ CheckString ("1", 1, 0);
+ CheckString ("+1", 1, 0);
+ CheckString ("-1", -1, 0);
+ CheckString ("1.0", 1, 0);
+ CheckString ("+1.0", 1, 0);
+ CheckString ("001.0", 1, 0);
+ CheckString ("+001.0", 1, 0);
+ CheckString ("020.0", 20, 0);
+ CheckString ("+020.0", 20, 0);
+ CheckString ("-1.0", -1, 0);
+ CheckString ("-1.0000", -1, 0);
+ CheckString ("1.0000000", 1, 0);
+ CheckString ("1.08446744073709551615", 1, 8446744073709551615LL);
+ CheckString ("-1.08446744073709551615", -1, 8446744073709551615LL);
+
+ return GetErrorStatus ();
+}
+
+class HpInputOutputTestCase : public TestCase
+{
+public:
+ HpInputOutputTestCase ();
+ virtual bool DoRun (void);
+ void CheckString (std::string str);
+};
+HpInputOutputTestCase::HpInputOutputTestCase ()
+ : TestCase ("Check that we can roundtrip HighPrecision numbers as strings")
+{
+}
+void
+HpInputOutputTestCase::CheckString (std::string str)
+{
+ std::istringstream iss;
+ iss.str (str);
+ HighPrecision hp;
+ iss >> hp;
+ std::ostringstream oss;
+ oss << hp;
+ NS_TEST_EXPECT_MSG_EQ (oss.str (), str, "Converted string does not match expected string");
+}
+bool
+HpInputOutputTestCase::DoRun (void)
+{
+ CheckString ("+1.0");
+ CheckString ("-1.0");
+ CheckString ("+20.0");
+ CheckString ("+1.08446744073709551615");
+ CheckString ("-1.08446744073709551615");
+ CheckString ("+1.18446744073709551615");
+ CheckString ("-1.18446744073709551615");
+
+ return GetErrorStatus ();
+}
+
+
+static class HighPrecision128TestSuite : public TestSuite
+{
+public:
+ HighPrecision128TestSuite ()
+ : TestSuite ("high-precision-128", UNIT)
+ {
+ AddTestCase (new HpFracTestCase ());
+ AddTestCase (new HpInputTestCase ());
+ //AddTestCase (new HpOutputTestCase ());
+ AddTestCase (new HpInputOutputTestCase ());
+ }
+} g_highPrecision128TestSuite;
+
+} // namespace ns3
--- a/src/simulator/high-precision-128.h Fri Aug 13 13:28:38 2010 +0200
+++ b/src/simulator/high-precision-128.h Fri Aug 13 13:30:14 2010 +0200
@@ -23,6 +23,7 @@
#include "ns3/simulator-config.h"
#include <math.h>
#include <stdint.h>
+#include <iostream>
#define noCOUNT_OPS 1
@@ -53,6 +54,7 @@
{
public:
inline HighPrecision ();
+ explicit HighPrecision (int64_t high, uint64_t low);
explicit inline HighPrecision (int64_t value, bool dummy);
explicit inline HighPrecision (double value);
@@ -67,6 +69,9 @@
inline int Compare (HighPrecision const &o) const;
inline static HighPrecision Zero (void);
+
+ int64_t GetHigh (void) const;
+ uint64_t GetLow (void) const;
private:
static uint128_t UmulByInvert (uint128_t a, uint128_t b);
static uint128_t Umul (uint128_t a, uint128_t b);
@@ -86,6 +91,9 @@
#endif
};
+std::ostream &operator << (std::ostream &os, const HighPrecision &hp);
+std::istream &operator >> (std::istream &is, HighPrecision &hp);
+
} // namespace ns3
namespace ns3 {
@@ -103,8 +111,11 @@
int64_t HighPrecision::GetInteger (void) const
{
- int128_t v = m_value >> 64;
- return v;
+ bool negative = m_value < 0;
+ int128_t v = negative?-m_value:m_value;
+ v >>= 64;
+ int64_t retval = v;
+ return negative?-retval:retval;
}
void
--- a/src/simulator/high-precision-cairo.cc Fri Aug 13 13:28:38 2010 +0200
+++ b/src/simulator/high-precision-cairo.cc Fri Aug 13 13:30:14 2010 +0200
@@ -155,6 +155,15 @@
return result;
}
+std::ostream &operator << (std::ostream &os, const HighPrecision &hp)
+{
+ return os;
+}
+std::istream &operator >> (std::istream &is, HighPrecision &hp)
+{
+ return is;
+}
+
} // namespace ns3
--- a/src/simulator/high-precision-cairo.h Fri Aug 13 13:28:38 2010 +0200
+++ b/src/simulator/high-precision-cairo.h Fri Aug 13 13:30:14 2010 +0200
@@ -68,6 +68,10 @@
cairo_int128_t m_value;
};
+std::ostream &operator << (std::ostream &os, const HighPrecision &hp);
+std::istream &operator >> (std::istream &is, HighPrecision &hp);
+
+
} // namespace ns3
namespace ns3 {
--- a/src/simulator/high-precision.cc Fri Aug 13 13:28:38 2010 +0200
+++ b/src/simulator/high-precision.cc Fri Aug 13 13:30:14 2010 +0200
@@ -172,7 +172,7 @@
a.Mul (V (3));
CHECK_EXPECTED (a, 1999999999);
- return false;
+ return GetErrorStatus ();
}
class HpBug455TestCase : public TestCase
@@ -205,7 +205,7 @@
a.Mul (HighPrecision (-5));
NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -2.5, "only second operand negative");
- return false;
+ return GetErrorStatus ();
}
@@ -240,7 +240,7 @@
a.Div (HighPrecision (-0.5));
NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 1.0, "both arguments negative");
- return false;
+ return GetErrorStatus ();
}
class HpCompareTestCase : public TestCase
@@ -279,7 +279,7 @@
b = V (1);
NS_TEST_ASSERT_MSG_EQ (a.Compare (b), 0, "a is equal to b");
- return false;
+ return GetErrorStatus ();
}
class HpInvertTestCase : public TestCase
@@ -342,7 +342,7 @@
TEST(100000000000000LL);
TEST(1000000000000000LL);
#undef TEST
- return false;
+ return GetErrorStatus ();
}