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