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/find_segment_if.h>
14 #include <__algorithm/min.h>
15 #include <__algorithm/unwrap_iter.h>
16 #include <__bit/countr.h>
17 #include <__bit/invert_if.h>
19 #include <__functional/identity.h>
20 #include <__fwd/bit_reference.h>
21 #include <__iterator/segmented_iterator.h>
22 #include <__string/constexpr_c_functions.h>
23 #include <__type_traits/enable_if.h>
24 #include <__type_traits/invoke.h>
25 #include <__type_traits/is_equality_comparable.h>
26 #include <__type_traits/is_integral.h>
27 #include <__type_traits/is_same.h>
28 #include <__type_traits/is_signed.h>
29 #include <__utility/move.h>
32 #if _LIBCPP_HAS_WIDE_CHARACTERS
36 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
37 # pragma GCC system_header
41 #include <__undef_macros>
43 _LIBCPP_BEGIN_NAMESPACE_STD
45 // generic implementation
46 template <class _Iter
, class _Sent
, class _Tp
, class _Proj
>
47 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
48 __find(_Iter __first
, _Sent __last
, const _Tp
& __value
, _Proj
& __proj
) {
49 for (; __first
!= __last
; ++__first
)
50 if (std::__invoke(__proj
, *__first
) == __value
)
55 // trivially equality comparable implementations
59 __enable_if_t
<__is_identity
<_Proj
>::value
&& __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
&&
62 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp
* __find(_Tp
* __first
, _Tp
* __last
, const _Up
& __value
, _Proj
&) {
63 if (auto __ret
= std::__constexpr_memchr(__first
, __value
, __last
- __first
))
68 #if _LIBCPP_HAS_WIDE_CHARACTERS
72 __enable_if_t
<__is_identity
<_Proj
>::value
&& __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
&&
73 sizeof(_Tp
) == sizeof(wchar_t) && _LIBCPP_ALIGNOF(_Tp
) >= _LIBCPP_ALIGNOF(wchar_t),
75 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp
* __find(_Tp
* __first
, _Tp
* __last
, const _Up
& __value
, _Proj
&) {
76 if (auto __ret
= std::__constexpr_wmemchr(__first
, __value
, __last
- __first
))
80 #endif // _LIBCPP_HAS_WIDE_CHARACTERS
82 // TODO: This should also be possible to get right with different signedness
83 // cast integral types to allow vectorization
87 __enable_if_t
<__is_identity
<_Proj
>::value
&& !__libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
&&
88 is_integral
<_Tp
>::value
&& is_integral
<_Up
>::value
&&
89 is_signed
<_Tp
>::value
== is_signed
<_Up
>::value
,
91 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp
*
92 __find(_Tp
* __first
, _Tp
* __last
, const _Up
& __value
, _Proj
& __proj
) {
93 if (__value
< numeric_limits
<_Tp
>::min() || __value
> numeric_limits
<_Tp
>::max())
95 return std::__find(__first
, __last
, _Tp(__value
), __proj
);
98 // __bit_iterator implementation
99 template <bool _ToFind
, class _Cp
, bool _IsConst
>
100 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator
<_Cp
, _IsConst
>
101 __find_bool(__bit_iterator
<_Cp
, _IsConst
> __first
, typename
_Cp::size_type __n
) {
102 using _It
= __bit_iterator
<_Cp
, _IsConst
>;
103 using __storage_type
= typename
_It::__storage_type
;
105 const int __bits_per_word
= _It::__bits_per_word
;
106 // do first partial word
107 if (__first
.__ctz_
!= 0) {
108 __storage_type __clz_f
= static_cast<__storage_type
>(__bits_per_word
- __first
.__ctz_
);
109 __storage_type __dn
= std::min(__clz_f
, __n
);
110 __storage_type __m
= (~__storage_type(0) << __first
.__ctz_
) & (~__storage_type(0) >> (__clz_f
- __dn
));
111 __storage_type __b
= std::__invert_if
<!_ToFind
>(*__first
.__seg_
) & __m
;
113 return _It(__first
.__seg_
, static_cast<unsigned>(std::__libcpp_ctz(__b
)));
115 return __first
+ __n
;
119 // do middle whole words
120 for (; __n
>= __bits_per_word
; ++__first
.__seg_
, __n
-= __bits_per_word
) {
121 __storage_type __b
= std::__invert_if
<!_ToFind
>(*__first
.__seg_
);
123 return _It(__first
.__seg_
, static_cast<unsigned>(std::__libcpp_ctz(__b
)));
125 // do last partial word
127 __storage_type __m
= ~__storage_type(0) >> (__bits_per_word
- __n
);
128 __storage_type __b
= std::__invert_if
<!_ToFind
>(*__first
.__seg_
) & __m
;
130 return _It(__first
.__seg_
, static_cast<unsigned>(std::__libcpp_ctz(__b
)));
132 return _It(__first
.__seg_
, static_cast<unsigned>(__n
));
135 template <class _Cp
, bool _IsConst
, class _Tp
, class _Proj
, __enable_if_t
<__is_identity
<_Proj
>::value
, int> = 0>
136 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator
<_Cp
, _IsConst
>
137 __find(__bit_iterator
<_Cp
, _IsConst
> __first
, __bit_iterator
<_Cp
, _IsConst
> __last
, const _Tp
& __value
, _Proj
&) {
138 if (static_cast<bool>(__value
))
139 return std::__find_bool
<true>(__first
, static_cast<typename
_Cp::size_type
>(__last
- __first
));
140 return std::__find_bool
<false>(__first
, static_cast<typename
_Cp::size_type
>(__last
- __first
));
143 // segmented iterator implementation
146 struct __find_segment
;
148 template <class _SegmentedIterator
,
151 __enable_if_t
<__is_segmented_iterator
<_SegmentedIterator
>::value
, int> = 0>
152 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
153 __find(_SegmentedIterator __first
, _SegmentedIterator __last
, const _Tp
& __value
, _Proj
& __proj
) {
154 return std::__find_segment_if(std::move(__first
), std::move(__last
), __find_segment
<_Tp
>(__value
), __proj
);
158 struct __find_segment
{
161 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
__find_segment(const _Tp
& __value
) : __value_(__value
) {}
163 template <class _InputIterator
, class _Proj
>
164 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _InputIterator
165 operator()(_InputIterator __first
, _InputIterator __last
, _Proj
& __proj
) const {
166 return std::__find(__first
, __last
, __value_
, __proj
);
171 template <class _InputIterator
, class _Tp
>
172 [[__nodiscard__
]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
173 find(_InputIterator __first
, _InputIterator __last
, const _Tp
& __value
) {
175 return std::__rewrap_iter(
176 __first
, std::__find(std::__unwrap_iter(__first
), std::__unwrap_iter(__last
), __value
, __proj
));
179 _LIBCPP_END_NAMESPACE_STD
183 #endif // _LIBCPP___ALGORITHM_FIND_H