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
41template <class T>
42struct constructible_from {
43 T v_;
44
45 explicit constructible_from(T v) : v_(v) {}
46
47 friend constructible_from operator+(constructible_from lhs, constructible_from rhs) {
48 return constructible_from{lhs.get() + rhs.get()};
49 }
50
51 T get() const { return v_; }
52};
53
54template <class Iter1, class Iter2, class ValueT>
55struct Test {
56 template <class Policy>
57 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(cont&: a)),
70 Iter1(std::data(cont&: a) + std::size(cont: a)),
71 Iter2(std::data(cont&: 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(cont&: a)), Iter1(std::data(cont&: a) + std::size(cont: a)), Iter2(std::data(cont&: 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(arr&: a)),
100 Iter1(std::end(arr&: a)),
101 Iter2(std::begin(arr&: 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
110int 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

source code of libcxx/test/std/numerics/numeric.ops/transform.reduce/pstl.transform_reduce.binary.pass.cpp