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