1 // -*- C++ -*- 2 //===-- reverse_copy.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 #include "support/pstl_test_config.h" 11 12 #ifdef PSTL_STANDALONE_TESTS 13 #include <iterator> 14 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 template <typename T> 27 struct wrapper 28 { 29 T t; 30 wrapper() {} 31 explicit wrapper(T t_) : t(t_) {} 32 wrapper& 33 operator=(const T& t_) 34 { 35 t = t_; 36 return *this; 37 } 38 bool 39 operator==(const wrapper& t_) const 40 { 41 return t == t_.t; 42 } 43 }; 44 45 template <typename T1, typename T2> 46 bool 47 eq(const wrapper<T1>& a, const wrapper<T2>& b) 48 { 49 return a.t == b.t; 50 } 51 52 template <typename T1, typename T2> 53 bool 54 eq(const T1& a, const T2& b) 55 { 56 return a == b; 57 } 58 59 // we need to save state here, because we need to test with different types of iterators 60 // due to the caller invoke_on_all_policies does forcing modification passed iterator type to cover additional usage cases. 61 template <typename Iterator> 62 struct test_one_policy 63 { 64 Iterator data_b; 65 Iterator data_e; 66 test_one_policy(Iterator b, Iterator e) : data_b(b), data_e(e) {} 67 68 #if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ 69 __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration 70 template <typename Iterator1> 71 typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type 72 operator()(pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) 73 { 74 } 75 template <typename Iterator1> 76 typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type 77 operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) 78 { 79 } 80 #endif 81 82 template <typename ExecutionPolicy, typename Iterator1> 83 void 84 operator()(ExecutionPolicy&& exec, Iterator1 actual_b, Iterator1 actual_e) 85 { 86 using namespace std; 87 using T = typename iterator_traits<Iterator1>::value_type; 88 using DifferenceType = typename iterator_traits<Iterator1>::difference_type; 89 90 fill(actual_b, actual_e, T(-123)); 91 Iterator1 actual_return = reverse_copy(exec, data_b, data_e, actual_b); 92 93 EXPECT_TRUE(actual_return == actual_e, "wrong result of reverse_copy"); 94 95 const auto n = std::distance(data_b, data_e); 96 Sequence<T> res(n); 97 std::copy(std::reverse_iterator<Iterator>(data_e), std::reverse_iterator<Iterator>(data_b), res.begin()); 98 99 EXPECT_EQ_N(res.begin(), actual_b, n, "wrong effect of reverse_copy"); 100 } 101 }; 102 103 template <typename T1, typename T2> 104 void 105 test() 106 { 107 typedef typename Sequence<T1>::iterator iterator_type; 108 typedef typename Sequence<T1>::const_bidirectional_iterator cbi_iterator_type; 109 110 const std::size_t max_len = 100000; 111 112 Sequence<T2> actual(max_len); 113 114 Sequence<T1> data(max_len, [](std::size_t i) { return T1(i); }); 115 116 for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) 117 { 118 invoke_on_all_policies(test_one_policy<iterator_type>(data.begin(), data.begin() + len), actual.begin(), 119 actual.begin() + len); 120 invoke_on_all_policies(test_one_policy<cbi_iterator_type>(data.cbibegin(), std::next(data.cbibegin(), len)), 121 actual.begin(), actual.begin() + len); 122 } 123 } 124 125 int32_t 126 main() 127 { 128 // clang-3.8 fails to correctly auto vectorize the loop in some cases of different types of container's elements, 129 // for example: int32_t and int8_t. This issue isn't detected for clang-3.9 and newer versions. 130 test<int16_t, int8_t>(); 131 test<uint16_t, float32_t>(); 132 test<float64_t, int64_t>(); 133 test<wrapper<float64_t>, wrapper<float64_t>>(); 134 135 std::cout << done() << std::endl; 136 return 0; 137 } 138