Index: include/algorithm =================================================================== --- include/algorithm +++ include/algorithm @@ -4907,6 +4907,32 @@ _VSTD::pop_heap(__first, __last, __less::value_type>()); } +// poke_heap + +template +inline _LIBCPP_INLINE_VISIBILITY +void +poke_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) +{ + typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first; +#ifdef _LIBCPP_DEBUG + typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref; + __debug_less<_Compare> __c(__comp); + __sift_down<_Comp_ref>(__first, __last, __comp, __len, __first); +#else // _LIBCPP_DEBUG + typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; + __sift_down<_Comp_ref>(__first, __last, __comp, __len, __first); +#endif // _LIBCPP_DEBUG +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +poke_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) +{ + _VSTD::poke_heap(__first, __last, __less::value_type>()); +} + // make_heap template Index: include/queue =================================================================== --- include/queue +++ include/queue @@ -545,6 +545,16 @@ void pop(); _LIBCPP_INLINE_VISIBILITY + void replace_top(const value_type& __v); +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + void replace_top(value_type&& __v); + template + _LIBCPP_INLINE_VISIBILITY + void reemplace_top(_Args&&... __args); +#endif // _LIBCPP_CXX03_LANG + + _LIBCPP_INLINE_VISIBILITY void swap(priority_queue& __q) _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value); @@ -769,6 +779,38 @@ template inline void +priority_queue<_Tp, _Container, _Compare>::replace_top(const value_type& __v) +{ + c.front() = __v; + __sift_down::type>(c.begin(), c.end(), comp, c.size(), c.begin()); +} + +#ifndef _LIBCPP_CXX03_LANG + +template +inline +void +priority_queue<_Tp, _Container, _Compare>::replace_top(value_type&& __v) +{ + c.front() = _VSTD::move(__v); + __sift_down::type>(c.begin(), c.end(), comp, c.size(), c.begin()); +} + +template +template +inline +void +priority_queue<_Tp, _Container, _Compare>::reemplace_top(_Args&&... __args) +{ + c.front() = _Tp(_VSTD::forward<_Args>(__args)...); + __sift_down::type>(c.begin(), c.end(), comp, c.size(), c.begin()); +} + +#endif // _LIBCPP_CXX03_LANG + +template +inline +void priority_queue<_Tp, _Container, _Compare>::swap(priority_queue& __q) _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value) Index: test/libcxx/algorithms/alg.sorting/alg.heap.operations/poke.heap/poke_heap.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/algorithms/alg.sorting/alg.heap.operations/poke.heap/poke_heap.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// template +// requires ShuffleIterator +// && LessThanComparable +// void +// poke_heap(Iter first, Iter last); + +#include +#include +#include +#include + +std::mt19937 randomness; + +void test(int M, int N) +{ + int* inputs = new int [N]; + for (int i = 0; i < N; ++i) + inputs[i] = i; + std::shuffle(inputs, inputs+N, randomness); + int* heap = new int[M]; + int* control = new int[M]; + std::make_heap(inputs, inputs+M); + std::copy(inputs, inputs+M, heap); + std::copy(inputs, inputs+M, control); + for (int i = 0; i < N; ++i) { + std::pop_heap(control, control+M); + control[M-1] = inputs[i]; + heap[0] = inputs[i]; + std::push_heap(control, control+M); + std::poke_heap(heap, heap+M); + assert(std::is_heap(control, control+M)); + assert(std::is_heap(heap, heap+M)); + assert(std::is_permutation(heap, heap+M, control)); + } + delete [] control; + delete [] heap; + delete [] inputs; +} + +int main(int, char**) +{ + test(100, 1000); + + // Test small cases + int ia[] = {1, 2, 3}; + std::poke_heap(ia, ia); // no-op + assert(ia[0] == 1); + std::poke_heap(ia, ia+1); // no-op + assert(ia[0] == 1); + std::poke_heap(ia, ia+2); + assert(ia[0] == 2 && ia[1] == 1); + + return 0; +} Index: test/libcxx/algorithms/alg.sorting/alg.heap.operations/poke.heap/poke_heap_comp.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/algorithms/alg.sorting/alg.heap.operations/poke.heap/poke_heap_comp.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// template +// requires ShuffleIterator +// && LessThanComparable +// void +// poke_heap(Iter first, Iter last); + +#include +#include +#include +#include + +#include "test_macros.h" + +std::mt19937 randomness; + +void test(int M, int N) +{ + int* inputs = new int [N]; + for (int i = 0; i < N; ++i) + inputs[i] = i; + std::shuffle(inputs, inputs+N, randomness); + int* heap = new int[M]; + int* control = new int[M]; + std::make_heap(inputs, inputs+M, std::greater()); + std::copy(inputs, inputs+M, heap); + std::copy(inputs, inputs+M, control); + for (int i = 0; i < N; ++i) { + std::pop_heap(control, control+M, std::greater()); + control[M-1] = inputs[i]; + heap[0] = inputs[i]; + std::push_heap(control, control+M, std::greater()); + std::poke_heap(heap, heap+M, std::greater()); + assert(std::is_heap(control, control+M, std::greater())); + assert(std::is_heap(heap, heap+M, std::greater())); + assert(std::is_permutation(heap, heap+M, control)); + } + delete [] control; + delete [] heap; + delete [] inputs; +} + +int main(int, char**) +{ + test(100, 1000); + + // Test small cases + int ia[] = {3, 2, 1}; + std::poke_heap(ia, ia, std::greater()); // no-op + assert(ia[0] == 3); + std::poke_heap(ia, ia+1, std::greater()); // no-op + assert(ia[0] == 3); + std::poke_heap(ia, ia+2, std::greater()); + assert(ia[0] == 2 && ia[1] == 3); + + return 0; +} Index: test/libcxx/containers/container.adaptors/priority.queue/priqueue.members/reemplace_top.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/container.adaptors/priority.queue/priqueue.members/reemplace_top.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// priority_queue(); + +// template void reemplace_top(Args&&... args); + +#include +#include + +#include "../../../../../std/containers/Emplaceable.h" + +int main(int, char**) +{ + std::priority_queue q; + q.emplace(1, 2.5); + assert(q.top() == Emplaceable(1, 2.5)); + q.emplace(3, 4.5); + assert(q.top() == Emplaceable(3, 4.5)); + q.reemplace_top(2, 3.5); + assert(q.top() == Emplaceable(2, 3.5)); + q.reemplace_top(0, 1.5); + assert(q.top() == Emplaceable(1, 2.5)); + + return 0; +} Index: test/libcxx/containers/container.adaptors/priority.queue/priqueue.members/replace_top.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/container.adaptors/priority.queue/priqueue.members/replace_top.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// priority_queue(); + +// void replace_top(const value_type& v); + +#include +#include + +int main(int, char**) +{ + std::priority_queue q; + q.push(1); + assert(q.top() == 1); + q.push(3); + assert(q.top() == 3); + q.replace_top(2); + assert(q.top() == 2); + q.replace_top(0); + assert(q.top() == 1); + + return 0; +} Index: test/libcxx/containers/container.adaptors/priority.queue/priqueue.members/replace_top_rvalue.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/container.adaptors/priority.queue/priqueue.members/replace_top_rvalue.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// priority_queue(); + +// void replace_top(value_type&& v); + +#include +#include + +#include "MoveOnly.h" + +int main(int, char**) +{ + std::priority_queue q; + q.push(1); + assert(q.top() == 1); + q.push(3); + assert(q.top() == 3); + q.replace_top(2); + assert(q.top() == 2); + q.replace_top(0); + assert(q.top() == 1); + + return 0; +}