2 //===-- sort.pass.cpp -----------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: c++03, c++11, c++14
12 #include "support/pstl_test_config.h"
17 #include "support/utils.h"
19 using namespace TestUtils
;
20 #define _CRT_SECURE_NO_WARNINGS
26 //! Number of extant keys
27 static std::atomic
<int32_t> KeyCount
;
29 //! One more than highest index in array to be sorted.
30 static uint32_t LastIndex
;
32 //! Keeping Equal() static and a friend of ParanoidKey class (C++, paragraphs 3.5/7.1.1)
35 Equal(const ParanoidKey
& x
, const ParanoidKey
& y
);
37 //! A key to be sorted, with lots of checking.
40 //! Value used by comparator
42 //! Original position or special value (Empty or Dead)
44 //! Special value used to mark object without a comparable value, e.g. after being moved from.
45 static const int32_t Empty
= -1;
46 //! Special value used to mark destroyed objects.
47 static const int32_t Dead
= -2;
48 // True if key object has comparable value
52 return (uint32_t)(index
) < LastIndex
;
54 // True if key object has been constructed.
58 return isLive() || index
== Empty
;
68 ParanoidKey(const ParanoidKey
& k
) : value(k
.value
), index(k
.index
)
70 EXPECT_TRUE(k
.isLive(), "source for copy-constructor is dead");
75 EXPECT_TRUE(isConstructed(), "double destruction");
80 operator=(const ParanoidKey
& k
)
82 EXPECT_TRUE(k
.isLive(), "source for copy-assignment is dead");
83 EXPECT_TRUE(isConstructed(), "destination for copy-assignment is dead");
88 ParanoidKey(int32_t index
, int32_t value
, OddTag
) : value(value
), index(index
) {}
89 ParanoidKey(ParanoidKey
&& k
) : value(k
.value
), index(k
.index
)
91 EXPECT_TRUE(k
.isConstructed(), "source for move-construction is dead");
92 // std::stable_sort() fails in move semantics on paranoid test before VS2015
93 #if !defined(_MSC_VER) || _MSC_VER >= 1900
99 operator=(ParanoidKey
&& k
)
101 EXPECT_TRUE(k
.isConstructed(), "source for move-assignment is dead");
102 EXPECT_TRUE(isConstructed(), "destination for move-assignment is dead");
105 // std::stable_sort() fails in move semantics on paranoid test before VS2015
106 #if !defined(_MSC_VER) || _MSC_VER >= 1900
111 friend class KeyCompare
;
113 Equal(const ParanoidKey
& x
, const ParanoidKey
& y
);
120 //! Special value used to mark defined object.
122 //! Special value used to mark destroyed objects.
127 KeyCompare(OddTag
) : status(Live
) {}
128 ~KeyCompare() { status
= Dead
; }
130 operator()(const ParanoidKey
& j
, const ParanoidKey
& k
) const
132 EXPECT_TRUE(status
== Live
, "key comparison object not defined");
133 EXPECT_TRUE(j
.isLive(), "first key to operator() is not live");
134 EXPECT_TRUE(k
.isLive(), "second key to operator() is not live");
135 return j
.value
< k
.value
;
139 // Equal is equality comparison used for checking result of sort against expected result.
141 Equal(const ParanoidKey
& x
, const ParanoidKey
& y
)
143 return (x
.value
== y
.value
&& !Stable
) || (x
.index
== y
.index
);
147 Equal(float32_t x
, float32_t y
)
153 Equal(int32_t x
, int32_t y
)
158 struct test_sort_with_compare
160 template <typename Policy
, typename InputIterator
, typename OutputIterator
, typename OutputIterator2
, typename Size
,
162 typename
std::enable_if
<is_same_iterator_category
<InputIterator
, std::random_access_iterator_tag
>::value
,
164 operator()(Policy
&& exec
, OutputIterator tmp_first
, OutputIterator tmp_last
, OutputIterator2 expected_first
,
165 OutputIterator2 expected_last
, InputIterator first
, InputIterator
, Size n
, Compare compare
)
168 copy_n(first
, n
, expected_first
);
169 copy_n(first
, n
, tmp_first
);
171 std::stable_sort(expected_first
+ 1, expected_last
- 1, compare
);
173 std::sort(expected_first
+ 1, expected_last
- 1, compare
);
174 int32_t count0
= KeyCount
;
176 stable_sort(exec
, tmp_first
+ 1, tmp_last
- 1, compare
);
178 sort(exec
, tmp_first
+ 1, tmp_last
- 1, compare
);
180 for (size_t i
= 0; i
< n
; ++i
, ++expected_first
, ++tmp_first
)
182 // Check that expected[i] is equal to tmp[i]
183 EXPECT_TRUE(Equal(*expected_first
, *tmp_first
), "bad sort");
185 int32_t count1
= KeyCount
;
186 EXPECT_EQ(count0
, count1
, "key cleanup error");
188 template <typename Policy
, typename InputIterator
, typename OutputIterator
, typename OutputIterator2
, typename Size
,
190 typename
std::enable_if
<!is_same_iterator_category
<InputIterator
, std::random_access_iterator_tag
>::value
,
192 operator()(Policy
&&, OutputIterator
, OutputIterator
, OutputIterator2
, OutputIterator2
, InputIterator
, InputIterator
,
198 template <typename T
, typename Compare
, typename Convert
>
200 test_sort(Compare compare
, Convert convert
)
202 for (size_t n
= 0; n
< 100000; n
= n
<= 16 ? n
+ 1 : size_t(3.1415 * n
))
205 // The rand()%(2*n+1) encourages generation of some duplicates.
206 // Sequence is padded with an extra element at front and back, to detect overwrite bugs.
207 Sequence
<T
> in(n
+ 2, [=](size_t k
) { return convert(k
, rand() % (2 * n
+ 1)); });
208 Sequence
<T
> expected(in
);
210 invoke_on_all_policies(test_sort_with_compare(), tmp
.begin(), tmp
.end(), expected
.begin(), expected
.end(),
211 in
.begin(), in
.end(), in
.size(), compare
);
215 template <typename T
>
216 struct test_non_const
218 template <typename Policy
, typename Iterator
>
220 operator()(Policy
&& exec
, Iterator iter
)
222 sort(exec
, iter
, iter
, non_const(std::less
<T
>()));
223 stable_sort(exec
, iter
, iter
, non_const(std::less
<T
>()));
231 for (int32_t kind
= 0; kind
< 2; ++kind
)
234 test_sort
<ParanoidKey
>(KeyCompare(OddTag()),
235 [](size_t k
, size_t val
) { return ParanoidKey(k
, val
, OddTag()); });
236 test_sort
<float32_t
>([](float32_t x
, float32_t y
) { return x
< y
; },
237 [](size_t, size_t val
) { return float32_t(val
); });
239 [](int32_t x
, int32_t y
) { return x
> y
; }, // Reversed so accidental use of < will be detected.
240 [](size_t, size_t val
) { return int32_t(val
); });
243 test_algo_basic_single
<int32_t>(run_for_rnd
<test_non_const
<int32_t>>());
245 std::cout
<< done() << std::endl
;