implement resize functions

This commit is contained in:
Liss Heidrich
2025-03-19 09:12:42 +01:00
committed by Martin Leitner-Ankerl
parent cac780fe97
commit 5dbcfc7650
2 changed files with 121 additions and 0 deletions

View File

@@ -701,6 +701,15 @@ private:
return (capacity + num_elements_in_block - 1U) / num_elements_in_block;
}
void resize_shrink(size_t new_size) {
if constexpr (!std::is_trivially_destructible_v<T>) {
for (size_t ix = new_size; ix < m_size; ++ix) {
operator[](ix).~T();
}
}
m_size = new_size;
}
public:
segmented_vector() = default;
@@ -813,6 +822,30 @@ public:
}
}
void resize(size_t const count) {
if (count < m_size) {
resize_shrink(count);
} else if (count > m_size) {
size_t const new_elems = count - m_size;
reserve(count);
for (size_t ix = 0; ix < new_elems; ++ix) {
emplace_back();
}
}
}
void resize(size_t const count, value_type const& value) {
if (count < m_size) {
resize_shrink(count);
} else if (count > m_size) {
size_t const new_elems = count - m_size;
reserve(count);
for (size_t ix = 0; ix < new_elems; ++ix) {
emplace_back(value);
}
}
}
[[nodiscard]] auto get_allocator() const -> allocator_type {
return allocator_type{m_blocks.get_allocator()};
}

View File

@@ -101,6 +101,94 @@ TEST_CASE("segmented_vector_reserve") {
REQUIRE(counts.size() == 3);
}
TEST_CASE("segmented_vector_resize") {
auto counts = counts_for_allocator{};
auto vec = ankerl::unordered_dense::segmented_vector<int, counting_allocator<int>, sizeof(int) * 16>(&counts);
REQUIRE(vec.size() == 0);
REQUIRE(vec.capacity() == 0);
REQUIRE(counts.size() < 2);
// noop resize
vec.resize(0);
REQUIRE(vec.size() == 0);
REQUIRE(vec.capacity() == 0);
REQUIRE(counts.size() < 2);
// size-increase resize
vec.resize(1100);
REQUIRE(vec.size() == 1100);
REQUIRE(vec.capacity() == 1104);
REQUIRE(counts.size() > 63);
counts.reset();
for (size_t ix = 0; ix < 1100; ++ix) {
REQUIRE(vec[ix] == 0);
}
// size-decrease resize
vec.resize(500);
REQUIRE(vec.size() == 500);
REQUIRE(vec.capacity() == 1104);
REQUIRE(counts.size() == 0);
for (size_t ix = 0; ix < 500; ++ix) {
REQUIRE(vec[ix] == 0);
}
// noop resize
vec.resize(500, 123);
REQUIRE(vec.size() == 500);
REQUIRE(vec.capacity() == 1104);
REQUIRE(counts.size() == 0);
for (size_t ix = 0; ix < 500; ++ix) {
REQUIRE(vec[ix] == 0);
}
// size-increase resize (no alloc)
vec.resize(1100, 123);
REQUIRE(vec.size() == 1100);
REQUIRE(vec.capacity() == 1104);
REQUIRE(counts.size() == 0);
for (size_t ix = 0; ix < 500; ++ix) {
REQUIRE(vec[ix] == 0);
}
for (size_t ix = 500; ix < 1100; ++ix) {
REQUIRE(vec[ix] == 123);
}
// size-increase resize (alloc)
vec.resize(2000, 42);
REQUIRE(vec.size() == 2000);
REQUIRE(vec.capacity() == 2000);
REQUIRE(counts.size() > 50);
counts.reset();
for (size_t ix = 0; ix < 500; ++ix) {
REQUIRE(vec[ix] == 0);
}
for (size_t ix = 500; ix < 1100; ++ix) {
REQUIRE(vec[ix] == 123);
}
for (size_t ix = 1100; ix < 2000; ++ix) {
REQUIRE(vec[ix] == 42);
}
// size-decrease resize
vec.resize(800, 99);
REQUIRE(vec.size() == 800);
REQUIRE(vec.capacity() == 2000);
REQUIRE(counts.size() == 0);
for (size_t ix = 0; ix < 500; ++ix) {
REQUIRE(vec[ix] == 0);
}
for (size_t ix = 500; ix < 800; ++ix) {
REQUIRE(vec[ix] == 123);
}
}
using vec_t = ankerl::unordered_dense::segmented_vector<counter::obj>;
static_assert(sizeof(vec_t) == sizeof(std::vector<counter::obj*>) + sizeof(size_t));