1 | // -*- C++ -*- |
2 | //===-- remove.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 remove, remove_if |
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_remove |
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 InputIterator, typename OutputIterator, typename Size, typename T> |
27 | void |
28 | operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, |
29 | OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, |
30 | const T& value) |
31 | { |
32 | } |
33 | template <typename InputIterator, typename OutputIterator, typename Size, typename T> |
34 | void |
35 | operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, |
36 | OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, |
37 | OutputIterator expected_last, Size n, const T& value) |
38 | { |
39 | } |
40 | #endif |
41 | |
42 | template <typename Policy, typename InputIterator, typename OutputIterator, typename Size, typename T> |
43 | void |
44 | operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, |
45 | OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size, |
46 | const T& value) |
47 | { |
48 | // Cleaning |
49 | std::copy(first, last, expected_first); |
50 | std::copy(first, last, out_first); |
51 | |
52 | // Run remove |
53 | OutputIterator i = remove(expected_first, expected_last, value); |
54 | OutputIterator k = remove(exec, out_first, out_last, value); |
55 | EXPECT_TRUE(std::distance(expected_first, i) == std::distance(out_first, k), "wrong return value from remove" ); |
56 | EXPECT_EQ_N(expected_first, out_first, std::distance(expected_first, i), "wrong remove effect" ); |
57 | } |
58 | }; |
59 | |
60 | struct run_remove_if |
61 | { |
62 | #if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ |
63 | defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration |
64 | template <typename InputIterator, typename OutputIterator, typename Size, typename Predicate> |
65 | void |
66 | operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, |
67 | OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, |
68 | Predicate pred) |
69 | { |
70 | } |
71 | template <typename InputIterator, typename OutputIterator, typename Size, typename Predicate> |
72 | void |
73 | operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, |
74 | OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, |
75 | OutputIterator expected_last, Size n, Predicate pred) |
76 | { |
77 | } |
78 | #endif |
79 | |
80 | template <typename Policy, typename InputIterator, typename OutputIterator, typename Size, typename Predicate> |
81 | void |
82 | operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, |
83 | OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size, |
84 | Predicate pred) |
85 | { |
86 | // Cleaning |
87 | std::copy(first, last, expected_first); |
88 | std::copy(first, last, out_first); |
89 | |
90 | // Run remove_if |
91 | OutputIterator i = remove_if(expected_first, expected_last, pred); |
92 | OutputIterator k = remove_if(exec, out_first, out_last, pred); |
93 | EXPECT_TRUE(std::distance(expected_first, i) == std::distance(out_first, k), |
94 | "wrong return value from remove_if" ); |
95 | EXPECT_EQ_N(expected_first, out_first, std::distance(expected_first, i), "wrong remove_if effect" ); |
96 | } |
97 | }; |
98 | |
99 | template <typename T, typename Predicate, typename Convert> |
100 | void |
101 | test(T trash, const T& value, Predicate pred, Convert convert) |
102 | { |
103 | const std::size_t max_size = 100000; |
104 | Sequence<T> out(max_size, [trash](size_t) { return trash; }); |
105 | Sequence<T> expected(max_size, [trash](size_t) { return trash; }); |
106 | |
107 | for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) |
108 | { |
109 | Sequence<T> data(n, [&](size_t k) -> T { return convert(k); }); |
110 | |
111 | invoke_on_all_policies(run_remove(), data.begin(), data.end(), out.begin(), out.begin() + n, expected.begin(), |
112 | expected.begin() + n, n, value); |
113 | invoke_on_all_policies(run_remove_if(), data.begin(), data.end(), out.begin(), out.begin() + n, |
114 | expected.begin(), expected.begin() + n, n, pred); |
115 | } |
116 | } |
117 | |
118 | struct test_non_const |
119 | { |
120 | template <typename Policy, typename Iterator> |
121 | void |
122 | operator()(Policy&& exec, Iterator iter) |
123 | { |
124 | auto is_even = [&](float64_t v) { |
125 | uint32_t i = (uint32_t)v; |
126 | return i % 2 == 0; |
127 | }; |
128 | |
129 | invoke_if(exec, [&]() { remove_if(exec, iter, iter, non_const(is_even)); }); |
130 | } |
131 | }; |
132 | |
133 | int |
134 | main() |
135 | { |
136 | #if !defined(_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN) |
137 | test<int32_t>(trash: 666, value: 42, pred: [](int32_t) { return true; }, convert: [](size_t j) { return j; }); |
138 | #endif |
139 | |
140 | test<int32_t>(trash: 666, value: 2001, pred: [](const int32_t& val) { return val != 2001; }, |
141 | convert: [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 2001 : -1 - int32_t(j); }); |
142 | test<float64_t>(trash: -666.0, value: 8.5, pred: [](const float64_t& val) { return val != 8.5; }, |
143 | convert: [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); }); |
144 | |
145 | #if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN) |
146 | test<Number>(trash: Number(-666, OddTag()), value: Number(42, OddTag()), pred: IsMultiple(3, OddTag()), |
147 | convert: [](int32_t j) { return Number(j, OddTag()); }); |
148 | #endif |
149 | |
150 | test_algo_basic_single<int32_t>(f: run_for_rnd_fw<test_non_const>()); |
151 | |
152 | test<MemoryChecker>(trash: MemoryChecker{0}, value: MemoryChecker{1}, |
153 | pred: [](const MemoryChecker& val){ return val.value() == 1; }, |
154 | convert: [](std::size_t idx){ return MemoryChecker{std::int32_t(idx % 3 == 0)}; } |
155 | ); |
156 | EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from remove,remove_if: number of ctors calls < num of dtors calls" ); |
157 | EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from remove,remove_if: number of ctors calls > num of dtors calls" ); |
158 | |
159 | std::cout << done() << std::endl; |
160 | return 0; |
161 | } |
162 | |