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?