xref: /llvm-project/pstl/test/std/numerics/numeric.ops/reduce.pass.cpp (revision 3b9a1bb1af90db9472340ef2122d3855eb9ba3fc)
13b62047bSLouis Dionne // -*- C++ -*-
23b62047bSLouis Dionne //===-- reduce.pass.cpp ---------------------------------------------------===//
33b62047bSLouis Dionne //
43b62047bSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
53b62047bSLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
63b62047bSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
73b62047bSLouis Dionne //
83b62047bSLouis Dionne //===----------------------------------------------------------------------===//
93b62047bSLouis Dionne 
10b5e896c0SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
116ab35c9dSLouis Dionne 
123b62047bSLouis Dionne #include "support/pstl_test_config.h"
133b62047bSLouis Dionne 
143b62047bSLouis Dionne #include <execution>
153b62047bSLouis Dionne #include <numeric>
163b62047bSLouis Dionne 
173b62047bSLouis Dionne #include "support/utils.h"
183b62047bSLouis Dionne 
193b62047bSLouis Dionne using namespace TestUtils;
203b62047bSLouis Dionne 
213b62047bSLouis Dionne struct test_long_forms_for_one_policy
223b62047bSLouis Dionne {
233b62047bSLouis Dionne     template <typename Policy, typename Iterator, typename T, typename BinaryOp>
243b62047bSLouis Dionne     void
operator ()test_long_forms_for_one_policy253b62047bSLouis Dionne     operator()(Policy&& exec, Iterator first, Iterator last, T init, BinaryOp binary, T expected)
263b62047bSLouis Dionne     {
273b62047bSLouis Dionne         T result_r = std::reduce(exec, first, last, init, binary);
283b62047bSLouis Dionne         EXPECT_EQ(expected, result_r, "bad result from reduce(exec, first, last, init, binary_op)");
293b62047bSLouis Dionne     }
303b62047bSLouis Dionne };
313b62047bSLouis Dionne 
323b62047bSLouis Dionne template <typename T, typename BinaryOp, typename F>
333b62047bSLouis Dionne void
test_long_form(T init,BinaryOp binary_op,F f)343b62047bSLouis Dionne test_long_form(T init, BinaryOp binary_op, F f)
353b62047bSLouis Dionne {
363b62047bSLouis Dionne     // Try sequences of various lengths
373b62047bSLouis Dionne     for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
383b62047bSLouis Dionne     {
393b62047bSLouis Dionne         T expected(init);
403b62047bSLouis Dionne         Sequence<T> in(n, [n, f](size_t k) { return f((int32_t(k ^ n) % 1000 - 500)); });
413b62047bSLouis Dionne         for (size_t k = 0; k < n; ++k)
423b62047bSLouis Dionne             expected = binary_op(expected, in[k]);
433b62047bSLouis Dionne 
443b62047bSLouis Dionne         using namespace std;
453b62047bSLouis Dionne 
463b62047bSLouis Dionne         T result = transform_reduce_serial(in.cfbegin(), in.cfend(), init, binary_op, [](const T& t) { return t; });
473b62047bSLouis Dionne         EXPECT_EQ(expected, result, "bad result from reduce(first, last, init, binary_op_op)");
483b62047bSLouis Dionne 
493b62047bSLouis Dionne         invoke_on_all_policies(test_long_forms_for_one_policy(), in.begin(), in.end(), init, binary_op, expected);
503b62047bSLouis Dionne         invoke_on_all_policies(test_long_forms_for_one_policy(), in.cbegin(), in.cend(), init, binary_op, expected);
513b62047bSLouis Dionne     }
523b62047bSLouis Dionne }
533b62047bSLouis Dionne 
543b62047bSLouis Dionne struct test_two_short_forms
553b62047bSLouis Dionne {
563b62047bSLouis Dionne 
57*3b9a1bb1SLouis Dionne #if defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) //dummy specialization by policy type, in case of broken configuration
583b62047bSLouis Dionne     template <typename Iterator>
593b62047bSLouis Dionne     void
operator ()test_two_short_forms603b62047bSLouis Dionne     operator()(pstl::execution::parallel_policy, Iterator first, Iterator last, Sum init, Sum expected)
613b62047bSLouis Dionne     {
623b62047bSLouis Dionne     }
633b62047bSLouis Dionne     template <typename Iterator>
643b62047bSLouis Dionne     void
operator ()test_two_short_forms653b62047bSLouis Dionne     operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Sum init, Sum expected)
663b62047bSLouis Dionne     {
673b62047bSLouis Dionne     }
683b62047bSLouis Dionne #endif
693b62047bSLouis Dionne 
703b62047bSLouis Dionne     template <typename Policy, typename Iterator>
713b62047bSLouis Dionne     void
operator ()test_two_short_forms723b62047bSLouis Dionne     operator()(Policy&& exec, Iterator first, Iterator last, Sum init, Sum expected)
733b62047bSLouis Dionne     {
743b62047bSLouis Dionne         using namespace std;
753b62047bSLouis Dionne 
763b62047bSLouis Dionne         Sum r0 = init + reduce(exec, first, last);
773b62047bSLouis Dionne         EXPECT_EQ(expected, r0, "bad result from reduce(exec, first, last)");
783b62047bSLouis Dionne 
793b62047bSLouis Dionne         Sum r1 = reduce(exec, first, last, init);
803b62047bSLouis Dionne         EXPECT_EQ(expected, r1, "bad result from reduce(exec, first, last, init)");
813b62047bSLouis Dionne     }
823b62047bSLouis Dionne };
833b62047bSLouis Dionne 
843b62047bSLouis Dionne // Test forms of reduce(...) that omit the binary_op or init operands.
853b62047bSLouis Dionne void
test_short_forms()863b62047bSLouis Dionne test_short_forms()
873b62047bSLouis Dionne {
883b62047bSLouis Dionne     for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
893b62047bSLouis Dionne     {
903b62047bSLouis Dionne         Sum init(42, OddTag());
913b62047bSLouis Dionne         Sum expected(init);
923b62047bSLouis Dionne         Sequence<Sum> in(n, [n](size_t k) { return Sum((int32_t(k ^ n) % 1000 - 500), OddTag()); });
933b62047bSLouis Dionne         for (size_t k = 0; k < n; ++k)
943b62047bSLouis Dionne             expected = expected + in[k];
953b62047bSLouis Dionne         invoke_on_all_policies(test_two_short_forms(), in.begin(), in.end(), init, expected);
963b62047bSLouis Dionne         invoke_on_all_policies(test_two_short_forms(), in.cbegin(), in.cend(), init, expected);
973b62047bSLouis Dionne     }
983b62047bSLouis Dionne }
993b62047bSLouis Dionne 
100249c1c74SLouis Dionne int
main()1013b62047bSLouis Dionne main()
1023b62047bSLouis Dionne {
1033b62047bSLouis Dionne     // Test for popular types
1043b62047bSLouis Dionne     test_long_form(42, std::plus<int32_t>(), [](int32_t x) { return x; });
1053b62047bSLouis Dionne     test_long_form(42.0, std::plus<float64_t>(), [](float64_t x) { return x; });
1063b62047bSLouis Dionne 
1073b62047bSLouis Dionne     // Test for strict types
1083b62047bSLouis Dionne     test_long_form<Number>(Number(42, OddTag()), Add(OddTag()), [](int32_t x) { return Number(x, OddTag()); });
1093b62047bSLouis Dionne 
1103b62047bSLouis Dionne     // Short forms are just facade for long forms, so just test with a single type.
1113b62047bSLouis Dionne     test_short_forms();
1123b62047bSLouis Dionne     std::cout << done() << std::endl;
1133b62047bSLouis Dionne     return 0;
1143b62047bSLouis Dionne }
115