Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:12

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___ALGORITHM_SEARCH_N_H
0011 #define _LIBCPP___ALGORITHM_SEARCH_N_H
0012 
0013 #include <__algorithm/comp.h>
0014 #include <__algorithm/iterator_operations.h>
0015 #include <__config>
0016 #include <__functional/identity.h>
0017 #include <__iterator/advance.h>
0018 #include <__iterator/concepts.h>
0019 #include <__iterator/distance.h>
0020 #include <__iterator/iterator_traits.h>
0021 #include <__ranges/concepts.h>
0022 #include <__type_traits/enable_if.h>
0023 #include <__type_traits/invoke.h>
0024 #include <__type_traits/is_callable.h>
0025 #include <__utility/convert_to_integral.h>
0026 #include <__utility/pair.h>
0027 
0028 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0029 #  pragma GCC system_header
0030 #endif
0031 
0032 _LIBCPP_BEGIN_NAMESPACE_STD
0033 
0034 template <class _AlgPolicy, class _Pred, class _Iter, class _Sent, class _SizeT, class _Type, class _Proj>
0035 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter> __search_n_forward_impl(
0036     _Iter __first, _Sent __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) {
0037   if (__count <= 0)
0038     return std::make_pair(__first, __first);
0039   while (true) {
0040     // Find first element in sequence that matchs __value, with a mininum of loop checks
0041     while (true) {
0042       if (__first == __last) { // return __last if no element matches __value
0043         _IterOps<_AlgPolicy>::__advance_to(__first, __last);
0044         return std::make_pair(__first, __first);
0045       }
0046       if (std::__invoke(__pred, std::__invoke(__proj, *__first), __value))
0047         break;
0048       ++__first;
0049     }
0050     // *__first matches __value, now match elements after here
0051     _Iter __m = __first;
0052     _SizeT __c(0);
0053     while (true) {
0054       if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern)
0055         return std::make_pair(__first, ++__m);
0056       if (++__m == __last) { // Otherwise if source exhaused, pattern not found
0057         _IterOps<_AlgPolicy>::__advance_to(__first, __last);
0058         return std::make_pair(__first, __first);
0059       }
0060 
0061       // if there is a mismatch, restart with a new __first
0062       if (!std::__invoke(__pred, std::__invoke(__proj, *__m), __value)) {
0063         __first = __m;
0064         ++__first;
0065         break;
0066       } // else there is a match, check next elements
0067     }
0068   }
0069 }
0070 
0071 template <class _AlgPolicy, class _Pred, class _Iter, class _Sent, class _SizeT, class _Type, class _Proj, class _DiffT>
0072 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 std::pair<_Iter, _Iter> __search_n_random_access_impl(
0073     _Iter __first, _Sent __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj, _DiffT __size1) {
0074   using difference_type = typename iterator_traits<_Iter>::difference_type;
0075   if (__count == 0)
0076     return std::make_pair(__first, __first);
0077   if (__size1 < static_cast<_DiffT>(__count)) {
0078     _IterOps<_AlgPolicy>::__advance_to(__first, __last);
0079     return std::make_pair(__first, __first);
0080   }
0081 
0082   const auto __s = __first + __size1 - difference_type(__count - 1); // Start of pattern match can't go beyond here
0083   while (true) {
0084     // Find first element in sequence that matchs __value, with a mininum of loop checks
0085     while (true) {
0086       if (__first >= __s) { // return __last if no element matches __value
0087         _IterOps<_AlgPolicy>::__advance_to(__first, __last);
0088         return std::make_pair(__first, __first);
0089       }
0090       if (std::__invoke(__pred, std::__invoke(__proj, *__first), __value))
0091         break;
0092       ++__first;
0093     }
0094     // *__first matches __value_, now match elements after here
0095     auto __m = __first;
0096     _SizeT __c(0);
0097     while (true) {
0098       if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern)
0099         return std::make_pair(__first, __first + _DiffT(__count));
0100       ++__m; // no need to check range on __m because __s guarantees we have enough source
0101 
0102       // if there is a mismatch, restart with a new __first
0103       if (!std::__invoke(__pred, std::__invoke(__proj, *__m), __value)) {
0104         __first = __m;
0105         ++__first;
0106         break;
0107       } // else there is a match, check next elements
0108     }
0109   }
0110 }
0111 
0112 template <class _Iter,
0113           class _Sent,
0114           class _DiffT,
0115           class _Type,
0116           class _Pred,
0117           class _Proj,
0118           __enable_if_t<__has_random_access_iterator_category<_Iter>::value, int> = 0>
0119 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter>
0120 __search_n_impl(_Iter __first, _Sent __last, _DiffT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) {
0121   return std::__search_n_random_access_impl<_ClassicAlgPolicy>(
0122       __first, __last, __count, __value, __pred, __proj, __last - __first);
0123 }
0124 
0125 template <class _Iter1,
0126           class _Sent1,
0127           class _DiffT,
0128           class _Type,
0129           class _Pred,
0130           class _Proj,
0131           __enable_if_t<__has_forward_iterator_category<_Iter1>::value &&
0132                             !__has_random_access_iterator_category<_Iter1>::value,
0133                         int> = 0>
0134 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1>
0135 __search_n_impl(_Iter1 __first, _Sent1 __last, _DiffT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) {
0136   return std::__search_n_forward_impl<_ClassicAlgPolicy>(__first, __last, __count, __value, __pred, __proj);
0137 }
0138 
0139 template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
0140 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n(
0141     _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) {
0142   static_assert(
0143       __is_callable<_BinaryPredicate&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
0144   auto __proj = __identity();
0145   return std::__search_n_impl(__first, __last, std::__convert_to_integral(__count), __value, __pred, __proj).first;
0146 }
0147 
0148 template <class _ForwardIterator, class _Size, class _Tp>
0149 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
0150 search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) {
0151   return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to());
0152 }
0153 
0154 _LIBCPP_END_NAMESPACE_STD
0155 
0156 #endif // _LIBCPP___ALGORITHM_SEARCH_N_H