151c0b2f7Stbbdev /*
2*c7157ce3SVladislav Shchapov Copyright (c) 2005-2022 Intel Corporation
351c0b2f7Stbbdev
451c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev you may not use this file except in compliance with the License.
651c0b2f7Stbbdev You may obtain a copy of the License at
751c0b2f7Stbbdev
851c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev
1051c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev See the License for the specific language governing permissions and
1451c0b2f7Stbbdev limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev
1751c0b2f7Stbbdev #include "common/test.h"
1851c0b2f7Stbbdev #include "common/utils_concurrency_limit.h"
1951c0b2f7Stbbdev #include "common/cpu_usertime.h"
20478de5b1Stbbdev #include "common/concepts_common.h"
21478de5b1Stbbdev #include "common/iterator.h"
2251c0b2f7Stbbdev
2351c0b2f7Stbbdev #include "tbb/parallel_sort.h"
2451c0b2f7Stbbdev #include "tbb/concurrent_vector.h"
2551c0b2f7Stbbdev #include "tbb/global_control.h"
2651c0b2f7Stbbdev
2751c0b2f7Stbbdev #include <math.h>
2851c0b2f7Stbbdev #include <vector>
2951c0b2f7Stbbdev #include <functional>
3051c0b2f7Stbbdev #include <string>
3151c0b2f7Stbbdev #include <cstring>
3251c0b2f7Stbbdev #include <cstddef>
33b95bbc9cSIvan Kochin #include <iterator>
34b95bbc9cSIvan Kochin #include <type_traits>
3551c0b2f7Stbbdev
3651c0b2f7Stbbdev //! \file test_parallel_sort.cpp
3751c0b2f7Stbbdev //! \brief Test for [algorithms.parallel_sort]
3851c0b2f7Stbbdev
3951c0b2f7Stbbdev /** Has tightly controlled interface so that we can verify
4051c0b2f7Stbbdev that parallel_sort uses only the required interface. */
4151c0b2f7Stbbdev class Minimal {
4251c0b2f7Stbbdev int val;
4351c0b2f7Stbbdev public:
set_val(int i)4451c0b2f7Stbbdev void set_val(int i) { val = i; }
Less(const Minimal & a,const Minimal & b)4551c0b2f7Stbbdev static bool Less (const Minimal &a, const Minimal &b) {
4651c0b2f7Stbbdev return (a.val < b.val);
4751c0b2f7Stbbdev }
AreEqual(const Minimal & a,const Minimal & b)48b95bbc9cSIvan Kochin static bool AreEqual( const Minimal &a, const Minimal &b) {
4951c0b2f7Stbbdev return a.val == b.val;
5051c0b2f7Stbbdev }
5151c0b2f7Stbbdev };
5251c0b2f7Stbbdev
5351c0b2f7Stbbdev //! Defines a comparison function object for Minimal
5451c0b2f7Stbbdev class MinimalLessCompare {
5551c0b2f7Stbbdev public:
operator ()(const Minimal & a,const Minimal & b) const5651c0b2f7Stbbdev bool operator() (const Minimal &a, const Minimal &b) const {
5751c0b2f7Stbbdev return Minimal::Less(a,b);
5851c0b2f7Stbbdev }
5951c0b2f7Stbbdev };
6051c0b2f7Stbbdev
61b95bbc9cSIvan Kochin template<typename Value>
compare(const Value & lhs,const Value & rhs)62b95bbc9cSIvan Kochin bool compare(const Value& lhs, const Value& rhs) {
63b95bbc9cSIvan Kochin return lhs == rhs;
64b95bbc9cSIvan Kochin }
65b95bbc9cSIvan Kochin
compare(const Minimal & lhs,const Minimal & rhs)66b95bbc9cSIvan Kochin bool compare(const Minimal& lhs, const Minimal& rhs) {
67b95bbc9cSIvan Kochin return Minimal::AreEqual(lhs, rhs);
68b95bbc9cSIvan Kochin }
69b95bbc9cSIvan Kochin
7051c0b2f7Stbbdev template<typename Range>
validate(Range test_range,Range sorted_range)71b95bbc9cSIvan Kochin void validate(Range test_range, Range sorted_range) {
72b95bbc9cSIvan Kochin using value_type = typename std::iterator_traits<decltype(std::begin(test_range))>::value_type;
73b95bbc9cSIvan Kochin REQUIRE(
74b95bbc9cSIvan Kochin std::equal(std::begin(test_range), std::end(test_range), std::begin(sorted_range),
75b95bbc9cSIvan Kochin [](const value_type& tested, const value_type& reference) {
76b95bbc9cSIvan Kochin return compare(tested, reference);
7751c0b2f7Stbbdev }
78b95bbc9cSIvan Kochin )
79b95bbc9cSIvan Kochin );
8051c0b2f7Stbbdev }
8151c0b2f7Stbbdev
8251c0b2f7Stbbdev //! The default initialization routine.
8351c0b2f7Stbbdev /*! This routine assumes that you can assign to the elements from a float.
8451c0b2f7Stbbdev It assumes that iter and sorted_list have already been allocated. It fills
8551c0b2f7Stbbdev them according to the current data set (tracked by a local static variable).
8651c0b2f7Stbbdev Returns true if a valid test has been setup, or false if there is no test to
8751c0b2f7Stbbdev perform.
8851c0b2f7Stbbdev */
8951c0b2f7Stbbdev template <typename RefType, typename ValueType>
set(RefType & ref,ValueType new_value)9051c0b2f7Stbbdev void set(RefType& ref, ValueType new_value) {
9151c0b2f7Stbbdev ref = static_cast<RefType>(new_value);
9251c0b2f7Stbbdev }
9351c0b2f7Stbbdev
9451c0b2f7Stbbdev template <typename ValueType>
set(Minimal & minimal_ref,ValueType new_value)9551c0b2f7Stbbdev void set(Minimal& minimal_ref, ValueType new_value) {
9651c0b2f7Stbbdev minimal_ref.set_val(static_cast<int>(new_value));
9751c0b2f7Stbbdev }
9851c0b2f7Stbbdev
99b95bbc9cSIvan Kochin template <typename KeyType>
set(std::string & string_ref,KeyType key)100b95bbc9cSIvan Kochin void set(std::string& string_ref, KeyType key) {
101*c7157ce3SVladislav Shchapov string_ref = std::to_string(static_cast<float>(key));
102b95bbc9cSIvan Kochin }
103b95bbc9cSIvan Kochin
104b95bbc9cSIvan Kochin
10551c0b2f7Stbbdev template <typename RandomAccessIterator, typename Compare>
fill_ranges(RandomAccessIterator test_range_begin,RandomAccessIterator sorted_range_begin,std::size_t size,const Compare & compare)10651c0b2f7Stbbdev bool fill_ranges(RandomAccessIterator test_range_begin, RandomAccessIterator sorted_range_begin,
10751c0b2f7Stbbdev std::size_t size, const Compare &compare) {
10851c0b2f7Stbbdev
10951c0b2f7Stbbdev static char test_case = 0;
11051c0b2f7Stbbdev const char num_cases = 3;
11151c0b2f7Stbbdev
11251c0b2f7Stbbdev if (test_case < num_cases) {
11351c0b2f7Stbbdev // switch on the current test case, filling the test_list and sorted_list appropriately
11451c0b2f7Stbbdev switch(test_case) {
11551c0b2f7Stbbdev case 0:
11651c0b2f7Stbbdev /* use sin to generate the values */
11751c0b2f7Stbbdev for (std::size_t i = 0; i < size; i++) {
11851c0b2f7Stbbdev set(test_range_begin[i], sin(float(i)));
11951c0b2f7Stbbdev set(sorted_range_begin[i], sin(float(i)));
12051c0b2f7Stbbdev }
12151c0b2f7Stbbdev break;
12251c0b2f7Stbbdev case 1:
12351c0b2f7Stbbdev /* presorted list */
12451c0b2f7Stbbdev for (std::size_t i = 0; i < size; i++) {
12551c0b2f7Stbbdev set(test_range_begin[i], i);
12651c0b2f7Stbbdev set(sorted_range_begin[i], i);
12751c0b2f7Stbbdev }
12851c0b2f7Stbbdev break;
12951c0b2f7Stbbdev case 2:
13051c0b2f7Stbbdev /* reverse-sorted list */
13151c0b2f7Stbbdev for (std::size_t i = 0; i < size; i++) {
13251c0b2f7Stbbdev set(test_range_begin[i], size - i);
13351c0b2f7Stbbdev set(sorted_range_begin[i], size - i);
13451c0b2f7Stbbdev }
13551c0b2f7Stbbdev break;
13651c0b2f7Stbbdev }
13751c0b2f7Stbbdev
13851c0b2f7Stbbdev // pre-sort sorted_range for later validity testing
13951c0b2f7Stbbdev std::sort(sorted_range_begin, sorted_range_begin + size, compare);
14051c0b2f7Stbbdev test_case++;
14151c0b2f7Stbbdev return true;
14251c0b2f7Stbbdev }
14351c0b2f7Stbbdev test_case = 0;
14451c0b2f7Stbbdev return false;
14551c0b2f7Stbbdev }
14651c0b2f7Stbbdev
14751c0b2f7Stbbdev //! The default test routine.
14851c0b2f7Stbbdev /*! Tests all data set sizes from 0 to N, all grainsizes from 0 to G=10, and selects from
14951c0b2f7Stbbdev all possible interfaces to parallel_sort depending on whether a scratch space and
15051c0b2f7Stbbdev compare have been provided.
15151c0b2f7Stbbdev */
152b95bbc9cSIvan Kochin template<typename ContainerType, std::size_t Size>
15351c0b2f7Stbbdev struct parallel_sort_test {
runparallel_sort_test15451c0b2f7Stbbdev static void run() {
155b95bbc9cSIvan Kochin std::less<typename ContainerType::value_type> default_comp;
156b95bbc9cSIvan Kochin ContainerType range(Size);
157b95bbc9cSIvan Kochin ContainerType sorted_range(Size);
15851c0b2f7Stbbdev
159b95bbc9cSIvan Kochin while (fill_ranges(std::begin(range), std::begin(sorted_range), Size, default_comp)) {
160b95bbc9cSIvan Kochin tbb::parallel_sort(range);
161b95bbc9cSIvan Kochin validate(range, sorted_range);
16251c0b2f7Stbbdev }
16351c0b2f7Stbbdev }
16451c0b2f7Stbbdev
16551c0b2f7Stbbdev template<typename Comparator>
runparallel_sort_test16651c0b2f7Stbbdev static void run(Comparator& comp) {
167b95bbc9cSIvan Kochin ContainerType range(Size);
168b95bbc9cSIvan Kochin ContainerType sorted_range(Size);
16951c0b2f7Stbbdev
170b95bbc9cSIvan Kochin while (fill_ranges(std::begin(range), std::begin(sorted_range), Size, comp)) {
171b95bbc9cSIvan Kochin tbb::parallel_sort(range, comp);
172b95bbc9cSIvan Kochin validate(range, sorted_range);
17351c0b2f7Stbbdev }
17451c0b2f7Stbbdev }
17551c0b2f7Stbbdev };
17651c0b2f7Stbbdev
177b95bbc9cSIvan Kochin template<typename ContainerType, typename Comparator>
parallel_sort_test_suite()17851c0b2f7Stbbdev void parallel_sort_test_suite() {
17951c0b2f7Stbbdev Comparator comp;
18051c0b2f7Stbbdev for (auto concurrency_level : utils::concurrency_range()) {
18151c0b2f7Stbbdev tbb::global_control control(tbb::global_control::max_allowed_parallelism, concurrency_level);
182b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/0 >::run(comp);
183b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/1 >::run(comp);
184b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/10 >::run(comp);
185b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/9999 >::run(comp);
186b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/50000>::run(comp);
18751c0b2f7Stbbdev }
18851c0b2f7Stbbdev }
18951c0b2f7Stbbdev
190b95bbc9cSIvan Kochin template<typename ContainerType>
parallel_sort_test_suite()19151c0b2f7Stbbdev void parallel_sort_test_suite() {
19251c0b2f7Stbbdev for (auto concurrency_level : utils::concurrency_range()) {
19351c0b2f7Stbbdev tbb::global_control control(tbb::global_control::max_allowed_parallelism, concurrency_level);
194b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/0 >::run();
195b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/1 >::run();
196b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/10 >::run();
197b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/9999 >::run();
198b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/50000>::run();
19951c0b2f7Stbbdev }
20051c0b2f7Stbbdev }
20151c0b2f7Stbbdev
202478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT
203478de5b1Stbbdev template <typename RandomAccessIterator>
204478de5b1Stbbdev concept can_call_parallel_sort_with_iterator = requires( RandomAccessIterator it ) {
205478de5b1Stbbdev tbb::parallel_sort(it, it);
206478de5b1Stbbdev };
207478de5b1Stbbdev
208478de5b1Stbbdev template <typename RandomAccessIterator, typename Compare>
209478de5b1Stbbdev concept can_call_parallel_sort_with_iterator_and_compare = requires( RandomAccessIterator it, const Compare& compare ) {
210478de5b1Stbbdev tbb::parallel_sort(it, it, compare);
211478de5b1Stbbdev };
212478de5b1Stbbdev
213478de5b1Stbbdev template <typename CBS>
214478de5b1Stbbdev concept can_call_parallel_sort_with_cbs = requires( CBS& cbs ) {
215478de5b1Stbbdev tbb::parallel_sort(cbs);
216478de5b1Stbbdev };
217478de5b1Stbbdev
218478de5b1Stbbdev template <typename CBS, typename Compare>
219478de5b1Stbbdev concept can_call_parallel_sort_with_cbs_and_compare = requires( CBS& cbs, const Compare& compare ) {
220478de5b1Stbbdev tbb::parallel_sort(cbs, compare);
221478de5b1Stbbdev };
222478de5b1Stbbdev
223478de5b1Stbbdev template <typename T>
224478de5b1Stbbdev using CorrectCompare = test_concepts::compare::Correct<T>;
225478de5b1Stbbdev
test_psort_iterator_constraints()226478de5b1Stbbdev void test_psort_iterator_constraints() {
2274eec89feSIvan Kochin using namespace test_concepts::parallel_sort_value;
2284eec89feSIvan Kochin
229478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator<utils::RandomIterator<int>>);
230478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator<typename std::vector<int>::iterator>);
231478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator<utils::ForwardIterator<int>>);
232478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator<utils::InputIterator<int>>);
2334eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<utils::RandomIterator<NonMovableValue>>);
2344eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<utils::RandomIterator<NonMoveAssignableValue>>);
2354eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<utils::RandomIterator<NonComparableValue>>);
2364eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<test_concepts::ConstantIT<int>>);
237478de5b1Stbbdev
238478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<utils::RandomIterator<int>, CorrectCompare<int>>);
239478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<typename std::vector<int>::iterator, CorrectCompare<int>>);
240478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::ForwardIterator<int>, CorrectCompare<int>>);
241478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::InputIterator<int>, CorrectCompare<int>>);
2424eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::RandomIterator<NonMovableValue>, CorrectCompare<NonMovableValue>>);
2434eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::RandomIterator<NonMoveAssignableValue>, CorrectCompare<NonMoveAssignableValue>>);
2444eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator_and_compare<test_concepts::ConstantIT<int>, CorrectCompare<const int>>);
245478de5b1Stbbdev }
246478de5b1Stbbdev
test_psort_compare_constraints()247478de5b1Stbbdev void test_psort_compare_constraints() {
248478de5b1Stbbdev using namespace test_concepts::compare;
2494eec89feSIvan Kochin
250478de5b1Stbbdev using CorrectCBS = test_concepts::container_based_sequence::Correct;
2514eec89feSIvan Kochin using CorrectIterator = CorrectCBS::iterator;
252478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, Correct<int>>);
253478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, NoOperatorRoundBrackets<int>>);
254478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongFirstInputOperatorRoundBrackets<int>>);
255478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongSecondInputOperatorRoundBrackets<int>>);
256478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongReturnOperatorRoundBrackets<int>>);
257478de5b1Stbbdev
258478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, Correct<int>>);
259478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, NoOperatorRoundBrackets<int>>);
260478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongFirstInputOperatorRoundBrackets<int>>);
261478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongSecondInputOperatorRoundBrackets<int>>);
262478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongReturnOperatorRoundBrackets<int>>);
263478de5b1Stbbdev }
264478de5b1Stbbdev
test_psort_cbs_constraints()265478de5b1Stbbdev void test_psort_cbs_constraints() {
266478de5b1Stbbdev using namespace test_concepts::container_based_sequence;
2674eec89feSIvan Kochin using namespace test_concepts::parallel_sort_value;
2684eec89feSIvan Kochin
269478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs<Correct>);
270478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<NoBegin>);
271478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<NoEnd>);
272478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<ForwardIteratorCBS>);
2734eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<ConstantCBS>);
274478de5b1Stbbdev
2754eec89feSIvan Kochin static_assert(can_call_parallel_sort_with_cbs<CustomValueCBS<CorrectValue>>);
2764eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<CustomValueCBS<NonMovableValue>>);
2774eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<CustomValueCBS<NonMoveAssignableValue>>);
2784eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<CustomValueCBS<NonComparableValue>>);\
2794eec89feSIvan Kochin
2804eec89feSIvan Kochin using CorrectCompare = test_concepts::compare::Correct<int>;
2814eec89feSIvan Kochin using NonMovableCompare = test_concepts::compare::Correct<NonMovableValue>;
2824eec89feSIvan Kochin using NonMoveAssignableCompare = test_concepts::compare::Correct<NonMoveAssignableValue>;
283478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs_and_compare<Correct, CorrectCompare>);
284478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<NoBegin, CorrectCompare>);
285478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<NoEnd, CorrectCompare>);
286478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<ForwardIteratorCBS, CorrectCompare>);
2874eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs_and_compare<ConstantCBS, CorrectCompare>);
2884eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs_and_compare<CustomValueCBS<NonMovableValue>, NonMovableCompare>);
2894eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs_and_compare<CustomValueCBS<NonMoveAssignableValue>, NonMoveAssignableCompare>);
290478de5b1Stbbdev }
291478de5b1Stbbdev
292478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT
293478de5b1Stbbdev
294b95bbc9cSIvan Kochin template<typename T>
295b95bbc9cSIvan Kochin struct minimal_span {
minimal_spanminimal_span296b95bbc9cSIvan Kochin minimal_span(T* input_data, std::size_t input_size)
297b95bbc9cSIvan Kochin : data{input_data}
298b95bbc9cSIvan Kochin , size{input_size}
299b95bbc9cSIvan Kochin {}
300b95bbc9cSIvan Kochin
beginminimal_span301b95bbc9cSIvan Kochin T* begin() const {
302b95bbc9cSIvan Kochin return data;
303b95bbc9cSIvan Kochin }
endminimal_span304b95bbc9cSIvan Kochin T* end() const {
305b95bbc9cSIvan Kochin return data + size;
306b95bbc9cSIvan Kochin }
307b95bbc9cSIvan Kochin private:
308b95bbc9cSIvan Kochin T* data;
309b95bbc9cSIvan Kochin std::size_t size;
310b95bbc9cSIvan Kochin };
311b95bbc9cSIvan Kochin
31251c0b2f7Stbbdev //! Minimal array sorting test (less comparator)
31351c0b2f7Stbbdev //! \brief \ref error_guessing
31451c0b2f7Stbbdev TEST_CASE("Minimal array sorting test (less comparator)") {
315b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<Minimal>, MinimalLessCompare>();
31651c0b2f7Stbbdev }
31751c0b2f7Stbbdev
31851c0b2f7Stbbdev //! Float array sorting test (default comparator)
31951c0b2f7Stbbdev //! \brief \ref error_guessing
32051c0b2f7Stbbdev TEST_CASE("Float array sorting test (default comparator)") {
321b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<float>>();
32251c0b2f7Stbbdev }
32351c0b2f7Stbbdev
32451c0b2f7Stbbdev //! tbb::concurrent_vector<float> sorting test (less comparator)
32551c0b2f7Stbbdev //! \brief \ref error_guessing
32651c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<float> sorting test (less comparator)") {
32751c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<float>, std::less<float>>();
32851c0b2f7Stbbdev }
32951c0b2f7Stbbdev
33051c0b2f7Stbbdev //! tbb::concurrent_vector<float> sorting test (default comparator)
33151c0b2f7Stbbdev //! \brief \ref error_guessing
33251c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<float> sorting test (default comparator)") {
33351c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<float>>();
33451c0b2f7Stbbdev }
33551c0b2f7Stbbdev
33651c0b2f7Stbbdev //! Array of strings sorting test (less comparator)
33751c0b2f7Stbbdev //! \brief \ref error_guessing
33851c0b2f7Stbbdev TEST_CASE("Array of strings sorting test (less comparator)") {
339b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<std::string>, std::less<std::string>>();
34051c0b2f7Stbbdev }
34151c0b2f7Stbbdev
34251c0b2f7Stbbdev //! Array of strings sorting test (default comparator)
34351c0b2f7Stbbdev //! \brief \ref error_guessing
34451c0b2f7Stbbdev TEST_CASE("Array of strings sorting test (default comparator)") {
345b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<std::string>>();
34651c0b2f7Stbbdev }
34751c0b2f7Stbbdev
34851c0b2f7Stbbdev //! tbb::concurrent_vector<Minimal> sorting test (less comparator)
34951c0b2f7Stbbdev //! \brief \ref error_guessing
35051c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<Minimal> sorting test (less comparator)") {
35151c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<Minimal>, MinimalLessCompare>();
35251c0b2f7Stbbdev }
35351c0b2f7Stbbdev
354b95bbc9cSIvan Kochin constexpr std::size_t array_size = 10000;
355b95bbc9cSIvan Kochin
356b95bbc9cSIvan Kochin template<typename SortFunctor>
sort_array_test(const SortFunctor & sort_functor)357b95bbc9cSIvan Kochin void sort_array_test(const SortFunctor& sort_functor) {
358b95bbc9cSIvan Kochin int test_array[array_size];
359b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i)
360b95bbc9cSIvan Kochin test_array[i] = rand() % array_size;
361b95bbc9cSIvan Kochin
362b95bbc9cSIvan Kochin sort_functor(test_array);
363b95bbc9cSIvan Kochin
364b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size - 1; ++i)
365b95bbc9cSIvan Kochin REQUIRE_MESSAGE(test_array[i] <= test_array[i + 1], "Testing data not sorted");
366b95bbc9cSIvan Kochin }
36751c0b2f7Stbbdev
36851c0b2f7Stbbdev //! Array sorting test (default comparator)
36951c0b2f7Stbbdev //! \brief \ref error_guessing
37051c0b2f7Stbbdev TEST_CASE("Array sorting test (default comparator)") {
37151c0b2f7Stbbdev for ( auto concurrency_level : utils::concurrency_range() ) {
37251c0b2f7Stbbdev tbb::global_control control(tbb::global_control::max_allowed_parallelism, concurrency_level);
__anon54e49e5e0202(int (&array)[array_size]) 373b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) {
374b95bbc9cSIvan Kochin tbb::parallel_sort(array);
375b95bbc9cSIvan Kochin });
37651c0b2f7Stbbdev }
37751c0b2f7Stbbdev }
37851c0b2f7Stbbdev
379b95bbc9cSIvan Kochin //! Test array sorting via rvalue span (default comparator)
380b95bbc9cSIvan Kochin //! \brief \ref error_guessing
381b95bbc9cSIvan Kochin TEST_CASE("Test array sorting via rvalue span (default comparator)") {
__anon54e49e5e0302(int (&array)[array_size]) 382b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) {
383b95bbc9cSIvan Kochin tbb::parallel_sort(minimal_span<int>{array, array_size});
384b95bbc9cSIvan Kochin });
385b95bbc9cSIvan Kochin }
386b95bbc9cSIvan Kochin
387b95bbc9cSIvan Kochin //! Test array sorting via const span (default comparator)
388b95bbc9cSIvan Kochin //! \brief \ref error_guessing
389b95bbc9cSIvan Kochin TEST_CASE("Test array sorting via const span (default comparator)") {
__anon54e49e5e0402(int (&array)[array_size]) 390b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) {
391b95bbc9cSIvan Kochin const minimal_span<int> span(array, array_size);
392b95bbc9cSIvan Kochin tbb::parallel_sort(span);
393b95bbc9cSIvan Kochin });
394b95bbc9cSIvan Kochin }
395b95bbc9cSIvan Kochin
396b95bbc9cSIvan Kochin //! Test rvalue container with stateful comparator
397b95bbc9cSIvan Kochin //! \brief \ref error_guessing
398b95bbc9cSIvan Kochin TEST_CASE("Test rvalue container with stateful comparator") {
399b95bbc9cSIvan Kochin // Create sorted range
400b95bbc9cSIvan Kochin std::vector<std::size_t> test_vector(array_size);
401b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i)
402b95bbc9cSIvan Kochin test_vector[i] = i;
403b95bbc9cSIvan Kochin
404b95bbc9cSIvan Kochin std::atomic<std::size_t> count{0};
__anon54e49e5e0502(std::size_t lhs, std::size_t rhs) 405b95bbc9cSIvan Kochin tbb::parallel_sort(std::move(test_vector), [&](std::size_t lhs, std::size_t rhs) {
406b95bbc9cSIvan Kochin ++count;
407b95bbc9cSIvan Kochin return lhs < rhs;
408b95bbc9cSIvan Kochin });
409b95bbc9cSIvan Kochin
410b95bbc9cSIvan Kochin // The comparator should be called at least (size - 1) times to check that the array is sorted
411b95bbc9cSIvan Kochin REQUIRE_MESSAGE(count >= array_size - 1, "Incorrect comparator calls count");
412b95bbc9cSIvan Kochin }
413b95bbc9cSIvan Kochin
41451c0b2f7Stbbdev //! Testing workers going to sleep
41551c0b2f7Stbbdev //! \brief \ref resource_usage
41651c0b2f7Stbbdev TEST_CASE("That all workers sleep when no work") {
417b95bbc9cSIvan Kochin int test_array[array_size];
418b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i)
419b95bbc9cSIvan Kochin test_array[i] = rand() % array_size;
42051c0b2f7Stbbdev
42151c0b2f7Stbbdev tbb::parallel_sort(test_array);
42251c0b2f7Stbbdev TestCPUUserTime(utils::get_platform_max_threads());
42351c0b2f7Stbbdev }
424478de5b1Stbbdev
425478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT
426478de5b1Stbbdev //! \brief \ref error_guessing
427478de5b1Stbbdev TEST_CASE("parallel_sort constraints") {
428478de5b1Stbbdev test_psort_iterator_constraints();
429478de5b1Stbbdev test_psort_compare_constraints();
430478de5b1Stbbdev test_psort_cbs_constraints();
431478de5b1Stbbdev }
432478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT
433