Details
- Reviewers
ldionne rupprecht - Group Reviewers
Restricted Project - Commits
- rG5d9565634c97: Revert "Revert "[libc++] [P0879] constexpr std::nth_element, and rewrite its…
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Simple "manual" tests can also pay off :-)
Well, actually, before landing this I thought I'd better run some more randomized tests... and I found that this patch also has a bug somewhere! Reduced from the randomized tests:
std::vector<int> v2 = { 18, -7, 1, -9, 3, 13, -10, -10, -9, 4, -10, 5, 8, 6, 11, -10, 19 }; std::nth_element(v2.begin(), v2.begin() + 10, v2.end()); assert(std::all_of(v2.begin(), v2.begin() + 10, [&](int x){ return x <= v2[10]; })); assert(std::all_of(v2.begin() + 10, v2.end(), [&](int x){ return x >= v2[10]; })); // fails!
So I'm still working on this.
...EDIT: wait, no, maybe I messed up and this fails using the old version but not the new version. Blech. Anyway, if I land this today it'll be after convincing myself that it passes randomized tests too.
FWIW, I applied this patch and was able to make it pass this pretty exhaustive test:
{ constexpr int kMaxLen = 64; for (int len = 1; len < kMaxLen; ++len) { int v[kMaxLen]; for (int i = 0; i < len; ++i) v[i] = i; T v2[kMaxLen]; std::copy(v, v + len, v2); do { for (int n = 0; n < len; ++n) { for (int m = 0; m < n; ++m) { std::nth_element(Iter(v2), Iter(v2 + m), Iter(v2 + n), std::greater<T>()); assert(std::is_permutation(v2, v2 + len, v)); // No element to m's left is less than m. for (int i = 0; i < m; ++i) { assert(!(v2[i] < v2[m])); } // No element to m's right is greater than m. for (int i = m; i < n; ++i) { assert(!(v2[i] > v2[m])); } } } } while (std::next_permutation(Iter(v2), Iter(v2 + len))); } }
@rupprecht: I'm looking at adding a similar test to the libc++ test suite, but, I don't really understand what this test is doing. You're running nth_element repeatedly on the same array with increasing m and n, which is kind of a selection sort on the first len-1 elements? And then next_permutation takes it from 4 3 2 1 0 5 to 4 3 2 1 5 0 and we selection-sort the first n-1 elements again to get 5 4 3 2 1 0, and then the second next_permutation kicks us out to increment len?
I thought maybe you were going for the "try all permutations of 64 elements" exhaustive test, but that would take 64! iterations which is heat-death-of-the-universe territory.
Is there a subtle logic to the particular sequence your test is actually doing?