| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_IS_PARTITIONED_H | ||
| #define _LIBCPP___ALGORITHM_IS_PARTITIONED_H | ||
|
|
||
| #include <__config> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _InputIterator, class _Predicate> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
| is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | ||
| for (; __first != __last; ++__first) | ||
| if (!__pred(*__first)) | ||
| break; | ||
| if (__first == __last) | ||
| return true; | ||
| ++__first; | ||
| for (; __first != __last; ++__first) | ||
| if (__pred(*__first)) | ||
| return false; | ||
| return true; | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_IS_PARTITIONED_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,308 @@ | ||
| // -*- C++ -*- | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_IS_PERMUTATION_H | ||
| #define _LIBCPP___ALGORITHM_IS_PERMUTATION_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__config> | ||
| #include <__functional/identity.h> | ||
| #include <__functional/invoke.h> | ||
| #include <__iterator/concepts.h> | ||
| #include <__iterator/distance.h> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__iterator/next.h> | ||
| #include <__type_traits/is_callable.h> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class = void> | ||
| struct _ConstTimeDistance : false_type {}; | ||
|
|
||
| #if _LIBCPP_STD_VER >= 20 | ||
|
|
||
| template <class _Iter1, class _Sent1, class _Iter2, class _Sent2> | ||
| struct _ConstTimeDistance<_Iter1, | ||
| _Sent1, | ||
| _Iter2, | ||
| _Sent2, | ||
| __enable_if_t< sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2> >> | ||
| : true_type {}; | ||
|
|
||
| #else | ||
|
|
||
| template <class _Iter1, class _Iter2> | ||
| struct _ConstTimeDistance< | ||
| _Iter1, | ||
| _Iter1, | ||
| _Iter2, | ||
| _Iter2, | ||
| __enable_if_t< is_same<typename iterator_traits<_Iter1>::iterator_category, random_access_iterator_tag>::value && | ||
| is_same<typename iterator_traits<_Iter2>::iterator_category, random_access_iterator_tag>::value > > | ||
| : true_type {}; | ||
|
|
||
| #endif // _LIBCPP_STD_VER >= 20 | ||
|
|
||
| // Internal functions | ||
|
|
||
| // For each element in [f1, l1) see if there are the same number of equal elements in [f2, l2) | ||
| template <class _AlgPolicy, | ||
| class _Iter1, | ||
| class _Sent1, | ||
| class _Iter2, | ||
| class _Sent2, | ||
| class _Proj1, | ||
| class _Proj2, | ||
| class _Pred> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation_impl( | ||
| _Iter1 __first1, | ||
| _Sent1 __last1, | ||
| _Iter2 __first2, | ||
| _Sent2 __last2, | ||
| _Pred&& __pred, | ||
| _Proj1&& __proj1, | ||
| _Proj2&& __proj2) { | ||
| using _D1 = __iter_diff_t<_Iter1>; | ||
|
|
||
| for (auto __i = __first1; __i != __last1; ++__i) { | ||
| // Have we already counted the number of *__i in [f1, l1)? | ||
| auto __match = __first1; | ||
| for (; __match != __i; ++__match) { | ||
| if (std::__invoke(__pred, std::__invoke(__proj1, *__match), std::__invoke(__proj1, *__i))) | ||
| break; | ||
| } | ||
|
|
||
| if (__match == __i) { | ||
| // Count number of *__i in [f2, l2) | ||
| _D1 __c2 = 0; | ||
| for (auto __j = __first2; __j != __last2; ++__j) { | ||
| if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj2, *__j))) | ||
| ++__c2; | ||
| } | ||
| if (__c2 == 0) | ||
| return false; | ||
|
|
||
| // Count number of *__i in [__i, l1) (we can start with 1) | ||
| _D1 __c1 = 1; | ||
| for (auto __j = _IterOps<_AlgPolicy>::next(__i); __j != __last1; ++__j) { | ||
| if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj1, *__j))) | ||
| ++__c1; | ||
| } | ||
| if (__c1 != __c2) | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| // 2+1 iterators, predicate. Not used by range algorithms. | ||
| template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _BinaryPredicate> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( | ||
| _ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _BinaryPredicate&& __pred) { | ||
| // Shorten sequences as much as possible by lopping of any equal prefix. | ||
| for (; __first1 != __last1; ++__first1, (void)++__first2) { | ||
| if (!__pred(*__first1, *__first2)) | ||
| break; | ||
| } | ||
|
|
||
| if (__first1 == __last1) | ||
| return true; | ||
|
|
||
| // __first1 != __last1 && *__first1 != *__first2 | ||
| using _D1 = __iter_diff_t<_ForwardIterator1>; | ||
| _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); | ||
| if (__l1 == _D1(1)) | ||
| return false; | ||
| auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1); | ||
|
|
||
| return std::__is_permutation_impl<_AlgPolicy>( | ||
| std::move(__first1), | ||
| std::move(__last1), | ||
| std::move(__first2), | ||
| std::move(__last2), | ||
| __pred, | ||
| __identity(), | ||
| __identity()); | ||
| } | ||
|
|
||
| // 2+2 iterators, predicate, non-constant time `distance`. | ||
| template <class _AlgPolicy, | ||
| class _Iter1, | ||
| class _Sent1, | ||
| class _Iter2, | ||
| class _Sent2, | ||
| class _Proj1, | ||
| class _Proj2, | ||
| class _Pred> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( | ||
| _Iter1 __first1, | ||
| _Sent1 __last1, | ||
| _Iter2 __first2, | ||
| _Sent2 __last2, | ||
| _Pred&& __pred, | ||
| _Proj1&& __proj1, | ||
| _Proj2&& __proj2, | ||
| /*_ConstTimeDistance=*/false_type) { | ||
| // Shorten sequences as much as possible by lopping of any equal prefix. | ||
| while (__first1 != __last1 && __first2 != __last2) { | ||
| if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) | ||
| break; | ||
| ++__first1; | ||
| ++__first2; | ||
| } | ||
|
|
||
| if (__first1 == __last1) | ||
| return __first2 == __last2; | ||
| if (__first2 == __last2) // Second range is shorter | ||
| return false; | ||
|
|
||
| using _D1 = __iter_diff_t<_Iter1>; | ||
| _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); | ||
|
|
||
| using _D2 = __iter_diff_t<_Iter2>; | ||
| _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2); | ||
| if (__l1 != __l2) | ||
| return false; | ||
|
|
||
| return std::__is_permutation_impl<_AlgPolicy>( | ||
| std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); | ||
| } | ||
|
|
||
| // 2+2 iterators, predicate, specialization for constant-time `distance` call. | ||
| template <class _AlgPolicy, | ||
| class _Iter1, | ||
| class _Sent1, | ||
| class _Iter2, | ||
| class _Sent2, | ||
| class _Proj1, | ||
| class _Proj2, | ||
| class _Pred> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( | ||
| _Iter1 __first1, | ||
| _Sent1 __last1, | ||
| _Iter2 __first2, | ||
| _Sent2 __last2, | ||
| _Pred&& __pred, | ||
| _Proj1&& __proj1, | ||
| _Proj2&& __proj2, | ||
| /*_ConstTimeDistance=*/true_type) { | ||
| if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) | ||
| return false; | ||
| return std::__is_permutation<_AlgPolicy>( | ||
| std::move(__first1), | ||
| std::move(__last1), | ||
| std::move(__first2), | ||
| std::move(__last2), | ||
| __pred, | ||
| __proj1, | ||
| __proj2, | ||
| /*_ConstTimeDistance=*/false_type()); | ||
| } | ||
|
|
||
| // 2+2 iterators, predicate | ||
| template <class _AlgPolicy, | ||
| class _Iter1, | ||
| class _Sent1, | ||
| class _Iter2, | ||
| class _Sent2, | ||
| class _Proj1, | ||
| class _Proj2, | ||
| class _Pred> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( | ||
| _Iter1 __first1, | ||
| _Sent1 __last1, | ||
| _Iter2 __first2, | ||
| _Sent2 __last2, | ||
| _Pred&& __pred, | ||
| _Proj1&& __proj1, | ||
| _Proj2&& __proj2) { | ||
| return std::__is_permutation<_AlgPolicy>( | ||
| std::move(__first1), | ||
| std::move(__last1), | ||
| std::move(__first2), | ||
| std::move(__last2), | ||
| __pred, | ||
| __proj1, | ||
| __proj2, | ||
| _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>()); | ||
| } | ||
|
|
||
| // Public interface | ||
|
|
||
| // 2+1 iterators, predicate | ||
| template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( | ||
| _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __pred) { | ||
| static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, | ||
| "The predicate has to be callable"); | ||
|
|
||
| return std::__is_permutation<_ClassicAlgPolicy>(std::move(__first1), std::move(__last1), std::move(__first2), __pred); | ||
| } | ||
|
|
||
| // 2+1 iterators | ||
| template <class _ForwardIterator1, class _ForwardIterator2> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
| is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { | ||
| return std::is_permutation(__first1, __last1, __first2, __equal_to()); | ||
| } | ||
|
|
||
| #if _LIBCPP_STD_VER >= 14 | ||
|
|
||
| // 2+2 iterators | ||
| template <class _ForwardIterator1, class _ForwardIterator2> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( | ||
| _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { | ||
| return std::__is_permutation<_ClassicAlgPolicy>( | ||
| std::move(__first1), | ||
| std::move(__last1), | ||
| std::move(__first2), | ||
| std::move(__last2), | ||
| __equal_to(), | ||
| __identity(), | ||
| __identity()); | ||
| } | ||
|
|
||
| // 2+2 iterators, predicate | ||
| template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( | ||
| _ForwardIterator1 __first1, | ||
| _ForwardIterator1 __last1, | ||
| _ForwardIterator2 __first2, | ||
| _ForwardIterator2 __last2, | ||
| _BinaryPredicate __pred) { | ||
| static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, | ||
| "The predicate has to be callable"); | ||
|
|
||
| return std::__is_permutation<_ClassicAlgPolicy>( | ||
| std::move(__first1), | ||
| std::move(__last1), | ||
| std::move(__first2), | ||
| std::move(__last2), | ||
| __pred, | ||
| __identity(), | ||
| __identity()); | ||
| } | ||
|
|
||
| #endif // _LIBCPP_STD_VER >= 14 | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_IS_PERMUTATION_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_IS_SORTED_H | ||
| #define _LIBCPP___ALGORITHM_IS_SORTED_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/is_sorted_until.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _ForwardIterator, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
| is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { | ||
| return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last; | ||
| } | ||
|
|
||
| template <class _ForwardIterator> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
| is_sorted(_ForwardIterator __first, _ForwardIterator __last) { | ||
| return std::is_sorted(__first, __last, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_IS_SORTED_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H | ||
| #define _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Compare, class _ForwardIterator> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator | ||
| __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { | ||
| if (__first != __last) { | ||
| _ForwardIterator __i = __first; | ||
| while (++__i != __last) { | ||
| if (__comp(*__i, *__first)) | ||
| return __i; | ||
| __first = __i; | ||
| } | ||
| } | ||
| return __last; | ||
| } | ||
|
|
||
| template <class _ForwardIterator, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator | ||
| is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { | ||
| return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp); | ||
| } | ||
|
|
||
| template <class _ForwardIterator> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator | ||
| is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) { | ||
| return std::is_sorted_until(__first, __last, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_ITER_SWAP_H | ||
| #define _LIBCPP___ALGORITHM_ITER_SWAP_H | ||
|
|
||
| #include <__config> | ||
| #include <__utility/declval.h> | ||
| #include <__utility/swap.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _ForwardIterator1, class _ForwardIterator2> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) | ||
| // _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b))) | ||
| _NOEXCEPT_(_NOEXCEPT_(swap(*std::declval<_ForwardIterator1>(), *std::declval<_ForwardIterator2>()))) { | ||
| swap(*__a, *__b); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_ITER_SWAP_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,223 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H | ||
| #define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H | ||
|
|
||
| #include <__algorithm/iter_swap.h> | ||
| #include <__algorithm/ranges_iterator_concept.h> | ||
| #include <__assert> | ||
| #include <__config> | ||
| #include <__iterator/advance.h> | ||
| #include <__iterator/distance.h> | ||
| #include <__iterator/incrementable_traits.h> | ||
| #include <__iterator/iter_move.h> | ||
| #include <__iterator/iter_swap.h> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__iterator/next.h> | ||
| #include <__iterator/prev.h> | ||
| #include <__iterator/readable_traits.h> | ||
| #include <__type_traits/enable_if.h> | ||
| #include <__type_traits/is_reference.h> | ||
| #include <__type_traits/is_same.h> | ||
| #include <__type_traits/remove_cvref.h> | ||
| #include <__utility/declval.h> | ||
| #include <__utility/forward.h> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _AlgPolicy> | ||
| struct _IterOps; | ||
|
|
||
| #if _LIBCPP_STD_VER >= 20 | ||
| struct _RangeAlgPolicy {}; | ||
|
|
||
| template <> | ||
| struct _IterOps<_RangeAlgPolicy> { | ||
| template <class _Iter> | ||
| using __value_type = iter_value_t<_Iter>; | ||
|
|
||
| template <class _Iter> | ||
| using __iterator_category = ranges::__iterator_concept<_Iter>; | ||
|
|
||
| template <class _Iter> | ||
| using __difference_type = iter_difference_t<_Iter>; | ||
|
|
||
| static constexpr auto advance = ranges::advance; | ||
| static constexpr auto distance = ranges::distance; | ||
| static constexpr auto __iter_move = ranges::iter_move; | ||
| static constexpr auto iter_swap = ranges::iter_swap; | ||
| static constexpr auto next = ranges::next; | ||
| static constexpr auto prev = ranges::prev; | ||
| static constexpr auto __advance_to = ranges::advance; | ||
| }; | ||
|
|
||
| #endif | ||
|
|
||
| struct _ClassicAlgPolicy {}; | ||
|
|
||
| template <> | ||
| struct _IterOps<_ClassicAlgPolicy> { | ||
| template <class _Iter> | ||
| using __value_type = typename iterator_traits<_Iter>::value_type; | ||
|
|
||
| template <class _Iter> | ||
| using __iterator_category = typename iterator_traits<_Iter>::iterator_category; | ||
|
|
||
| template <class _Iter> | ||
| using __difference_type = typename iterator_traits<_Iter>::difference_type; | ||
|
|
||
| // advance | ||
| template <class _Iter, class _Distance> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void advance(_Iter& __iter, _Distance __count) { | ||
| std::advance(__iter, __count); | ||
| } | ||
|
|
||
| // distance | ||
| template <class _Iter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static typename iterator_traits<_Iter>::difference_type | ||
| distance(_Iter __first, _Iter __last) { | ||
| return std::distance(__first, __last); | ||
| } | ||
|
|
||
| template <class _Iter> | ||
| using __deref_t = decltype(*std::declval<_Iter&>()); | ||
|
|
||
| template <class _Iter> | ||
| using __move_t = decltype(std::move(*std::declval<_Iter&>())); | ||
|
|
||
| template <class _Iter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void __validate_iter_reference() { | ||
| static_assert( | ||
| is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value, | ||
| "It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of " | ||
| "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] " | ||
| "and can lead to dangling reference issues at runtime, so we are flagging this."); | ||
| } | ||
|
|
||
| // iter_move | ||
| template <class _Iter, __enable_if_t<is_reference<__deref_t<_Iter> >::value, int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static | ||
| // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. | ||
| // Note that the C++03 mode doesn't support `decltype(auto)` as the return type. | ||
| __move_t<_Iter> | ||
| __iter_move(_Iter&& __i) { | ||
| __validate_iter_reference<_Iter>(); | ||
|
|
||
| return std::move(*std::forward<_Iter>(__i)); | ||
| } | ||
|
|
||
| template <class _Iter, __enable_if_t<!is_reference<__deref_t<_Iter> >::value, int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static | ||
| // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a | ||
| // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to | ||
| // that temporary. Note that the C++03 mode doesn't support `auto` as the return type. | ||
| __deref_t<_Iter> | ||
| __iter_move(_Iter&& __i) { | ||
| __validate_iter_reference<_Iter>(); | ||
|
|
||
| return *std::forward<_Iter>(__i); | ||
| } | ||
|
|
||
| // iter_swap | ||
| template <class _Iter1, class _Iter2> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void iter_swap(_Iter1&& __a, _Iter2&& __b) { | ||
| std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b)); | ||
| } | ||
|
|
||
| // next | ||
| template <class _Iterator> | ||
| _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iterator next(_Iterator, _Iterator __last) { | ||
| return __last; | ||
| } | ||
|
|
||
| template <class _Iter> | ||
| _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 __remove_cvref_t<_Iter> | ||
| next(_Iter&& __it, typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) { | ||
| return std::next(std::forward<_Iter>(__it), __n); | ||
| } | ||
|
|
||
| // prev | ||
| template <class _Iter> | ||
| _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 __remove_cvref_t<_Iter> | ||
| prev(_Iter&& __iter, typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) { | ||
| return std::prev(std::forward<_Iter>(__iter), __n); | ||
| } | ||
|
|
||
| template <class _Iter> | ||
| _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 void __advance_to(_Iter& __first, _Iter __last) { | ||
| __first = __last; | ||
| } | ||
|
|
||
| // advance with sentinel, a la std::ranges::advance | ||
| template <class _Iter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_Iter> | ||
| __advance_to(_Iter& __iter, __difference_type<_Iter> __count, const _Iter& __sentinel) { | ||
| return _IterOps::__advance_to(__iter, __count, __sentinel, typename iterator_traits<_Iter>::iterator_category()); | ||
| } | ||
|
|
||
| private: | ||
| // advance with sentinel, a la std::ranges::advance -- InputIterator specialization | ||
| template <class _InputIter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_InputIter> __advance_to( | ||
| _InputIter& __iter, __difference_type<_InputIter> __count, const _InputIter& __sentinel, input_iterator_tag) { | ||
| __difference_type<_InputIter> __dist = 0; | ||
| for (; __dist < __count && __iter != __sentinel; ++__dist) | ||
| ++__iter; | ||
| return __count - __dist; | ||
| } | ||
|
|
||
| // advance with sentinel, a la std::ranges::advance -- BidirectionalIterator specialization | ||
| template <class _BiDirIter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_BiDirIter> | ||
| __advance_to(_BiDirIter& __iter, | ||
| __difference_type<_BiDirIter> __count, | ||
| const _BiDirIter& __sentinel, | ||
| bidirectional_iterator_tag) { | ||
| __difference_type<_BiDirIter> __dist = 0; | ||
| if (__count >= 0) | ||
| for (; __dist < __count && __iter != __sentinel; ++__dist) | ||
| ++__iter; | ||
| else | ||
| for (__count = -__count; __dist < __count && __iter != __sentinel; ++__dist) | ||
| --__iter; | ||
| return __count - __dist; | ||
| } | ||
|
|
||
| // advance with sentinel, a la std::ranges::advance -- RandomIterator specialization | ||
| template <class _RandIter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_RandIter> | ||
| __advance_to(_RandIter& __iter, | ||
| __difference_type<_RandIter> __count, | ||
| const _RandIter& __sentinel, | ||
| random_access_iterator_tag) { | ||
| auto __dist = _IterOps::distance(__iter, __sentinel); | ||
| _LIBCPP_ASSERT_VALID_INPUT_RANGE( | ||
| __count == 0 || (__dist < 0) == (__count < 0), "__sentinel must precede __iter when __count < 0"); | ||
| if (__count < 0) | ||
| __dist = __dist > __count ? __dist : __count; | ||
| else | ||
| __dist = __dist < __count ? __dist : __count; | ||
| __iter += __dist; | ||
| return __count - __dist; | ||
| } | ||
| }; | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H | ||
| #define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Compare, class _InputIterator1, class _InputIterator2> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __lexicographical_compare( | ||
| _InputIterator1 __first1, | ||
| _InputIterator1 __last1, | ||
| _InputIterator2 __first2, | ||
| _InputIterator2 __last2, | ||
| _Compare __comp) { | ||
| for (; __first2 != __last2; ++__first1, (void)++__first2) { | ||
| if (__first1 == __last1 || __comp(*__first1, *__first2)) | ||
| return true; | ||
| if (__comp(*__first2, *__first1)) | ||
| return false; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( | ||
| _InputIterator1 __first1, | ||
| _InputIterator1 __last1, | ||
| _InputIterator2 __first2, | ||
| _InputIterator2 __last2, | ||
| _Compare __comp) { | ||
| return std::__lexicographical_compare<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __comp); | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( | ||
| _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { | ||
| return std::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H | ||
| #define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H | ||
|
|
||
| #include <__algorithm/min.h> | ||
| #include <__algorithm/three_way_comp_ref_type.h> | ||
| #include <__compare/compare_three_way.h> | ||
| #include <__compare/ordering.h> | ||
| #include <__concepts/arithmetic.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__type_traits/common_type.h> | ||
| #include <__type_traits/is_constructible.h> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| #if _LIBCPP_STD_VER >= 20 | ||
|
|
||
| // Fast path for random access iterators which computes the number of loop iterations up-front and | ||
| // then skips the iterator comparisons inside the loop. | ||
| template <class _InputIterator1, class _InputIterator2, class _Cmp> | ||
| _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_path( | ||
| _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp) | ||
| -> decltype(__comp(*__first1, *__first2)) { | ||
| static_assert( | ||
| signed_integral<__iter_diff_t<_InputIterator1>>, "Using a non-integral difference_type is undefined behavior."); | ||
| static_assert( | ||
| signed_integral<__iter_diff_t<_InputIterator2>>, "Using a non-integral difference_type is undefined behavior."); | ||
|
|
||
| using _Len1 = __iter_diff_t<_InputIterator1>; | ||
| using _Len2 = __iter_diff_t<_InputIterator2>; | ||
| using _Common = common_type_t<_Len1, _Len2>; | ||
|
|
||
| _Len1 __len1 = __last1 - __first1; | ||
| _Len2 __len2 = __last2 - __first2; | ||
| _Common __min_len = std::min<_Common>(__len1, __len2); | ||
|
|
||
| for (_Common __i = 0; __i < __min_len; ++__i) { | ||
| auto __c = __comp(*__first1, *__first2); | ||
| if (__c != 0) { | ||
| return __c; | ||
| } | ||
| ++__first1; | ||
| ++__first2; | ||
| } | ||
|
|
||
| return __len1 <=> __len2; | ||
| } | ||
|
|
||
| // Unoptimized implementation which compares the iterators against the end in every loop iteration | ||
| template <class _InputIterator1, class _InputIterator2, class _Cmp> | ||
| _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_slow_path( | ||
| _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp) | ||
| -> decltype(__comp(*__first1, *__first2)) { | ||
| while (true) { | ||
| bool __exhausted1 = __first1 == __last1; | ||
| bool __exhausted2 = __first2 == __last2; | ||
|
|
||
| if (__exhausted1 || __exhausted2) { | ||
| if (!__exhausted1) | ||
| return strong_ordering::greater; | ||
| if (!__exhausted2) | ||
| return strong_ordering::less; | ||
| return strong_ordering::equal; | ||
| } | ||
|
|
||
| auto __c = __comp(*__first1, *__first2); | ||
| if (__c != 0) { | ||
| return __c; | ||
| } | ||
|
|
||
| ++__first1; | ||
| ++__first2; | ||
| } | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2, class _Cmp> | ||
| [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( | ||
| _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp __comp) | ||
| -> decltype(__comp(*__first1, *__first2)) { | ||
| static_assert(__comparison_category<decltype(__comp(*__first1, *__first2))>, | ||
| "The comparator passed to lexicographical_compare_three_way must return a comparison category type."); | ||
| static_assert(std::is_copy_constructible_v<_InputIterator1>, "Iterators must be copy constructible."); | ||
| static_assert(std::is_copy_constructible_v<_InputIterator2>, "Iterators must be copy constructible."); | ||
| __three_way_comp_ref_type<_Cmp> __wrapped_comp_ref(__comp); | ||
| if constexpr (__has_random_access_iterator_category<_InputIterator1>::value && | ||
| __has_random_access_iterator_category<_InputIterator2>::value) { | ||
| return std::__lexicographical_compare_three_way_fast_path( | ||
| std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); | ||
| } else { | ||
| // Unoptimized implementation which compares the iterators against the end in every loop iteration | ||
| return std::__lexicographical_compare_three_way_slow_path( | ||
| std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); | ||
| } | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2> | ||
| [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( | ||
| _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { | ||
| return std::lexicographical_compare_three_way( | ||
| std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::compare_three_way()); | ||
| } | ||
|
|
||
| #endif // _LIBCPP_STD_VER >= 20 | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_LOWER_BOUND_H | ||
| #define _LIBCPP___ALGORITHM_LOWER_BOUND_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/half_positive.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__config> | ||
| #include <__functional/identity.h> | ||
| #include <__functional/invoke.h> | ||
| #include <__iterator/advance.h> | ||
| #include <__iterator/distance.h> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__type_traits/is_callable.h> | ||
| #include <__type_traits/remove_reference.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _AlgPolicy, class _Iter, class _Type, class _Proj, class _Comp> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter __lower_bound_bisecting( | ||
| _Iter __first, | ||
| const _Type& __value, | ||
| typename iterator_traits<_Iter>::difference_type __len, | ||
| _Comp& __comp, | ||
| _Proj& __proj) { | ||
| while (__len != 0) { | ||
| auto __l2 = std::__half_positive(__len); | ||
| _Iter __m = __first; | ||
| _IterOps<_AlgPolicy>::advance(__m, __l2); | ||
| if (std::__invoke(__comp, std::__invoke(__proj, *__m), __value)) { | ||
| __first = ++__m; | ||
| __len -= __l2 + 1; | ||
| } else { | ||
| __len = __l2; | ||
| } | ||
| } | ||
| return __first; | ||
| } | ||
|
|
||
| // One-sided binary search, aka meta binary search, has been in the public domain for decades, and has the general | ||
| // advantage of being \Omega(1) rather than the classic algorithm's \Omega(log(n)), with the downside of executing at | ||
| // most 2*log(n) comparisons vs the classic algorithm's exact log(n). There are two scenarios in which it really shines: | ||
| // the first one is when operating over non-random-access iterators, because the classic algorithm requires knowing the | ||
| // container's size upfront, which adds \Omega(n) iterator increments to the complexity. The second one is when you're | ||
| // traversing the container in order, trying to fast-forward to the next value: in that case, the classic algorithm | ||
| // would yield \Omega(n*log(n)) comparisons and, for non-random-access iterators, \Omega(n^2) iterator increments, | ||
| // whereas the one-sided version will yield O(n) operations on both counts, with a \Omega(log(n)) bound on the number of | ||
| // comparisons. | ||
| template <class _AlgPolicy, class _ForwardIterator, class _Sent, class _Type, class _Proj, class _Comp> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator | ||
| __lower_bound_onesided(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { | ||
| // step = 0, ensuring we can always short-circuit when distance is 1 later on | ||
| if (__first == __last || !std::__invoke(__comp, std::__invoke(__proj, *__first), __value)) | ||
| return __first; | ||
|
|
||
| using _Distance = typename iterator_traits<_ForwardIterator>::difference_type; | ||
| for (_Distance __step = 1; __first != __last; __step <<= 1) { | ||
| auto __it = __first; | ||
| auto __dist = __step - _IterOps<_AlgPolicy>::__advance_to(__it, __step, __last); | ||
| // once we reach the last range where needle can be we must start | ||
| // looking inwards, bisecting that range | ||
| if (__it == __last || !std::__invoke(__comp, std::__invoke(__proj, *__it), __value)) { | ||
| // we've already checked the previous value and it was less, we can save | ||
| // one comparison by skipping bisection | ||
| if (__dist == 1) | ||
| return __it; | ||
| return std::__lower_bound_bisecting<_AlgPolicy>(__first, __value, __dist, __comp, __proj); | ||
| } | ||
| // range not found, move forward! | ||
| __first = __it; | ||
| } | ||
| return __first; | ||
| } | ||
|
|
||
| template <class _AlgPolicy, class _ForwardIterator, class _Sent, class _Type, class _Proj, class _Comp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator | ||
| __lower_bound(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { | ||
| const auto __dist = _IterOps<_AlgPolicy>::distance(__first, __last); | ||
| return std::__lower_bound_bisecting<_AlgPolicy>(__first, __value, __dist, __comp, __proj); | ||
| } | ||
|
|
||
| template <class _ForwardIterator, class _Tp, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator | ||
| lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { | ||
| static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); | ||
| auto __proj = std::__identity(); | ||
| return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj); | ||
| } | ||
|
|
||
| template <class _ForwardIterator, class _Tp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator | ||
| lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { | ||
| return std::lower_bound(__first, __last, __value, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_LOWER_BOUND_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MAKE_HEAP_H | ||
| #define _LIBCPP___ALGORITHM_MAKE_HEAP_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__algorithm/sift_down.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void | ||
| __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { | ||
| __comp_ref_type<_Compare> __comp_ref = __comp; | ||
|
|
||
| using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; | ||
| difference_type __n = __last - __first; | ||
| if (__n > 1) { | ||
| // start from the first parent, there is no need to consider children | ||
| for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) { | ||
| std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| template <class _RandomAccessIterator, class _Compare> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
| make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { | ||
| std::__make_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); | ||
| } | ||
|
|
||
| template <class _RandomAccessIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
| make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { | ||
| std::make_heap(std::move(__first), std::move(__last), __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MAKE_HEAP_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MAKE_PROJECTED_H | ||
| #define _LIBCPP___ALGORITHM_MAKE_PROJECTED_H | ||
|
|
||
| #include <__concepts/same_as.h> | ||
| #include <__config> | ||
| #include <__functional/identity.h> | ||
| #include <__functional/invoke.h> | ||
| #include <__type_traits/decay.h> | ||
| #include <__type_traits/enable_if.h> | ||
| #include <__type_traits/integral_constant.h> | ||
| #include <__type_traits/is_member_pointer.h> | ||
| #include <__type_traits/is_same.h> | ||
| #include <__utility/declval.h> | ||
| #include <__utility/forward.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Pred, class _Proj> | ||
| struct _ProjectedPred { | ||
| _Pred& __pred; // Can be a unary or a binary predicate. | ||
| _Proj& __proj; | ||
|
|
||
| _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) | ||
| : __pred(__pred_arg), __proj(__proj_arg) {} | ||
|
|
||
| template <class _Tp> | ||
| typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>()))>::type | ||
| _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI | ||
| operator()(_Tp&& __v) const { | ||
| return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); | ||
| } | ||
|
|
||
| template <class _T1, class _T2> | ||
| typename __invoke_of<_Pred&, | ||
| decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), | ||
| decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>()))>::type _LIBCPP_CONSTEXPR | ||
| _LIBCPP_HIDE_FROM_ABI | ||
| operator()(_T1&& __lhs, _T2&& __rhs) const { | ||
| return std::__invoke( | ||
| __pred, std::__invoke(__proj, std::forward<_T1>(__lhs)), std::__invoke(__proj, std::forward<_T2>(__rhs))); | ||
| } | ||
| }; | ||
|
|
||
| template < | ||
| class _Pred, | ||
| class _Proj, | ||
| __enable_if_t<!(!is_member_pointer<__decay_t<_Pred> >::value && __is_identity<__decay_t<_Proj> >::value), int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj> __make_projected(_Pred& __pred, _Proj& __proj) { | ||
| return _ProjectedPred<_Pred, _Proj>(__pred, __proj); | ||
| } | ||
|
|
||
| // Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable | ||
| // optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in | ||
| // the call stack when the comparator is invoked, even in an unoptimized build. | ||
| template < | ||
| class _Pred, | ||
| class _Proj, | ||
| __enable_if_t<!is_member_pointer<__decay_t<_Pred> >::value && __is_identity<__decay_t<_Proj> >::value, int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Pred& __make_projected(_Pred& __pred, _Proj&) { | ||
| return __pred; | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #if _LIBCPP_STD_VER >= 20 | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| namespace ranges { | ||
|
|
||
| template <class _Comp, class _Proj1, class _Proj2> | ||
| _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { | ||
| if constexpr (__is_identity<decay_t<_Proj1>>::value && __is_identity<decay_t<_Proj2>>::value && | ||
| !is_member_pointer_v<decay_t<_Comp>>) { | ||
| // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable | ||
| // optimizations that rely on the type of the comparator. | ||
| return __comp; | ||
|
|
||
| } else { | ||
| return [&](auto&& __lhs, auto&& __rhs) -> bool { | ||
| return std::invoke(__comp, | ||
| std::invoke(__proj1, std::forward<decltype(__lhs)>(__lhs)), | ||
| std::invoke(__proj2, std::forward<decltype(__rhs)>(__rhs))); | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| } // namespace ranges | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP_STD_VER >= 20 | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MAX_H | ||
| #define _LIBCPP___ALGORITHM_MAX_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/max_element.h> | ||
| #include <__config> | ||
| #include <initializer_list> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Tp, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& | ||
| max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { | ||
| return __comp(__a, __b) ? __b : __a; | ||
| } | ||
|
|
||
| template <class _Tp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& | ||
| max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { | ||
| return std::max(__a, __b, __less<>()); | ||
| } | ||
|
|
||
| #ifndef _LIBCPP_CXX03_LANG | ||
|
|
||
| template <class _Tp, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp | ||
| max(initializer_list<_Tp> __t, _Compare __comp) { | ||
| return *std::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); | ||
| } | ||
|
|
||
| template <class _Tp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { | ||
| return *std::max_element(__t.begin(), __t.end(), __less<>()); | ||
| } | ||
|
|
||
| #endif // _LIBCPP_CXX03_LANG | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MAX_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MAX_ELEMENT_H | ||
| #define _LIBCPP___ALGORITHM_MAX_ELEMENT_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Compare, class _ForwardIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator | ||
| __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { | ||
| static_assert( | ||
| __has_forward_iterator_category<_ForwardIterator>::value, "std::max_element requires a ForwardIterator"); | ||
| if (__first != __last) { | ||
| _ForwardIterator __i = __first; | ||
| while (++__i != __last) | ||
| if (__comp(*__first, *__i)) | ||
| __first = __i; | ||
| } | ||
| return __first; | ||
| } | ||
|
|
||
| template <class _ForwardIterator, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator | ||
| max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { | ||
| return std::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp); | ||
| } | ||
|
|
||
| template <class _ForwardIterator> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator | ||
| max_element(_ForwardIterator __first, _ForwardIterator __last) { | ||
| return std::max_element(__first, __last, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MAX_ELEMENT_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MERGE_H | ||
| #define _LIBCPP___ALGORITHM_MERGE_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/copy.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator __merge( | ||
| _InputIterator1 __first1, | ||
| _InputIterator1 __last1, | ||
| _InputIterator2 __first2, | ||
| _InputIterator2 __last2, | ||
| _OutputIterator __result, | ||
| _Compare __comp) { | ||
| for (; __first1 != __last1; ++__result) { | ||
| if (__first2 == __last2) | ||
| return std::copy(__first1, __last1, __result); | ||
| if (__comp(*__first2, *__first1)) { | ||
| *__result = *__first2; | ||
| ++__first2; | ||
| } else { | ||
| *__result = *__first1; | ||
| ++__first1; | ||
| } | ||
| } | ||
| return std::copy(__first2, __last2, __result); | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator | ||
| merge(_InputIterator1 __first1, | ||
| _InputIterator1 __last1, | ||
| _InputIterator2 __first2, | ||
| _InputIterator2 __last2, | ||
| _OutputIterator __result, | ||
| _Compare __comp) { | ||
| return std::__merge<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __result, __comp); | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator | ||
| merge(_InputIterator1 __first1, | ||
| _InputIterator1 __last1, | ||
| _InputIterator2 __first2, | ||
| _InputIterator2 __last2, | ||
| _OutputIterator __result) { | ||
| return std::merge(__first1, __last1, __first2, __last2, __result, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MERGE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MIN_H | ||
| #define _LIBCPP___ALGORITHM_MIN_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/min_element.h> | ||
| #include <__config> | ||
| #include <initializer_list> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Tp, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& | ||
| min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { | ||
| return __comp(__b, __a) ? __b : __a; | ||
| } | ||
|
|
||
| template <class _Tp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& | ||
| min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { | ||
| return std::min(__a, __b, __less<>()); | ||
| } | ||
|
|
||
| #ifndef _LIBCPP_CXX03_LANG | ||
|
|
||
| template <class _Tp, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp | ||
| min(initializer_list<_Tp> __t, _Compare __comp) { | ||
| return *std::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); | ||
| } | ||
|
|
||
| template <class _Tp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { | ||
| return *std::min_element(__t.begin(), __t.end(), __less<>()); | ||
| } | ||
|
|
||
| #endif // _LIBCPP_CXX03_LANG | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MIN_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MIN_ELEMENT_H | ||
| #define _LIBCPP___ALGORITHM_MIN_ELEMENT_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__config> | ||
| #include <__functional/identity.h> | ||
| #include <__functional/invoke.h> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__type_traits/is_callable.h> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Comp, class _Iter, class _Sent, class _Proj> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter | ||
| __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) { | ||
| if (__first == __last) | ||
| return __first; | ||
|
|
||
| _Iter __i = __first; | ||
| while (++__i != __last) | ||
| if (std::__invoke(__comp, std::__invoke(__proj, *__i), std::__invoke(__proj, *__first))) | ||
| __first = __i; | ||
|
|
||
| return __first; | ||
| } | ||
|
|
||
| template <class _Comp, class _Iter, class _Sent> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element(_Iter __first, _Sent __last, _Comp __comp) { | ||
| auto __proj = __identity(); | ||
| return std::__min_element<_Comp>(std::move(__first), std::move(__last), __comp, __proj); | ||
| } | ||
|
|
||
| template <class _ForwardIterator, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator | ||
| min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { | ||
| static_assert( | ||
| __has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator"); | ||
| static_assert( | ||
| __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable"); | ||
|
|
||
| return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp); | ||
| } | ||
|
|
||
| template <class _ForwardIterator> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator | ||
| min_element(_ForwardIterator __first, _ForwardIterator __last) { | ||
| return std::min_element(__first, __last, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MIN_ELEMENT_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // -*- C++ -*- | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MIN_MAX_RESULT_H | ||
| #define _LIBCPP___ALGORITHM_MIN_MAX_RESULT_H | ||
|
|
||
| #include <__concepts/convertible_to.h> | ||
| #include <__config> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| #if _LIBCPP_STD_VER >= 20 | ||
|
|
||
| namespace ranges { | ||
|
|
||
| template <class _T1> | ||
| struct min_max_result { | ||
| _LIBCPP_NO_UNIQUE_ADDRESS _T1 min; | ||
| _LIBCPP_NO_UNIQUE_ADDRESS _T1 max; | ||
|
|
||
| template <class _T2> | ||
| requires convertible_to<const _T1&, _T2> | ||
| _LIBCPP_HIDE_FROM_ABI constexpr operator min_max_result<_T2>() const& { | ||
| return {min, max}; | ||
| } | ||
|
|
||
| template <class _T2> | ||
| requires convertible_to<_T1, _T2> | ||
| _LIBCPP_HIDE_FROM_ABI constexpr operator min_max_result<_T2>() && { | ||
| return {std::move(min), std::move(max)}; | ||
| } | ||
| }; | ||
|
|
||
| } // namespace ranges | ||
|
|
||
| #endif // _LIBCPP_STD_VER >= 20 | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MIN_MAX_RESULT_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MINMAX_H | ||
| #define _LIBCPP___ALGORITHM_MINMAX_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/minmax_element.h> | ||
| #include <__config> | ||
| #include <__functional/identity.h> | ||
| #include <__type_traits/is_callable.h> | ||
| #include <__utility/pair.h> | ||
| #include <initializer_list> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Tp, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<const _Tp&, const _Tp&> | ||
| minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { | ||
| return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a) : pair<const _Tp&, const _Tp&>(__a, __b); | ||
| } | ||
|
|
||
| template <class _Tp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<const _Tp&, const _Tp&> | ||
| minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { | ||
| return std::minmax(__a, __b, __less<>()); | ||
| } | ||
|
|
||
| #ifndef _LIBCPP_CXX03_LANG | ||
|
|
||
| template <class _Tp, class _Compare> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> | ||
| minmax(initializer_list<_Tp> __t, _Compare __comp) { | ||
| static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable"); | ||
| __identity __proj; | ||
| auto __ret = std::__minmax_element_impl(__t.begin(), __t.end(), __comp, __proj); | ||
| return pair<_Tp, _Tp>(*__ret.first, *__ret.second); | ||
| } | ||
|
|
||
| template <class _Tp> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> | ||
| minmax(initializer_list<_Tp> __t) { | ||
| return std::minmax(__t, __less<>()); | ||
| } | ||
|
|
||
| #endif // _LIBCPP_CXX03_LANG | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MINMAX_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H | ||
| #define _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__config> | ||
| #include <__functional/identity.h> | ||
| #include <__functional/invoke.h> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__type_traits/is_callable.h> | ||
| #include <__utility/pair.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Comp, class _Proj> | ||
| class _MinmaxElementLessFunc { | ||
| _Comp& __comp_; | ||
| _Proj& __proj_; | ||
|
|
||
| public: | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _MinmaxElementLessFunc(_Comp& __comp, _Proj& __proj) | ||
| : __comp_(__comp), __proj_(__proj) {} | ||
|
|
||
| template <class _Iter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(_Iter& __it1, _Iter& __it2) { | ||
| return std::__invoke(__comp_, std::__invoke(__proj_, *__it1), std::__invoke(__proj_, *__it2)); | ||
| } | ||
| }; | ||
|
|
||
| template <class _Iter, class _Sent, class _Proj, class _Comp> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter> | ||
| __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { | ||
| auto __less = _MinmaxElementLessFunc<_Comp, _Proj>(__comp, __proj); | ||
|
|
||
| pair<_Iter, _Iter> __result(__first, __first); | ||
| if (__first == __last || ++__first == __last) | ||
| return __result; | ||
|
|
||
| if (__less(__first, __result.first)) | ||
| __result.first = __first; | ||
| else | ||
| __result.second = __first; | ||
|
|
||
| while (++__first != __last) { | ||
| _Iter __i = __first; | ||
| if (++__first == __last) { | ||
| if (__less(__i, __result.first)) | ||
| __result.first = __i; | ||
| else if (!__less(__i, __result.second)) | ||
| __result.second = __i; | ||
| return __result; | ||
| } | ||
|
|
||
| if (__less(__first, __i)) { | ||
| if (__less(__first, __result.first)) | ||
| __result.first = __first; | ||
| if (!__less(__i, __result.second)) | ||
| __result.second = __i; | ||
| } else { | ||
| if (__less(__i, __result.first)) | ||
| __result.first = __i; | ||
| if (!__less(__first, __result.second)) | ||
| __result.second = __first; | ||
| } | ||
| } | ||
|
|
||
| return __result; | ||
| } | ||
|
|
||
| template <class _ForwardIterator, class _Compare> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> | ||
| minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { | ||
| static_assert( | ||
| __has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator"); | ||
| static_assert( | ||
| __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable"); | ||
| auto __proj = __identity(); | ||
| return std::__minmax_element_impl(__first, __last, __comp, __proj); | ||
| } | ||
|
|
||
| template <class _ForwardIterator> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> | ||
| minmax_element(_ForwardIterator __first, _ForwardIterator __last) { | ||
| return std::minmax_element(__first, __last, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| // -*- C++ -*- | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MISMATCH_H | ||
| #define _LIBCPP___ALGORITHM_MISMATCH_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/min.h> | ||
| #include <__algorithm/simd_utils.h> | ||
| #include <__algorithm/unwrap_iter.h> | ||
| #include <__config> | ||
| #include <__functional/identity.h> | ||
| #include <__iterator/aliasing_iterator.h> | ||
| #include <__type_traits/desugars_to.h> | ||
| #include <__type_traits/invoke.h> | ||
| #include <__type_traits/is_constant_evaluated.h> | ||
| #include <__type_traits/is_equality_comparable.h> | ||
| #include <__type_traits/is_integral.h> | ||
| #include <__utility/move.h> | ||
| #include <__utility/pair.h> | ||
| #include <__utility/unreachable.h> | ||
| #include <cstddef> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Iter1, class _Sent1, class _Iter2, class _Pred, class _Proj1, class _Proj2> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> | ||
| __mismatch_loop(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { | ||
| while (__first1 != __last1) { | ||
| if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) | ||
| break; | ||
| ++__first1; | ||
| ++__first2; | ||
| } | ||
| return std::make_pair(std::move(__first1), std::move(__first2)); | ||
| } | ||
|
|
||
| template <class _Iter1, class _Sent1, class _Iter2, class _Pred, class _Proj1, class _Proj2> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> | ||
| __mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { | ||
| return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2); | ||
| } | ||
|
|
||
| #if _LIBCPP_VECTORIZE_ALGORITHMS | ||
|
|
||
| template <class _Iter> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter, _Iter> | ||
| __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) { | ||
| using __value_type = __iter_value_type<_Iter>; | ||
| constexpr size_t __unroll_count = 4; | ||
| constexpr size_t __vec_size = __native_vector_size<__value_type>; | ||
| using __vec = __simd_vector<__value_type, __vec_size>; | ||
|
|
||
| if (!__libcpp_is_constant_evaluated()) { | ||
| auto __orig_first1 = __first1; | ||
| auto __last2 = __first2 + (__last1 - __first1); | ||
| while (static_cast<size_t>(__last1 - __first1) >= __unroll_count * __vec_size) [[__unlikely__]] { | ||
| __vec __lhs[__unroll_count]; | ||
| __vec __rhs[__unroll_count]; | ||
|
|
||
| for (size_t __i = 0; __i != __unroll_count; ++__i) { | ||
| __lhs[__i] = std::__load_vector<__vec>(__first1 + __i * __vec_size); | ||
| __rhs[__i] = std::__load_vector<__vec>(__first2 + __i * __vec_size); | ||
| } | ||
|
|
||
| for (size_t __i = 0; __i != __unroll_count; ++__i) { | ||
| if (auto __cmp_res = __lhs[__i] == __rhs[__i]; !std::__all_of(__cmp_res)) { | ||
| auto __offset = __i * __vec_size + std::__find_first_not_set(__cmp_res); | ||
| return {__first1 + __offset, __first2 + __offset}; | ||
| } | ||
| } | ||
|
|
||
| __first1 += __unroll_count * __vec_size; | ||
| __first2 += __unroll_count * __vec_size; | ||
| } | ||
|
|
||
| // check the remaining 0-3 vectors | ||
| while (static_cast<size_t>(__last1 - __first1) >= __vec_size) { | ||
| if (auto __cmp_res = std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2); | ||
| !std::__all_of(__cmp_res)) { | ||
| auto __offset = std::__find_first_not_set(__cmp_res); | ||
| return {__first1 + __offset, __first2 + __offset}; | ||
| } | ||
| __first1 += __vec_size; | ||
| __first2 += __vec_size; | ||
| } | ||
|
|
||
| if (__last1 - __first1 == 0) | ||
| return {__first1, __first2}; | ||
|
|
||
| // Check if we can load elements in front of the current pointer. If that's the case load a vector at | ||
| // (last - vector_size) to check the remaining elements | ||
| if (static_cast<size_t>(__first1 - __orig_first1) >= __vec_size) { | ||
| __first1 = __last1 - __vec_size; | ||
| __first2 = __last2 - __vec_size; | ||
| auto __offset = | ||
| std::__find_first_not_set(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2)); | ||
| return {__first1 + __offset, __first2 + __offset}; | ||
| } // else loop over the elements individually | ||
| } | ||
|
|
||
| __equal_to __pred; | ||
| __identity __proj; | ||
| return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj, __proj); | ||
| } | ||
|
|
||
| template <class _Tp, | ||
| class _Pred, | ||
| class _Proj1, | ||
| class _Proj2, | ||
| __enable_if_t<is_integral<_Tp>::value && __desugars_to_v<__equal_tag, _Pred, _Tp, _Tp> && | ||
| __is_identity<_Proj1>::value && __is_identity<_Proj2>::value, | ||
| int> = 0> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> | ||
| __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred&, _Proj1&, _Proj2&) { | ||
| return std::__mismatch_vectorized(__first1, __last1, __first2); | ||
| } | ||
|
|
||
| template <class _Tp, | ||
| class _Pred, | ||
| class _Proj1, | ||
| class _Proj2, | ||
| __enable_if_t<!is_integral<_Tp>::value && __desugars_to_v<__equal_tag, _Pred, _Tp, _Tp> && | ||
| __is_identity<_Proj1>::value && __is_identity<_Proj2>::value && | ||
| __can_map_to_integer_v<_Tp> && __libcpp_is_trivially_equality_comparable<_Tp, _Tp>::value, | ||
| int> = 0> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> | ||
| __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { | ||
| if (__libcpp_is_constant_evaluated()) { | ||
| return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2); | ||
| } else { | ||
| using _Iter = __aliasing_iterator<_Tp*, __get_as_integer_type_t<_Tp>>; | ||
| auto __ret = std::__mismatch_vectorized(_Iter(__first1), _Iter(__last1), _Iter(__first2)); | ||
| return {__ret.first.__base(), __ret.second.__base()}; | ||
| } | ||
| } | ||
| #endif // _LIBCPP_VECTORIZE_ALGORITHMS | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> | ||
| mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { | ||
| __identity __proj; | ||
| auto __res = std::__mismatch( | ||
| std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred, __proj, __proj); | ||
| return std::make_pair(std::__rewrap_iter(__first1, __res.first), std::__rewrap_iter(__first2, __res.second)); | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> | ||
| mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { | ||
| return std::mismatch(__first1, __last1, __first2, __equal_to()); | ||
| } | ||
|
|
||
| #if _LIBCPP_STD_VER >= 14 | ||
| template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( | ||
| _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { | ||
| while (__first1 != __last1 && __first2 != __last2) { | ||
| if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) | ||
| break; | ||
| ++__first1; | ||
| ++__first2; | ||
| } | ||
| return {std::move(__first1), std::move(__first2)}; | ||
| } | ||
|
|
||
| template <class _Tp, class _Pred, class _Proj1, class _Proj2> | ||
| _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> | ||
| __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { | ||
| auto __len = std::min(__last1 - __first1, __last2 - __first2); | ||
| return std::__mismatch(__first1, __first1 + __len, __first2, __pred, __proj1, __proj2); | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> | ||
| mismatch(_InputIterator1 __first1, | ||
| _InputIterator1 __last1, | ||
| _InputIterator2 __first2, | ||
| _InputIterator2 __last2, | ||
| _BinaryPredicate __pred) { | ||
| __identity __proj; | ||
| auto __res = std::__mismatch( | ||
| std::__unwrap_iter(__first1), | ||
| std::__unwrap_iter(__last1), | ||
| std::__unwrap_iter(__first2), | ||
| std::__unwrap_iter(__last2), | ||
| __pred, | ||
| __proj, | ||
| __proj); | ||
| return {std::__rewrap_iter(__first1, __res.first), std::__rewrap_iter(__first2, __res.second)}; | ||
| } | ||
|
|
||
| template <class _InputIterator1, class _InputIterator2> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> | ||
| mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { | ||
| return std::mismatch(__first1, __last1, __first2, __last2, __equal_to()); | ||
| } | ||
| #endif | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MISMATCH_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MOVE_H | ||
| #define _LIBCPP___ALGORITHM_MOVE_H | ||
|
|
||
| #include <__algorithm/copy_move_common.h> | ||
| #include <__algorithm/for_each_segment.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__algorithm/min.h> | ||
| #include <__config> | ||
| #include <__iterator/segmented_iterator.h> | ||
| #include <__type_traits/common_type.h> | ||
| #include <__type_traits/is_constructible.h> | ||
| #include <__utility/move.h> | ||
| #include <__utility/pair.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| __move(_InIter __first, _Sent __last, _OutIter __result); | ||
|
|
||
| template <class _AlgPolicy> | ||
| struct __move_impl { | ||
| template <class _InIter, class _Sent, class _OutIter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| operator()(_InIter __first, _Sent __last, _OutIter __result) const { | ||
| while (__first != __last) { | ||
| *__result = _IterOps<_AlgPolicy>::__iter_move(__first); | ||
| ++__first; | ||
| ++__result; | ||
| } | ||
| return std::make_pair(std::move(__first), std::move(__result)); | ||
| } | ||
|
|
||
| template <class _InIter, class _OutIter> | ||
| struct _MoveSegment { | ||
| using _Traits = __segmented_iterator_traits<_InIter>; | ||
|
|
||
| _OutIter& __result_; | ||
|
|
||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit _MoveSegment(_OutIter& __result) | ||
| : __result_(__result) {} | ||
|
|
||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void | ||
| operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { | ||
| __result_ = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; | ||
| } | ||
| }; | ||
|
|
||
| template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| operator()(_InIter __first, _InIter __last, _OutIter __result) const { | ||
| std::__for_each_segment(__first, __last, _MoveSegment<_InIter, _OutIter>(__result)); | ||
| return std::make_pair(__last, std::move(__result)); | ||
| } | ||
|
|
||
| template <class _InIter, | ||
| class _OutIter, | ||
| __enable_if_t<__has_random_access_iterator_category<_InIter>::value && | ||
| !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, | ||
| int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| operator()(_InIter __first, _InIter __last, _OutIter __result) const { | ||
| using _Traits = __segmented_iterator_traits<_OutIter>; | ||
| using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; | ||
|
|
||
| if (__first == __last) | ||
| return std::make_pair(std::move(__first), std::move(__result)); | ||
|
|
||
| auto __local_first = _Traits::__local(__result); | ||
| auto __segment_iterator = _Traits::__segment(__result); | ||
| while (true) { | ||
| auto __local_last = _Traits::__end(__segment_iterator); | ||
| auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); | ||
| auto __iters = std::__move<_AlgPolicy>(__first, __first + __size, __local_first); | ||
| __first = std::move(__iters.first); | ||
|
|
||
| if (__first == __last) | ||
| return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second))); | ||
|
|
||
| __local_first = _Traits::__begin(++__segment_iterator); | ||
| } | ||
| } | ||
|
|
||
| // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. | ||
| template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> | ||
| operator()(_In* __first, _In* __last, _Out* __result) const { | ||
| return std::__copy_trivial_impl(__first, __last, __result); | ||
| } | ||
| }; | ||
|
|
||
| template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| __move(_InIter __first, _Sent __last, _OutIter __result) { | ||
| return std::__copy_move_unwrap_iters<__move_impl<_AlgPolicy> >( | ||
| std::move(__first), std::move(__last), std::move(__result)); | ||
| } | ||
|
|
||
| template <class _InputIterator, class _OutputIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator | ||
| move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { | ||
| static_assert(is_copy_constructible<_InputIterator>::value, "Iterators has to be copy constructible."); | ||
| static_assert(is_copy_constructible<_OutputIterator>::value, "The output iterator has to be copy constructible."); | ||
|
|
||
| return std::__move<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second; | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MOVE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H | ||
| #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H | ||
|
|
||
| #include <__algorithm/copy_move_common.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__algorithm/min.h> | ||
| #include <__config> | ||
| #include <__iterator/segmented_iterator.h> | ||
| #include <__type_traits/common_type.h> | ||
| #include <__type_traits/is_constructible.h> | ||
| #include <__utility/move.h> | ||
| #include <__utility/pair.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> | ||
| __move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result); | ||
|
|
||
| template <class _AlgPolicy> | ||
| struct __move_backward_impl { | ||
| template <class _InIter, class _Sent, class _OutIter> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| operator()(_InIter __first, _Sent __last, _OutIter __result) const { | ||
| auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); | ||
| auto __original_last_iter = __last_iter; | ||
|
|
||
| while (__first != __last_iter) { | ||
| *--__result = _IterOps<_AlgPolicy>::__iter_move(--__last_iter); | ||
| } | ||
|
|
||
| return std::make_pair(std::move(__original_last_iter), std::move(__result)); | ||
| } | ||
|
|
||
| template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| operator()(_InIter __first, _InIter __last, _OutIter __result) const { | ||
| using _Traits = __segmented_iterator_traits<_InIter>; | ||
| auto __sfirst = _Traits::__segment(__first); | ||
| auto __slast = _Traits::__segment(__last); | ||
| if (__sfirst == __slast) { | ||
| auto __iters = | ||
| std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); | ||
| return std::make_pair(__last, __iters.second); | ||
| } | ||
|
|
||
| __result = | ||
| std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result)) | ||
| .second; | ||
| --__slast; | ||
| while (__sfirst != __slast) { | ||
| __result = | ||
| std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result)) | ||
| .second; | ||
| --__slast; | ||
| } | ||
| __result = std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result)) | ||
| .second; | ||
| return std::make_pair(__last, std::move(__result)); | ||
| } | ||
|
|
||
| template <class _InIter, | ||
| class _OutIter, | ||
| __enable_if_t<__has_random_access_iterator_category<_InIter>::value && | ||
| !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, | ||
| int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> | ||
| operator()(_InIter __first, _InIter __last, _OutIter __result) const { | ||
| using _Traits = __segmented_iterator_traits<_OutIter>; | ||
| using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; | ||
|
|
||
| // When the range contains no elements, __result might not be a valid iterator | ||
| if (__first == __last) | ||
| return std::make_pair(__first, __result); | ||
|
|
||
| auto __orig_last = __last; | ||
|
|
||
| auto __local_last = _Traits::__local(__result); | ||
| auto __segment_iterator = _Traits::__segment(__result); | ||
| while (true) { | ||
| auto __local_first = _Traits::__begin(__segment_iterator); | ||
| auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); | ||
| auto __iter = std::__move_backward<_AlgPolicy>(__last - __size, __last, __local_last).second; | ||
| __last -= __size; | ||
|
|
||
| if (__first == __last) | ||
| return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter))); | ||
|
|
||
| __local_last = _Traits::__end(--__segment_iterator); | ||
| } | ||
| } | ||
|
|
||
| // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. | ||
| template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> | ||
| operator()(_In* __first, _In* __last, _Out* __result) const { | ||
| return std::__copy_backward_trivial_impl(__first, __last, __result); | ||
| } | ||
| }; | ||
|
|
||
| template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> | ||
| __move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { | ||
| static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value && | ||
| std::is_copy_constructible<_BidirectionalIterator1>::value, | ||
| "Iterators must be copy constructible."); | ||
|
|
||
| return std::__copy_move_unwrap_iters<__move_backward_impl<_AlgPolicy> >( | ||
| std::move(__first), std::move(__last), std::move(__result)); | ||
| } | ||
|
|
||
| template <class _BidirectionalIterator1, class _BidirectionalIterator2> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 | ||
| move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { | ||
| return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second; | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H | ||
| #define _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__algorithm/reverse.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__utility/move.h> | ||
| #include <__utility/pair.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _AlgPolicy, class _Compare, class _BidirectionalIterator, class _Sentinel> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, bool> | ||
| __next_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) { | ||
| using _Result = pair<_BidirectionalIterator, bool>; | ||
|
|
||
| _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); | ||
| _BidirectionalIterator __i = __last_iter; | ||
| if (__first == __last || __first == --__i) | ||
| return _Result(std::move(__last_iter), false); | ||
|
|
||
| while (true) { | ||
| _BidirectionalIterator __ip1 = __i; | ||
| if (__comp(*--__i, *__ip1)) { | ||
| _BidirectionalIterator __j = __last_iter; | ||
| while (!__comp(*__i, *--__j)) | ||
| ; | ||
| _IterOps<_AlgPolicy>::iter_swap(__i, __j); | ||
| std::__reverse<_AlgPolicy>(__ip1, __last_iter); | ||
| return _Result(std::move(__last_iter), true); | ||
| } | ||
| if (__i == __first) { | ||
| std::__reverse<_AlgPolicy>(__first, __last_iter); | ||
| return _Result(std::move(__last_iter), false); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| template <class _BidirectionalIterator, class _Compare> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
| next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { | ||
| return std::__next_permutation<_ClassicAlgPolicy>( | ||
| std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)) | ||
| .second; | ||
| } | ||
|
|
||
| template <class _BidirectionalIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
| next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) { | ||
| return std::next_permutation(__first, __last, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // -*- C++ -*- | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_NONE_OF_H | ||
| #define _LIBCPP___ALGORITHM_NONE_OF_H | ||
|
|
||
| #include <__config> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _InputIterator, class _Predicate> | ||
| _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
| none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | ||
| for (; __first != __last; ++__first) | ||
| if (__pred(*__first)) | ||
| return false; | ||
| return true; | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_NONE_OF_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,261 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_NTH_ELEMENT_H | ||
| #define _LIBCPP___ALGORITHM_NTH_ELEMENT_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__algorithm/sort.h> | ||
| #include <__assert> | ||
| #include <__config> | ||
| #include <__debug_utils/randomize_range.h> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Compare, class _RandomAccessIterator> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __nth_element_find_guard( | ||
| _RandomAccessIterator& __i, _RandomAccessIterator& __j, _RandomAccessIterator __m, _Compare __comp) { | ||
| // manually guard downward moving __j against __i | ||
| while (true) { | ||
| if (__i == --__j) { | ||
| return false; | ||
| } | ||
| if (__comp(*__j, *__m)) { | ||
| return true; // found guard for downward moving __j, now use unguarded partition | ||
| } | ||
| } | ||
| } | ||
|
|
||
| template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void | ||
| // NOLINTNEXTLINE(readability-function-cognitive-complexity) | ||
| __nth_element( | ||
| _RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) { | ||
| using _Ops = _IterOps<_AlgPolicy>; | ||
|
|
||
| // _Compare is known to be a reference type | ||
| typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
| const difference_type __limit = 7; | ||
| while (true) { | ||
| if (__nth == __last) | ||
| return; | ||
| difference_type __len = __last - __first; | ||
| switch (__len) { | ||
| case 0: | ||
| case 1: | ||
| return; | ||
| case 2: | ||
| if (__comp(*--__last, *__first)) | ||
| _Ops::iter_swap(__first, __last); | ||
| return; | ||
| case 3: { | ||
| _RandomAccessIterator __m = __first; | ||
| std::__sort3<_AlgPolicy, _Compare>(__first, ++__m, --__last, __comp); | ||
| return; | ||
| } | ||
| } | ||
| if (__len <= __limit) { | ||
| std::__selection_sort<_AlgPolicy, _Compare>(__first, __last, __comp); | ||
| return; | ||
| } | ||
| // __len > __limit >= 3 | ||
| _RandomAccessIterator __m = __first + __len / 2; | ||
| _RandomAccessIterator __lm1 = __last; | ||
| unsigned __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, --__lm1, __comp); | ||
| // *__m is median | ||
| // partition [__first, __m) < *__m and *__m <= [__m, __last) | ||
| // (this inhibits tossing elements equivalent to __m around unnecessarily) | ||
| _RandomAccessIterator __i = __first; | ||
| _RandomAccessIterator __j = __lm1; | ||
| // j points beyond range to be tested, *__lm1 is known to be <= *__m | ||
| // The search going up is known to be guarded but the search coming down isn't. | ||
| // Prime the downward search with a guard. | ||
| if (!__comp(*__i, *__m)) // if *__first == *__m | ||
| { | ||
| // *__first == *__m, *__first doesn't go in first part | ||
| if (std::__nth_element_find_guard<_Compare>(__i, __j, __m, __comp)) { | ||
| _Ops::iter_swap(__i, __j); | ||
| ++__n_swaps; | ||
| } else { | ||
| // *__first == *__m, *__m <= all other elements | ||
| // Partition instead into [__first, __i) == *__first and *__first < [__i, __last) | ||
| ++__i; // __first + 1 | ||
| __j = __last; | ||
| if (!__comp(*__first, *--__j)) { // we need a guard if *__first == *(__last-1) | ||
| while (true) { | ||
| if (__i == __j) { | ||
| return; // [__first, __last) all equivalent elements | ||
| } else if (__comp(*__first, *__i)) { | ||
| _Ops::iter_swap(__i, __j); | ||
| ++__n_swaps; | ||
| ++__i; | ||
| break; | ||
| } | ||
| ++__i; | ||
| } | ||
| } | ||
| // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 | ||
| if (__i == __j) { | ||
| return; | ||
| } | ||
| while (true) { | ||
| while (!__comp(*__first, *__i)) { | ||
| ++__i; | ||
| _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( | ||
| __i != __last, | ||
| "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); | ||
| } | ||
| do { | ||
| _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( | ||
| __j != __first, | ||
| "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); | ||
| --__j; | ||
| } while (__comp(*__first, *__j)); | ||
| if (__i >= __j) | ||
| break; | ||
| _Ops::iter_swap(__i, __j); | ||
| ++__n_swaps; | ||
| ++__i; | ||
| } | ||
| // [__first, __i) == *__first and *__first < [__i, __last) | ||
| // The first part is sorted, | ||
| if (__nth < __i) { | ||
| return; | ||
| } | ||
| // __nth_element the second part | ||
| // std::__nth_element<_Compare>(__i, __nth, __last, __comp); | ||
| __first = __i; | ||
| continue; | ||
| } | ||
| } | ||
| ++__i; | ||
| // j points beyond range to be tested, *__lm1 is known to be <= *__m | ||
| // if not yet partitioned... | ||
| if (__i < __j) { | ||
| // known that *(__i - 1) < *__m | ||
| while (true) { | ||
| // __m still guards upward moving __i | ||
| while (__comp(*__i, *__m)) { | ||
| ++__i; | ||
| _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( | ||
| __i != __last, | ||
| "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); | ||
| } | ||
| // It is now known that a guard exists for downward moving __j | ||
| do { | ||
| _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( | ||
| __j != __first, | ||
| "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); | ||
| --__j; | ||
| } while (!__comp(*__j, *__m)); | ||
| if (__i >= __j) | ||
| break; | ||
| _Ops::iter_swap(__i, __j); | ||
| ++__n_swaps; | ||
| // It is known that __m != __j | ||
| // If __m just moved, follow it | ||
| if (__m == __i) | ||
| __m = __j; | ||
| ++__i; | ||
| } | ||
| } | ||
| // [__first, __i) < *__m and *__m <= [__i, __last) | ||
| if (__i != __m && __comp(*__m, *__i)) { | ||
| _Ops::iter_swap(__i, __m); | ||
| ++__n_swaps; | ||
| } | ||
| // [__first, __i) < *__i and *__i <= [__i+1, __last) | ||
| if (__nth == __i) | ||
| return; | ||
| if (__n_swaps == 0) { | ||
| // We were given a perfectly partitioned sequence. Coincidence? | ||
| if (__nth < __i) { | ||
| // Check for [__first, __i) already sorted | ||
| __j = __m = __first; | ||
| while (true) { | ||
| if (++__j == __i) { | ||
| // [__first, __i) sorted | ||
| return; | ||
| } | ||
| if (__comp(*__j, *__m)) { | ||
| // not yet sorted, so sort | ||
| break; | ||
| } | ||
| __m = __j; | ||
| } | ||
| } else { | ||
| // Check for [__i, __last) already sorted | ||
| __j = __m = __i; | ||
| while (true) { | ||
| if (++__j == __last) { | ||
| // [__i, __last) sorted | ||
| return; | ||
| } | ||
| if (__comp(*__j, *__m)) { | ||
| // not yet sorted, so sort | ||
| break; | ||
| } | ||
| __m = __j; | ||
| } | ||
| } | ||
| } | ||
| // __nth_element on range containing __nth | ||
| if (__nth < __i) { | ||
| // std::__nth_element<_Compare>(__first, __nth, __i, __comp); | ||
| __last = __i; | ||
| } else { | ||
| // std::__nth_element<_Compare>(__i+1, __nth, __last, __comp); | ||
| __first = ++__i; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __nth_element_impl( | ||
| _RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare& __comp) { | ||
| if (__nth == __last) | ||
| return; | ||
|
|
||
| std::__debug_randomize_range<_AlgPolicy>(__first, __last); | ||
|
|
||
| std::__nth_element<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __nth, __last, __comp); | ||
|
|
||
| std::__debug_randomize_range<_AlgPolicy>(__first, __nth); | ||
| if (__nth != __last) { | ||
| std::__debug_randomize_range<_AlgPolicy>(++__nth, __last); | ||
| } | ||
| } | ||
|
|
||
| template <class _RandomAccessIterator, class _Compare> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
| nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) { | ||
| std::__nth_element_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__nth), std::move(__last), __comp); | ||
| } | ||
|
|
||
| template <class _RandomAccessIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
| nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) { | ||
| std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_NTH_ELEMENT_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ALGORITHM_PARTIAL_SORT_H | ||
| #define _LIBCPP___ALGORITHM_PARTIAL_SORT_H | ||
|
|
||
| #include <__algorithm/comp.h> | ||
| #include <__algorithm/comp_ref_type.h> | ||
| #include <__algorithm/iterator_operations.h> | ||
| #include <__algorithm/make_heap.h> | ||
| #include <__algorithm/sift_down.h> | ||
| #include <__algorithm/sort_heap.h> | ||
| #include <__config> | ||
| #include <__debug_utils/randomize_range.h> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__type_traits/is_assignable.h> | ||
| #include <__type_traits/is_constructible.h> | ||
| #include <__utility/move.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_PUSH_MACROS | ||
| #include <__undef_macros> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator __partial_sort_impl( | ||
| _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare&& __comp) { | ||
| if (__first == __middle) { | ||
| return _IterOps<_AlgPolicy>::next(__middle, __last); | ||
| } | ||
|
|
||
| std::__make_heap<_AlgPolicy>(__first, __middle, __comp); | ||
|
|
||
| typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; | ||
| _RandomAccessIterator __i = __middle; | ||
| for (; __i != __last; ++__i) { | ||
| if (__comp(*__i, *__first)) { | ||
| _IterOps<_AlgPolicy>::iter_swap(__i, __first); | ||
| std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first); | ||
| } | ||
| } | ||
| std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp); | ||
|
|
||
| return __i; | ||
| } | ||
|
|
||
| template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel> | ||
| _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator | ||
| __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare& __comp) { | ||
| if (__first == __middle) | ||
| return _IterOps<_AlgPolicy>::next(__middle, __last); | ||
|
|
||
| std::__debug_randomize_range<_AlgPolicy>(__first, __last); | ||
|
|
||
| auto __last_iter = | ||
| std::__partial_sort_impl<_AlgPolicy>(__first, __middle, __last, static_cast<__comp_ref_type<_Compare> >(__comp)); | ||
|
|
||
| std::__debug_randomize_range<_AlgPolicy>(__middle, __last); | ||
|
|
||
| return __last_iter; | ||
| } | ||
|
|
||
| template <class _RandomAccessIterator, class _Compare> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void partial_sort( | ||
| _RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp) { | ||
| static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); | ||
| static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); | ||
|
|
||
| (void)std::__partial_sort<_ClassicAlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __comp); | ||
| } | ||
|
|
||
| template <class _RandomAccessIterator> | ||
| inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
| partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) { | ||
| std::partial_sort(__first, __middle, __last, __less<>()); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| _LIBCPP_POP_MACROS | ||
|
|
||
| #endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_H |