| 1 | // -*- C++ -*- |
| 2 | //===-- unique.pass.cpp ---------------------------------------------------===// |
| 3 | // |
| 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 |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | // UNSUPPORTED: c++03, c++11, c++14 |
| 11 | |
| 12 | // Test for unique |
| 13 | #include "support/pstl_test_config.h" |
| 14 | |
| 15 | #include <execution> |
| 16 | #include <algorithm> |
| 17 | |
| 18 | #include "support/utils.h" |
| 19 | |
| 20 | using namespace TestUtils; |
| 21 | |
| 22 | struct run_unique |
| 23 | { |
| 24 | #if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ |
| 25 | defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration |
| 26 | template <typename ForwardIt, typename Generator> |
| 27 | void |
| 28 | operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, |
| 29 | ForwardIt last2, Generator generator) |
| 30 | { |
| 31 | } |
| 32 | |
| 33 | template <typename ForwardIt, typename Generator> |
| 34 | void |
| 35 | operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, |
| 36 | ForwardIt last2, Generator generator) |
| 37 | { |
| 38 | } |
| 39 | |
| 40 | template <typename ForwardIt, typename BinaryPred, typename Generator> |
| 41 | void |
| 42 | operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, |
| 43 | ForwardIt last2, BinaryPred pred, Generator generator) |
| 44 | { |
| 45 | } |
| 46 | |
| 47 | template <typename ForwardIt, typename BinaryPred, typename Generator> |
| 48 | void |
| 49 | operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, |
| 50 | ForwardIt last2, BinaryPred pred, Generator generator) |
| 51 | { |
| 52 | } |
| 53 | #endif |
| 54 | |
| 55 | template <typename Policy, typename ForwardIt, typename Generator> |
| 56 | void |
| 57 | operator()(Policy&& exec, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, Generator generator) |
| 58 | { |
| 59 | using namespace std; |
| 60 | |
| 61 | // Preparation |
| 62 | fill_data(first1, last1, generator); |
| 63 | fill_data(first2, last2, generator); |
| 64 | |
| 65 | ForwardIt i = unique(first1, last1); |
| 66 | ForwardIt k = unique(exec, first2, last2); |
| 67 | |
| 68 | auto n = std::distance(first1, i); |
| 69 | EXPECT_TRUE(std::distance(first2, k) == n, "wrong return value from unique without predicate" ); |
| 70 | EXPECT_EQ_N(first1, first2, n, "wrong effect from unique without predicate" ); |
| 71 | } |
| 72 | |
| 73 | template <typename Policy, typename ForwardIt, typename BinaryPred, typename Generator> |
| 74 | void |
| 75 | operator()(Policy&& exec, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, BinaryPred pred, |
| 76 | Generator generator) |
| 77 | { |
| 78 | using namespace std; |
| 79 | |
| 80 | // Preparation |
| 81 | fill_data(first1, last1, generator); |
| 82 | fill_data(first2, last2, generator); |
| 83 | |
| 84 | ForwardIt i = unique(first1, last1, pred); |
| 85 | ForwardIt k = unique(exec, first2, last2, pred); |
| 86 | |
| 87 | auto n = std::distance(first1, i); |
| 88 | EXPECT_TRUE(std::distance(first2, k) == n, "wrong return value from unique with predicate" ); |
| 89 | EXPECT_EQ_N(first1, first2, n, "wrong effect from unique with predicate" ); |
| 90 | } |
| 91 | }; |
| 92 | |
| 93 | template <typename T, typename Generator, typename Predicate> |
| 94 | void |
| 95 | test(Generator generator, Predicate pred) |
| 96 | { |
| 97 | const std::size_t max_size = 1000000; |
| 98 | Sequence<T> in(max_size, [](size_t v) { return T(v); }); |
| 99 | Sequence<T> exp(max_size, [](size_t v) { return T(v); }); |
| 100 | |
| 101 | for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) |
| 102 | { |
| 103 | invoke_on_all_policies(run_unique(), exp.begin(), exp.begin() + n, in.begin(), in.begin() + n, generator); |
| 104 | invoke_on_all_policies(run_unique(), exp.begin(), exp.begin() + n, in.begin(), in.begin() + n, pred, generator); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | template <typename T> |
| 109 | struct LocalWrapper |
| 110 | { |
| 111 | T my_val; |
| 112 | |
| 113 | explicit LocalWrapper(T k) : my_val(k) {} |
| 114 | LocalWrapper(LocalWrapper&& input) : my_val(std::move(input.my_val)) {} |
| 115 | LocalWrapper& |
| 116 | operator=(LocalWrapper&& input) |
| 117 | { |
| 118 | my_val = std::move(input.my_val); |
| 119 | return *this; |
| 120 | } |
| 121 | friend bool |
| 122 | operator==(const LocalWrapper<T>& x, const LocalWrapper<T>& y) |
| 123 | { |
| 124 | return x.my_val == y.my_val; |
| 125 | } |
| 126 | }; |
| 127 | |
| 128 | template <typename T> |
| 129 | struct test_non_const |
| 130 | { |
| 131 | template <typename Policy, typename Iterator> |
| 132 | void |
| 133 | operator()(Policy&& exec, Iterator iter) |
| 134 | { |
| 135 | invoke_if(exec, [&]() { unique(exec, iter, iter, non_const(std::equal_to<T>())); }); |
| 136 | } |
| 137 | }; |
| 138 | |
| 139 | int |
| 140 | main() |
| 141 | { |
| 142 | #if !defined(_PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN) |
| 143 | test<int32_t>(generator: [](size_t j) { return j / 3; }, |
| 144 | pred: [](const int32_t& val1, const int32_t& val2) { return val1 * val1 == val2 * val2; }); |
| 145 | test<float64_t>(generator: [](size_t) { return float64_t(1); }, |
| 146 | pred: [](const float64_t& val1, const float64_t& val2) { return val1 != val2; }); |
| 147 | #endif |
| 148 | test<LocalWrapper<uint32_t>>(generator: [](size_t j) { return LocalWrapper<uint32_t>(j); }, |
| 149 | pred: [](const LocalWrapper<uint32_t>& val1, const LocalWrapper<uint32_t>& val2) { |
| 150 | return val1.my_val != val2.my_val; |
| 151 | }); |
| 152 | |
| 153 | test_algo_basic_single<int32_t>(f: run_for_rnd_fw<test_non_const<int32_t>>()); |
| 154 | |
| 155 | test<MemoryChecker>( |
| 156 | generator: [](std::size_t idx){ return MemoryChecker{std::int32_t(idx / 3)}; }, |
| 157 | pred: [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() == val2.value(); }); |
| 158 | EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from unique: number of ctors calls < num of dtors calls" ); |
| 159 | EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from unique: number of ctors calls > num of dtors calls" ); |
| 160 | |
| 161 | std::cout << done() << std::endl; |
| 162 | return 0; |
| 163 | } |
| 164 | |