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