2 //===-- transform_reduce.pass.cpp -----------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: c++03, c++11, c++14
12 #include "support/pstl_test_config.h"
17 #include "support/utils.h"
19 using namespace TestUtils
;
21 // Functor for xor-operation for modeling binary operations in inner_product
27 operator()(const T
& left
, const T
& right
) const
33 // Model of User-defined class
38 MyClass() { my_field
= 0; }
39 MyClass(int32_t in
) { my_field
= in
; }
40 MyClass(const MyClass
& in
) = default;
43 operator+(const MyClass
& x
, const MyClass
& y
)
45 return MyClass(x
.my_field
+ y
.my_field
);
48 operator-(const MyClass
& x
)
50 return MyClass(-x
.my_field
);
52 friend MyClass
operator*(const MyClass
& x
, const MyClass
& y
)
54 return MyClass(x
.my_field
* y
.my_field
);
56 friend bool operator==(const MyClass
& x
, const MyClass
& y
)
58 return x
.my_field
== y
.my_field
;
64 CheckResults(const T
& expected
, const T
& in
)
66 EXPECT_TRUE(expected
== in
, "wrong result of transform_reduce");
69 // We need to check correctness only for "int" (for example) except cases
70 // if we have "floating-point type"-specialization
72 CheckResults(const float32_t
&, const float32_t
&)
76 // Test for different types and operations with different iterators
77 struct test_transform_reduce
79 template <typename Policy
, typename InputIterator1
, typename InputIterator2
, typename T
, typename BinaryOperation1
,
80 typename BinaryOperation2
, typename UnaryOp
>
82 operator()(Policy
&& exec
, InputIterator1 first1
, InputIterator1 last1
, InputIterator2 first2
, InputIterator2
,
83 T init
, BinaryOperation1 opB1
, BinaryOperation2 opB2
, UnaryOp opU
)
86 auto expectedB
= std::inner_product(first1
, last1
, first2
, init
, opB1
, opB2
);
87 auto expectedU
= transform_reduce_serial(first1
, last1
, init
, opB1
, opU
);
88 T resRA
= std::transform_reduce(exec
, first1
, last1
, first2
, init
, opB1
, opB2
);
89 CheckResults(expectedB
, resRA
);
90 resRA
= std::transform_reduce(exec
, first1
, last1
, init
, opB1
, opU
);
91 CheckResults(expectedU
, resRA
);
95 template <typename T
, typename BinaryOperation1
, typename BinaryOperation2
, typename UnaryOp
, typename Initializer
>
97 test_by_type(T init
, BinaryOperation1 opB1
, BinaryOperation2 opB2
, UnaryOp opU
, Initializer initObj
)
100 std::size_t maxSize
= 100000;
101 Sequence
<T
> in1(maxSize
, initObj
);
102 Sequence
<T
> in2(maxSize
, initObj
);
104 for (std::size_t n
= 0; n
< maxSize
; n
= n
< 16 ? n
+ 1 : size_t(3.1415 * n
))
106 invoke_on_all_policies(test_transform_reduce(), in1
.begin(), in1
.begin() + n
, in2
.begin(), in2
.begin() + n
,
107 init
, opB1
, opB2
, opU
);
108 invoke_on_all_policies(test_transform_reduce(), in1
.cbegin(), in1
.cbegin() + n
, in2
.cbegin(), in2
.cbegin() + n
,
109 init
, opB1
, opB2
, opU
);
116 test_by_type
<int32_t>(42, std::plus
<int32_t>(), std::multiplies
<int32_t>(), std::negate
<int32_t>(),
117 [](std::size_t) -> int32_t { return int32_t(rand() % 1000); });
118 test_by_type
<int64_t>(0, [](const int64_t& a
, const int64_t& b
) -> int64_t { return a
| b
; }, XOR(),
119 [](const int64_t& x
) -> int64_t { return x
* 2; },
120 [](std::size_t) -> int64_t { return int64_t(rand() % 1000); });
121 test_by_type
<float32_t
>(
122 1.0f
, std::multiplies
<float32_t
>(), [](const float32_t
& a
, const float32_t
& b
) -> float32_t
{ return a
+ b
; },
123 [](const float32_t
& x
) -> float32_t
{ return x
+ 2; }, [](std::size_t) -> float32_t
{ return rand() % 1000; });
124 test_by_type
<MyClass
>(MyClass(), std::plus
<MyClass
>(), std::multiplies
<MyClass
>(), std::negate
<MyClass
>(),
125 [](std::size_t) -> MyClass
{ return MyClass(rand() % 1000); });
127 std::cout
<< done() << std::endl
;