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