1 // -*- C++ -*-
2 //===-- copy_move.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 // Tests for copy, move and copy_n
11 
12 #include "support/pstl_test_config.h"
13 
14 #include <execution>
15 #include <algorithm>
16 
17 #include "support/utils.h"
18 
19 using namespace TestUtils;
20 
21 struct run_copy
22 {
23 
24 #if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
25     _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 OutputIterator2, typename Size, typename T>
27     void
28     operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
29                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
30                Size n, T trash)
31     {
32     }
33 
34     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename T>
35     void
36     operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
37                OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
38                OutputIterator2 expected_last, Size size, Size n, T trash)
39     {
40     }
41 #endif
42 
43     template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
44               typename T>
45     void
46     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
47                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
48                Size n, T trash)
49     {
50         // Cleaning
51         std::fill_n(expected_first, size, trash);
52         std::fill_n(out_first, size, trash);
53 
54         // Run copy
55         copy(first, last, expected_first);
56         auto k = copy(exec, first, last, out_first);
57         for (size_t j = 0; j < GuardSize; ++j)
58             ++k;
59         EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from copy");
60         EXPECT_TRUE(out_last == k, "wrong return value from copy");
61 
62         // Cleaning
63         std::fill_n(out_first, size, trash);
64         // Run copy_n
65         k = copy_n(exec, first, n, out_first);
66         for (size_t j = 0; j < GuardSize; ++j)
67             ++k;
68         EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from copy_n");
69         EXPECT_TRUE(out_last == k, "wrong return value from copy_n");
70     }
71 };
72 
73 template <typename T>
74 struct run_move
75 {
76 
77 #if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
78     _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
79     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
80     void
81     operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
82                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
83                Size n, T trash)
84     {
85     }
86 
87     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
88     void
89     operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
90                OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
91                OutputIterator2 expected_last, Size size, Size n, T trash)
92     {
93     }
94 #endif
95 
96     template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
97     void
98     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
99                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
100                Size n, T trash)
101     {
102         // Cleaning
103         std::fill_n(expected_first, size, trash);
104         std::fill_n(out_first, size, trash);
105 
106         // Run move
107         move(first, last, expected_first);
108         auto k = move(exec, first, last, out_first);
109         for (size_t j = 0; j < GuardSize; ++j)
110             ++k;
111         EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from move");
112         EXPECT_TRUE(out_last == k, "wrong return value from move");
113     }
114 };
115 
116 template <typename T>
117 struct run_move<Wrapper<T>>
118 {
119 
120 #if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
121     _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
122     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
123     void
124     operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
125                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
126                Size n, Wrapper<T> trash)
127     {
128     }
129 
130     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
131     void
132     operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
133                OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
134                OutputIterator2 expected_last, Size size, Size n, Wrapper<T> trash)
135     {
136     }
137 #endif
138 
139     template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
140     void
141     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
142                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
143                Size n, Wrapper<T> trash)
144     {
145         // Cleaning
146         std::fill_n(out_first, size, trash);
147         Wrapper<T>::SetMoveCount(0);
148 
149         // Run move
150         auto k = move(exec, first, last, out_first);
151         for (size_t j = 0; j < GuardSize; ++j)
152             ++k;
153         EXPECT_TRUE(Wrapper<T>::MoveCount() == size, "wrong effect from move");
154         EXPECT_TRUE(out_last == k, "wrong return value from move");
155     }
156 };
157 
158 template <typename T, typename Convert>
159 void
160 test(T trash, Convert convert)
161 {
162     // Try sequences of various lengths.
163     for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
164     {
165         // count is number of output elements, plus a handful
166         // more for sake of detecting buffer overruns.
167         Sequence<T> in(n, [&](size_t k) -> T {
168             T val = convert(n ^ k);
169             return val;
170         });
171 
172         const size_t outN = n + GuardSize;
173         Sequence<T> out(outN, [=](size_t) { return trash; });
174         Sequence<T> expected(outN, [=](size_t) { return trash; });
175         invoke_on_all_policies(run_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
176                                expected.end(), outN, n, trash);
177         invoke_on_all_policies(run_copy(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(),
178                                expected.end(), outN, n, trash);
179         invoke_on_all_policies(run_move<T>(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
180                                expected.end(), n, n, trash);
181 
182         // For this test const iterator isn't suitable
183         // because const rvalue-reference call copy assignment operator
184     }
185 }
186 
187 int32_t
188 main()
189 {
190     test<int32_t>(-666, [](size_t j) { return int32_t(j); });
191     test<Wrapper<float64_t>>(Wrapper<float64_t>(-666.0), [](int32_t j) { return Wrapper<float64_t>(j); });
192 
193 #if !_PSTL_ICC_16_17_TEST_64_TIMEOUT
194     test<float64_t>(-666.0, [](size_t j) { return float64_t(j); });
195     test<Number>(Number(42, OddTag()), [](int32_t j) { return Number(j, OddTag()); });
196 #endif
197     std::cout << done() << std::endl;
198     return 0;
199 }
200