From 7b40d001ec2578906ef09066301b6c39d4a60711 Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Tue, 8 Oct 2024 07:20:41 +0300 Subject: [PATCH] stable vector fix for algorithm. Still no correct Iterator. --- .../Data/Containers/BinSearchArrayMap.hpp | 6 +- .../Data/Containers/StableVector.hpp | 104 ++++- tests/BinSearchArrayMapTest.cpp | 100 ++--- tests/StableVectorTest.cpp | 372 +++++++++--------- 4 files changed, 316 insertions(+), 266 deletions(-) diff --git a/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp b/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp index 00ba69a..2a525a7 100644 --- a/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp +++ b/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp @@ -54,7 +54,7 @@ namespace OpenVulkano V& Get(const K key) { return FindPair(key).second; } - Pair& FindPair(const K key) + Pair& FindPair(const K key) { size_t low = 0; size_t high = m_data.size(); @@ -76,7 +76,7 @@ namespace OpenVulkano high = mid - 1; } } - + throw std::runtime_error("Key not found."); } @@ -106,7 +106,7 @@ namespace OpenVulkano return -1; } - bool Contains(const K key) const noexcept + bool Contains(const K key) noexcept { size_t low = 0; size_t high = m_data.size(); diff --git a/openVulkanoCpp/Data/Containers/StableVector.hpp b/openVulkanoCpp/Data/Containers/StableVector.hpp index f42c313..fbac15a 100644 --- a/openVulkanoCpp/Data/Containers/StableVector.hpp +++ b/openVulkanoCpp/Data/Containers/StableVector.hpp @@ -52,7 +52,7 @@ namespace OpenVulkano ~VectorChunk() { - for (size_t i = 0; i < m_size; i++) + for (size_t i = 0; i < m_capacity; i++) { if (m_occupiedIndices[i]) { @@ -65,13 +65,13 @@ namespace OpenVulkano size_t GetRealIndex(size_t reqIndex) { - if (m_gapCount == 0) + if (m_gapCount == 0 || reqIndex == 0) { return reqIndex; } size_t gapCount = 0; - for (size_t i = 0; i < reqIndex; i++) + for (size_t i = 0; i <= reqIndex; i++) { if (!m_occupiedIndices[i]) { @@ -93,6 +93,8 @@ namespace OpenVulkano return m_data[i]; } } + + throw std::out_of_range("Index out of range"); } size_t GetLastOccupiedIndex() @@ -115,8 +117,17 @@ namespace OpenVulkano public: Iterator(VectorChunk* chunk, size_t index) : m_chunk(chunk), m_index(index) {} - T& operator*() { return m_chunk->GetAlignedData(m_index); } - T* operator->() { return &m_chunk->GetAlignedData(m_index); } + T& operator*() + { + auto realIndex = m_chunk->GetRealIndex(m_index); + return m_chunk->GetAlignedData(m_index); + } + + T* operator->() + { + auto realIndex = m_chunk->GetRealIndex(m_index); + return &m_chunk->GetAlignedData(m_index); + } Iterator& operator++() { @@ -174,13 +185,30 @@ namespace OpenVulkano return m_chunk != other.m_chunk || m_index != other.m_index; } + size_t GetIndex() const { return m_index; } + size_t GetChunk() const { return m_chunk; } + protected: void MoveToNextChunk() { - while (m_chunk && m_index > m_chunk->m_size) + while (m_chunk && (m_index > m_chunk->m_size || !m_chunk->m_occupiedIndices[m_index])) + { + if (m_index >= m_chunk->m_size) + { + m_chunk = m_chunk->m_next; + m_index = 0; + } + else + { + ++m_index; + } + } + + if (m_chunk && m_index >= m_chunk->m_size) { - m_index -= m_chunk->m_size; m_chunk = m_chunk->m_next; + m_index = 0; + MoveToNextChunk(); } } @@ -264,10 +292,9 @@ namespace OpenVulkano VectorChunk* currentChunk = m_FirstChunk; while (currentChunk) { - VectorChunk* nextChunk = currentChunk->m_next; - currentChunk->~VectorChunk(); - ::operator delete(currentChunk); - currentChunk = nextChunk; + VectorChunk* temp = currentChunk; + currentChunk = currentChunk->m_next; + delete temp; } } @@ -276,6 +303,7 @@ namespace OpenVulkano if (m_LastChunk->m_nextIndex == m_LastChunk->m_capacity) { VectorChunk* newChunk = Grow(m_LastChunk->m_capacity * GROW_FACTOR); + m_Capacity += m_LastChunk->m_capacity * GROW_FACTOR; m_LastChunk->m_next = newChunk; newChunk->m_prev = m_LastChunk; m_LastChunk = newChunk; @@ -296,6 +324,7 @@ namespace OpenVulkano if (m_LastChunk->m_nextIndex == m_LastChunk->m_capacity) { VectorChunk* newChunk = Grow(m_LastChunk->m_capacity * GROW_FACTOR); + m_Capacity += m_LastChunk->m_capacity * GROW_FACTOR; m_LastChunk->m_next = newChunk; newChunk->m_prev = m_LastChunk; m_LastChunk = newChunk; @@ -358,6 +387,8 @@ namespace OpenVulkano } } } + + currentChunk = currentChunk->m_next; } PushBack(std::move(value)); @@ -368,6 +399,7 @@ namespace OpenVulkano if (m_LastChunk->m_nextIndex == m_LastChunk->m_capacity) { VectorChunk* newChunk = Grow(m_LastChunk->m_capacity * GROW_FACTOR); + m_Capacity += m_LastChunk->m_capacity * GROW_FACTOR; m_LastChunk->m_next = newChunk; newChunk->m_prev = m_LastChunk; m_LastChunk = newChunk; @@ -404,6 +436,8 @@ namespace OpenVulkano } } } + + currentChunk = currentChunk->m_next; } EmplaceBack(std::forward(args)...); @@ -416,6 +450,15 @@ namespace OpenVulkano return; // return? or make } + if (m_LastChunk->m_nextIndex == -1) + { + VectorChunk* temp = m_LastChunk; + m_LastChunk = m_LastChunk->m_prev; + m_LastChunk->m_next = nullptr; + temp->~VectorChunk(); + ::operator delete(temp); + } + m_LastChunk->m_data[m_LastChunk->m_nextIndex - 1].~T(); m_LastChunk->m_occupiedIndices[m_LastChunk->m_nextIndex - 1] = false; m_LastChunk->m_nextIndex--; @@ -480,9 +523,9 @@ namespace OpenVulkano VectorChunk* currentChunk = m_FirstChunk; while (currentChunk) { - if (index + currentChunk->m_size > it.m_index) + if (index + currentChunk->m_size > it.GetIndex()) { - size_t realIndex = currentChunk->GetRealIndex(it.m_index); + size_t realIndex = currentChunk->GetRealIndex(it.GetIndex()); currentChunk->m_data[realIndex].~T(); currentChunk->m_occupiedIndices[realIndex] = false; currentChunk->m_size--; @@ -496,7 +539,7 @@ namespace OpenVulkano } } - T& operator[](size_t index) { return At(index); } + T& operator[](size_t index) noexcept { return At(index); } T& At(size_t index) { if (index >= m_Size) [[unlikely]] @@ -508,6 +551,39 @@ namespace OpenVulkano return handle.first->GetAlignedData(handle.second); } + bool Contains(size_t index) noexcept + { + if (index >= m_Size) + { + return false; + } + + auto handle = FindChunk(index); + return handle.first->m_occupiedIndices[handle.second]; + } + + /// std version of contains + bool contains(size_t index) noexcept { return Contains(index); } + + void Clear() + { + VectorChunk* currentChunk = m_FirstChunk; + while (currentChunk) + { + VectorChunk* nextChunk = currentChunk->m_next; + delete currentChunk; + currentChunk = nextChunk; + } + + m_FirstChunk = Grow(DEFAULT_CHUNK_SIZE); + m_LastChunk = m_FirstChunk; + m_Capacity = DEFAULT_CHUNK_SIZE; + m_Size = 0; + } + + /// std version of clear + void clear() { Clear(); } + /// std version of at T& at(size_t index) { return At(index); } diff --git a/tests/BinSearchArrayMapTest.cpp b/tests/BinSearchArrayMapTest.cpp index 64813df..2df828d 100644 --- a/tests/BinSearchArrayMapTest.cpp +++ b/tests/BinSearchArrayMapTest.cpp @@ -45,69 +45,43 @@ TEST_CASE("BinSearchArrayMap With Default") map.Remove(16); map.Remove(23); map.Remove(48); - - REQUIRE(map[49] == "49"); - - printf("ARRAY WITH DEFAULT\n"); - for (int i = 0; i < 50; i++) - { - if (map.Contains(i)) - { - printf("index: %d, value: %s\n", i, map[i].c_str()); - } - else - { - printf("index: %d, value: %s\n", i, "EMPTY"); - } - } } } -//TEST_CASE("BinSearchArrayMap With StableVector") -//{ -// SECTION("Insert") -// { -// BinSearchArrayMap map; -// -// for (int i = 0; i < 50; i++) -// { -// map.Insert(i, std::to_string(i)); -// } -// -// REQUIRE(map.Size() == 50); -// REQUIRE(map.Get(16) == "16"); -// REQUIRE(map.Get(23) == "23"); -// REQUIRE(map.Get(48) == "48"); -// } -// -// SECTION("Remove") -// { -// BinSearchArrayMap map; -// -// for (int i = 0; i < 50; i++) -// { -// map.Insert(i, std::to_string(i)); -// } -// -// map.Remove(16); -// map.Remove(23); -// -// if (map.Contains(49)) -// { -// printf("index: %d, value: %s\n", 49, map[49].c_str()); -// } -// -// printf("ARRAY WITH STABLE VECTOR\n"); -// for (int i = 0; i < 50; i++) -// { -// if (map.Contains(i)) -// { -// printf("index: %d, value: %s\n", i, map[i].c_str()); -// } -// else -// { -// printf("index: %d, value: %s\n", i, "EMPTY"); -// } -// } -// } -//} \ No newline at end of file +TEST_CASE("BinSearchArrayMap With StableVector") +{ + SECTION("Insert") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Insert(i, std::to_string(i)); + } + + REQUIRE(map.Size() == 50); + REQUIRE(map.Get(16) == "16"); + REQUIRE(map.Get(23) == "23"); + REQUIRE(map.Get(48) == "48"); + } + + SECTION("Remove") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Insert(i, std::to_string(i)); + } + + map.Remove(16); + map.Remove(23); + map.Remove(48); + + printf("ARRAY WITH STABLE VECTOR\n"); + for (int i = 0; i < 50; i++) + { + printf("index: %d, value: %s\n", i, map[i].c_str()); + } + } +} \ No newline at end of file diff --git a/tests/StableVectorTest.cpp b/tests/StableVectorTest.cpp index 0cdb5f2..d0efb35 100644 --- a/tests/StableVectorTest.cpp +++ b/tests/StableVectorTest.cpp @@ -4,189 +4,189 @@ using namespace OpenVulkano; -//struct Test -//{ -// uint32_t mValue; -// Test(uint32_t value) : mValue(value) {} -// Test() : mValue(0) {} -//}; -// -//static int incrementCounter = 0; -//static int decrementCounter = 0; -// -//struct TestCount -//{ -// TestCount() : m_value("") { ++incrementCounter; } -// TestCount(const std::string& val) : m_value(val) { ++incrementCounter; } -// TestCount(TestCount&& other) noexcept : m_value(std::move(other.m_value)) { ++incrementCounter; } -// TestCount(const TestCount& other) : m_value(other.m_value) { ++incrementCounter; } -// -// TestCount& operator=(const TestCount& other) -// { -// m_value = other.m_value; -// return *this; -// } -// -// TestCount& operator=(TestCount&& other) noexcept -// { -// m_value = std::move(other.m_value); -// return *this; -// } -// -// ~TestCount() { ++decrementCounter; } -// -// std::string m_value; -//}; -// -//TEST_CASE("ChunkVector") -//{ -// SECTION("PushBack") -// { -// StableVector vec; -// -// REQUIRE(vec.Size() == 0); -// REQUIRE(vec.Capacity() == 32); -// -// for (uint32_t i = 0; i < 100; ++i) -// { -// vec.PushBack(i); -// } -// -// REQUIRE(vec.Size() == 100); -// REQUIRE(vec.Capacity() == 224); // 32 + 64 + 128 = 3 | previous chunk size multiplied by 2 -// } -// -// SECTION("EmplaceBack") -// { -// StableVector vec; -// -// REQUIRE(vec.Size() == 0); -// REQUIRE(vec.Capacity() == 32); -// -// for (uint32_t i = 0; i < 100; ++i) -// { -// vec.EmplaceBack(i); -// } -// -// REQUIRE(vec.Size() == 100); -// -// for (uint32_t i = 0; i < 100; ++i) -// { -// REQUIRE(vec[i].mValue == i); -// } -// } -// -// SECTION("PopBack") -// { -// StableVector vec; -// -// REQUIRE(vec.Size() == 0); -// REQUIRE(vec.Capacity() == 32); -// -// for (uint32_t i = 0; i < 100; ++i) -// { -// vec.PushBack(i); -// } -// -// REQUIRE(vec.Size() == 100); -// -// uint64_t tempVal = vec.Capacity(); -// -// for (uint32_t i = 0; i < 50; ++i) -// { -// vec.PopBack(); -// } -// -// REQUIRE(vec.Size() == 50); -// REQUIRE(vec.Capacity() == tempVal); -// } -// -// SECTION("Clear") -// { -// StableVector vec; -// -// REQUIRE(vec.Size() == 0); -// REQUIRE(vec.Capacity() == 32); -// -// for (uint32_t i = 0; i < 100; ++i) -// { -// vec.PushBack(i); -// } -// -// REQUIRE(vec.Size() == 100); -// -// vec.Clear(); -// -// REQUIRE(vec.Size() == 0); -// REQUIRE(vec.Capacity() == 32); -// } -// -// SECTION("Add/Fill") -// { -// StableVector vec; -// -// REQUIRE(vec.Size() == 0); -// REQUIRE(vec.Capacity() == 32); -// -// for (uint32_t i = 0; i < 100; ++i) -// { -// vec.PushBack("a"); -// } -// -// REQUIRE(vec.Size() == 100); -// -// vec.Remove(56); -// REQUIRE(vec[56] == "a"); -// -// vec.Add("z"); -// -// REQUIRE(vec.Size() == 100); -// REQUIRE(vec[56] == "z"); -// } -// -// SECTION("Correct Initialization") -// { -// StableVector vec; -// -// REQUIRE(incrementCounter == 0); -// REQUIRE(decrementCounter == 0); -// -// vec.EmplaceBack("a"); -// -// REQUIRE(incrementCounter == 1); -// REQUIRE(decrementCounter == 0); -// -// vec.PushBack(TestCount("b")); -// -// REQUIRE(incrementCounter == 3); -// REQUIRE(decrementCounter == 1); -// -// TestCount testClass = TestCount("c"); -// vec.PushBack(std::move(testClass)); -// -// REQUIRE(incrementCounter == 5); -// REQUIRE(decrementCounter == 1); -// -// vec.Clear(); -// -// REQUIRE(incrementCounter == 5); -// REQUIRE(decrementCounter == 4); -// -// vec.PushBack(TestCount("d")); -// -// REQUIRE(incrementCounter == 7); -// REQUIRE(decrementCounter == 5); -// -// TestCount testClass2 = TestCount("e"); -// vec.PushBack(testClass2); -// -// REQUIRE(incrementCounter == 9); -// REQUIRE(decrementCounter == 5); -// } -// -// SECTION("Out of scope check") -// { -// REQUIRE(incrementCounter == 9); -// REQUIRE(decrementCounter == 9); -// } -//} +struct Test +{ + uint32_t mValue; + Test(uint32_t value) : mValue(value) {} + Test() : mValue(0) {} +}; + +static int incrementCounter = 0; +static int decrementCounter = 0; + +struct TestCount +{ + TestCount() : m_value("") { ++incrementCounter; } + TestCount(const std::string& val) : m_value(val) { ++incrementCounter; } + TestCount(TestCount&& other) noexcept : m_value(std::move(other.m_value)) { ++incrementCounter; } + TestCount(const TestCount& other) : m_value(other.m_value) { ++incrementCounter; } + + TestCount& operator=(const TestCount& other) + { + m_value = other.m_value; + return *this; + } + + TestCount& operator=(TestCount&& other) noexcept + { + m_value = std::move(other.m_value); + return *this; + } + + ~TestCount() { ++decrementCounter; } + + std::string m_value; +}; + +TEST_CASE("ChunkVector") +{ + SECTION("PushBack") + { + StableVector vec; + + REQUIRE(vec.Size() == 0); + REQUIRE(vec.Capacity() == 32); + + for (uint32_t i = 0; i < 100; ++i) + { + vec.PushBack(i); + } + + REQUIRE(vec.Size() == 100); + REQUIRE(vec.Capacity() == 224); // 32 + 64 + 128 = 3 | previous chunk size multiplied by 2 + } + + SECTION("EmplaceBack") + { + StableVector vec; + + REQUIRE(vec.Size() == 0); + REQUIRE(vec.Capacity() == 32); + + for (uint32_t i = 0; i < 100; ++i) + { + vec.EmplaceBack(i); + } + + REQUIRE(vec.Size() == 100); + + for (uint32_t i = 0; i < 100; ++i) + { + REQUIRE(vec[i].mValue == i); + } + } + + SECTION("PopBack") + { + StableVector vec; + + REQUIRE(vec.Size() == 0); + REQUIRE(vec.Capacity() == 32); + + for (uint32_t i = 0; i < 100; ++i) + { + vec.PushBack(i); + } + + REQUIRE(vec.Size() == 100); + + uint64_t tempVal = vec.Capacity(); + + for (uint32_t i = 0; i < 50; ++i) + { + vec.PopBack(); + } + + REQUIRE(vec.Size() == 50); + REQUIRE(vec.Capacity() == tempVal); + } + + SECTION("Clear") + { + StableVector vec; + + REQUIRE(vec.Size() == 0); + REQUIRE(vec.Capacity() == 32); + + for (uint32_t i = 0; i < 100; ++i) + { + vec.PushBack(i); + } + + REQUIRE(vec.Size() == 100); + + vec.Clear(); + + REQUIRE(vec.Size() == 0); + REQUIRE(vec.Capacity() == 32); + } + + SECTION("Add/Fill") + { + StableVector vec; + + REQUIRE(vec.Size() == 0); + REQUIRE(vec.Capacity() == 32); + + for (uint32_t i = 0; i < 100; ++i) + { + vec.PushBack("a"); + } + + REQUIRE(vec.Size() == 100); + + vec.Remove(56); + REQUIRE(vec[56] == "a"); + + vec.Push("z"); + + REQUIRE(vec.Size() == 100); + REQUIRE(vec[56] == "z"); + } + + SECTION("Correct Initialization") + { + StableVector vec; + + REQUIRE(incrementCounter == 0); + REQUIRE(decrementCounter == 0); + + vec.EmplaceBack("a"); + + REQUIRE(incrementCounter == 1); + REQUIRE(decrementCounter == 0); + + vec.PushBack(TestCount("b")); + + REQUIRE(incrementCounter == 3); + REQUIRE(decrementCounter == 1); + + TestCount testClass = TestCount("c"); + vec.PushBack(std::move(testClass)); + + REQUIRE(incrementCounter == 5); + REQUIRE(decrementCounter == 1); + + vec.Clear(); + + REQUIRE(incrementCounter == 5); + REQUIRE(decrementCounter == 4); + + vec.PushBack(TestCount("d")); + + REQUIRE(incrementCounter == 7); + REQUIRE(decrementCounter == 5); + + TestCount testClass2 = TestCount("e"); + vec.PushBack(testClass2); + + REQUIRE(incrementCounter == 9); + REQUIRE(decrementCounter == 5); + } + + SECTION("Out of scope check") + { + REQUIRE(incrementCounter == 9); + REQUIRE(decrementCounter == 9); + } +}