15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier
95a83710eSEric Fiselier // <numeric>
105a83710eSEric Fiselier
1167c88e47SMark de Wever // Became constexpr in C++20
125a83710eSEric Fiselier // template<InputIterator InIter,
135a83710eSEric Fiselier // OutputIterator<auto, const InIter::value_type&> OutIter,
145a83710eSEric Fiselier // Callable<auto, const InIter::value_type&, InIter::reference> BinaryOperation>
155a83710eSEric Fiselier // requires HasAssign<InIter::value_type, BinaryOperation::result_type>
165a83710eSEric Fiselier // && Constructible<InIter::value_type, InIter::reference>
175a83710eSEric Fiselier // && CopyConstructible<BinaryOperation>
185a83710eSEric Fiselier // OutIter
195a83710eSEric Fiselier // partial_sum(InIter first, InIter last, OutIter result, BinaryOperation binary_op);
205a83710eSEric Fiselier
215a83710eSEric Fiselier #include <numeric>
225a83710eSEric Fiselier #include <functional>
23b2943765Szoecarver #include <string>
245a83710eSEric Fiselier #include <cassert>
255a83710eSEric Fiselier
267fc6a556SMarshall Clow #include "test_macros.h"
275a83710eSEric Fiselier #include "test_iterators.h"
285a83710eSEric Fiselier
29b2943765Szoecarver #if TEST_STD_VER > 17
30b2943765Szoecarver struct rvalue_addable
31b2943765Szoecarver {
32b2943765Szoecarver bool correctOperatorUsed = false;
33b2943765Szoecarver
34b2943765Szoecarver // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)
operator ()rvalue_addable3567c88e47SMark de Wever constexpr rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
36b2943765Szoecarver r.correctOperatorUsed = true;
37b2943765Szoecarver return std::move(r);
38b2943765Szoecarver }
39b2943765Szoecarver };
40b2943765Szoecarver
operator +(rvalue_addable & lhs,rvalue_addable const &)4167c88e47SMark de Wever constexpr rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
42b2943765Szoecarver {
43b2943765Szoecarver lhs.correctOperatorUsed = false;
44b2943765Szoecarver return lhs;
45b2943765Szoecarver }
46b2943765Szoecarver
operator +(rvalue_addable && lhs,rvalue_addable const &)4767c88e47SMark de Wever constexpr rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
48b2943765Szoecarver {
49b2943765Szoecarver lhs.correctOperatorUsed = true;
50b2943765Szoecarver return std::move(lhs);
51b2943765Szoecarver }
52b2943765Szoecarver
5367c88e47SMark de Wever constexpr void
test_use_move()54b2943765Szoecarver test_use_move()
55b2943765Szoecarver {
56b2943765Szoecarver const std::size_t size = 100;
57b2943765Szoecarver rvalue_addable arr[size];
58b2943765Szoecarver rvalue_addable res1[size];
59b2943765Szoecarver rvalue_addable res2[size];
60b2943765Szoecarver std::partial_sum(arr, arr + size, res1);
61b2943765Szoecarver std::partial_sum(arr, arr + size, res2, /*predicate=*/rvalue_addable());
62b2943765Szoecarver // start at 1 because the first element is not moved
63b2943765Szoecarver for (unsigned i = 1; i < size; ++i) assert(res1[i].correctOperatorUsed);
64b2943765Szoecarver for (unsigned i = 1; i < size; ++i) assert(res2[i].correctOperatorUsed);
65b2943765Szoecarver }
66b2943765Szoecarver #endif // TEST_STD_VER > 17
67b2943765Szoecarver
6867c88e47SMark de Wever // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
6967c88e47SMark de Wever // don't have the support yet. In these cases omit the constexpr test.
7067c88e47SMark de Wever // FIXME Remove constexpr string workaround introduced in D90569
7167c88e47SMark de Wever #if TEST_STD_VER > 17 && \
7267c88e47SMark de Wever (!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
73b2943765Szoecarver void
7467c88e47SMark de Wever #else
7567c88e47SMark de Wever TEST_CONSTEXPR_CXX20 void
7667c88e47SMark de Wever #endif
test_string()77b2943765Szoecarver test_string()
78b2943765Szoecarver {
79b2943765Szoecarver std::string sa[] = {"a", "b", "c"};
80b2943765Szoecarver std::string sr[] = {"a", "ba", "cb"};
81b2943765Szoecarver std::string output[3];
82b2943765Szoecarver std::adjacent_difference(sa, sa + 3, output, std::plus<std::string>());
83b2943765Szoecarver for (unsigned i = 0; i < 3; ++i) assert(output[i] == sr[i]);
84b2943765Szoecarver }
85b2943765Szoecarver
865a83710eSEric Fiselier template <class InIter, class OutIter>
8767c88e47SMark de Wever TEST_CONSTEXPR_CXX20 void
test()885a83710eSEric Fiselier test()
895a83710eSEric Fiselier {
905a83710eSEric Fiselier int ia[] = {1, 2, 3, 4, 5};
915a83710eSEric Fiselier int ir[] = {1, -1, -4, -8, -13};
925a83710eSEric Fiselier const unsigned s = sizeof(ia) / sizeof(ia[0]);
935a83710eSEric Fiselier int ib[s] = {0};
945a83710eSEric Fiselier OutIter r = std::partial_sum(InIter(ia), InIter(ia+s), OutIter(ib), std::minus<int>());
955a83710eSEric Fiselier assert(base(r) == ib + s);
965a83710eSEric Fiselier for (unsigned i = 0; i < s; ++i)
975a83710eSEric Fiselier assert(ib[i] == ir[i]);
985a83710eSEric Fiselier }
995a83710eSEric Fiselier
10067c88e47SMark de Wever TEST_CONSTEXPR_CXX20 bool
test()10167c88e47SMark de Wever test()
1025a83710eSEric Fiselier {
103*5e97d37bSMark de Wever test<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();
104773ae441SChristopher Di Bella test<cpp17_input_iterator<const int*>, forward_iterator<int*> >();
105773ae441SChristopher Di Bella test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();
106773ae441SChristopher Di Bella test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();
107773ae441SChristopher Di Bella test<cpp17_input_iterator<const int*>, int*>();
1085a83710eSEric Fiselier
109*5e97d37bSMark de Wever test<forward_iterator<const int*>, cpp17_output_iterator<int*> >();
1105a83710eSEric Fiselier test<forward_iterator<const int*>, forward_iterator<int*> >();
1115a83710eSEric Fiselier test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
1125a83710eSEric Fiselier test<forward_iterator<const int*>, random_access_iterator<int*> >();
1135a83710eSEric Fiselier test<forward_iterator<const int*>, int*>();
1145a83710eSEric Fiselier
115*5e97d37bSMark de Wever test<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
1165a83710eSEric Fiselier test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
1175a83710eSEric Fiselier test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
1185a83710eSEric Fiselier test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
1195a83710eSEric Fiselier test<bidirectional_iterator<const int*>, int*>();
1205a83710eSEric Fiselier
121*5e97d37bSMark de Wever test<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
1225a83710eSEric Fiselier test<random_access_iterator<const int*>, forward_iterator<int*> >();
1235a83710eSEric Fiselier test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
1245a83710eSEric Fiselier test<random_access_iterator<const int*>, random_access_iterator<int*> >();
1255a83710eSEric Fiselier test<random_access_iterator<const int*>, int*>();
1265a83710eSEric Fiselier
127*5e97d37bSMark de Wever test<const int*, cpp17_output_iterator<int*> >();
1285a83710eSEric Fiselier test<const int*, forward_iterator<int*> >();
1295a83710eSEric Fiselier test<const int*, bidirectional_iterator<int*> >();
1305a83710eSEric Fiselier test<const int*, random_access_iterator<int*> >();
1315a83710eSEric Fiselier test<const int*, int*>();
1322df59c50SJF Bastien
133b2943765Szoecarver #if TEST_STD_VER > 17
134b2943765Szoecarver test_use_move();
135b2943765Szoecarver #endif // TEST_STD_VER > 17
13667c88e47SMark de Wever // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
13767c88e47SMark de Wever // don't have the support yet. In these cases omit the constexpr test.
13867c88e47SMark de Wever // FIXME Remove constexpr string workaround introduced in D90569
13967c88e47SMark de Wever #if TEST_STD_VER > 17 && \
14067c88e47SMark de Wever (!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
14167c88e47SMark de Wever if (!std::is_constant_evaluated())
14267c88e47SMark de Wever #endif
143b2943765Szoecarver test_string();
144b2943765Szoecarver
14567c88e47SMark de Wever return true;
14667c88e47SMark de Wever }
14767c88e47SMark de Wever
main(int,char **)14867c88e47SMark de Wever int main(int, char**)
14967c88e47SMark de Wever {
15067c88e47SMark de Wever test();
15167c88e47SMark de Wever #if TEST_STD_VER > 17
15267c88e47SMark de Wever static_assert(test());
15367c88e47SMark de Wever #endif
15467c88e47SMark de Wever
1552df59c50SJF Bastien return 0;
1565a83710eSEric Fiselier }
157