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