diff --git a/src/tl/tl/tlInt128Support.cc b/src/tl/tl/tlInt128Support.cc index a31b0ade3..c6f4bd007 100644 --- a/src/tl/tl/tlInt128Support.cc +++ b/src/tl/tl/tlInt128Support.cc @@ -24,44 +24,6 @@ #include "tlInt128Support.h" -namespace tl -{ - -std::string -int128_to_string (__int128 x) -{ - std::string r; - - // this is the max. power of 10 that can be represented with __int128 - __int128 m = (unsigned long long) 0x4b3b4ca85a86c47a; - m <<= 64; - m |= (unsigned long long) 0x98a224000000000; - - if (x < 0) { - r = "-"; - x = -x; - } else if (x == 0) { - return "0"; - } - - bool first = true; - while (m > 1) { - int d = 0; - while (x >= m) { - d += 1; - x -= m; - } - if (d > 0 || !first) { - r += char ('0' + d); - first = false; - } - m /= 10; - } - - r += char('0' + int(x)); - return r; -} - -} +// .. nothing yet .. #endif diff --git a/src/tl/tl/tlInt128Support.h b/src/tl/tl/tlInt128Support.h index be69c2ab9..1ead22cc6 100644 --- a/src/tl/tl/tlInt128Support.h +++ b/src/tl/tl/tlInt128Support.h @@ -26,27 +26,27 @@ #if defined(HAVE_64BIT_COORD) #include "tlCommon.h" +#include "tlString.h" #include #include -namespace tl -{ - TL_PUBLIC std::string int128_to_string (__int128 x); -} - namespace std { +#if !defined(__GLIBCXX_BITSIZE_INT_N_0) || __GLIBCXX_BITSIZE_INT_N_0 != 128 + // Provide an implementation for abs(__int128_t) if there isn't one inline __int128 abs (__int128 x) { return x < 0 ? -x : x; } +#endif + // Provide ostream serialization for 128bit values inline std::ostream &operator<< (std::ostream &os, __int128 x) { - os << tl::int128_to_string (x); + os << tl::to_string (x); return os; } diff --git a/src/tl/tl/tlString.cc b/src/tl/tl/tlString.cc index 95ae2cea4..52d7f6715 100644 --- a/src/tl/tl/tlString.cc +++ b/src/tl/tl/tlString.cc @@ -232,29 +232,52 @@ tl::to_string (const unsigned long long &d) } #if defined(HAVE_64BIT_COORD) + template <> std::string tl::to_string (const __int128 &d) { if (d < 0 ) { - return "-" + tl::to_string(static_cast(-d)); + return "-" + tl::to_string(static_cast (-d)); } else { - return tl::to_string(static_cast(d)); + return tl::to_string(static_cast (d)); } } template <> std::string -tl::to_string (const unsigned __int128 &d) +tl::to_string (const unsigned __int128 &_x) { - if (static_cast(d) == d) { - return tl::to_string(static_cast(d)); + std::string r; + unsigned __int128 x = _x; + + // this is the max. power of 10 that can be represented with __int128 + unsigned __int128 m = (unsigned long long) 0x4b3b4ca85a86c47a; + m <<= 64; + m |= (unsigned long long) 0x98a224000000000; + + if (x == 0) { + return "0"; } - std::ostringstream os; - os.imbue (c_locale); - os << "0x" << std::hex << static_cast (d>>64) << static_cast (d); - return os.str (); + + bool first = true; + while (m > 1) { + int d = 0; + while (x >= m) { + d += 1; + x -= m; + } + if (d > 0 || !first) { + r += char ('0' + d); + first = false; + } + m /= 10; + } + + r += char('0' + int(x)); + return r; } + #endif template <> diff --git a/src/tl/unit_tests/tlInt128Support.cc b/src/tl/unit_tests/tlInt128Support.cc index 64a2ed784..bca43995e 100644 --- a/src/tl/unit_tests/tlInt128Support.cc +++ b/src/tl/unit_tests/tlInt128Support.cc @@ -29,19 +29,34 @@ TEST(1) { - EXPECT_EQ (tl::int128_to_string (__int128 (0)), "0"); - EXPECT_EQ (tl::int128_to_string (__int128 (42)), "42"); - EXPECT_EQ (tl::int128_to_string (__int128 (-42)), "-42"); + EXPECT_EQ (tl::to_string (__int128 (0)), "0"); + EXPECT_EQ (tl::to_string (__int128 (42)), "42"); + EXPECT_EQ (tl::to_string (__int128 (-42)), "-42"); __int128 x = 1; for (int i = 0; i < 30; ++i) { x *= 10; } - EXPECT_EQ (tl::int128_to_string (x), "1000000000000000000000000000000"); - EXPECT_EQ (tl::int128_to_string (-x), "-1000000000000000000000000000000"); - EXPECT_EQ (tl::int128_to_string (x + 1), "1000000000000000000000000000001"); - EXPECT_EQ (tl::int128_to_string (x - 1), "999999999999999999999999999999"); + EXPECT_EQ (tl::to_string (x), "1000000000000000000000000000000"); + EXPECT_EQ (tl::to_string (-x), "-1000000000000000000000000000000"); + EXPECT_EQ (tl::to_string (x + 1), "1000000000000000000000000000001"); + EXPECT_EQ (tl::to_string (x - 1), "999999999999999999999999999999"); +} + +TEST(2) +{ + EXPECT_EQ (tl::to_string ((unsigned __int128) 0), "0"); + EXPECT_EQ (tl::to_string ((unsigned __int128) 42), "42"); + + unsigned __int128 x = 1; + for (int i = 0; i < 30; ++i) { + x *= 10; + } + + EXPECT_EQ (tl::to_string (x), "1000000000000000000000000000000"); + EXPECT_EQ (tl::to_string (x + 1), "1000000000000000000000000000001"); + EXPECT_EQ (tl::to_string (x - 1), "999999999999999999999999999999"); } #endif