forked from OSchip/llvm-project
Fix PR#22427. The implementation of inplace_merge had a \'small data set\' optimization; if either half of the merge was small (i.e, less than 9 items), it did an inplace merge rather than allocating a buffer and doing a faster/smarter merge. However, this failed to satisfy the complexity requirements in the standard. Remove that code. Add tests to check the complexity, and add the same tests for std::merge, since we are in that section of the test suite anyway.
llvm-svn: 227811
This commit is contained in:
parent
6a4ea636f3
commit
0b48cf9a62
|
@ -4482,12 +4482,6 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Tp>
|
|
||||||
struct __inplace_merge_switch
|
|
||||||
{
|
|
||||||
static const unsigned value = is_trivially_copy_assignable<_Tp>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _BidirectionalIterator, class _Compare>
|
template <class _BidirectionalIterator, class _Compare>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
void
|
void
|
||||||
|
@ -4499,13 +4493,9 @@ inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _
|
||||||
difference_type __len1 = _VSTD::distance(__first, __middle);
|
difference_type __len1 = _VSTD::distance(__first, __middle);
|
||||||
difference_type __len2 = _VSTD::distance(__middle, __last);
|
difference_type __len2 = _VSTD::distance(__middle, __last);
|
||||||
difference_type __buf_size = _VSTD::min(__len1, __len2);
|
difference_type __buf_size = _VSTD::min(__len1, __len2);
|
||||||
pair<value_type*, ptrdiff_t> __buf(0, 0);
|
pair<value_type*, ptrdiff_t> __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size);
|
||||||
unique_ptr<value_type, __return_temporary_buffer> __h;
|
unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first);
|
||||||
if (__inplace_merge_switch<value_type>::value && __buf_size > 8)
|
|
||||||
{
|
|
||||||
__buf = _VSTD::get_temporary_buffer<value_type>(__buf_size);
|
|
||||||
__h.reset(__buf.first);
|
|
||||||
}
|
|
||||||
#ifdef _LIBCPP_DEBUG
|
#ifdef _LIBCPP_DEBUG
|
||||||
typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
|
typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
|
||||||
__debug_less<_Compare> __c(__comp);
|
__debug_less<_Compare> __c(__comp);
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct indirect_less
|
||||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||||
|
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
|
#include "counting_predicates.hpp"
|
||||||
|
|
||||||
template <class Iter>
|
template <class Iter>
|
||||||
void
|
void
|
||||||
|
@ -43,12 +44,14 @@ test_one(unsigned N, unsigned M)
|
||||||
std::random_shuffle(ia, ia+N);
|
std::random_shuffle(ia, ia+N);
|
||||||
std::sort(ia, ia+M, std::greater<int>());
|
std::sort(ia, ia+M, std::greater<int>());
|
||||||
std::sort(ia+M, ia+N, std::greater<int>());
|
std::sort(ia+M, ia+N, std::greater<int>());
|
||||||
std::inplace_merge(Iter(ia), Iter(ia+M), Iter(ia+N), std::greater<int>());
|
binary_counting_predicate<std::greater<int>, int, int> pred((std::greater<int>()));
|
||||||
|
std::inplace_merge(Iter(ia), Iter(ia+M), Iter(ia+N), std::ref(pred));
|
||||||
if(N > 0)
|
if(N > 0)
|
||||||
{
|
{
|
||||||
assert(ia[0] == N-1);
|
assert(ia[0] == N-1);
|
||||||
assert(ia[N-1] == 0);
|
assert(ia[N-1] == 0);
|
||||||
assert(std::is_sorted(ia, ia+N, std::greater<int>()));
|
assert(std::is_sorted(ia, ia+N, std::greater<int>()));
|
||||||
|
assert(pred.count() <= (N-1));
|
||||||
}
|
}
|
||||||
delete [] ia;
|
delete [] ia;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +82,7 @@ test()
|
||||||
test_one<Iter>(3, 2);
|
test_one<Iter>(3, 2);
|
||||||
test_one<Iter>(3, 3);
|
test_one<Iter>(3, 3);
|
||||||
test<Iter>(4);
|
test<Iter>(4);
|
||||||
|
test<Iter>(20);
|
||||||
test<Iter>(100);
|
test<Iter>(100);
|
||||||
test<Iter>(1000);
|
test<Iter>(1000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
|
#include "counting_predicates.hpp"
|
||||||
|
|
||||||
template <class InIter1, class InIter2, class OutIter>
|
template <class InIter1, class InIter2, class OutIter>
|
||||||
void
|
void
|
||||||
|
@ -41,12 +42,14 @@ test()
|
||||||
ib[i] = 2*i+1;
|
ib[i] = 2*i+1;
|
||||||
std::reverse(ia, ia+N);
|
std::reverse(ia, ia+N);
|
||||||
std::reverse(ib, ib+N);
|
std::reverse(ib, ib+N);
|
||||||
|
binary_counting_predicate<std::greater<int>, int, int> pred((std::greater<int>()));
|
||||||
OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
|
OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
|
||||||
InIter2(ib), InIter2(ib+N), OutIter(ic), std::greater<int>());
|
InIter2(ib), InIter2(ib+N), OutIter(ic), pred);
|
||||||
assert(base(r) == ic+2*N);
|
assert(base(r) == ic+2*N);
|
||||||
assert(ic[0] == 2*N-1);
|
assert(ic[0] == 2*N-1);
|
||||||
assert(ic[2*N-1] == 0);
|
assert(ic[2*N-1] == 0);
|
||||||
assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
|
assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
|
||||||
|
assert(pred.count() <= (N + N - 1));
|
||||||
delete [] ic;
|
delete [] ic;
|
||||||
delete [] ib;
|
delete [] ib;
|
||||||
delete [] ia;
|
delete [] ia;
|
||||||
|
@ -63,12 +66,14 @@ test()
|
||||||
std::copy(ic+N, ic+2*N, ib);
|
std::copy(ic+N, ic+2*N, ib);
|
||||||
std::sort(ia, ia+N, std::greater<int>());
|
std::sort(ia, ia+N, std::greater<int>());
|
||||||
std::sort(ib, ib+N, std::greater<int>());
|
std::sort(ib, ib+N, std::greater<int>());
|
||||||
|
binary_counting_predicate<std::greater<int>, int, int> pred((std::greater<int>()));
|
||||||
OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
|
OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
|
||||||
InIter2(ib), InIter2(ib+N), OutIter(ic), std::greater<int>());
|
InIter2(ib), InIter2(ib+N), OutIter(ic), pred);
|
||||||
assert(base(r) == ic+2*N);
|
assert(base(r) == ic+2*N);
|
||||||
assert(ic[0] == 2*N-1);
|
assert(ic[0] == 2*N-1);
|
||||||
assert(ic[2*N-1] == 0);
|
assert(ic[2*N-1] == 0);
|
||||||
assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
|
assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
|
||||||
|
assert(pred.count() <= (N + N - 1));
|
||||||
delete [] ic;
|
delete [] ic;
|
||||||
delete [] ib;
|
delete [] ib;
|
||||||
delete [] ia;
|
delete [] ia;
|
||||||
|
|
Loading…
Reference in New Issue