// -*- C++ -*- //===-- test_partial_sort_copy.cpp ----------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // Tests for partial_sort_copy #include #include "pstl_test_config.h" #include "pstl/execution" #include "pstl/algorithm" #include "utils.h" using namespace TestUtils; template struct Num { T val; Num() : val(0) {} Num(T v) : val(v) {} Num(const Num& v) : val(v.val) {} Num(Num&& v) : val(v.val) {} Num& operator=(const Num& v) { val = v.val; return *this; } operator T() const { return val; } bool operator<(const Num& v) const { return val < v.val; } }; template struct test_one_policy { RandomAccessIterator d_first; RandomAccessIterator d_last; RandomAccessIterator exp_first; RandomAccessIterator exp_last; // This ctor is needed because output shouldn't be transformed to any iterator type (only random access iterators are allowed) test_one_policy(RandomAccessIterator b1, RandomAccessIterator e1, RandomAccessIterator b2, RandomAccessIterator e2) : d_first(b1), d_last(e1), exp_first(b2), exp_last(e2) { } #if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration template void operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) { } template void operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) { } template void operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) { } template void operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) { } #endif template void operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) { prepare_data(first, last, n1, trash); RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last, compare); RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last, compare); EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy with predicate"); EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy with predicate"); } template void operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) { prepare_data(first, last, n1, trash); RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last); RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last); EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy without predicate"); EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy without predicate"); } private: template void prepare_data(InputIterator first, InputIterator last, Size n1, const T& trash) { // The rand()%(2*n+1) encourages generation of some duplicates. std::srand(42); std::generate(first, last, [n1]() { return T(rand() % (2 * n1 + 1)); }); std::fill(exp_first, exp_last, trash); std::fill(d_first, d_last, trash); } }; template void test_partial_sort_copy(Compare compare) { typedef typename Sequence::iterator iterator_type; const std::size_t n_max = 100000; Sequence in(n_max); Sequence out(2 * n_max); Sequence exp(2 * n_max); std::size_t n1 = 0; std::size_t n2; T trash = T(-666); for (; n1 < n_max; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) { // If both sequences are equal n2 = n1; invoke_on_all_policies( test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), in.begin() + n1, n1, n2, trash, compare); // If first sequence is greater than second n2 = n1 / 3; invoke_on_all_policies( test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), in.begin() + n1, n1, n2, trash, compare); // If first sequence is less than second n2 = 2 * n1; invoke_on_all_policies( test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), in.begin() + n1, n1, n2, trash, compare); } // Test partial_sort_copy without predicate n1 = n_max; n2 = 2 * n1; invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), in.begin() + n1, n1, n2, trash); } template struct test_non_const { template void operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) { invoke_if(exec, [&]() { partial_sort_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(std::less())); }); } }; int32_t main() { test_partial_sort_copy>([](Num x, Num y) { return x < y; }); test_partial_sort_copy([](int32_t x, int32_t y) { return x > y; }); test_algo_basic_double(run_for_rnd>()); std::cout << done() << std::endl; return 0; }