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