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> 34b95bbc9cSIvan Kochin #include <iterator> 35b95bbc9cSIvan 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 } 49b95bbc9cSIvan 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 62b95bbc9cSIvan Kochin template<typename Value> 63b95bbc9cSIvan Kochin bool compare(const Value& lhs, const Value& rhs) { 64b95bbc9cSIvan Kochin return lhs == rhs; 65b95bbc9cSIvan Kochin } 66b95bbc9cSIvan Kochin 67b95bbc9cSIvan Kochin bool compare(const Minimal& lhs, const Minimal& rhs) { 68b95bbc9cSIvan Kochin return Minimal::AreEqual(lhs, rhs); 69b95bbc9cSIvan Kochin } 70b95bbc9cSIvan Kochin 7151c0b2f7Stbbdev template<typename Range> 72b95bbc9cSIvan Kochin void validate(Range test_range, Range sorted_range) { 73b95bbc9cSIvan Kochin using value_type = typename std::iterator_traits<decltype(std::begin(test_range))>::value_type; 74b95bbc9cSIvan Kochin REQUIRE( 75b95bbc9cSIvan Kochin std::equal(std::begin(test_range), std::end(test_range), std::begin(sorted_range), 76b95bbc9cSIvan Kochin [](const value_type& tested, const value_type& reference) { 77b95bbc9cSIvan Kochin return compare(tested, reference); 7851c0b2f7Stbbdev } 79b95bbc9cSIvan Kochin ) 80b95bbc9cSIvan 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 100b95bbc9cSIvan Kochin template <typename KeyType> 101b95bbc9cSIvan Kochin void set(std::string& string_ref, KeyType key) { 102b95bbc9cSIvan Kochin static char buffer[20]; 103b95bbc9cSIvan Kochin #if _MSC_VER && __STDC_SECURE_LIB__>=200411 104b95bbc9cSIvan Kochin sprintf_s(buffer, sizeof(buffer), "%f", static_cast<float>(key)); 105b95bbc9cSIvan Kochin #else 106b95bbc9cSIvan Kochin sprintf(buffer, "%f", static_cast<float>(key)); 107b95bbc9cSIvan Kochin #endif 108b95bbc9cSIvan Kochin string_ref = buffer; 109b95bbc9cSIvan Kochin } 110b95bbc9cSIvan Kochin 111b95bbc9cSIvan 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 */ 159b95bbc9cSIvan Kochin template<typename ContainerType, std::size_t Size> 16051c0b2f7Stbbdev struct parallel_sort_test { 16151c0b2f7Stbbdev static void run() { 162b95bbc9cSIvan Kochin std::less<typename ContainerType::value_type> default_comp; 163b95bbc9cSIvan Kochin ContainerType range(Size); 164b95bbc9cSIvan Kochin ContainerType sorted_range(Size); 16551c0b2f7Stbbdev 166b95bbc9cSIvan Kochin while (fill_ranges(std::begin(range), std::begin(sorted_range), Size, default_comp)) { 167b95bbc9cSIvan Kochin tbb::parallel_sort(range); 168b95bbc9cSIvan Kochin validate(range, sorted_range); 16951c0b2f7Stbbdev } 17051c0b2f7Stbbdev } 17151c0b2f7Stbbdev 17251c0b2f7Stbbdev template<typename Comparator> 17351c0b2f7Stbbdev static void run(Comparator& comp) { 174b95bbc9cSIvan Kochin ContainerType range(Size); 175b95bbc9cSIvan Kochin ContainerType sorted_range(Size); 17651c0b2f7Stbbdev 177b95bbc9cSIvan Kochin while (fill_ranges(std::begin(range), std::begin(sorted_range), Size, comp)) { 178b95bbc9cSIvan Kochin tbb::parallel_sort(range, comp); 179b95bbc9cSIvan Kochin validate(range, sorted_range); 18051c0b2f7Stbbdev } 18151c0b2f7Stbbdev } 18251c0b2f7Stbbdev }; 18351c0b2f7Stbbdev 184b95bbc9cSIvan 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); 189b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/0 >::run(comp); 190b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/1 >::run(comp); 191b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/10 >::run(comp); 192b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/9999 >::run(comp); 193b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/50000>::run(comp); 19451c0b2f7Stbbdev } 19551c0b2f7Stbbdev } 19651c0b2f7Stbbdev 197b95bbc9cSIvan 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); 201b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/0 >::run(); 202b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/1 >::run(); 203b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/10 >::run(); 204b95bbc9cSIvan Kochin parallel_sort_test<ContainerType, /*Size*/9999 >::run(); 205b95bbc9cSIvan 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() { 234*4eec89feSIvan Kochin using namespace test_concepts::parallel_sort_value; 235*4eec89feSIvan Kochin 236478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator<utils::RandomIterator<int>>); 237478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator<typename std::vector<int>::iterator>); 238478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator<utils::ForwardIterator<int>>); 239478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator<utils::InputIterator<int>>); 240*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<utils::RandomIterator<NonMovableValue>>); 241*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<utils::RandomIterator<NonMoveAssignableValue>>); 242*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<utils::RandomIterator<NonComparableValue>>); 243*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator<test_concepts::ConstantIT<int>>); 244478de5b1Stbbdev 245478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<utils::RandomIterator<int>, CorrectCompare<int>>); 246478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<typename std::vector<int>::iterator, CorrectCompare<int>>); 247478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::ForwardIterator<int>, CorrectCompare<int>>); 248478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::InputIterator<int>, CorrectCompare<int>>); 249*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::RandomIterator<NonMovableValue>, CorrectCompare<NonMovableValue>>); 250*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator_and_compare<utils::RandomIterator<NonMoveAssignableValue>, CorrectCompare<NonMoveAssignableValue>>); 251*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_iterator_and_compare<test_concepts::ConstantIT<int>, CorrectCompare<const int>>); 252478de5b1Stbbdev } 253478de5b1Stbbdev 254478de5b1Stbbdev void test_psort_compare_constraints() { 255478de5b1Stbbdev using namespace test_concepts::compare; 256*4eec89feSIvan Kochin 257478de5b1Stbbdev using CorrectCBS = test_concepts::container_based_sequence::Correct; 258*4eec89feSIvan Kochin using CorrectIterator = CorrectCBS::iterator; 259478de5b1Stbbdev static_assert(can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, Correct<int>>); 260478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, NoOperatorRoundBrackets<int>>); 261478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongFirstInputOperatorRoundBrackets<int>>); 262478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongSecondInputOperatorRoundBrackets<int>>); 263478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_iterator_and_compare<CorrectIterator, WrongReturnOperatorRoundBrackets<int>>); 264478de5b1Stbbdev 265478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, Correct<int>>); 266478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, NoOperatorRoundBrackets<int>>); 267478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongFirstInputOperatorRoundBrackets<int>>); 268478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongSecondInputOperatorRoundBrackets<int>>); 269478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<CorrectCBS, WrongReturnOperatorRoundBrackets<int>>); 270478de5b1Stbbdev } 271478de5b1Stbbdev 272478de5b1Stbbdev void test_psort_cbs_constraints() { 273478de5b1Stbbdev using namespace test_concepts::container_based_sequence; 274*4eec89feSIvan Kochin using namespace test_concepts::parallel_sort_value; 275*4eec89feSIvan Kochin 276478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs<Correct>); 277478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<NoBegin>); 278478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<NoEnd>); 279478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs<ForwardIteratorCBS>); 280*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<ConstantCBS>); 281478de5b1Stbbdev 282*4eec89feSIvan Kochin static_assert(can_call_parallel_sort_with_cbs<CustomValueCBS<CorrectValue>>); 283*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<CustomValueCBS<NonMovableValue>>); 284*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<CustomValueCBS<NonMoveAssignableValue>>); 285*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs<CustomValueCBS<NonComparableValue>>);\ 286*4eec89feSIvan Kochin 287*4eec89feSIvan Kochin using CorrectCompare = test_concepts::compare::Correct<int>; 288*4eec89feSIvan Kochin using NonMovableCompare = test_concepts::compare::Correct<NonMovableValue>; 289*4eec89feSIvan Kochin using NonMoveAssignableCompare = test_concepts::compare::Correct<NonMoveAssignableValue>; 290478de5b1Stbbdev static_assert(can_call_parallel_sort_with_cbs_and_compare<Correct, CorrectCompare>); 291478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<NoBegin, CorrectCompare>); 292478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<NoEnd, CorrectCompare>); 293478de5b1Stbbdev static_assert(!can_call_parallel_sort_with_cbs_and_compare<ForwardIteratorCBS, CorrectCompare>); 294*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs_and_compare<ConstantCBS, CorrectCompare>); 295*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs_and_compare<CustomValueCBS<NonMovableValue>, NonMovableCompare>); 296*4eec89feSIvan Kochin static_assert(!can_call_parallel_sort_with_cbs_and_compare<CustomValueCBS<NonMoveAssignableValue>, NonMoveAssignableCompare>); 297478de5b1Stbbdev } 298478de5b1Stbbdev 299478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT 300478de5b1Stbbdev 301b95bbc9cSIvan Kochin template<typename T> 302b95bbc9cSIvan Kochin struct minimal_span { 303b95bbc9cSIvan Kochin minimal_span(T* input_data, std::size_t input_size) 304b95bbc9cSIvan Kochin : data{input_data} 305b95bbc9cSIvan Kochin , size{input_size} 306b95bbc9cSIvan Kochin {} 307b95bbc9cSIvan Kochin 308b95bbc9cSIvan Kochin T* begin() const { 309b95bbc9cSIvan Kochin return data; 310b95bbc9cSIvan Kochin } 311b95bbc9cSIvan Kochin T* end() const { 312b95bbc9cSIvan Kochin return data + size; 313b95bbc9cSIvan Kochin } 314b95bbc9cSIvan Kochin private: 315b95bbc9cSIvan Kochin T* data; 316b95bbc9cSIvan Kochin std::size_t size; 317b95bbc9cSIvan Kochin }; 318b95bbc9cSIvan Kochin 31951c0b2f7Stbbdev //! Minimal array sorting test (less comparator) 32051c0b2f7Stbbdev //! \brief \ref error_guessing 32151c0b2f7Stbbdev TEST_CASE("Minimal array sorting test (less comparator)") { 322b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<Minimal>, MinimalLessCompare>(); 32351c0b2f7Stbbdev } 32451c0b2f7Stbbdev 32551c0b2f7Stbbdev //! Float array sorting test (default comparator) 32651c0b2f7Stbbdev //! \brief \ref error_guessing 32751c0b2f7Stbbdev TEST_CASE("Float array sorting test (default comparator)") { 328b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<float>>(); 32951c0b2f7Stbbdev } 33051c0b2f7Stbbdev 33151c0b2f7Stbbdev //! tbb::concurrent_vector<float> sorting test (less comparator) 33251c0b2f7Stbbdev //! \brief \ref error_guessing 33351c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<float> sorting test (less comparator)") { 33451c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<float>, std::less<float>>(); 33551c0b2f7Stbbdev } 33651c0b2f7Stbbdev 33751c0b2f7Stbbdev //! tbb::concurrent_vector<float> sorting test (default comparator) 33851c0b2f7Stbbdev //! \brief \ref error_guessing 33951c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<float> sorting test (default comparator)") { 34051c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<float>>(); 34151c0b2f7Stbbdev } 34251c0b2f7Stbbdev 34351c0b2f7Stbbdev //! Array of strings sorting test (less comparator) 34451c0b2f7Stbbdev //! \brief \ref error_guessing 34551c0b2f7Stbbdev TEST_CASE("Array of strings sorting test (less comparator)") { 346b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<std::string>, std::less<std::string>>(); 34751c0b2f7Stbbdev } 34851c0b2f7Stbbdev 34951c0b2f7Stbbdev //! Array of strings sorting test (default comparator) 35051c0b2f7Stbbdev //! \brief \ref error_guessing 35151c0b2f7Stbbdev TEST_CASE("Array of strings sorting test (default comparator)") { 352b95bbc9cSIvan Kochin parallel_sort_test_suite<std::vector<std::string>>(); 35351c0b2f7Stbbdev } 35451c0b2f7Stbbdev 35551c0b2f7Stbbdev //! tbb::concurrent_vector<Minimal> sorting test (less comparator) 35651c0b2f7Stbbdev //! \brief \ref error_guessing 35751c0b2f7Stbbdev TEST_CASE("tbb::concurrent_vector<Minimal> sorting test (less comparator)") { 35851c0b2f7Stbbdev parallel_sort_test_suite<tbb::concurrent_vector<Minimal>, MinimalLessCompare>(); 35951c0b2f7Stbbdev } 36051c0b2f7Stbbdev 361b95bbc9cSIvan Kochin constexpr std::size_t array_size = 10000; 362b95bbc9cSIvan Kochin 363b95bbc9cSIvan Kochin template<typename SortFunctor> 364b95bbc9cSIvan Kochin void sort_array_test(const SortFunctor& sort_functor) { 365b95bbc9cSIvan Kochin int test_array[array_size]; 366b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i) 367b95bbc9cSIvan Kochin test_array[i] = rand() % array_size; 368b95bbc9cSIvan Kochin 369b95bbc9cSIvan Kochin sort_functor(test_array); 370b95bbc9cSIvan Kochin 371b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size - 1; ++i) 372b95bbc9cSIvan Kochin REQUIRE_MESSAGE(test_array[i] <= test_array[i + 1], "Testing data not sorted"); 373b95bbc9cSIvan Kochin } 37451c0b2f7Stbbdev 37551c0b2f7Stbbdev //! Array sorting test (default comparator) 37651c0b2f7Stbbdev //! \brief \ref error_guessing 37751c0b2f7Stbbdev TEST_CASE("Array sorting test (default comparator)") { 37851c0b2f7Stbbdev for ( auto concurrency_level : utils::concurrency_range() ) { 37951c0b2f7Stbbdev tbb::global_control control(tbb::global_control::max_allowed_parallelism, concurrency_level); 380b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) { 381b95bbc9cSIvan Kochin tbb::parallel_sort(array); 382b95bbc9cSIvan Kochin }); 38351c0b2f7Stbbdev } 38451c0b2f7Stbbdev } 38551c0b2f7Stbbdev 386b95bbc9cSIvan Kochin //! Test array sorting via rvalue span (default comparator) 387b95bbc9cSIvan Kochin //! \brief \ref error_guessing 388b95bbc9cSIvan Kochin TEST_CASE("Test array sorting via rvalue span (default comparator)") { 389b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) { 390b95bbc9cSIvan Kochin tbb::parallel_sort(minimal_span<int>{array, array_size}); 391b95bbc9cSIvan Kochin }); 392b95bbc9cSIvan Kochin } 393b95bbc9cSIvan Kochin 394b95bbc9cSIvan Kochin //! Test array sorting via const span (default comparator) 395b95bbc9cSIvan Kochin //! \brief \ref error_guessing 396b95bbc9cSIvan Kochin TEST_CASE("Test array sorting via const span (default comparator)") { 397b95bbc9cSIvan Kochin sort_array_test([](int (&array)[array_size]) { 398b95bbc9cSIvan Kochin const minimal_span<int> span(array, array_size); 399b95bbc9cSIvan Kochin tbb::parallel_sort(span); 400b95bbc9cSIvan Kochin }); 401b95bbc9cSIvan Kochin } 402b95bbc9cSIvan Kochin 403b95bbc9cSIvan Kochin //! Test rvalue container with stateful comparator 404b95bbc9cSIvan Kochin //! \brief \ref error_guessing 405b95bbc9cSIvan Kochin TEST_CASE("Test rvalue container with stateful comparator") { 406b95bbc9cSIvan Kochin // Create sorted range 407b95bbc9cSIvan Kochin std::vector<std::size_t> test_vector(array_size); 408b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i) 409b95bbc9cSIvan Kochin test_vector[i] = i; 410b95bbc9cSIvan Kochin 411b95bbc9cSIvan Kochin std::atomic<std::size_t> count{0}; 412b95bbc9cSIvan Kochin tbb::parallel_sort(std::move(test_vector), [&](std::size_t lhs, std::size_t rhs) { 413b95bbc9cSIvan Kochin ++count; 414b95bbc9cSIvan Kochin return lhs < rhs; 415b95bbc9cSIvan Kochin }); 416b95bbc9cSIvan Kochin 417b95bbc9cSIvan Kochin // The comparator should be called at least (size - 1) times to check that the array is sorted 418b95bbc9cSIvan Kochin REQUIRE_MESSAGE(count >= array_size - 1, "Incorrect comparator calls count"); 419b95bbc9cSIvan Kochin } 420b95bbc9cSIvan Kochin 42151c0b2f7Stbbdev //! Testing workers going to sleep 42251c0b2f7Stbbdev //! \brief \ref resource_usage 42351c0b2f7Stbbdev TEST_CASE("That all workers sleep when no work") { 424b95bbc9cSIvan Kochin int test_array[array_size]; 425b95bbc9cSIvan Kochin for (std::size_t i = 0; i < array_size; ++i) 426b95bbc9cSIvan Kochin test_array[i] = rand() % array_size; 42751c0b2f7Stbbdev 42851c0b2f7Stbbdev tbb::parallel_sort(test_array); 42951c0b2f7Stbbdev TestCPUUserTime(utils::get_platform_max_threads()); 43051c0b2f7Stbbdev } 431478de5b1Stbbdev 432478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT 433478de5b1Stbbdev //! \brief \ref error_guessing 434478de5b1Stbbdev TEST_CASE("parallel_sort constraints") { 435478de5b1Stbbdev test_psort_iterator_constraints(); 436478de5b1Stbbdev test_psort_compare_constraints(); 437478de5b1Stbbdev test_psort_cbs_constraints(); 438478de5b1Stbbdev } 439478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT 440