1*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #ifndef _LIBCPP___PSTL_BACKENDS_DEFAULT_H 10*0fca6ea1SDimitry Andric #define _LIBCPP___PSTL_BACKENDS_DEFAULT_H 11*0fca6ea1SDimitry Andric 12*0fca6ea1SDimitry Andric #include <__algorithm/copy_n.h> 13*0fca6ea1SDimitry Andric #include <__algorithm/equal.h> 14*0fca6ea1SDimitry Andric #include <__algorithm/fill_n.h> 15*0fca6ea1SDimitry Andric #include <__algorithm/for_each_n.h> 16*0fca6ea1SDimitry Andric #include <__config> 17*0fca6ea1SDimitry Andric #include <__functional/identity.h> 18*0fca6ea1SDimitry Andric #include <__functional/not_fn.h> 19*0fca6ea1SDimitry Andric #include <__functional/operations.h> 20*0fca6ea1SDimitry Andric #include <__iterator/concepts.h> 21*0fca6ea1SDimitry Andric #include <__iterator/iterator_traits.h> 22*0fca6ea1SDimitry Andric #include <__pstl/backend_fwd.h> 23*0fca6ea1SDimitry Andric #include <__pstl/dispatch.h> 24*0fca6ea1SDimitry Andric #include <__utility/empty.h> 25*0fca6ea1SDimitry Andric #include <__utility/forward.h> 26*0fca6ea1SDimitry Andric #include <__utility/move.h> 27*0fca6ea1SDimitry Andric #include <optional> 28*0fca6ea1SDimitry Andric 29*0fca6ea1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30*0fca6ea1SDimitry Andric # pragma GCC system_header 31*0fca6ea1SDimitry Andric #endif 32*0fca6ea1SDimitry Andric 33*0fca6ea1SDimitry Andric _LIBCPP_PUSH_MACROS 34*0fca6ea1SDimitry Andric #include <__undef_macros> 35*0fca6ea1SDimitry Andric 36*0fca6ea1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 37*0fca6ea1SDimitry Andric namespace __pstl { 38*0fca6ea1SDimitry Andric 39*0fca6ea1SDimitry Andric // 40*0fca6ea1SDimitry Andric // This file provides an incomplete PSTL backend that implements all of the PSTL algorithms 41*0fca6ea1SDimitry Andric // based on a smaller set of basis operations. 42*0fca6ea1SDimitry Andric // 43*0fca6ea1SDimitry Andric // It is intended as a building block for other PSTL backends that implement some operations more 44*0fca6ea1SDimitry Andric // efficiently but may not want to define the full set of PSTL algorithms. 45*0fca6ea1SDimitry Andric // 46*0fca6ea1SDimitry Andric // This backend implements all the PSTL algorithms based on the following basis operations: 47*0fca6ea1SDimitry Andric // 48*0fca6ea1SDimitry Andric // find_if family 49*0fca6ea1SDimitry Andric // -------------- 50*0fca6ea1SDimitry Andric // - find 51*0fca6ea1SDimitry Andric // - find_if_not 52*0fca6ea1SDimitry Andric // - any_of 53*0fca6ea1SDimitry Andric // - all_of 54*0fca6ea1SDimitry Andric // - none_of 55*0fca6ea1SDimitry Andric // - is_partitioned 56*0fca6ea1SDimitry Andric // 57*0fca6ea1SDimitry Andric // for_each family 58*0fca6ea1SDimitry Andric // --------------- 59*0fca6ea1SDimitry Andric // - for_each_n 60*0fca6ea1SDimitry Andric // - fill 61*0fca6ea1SDimitry Andric // - fill_n 62*0fca6ea1SDimitry Andric // - replace 63*0fca6ea1SDimitry Andric // - replace_if 64*0fca6ea1SDimitry Andric // - generate 65*0fca6ea1SDimitry Andric // - generate_n 66*0fca6ea1SDimitry Andric // 67*0fca6ea1SDimitry Andric // merge family 68*0fca6ea1SDimitry Andric // ------------ 69*0fca6ea1SDimitry Andric // No other algorithms based on merge 70*0fca6ea1SDimitry Andric // 71*0fca6ea1SDimitry Andric // stable_sort family 72*0fca6ea1SDimitry Andric // ------------------ 73*0fca6ea1SDimitry Andric // - sort 74*0fca6ea1SDimitry Andric // 75*0fca6ea1SDimitry Andric // transform_reduce and transform_reduce_binary family 76*0fca6ea1SDimitry Andric // --------------------------------------------------- 77*0fca6ea1SDimitry Andric // - count_if 78*0fca6ea1SDimitry Andric // - count 79*0fca6ea1SDimitry Andric // - equal(3 legs) 80*0fca6ea1SDimitry Andric // - equal 81*0fca6ea1SDimitry Andric // - reduce 82*0fca6ea1SDimitry Andric // 83*0fca6ea1SDimitry Andric // transform and transform_binary family 84*0fca6ea1SDimitry Andric // ------------------------------------- 85*0fca6ea1SDimitry Andric // - replace_copy_if 86*0fca6ea1SDimitry Andric // - replace_copy 87*0fca6ea1SDimitry Andric // - move 88*0fca6ea1SDimitry Andric // - copy 89*0fca6ea1SDimitry Andric // - copy_n 90*0fca6ea1SDimitry Andric // - rotate_copy 91*0fca6ea1SDimitry Andric // 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 94*0fca6ea1SDimitry Andric // find_if family 95*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 96*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 97*0fca6ea1SDimitry Andric struct __find<__default_backend_tag, _ExecutionPolicy> { 98*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Tp> 99*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> 100*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept { 101*0fca6ea1SDimitry Andric using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 102*0fca6ea1SDimitry Andric return _FindIf()( 103*0fca6ea1SDimitry Andric __policy, std::move(__first), std::move(__last), [&](__iter_reference<_ForwardIterator> __element) { 104*0fca6ea1SDimitry Andric return __element == __value; 105*0fca6ea1SDimitry Andric }); 106*0fca6ea1SDimitry Andric } 107*0fca6ea1SDimitry Andric }; 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 110*0fca6ea1SDimitry Andric struct __find_if_not<__default_backend_tag, _ExecutionPolicy> { 111*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Pred> 112*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> 113*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 114*0fca6ea1SDimitry Andric using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 115*0fca6ea1SDimitry Andric return _FindIf()(__policy, __first, __last, std::not_fn(std::forward<_Pred>(__pred))); 116*0fca6ea1SDimitry Andric } 117*0fca6ea1SDimitry Andric }; 118*0fca6ea1SDimitry Andric 119*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 120*0fca6ea1SDimitry Andric struct __any_of<__default_backend_tag, _ExecutionPolicy> { 121*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Pred> 122*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 123*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 124*0fca6ea1SDimitry Andric using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 125*0fca6ea1SDimitry Andric auto __res = _FindIf()(__policy, __first, __last, std::forward<_Pred>(__pred)); 126*0fca6ea1SDimitry Andric if (!__res) 127*0fca6ea1SDimitry Andric return nullopt; 128*0fca6ea1SDimitry Andric return *__res != __last; 129*0fca6ea1SDimitry Andric } 130*0fca6ea1SDimitry Andric }; 131*0fca6ea1SDimitry Andric 132*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 133*0fca6ea1SDimitry Andric struct __all_of<__default_backend_tag, _ExecutionPolicy> { 134*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Pred> 135*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 136*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 137*0fca6ea1SDimitry Andric using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; 138*0fca6ea1SDimitry Andric auto __res = _AnyOf()(__policy, __first, __last, [&](__iter_reference<_ForwardIterator> __value) { 139*0fca6ea1SDimitry Andric return !__pred(__value); 140*0fca6ea1SDimitry Andric }); 141*0fca6ea1SDimitry Andric if (!__res) 142*0fca6ea1SDimitry Andric return nullopt; 143*0fca6ea1SDimitry Andric return !*__res; 144*0fca6ea1SDimitry Andric } 145*0fca6ea1SDimitry Andric }; 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 148*0fca6ea1SDimitry Andric struct __none_of<__default_backend_tag, _ExecutionPolicy> { 149*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Pred> 150*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 151*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 152*0fca6ea1SDimitry Andric using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; 153*0fca6ea1SDimitry Andric auto __res = _AnyOf()(__policy, __first, __last, std::forward<_Pred>(__pred)); 154*0fca6ea1SDimitry Andric if (!__res) 155*0fca6ea1SDimitry Andric return nullopt; 156*0fca6ea1SDimitry Andric return !*__res; 157*0fca6ea1SDimitry Andric } 158*0fca6ea1SDimitry Andric }; 159*0fca6ea1SDimitry Andric 160*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 161*0fca6ea1SDimitry Andric struct __is_partitioned<__default_backend_tag, _ExecutionPolicy> { 162*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Pred> 163*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 164*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 165*0fca6ea1SDimitry Andric using _FindIfNot = __dispatch<__find_if_not, __current_configuration, _ExecutionPolicy>; 166*0fca6ea1SDimitry Andric auto __maybe_first = _FindIfNot()(__policy, std::move(__first), std::move(__last), __pred); 167*0fca6ea1SDimitry Andric if (__maybe_first == nullopt) 168*0fca6ea1SDimitry Andric return nullopt; 169*0fca6ea1SDimitry Andric 170*0fca6ea1SDimitry Andric __first = *__maybe_first; 171*0fca6ea1SDimitry Andric if (__first == __last) 172*0fca6ea1SDimitry Andric return true; 173*0fca6ea1SDimitry Andric ++__first; 174*0fca6ea1SDimitry Andric using _NoneOf = __dispatch<__none_of, __current_configuration, _ExecutionPolicy>; 175*0fca6ea1SDimitry Andric return _NoneOf()(__policy, std::move(__first), std::move(__last), __pred); 176*0fca6ea1SDimitry Andric } 177*0fca6ea1SDimitry Andric }; 178*0fca6ea1SDimitry Andric 179*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 180*0fca6ea1SDimitry Andric // for_each family 181*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 182*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 183*0fca6ea1SDimitry Andric struct __for_each_n<__default_backend_tag, _ExecutionPolicy> { 184*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Size, class _Function> 185*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 186*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) const noexcept { 187*0fca6ea1SDimitry Andric if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 188*0fca6ea1SDimitry Andric using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 189*0fca6ea1SDimitry Andric _ForwardIterator __last = __first + __size; 190*0fca6ea1SDimitry Andric return _ForEach()(__policy, std::move(__first), std::move(__last), std::move(__func)); 191*0fca6ea1SDimitry Andric } else { 192*0fca6ea1SDimitry Andric // Otherwise, use the serial algorithm to avoid doing two passes over the input 193*0fca6ea1SDimitry Andric std::for_each_n(std::move(__first), __size, std::move(__func)); 194*0fca6ea1SDimitry Andric return __empty{}; 195*0fca6ea1SDimitry Andric } 196*0fca6ea1SDimitry Andric } 197*0fca6ea1SDimitry Andric }; 198*0fca6ea1SDimitry Andric 199*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 200*0fca6ea1SDimitry Andric struct __fill<__default_backend_tag, _ExecutionPolicy> { 201*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Tp> 202*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 203*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { 204*0fca6ea1SDimitry Andric using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 205*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 206*0fca6ea1SDimitry Andric return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __value; }); 207*0fca6ea1SDimitry Andric } 208*0fca6ea1SDimitry Andric }; 209*0fca6ea1SDimitry Andric 210*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 211*0fca6ea1SDimitry Andric struct __fill_n<__default_backend_tag, _ExecutionPolicy> { 212*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Size, class _Tp> 213*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 214*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept { 215*0fca6ea1SDimitry Andric if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 216*0fca6ea1SDimitry Andric using _Fill = __dispatch<__fill, __current_configuration, _ExecutionPolicy>; 217*0fca6ea1SDimitry Andric _ForwardIterator __last = __first + __n; 218*0fca6ea1SDimitry Andric return _Fill()(__policy, std::move(__first), std::move(__last), __value); 219*0fca6ea1SDimitry Andric } else { 220*0fca6ea1SDimitry Andric // Otherwise, use the serial algorithm to avoid doing two passes over the input 221*0fca6ea1SDimitry Andric std::fill_n(std::move(__first), __n, __value); 222*0fca6ea1SDimitry Andric return optional<__empty>{__empty{}}; 223*0fca6ea1SDimitry Andric } 224*0fca6ea1SDimitry Andric } 225*0fca6ea1SDimitry Andric }; 226*0fca6ea1SDimitry Andric 227*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 228*0fca6ea1SDimitry Andric struct __replace<__default_backend_tag, _ExecutionPolicy> { 229*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Tp> 230*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 231*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __old, _Tp const& __new) 232*0fca6ea1SDimitry Andric const noexcept { 233*0fca6ea1SDimitry Andric using _ReplaceIf = __dispatch<__replace_if, __current_configuration, _ExecutionPolicy>; 234*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 235*0fca6ea1SDimitry Andric return _ReplaceIf()( 236*0fca6ea1SDimitry Andric __policy, std::move(__first), std::move(__last), [&](_Ref __element) { return __element == __old; }, __new); 237*0fca6ea1SDimitry Andric } 238*0fca6ea1SDimitry Andric }; 239*0fca6ea1SDimitry Andric 240*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 241*0fca6ea1SDimitry Andric struct __replace_if<__default_backend_tag, _ExecutionPolicy> { 242*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Pred, class _Tp> 243*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( 244*0fca6ea1SDimitry Andric _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred, _Tp const& __new_value) 245*0fca6ea1SDimitry Andric const noexcept { 246*0fca6ea1SDimitry Andric using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 247*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 248*0fca6ea1SDimitry Andric return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { 249*0fca6ea1SDimitry Andric if (__pred(__element)) 250*0fca6ea1SDimitry Andric __element = __new_value; 251*0fca6ea1SDimitry Andric }); 252*0fca6ea1SDimitry Andric } 253*0fca6ea1SDimitry Andric }; 254*0fca6ea1SDimitry Andric 255*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 256*0fca6ea1SDimitry Andric struct __generate<__default_backend_tag, _ExecutionPolicy> { 257*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Generator> 258*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 259*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator&& __gen) const noexcept { 260*0fca6ea1SDimitry Andric using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 261*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 262*0fca6ea1SDimitry Andric return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __gen(); }); 263*0fca6ea1SDimitry Andric } 264*0fca6ea1SDimitry Andric }; 265*0fca6ea1SDimitry Andric 266*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 267*0fca6ea1SDimitry Andric struct __generate_n<__default_backend_tag, _ExecutionPolicy> { 268*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Size, class _Generator> 269*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 270*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Generator&& __gen) const noexcept { 271*0fca6ea1SDimitry Andric using _ForEachN = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>; 272*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 273*0fca6ea1SDimitry Andric return _ForEachN()(__policy, std::move(__first), __n, [&](_Ref __element) { __element = __gen(); }); 274*0fca6ea1SDimitry Andric } 275*0fca6ea1SDimitry Andric }; 276*0fca6ea1SDimitry Andric 277*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 278*0fca6ea1SDimitry Andric // stable_sort family 279*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 280*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 281*0fca6ea1SDimitry Andric struct __sort<__default_backend_tag, _ExecutionPolicy> { 282*0fca6ea1SDimitry Andric template <class _Policy, class _RandomAccessIterator, class _Comp> 283*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( 284*0fca6ea1SDimitry Andric _Policy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp&& __comp) const noexcept { 285*0fca6ea1SDimitry Andric using _StableSort = __dispatch<__stable_sort, __current_configuration, _ExecutionPolicy>; 286*0fca6ea1SDimitry Andric return _StableSort()(__policy, std::move(__first), std::move(__last), std::forward<_Comp>(__comp)); 287*0fca6ea1SDimitry Andric } 288*0fca6ea1SDimitry Andric }; 289*0fca6ea1SDimitry Andric 290*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 291*0fca6ea1SDimitry Andric // transform_reduce family 292*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 293*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 294*0fca6ea1SDimitry Andric struct __count_if<__default_backend_tag, _ExecutionPolicy> { 295*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Predicate> 296*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> operator()( 297*0fca6ea1SDimitry Andric _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred) const noexcept { 298*0fca6ea1SDimitry Andric using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; 299*0fca6ea1SDimitry Andric using _DiffT = __iter_diff_t<_ForwardIterator>; 300*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 301*0fca6ea1SDimitry Andric return _TransformReduce()( 302*0fca6ea1SDimitry Andric __policy, std::move(__first), std::move(__last), _DiffT{}, std::plus{}, [&](_Ref __element) -> _DiffT { 303*0fca6ea1SDimitry Andric return __pred(__element) ? _DiffT(1) : _DiffT(0); 304*0fca6ea1SDimitry Andric }); 305*0fca6ea1SDimitry Andric } 306*0fca6ea1SDimitry Andric }; 307*0fca6ea1SDimitry Andric 308*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 309*0fca6ea1SDimitry Andric struct __count<__default_backend_tag, _ExecutionPolicy> { 310*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Tp> 311*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> 312*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { 313*0fca6ea1SDimitry Andric using _CountIf = __dispatch<__count_if, __current_configuration, _ExecutionPolicy>; 314*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 315*0fca6ea1SDimitry Andric return _CountIf()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) -> bool { 316*0fca6ea1SDimitry Andric return __element == __value; 317*0fca6ea1SDimitry Andric }); 318*0fca6ea1SDimitry Andric } 319*0fca6ea1SDimitry Andric }; 320*0fca6ea1SDimitry Andric 321*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 322*0fca6ea1SDimitry Andric struct __equal_3leg<__default_backend_tag, _ExecutionPolicy> { 323*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> 324*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 325*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, 326*0fca6ea1SDimitry Andric _ForwardIterator1 __first1, 327*0fca6ea1SDimitry Andric _ForwardIterator1 __last1, 328*0fca6ea1SDimitry Andric _ForwardIterator2 __first2, 329*0fca6ea1SDimitry Andric _Predicate&& __pred) const noexcept { 330*0fca6ea1SDimitry Andric using _TransformReduce = __dispatch<__transform_reduce_binary, __current_configuration, _ExecutionPolicy>; 331*0fca6ea1SDimitry Andric return _TransformReduce()( 332*0fca6ea1SDimitry Andric __policy, 333*0fca6ea1SDimitry Andric std::move(__first1), 334*0fca6ea1SDimitry Andric std::move(__last1), 335*0fca6ea1SDimitry Andric std::move(__first2), 336*0fca6ea1SDimitry Andric true, 337*0fca6ea1SDimitry Andric std::logical_and{}, 338*0fca6ea1SDimitry Andric std::forward<_Predicate>(__pred)); 339*0fca6ea1SDimitry Andric } 340*0fca6ea1SDimitry Andric }; 341*0fca6ea1SDimitry Andric 342*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 343*0fca6ea1SDimitry Andric struct __equal<__default_backend_tag, _ExecutionPolicy> { 344*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> 345*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 346*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, 347*0fca6ea1SDimitry Andric _ForwardIterator1 __first1, 348*0fca6ea1SDimitry Andric _ForwardIterator1 __last1, 349*0fca6ea1SDimitry Andric _ForwardIterator2 __first2, 350*0fca6ea1SDimitry Andric _ForwardIterator2 __last2, 351*0fca6ea1SDimitry Andric _Predicate&& __pred) const noexcept { 352*0fca6ea1SDimitry Andric if constexpr (__has_random_access_iterator_category<_ForwardIterator1>::value && 353*0fca6ea1SDimitry Andric __has_random_access_iterator_category<_ForwardIterator2>::value) { 354*0fca6ea1SDimitry Andric if (__last1 - __first1 != __last2 - __first2) 355*0fca6ea1SDimitry Andric return false; 356*0fca6ea1SDimitry Andric // Fall back to the 3 legged algorithm 357*0fca6ea1SDimitry Andric using _Equal3Leg = __dispatch<__equal_3leg, __current_configuration, _ExecutionPolicy>; 358*0fca6ea1SDimitry Andric return _Equal3Leg()( 359*0fca6ea1SDimitry Andric __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::forward<_Predicate>(__pred)); 360*0fca6ea1SDimitry Andric } else { 361*0fca6ea1SDimitry Andric // If we don't have random access, fall back to the serial algorithm cause we can't do much 362*0fca6ea1SDimitry Andric return std::equal( 363*0fca6ea1SDimitry Andric std::move(__first1), 364*0fca6ea1SDimitry Andric std::move(__last1), 365*0fca6ea1SDimitry Andric std::move(__first2), 366*0fca6ea1SDimitry Andric std::move(__last2), 367*0fca6ea1SDimitry Andric std::forward<_Predicate>(__pred)); 368*0fca6ea1SDimitry Andric } 369*0fca6ea1SDimitry Andric } 370*0fca6ea1SDimitry Andric }; 371*0fca6ea1SDimitry Andric 372*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 373*0fca6ea1SDimitry Andric struct __reduce<__default_backend_tag, _ExecutionPolicy> { 374*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Tp, class _BinaryOperation> 375*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Tp> 376*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation&& __op) 377*0fca6ea1SDimitry Andric const noexcept { 378*0fca6ea1SDimitry Andric using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; 379*0fca6ea1SDimitry Andric return _TransformReduce()( 380*0fca6ea1SDimitry Andric __policy, 381*0fca6ea1SDimitry Andric std::move(__first), 382*0fca6ea1SDimitry Andric std::move(__last), 383*0fca6ea1SDimitry Andric std::move(__init), 384*0fca6ea1SDimitry Andric std::forward<_BinaryOperation>(__op), 385*0fca6ea1SDimitry Andric __identity{}); 386*0fca6ea1SDimitry Andric } 387*0fca6ea1SDimitry Andric }; 388*0fca6ea1SDimitry Andric 389*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 390*0fca6ea1SDimitry Andric // transform family 391*0fca6ea1SDimitry Andric ////////////////////////////////////////////////////////////// 392*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 393*0fca6ea1SDimitry Andric struct __replace_copy_if<__default_backend_tag, _ExecutionPolicy> { 394*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Pred, class _Tp> 395*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 396*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, 397*0fca6ea1SDimitry Andric _ForwardIterator __first, 398*0fca6ea1SDimitry Andric _ForwardIterator __last, 399*0fca6ea1SDimitry Andric _ForwardOutIterator __out_it, 400*0fca6ea1SDimitry Andric _Pred&& __pred, 401*0fca6ea1SDimitry Andric _Tp const& __new_value) const noexcept { 402*0fca6ea1SDimitry Andric using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 403*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 404*0fca6ea1SDimitry Andric auto __res = 405*0fca6ea1SDimitry Andric _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](_Ref __element) { 406*0fca6ea1SDimitry Andric return __pred(__element) ? __new_value : __element; 407*0fca6ea1SDimitry Andric }); 408*0fca6ea1SDimitry Andric if (__res == nullopt) 409*0fca6ea1SDimitry Andric return nullopt; 410*0fca6ea1SDimitry Andric return __empty{}; 411*0fca6ea1SDimitry Andric } 412*0fca6ea1SDimitry Andric }; 413*0fca6ea1SDimitry Andric 414*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 415*0fca6ea1SDimitry Andric struct __replace_copy<__default_backend_tag, _ExecutionPolicy> { 416*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Tp> 417*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 418*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, 419*0fca6ea1SDimitry Andric _ForwardIterator __first, 420*0fca6ea1SDimitry Andric _ForwardIterator __last, 421*0fca6ea1SDimitry Andric _ForwardOutIterator __out_it, 422*0fca6ea1SDimitry Andric _Tp const& __old_value, 423*0fca6ea1SDimitry Andric _Tp const& __new_value) const noexcept { 424*0fca6ea1SDimitry Andric using _ReplaceCopyIf = __dispatch<__replace_copy_if, __current_configuration, _ExecutionPolicy>; 425*0fca6ea1SDimitry Andric using _Ref = __iter_reference<_ForwardIterator>; 426*0fca6ea1SDimitry Andric return _ReplaceCopyIf()( 427*0fca6ea1SDimitry Andric __policy, 428*0fca6ea1SDimitry Andric std::move(__first), 429*0fca6ea1SDimitry Andric std::move(__last), 430*0fca6ea1SDimitry Andric std::move(__out_it), 431*0fca6ea1SDimitry Andric [&](_Ref __element) { return __element == __old_value; }, 432*0fca6ea1SDimitry Andric __new_value); 433*0fca6ea1SDimitry Andric } 434*0fca6ea1SDimitry Andric }; 435*0fca6ea1SDimitry Andric 436*0fca6ea1SDimitry Andric // TODO: Use the std::copy/move shenanigans to forward to std::memmove 437*0fca6ea1SDimitry Andric // Investigate whether we want to still forward to std::transform(policy) 438*0fca6ea1SDimitry Andric // in that case for the execution::par part, or whether we actually want 439*0fca6ea1SDimitry Andric // to run everything serially in that case. 440*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 441*0fca6ea1SDimitry Andric struct __move<__default_backend_tag, _ExecutionPolicy> { 442*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 443*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 444*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) 445*0fca6ea1SDimitry Andric const noexcept { 446*0fca6ea1SDimitry Andric using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 447*0fca6ea1SDimitry Andric return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](auto&& __element) { 448*0fca6ea1SDimitry Andric return std::move(__element); 449*0fca6ea1SDimitry Andric }); 450*0fca6ea1SDimitry Andric } 451*0fca6ea1SDimitry Andric }; 452*0fca6ea1SDimitry Andric 453*0fca6ea1SDimitry Andric // TODO: Use the std::copy/move shenanigans to forward to std::memmove 454*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 455*0fca6ea1SDimitry Andric struct __copy<__default_backend_tag, _ExecutionPolicy> { 456*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 457*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 458*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) 459*0fca6ea1SDimitry Andric const noexcept { 460*0fca6ea1SDimitry Andric using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 461*0fca6ea1SDimitry Andric return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), __identity()); 462*0fca6ea1SDimitry Andric } 463*0fca6ea1SDimitry Andric }; 464*0fca6ea1SDimitry Andric 465*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 466*0fca6ea1SDimitry Andric struct __copy_n<__default_backend_tag, _ExecutionPolicy> { 467*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _Size, class _ForwardOutIterator> 468*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 469*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __out_it) const noexcept { 470*0fca6ea1SDimitry Andric if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 471*0fca6ea1SDimitry Andric using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; 472*0fca6ea1SDimitry Andric _ForwardIterator __last = __first + __n; 473*0fca6ea1SDimitry Andric return _Copy()(__policy, std::move(__first), std::move(__last), std::move(__out_it)); 474*0fca6ea1SDimitry Andric } else { 475*0fca6ea1SDimitry Andric // Otherwise, use the serial algorithm to avoid doing two passes over the input 476*0fca6ea1SDimitry Andric return std::copy_n(std::move(__first), __n, std::move(__out_it)); 477*0fca6ea1SDimitry Andric } 478*0fca6ea1SDimitry Andric } 479*0fca6ea1SDimitry Andric }; 480*0fca6ea1SDimitry Andric 481*0fca6ea1SDimitry Andric template <class _ExecutionPolicy> 482*0fca6ea1SDimitry Andric struct __rotate_copy<__default_backend_tag, _ExecutionPolicy> { 483*0fca6ea1SDimitry Andric template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 484*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 485*0fca6ea1SDimitry Andric operator()(_Policy&& __policy, 486*0fca6ea1SDimitry Andric _ForwardIterator __first, 487*0fca6ea1SDimitry Andric _ForwardIterator __middle, 488*0fca6ea1SDimitry Andric _ForwardIterator __last, 489*0fca6ea1SDimitry Andric _ForwardOutIterator __out_it) const noexcept { 490*0fca6ea1SDimitry Andric using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; 491*0fca6ea1SDimitry Andric auto __result_mid = _Copy()(__policy, __middle, std::move(__last), std::move(__out_it)); 492*0fca6ea1SDimitry Andric if (__result_mid == nullopt) 493*0fca6ea1SDimitry Andric return nullopt; 494*0fca6ea1SDimitry Andric return _Copy()(__policy, std::move(__first), std::move(__middle), *std::move(__result_mid)); 495*0fca6ea1SDimitry Andric } 496*0fca6ea1SDimitry Andric }; 497*0fca6ea1SDimitry Andric 498*0fca6ea1SDimitry Andric } // namespace __pstl 499*0fca6ea1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 500*0fca6ea1SDimitry Andric 501*0fca6ea1SDimitry Andric _LIBCPP_POP_MACROS 502*0fca6ea1SDimitry Andric 503*0fca6ea1SDimitry Andric #endif // _LIBCPP___PSTL_BACKENDS_DEFAULT_H 504