From b5592cb1813f2af3d2c7c56ae874e67c023644a9 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 8 Dec 2023 23:12:14 +0100 Subject: workaround bug with push_heap _GLIBCXX_DEBUG --- compat/heap.hpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 compat/heap.hpp (limited to 'compat') diff --git a/compat/heap.hpp b/compat/heap.hpp new file mode 100644 index 00000000..e9cac8cf --- /dev/null +++ b/compat/heap.hpp @@ -0,0 +1,87 @@ +#pragma once + +#if defined __GLIBCXX__ && defined _GLIBCXX_DEBUG +#include +#include +// regular STL implementation stripped of debug code +namespace floormat::Heap { + +template +inline void _push_heap(It first, + std::iter_difference_t holeIndex, + std::iter_difference_t topIndex, + std::iter_value_t value, + Compare& comp) +{ + std::iter_difference_t parent = (holeIndex - 1) / 2; + while (holeIndex > topIndex && comp(*(first + parent), value)) + { + *(first + holeIndex) = std::move(*(first + parent)); + holeIndex = parent; + parent = (holeIndex - 1) / 2; + } + *(first + holeIndex) = std::move(value); +} + +template +void push_heap(It first, It last, Compare comp) +{ + _push_heap(first, + std::iter_difference_t((last - first) - 1), + std::iter_difference_t(0), + std::move(*(last - 1)), + comp); +} + +template +void _adjust_heap(It first, + std::iter_difference_t holeIndex, + std::iter_difference_t len, + std::iter_value_t value, + Compare& comp) +{ + const auto topIndex = holeIndex; + auto secondChild = holeIndex; + while (secondChild < (len - 1) / 2) + { + secondChild = 2 * (secondChild + 1); + if (comp(*(first + secondChild), *(first + (secondChild - 1)))) + secondChild--; + *(first + holeIndex) = std::move(*(first + secondChild)); + holeIndex = secondChild; + } + if ((len & 1) == 0 && secondChild == (len - 2) / 2) + { + secondChild = 2 * (secondChild + 1); + *(first + holeIndex) = std::move(*(first + (secondChild - 1))); + holeIndex = secondChild - 1; + } + _push_heap(first, holeIndex, topIndex, std::move(value), comp); +} + +template +void pop_heap(It first, It last, Compare comp) +{ + if (last - first > 1) + { + --last; + auto value = std::move(*last); + *last = std::move(*first); + _adjust_heap(first, + std::iter_difference_t(0), + std::iter_difference_t(last - first), + std::move(value), + comp); + } +} + +} // namespace floormat::Heap +#else +#include +namespace floormat::Heap { + +using std::push_heap; +using std::pop_heap; + +} // namespace floormat::Heap +#endif -- cgit v1.2.3