From 4ac651c1295a3889c5c0efd09a13e2f80d57a370 Mon Sep 17 00:00:00 2001 From: Tomas Maly Date: Thu, 11 Jan 2024 02:32:19 +0100 Subject: [PATCH] FlatBag using hashmap --- sources/include/cage-core/flatBag.h | 73 ++++++++++------------------- sources/include/cage-core/flatSet.h | 2 - sources/test-core/flatBag.cpp | 49 +------------------ 3 files changed, 27 insertions(+), 97 deletions(-) diff --git a/sources/include/cage-core/flatBag.h b/sources/include/cage-core/flatBag.h index 38a81872..90148f1e 100644 --- a/sources/include/cage-core/flatBag.h +++ b/sources/include/cage-core/flatBag.h @@ -1,9 +1,10 @@ #ifndef guard_flatBag_sezik4edrt5 #define guard_flatBag_sezik4edrt5 -#include // lower_bound, binary_search #include +#include + #include namespace cage @@ -19,67 +20,46 @@ namespace cage constexpr void insert(const Value &value) { - CAGE_ASSERT(count(value) == 0); + if (indices.count(value)) + return; + indices[value] = data_.size(); data_.push_back(value); - unsorted++; - if (unsorted > 100) - { - std::sort(data_.begin(), data_.end()); - sorted = data_.size(); - unsorted = 0; - } } constexpr uintPtr erase(const Value &value) { - CAGE_ASSERT(sorted + unsorted == data_.size()); - if (unsorted > 0) - { - auto it = std::find(data_.begin() + sorted, data_.end(), value); - if (it != data_.end()) - { - std::swap(*it, data_.back()); - data_.pop_back(); - unsorted--; - return 1; - } - } - if (sorted > 0) + auto it = indices.find(value); + if (it == indices.end()) + return 0; + const uintPtr off = it->second; + indices.erase(it); + if (off + 1 != data_.size()) { - auto it = std::lower_bound(data_.begin(), data_.begin() + sorted, value); - if (it == data_.begin() + sorted) - return 0; - if (*it != value) - return 0; - std::copy_n(it + 1, data_.end() - it - 1, it); - data_.pop_back(); - sorted--; - return 1; + indices[data_.back()] = off; + std::swap(data_[off], data_.back()); } - return 0; + data_.pop_back(); + return 1; } constexpr void clear() { + indices.clear(); data_.clear(); - sorted = unsorted = 0; } - constexpr void reserve(uintPtr s) { data_.reserve(s); } + constexpr void reserve(uintPtr s) + { + indices.reserve(s); + data_.reserve(s); + } constexpr const_iterator find(const Value &value) const { - CAGE_ASSERT(sorted + unsorted == data_.size()); - CAGE_ASSERT(std::is_sorted(data_.begin(), data_.begin() + sorted)); - auto it = std::find(data_.begin() + sorted, data_.end(), value); - if (it != data_.end()) - return it; - it = std::lower_bound(data_.begin(), data_.begin() + sorted, value); - if (it == data_.begin() + sorted) + auto it = indices.find(value); + if (it == indices.end()) return data_.end(); - if (*it == value) - return it; - return data_.end(); + return data_.begin() + it->second; } constexpr uintPtr count(const Value &value) const { return find(value) == end() ? 0 : 1; } @@ -94,14 +74,11 @@ namespace cage constexpr const_iterator end() const noexcept { return data_.end(); } - constexpr const std::vector &unsafeData() const noexcept { return data_; } - constexpr std::vector &unsafeData() noexcept { return data_; } private: + ankerl::unordered_dense::map indices; std::vector data_; - uintPtr sorted = 0; - uintPtr unsorted = 0; }; } diff --git a/sources/include/cage-core/flatSet.h b/sources/include/cage-core/flatSet.h index 870ff1b1..ff16d45b 100644 --- a/sources/include/cage-core/flatSet.h +++ b/sources/include/cage-core/flatSet.h @@ -113,8 +113,6 @@ namespace cage constexpr const_reverse_iterator rend() const noexcept { return data_.rend(); } - constexpr const std::vector &unsafeData() const noexcept { return data_; } - constexpr std::vector &unsafeData() noexcept { return data_; } private: diff --git a/sources/test-core/flatBag.cpp b/sources/test-core/flatBag.cpp index 34f65ce5..eb511d60 100644 --- a/sources/test-core/flatBag.cpp +++ b/sources/test-core/flatBag.cpp @@ -3,24 +3,7 @@ #include #include #include - -namespace -{ - constexpr uint32 testConstexpr() - { - FlatBag s; - s.insert("hello"); - s.insert("there"); - s.insert("Obi-Wan"); - s.insert("Kenobi"); - s.insert("says"); - s.insert("how"); - s.insert("are"); - s.insert("you"); - s.erase("bro"); - return s.size(); - } -} +#include void testFlatBag() { @@ -34,7 +17,7 @@ void testFlatBag() s.insert(1024); s.insert(42); CAGE_TEST(s.size() == 3); - CAGE_TEST_ASSERTED(s.insert(1024)); + s.insert(42); CAGE_TEST(s.size() == 3); CAGE_TEST(s.count(20) == 0); CAGE_TEST(s.count(42) == 1); @@ -71,31 +54,10 @@ void testFlatBag() s.insert(1024); s.insert(13); s.insert(42); - CAGE_TEST_ASSERTED(s.insert(1024)); PointerRange pr = s; CAGE_TEST(pr.size() == 3); } - { - CAGE_TESTCASE("custom struct"); - - struct Custom - { - uint32 v = m; - constexpr explicit Custom(uint32 v) : v(v) {} - constexpr bool operator<(const Custom &b) const noexcept { return v < b.v; } - constexpr bool operator==(const Custom &b) const noexcept { return v == b.v; } - }; - - FlatBag s; - s.insert(Custom(1024)); - s.insert(Custom(13)); - s.insert(Custom(42)); - CAGE_TEST(s.size() == 3); - CAGE_TEST(s.count(Custom(20)) == 0); - CAGE_TEST(s.count(Custom(42)) == 1); - } - { CAGE_TESTCASE("find"); @@ -122,13 +84,6 @@ void testFlatBag() CAGE_TEST(s.count(42) == 0); } - { - CAGE_TESTCASE("constexpr"); - constexpr const uint32 a = testConstexpr(); - uint32 b = testConstexpr(); - CAGE_TEST(a == b); - } - { CAGE_TESTCASE("randomized");