1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // UNSUPPORTED: libcpp-has-no-incomplete-pstl
12 
13 // <numeric>
14 
15 // template<class ExecutionPolicy,
16 //          class ForwardIterator1, class ForwardIterator2, class T>
17 //   T transform_reduce(ExecutionPolicy&& exec,
18 //                      ForwardIterator1 first1, ForwardIterator1 last1,
19 //                      ForwardIterator2 first2,
20 //                      T init);
21 //
22 // template<class ExecutionPolicy,
23 //          class ForwardIterator1, class ForwardIterator2, class T,
24 //          class BinaryOperation1, class BinaryOperation2>
25 //   T transform_reduce(ExecutionPolicy&& exec,
26 //                      ForwardIterator1 first1, ForwardIterator1 last1,
27 //                      ForwardIterator2 first2,
28 //                      T init,
29 //                      BinaryOperation1 binary_op1,
30 //                      BinaryOperation2 binary_op2);
31 
32 #include <numeric>
33 #include <vector>
34 
35 #include "MoveOnly.h"
36 #include "test_execution_policies.h"
37 #include "test_iterators.h"
38 #include "test_macros.h"
39 #include "type_algorithms.h"
40 
41 template <class T>
42 struct constructible_from {
43   T v_;
44 
constructible_fromconstructible_from45   explicit constructible_from(T v) : v_(v) {}
46 
operator +(constructible_from lhs,constructible_from rhs)47   friend constructible_from operator+(constructible_from lhs, constructible_from rhs) {
48     return constructible_from{lhs.get() + rhs.get()};
49   }
50 
getconstructible_from51   T get() const { return v_; }
52 };
53 
54 template <class Iter1, class Iter2, class ValueT>
55 struct Test {
56   template <class Policy>
operator ()Test57   void operator()(Policy&& policy) {
58     for (const auto& pair : {std::pair{0, 34}, {1, 40}, {2, 48}, {100, 10534}, {350, 124284}}) {
59       auto [size, expected] = pair;
60       std::vector<int> a(size);
61       std::vector<int> b(size);
62       for (int i = 0; i != size; ++i) {
63         a[i] = i + 1;
64         b[i] = i + 4;
65       }
66 
67       decltype(auto) ret = std::transform_reduce(
68           policy,
69           Iter1(std::data(a)),
70           Iter1(std::data(a) + std::size(a)),
71           Iter2(std::data(b)),
72           ValueT(34),
73           std::plus{},
74           [](ValueT i, ValueT j) { return i + j + 1; });
75       static_assert(std::is_same_v<decltype(ret), ValueT>);
76       assert(ret == expected);
77     }
78 
79     for (const auto& pair : {std::pair{0, 34}, {1, 30}, {2, 24}, {100, 313134}, {350, 14045884}}) {
80       auto [size, expected] = pair;
81       std::vector<int> a(size);
82       std::vector<int> b(size);
83       for (int i = 0; i != size; ++i) {
84         a[i] = i + 1;
85         b[i] = i - 4;
86       }
87 
88       decltype(auto) ret = std::transform_reduce(
89           policy, Iter1(std::data(a)), Iter1(std::data(a) + std::size(a)), Iter2(std::data(b)), 34);
90       static_assert(std::is_same_v<decltype(ret), int>);
91       assert(ret == expected);
92     }
93     {
94       int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
95       int b[] = {8, 7, 6, 5, 4, 3, 2, 1};
96 
97       auto ret = std::transform_reduce(
98           policy,
99           Iter1(std::begin(a)),
100           Iter1(std::end(a)),
101           Iter2(std::begin(b)),
102           constructible_from<int>{0},
103           std::plus{},
104           [](int i, int j) { return constructible_from<int>{i + j}; });
105       assert(ret.get() == 72);
106     }
107   }
108 };
109 
main(int,char **)110 int main(int, char**) {
111   types::for_each(
112       types::forward_iterator_list<int*>{}, types::apply_type_identity{[](auto v) {
113         using Iter2 = typename decltype(v)::type;
114         types::for_each(
115             types::forward_iterator_list<int*>{}, types::apply_type_identity{[](auto v2) {
116               using Iter1 = typename decltype(v2)::type;
117               types::for_each(
118                   types::type_list<int, MoveOnly>{},
119                   TestIteratorWithPolicies<types::partial_instantiation<Test, Iter1, Iter2>::template apply>{});
120             }});
121       }});
122 
123   return 0;
124 }
125