[PATCH] D32788: Fix std::inplace_merge to be stable for all inputs

Jan Wilken Dörrie via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed May 3 01:22:00 PDT 2017


jdoerrie created this revision.

This change fixes std::inplace_merge to be stable for all inputs and adds corresponding tests.

Fixes Bug 31166: https://bugs.llvm.org//show_bug.cgi?id=31166


https://reviews.llvm.org/D32788

Files:
  include/algorithm
  test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp


Index: test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
===================================================================
--- test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
+++ test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
@@ -32,6 +32,14 @@
         {return *x < *y;}
 };
 
+struct first_only
+{
+    bool operator()(const std::pair<int, int>& x, const std::pair<int, int>& y)
+    {
+        return x.first < y.first;
+    }
+};
+
 struct S {
 	S() : i_(0) {}
 	S(int i) : i_(i) {}
@@ -85,6 +93,23 @@
     delete [] ia;
 }
 
+void
+test_two(unsigned N, unsigned M)
+{
+    typedef std::pair<int, int> P;
+    std::vector<P> v(N);
+    unsigned mod = std::max(M, N - M);
+    for (unsigned i = 0; i < N; ++i)
+    {
+        v[i] = P(i % mod, i >= M);
+    }
+
+    std::stable_sort(v.begin(), v.begin() + M, first_only());
+    std::stable_sort(v.begin() + M, v.end(), first_only());
+    std::inplace_merge(v.begin(), v.begin() + M, v.end(), first_only());
+    assert(std::is_sorted(v.begin(), v.end()));
+}
+
 template <class Iter>
 void
 test(unsigned N)
@@ -94,6 +119,12 @@
     test_one<Iter>(N, N/2);
     test_one<Iter>(N, 3*N/4);
     test_one<Iter>(N, N);
+
+    test_two(N, 0);
+    test_two(N, N/4);
+    test_two(N, N/2);
+    test_two(N, 3*N/4);
+    test_two(N, N);
 }
 
 template <class Iter>
@@ -110,6 +141,18 @@
     test_one<Iter>(3, 1);
     test_one<Iter>(3, 2);
     test_one<Iter>(3, 3);
+
+    test_two(0, 0);
+    test_two(1, 0);
+    test_two(1, 1);
+    test_two(2, 0);
+    test_two(2, 1);
+    test_two(2, 2);
+    test_two(3, 0);
+    test_two(3, 1);
+    test_two(3, 2);
+    test_two(3, 3);
+
     test<Iter>(4);
     test<Iter>(20);
     test<Iter>(100);
Index: include/algorithm
===================================================================
--- include/algorithm
+++ include/algorithm
@@ -745,7 +745,7 @@
 
     template <class _T1, class _T2>
     _LIBCPP_INLINE_VISIBILITY
-    bool operator()(const _T1& __x, const _T2& __y) {return !__p_(__x, __y);}
+    bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);}
 };
 
 #ifdef _LIBCPP_DEBUG


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D32788.97567.patch
Type: text/x-patch
Size: 2172 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170503/aa9e6c06/attachment-0001.bin>


More information about the cfe-commits mailing list