Skip to content

Commit 88dc8c8

Browse files
committed
Fix tests for stable_sort with predicate too
1 parent 888097c commit 88dc8c8

File tree

3 files changed

+184
-150
lines changed

3 files changed

+184
-150
lines changed

libcxx/include/__algorithm/stable_sort.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ _LIBCPP_PUSH_MACROS
4242
_LIBCPP_BEGIN_NAMESPACE_STD
4343

4444
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
45-
_LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
45+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insertion_sort_move(
4646
_BidirectionalIterator __first1,
4747
_BidirectionalIterator __last1,
4848
typename iterator_traits<_BidirectionalIterator>::value_type* __first2,

libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp

Lines changed: 128 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@
99
// <algorithm>
1010

1111
// template <class RandomAccessIterator>
12-
// constexpr void // constexpr in C++26
12+
// constexpr void // constexpr since C++26
1313
// stable_sort(RandomAccessIterator first, RandomAccessIterator last);
1414

1515
// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=20000000
1616
// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=80000000
1717

1818
#include <algorithm>
19-
#include <array>
2019
#include <cassert>
2120
#include <iterator>
2221
#include <random>
@@ -25,154 +24,167 @@
2524
#include "count_new.h"
2625
#include "test_macros.h"
2726

28-
template <class RI>
29-
void
30-
test_sort_helper(RI f, RI l)
31-
{
32-
typedef typename std::iterator_traits<RI>::value_type value_type;
33-
typedef typename std::iterator_traits<RI>::difference_type difference_type;
34-
35-
if (f != l)
36-
{
37-
difference_type len = l - f;
38-
value_type* save(new value_type[len]);
39-
do
40-
{
41-
std::copy(f, l, save);
42-
std::stable_sort(save, save+len);
43-
assert(std::is_sorted(save, save+len));
44-
} while (std::next_permutation(f, l));
45-
delete [] save;
46-
}
27+
template <class Iterator>
28+
TEST_CONSTEXPR_CXX26 void test_all_permutations(Iterator first, Iterator last) {
29+
using T = typename std::iterator_traits<Iterator>::value_type;
30+
31+
do {
32+
std::vector<T> save(first, last);
33+
std::stable_sort(save.begin(), save.end());
34+
assert(std::is_sorted(save.begin(), save.end()));
35+
} while (std::next_permutation(first, last));
4736
}
4837

49-
template <class RI>
50-
void
51-
test_sort_driver_driver(RI f, RI l, int start, RI real_last)
52-
{
53-
using value_type = typename std::iterator_traits<RI>::value_type;
38+
template <class Iterator>
39+
TEST_CONSTEXPR_CXX26 void test_sort_exhaustive_impl(Iterator first, Iterator last, int start, Iterator real_last) {
40+
using T = typename std::iterator_traits<Iterator>::value_type;
5441

55-
for (RI i = l; i > f + start;) {
56-
*--i = static_cast<value_type>(start);
57-
if (f == i) {
58-
test_sort_helper(f, real_last);
42+
for (Iterator i = last; i > first + start;) {
43+
*--i = static_cast<T>(start);
44+
if (first == i) {
45+
test_all_permutations(first, real_last);
5946
}
6047
if (start > 0)
61-
test_sort_driver_driver(f, i, start-1, real_last);
48+
test_sort_exhaustive_impl(first, i, start - 1, real_last);
6249
}
6350
}
6451

65-
template <class RI>
66-
void
67-
test_sort_driver(RI f, RI l, int start)
68-
{
69-
test_sort_driver_driver(f, l, start, l);
70-
}
71-
72-
template <int sa, class V>
73-
void test_sort_() {
74-
V ia[sa];
75-
for (int i = 0; i < sa; ++i) {
76-
test_sort_driver(ia, ia + sa, i);
52+
template <class T>
53+
TEST_CONSTEXPR_CXX26 void test_sort_exhaustive(int N) {
54+
std::vector<T> vec;
55+
vec.resize(N);
56+
for (int i = 0; i < N; ++i) {
57+
test_sort_exhaustive_impl(vec.begin(), vec.end(), i, vec.end());
7758
}
7859
}
7960

80-
template <int sa>
81-
void test_sort_() {
82-
test_sort_<sa, int>();
83-
test_sort_<sa, float>();
84-
}
85-
86-
template <class V>
87-
void test_larger_sorts(int N, int M) {
88-
assert(N != 0);
89-
assert(M != 0);
90-
// create array length N filled with M different numbers
91-
V* array = new V[N];
92-
int x = 0;
61+
template <class T>
62+
TEST_CONSTEXPR_CXX26 std::vector<T> generate_sawtooth(int N, int M) {
63+
// Populate a sequence of length N with M different numbers
64+
std::vector<T> v;
65+
T x = 0;
9366
for (int i = 0; i < N; ++i) {
94-
array[i] = static_cast<V>(x);
67+
v.push_back(x);
9568
if (++x == M)
9669
x = 0;
9770
}
71+
return v;
72+
}
73+
74+
template <class T>
75+
TEST_CONSTEXPR_CXX26 void test_larger_sorts(int N, int M) {
76+
assert(N != 0);
77+
assert(M != 0);
78+
9879
// test saw tooth pattern
99-
std::stable_sort(array, array + N);
100-
assert(std::is_sorted(array, array + N));
80+
{
81+
auto v = generate_sawtooth<T>(N, M);
82+
std::stable_sort(v.begin(), v.end());
83+
assert(std::is_sorted(v.begin(), v.end()));
84+
}
85+
10186
// test random pattern
102-
std::shuffle(array, array + N, randomness);
103-
std::stable_sort(array, array + N);
104-
assert(std::is_sorted(array, array + N));
87+
{
88+
if (!TEST_IS_CONSTANT_EVALUATED) {
89+
auto v = generate_sawtooth<T>(N, M);
90+
std::mt19937 randomness;
91+
std::shuffle(v.begin(), v.end(), randomness);
92+
std::stable_sort(v.begin(), v.end());
93+
assert(std::is_sorted(v.begin(), v.end()));
94+
}
95+
}
96+
10597
// test sorted pattern
106-
std::stable_sort(array, array + N);
107-
assert(std::is_sorted(array, array + N));
98+
{
99+
auto v = generate_sawtooth<T>(N, M);
100+
std::sort(v.begin(), v.end());
101+
102+
std::stable_sort(v.begin(), v.end());
103+
assert(std::is_sorted(v.begin(), v.end()));
104+
}
105+
108106
// test reverse sorted pattern
109-
std::reverse(array, array + N);
110-
std::stable_sort(array, array + N);
111-
assert(std::is_sorted(array, array + N));
107+
{
108+
auto v = generate_sawtooth<T>(N, M);
109+
std::sort(v.begin(), v.end());
110+
std::reverse(v.begin(), v.end());
111+
112+
std::stable_sort(v.begin(), v.end());
113+
assert(std::is_sorted(v.begin(), v.end()));
114+
}
115+
112116
// test swap ranges 2 pattern
113-
std::swap_ranges(array, array + N / 2, array + N / 2);
114-
std::stable_sort(array, array + N);
115-
assert(std::is_sorted(array, array + N));
116-
// test reverse swap ranges 2 pattern
117-
std::reverse(array, array + N);
118-
std::swap_ranges(array, array + N / 2, array + N / 2);
119-
std::stable_sort(array, array + N);
120-
assert(std::is_sorted(array, array + N));
121-
delete[] array;
122-
}
117+
{
118+
auto v = generate_sawtooth<T>(N, M);
119+
std::sort(v.begin(), v.end());
120+
std::swap_ranges(v.begin(), v.begin() + (N / 2), v.begin() + (N / 2));
121+
122+
std::stable_sort(v.begin(), v.end());
123+
assert(std::is_sorted(v.begin(), v.end()));
124+
}
123125

124-
void test_larger_sorts(int N, int M) {
125-
test_larger_sorts<int>(N, M);
126-
test_larger_sorts<float>(N, M);
126+
// test reverse swap ranges 2 pattern
127+
{
128+
auto v = generate_sawtooth<T>(N, M);
129+
std::sort(v.begin(), v.end());
130+
std::reverse(v.begin(), v.end());
131+
std::swap_ranges(v.begin(), v.begin() + (N / 2), v.begin() + (N / 2));
132+
133+
std::stable_sort(v.begin(), v.end());
134+
assert(std::is_sorted(v.begin(), v.end()));
135+
}
127136
}
128137

129-
template <int N>
130-
TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
131-
test_larger_sorts<N, 1>();
132-
test_larger_sorts<N, 2>();
133-
test_larger_sorts<N, 3>();
134-
test_larger_sorts<N, N / 2 - 1>();
135-
test_larger_sorts<N, N / 2>();
136-
test_larger_sorts<N, N / 2 + 1>();
137-
test_larger_sorts<N, N - 2>();
138-
test_larger_sorts<N, N - 1>();
139-
test_larger_sorts<N, N>();
138+
template <class T>
139+
TEST_CONSTEXPR_CXX26 void test_larger_sorts(int N) {
140+
test_larger_sorts<T>(N, 1);
141+
test_larger_sorts<T>(N, 2);
142+
test_larger_sorts<T>(N, 3);
143+
test_larger_sorts<T>(N, N / 2 - 1);
144+
test_larger_sorts<T>(N, N / 2);
145+
test_larger_sorts<T>(N, N / 2 + 1);
146+
test_larger_sorts<T>(N, N - 2);
147+
test_larger_sorts<T>(N, N - 1);
148+
test_larger_sorts<T>(N, N);
140149
}
141150

151+
template <class T>
142152
TEST_CONSTEXPR_CXX26 bool test() {
143153
// test null range
144-
int d = 0;
145-
std::stable_sort(&d, &d);
154+
{
155+
T value = 0;
156+
std::stable_sort(&value, &value);
157+
}
146158

147159
// exhaustively test all possibilities up to length 8
148160
if (!TEST_IS_CONSTANT_EVALUATED) {
149-
test_sort_<1>();
150-
test_sort_<2>();
151-
test_sort_<3>();
152-
test_sort_<4>();
153-
test_sort_<5>();
154-
test_sort_<6>();
155-
test_sort_<7>();
156-
test_sort_<8>();
161+
test_sort_exhaustive<T>(1);
162+
test_sort_exhaustive<T>(2);
163+
test_sort_exhaustive<T>(3);
164+
test_sort_exhaustive<T>(4);
165+
test_sort_exhaustive<T>(5);
166+
test_sort_exhaustive<T>(6);
167+
test_sort_exhaustive<T>(7);
168+
test_sort_exhaustive<T>(8);
157169
}
158170

159-
test_larger_sorts(256);
160-
test_larger_sorts(257);
171+
test_larger_sorts<T>(256);
172+
test_larger_sorts<T>(257);
161173
if (!TEST_IS_CONSTANT_EVALUATED) { // avoid blowing past constexpr evaluation limit
162-
test_larger_sorts(499);
163-
test_larger_sorts(500);
164-
test_larger_sorts(997);
165-
test_larger_sorts(1000);
166-
test_larger_sorts(1009);
167-
test_larger_sorts(1024);
168-
test_larger_sorts(1031);
169-
test_larger_sorts(2053);
174+
test_larger_sorts<T>(499);
175+
test_larger_sorts<T>(500);
176+
test_larger_sorts<T>(997);
177+
test_larger_sorts<T>(1000);
178+
test_larger_sorts<T>(1009);
179+
test_larger_sorts<T>(1024);
180+
test_larger_sorts<T>(1031);
181+
test_larger_sorts<T>(2053);
170182
}
171183

172184
// check that the algorithm works without memory
173185
#ifndef TEST_HAS_NO_EXCEPTIONS
174186
if (!TEST_IS_CONSTANT_EVALUATED) {
175-
std::vector<int> vec(150, 3);
187+
std::vector<T> vec(150, T(3));
176188
getGlobalMemCounter()->throw_after = 0;
177189
std::stable_sort(vec.begin(), vec.end());
178190
}
@@ -182,9 +194,11 @@ TEST_CONSTEXPR_CXX26 bool test() {
182194
}
183195

184196
int main(int, char**) {
185-
test();
197+
test<int>();
198+
test<float>();
186199
#if TEST_STD_VER >= 26
187-
static_assert(test());
200+
static_assert(test<int>());
201+
static_assert(test<float>());
188202
#endif
189203
return 0;
190204
}

0 commit comments

Comments
 (0)