Created
November 29, 2018 01:37
-
-
Save laverdet/4df73535c8c11034ae3909fb00671fe5 to your computer and use it in GitHub Desktop.
screeps local matrix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Matrix of any type which holds a value for each position in a room | |
template <typename Type, typename Store, size_t Pack, bool Packed = sizeof(Store) << 3 != Pack> | |
class local_matrix_store_t {}; | |
template <typename Type, typename Store, size_t Pack> | |
class local_matrix_store_t<Type, Store, Pack, false> { | |
protected: | |
std::array<Store, 2500> costs; | |
using reference = Type&; | |
using const_reference = typename std::conditional<std::is_trivial<Type>::value && sizeof(Type) <= sizeof(size_t), Type, const Type&>::type; | |
public: | |
constexpr local_matrix_store_t() = default; | |
constexpr local_matrix_store_t(Type value) { | |
fill(value); | |
} | |
constexpr void fill(Type value) { | |
std::fill(costs.begin(), costs.end(), value); | |
} | |
constexpr reference operator[](int index) { | |
return costs[index]; | |
} | |
constexpr const_reference operator[](int index) const { | |
return costs[index]; | |
} | |
constexpr Store* data() { | |
return costs.data(); | |
} | |
constexpr const Store* data() const { | |
return costs.data(); | |
} | |
}; | |
// Backing store for local_matrix_t which can bitpack 1, 2, or 4 bits into a matrix | |
template <typename Type, typename Store, size_t Pack> | |
class local_matrix_store_t<Type, Store, Pack, true> { | |
protected: | |
static constexpr uint8_t log2(size_t value) { | |
return value == 1 ? 0 : (1 + log2(value >> 1)); | |
} | |
static constexpr uint8_t StoreBits = sizeof(Store) << 3; | |
static constexpr uint8_t IndexShift = log2(StoreBits / Pack); | |
static constexpr uint8_t IndexMask = StoreBits / Pack - 1; | |
static constexpr uint8_t IndexBitShift = log2(Pack); | |
static constexpr Store Mask = (1 << Pack) - 1; | |
static_assert(StoreBits >= Pack, "sizeof(Store) must be greater than or equal to pack bits"); | |
static_assert(StoreBits % Pack == 0, "Store is not aligned to pack bits"); | |
std::array<Store, (2500 * Pack + StoreBits / Pack) / StoreBits> costs; | |
class reference { | |
private: | |
Store& ref; | |
int bit_pos; | |
public: | |
constexpr reference(int bit_pos, Store& ref) : ref(ref), bit_pos(bit_pos) {} | |
constexpr operator Type() const { | |
return (ref >> bit_pos) & Mask; | |
} | |
constexpr const reference& operator=(Type value) const { | |
ref = (ref & ~(Mask << bit_pos)) | ((value & Mask) << bit_pos); | |
return *this; | |
} | |
}; | |
using const_reference = Type; | |
public: | |
constexpr local_matrix_store_t() { | |
// Explicitly assign final data entry because otherwise it could be anything and .data() would | |
// be inconsistent | |
costs.back() = 0; | |
} | |
constexpr local_matrix_store_t(Type value) { | |
costs.back() = 0; | |
fill(value); | |
} | |
constexpr void fill(Type value) { | |
Store packed{}; | |
for (int ii = 0; ii < StoreBits; ii += Pack) { | |
packed <<= Pack; | |
packed |= value & Mask; | |
} | |
costs.fill(packed); | |
} | |
constexpr reference operator[](int index) { | |
return {(index & IndexMask) << IndexBitShift, costs[index >> IndexShift]}; | |
} | |
constexpr const_reference operator[](int index) const { | |
return (costs[index >> IndexShift] >> ((index & IndexMask) << IndexBitShift)) & Mask; | |
} | |
constexpr Store* data() { | |
return costs.data(); | |
} | |
constexpr const Store* data() const { | |
return costs.data(); | |
} | |
}; | |
// Extra methods on top of the backing store which accept local_position_t or xx/yy coords | |
template < | |
typename Type, | |
typename Store = typename std::conditional<std::is_same<Type, bool>::value, uint32_t, Type>::type, | |
size_t Pack = std::conditional< | |
std::is_same<Type, bool>::value, | |
std::integral_constant<size_t, 1>, | |
std::integral_constant<size_t, sizeof(Store) << 3> | |
>::type::value | |
> | |
class local_matrix_t : public local_matrix_store_t<Type, Store, Pack> { | |
public: | |
using local_matrix_store_t<Type, Store, Pack>::local_matrix_store_t; | |
using local_matrix_store_t<Type, Store, Pack>::operator[]; | |
using reference = typename local_matrix_store_t<Type, Store, Pack>::reference; | |
using const_reference = typename local_matrix_store_t<Type, Store, Pack>::const_reference; | |
constexpr reference get(int xx, int yy) { | |
return (*this)[xx * 50 + yy]; | |
} | |
constexpr const_reference get(int xx, int yy) const { | |
return (*this)[xx * 50 + yy]; | |
} | |
constexpr void set(int xx, int yy, Type cost) { | |
(*this)[xx * 50 + yy] = cost; | |
} | |
constexpr reference operator[](local_position_t pos) { | |
return get(pos.xx, pos.yy); | |
} | |
constexpr const_reference operator[](local_position_t pos) const { | |
return get(pos.xx, pos.yy); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment