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_COUNT_H
11 #define _LIBCPP___ALGORITHM_COUNT_H
13 #include <__cxx03/__algorithm/iterator_operations.h>
14 #include <__cxx03/__algorithm/min.h>
15 #include <__cxx03/__bit/invert_if.h>
16 #include <__cxx03/__bit/popcount.h>
17 #include <__cxx03/__config>
18 #include <__cxx03/__functional/identity.h>
19 #include <__cxx03/__functional/invoke.h>
20 #include <__cxx03/__fwd/bit_reference.h>
21 #include <__cxx03/__iterator/iterator_traits.h>
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 # pragma GCC system_header
28 #include <__cxx03/__undef_macros>
30 _LIBCPP_BEGIN_NAMESPACE_STD
32 // generic implementation
33 template <class _AlgPolicy
, class _Iter
, class _Sent
, class _Tp
, class _Proj
>
34 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename _IterOps
<_AlgPolicy
>::template __difference_type
<_Iter
>
35 __count(_Iter __first
, _Sent __last
, const _Tp
& __value
, _Proj
& __proj
) {
36 typename _IterOps
<_AlgPolicy
>::template __difference_type
<_Iter
> __r(0);
37 for (; __first
!= __last
; ++__first
)
38 if (std::__invoke(__proj
, *__first
) == __value
)
43 // __bit_iterator implementation
44 template <bool _ToCount
, class _Cp
, bool _IsConst
>
45 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bit_iterator
<_Cp
, _IsConst
>::difference_type
46 __count_bool(__bit_iterator
<_Cp
, _IsConst
> __first
, typename
_Cp::size_type __n
) {
47 using _It
= __bit_iterator
<_Cp
, _IsConst
>;
48 using __storage_type
= typename
_It::__storage_type
;
49 using difference_type
= typename
_It::difference_type
;
51 const int __bits_per_word
= _It::__bits_per_word
;
52 difference_type __r
= 0;
53 // do first partial word
54 if (__first
.__ctz_
!= 0) {
55 __storage_type __clz_f
= static_cast<__storage_type
>(__bits_per_word
- __first
.__ctz_
);
56 __storage_type __dn
= std::min(__clz_f
, __n
);
57 __storage_type __m
= (~__storage_type(0) << __first
.__ctz_
) & (~__storage_type(0) >> (__clz_f
- __dn
));
58 __r
= std::__libcpp_popcount(std::__invert_if
<!_ToCount
>(*__first
.__seg_
) & __m
);
62 // do middle whole words
63 for (; __n
>= __bits_per_word
; ++__first
.__seg_
, __n
-= __bits_per_word
)
64 __r
+= std::__libcpp_popcount(std::__invert_if
<!_ToCount
>(*__first
.__seg_
));
65 // do last partial word
67 __storage_type __m
= ~__storage_type(0) >> (__bits_per_word
- __n
);
68 __r
+= std::__libcpp_popcount(std::__invert_if
<!_ToCount
>(*__first
.__seg_
) & __m
);
73 template <class, class _Cp
, bool _IsConst
, class _Tp
, class _Proj
, __enable_if_t
<__is_identity
<_Proj
>::value
, int> = 0>
74 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t
<__bit_iterator
<_Cp
, _IsConst
> >
75 __count(__bit_iterator
<_Cp
, _IsConst
> __first
, __bit_iterator
<_Cp
, _IsConst
> __last
, const _Tp
& __value
, _Proj
&) {
77 return std::__count_bool
<true>(__first
, static_cast<typename
_Cp::size_type
>(__last
- __first
));
78 return std::__count_bool
<false>(__first
, static_cast<typename
_Cp::size_type
>(__last
- __first
));
81 template <class _InputIterator
, class _Tp
>
82 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t
<_InputIterator
>
83 count(_InputIterator __first
, _InputIterator __last
, const _Tp
& __value
) {
85 return std::__count
<_ClassicAlgPolicy
>(__first
, __last
, __value
, __proj
);
88 _LIBCPP_END_NAMESPACE_STD
92 #endif // _LIBCPP___ALGORITHM_COUNT_H