2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___ALGORITHM_FIND_H
11 #define _LIBCPP___ALGORITHM_FIND_H
13 #include <__algorithm/min.h>
14 #include <__algorithm/unwrap_iter.h>
15 #include <__bit/countr.h>
16 #include <__bit/invert_if.h>
18 #include <__functional/identity.h>
19 #include <__functional/invoke.h>
20 #include <__fwd/bit_reference.h>
21 #include <__string/constexpr_c_functions.h>
22 #include <__type_traits/is_same.h>
24 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
28 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29 # pragma GCC system_header
33 #include <__undef_macros>
35 _LIBCPP_BEGIN_NAMESPACE_STD
37 // generic implementation
38 template <class _Iter
, class _Sent
, class _Tp
, class _Proj
>
39 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
40 __find_impl(_Iter __first
, _Sent __last
, const _Tp
& __value
, _Proj
& __proj
) {
41 for (; __first
!= __last
; ++__first
)
42 if (std::__invoke(__proj
, *__first
) == __value
)
47 // trivially equality comparable implementations
51 __enable_if_t
<__is_identity
<_Proj
>::value
&& __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
&&
54 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp
*
55 __find_impl(_Tp
* __first
, _Tp
* __last
, const _Up
& __value
, _Proj
&) {
56 if (auto __ret
= std::__constexpr_memchr(__first
, __value
, __last
- __first
))
61 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
65 __enable_if_t
<__is_identity
<_Proj
>::value
&& __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
&&
66 sizeof(_Tp
) == sizeof(wchar_t) && _LIBCPP_ALIGNOF(_Tp
) >= _LIBCPP_ALIGNOF(wchar_t),
68 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp
*
69 __find_impl(_Tp
* __first
, _Tp
* __last
, const _Up
& __value
, _Proj
&) {
70 if (auto __ret
= std::__constexpr_wmemchr(__first
, __value
, __last
- __first
))
74 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
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
;
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
;
91 return _It(__first
.__seg_
, static_cast<unsigned>(std::__libcpp_ctz(__b
)));
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_
);
101 return _It(__first
.__seg_
, static_cast<unsigned>(std::__libcpp_ctz(__b
)));
103 // do last partial word
105 __storage_type __m
= ~__storage_type(0) >> (__bits_per_word
- __n
);
106 __storage_type __b
= std::__invert_if
<!_ToFind
>(*__first
.__seg_
) & __m
;
108 return _It(__first
.__seg_
, static_cast<unsigned>(std::__libcpp_ctz(__b
)));
110 return _It(__first
.__seg_
, static_cast<unsigned>(__n
));
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
));
121 template <class _InputIterator
, class _Tp
>
122 _LIBCPP_NODISCARD_EXT
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
123 find(_InputIterator __first
, _InputIterator __last
, const _Tp
& __value
) {
125 return std::__rewrap_iter(
126 __first
, std::__find_impl(std::__unwrap_iter(__first
), std::__unwrap_iter(__last
), __value
, __proj
));
129 _LIBCPP_END_NAMESPACE_STD
133 #endif // _LIBCPP___ALGORITHM_FIND_H