More consistent 64bit coordinate support

This commit is contained in:
Matthias Koefferlein 2018-01-12 00:30:49 +01:00
parent 390a5c11a8
commit a2ba300bd7
4 changed files with 61 additions and 61 deletions

View File

@ -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

View File

@ -26,27 +26,27 @@
#if defined(HAVE_64BIT_COORD)
#include "tlCommon.h"
#include "tlString.h"
#include <inttypes.h>
#include <ostream>
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;
}

View File

@ -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<unsigned __int128>(-d));
return "-" + tl::to_string(static_cast<unsigned __int128> (-d));
} else {
return tl::to_string(static_cast<unsigned __int128>(d));
return tl::to_string(static_cast<unsigned __int128> (d));
}
}
template <>
std::string
tl::to_string (const unsigned __int128 &d)
tl::to_string (const unsigned __int128 &_x)
{
if (static_cast<uint64_t>(d) == d) {
return tl::to_string(static_cast<uint64_t>(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<uint64_t> (d>>64) << static_cast<uint64_t> (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 <>

View File

@ -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