151c0b2f7Stbbdev /* 2b15aabb3Stbbdev Copyright (c) 2005-2021 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> 3351c0b2f7Stbbdev #include <cstdio> 34*b95bbc9cSIvan Kochin #include <iterator> 35*b95bbc9cSIvan Kochin #include <type_traits> 3651c0b2f7Stbbdev 3751c0b2f7Stbbdev //! \file test_parallel_sort.cpp 3851c0b2f7Stbbdev //! \brief Test for [algorithms.parallel_sort] 3951c0b2f7Stbbdev 4051c0b2f7Stbbdev /** Has tightly controlled interface so that we can verify 4151c0b2f7Stbbdev that parallel_sort uses only the required interface. */ 4251c0b2f7Stbbdev class Minimal { 4351c0b2f7Stbbdev int val; 4451c0b2f7Stbbdev public: 4551c0b2f7Stbbdev void set_val(int i) { val = i; } 4651c0b2f7Stbbdev static bool Less (const Minimal &a, const Minimal &b) { 4751c0b2f7Stbbdev return (a.val < b.val); 4851c0b2f7Stbbdev } 49*b95bbc9cSIvan Kochin static bool AreEqual( const Minimal &a, const Minimal &b) { 5051c0b2f7Stbbdev return a.val == b.val; 5151c0b2f7Stbbdev } 5251c0b2f7Stbbdev }; 5351c0b2f7Stbbdev 5451c0b2f7Stbbdev //! Defines a comparison function object for Minimal 5551c0b2f7Stbbdev class MinimalLessCompare { 5651c0b2f7Stbbdev public: 5751c0b2f7Stbbdev bool operator() (const Minimal &a, const Minimal &b) const { 5851c0b2f7Stbbdev return Minimal::Less(a,b); 5951c0b2f7Stbbdev } 6051c0b2f7Stbbdev }; 6151c0b2f7Stbbdev 62*b95bbc9cSIvan Kochin template<typename Value> 63*b95bbc9cSIvan Kochin bool compare(const Value& lhs, const Value& rhs) { 64*b95bbc9cSIvan Kochin return lhs == rhs; 65*b95bbc9cSIvan Kochin } 66*b95bbc9cSIvan Kochin 67*b95bbc9cSIvan Kochin bool compare(const Minimal& lhs, const Minimal& rhs) { 68*b95bbc9cSIvan Kochin return Minimal::AreEqual(lhs, rhs); 69*b95bbc9cSIvan Kochin } 70*b95bbc9cSIvan Kochin 7151c0b2f7Stbbdev template<typename Range> 72*b95bbc9cSIvan Kochin void validate(Range test_range, Range sorted_range) { 73*b95bbc9cSIvan Kochin using value_type = typename std::iterator_traits<decltype(std::begin(test_range))>::value_type; 74*b95bbc9cSIvan Kochin REQUIRE( 75*b95bbc9cSIvan Kochin std::equal(std::begin(test_range), std::end(test_range), std::begin(sorted_range), 76*b95bbc9cSIvan Kochin [](const value_type& tested, const value_type& reference) { 77*b95bbc9cSIvan Kochin return compare(tested, reference); 7851c0b2f7Stbbdev } 79*b95bbc9cSIvan Kochin ) 80*b95bbc9cSIvan Kochin ); 8151c0b2f7Stbbdev } 8251c0b2f7Stbbdev 8351c0b2f7Stbbdev //! The default initialization routine. 8451c0b2f7Stbbdev /*! This routine assumes that you can assign to the elements from a float. 8551c0b2f7Stbbdev It assumes that iter and sorted_list have already been allocated. It fills 8651c0b2f7Stbbdev them according to the current data set (tracked by a local static variable). 8751c0b2f7Stbbdev Returns true if a valid test has been setup, or false if there is no test to 8851c0b2f7Stbbdev perform. 8951c0b2f7Stbbdev */ 9051c0b2f7Stbbdev template <typename RefType, typename ValueType> 9151c0b2f7Stbbdev void set(RefType& ref, ValueType new_value) { 9251c0b2f7Stbbdev ref = static_cast<RefType>(new_value); 9351c0b2f7Stbbdev } 9451c0b2f7Stbbdev 9551c0b2f7Stbbdev template <typename ValueType> 9651c0b2f7Stbbdev void set(Minimal& minimal_ref, ValueType new_value) { 9751c0b2f7Stbbdev minimal_ref.set_val(static_cast<int>(new_value)); 9851c0b2f7Stbbdev } 9951c0b2f7Stbbdev 100*b95bbc9cSIvan Kochin template <typename KeyType> 101*b95bbc9cSIvan Kochin void set(std::string& string_ref, KeyType key) { 102*b95bbc9cSIvan Kochin static char buffer[20]; 103*b95bbc9cSIvan Kochin #if _MSC_VER && __STDC_SECURE_LIB__>=200411 104*b95bbc9cSIvan Kochin sprintf_s(buffer, sizeof(buffer), "%f", static_cast<float>(key)); 105*b95bbc9cSIvan Kochin #else 106*b95bbc9cSIvan Kochin sprintf(buffer, "%f", static_cast<float>(key)); 107*b95bbc9cSIvan Kochin #endif 108*b95bbc9cSIvan Kochin string_ref = buffer; 109*b95bbc9cSIvan Kochin } 110*b95bbc9cSIvan Kochin 111*b95bbc9cSIvan Kochin 11251c0b2f7Stbbdev template <typename RandomAccessIterator, typename Compare> 11351c0b2f7Stbbdev bool fill_ranges(RandomAccessIterator test_range_begin, RandomAccessIterator sorted_range_begin, 11451c0b2f7Stbbdev std::size_t size, const Compare &compare) { 11551c0b2f7Stbbdev 11651c0b2f7Stbbdev static char test_case = 0; 11751c0b2f7Stbbdev const char num_cases = 3; 11851c0b2f7Stbbdev 11951c0b2f7Stbbdev if (test_case < num_cases) { 12051c0b2f7Stbbdev // switch on the current test case, filling the test_list and sorted_list appropriately 12151c0b2f7Stbbdev switch(test_case) { 12251c0b2f7Stbbdev case 0: 12351c0b2f7Stbbdev /* use sin to generate the values */ 12451c0b2f7Stbbdev for (std::size_t i = 0; i < size; i++) { 12551c0b2f7Stbbdev set(test_range_begin[i], sin(float(i))); 12651c0b2f7Stbbdev set(sorted_range_begin[i], sin(float(i))); 12751c0b2f7Stbbdev } 12851c0b2f7Stbbdev break; 12951c0b2f7Stbbdev case 1: 13051c0b2f7Stbbdev /* presorted list */ 13151c0b2f7Stbbdev for (std::size_t i = 0; i < size; i++) { 13251c0b2f7Stbbdev set(test_range_begin[i], i); 13351c0b2f7Stbbdev set(sorted_range_begin[i], i); 13451c0b2f7Stbbdev } 13551c0b2f7Stbbdev break; 13651c0b2f7Stbbdev case 2: 13751c0b2f7Stbbdev /* reverse-sorted list */ 13851c0b2f7Stbbdev for (std::size_t i = 0; i < size; i++) { 13951c0b2f7Stbbdev set(test_range_begin[i], size - i); 14051c0b2f7Stbbdev set(sorted_range_begin[i], size - i); 14151c0b2f7Stbbdev } 14251c0b2f7Stbbdev break; 14351c0b2f7Stbbdev } 14451c0b2f7Stbbdev 14551c0b2f7Stbbdev // pre-sort sorted_range for later validity testing 14651c0b2f7Stbbdev std::sort(sorted_range_begin, sorted_range_begin + size, compare); 14751c0b2f7Stbbdev test_case++; 14851c0b2f7Stbbdev return true; 14951c0b2f7Stbbdev } 15051c0b2f7Stbbdev test_case = 0; 15151c0b2f7Stbbdev return false; 15251c0b2f7Stbbdev } 15351c0b2f7Stbbdev 15451c0b2f7Stbbdev //! The default test routine. 15551c0b2f7Stbbdev /*! Tests all data set sizes from 0 to N, all grainsizes from 0 to G=10, and selects from 15651c0b2f7Stbbdev all possible interfaces to parallel_sort depending on whether a scratch space and 15751c0b2f7Stbbdev compare have been provided. 15851c0b2f7Stbbdev */ 159*b95bbc9cSIvan Kochin template<typename ContainerType, std::size_t Size> 16051c0b2f7Stbbdev struct parallel_sort_test { 16151c0b2f7Stbbdev static void run() { 162*b95bbc9cSIvan Kochin std::less<typename ContainerType::value_type> default_comp; 163*b95bbc9cSIvan Kochin ContainerType range(Size); 164*b95bbc9cSIvan Kochin ContainerType sorted_range(Size); 16551c0b2f7Stbbdev 166*b95bbc9cSIvan Kochin while (fill_ranges(std::begin(range), std::begin(sorted_range), Size, default_comp)) { 167*b95bbc9cSIvan Kochin tbb::parallel_sort(range); 168*b95bbc9cSIvan Kochin validate(range, sorted_range); 16951c0b2f7Stbbdev } 17051c0b2f7Stbbdev } 17151c0b2f7Stbbdev 17251c0b2f7Stbbdev template<typename Comparator> 17351c0b2f7Stbbdev static void run(Comparator& comp) { 174*b95bbc9cSIvan Kochin ContainerType range(Size); 175*b95bbc9cSIvan Kochin ContainerType sorted_range(Size); 17651c0b2f7Stbbdev 177*b95bbc9cSIvan Kochin while (fill_ranges(std::begin(range), std::begin(sorted_range), Size, comp)) { 178*b95bbc9cSIvan Kochin tbb::parallel_sort(range, comp); 179*b95bbc9cSIvan Kochin validate(range, sorted_range); 18051c0b2f7Stbbdev } 18151c0b2f7Stbbdev } 18251c0b2f7Stbbdev }; 18351c0b2f7Stbbdev 184*b95bbc9cSIvan Kochin template<typename ContainerType, typename Comparator> 18551c0b2f7Stbbdev void parallel_sort_test_suite() { 18651c0b2f7Stbbdev Comparator comp; 18751c0b2f7Stbbdev for (auto concurrency_level : utils::concurrency_range()) { 18851c0b2f7Stbbdev tbb::global_control control(tbb::global_control::max_allowed_parallelism, concurrency_level); 189*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/0 >::run(comp); 190*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/1 >::run(comp); 191*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/10 >::run(comp); 192*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/9999 >::run(comp); 193*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/50000>::run(comp); 19451c0b2f7Stbbdev } 19551c0b2f7Stbbdev } 19651c0b2f7Stbbdev 197*b95bbc9cSIvan Kochin template<typename ContainerType> 19851c0b2f7Stbbdev void parallel_sort_test_suite() { 19951c0b2f7Stbbdev for (auto concurrency_level : utils::concurrency_range()) { 20051c0b2f7Stbbdev tbb::global_control control(tbb::global_control::max_allowed_parallelism, concurrency_level); 201*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/0 >::run(); 202*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/1 >::run(); 203*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/10 >::run(); 204*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/9999 >::run(); 205*b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/50000>::run(); 20651c0b2f7Stbbdev } 20751c0b2f7Stbbdev } 20851c0b2f7Stbbdev 209478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT 210478de5b1Stbbdev template <typename RandomAccessIterator> 211478de5b1Stbbdev concept can_call_parallel_sort_with_iterator = requires( RandomAccessIterator it ) { 212478de5b1Stbbdev tbb::parallel_sort(it, it); 213478de5b1Stbbdev }; 214478de5b1Stbbdev 215478de5b1Stbbdev template <typename RandomAccessIterator, typename Compare> 216478de5b1Stbbdev concept can_call_parallel_sort_with_iterator_and_compare = requires( RandomAccessIterator it, const Compare& compare ) { 217478de5b1Stbbdev tbb::parallel_sort(it, it, compare); 218478de5b1Stbbdev }; 219478de5b1Stbbdev 220478de5b1Stbbdev template <typename CBS> 221478de5b1Stbbdev concept can_call_parallel_sort_with_cbs = requires( CBS& cbs ) { 222478de5b1Stbbdev tbb::parallel_sort(cbs); 223478de5b1Stbbdev }; 224478de5b1Stbbdev 225478de5b1Stbbdev template <typename CBS, typename Compare> 226478de5b1Stbbdev concept can_call_parallel_sort_with_cbs_and_compare = requires( CBS& cbs, const Compare& compare ) { 227478de5b1Stbbdev tbb::parallel_sort(cbs, compare); 228478de5b1Stbbdev }; 229478de5b1Stbbdev 230478de5b1Stbbdev template <typename T> 231478de5b1Stbbdev using CorrectCompare = test_concepts::compare::Correct<T>; 232478de5b1Stbbdev 233478de5b1Stbbdev void test_psort_iterator_constraints() { 234478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator<utils::RandomIterator<int>>); 235478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator<typename std::vector<int>::iterator>); 236478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator<utils::ForwardIterator<int>>); 237478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator<utils::InputIterator<int>>); 238478de5b1Stbbdev 239478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<utils::RandomIterator<int>, CorrectCompare<int>>); 240478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<typename std::vector<int>::iterator, CorrectCompare<int>>); 241478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::ForwardIterator<int>, CorrectCompare<int>>); 242478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::InputIterator<int>, CorrectCompare<int>>); 243478de5b1Stbbdev } 244478de5b1Stbbdev 245478de5b1Stbbdev void test_psort_compare_constraints() { 246478de5b1Stbbdev using namespace test_concepts::compare; 247478de5b1Stbbdev using CorrectIterator = test_concepts::container_based_sequence::iterator; 248478de5b1Stbbdev using CorrectCBS = test_concepts::container_based_sequence::Correct; 249478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, Correct<int>>); 250478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, NoOperatorRoundBrackets<int>>); 251478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongFirstInputOperatorRoundBrackets<int>>); 252478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongSecondInputOperatorRoundBrackets<int>>); 253478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongReturnOperatorRoundBrackets<int>>); 254478de5b1Stbbdev 255478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, Correct<int>>); 256478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, NoOperatorRoundBrackets<int>>); 257478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongFirstInputOperatorRoundBrackets<int>>); 258478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongSecondInputOperatorRoundBrackets<int>>); 259478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongReturnOperatorRoundBrackets<int>>); 260478de5b1Stbbdev } 261478de5b1Stbbdev 262478de5b1Stbbdev void test_psort_cbs_constraints() { 263478de5b1Stbbdev using namespace test_concepts::container_based_sequence; 264478de5b1Stbbdev using CorrectCompare = test_concepts::compare::Correct<int>; 265478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs<Correct>); 266478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<NoBegin>); 267478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<NoEnd>); 268478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<ForwardIteratorCBS>); 269478de5b1Stbbdev 270478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs_and_compare<Correct, CorrectCompare>); 271478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<NoBegin, CorrectCompare>); 272478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<NoEnd, CorrectCompare>); 273478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<ForwardIteratorCBS, CorrectCompare>); 274478de5b1Stbbdev } 275478de5b1Stbbdev 276478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT 277478de5b1Stbbdev 278*b95bbc9cSIvan Kochin template<typename T> 279*b95bbc9cSIvan Kochin struct minimal_span { 280*b95bbc9cSIvan Kochin minimal_span(T* input_data, std::size_t input_size) 281*b95bbc9cSIvan Kochin : data{input_data} 282*b95bbc9cSIvan Kochin , size{input_size} 283*b95bbc9cSIvan Kochin {} 284*b95bbc9cSIvan Kochin 285*b95bbc9cSIvan Kochin T* begin() const { 286*b95bbc9cSIvan Kochin return data; 287*b95bbc9cSIvan Kochin } 288*b95bbc9cSIvan Kochin T* end() const { 289*b95bbc9cSIvan Kochin return data + size; 290*b95bbc9cSIvan Kochin } 291*b95bbc9cSIvan Kochin private: 292*b95bbc9cSIvan Kochin T* data; 293*b95bbc9cSIvan Kochin std::size_t size; 294*b95bbc9cSIvan Kochin }; 295*b95bbc9cSIvan Kochin 29651c0b2f7Stbbdev //! Minimal array sorting test (less comparator) 29751c0b2f7Stbbdev //! \brief \ref error_guessing 29851c0b2f7Stbbdev TEST_CASE("Minimal array sorting test (less comparator)") { 299*b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<Minimal>, MinimalLessCompare>(); 30051c0b2f7Stbbdev } 30151c0b2f7Stbbdev 30251c0b2f7Stbbdev //! Float array sorting test (default comparator) 30351c0b2f7Stbbdev //! \brief \ref error_guessing 30451c0b2f7Stbbdev TEST_CASE("Float array sorting test (default comparator)") { 305*b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<float>>(); 30651c0b2f7Stbbdev } 30751c0b2f7Stbbdev 30851c0b2f7Stbbdev //! tbb::concurrent_vector<float> sorting test (less comparator) 30951c0b2f7Stbbdev //! \brief \ref error_guessing 31051c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<float> sorting test (less comparator)") { 31151c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<float>, std::less<float>>(); 31251c0b2f7Stbbdev } 31351c0b2f7Stbbdev 31451c0b2f7Stbbdev //! tbb::concurrent_vector<float> sorting test (default comparator) 31551c0b2f7Stbbdev //! \brief \ref error_guessing 31651c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<float> sorting test (default comparator)") { 31751c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<float>>(); 31851c0b2f7Stbbdev } 31951c0b2f7Stbbdev 32051c0b2f7Stbbdev //! Array of strings sorting test (less comparator) 32151c0b2f7Stbbdev //! \brief \ref error_guessing 32251c0b2f7Stbbdev TEST_CASE("Array of strings sorting test (less comparator)") { 323*b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<std::string>, std::less<std::string>>(); 32451c0b2f7Stbbdev } 32551c0b2f7Stbbdev 32651c0b2f7Stbbdev //! Array of strings sorting test (default comparator) 32751c0b2f7Stbbdev //! \brief \ref error_guessing 32851c0b2f7Stbbdev TEST_CASE("Array of strings sorting test (default comparator)") { 329*b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<std::string>>(); 33051c0b2f7Stbbdev } 33151c0b2f7Stbbdev 33251c0b2f7Stbbdev //! tbb::concurrent_vector<Minimal> sorting test (less comparator) 33351c0b2f7Stbbdev //! \brief \ref error_guessing 33451c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<Minimal> sorting test (less comparator)") { 33551c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<Minimal>, MinimalLessCompare>(); 33651c0b2f7Stbbdev } 33751c0b2f7Stbbdev 338*b95bbc9cSIvan Kochin constexpr std::size_t array_size = 10000; 339*b95bbc9cSIvan Kochin 340*b95bbc9cSIvan Kochin template<typename SortFunctor> 341*b95bbc9cSIvan Kochin void sort_array_test(const SortFunctor& sort_functor) { 342*b95bbc9cSIvan Kochin int test_array[array_size]; 343*b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i) 344*b95bbc9cSIvan Kochin test_array[i] = rand() % array_size; 345*b95bbc9cSIvan Kochin 346*b95bbc9cSIvan Kochin sort_functor(test_array); 347*b95bbc9cSIvan Kochin 348*b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size - 1; ++i) 349*b95bbc9cSIvan Kochin REQUIRE_MESSAGE(test_array[i] <= test_array[i + 1], "Testing data not sorted"); 350*b95bbc9cSIvan Kochin } 35151c0b2f7Stbbdev 35251c0b2f7Stbbdev //! Array sorting test (default comparator) 35351c0b2f7Stbbdev //! \brief \ref error_guessing 35451c0b2f7Stbbdev TEST_CASE("Array sorting test (default comparator)") { 35551c0b2f7Stbbdev for ( auto concurrency_level : utils::concurrency_range() ) { 35651c0b2f7Stbbdev tbb::global_control control(tbb::global_control::max_allowed_parallelism, concurrency_level); 357*b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) { 358*b95bbc9cSIvan Kochin tbb::parallel_sort(array); 359*b95bbc9cSIvan Kochin }); 36051c0b2f7Stbbdev } 36151c0b2f7Stbbdev } 36251c0b2f7Stbbdev 363*b95bbc9cSIvan Kochin //! Test array sorting via rvalue span (default comparator) 364*b95bbc9cSIvan Kochin //! \brief \ref error_guessing 365*b95bbc9cSIvan Kochin TEST_CASE("Test array sorting via rvalue span (default comparator)") { 366*b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) { 367*b95bbc9cSIvan Kochin tbb::parallel_sort(minimal_span<int>{array, array_size}); 368*b95bbc9cSIvan Kochin }); 369*b95bbc9cSIvan Kochin } 370*b95bbc9cSIvan Kochin 371*b95bbc9cSIvan Kochin //! Test array sorting via const span (default comparator) 372*b95bbc9cSIvan Kochin //! \brief \ref error_guessing 373*b95bbc9cSIvan Kochin TEST_CASE("Test array sorting via const span (default comparator)") { 374*b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) { 375*b95bbc9cSIvan Kochin const minimal_span<int> span(array, array_size); 376*b95bbc9cSIvan Kochin tbb::parallel_sort(span); 377*b95bbc9cSIvan Kochin }); 378*b95bbc9cSIvan Kochin } 379*b95bbc9cSIvan Kochin 380*b95bbc9cSIvan Kochin //! Test rvalue container with stateful comparator 381*b95bbc9cSIvan Kochin //! \brief \ref error_guessing 382*b95bbc9cSIvan Kochin TEST_CASE("Test rvalue container with stateful comparator") { 383*b95bbc9cSIvan Kochin // Create sorted range 384*b95bbc9cSIvan Kochin std::vector<std::size_t> test_vector(array_size); 385*b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i) 386*b95bbc9cSIvan Kochin test_vector[i] = i; 387*b95bbc9cSIvan Kochin 388*b95bbc9cSIvan Kochin std::atomic<std::size_t> count{0}; 389*b95bbc9cSIvan Kochin tbb::parallel_sort(std::move(test_vector), [&](std::size_t lhs, std::size_t rhs) { 390*b95bbc9cSIvan Kochin ++count; 391*b95bbc9cSIvan Kochin return lhs < rhs; 392*b95bbc9cSIvan Kochin }); 393*b95bbc9cSIvan Kochin 394*b95bbc9cSIvan Kochin // The comparator should be called at least (size - 1) times to check that the array is sorted 395*b95bbc9cSIvan Kochin REQUIRE_MESSAGE(count >= array_size - 1, "Incorrect comparator calls count"); 396*b95bbc9cSIvan Kochin } 397*b95bbc9cSIvan Kochin 39851c0b2f7Stbbdev //! Testing workers going to sleep 39951c0b2f7Stbbdev //! \brief \ref resource_usage 40051c0b2f7Stbbdev TEST_CASE("That all workers sleep when no work") { 401*b95bbc9cSIvan Kochin int test_array[array_size]; 402*b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i) 403*b95bbc9cSIvan Kochin test_array[i] = rand() % array_size; 40451c0b2f7Stbbdev 40551c0b2f7Stbbdev tbb::parallel_sort(test_array); 40651c0b2f7Stbbdev TestCPUUserTime(utils::get_platform_max_threads()); 40751c0b2f7Stbbdev } 408478de5b1Stbbdev 409478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT 410478de5b1Stbbdev //! \brief \ref error_guessing 411478de5b1Stbbdev TEST_CASE("parallel_sort constraints") { 412478de5b1Stbbdev test_psort_iterator_constraints(); 413478de5b1Stbbdev test_psort_compare_constraints(); 414478de5b1Stbbdev test_psort_cbs_constraints(); 415478de5b1Stbbdev } 416478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT 417