From a1996b2d75ff3a259a98f7da97593c859a51a77e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 16 Aug 2015 16:34:32 +0200 Subject: [PATCH] Add implementation for operator-= --- include/doorkeeper/components/tilecoords.hpp | 7 +++ include/doorkeeper/implem/tilecoords.inl | 54 ++++++++++++++++++++ test/unit/tilecoords.cpp | 28 ++++++++++ tools/calc_advance.rb | 8 +-- 4 files changed, 93 insertions(+), 4 deletions(-) diff --git a/include/doorkeeper/components/tilecoords.hpp b/include/doorkeeper/components/tilecoords.hpp index 8c8ad25..1126f50 100644 --- a/include/doorkeeper/components/tilecoords.hpp +++ b/include/doorkeeper/components/tilecoords.hpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include namespace dk { template @@ -32,6 +34,9 @@ namespace dk { const CoordinateScalarType& operator[] ( int parIndex ) const; CoordinateScalarType& operator[] ( int parIndex ); + const coords& position ( void ) const; + const coords& upper ( void ) const; + private: coords m_pos; coords m_size; @@ -40,6 +45,8 @@ namespace dk { namespace implem { CoordinateScalarType sum_mod ( CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv ) a_pure; CoordinateScalarType sum_div ( CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv ) a_pure; + CoordinateScalarType sub_mod ( CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv ) a_pure; + CoordinateScalarType sub_div ( CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv ) a_pure; } //namespace implem } //namespace dk diff --git a/include/doorkeeper/implem/tilecoords.inl b/include/doorkeeper/implem/tilecoords.inl index f35ea90..6b19bef 100644 --- a/include/doorkeeper/implem/tilecoords.inl +++ b/include/doorkeeper/implem/tilecoords.inl @@ -19,9 +19,25 @@ namespace dk { ///Equivalent to (parA + parB) / parDiv ///---------------------------------------------------------------------- inline CoordinateScalarType sum_div (CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv) { + DK_ASSERT(parA >= 0 and parB >= 0 and parDiv > 0); + DK_ASSERT(std::numeric_limits::max() - (parA % parDiv) >= (parB % parDiv)); const auto x = ((parA % parDiv) + (parB % parDiv)) / parDiv; + DK_ASSERT(std::numeric_limits::max() - parA / parDiv >= parB / parDiv); + DK_ASSERT(std::numeric_limits::max() - parA / parDiv - parB / parDiv >= x); return parA / parDiv + parB / parDiv + x; } + + inline CoordinateScalarType sub_mod (CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv) { + typedef std::make_unsigned::type unsigned_coord; + const unsigned_coord rounded_sum = static_cast(sub_div(parA, parB, parDiv) * parDiv); + const unsigned_coord ret = static_cast(parA) - rounded_sum - static_cast(parB); + return static_cast(ret); + } + + inline CoordinateScalarType sub_div (CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv) { + const auto x = ((parA % parDiv) + (parB % parDiv)) / parDiv; + return parA / parDiv - parB / parDiv + x; + } } //namespace implem template @@ -86,6 +102,34 @@ namespace dk { return retval; } + template + const TileCoords& TileCoords::operator-= (CoordinateScalarType parValue) { + std::size_t index = 0; + if (parValue > 0) { + while (parValue) { + const auto t = parValue % (m_size[index] + 1); + DK_ASSERT(t >= 0); + const CoordinateScalarType r = (t > m_pos[index] ? 1 : 0); + m_pos[index] = (m_size[index] + 1) * r + m_pos[index] - t; + parValue /= (m_size[index] + 1); + parValue += r; + + ++index; + } + } + else if (parValue < 0) { + while (parValue) { + const auto new_pos = implem::sub_mod(m_pos[index], parValue, m_size[index] + 1); + parValue = -implem::sub_div(m_pos[index], parValue, m_size[index] + 1); + m_pos[index] = new_pos; + + ++index; + } + } + + return *this; + } + template const TileCoords& TileCoords::operator+= (CoordinateScalarType parValue) { std::size_t index = 0; @@ -143,4 +187,14 @@ namespace dk { DK_ASSERT(static_cast(parIndex) < D); return m_pos[parIndex]; } + + template + auto TileCoords::position() const -> const coords& { + return m_pos; + } + + template + auto TileCoords::upper() const -> const coords& { + return m_size; + } } //namespace dk diff --git a/test/unit/tilecoords.cpp b/test/unit/tilecoords.cpp index 9127714..55c94ea 100644 --- a/test/unit/tilecoords.cpp +++ b/test/unit/tilecoords.cpp @@ -90,6 +90,11 @@ TEST(advance, tilecoords) { EXPECT_EQ(1201, test[2]); EXPECT_EQ(710, test[3]); } +} + +TEST(back_forward, tilecoords) { + typedef dk::TileCoords<4> tcoords4; + typedef dk::TileCoords<4>::coords coords4; { const coords4 max_coords(32); @@ -111,4 +116,27 @@ TEST(advance, tilecoords) { test += -33 * 33 * 2; EXPECT_EQ(tcoords4(max_coords), test); } + + { + const coords4 max_coords(5300, 2499, 12631, 171244); + tcoords4 test(max_coords); + + test += 5000000; + EXPECT_EQ(coords4(1157, 943, 0, 0), test.position()); + + test -= 3350000; + EXPECT_EQ(coords4(1389, 311, 0, 0), test.position()); + + test += 50000000 - 5000000 + 3350000; + EXPECT_EQ(coords4(968, 1932, 3, 0), test.position()); + + test -= 900; + EXPECT_EQ(coords4(68, 1932, 3, 0), test.position()); + + test += 5300 + 1; + EXPECT_EQ(coords4(68, 1933, 3, 0), test.position()); + + test -= -5302; + EXPECT_EQ(coords4(69, 1934, 3, 0), test.position()); + } } diff --git a/tools/calc_advance.rb b/tools/calc_advance.rb index e0beb10..af9ae2c 100755 --- a/tools/calc_advance.rb +++ b/tools/calc_advance.rb @@ -2,8 +2,7 @@ M = 2147483647 -def calc(arr, m) - v = M +def calc(v, arr, m) index = 0 out = arr.dup while (v > 0) do @@ -16,5 +15,6 @@ def calc(arr, m) out end -p calc([540, 800, 1200, 710], [M - 10, M - 11, M - 12, M - 13]) -p calc([M - 1, 800, 1200, 710], [M - 1, 800, M - 1, M - 1]) +p calc(M, [540, 800, 1200, 710], [M - 10, M - 11, M - 12, M - 13]) +p calc(M, [M - 1, 800, 1200, 710], [M - 1, 800, M - 1, M - 1]) +p calc(1650000, [0, 0, 0, 0], [5300, 2499, 12631, 171244])