2 //===-- nth_element.pass.cpp ----------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: c++03, c++11, c++14
12 #include "support/pstl_test_config.h"
18 #include "support/utils.h"
20 using namespace TestUtils
;
22 // User defined type with minimal requirements
26 explicit DataType(int32_t k
) : my_val(k
) {}
27 DataType(DataType
&& input
)
29 my_val
= std::move(input
.my_val
);
33 operator=(DataType
&& input
)
35 my_val
= std::move(input
.my_val
);
46 operator<<(std::ostream
& stream
, const DataType
<T
>& input
)
48 return stream
<< input
.my_val
;
57 is_equal(const DataType
<T
>& x
, const DataType
<T
>& y
)
59 return x
.get_val() == y
.get_val();
64 is_equal(const T
& x
, const T
& y
)
69 struct test_one_policy
71 #if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \
72 defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
73 template <typename Iterator1
, typename Size
, typename Generator1
, typename Generator2
, typename Compare
>
74 typename
std::enable_if
<is_same_iterator_category
<Iterator1
, std::random_access_iterator_tag
>::value
, void>::type
75 operator()(pstl::execution::unsequenced_policy
, Iterator1 first1
, Iterator1 last1
, Iterator1 first2
,
76 Iterator1 last2
, Size n
, Size m
, Generator1 generator1
, Generator2 generator2
, Compare comp
)
79 template <typename Iterator1
, typename Size
, typename Generator1
, typename Generator2
, typename Compare
>
80 typename
std::enable_if
<is_same_iterator_category
<Iterator1
, std::random_access_iterator_tag
>::value
, void>::type
81 operator()(pstl::execution::parallel_unsequenced_policy
, Iterator1 first1
, Iterator1 last1
, Iterator1 first2
,
82 Iterator1 last2
, Size n
, Size m
, Generator1 generator1
, Generator2 generator2
, Compare comp
)
87 // nth_element works only with random access iterators
88 template <typename Policy
, typename Iterator1
, typename Size
, typename Generator1
, typename Generator2
,
90 typename
std::enable_if
<is_same_iterator_category
<Iterator1
, std::random_access_iterator_tag
>::value
, void>::type
91 operator()(Policy
&& exec
, Iterator1 first1
, Iterator1 last1
, Iterator1 first2
, Iterator1 last2
, Size n
, Size m
,
92 Generator1 generator1
, Generator2 generator2
, Compare comp
)
95 using T
= typename
std::iterator_traits
<Iterator1
>::value_type
;
96 const Iterator1 mid1
= std::next(first1
, m
);
97 const Iterator1 mid2
= std::next(first2
, m
);
99 fill_data(first1
, mid1
, generator1
);
100 fill_data(mid1
, last1
, generator2
);
101 fill_data(first2
, mid2
, generator1
);
102 fill_data(mid2
, last2
, generator2
);
103 std::nth_element(first1
, mid1
, last1
, comp
);
104 std::nth_element(exec
, first2
, mid2
, last2
, comp
);
107 EXPECT_TRUE(is_equal(*mid1
, *mid2
), "wrong result from nth_element with predicate");
109 EXPECT_TRUE(std::find_first_of(first2
, mid2
, mid2
, last2
, [comp
](T
& x
, T
& y
) { return comp(y
, x
); }) == mid2
,
110 "wrong effect from nth_element with predicate");
113 template <typename Policy
, typename Iterator1
, typename Size
, typename Generator1
, typename Generator2
,
115 typename
std::enable_if
<!is_same_iterator_category
<Iterator1
, std::random_access_iterator_tag
>::value
, void>::type
116 operator()(Policy
&&, Iterator1
, Iterator1
, Iterator1
, Iterator1
, Size
, Size
, Generator1
, Generator2
, Compare
)
121 template <typename T
, typename Generator1
, typename Generator2
, typename Compare
>
123 test_by_type(Generator1 generator1
, Generator2 generator2
, Compare comp
)
126 size_t max_size
= 10000;
127 Sequence
<T
> in1(max_size
, [](size_t v
) { return T(v
); });
128 Sequence
<T
> exp(max_size
, [](size_t v
) { return T(v
); });
131 for (size_t n
= 0; n
<= max_size
; n
= n
<= 16 ? n
+ 1 : size_t(3.1415 * n
))
134 invoke_on_all_policies(test_one_policy(), exp
.begin(), exp
.begin() + n
, in1
.begin(), in1
.begin() + n
, n
, m
,
135 generator1
, generator2
, comp
);
137 invoke_on_all_policies(test_one_policy(), exp
.begin(), exp
.begin() + n
, in1
.begin(), in1
.begin() + n
, n
, m
,
138 generator1
, generator2
, comp
);
140 invoke_on_all_policies(test_one_policy(), exp
.begin(), exp
.begin() + n
, in1
.begin(), in1
.begin() + n
, n
, m
,
141 generator1
, generator2
, comp
);
143 invoke_on_all_policies(test_one_policy(), exp
.begin(), exp
.begin() + max_size
, in1
.begin(), in1
.begin() + max_size
,
144 max_size
, max_size
, generator1
, generator2
, comp
);
147 template <typename T
>
148 struct test_non_const
150 template <typename Policy
, typename Iterator
>
152 operator()(Policy
&& exec
, Iterator iter
)
154 invoke_if(exec
, [&]() { nth_element(exec
, iter
, iter
, iter
, non_const(std::less
<T
>())); });
161 test_by_type
<int32_t>([](int32_t i
) { return 10 * i
; }, [](int32_t i
) { return i
+ 1; }, std::less
<int32_t>());
162 test_by_type
<int32_t>([](int32_t) { return 0; }, [](int32_t) { return 0; }, std::less
<int32_t>());
164 test_by_type
<float64_t
>([](int32_t i
) { return -2 * i
; }, [](int32_t i
) { return -(2 * i
+ 1); },
165 [](const float64_t x
, const float64_t y
) { return x
> y
; });
167 test_by_type
<DataType
<float32_t
>>(
168 [](int32_t i
) { return DataType
<float32_t
>(2 * i
+ 1); }, [](int32_t i
) { return DataType
<float32_t
>(2 * i
); },
169 [](const DataType
<float32_t
>& x
, const DataType
<float32_t
>& y
) { return x
.get_val() < y
.get_val(); });
171 test_algo_basic_single
<int32_t>(run_for_rnd
<test_non_const
<int32_t>>());
173 std::cout
<< done() << std::endl
;