Try mplementing operator+= (broken but almost there).
This commit is contained in:
parent
9ea9743e95
commit
dbdc814049
4 changed files with 136 additions and 6 deletions
|
@ -5,6 +5,7 @@
|
||||||
#include "doorkeeper/implem/vector.hpp"
|
#include "doorkeeper/implem/vector.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace dk {
|
namespace dk {
|
||||||
template <uint32_t D>
|
template <uint32_t D>
|
||||||
|
@ -28,11 +29,18 @@ namespace dk {
|
||||||
bool operator== ( const TileCoords& parOther ) const;
|
bool operator== ( const TileCoords& parOther ) const;
|
||||||
bool operator!= ( const TileCoords& parOther ) const;
|
bool operator!= ( const TileCoords& parOther ) const;
|
||||||
TileCoords& operator= ( const TileCoords& ) = default;
|
TileCoords& operator= ( const TileCoords& ) = default;
|
||||||
|
const CoordinateScalarType& operator[] ( int parIndex ) const;
|
||||||
|
CoordinateScalarType& operator[] ( int parIndex );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
coords m_pos;
|
coords m_pos;
|
||||||
coords m_size;
|
coords m_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace implem {
|
||||||
|
CoordinateScalarType sum_mod ( CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv ) a_pure;
|
||||||
|
CoordinateScalarType sum_div ( CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv ) a_pure;
|
||||||
|
} //namespace implem
|
||||||
} //namespace dk
|
} //namespace dk
|
||||||
|
|
||||||
#include "doorkeeper/implem/tilecoords.inl"
|
#include "doorkeeper/implem/tilecoords.inl"
|
||||||
|
|
|
@ -1,10 +1,30 @@
|
||||||
namespace dk {
|
namespace dk {
|
||||||
|
namespace implem {
|
||||||
|
inline CoordinateScalarType sum_mod (CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv) {
|
||||||
|
//const auto sum = m_pos[index] + parValue;
|
||||||
|
//const auto sz = m_size[index] + 1;
|
||||||
|
//const auto remainder = sum - (sum / sz) * sz;
|
||||||
|
|
||||||
|
//m_pos[index] = remainder;
|
||||||
|
//parValue /= sz;
|
||||||
|
|
||||||
|
const auto rounded_sum = sum_div(parA, parB, parDiv) * parDiv;
|
||||||
|
return std::max(parA, parB) - rounded_sum + std::min(parA, parB);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CoordinateScalarType sum_div (CoordinateScalarType parA, CoordinateScalarType parB, CoordinateScalarType parDiv) {
|
||||||
|
const auto x = ((parA % parDiv) + (parB % parDiv)) / parDiv;
|
||||||
|
return parA / parDiv + parB / parDiv + x;
|
||||||
|
}
|
||||||
|
} //namespace implem
|
||||||
|
|
||||||
template <uint32_t D>
|
template <uint32_t D>
|
||||||
TileCoords<D>::TileCoords (const coords& parSize) :
|
TileCoords<D>::TileCoords (const coords& parSize) :
|
||||||
m_pos(CoordinateScalarType(0)),
|
m_pos(CoordinateScalarType(0)),
|
||||||
m_size(parSize)
|
m_size(parSize)
|
||||||
{
|
{
|
||||||
DK_ASSERT(m_pos <= m_size);
|
DK_ASSERT(m_pos <= m_size);
|
||||||
|
DK_ASSERT(m_size < coords(std::numeric_limits<CoordinateScalarType>::max()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t D>
|
template <uint32_t D>
|
||||||
|
@ -13,6 +33,7 @@ namespace dk {
|
||||||
m_size(parSize)
|
m_size(parSize)
|
||||||
{
|
{
|
||||||
DK_ASSERT(m_pos <= m_size);
|
DK_ASSERT(m_pos <= m_size);
|
||||||
|
DK_ASSERT(m_size < coords(std::numeric_limits<CoordinateScalarType>::max()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t D>
|
template <uint32_t D>
|
||||||
|
@ -61,13 +82,20 @@ namespace dk {
|
||||||
|
|
||||||
template <uint32_t D>
|
template <uint32_t D>
|
||||||
const TileCoords<D>& TileCoords<D>::operator+= (CoordinateScalarType parValue) {
|
const TileCoords<D>& TileCoords<D>::operator+= (CoordinateScalarType parValue) {
|
||||||
CoordinateScalarType acc(parValue);
|
std::size_t index = 0;
|
||||||
CoordinateScalarType div(1);
|
while (parValue) {
|
||||||
for (std::size_t z = 0; z < D; ++z) {
|
//naïve implementation
|
||||||
m_pos[z] = (m_pos[z] + acc / div) % m_size[z];
|
//parValue += m_pos[index];
|
||||||
div *= m_size[z];
|
//m_pos[index] = parValue % (m_size[index] + 1);
|
||||||
acc += m_pos[z];
|
//parValue /= (m_size[index] + 1);
|
||||||
|
//++index;
|
||||||
|
|
||||||
|
//overflow-aware implementation
|
||||||
|
const auto new_pos = implem::sum_mod(m_pos[index], parValue, m_size[index] + 1);
|
||||||
|
parValue = implem::sum_div(m_pos[index], parValue, m_size[index] + 1);
|
||||||
|
m_pos[index] = new_pos;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t D>
|
template <uint32_t D>
|
||||||
|
@ -79,4 +107,17 @@ namespace dk {
|
||||||
bool TileCoords<D>::operator!= (const TileCoords& parOther) const {
|
bool TileCoords<D>::operator!= (const TileCoords& parOther) const {
|
||||||
return not(*this == parOther);
|
return not(*this == parOther);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <uint32_t D>
|
||||||
|
const CoordinateScalarType& TileCoords<D>::operator[] (int parIndex) const {
|
||||||
|
DK_ASSERT(parIndex >= 0);
|
||||||
|
DK_ASSERT(static_cast<uint32_t>(parIndex) < D);
|
||||||
|
return m_pos[parIndex];
|
||||||
|
}
|
||||||
|
template <uint32_t D>
|
||||||
|
CoordinateScalarType& TileCoords<D>::operator[] (int parIndex) {
|
||||||
|
DK_ASSERT(parIndex >= 0);
|
||||||
|
DK_ASSERT(static_cast<uint32_t>(parIndex) < D);
|
||||||
|
return m_pos[parIndex];
|
||||||
|
}
|
||||||
} //namespace dk
|
} //namespace dk
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include "doorkeeper/components/tilecoords.hpp"
|
#include "doorkeeper/components/tilecoords.hpp"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
TEST(increment, tilecoords) {
|
TEST(increment, tilecoords) {
|
||||||
typedef dk::TileCoords<2> tcoords2;
|
typedef dk::TileCoords<2> tcoords2;
|
||||||
|
@ -30,3 +31,63 @@ TEST(increment, tilecoords) {
|
||||||
EXPECT_EQ(tcoords5(max_coords, max_coords), test);
|
EXPECT_EQ(tcoords5(max_coords, max_coords), test);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(advance, tilecoords) {
|
||||||
|
typedef dk::TileCoords<4> tcoords4;
|
||||||
|
typedef dk::TileCoords<4>::coords coords4;
|
||||||
|
|
||||||
|
{
|
||||||
|
const coords4 max_coords(3);
|
||||||
|
tcoords4 test(max_coords);
|
||||||
|
|
||||||
|
EXPECT_EQ(0, test[0]);
|
||||||
|
EXPECT_EQ(0, test[1]);
|
||||||
|
EXPECT_EQ(0, test[2]);
|
||||||
|
EXPECT_EQ(0, test[3]);
|
||||||
|
|
||||||
|
test += 3;
|
||||||
|
EXPECT_EQ(3, test[0]);
|
||||||
|
EXPECT_EQ(0, test[1]);
|
||||||
|
EXPECT_EQ(0, test[2]);
|
||||||
|
EXPECT_EQ(0, test[3]);
|
||||||
|
|
||||||
|
test += 3;
|
||||||
|
EXPECT_EQ(2, test[0]);
|
||||||
|
EXPECT_EQ(1, test[1]);
|
||||||
|
EXPECT_EQ(0, test[2]);
|
||||||
|
EXPECT_EQ(0, test[3]);
|
||||||
|
|
||||||
|
test += 20;
|
||||||
|
EXPECT_EQ(2, test[0]);
|
||||||
|
EXPECT_EQ(2, test[1]);
|
||||||
|
EXPECT_EQ(1, test[2]);
|
||||||
|
EXPECT_EQ(0, test[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto max_scalar = std::numeric_limits<dk::CoordinateScalarType>::max();
|
||||||
|
ASSERT_EQ(std::numeric_limits<int32_t>::max(), max_scalar);
|
||||||
|
{
|
||||||
|
coords4 max_coords(max_scalar - 10);
|
||||||
|
max_coords[1] -= 1;
|
||||||
|
max_coords[2] -= 2;
|
||||||
|
max_coords[3] -= 3;
|
||||||
|
|
||||||
|
tcoords4 test(coords4(540, 800, 1200, 710), max_coords);
|
||||||
|
test += max_scalar;
|
||||||
|
EXPECT_EQ(549, test[0]);
|
||||||
|
EXPECT_EQ(801, test[1]);
|
||||||
|
EXPECT_EQ(1200, test[2]);
|
||||||
|
EXPECT_EQ(710, test[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const coords4 max_coords(max_scalar, 800, max_scalar, max_scalar);
|
||||||
|
|
||||||
|
tcoords4 test(coords4(max_scalar, 800, 1200, 710), max_coords);
|
||||||
|
test += max_scalar;
|
||||||
|
EXPECT_EQ(2147483646, test[0]);
|
||||||
|
EXPECT_EQ(0, test[1]);
|
||||||
|
EXPECT_EQ(1201, test[2]);
|
||||||
|
EXPECT_EQ(710, test[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
20
tools/calc_advance.rb
Normal file
20
tools/calc_advance.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
M = 2147483647
|
||||||
|
|
||||||
|
def calc(arr, m)
|
||||||
|
v = M
|
||||||
|
index = 0
|
||||||
|
out = arr.dup
|
||||||
|
while (v > 0) do
|
||||||
|
v += arr[index]
|
||||||
|
#puts "index #{index} - v is #{v}, m is #{m[index]}"
|
||||||
|
out[index] = v % (m[index] + 1)
|
||||||
|
v /= (m[index] + 1)
|
||||||
|
index += 1
|
||||||
|
end
|
||||||
|
out
|
||||||
|
end
|
||||||
|
|
||||||
|
p calc([540, 800, 1200, 710], [M - 10, M - 11, M - 12, M - 13])
|
||||||
|
p calc([M, 800, 1200, 710], [M, 800, M, M])
|
Loading…
Add table
Add a link
Reference in a new issue