1*0fca6ea1SDimitry Andric // -*- C++ -*- 2*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 3*0fca6ea1SDimitry Andric // 4*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*0fca6ea1SDimitry Andric // 8*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 9*0fca6ea1SDimitry Andric 10*0fca6ea1SDimitry Andric #ifndef _LIBCPP___PSTL_BACKENDS_SERIAL_H 11*0fca6ea1SDimitry Andric #define _LIBCPP___PSTL_BACKENDS_SERIAL_H 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include <__algorithm/find_if.h> 14*0fca6ea1SDimitry Andric #include <__algorithm/for_each.h> 15*0fca6ea1SDimitry Andric #include <__algorithm/merge.h> 16*0fca6ea1SDimitry Andric #include <__algorithm/stable_sort.h> 17*0fca6ea1SDimitry Andric #include <__algorithm/transform.h> 18*0fca6ea1SDimitry Andric #include <__config> 19*0fca6ea1SDimitry Andric #include <__numeric/transform_reduce.h> 20*0fca6ea1SDimitry Andric #include <__pstl/backend_fwd.h> 21*0fca6ea1SDimitry Andric #include <__utility/empty.h> 22*0fca6ea1SDimitry Andric #include <__utility/forward.h> 23*0fca6ea1SDimitry Andric #include <__utility/move.h> 24*0fca6ea1SDimitry Andric #include <optional> 25*0fca6ea1SDimitry Andric 26*0fca6ea1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 27*0fca6ea1SDimitry Andric # pragma GCC system_header 28*0fca6ea1SDimitry Andric #endif 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric _LIBCPP_PUSH_MACROS 31*0fca6ea1SDimitry Andric #include <__undef_macros> 32*0fca6ea1SDimitry Andric 33*0fca6ea1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 34*0fca6ea1SDimitry Andric namespace __pstl { 35*0fca6ea1SDimitry Andric 36*0fca6ea1SDimitry Andric // 37*0fca6ea1SDimitry Andric // This partial PSTL backend runs everything serially. 38*0fca6ea1SDimitry Andric // 39*0fca6ea1SDimitry Andric // TODO: Right now, the serial backend must be used with another backend 40*0fca6ea1SDimitry Andric // like the "default backend" because it doesn't implement all the 41*0fca6ea1SDimitry Andric // necessary PSTL operations. It would be better to dispatch all 42*0fca6ea1SDimitry Andric // algorithms to their serial counterpart directly, since this can 43*0fca6ea1SDimitry Andric // often be more efficient than the "default backend"'s implementation 44*0fca6ea1SDimitry Andric // if we end up running serially anyways. 45*0fca6ea1SDimitry Andric // 46*0fca6ea1SDimitry Andric 47*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 48*0fca6ea1SDimitry Andric struct __find_if<__serial_backend_tag, _ExecutionPolicy> { 49*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Pred> 50*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> 51*0fca6ea1SDimitry Andric operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 52*0fca6ea1SDimitry Andric return std::find_if(std::move(__first), std::move(__last), std::forward<_Pred>(__pred)); 53*0fca6ea1SDimitry Andric } 54*0fca6ea1SDimitry Andric }; 55*0fca6ea1SDimitry Andric 56*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 57*0fca6ea1SDimitry Andric struct __for_each<__serial_backend_tag, _ExecutionPolicy> { 58*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Function> 59*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<__empty> 60*0fca6ea1SDimitry Andric operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Function&& __func) const noexcept { 61*0fca6ea1SDimitry Andric std::for_each(std::move(__first), std::move(__last), std::forward<_Function>(__func)); 62*0fca6ea1SDimitry Andric return __empty{}; 63*0fca6ea1SDimitry Andric } 64*0fca6ea1SDimitry Andric }; 65*0fca6ea1SDimitry Andric 66*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 67*0fca6ea1SDimitry Andric struct __merge<__serial_backend_tag, _ExecutionPolicy> { 68*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Comp> 69*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> operator()( 70*0fca6ea1SDimitry Andric _Policy&&, 71*0fca6ea1SDimitry Andric _ForwardIterator1 __first1, 72*0fca6ea1SDimitry Andric _ForwardIterator1 __last1, 73*0fca6ea1SDimitry Andric _ForwardIterator2 __first2, 74*0fca6ea1SDimitry Andric _ForwardIterator2 __last2, 75*0fca6ea1SDimitry Andric _ForwardOutIterator __outit, 76*0fca6ea1SDimitry Andric _Comp&& __comp) const noexcept { 77*0fca6ea1SDimitry Andric return std::merge( 78*0fca6ea1SDimitry Andric std::move(__first1), 79*0fca6ea1SDimitry Andric std::move(__last1), 80*0fca6ea1SDimitry Andric std::move(__first2), 81*0fca6ea1SDimitry Andric std::move(__last2), 82*0fca6ea1SDimitry Andric std::move(__outit), 83*0fca6ea1SDimitry Andric std::forward<_Comp>(__comp)); 84*0fca6ea1SDimitry Andric } 85*0fca6ea1SDimitry Andric }; 86*0fca6ea1SDimitry Andric 87*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 88*0fca6ea1SDimitry Andric struct __stable_sort<__serial_backend_tag, _ExecutionPolicy> { 89*0fca6ea1SDimitry Andric template <class _Policy, class _RandomAccessIterator, class _Comp> 90*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<__empty> 91*0fca6ea1SDimitry Andric operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp&& __comp) const noexcept { 92*0fca6ea1SDimitry Andric std::stable_sort(std::move(__first), std::move(__last), std::forward<_Comp>(__comp)); 93*0fca6ea1SDimitry Andric return __empty{}; 94*0fca6ea1SDimitry Andric } 95*0fca6ea1SDimitry Andric }; 96*0fca6ea1SDimitry Andric 97*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 98*0fca6ea1SDimitry Andric struct __transform<__serial_backend_tag, _ExecutionPolicy> { 99*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _UnaryOperation> 100*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> operator()( 101*0fca6ea1SDimitry Andric _Policy&&, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __outit, _UnaryOperation&& __op) 102*0fca6ea1SDimitry Andric const noexcept { 103*0fca6ea1SDimitry Andric return std::transform( 104*0fca6ea1SDimitry Andric std::move(__first), std::move(__last), std::move(__outit), std::forward<_UnaryOperation>(__op)); 105*0fca6ea1SDimitry Andric } 106*0fca6ea1SDimitry Andric }; 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 109*0fca6ea1SDimitry Andric struct __transform_binary<__serial_backend_tag, _ExecutionPolicy> { 110*0fca6ea1SDimitry Andric template <class _Policy, 111*0fca6ea1SDimitry Andric class _ForwardIterator1, 112*0fca6ea1SDimitry Andric class _ForwardIterator2, 113*0fca6ea1SDimitry Andric class _ForwardOutIterator, 114*0fca6ea1SDimitry Andric class _BinaryOperation> 115*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 116*0fca6ea1SDimitry Andric operator()(_Policy&&, 117*0fca6ea1SDimitry Andric _ForwardIterator1 __first1, 118*0fca6ea1SDimitry Andric _ForwardIterator1 __last1, 119*0fca6ea1SDimitry Andric _ForwardIterator2 __first2, 120*0fca6ea1SDimitry Andric _ForwardOutIterator __outit, 121*0fca6ea1SDimitry Andric _BinaryOperation&& __op) const noexcept { 122*0fca6ea1SDimitry Andric return std::transform( 123*0fca6ea1SDimitry Andric std::move(__first1), 124*0fca6ea1SDimitry Andric std::move(__last1), 125*0fca6ea1SDimitry Andric std::move(__first2), 126*0fca6ea1SDimitry Andric std::move(__outit), 127*0fca6ea1SDimitry Andric std::forward<_BinaryOperation>(__op)); 128*0fca6ea1SDimitry Andric } 129*0fca6ea1SDimitry Andric }; 130*0fca6ea1SDimitry Andric 131*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 132*0fca6ea1SDimitry Andric struct __transform_reduce<__serial_backend_tag, _ExecutionPolicy> { 133*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation> 134*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<_Tp> 135*0fca6ea1SDimitry Andric operator()(_Policy&&, 136*0fca6ea1SDimitry Andric _ForwardIterator __first, 137*0fca6ea1SDimitry Andric _ForwardIterator __last, 138*0fca6ea1SDimitry Andric _Tp __init, 139*0fca6ea1SDimitry Andric _BinaryOperation&& __reduce, 140*0fca6ea1SDimitry Andric _UnaryOperation&& __transform) const noexcept { 141*0fca6ea1SDimitry Andric return std::transform_reduce( 142*0fca6ea1SDimitry Andric std::move(__first), 143*0fca6ea1SDimitry Andric std::move(__last), 144*0fca6ea1SDimitry Andric std::move(__init), 145*0fca6ea1SDimitry Andric std::forward<_BinaryOperation>(__reduce), 146*0fca6ea1SDimitry Andric std::forward<_UnaryOperation>(__transform)); 147*0fca6ea1SDimitry Andric } 148*0fca6ea1SDimitry Andric }; 149*0fca6ea1SDimitry Andric 150*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 151*0fca6ea1SDimitry Andric struct __transform_reduce_binary<__serial_backend_tag, _ExecutionPolicy> { 152*0fca6ea1SDimitry Andric template <class _Policy, 153*0fca6ea1SDimitry Andric class _ForwardIterator1, 154*0fca6ea1SDimitry Andric class _ForwardIterator2, 155*0fca6ea1SDimitry Andric class _Tp, 156*0fca6ea1SDimitry Andric class _BinaryOperation1, 157*0fca6ea1SDimitry Andric class _BinaryOperation2> 158*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<_Tp> operator()( 159*0fca6ea1SDimitry Andric _Policy&&, 160*0fca6ea1SDimitry Andric _ForwardIterator1 __first1, 161*0fca6ea1SDimitry Andric _ForwardIterator1 __last1, 162*0fca6ea1SDimitry Andric _ForwardIterator2 __first2, 163*0fca6ea1SDimitry Andric _Tp __init, 164*0fca6ea1SDimitry Andric _BinaryOperation1&& __reduce, 165*0fca6ea1SDimitry Andric _BinaryOperation2&& __transform) const noexcept { 166*0fca6ea1SDimitry Andric return std::transform_reduce( 167*0fca6ea1SDimitry Andric std::move(__first1), 168*0fca6ea1SDimitry Andric std::move(__last1), 169*0fca6ea1SDimitry Andric std::move(__first2), 170*0fca6ea1SDimitry Andric std::move(__init), 171*0fca6ea1SDimitry Andric std::forward<_BinaryOperation1>(__reduce), 172*0fca6ea1SDimitry Andric std::forward<_BinaryOperation2>(__transform)); 173*0fca6ea1SDimitry Andric } 174*0fca6ea1SDimitry Andric }; 175*0fca6ea1SDimitry Andric 176*0fca6ea1SDimitry Andric } // namespace __pstl 177*0fca6ea1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 178*0fca6ea1SDimitry Andric 179*0fca6ea1SDimitry Andric _LIBCPP_POP_MACROS 180*0fca6ea1SDimitry Andric 181*0fca6ea1SDimitry Andric #endif // _LIBCPP___PSTL_BACKENDS_SERIAL_H 182