1111#define _LIBCPP___ALGORITHM_SEARCH_N_H
1212
1313#include < __algorithm/comp.h>
14+ #include < __algorithm/find.h>
1415#include < __algorithm/iterator_operations.h>
16+ #include < __algorithm/unwrap_iter.h>
1517#include < __config>
1618#include < __functional/identity.h>
1719#include < __iterator/advance.h>
@@ -68,43 +70,34 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter> __search_
6870 }
6971}
7072
71- template <class _AlgPolicy , class _Pred , class _Iter , class _Sent , class _SizeT , class _Type , class _Proj , class _DiffT >
73+ template <class _AlgPolicy , class _Pred , class _Iter , class _SizeT , class _Type , class _Proj , class _DiffT >
7274_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 std::pair<_Iter, _Iter> __search_n_random_access_impl (
73- _Iter __first, _Sent __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj, _DiffT __size1) {
74- using difference_type = typename iterator_traits<_Iter>::difference_type;
75+ _Iter __first, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj, _DiffT __size) {
76+ auto __last = __first + __size;
77+
7578 if (__count == 0 )
7679 return std::make_pair (__first, __first);
77- if (__size1 < static_cast <_DiffT>(__count)) {
78- _IterOps<_AlgPolicy>::__advance_to (__first, __last);
79- return std::make_pair (__first, __first);
80- }
80+ if (__size < static_cast <_DiffT>(__count))
81+ return std::make_pair (__last, __last);
8182
82- const auto __s = __first + __size1 - difference_type (__count - 1 ); // Start of pattern match can't go beyond here
83+ _Iter __try_match_until = __last - __count;
84+ _Iter __match_start = __first;
85+ _Iter __matched_until = __first;
8386 while (true ) {
84- // Find first element in sequence that matchs __value, with a mininum of loop checks
85- while (true ) {
86- if (__first >= __s) { // return __last if no element matches __value
87- _IterOps<_AlgPolicy>::__advance_to (__first, __last);
88- return std::make_pair (__first, __first);
89- }
90- if (std::__invoke (__pred, std::__invoke (__proj, *__first), __value))
91- break ;
92- ++__first;
93- }
94- // *__first matches __value_, now match elements after here
95- auto __m = __first;
96- _SizeT __c (0 );
87+ if (__match_start > __try_match_until)
88+ return std::make_pair (__last, __last);
89+
90+ _Iter __check = __match_start + __count;
91+
9792 while (true ) {
98- if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern)
99- return std::make_pair (__first, __first + _DiffT (__count));
100- ++__m; // no need to check range on __m because __s guarantees we have enough source
93+ if (__check == __matched_until)
94+ return std::make_pair (__match_start, __match_start + __count);
10195
102- // if there is a mismatch, restart with a new __first
103- if (!std::__invoke (__pred, std::__invoke (__proj, *__m), __value)) {
104- __first = __m;
105- ++__first;
96+ if (!std::__invoke (__pred, std::__invoke (__proj, *--__check), __value)) {
97+ __matched_until = __match_start + __count;
98+ __match_start = ++__check;
10699 break ;
107- } // else there is a match, check next elements
100+ }
108101 }
109102 }
110103}
@@ -119,7 +112,7 @@ template <class _Iter,
119112_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter>
120113__search_n_impl (_Iter __first, _Sent __last, _DiffT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) {
121114 return std::__search_n_random_access_impl<_ClassicAlgPolicy>(
122- __first, __last, __count, __value, __pred, __proj, __last - __first);
115+ __first, __count, __value, __pred, __proj, __last - __first);
123116}
124117
125118template <class _Iter1 ,
@@ -142,7 +135,16 @@ template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate
142135 static_assert (
143136 __is_callable<_BinaryPredicate&, decltype (*__first), const _Tp&>::value, " The comparator has to be callable" );
144137 auto __proj = __identity ();
145- return std::__search_n_impl (__first, __last, std::__convert_to_integral (__count), __value, __pred, __proj).first ;
138+ return std::__rewrap_iter (
139+ __first,
140+ std::__search_n_impl (
141+ std::__unwrap_iter (__first),
142+ std::__unwrap_iter (__last),
143+ std::__convert_to_integral (__count),
144+ __value,
145+ __pred,
146+ __proj)
147+ .first );
146148}
147149
148150template <class _ForwardIterator , class _Size , class _Tp >
0 commit comments