173ebcabfSKonstantin Varlamov //===----------------------------------------------------------------------===// 273ebcabfSKonstantin Varlamov // 373ebcabfSKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 473ebcabfSKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information. 573ebcabfSKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 673ebcabfSKonstantin Varlamov // 773ebcabfSKonstantin Varlamov //===----------------------------------------------------------------------===// 873ebcabfSKonstantin Varlamov 973ebcabfSKonstantin Varlamov #ifndef _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H 1073ebcabfSKonstantin Varlamov #define _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H 1173ebcabfSKonstantin Varlamov 12065202f3SKonstantin Varlamov #include <__algorithm/half_positive.h> 1373ebcabfSKonstantin Varlamov #include <__config> 1473ebcabfSKonstantin Varlamov #include <__functional/identity.h> 1573ebcabfSKonstantin Varlamov #include <__functional/invoke.h> 1673ebcabfSKonstantin Varlamov #include <__iterator/concepts.h> 17065202f3SKonstantin Varlamov #include <__iterator/distance.h> 1873ebcabfSKonstantin Varlamov #include <__iterator/iterator_traits.h> 19065202f3SKonstantin Varlamov #include <__iterator/next.h> 2073ebcabfSKonstantin Varlamov #include <__iterator/projected.h> 2173ebcabfSKonstantin Varlamov #include <__ranges/access.h> 2273ebcabfSKonstantin Varlamov #include <__ranges/concepts.h> 2373ebcabfSKonstantin Varlamov #include <__ranges/dangling.h> 2473ebcabfSKonstantin Varlamov #include <__utility/move.h> 2573ebcabfSKonstantin Varlamov 2673ebcabfSKonstantin Varlamov #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2773ebcabfSKonstantin Varlamov # pragma GCC system_header 2873ebcabfSKonstantin Varlamov #endif 2973ebcabfSKonstantin Varlamov 307b462251SLouis Dionne _LIBCPP_PUSH_MACROS 317b462251SLouis Dionne #include <__undef_macros> 327b462251SLouis Dionne 334f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 3473ebcabfSKonstantin Varlamov 3573ebcabfSKonstantin Varlamov _LIBCPP_BEGIN_NAMESPACE_STD 3673ebcabfSKonstantin Varlamov 3773ebcabfSKonstantin Varlamov namespace ranges { 38*d10dc5a0SChristopher Di Bella struct __partition_point { 39065202f3SKonstantin Varlamov // TODO(ranges): delegate to the classic algorithm. 40065202f3SKonstantin Varlamov template <class _Iter, class _Sent, class _Proj, class _Pred> 415aa03b64SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr static _Iter 425aa03b64SLouis Dionne __partition_point_fn_impl(_Iter&& __first, _Sent&& __last, _Pred& __pred, _Proj& __proj) { 43065202f3SKonstantin Varlamov auto __len = ranges::distance(__first, __last); 44065202f3SKonstantin Varlamov 45065202f3SKonstantin Varlamov while (__len != 0) { 46065202f3SKonstantin Varlamov auto __half_len = std::__half_positive(__len); 47065202f3SKonstantin Varlamov auto __mid = ranges::next(__first, __half_len); 48065202f3SKonstantin Varlamov 49065202f3SKonstantin Varlamov if (std::invoke(__pred, std::invoke(__proj, *__mid))) { 50065202f3SKonstantin Varlamov __first = ++__mid; 51065202f3SKonstantin Varlamov __len -= __half_len + 1; 52065202f3SKonstantin Varlamov 53065202f3SKonstantin Varlamov } else { 54065202f3SKonstantin Varlamov __len = __half_len; 55065202f3SKonstantin Varlamov } 56065202f3SKonstantin Varlamov } 57065202f3SKonstantin Varlamov 58065202f3SKonstantin Varlamov return __first; 59065202f3SKonstantin Varlamov } 60065202f3SKonstantin Varlamov 615aa03b64SLouis Dionne template <forward_iterator _Iter, 625aa03b64SLouis Dionne sentinel_for<_Iter> _Sent, 635aa03b64SLouis Dionne class _Proj = identity, 6473ebcabfSKonstantin Varlamov indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> 655aa03b64SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { 66065202f3SKonstantin Varlamov return __partition_point_fn_impl(std::move(__first), std::move(__last), __pred, __proj); 6773ebcabfSKonstantin Varlamov } 6873ebcabfSKonstantin Varlamov 695aa03b64SLouis Dionne template <forward_range _Range, 705aa03b64SLouis Dionne class _Proj = identity, 7173ebcabfSKonstantin Varlamov indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> 725aa03b64SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> 735aa03b64SLouis Dionne operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { 74065202f3SKonstantin Varlamov return __partition_point_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); 7573ebcabfSKonstantin Varlamov } 7673ebcabfSKonstantin Varlamov }; 7773ebcabfSKonstantin Varlamov 7873ebcabfSKonstantin Varlamov inline namespace __cpo { 79*d10dc5a0SChristopher Di Bella inline constexpr auto partition_point = __partition_point{}; 8073ebcabfSKonstantin Varlamov } // namespace __cpo 8173ebcabfSKonstantin Varlamov } // namespace ranges 8273ebcabfSKonstantin Varlamov 8373ebcabfSKonstantin Varlamov _LIBCPP_END_NAMESPACE_STD 8473ebcabfSKonstantin Varlamov 854f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20 8673ebcabfSKonstantin Varlamov 877b462251SLouis Dionne _LIBCPP_POP_MACROS 887b462251SLouis Dionne 8973ebcabfSKonstantin Varlamov #endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H 90