1 // -*- C++ -*- 2 //===-- transform_reduce.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 #include "support/pstl_test_config.h" 13 14 #include <execution> 15 #include <numeric> 16 17 #include "support/utils.h" 18 19 using namespace TestUtils; 20 21 // Equal for all types 22 template <typename T> 23 static bool 24 Equal(T x, T y) 25 { 26 return x == y; 27 } 28 29 // Functor for xor-operation for modeling binary operations in inner_product 30 class XOR 31 { 32 public: 33 template <typename T> 34 T 35 operator()(const T& left, const T& right) const 36 { 37 return left ^ right; 38 } 39 }; 40 41 // Model of User-defined class 42 class MyClass 43 { 44 public: 45 int32_t my_field; 46 MyClass() { my_field = 0; } 47 MyClass(int32_t in) { my_field = in; } 48 MyClass(const MyClass& in) { my_field = in.my_field; } 49 50 friend MyClass 51 operator+(const MyClass& x, const MyClass& y) 52 { 53 return MyClass(x.my_field + y.my_field); 54 } 55 friend MyClass 56 operator-(const MyClass& x) 57 { 58 return MyClass(-x.my_field); 59 } 60 friend MyClass operator*(const MyClass& x, const MyClass& y) { return MyClass(x.my_field * y.my_field); } 61 bool 62 operator==(const MyClass& in) 63 { 64 return my_field == in.my_field; 65 } 66 }; 67 68 template <typename T> 69 void 70 CheckResults(const T& expected, const T& in) 71 { 72 EXPECT_TRUE(Equal(expected, in), "wrong result of transform_reduce"); 73 } 74 75 // We need to check correctness only for "int" (for example) except cases 76 // if we have "floating-point type"-specialization 77 void 78 CheckResults(const float32_t&, const float32_t&) 79 { 80 } 81 82 // Test for different types and operations with different iterators 83 struct test_transform_reduce 84 { 85 template <typename Policy, typename InputIterator1, typename InputIterator2, typename T, typename BinaryOperation1, 86 typename BinaryOperation2, typename UnaryOp> 87 void 88 operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2, 89 T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU) 90 { 91 92 auto expectedB = std::inner_product(first1, last1, first2, init, opB1, opB2); 93 auto expectedU = transform_reduce_serial(first1, last1, init, opB1, opU); 94 T resRA = std::transform_reduce(exec, first1, last1, first2, init, opB1, opB2); 95 CheckResults(expectedB, resRA); 96 resRA = std::transform_reduce(exec, first1, last1, init, opB1, opU); 97 CheckResults(expectedU, resRA); 98 } 99 }; 100 101 template <typename T, typename BinaryOperation1, typename BinaryOperation2, typename UnaryOp, typename Initializer> 102 void 103 test_by_type(T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU, Initializer initObj) 104 { 105 106 std::size_t maxSize = 100000; 107 Sequence<T> in1(maxSize, initObj); 108 Sequence<T> in2(maxSize, initObj); 109 110 for (std::size_t n = 0; n < maxSize; n = n < 16 ? n + 1 : size_t(3.1415 * n)) 111 { 112 invoke_on_all_policies(test_transform_reduce(), in1.begin(), in1.begin() + n, in2.begin(), in2.begin() + n, 113 init, opB1, opB2, opU); 114 invoke_on_all_policies(test_transform_reduce(), in1.cbegin(), in1.cbegin() + n, in2.cbegin(), in2.cbegin() + n, 115 init, opB1, opB2, opU); 116 } 117 } 118 119 int 120 main() 121 { 122 test_by_type<int32_t>(42, std::plus<int32_t>(), std::multiplies<int32_t>(), std::negate<int32_t>(), 123 [](std::size_t) -> int32_t { return int32_t(rand() % 1000); }); 124 test_by_type<int64_t>(0, [](const int64_t& a, const int64_t& b) -> int64_t { return a | b; }, XOR(), 125 [](const int64_t& x) -> int64_t { return x * 2; }, 126 [](std::size_t) -> int64_t { return int64_t(rand() % 1000); }); 127 test_by_type<float32_t>( 128 1.0f, std::multiplies<float32_t>(), [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; }, 129 [](const float32_t& x) -> float32_t { return x + 2; }, [](std::size_t) -> float32_t { return rand() % 1000; }); 130 test_by_type<MyClass>(MyClass(), std::plus<MyClass>(), std::multiplies<MyClass>(), std::negate<MyClass>(), 131 [](std::size_t) -> MyClass { return MyClass(rand() % 1000); }); 132 133 std::cout << done() << std::endl; 134 return 0; 135 } 136