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