1010#ifndef _LIBCPP___ALGORITHM_FIND_H
1111#define _LIBCPP___ALGORITHM_FIND_H
1212
13+ #include < __algorithm/min.h>
1314#include < __algorithm/unwrap_iter.h>
15+ #include < __bit/countr.h>
16+ #include < __bit/invert_if.h>
1417#include < __config>
1518#include < __functional/identity.h>
1619#include < __functional/invoke.h>
20+ #include < __fwd/bit_reference.h>
1721#include < __string/constexpr_c_functions.h>
1822#include < __type_traits/is_same.h>
1923
2529# pragma GCC system_header
2630#endif
2731
32+ _LIBCPP_PUSH_MACROS
33+ #include < __undef_macros>
34+
2835_LIBCPP_BEGIN_NAMESPACE_STD
2936
37+ // generic implementation
3038template <class _Iter , class _Sent , class _Tp , class _Proj >
3139_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
3240__find_impl (_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
@@ -36,6 +44,7 @@ __find_impl(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
3644 return __first;
3745}
3846
47+ // trivially equality comparable implementations
3948template <class _Tp ,
4049 class _Up ,
4150 class _Proj ,
@@ -64,6 +73,51 @@ __find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) {
6473}
6574#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
6675
76+ // __bit_iterator implementation
77+ template <bool _ToFind, class _Cp , bool _IsConst>
78+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, _IsConst>
79+ __find_bool (__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) {
80+ using _It = __bit_iterator<_Cp, _IsConst>;
81+ using __storage_type = typename _It::__storage_type;
82+
83+ const int __bits_per_word = _It::__bits_per_word;
84+ // do first partial word
85+ if (__first.__ctz_ != 0 ) {
86+ __storage_type __clz_f = static_cast <__storage_type>(__bits_per_word - __first.__ctz_ );
87+ __storage_type __dn = std::min (__clz_f, __n);
88+ __storage_type __m = (~__storage_type (0 ) << __first.__ctz_ ) & (~__storage_type (0 ) >> (__clz_f - __dn));
89+ __storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_ ) & __m;
90+ if (__b)
91+ return _It (__first.__seg_ , static_cast <unsigned >(std::__libcpp_ctz (__b)));
92+ if (__n == __dn)
93+ return __first + __n;
94+ __n -= __dn;
95+ ++__first.__seg_ ;
96+ }
97+ // do middle whole words
98+ for (; __n >= __bits_per_word; ++__first.__seg_ , __n -= __bits_per_word) {
99+ __storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_ );
100+ if (__b)
101+ return _It (__first.__seg_ , static_cast <unsigned >(std::__libcpp_ctz (__b)));
102+ }
103+ // do last partial word
104+ if (__n > 0 ) {
105+ __storage_type __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
106+ __storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_ ) & __m;
107+ if (__b)
108+ return _It (__first.__seg_ , static_cast <unsigned >(std::__libcpp_ctz (__b)));
109+ }
110+ return _It (__first.__seg_ , static_cast <unsigned >(__n));
111+ }
112+
113+ template <class _Cp , bool _IsConst, class _Tp , class _Proj , __enable_if_t <__is_identity<_Proj>::value, int > = 0 >
114+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, _IsConst>
115+ __find_impl (__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value, _Proj&) {
116+ if (static_cast <bool >(__value))
117+ return std::__find_bool<true >(__first, static_cast <typename _Cp::size_type>(__last - __first));
118+ return std::__find_bool<false >(__first, static_cast <typename _Cp::size_type>(__last - __first));
119+ }
120+
67121template <class _InputIterator , class _Tp >
68122_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
69123find (_InputIterator __first, _InputIterator __last, const _Tp& __value) {
@@ -74,4 +128,6 @@ find(_InputIterator __first, _InputIterator __last, const _Tp& __value) {
74128
75129_LIBCPP_END_NAMESPACE_STD
76130
131+ _LIBCPP_POP_MACROS
132+
77133#endif // _LIBCPP___ALGORITHM_FIND_H
0 commit comments