[libcxx] r227811 - 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.

Marshall Clow mclow.lists at gmail.com
Mon Feb 2 09:35:54 PST 2015


Author: marshall
Date: Mon Feb  2 11:35:53 2015
New Revision: 227811

URL: http://llvm.org/viewvc/llvm-project?rev=227811&view=rev
Log:
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.

Modified:
    libcxx/trunk/include/algorithm
    libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
    libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp

Modified: libcxx/trunk/include/algorithm
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/algorithm?rev=227811&r1=227810&r2=227811&view=diff
==============================================================================
--- libcxx/trunk/include/algorithm (original)
+++ libcxx/trunk/include/algorithm Mon Feb  2 11:35:53 2015
@@ -4482,12 +4482,6 @@ __inplace_merge(_BidirectionalIterator _
     }
 }
 
-template <class _Tp>
-struct __inplace_merge_switch
-{
-    static const unsigned value = is_trivially_copy_assignable<_Tp>::value;
-};
-
 template <class _BidirectionalIterator, class _Compare>
 inline _LIBCPP_INLINE_VISIBILITY
 void
@@ -4499,13 +4493,9 @@ inplace_merge(_BidirectionalIterator __f
     difference_type __len1 = _VSTD::distance(__first, __middle);
     difference_type __len2 = _VSTD::distance(__middle, __last);
     difference_type __buf_size = _VSTD::min(__len1, __len2);
-    pair<value_type*, ptrdiff_t> __buf(0, 0);
-    unique_ptr<value_type, __return_temporary_buffer> __h;
-    if (__inplace_merge_switch<value_type>::value && __buf_size > 8)
-    {
-        __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size);
-        __h.reset(__buf.first);
-    }
+    pair<value_type*, ptrdiff_t> __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size);
+    unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first);
+
 #ifdef _LIBCPP_DEBUG
     typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
     __debug_less<_Compare> __c(__comp);

Modified: libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp?rev=227811&r1=227810&r2=227811&view=diff
==============================================================================
--- libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp (original)
+++ libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp Mon Feb  2 11:35:53 2015
@@ -31,6 +31,7 @@ struct indirect_less
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 #include "test_iterators.h"
+#include "counting_predicates.hpp"
 
 template <class Iter>
 void
@@ -43,12 +44,14 @@ test_one(unsigned N, unsigned M)
     std::random_shuffle(ia, ia+N);
     std::sort(ia, ia+M, 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)
     {
         assert(ia[0] == N-1);
         assert(ia[N-1] == 0);
         assert(std::is_sorted(ia, ia+N, std::greater<int>()));
+        assert(pred.count() <= (N-1));
     }
     delete [] ia;
 }
@@ -79,6 +82,7 @@ test()
     test_one<Iter>(3, 2);
     test_one<Iter>(3, 3);
     test<Iter>(4);
+    test<Iter>(20);
     test<Iter>(100);
     test<Iter>(1000);
 }

Modified: libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp?rev=227811&r1=227810&r2=227811&view=diff
==============================================================================
--- libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp (original)
+++ libcxx/trunk/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp Mon Feb  2 11:35:53 2015
@@ -25,6 +25,7 @@
 #include <cassert>
 
 #include "test_iterators.h"
+#include "counting_predicates.hpp"
 
 template <class InIter1, class InIter2, class OutIter>
 void
@@ -41,12 +42,14 @@ test()
         ib[i] = 2*i+1;
     std::reverse(ia, ia+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),
-                           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(ic[0] == 2*N-1);
     assert(ic[2*N-1] == 0);
     assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
+    assert(pred.count() <= (N + N - 1));
     delete [] ic;
     delete [] ib;
     delete [] ia;
@@ -63,12 +66,14 @@ test()
     std::copy(ic+N, ic+2*N, ib);
     std::sort(ia, ia+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),
-                           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(ic[0] == 2*N-1);
     assert(ic[2*N-1] == 0);
     assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
+    assert(pred.count() <= (N + N - 1));
     delete [] ic;
     delete [] ib;
     delete [] ia;





More information about the cfe-commits mailing list