memory: fast_mod no longer requires a compile-time modulus (but it's still a constexpr function)

This commit is contained in:
Michele Caini
2021-10-08 20:24:07 +02:00
parent 3144cfafd5
commit e4991d367e
4 changed files with 17 additions and 15 deletions

View File

@@ -98,14 +98,13 @@ constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[ma
/**
* @brief Fast module utility function (powers of two only).
* @tparam Value Compile-time page size, it must be a power of two.
* @param value A value for which to calculate the modulus.
* @return Remainder of division.
* @param mod _Modulus_, it must be a power of two.
* @return The common remainder.
*/
template<std::size_t Value>
[[nodiscard]] constexpr std::size_t fast_mod(const std::size_t value) ENTT_NOEXCEPT {
static_assert(is_power_of_two(Value), "Value must be a power of two");
return value & (Value - 1u);
[[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
return value & (mod - 1u);
}
} // namespace entt

View File

@@ -171,13 +171,13 @@ class basic_sparse_set {
[[nodiscard]] auto sparse_ptr(const Entity entt) const {
const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
const auto page = pos / sparse_page_v;
return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod<sparse_page_v>(pos)) : nullptr;
return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, sparse_page_v)) : nullptr;
}
[[nodiscard]] auto &sparse_ref(const Entity entt) const {
ENTT_ASSERT(sparse_ptr(entt), "Invalid element");
const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
return sparse[pos / sparse_page_v][fast_mod<sparse_page_v>(pos)];
return sparse[pos / sparse_page_v][fast_mod(pos, sparse_page_v)];
}
void release_sparse_pages() {
@@ -253,7 +253,7 @@ protected:
std::uninitialized_fill(sparse[page], sparse[page] + sparse_page_v, null);
}
auto &elem = sparse[page][fast_mod<sparse_page_v>(pos)];
auto &elem = sparse[page][fast_mod(pos, sparse_page_v)];
ENTT_ASSERT(entity_traits::to_version(elem) == entity_traits::to_version(tombstone), "Slot not available");
if(free_list == null) {

View File

@@ -123,7 +123,7 @@ public:
[[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
const auto pos = index - 1;
return (*packed)[pos / packed_page_v] + fast_mod<packed_page_v>(pos);
return (*packed)[pos / packed_page_v] + fast_mod(pos, packed_page_v);
}
[[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
@@ -182,7 +182,7 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
[[nodiscard]] auto &element_at(const std::size_t pos) const {
return packed.first()[pos / packed_page_v][fast_mod<packed_page_v>(pos)];
return packed.first()[pos / packed_page_v][fast_mod(pos, packed_page_v)];
}
auto assure_at_least(const std::size_t pos) {
@@ -204,7 +204,7 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
}
}
return container[idx] + fast_mod<packed_page_v>(pos);
return container[idx] + fast_mod(pos, packed_page_v);
}
void release_unused_pages() {

View File

@@ -65,7 +65,10 @@ TEST(Memory, NextPowerOfTwo) {
}
TEST(Memory, FastMod) {
ASSERT_EQ(entt::fast_mod<8u>(0u), 0u);
ASSERT_EQ(entt::fast_mod<8u>(7u), 7u);
ASSERT_EQ(entt::fast_mod<8u>(8u), 0u);
// constexpr-ness guaranteed
constexpr auto fast_mod_of_zero = entt::fast_mod(0u, 8u);
ASSERT_EQ(fast_mod_of_zero, 0u);
ASSERT_EQ(entt::fast_mod(7u, 8u), 7u);
ASSERT_EQ(entt::fast_mod(8u, 8u), 0u);
}