xref: /oneTBB/test/tbb/test_parallel_sort.cpp (revision c7157ce3)
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