1111#define _LIBCPP___ALGORITHM_EQUAL_H
1212
1313#include < __algorithm/comp.h>
14+ #include < __algorithm/min.h>
1415#include < __algorithm/unwrap_iter.h>
1516#include < __config>
1617#include < __functional/identity.h>
18+ #include < __fwd/bit_reference.h>
1719#include < __iterator/distance.h>
1820#include < __iterator/iterator_traits.h>
21+ #include < __memory/pointer_traits.h>
1922#include < __string/constexpr_c_functions.h>
2023#include < __type_traits/desugars_to.h>
2124#include < __type_traits/enable_if.h>
2225#include < __type_traits/invoke.h>
2326#include < __type_traits/is_equality_comparable.h>
27+ #include < __type_traits/is_same.h>
2428#include < __type_traits/is_volatile.h>
2529#include < __utility/move.h>
2630
31+ #if _LIBCPP_STD_VER >= 20
32+ # include < __functional/ranges_operations.h>
33+ #endif
34+
2735#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2836# pragma GCC system_header
2937#endif
@@ -33,6 +41,132 @@ _LIBCPP_PUSH_MACROS
3341
3442_LIBCPP_BEGIN_NAMESPACE_STD
3543
44+ template <class _Cp , bool _IC1, bool _IC2>
45+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_unaligned (
46+ __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
47+ using _It = __bit_iterator<_Cp, _IC1>;
48+ using difference_type = typename _It::difference_type;
49+ using __storage_type = typename _It::__storage_type;
50+
51+ const int __bits_per_word = _It::__bits_per_word;
52+ difference_type __n = __last1 - __first1;
53+ if (__n > 0 ) {
54+ // do first word
55+ if (__first1.__ctz_ != 0 ) {
56+ unsigned __clz_f = __bits_per_word - __first1.__ctz_ ;
57+ difference_type __dn = std::min (static_cast <difference_type>(__clz_f), __n);
58+ __n -= __dn;
59+ __storage_type __m = (~__storage_type (0 ) << __first1.__ctz_ ) & (~__storage_type (0 ) >> (__clz_f - __dn));
60+ __storage_type __b = *__first1.__seg_ & __m;
61+ unsigned __clz_r = __bits_per_word - __first2.__ctz_ ;
62+ __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
63+ __m = (~__storage_type (0 ) << __first2.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __ddn));
64+ if (__first2.__ctz_ > __first1.__ctz_ ) {
65+ if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_ )))
66+ return false ;
67+ } else {
68+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_ )))
69+ return false ;
70+ }
71+ __first2.__seg_ += (__ddn + __first2.__ctz_ ) / __bits_per_word;
72+ __first2.__ctz_ = static_cast <unsigned >((__ddn + __first2.__ctz_ ) % __bits_per_word);
73+ __dn -= __ddn;
74+ if (__dn > 0 ) {
75+ __m = ~__storage_type (0 ) >> (__bits_per_word - __dn);
76+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn)))
77+ return false ;
78+ __first2.__ctz_ = static_cast <unsigned >(__dn);
79+ }
80+ ++__first1.__seg_ ;
81+ // __first1.__ctz_ = 0;
82+ }
83+ // __first1.__ctz_ == 0;
84+ // do middle words
85+ unsigned __clz_r = __bits_per_word - __first2.__ctz_ ;
86+ __storage_type __m = ~__storage_type (0 ) << __first2.__ctz_ ;
87+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_ ) {
88+ __storage_type __b = *__first1.__seg_ ;
89+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_ ))
90+ return false ;
91+ ++__first2.__seg_ ;
92+ if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r))
93+ return false ;
94+ }
95+ // do last word
96+ if (__n > 0 ) {
97+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
98+ __storage_type __b = *__first1.__seg_ & __m;
99+ __storage_type __dn = std::min (__n, static_cast <difference_type>(__clz_r));
100+ __m = (~__storage_type (0 ) << __first2.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __dn));
101+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_ ))
102+ return false ;
103+ __first2.__seg_ += (__dn + __first2.__ctz_ ) / __bits_per_word;
104+ __first2.__ctz_ = static_cast <unsigned >((__dn + __first2.__ctz_ ) % __bits_per_word);
105+ __n -= __dn;
106+ if (__n > 0 ) {
107+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
108+ if ((*__first2.__seg_ & __m) != (__b >> __dn))
109+ return false ;
110+ }
111+ }
112+ }
113+ return true ;
114+ }
115+
116+ template <class _Cp , bool _IC1, bool _IC2>
117+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_aligned (
118+ __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
119+ using _It = __bit_iterator<_Cp, _IC1>;
120+ using difference_type = typename _It::difference_type;
121+ using __storage_type = typename _It::__storage_type;
122+
123+ const int __bits_per_word = _It::__bits_per_word;
124+ difference_type __n = __last1 - __first1;
125+ if (__n > 0 ) {
126+ // do first word
127+ if (__first1.__ctz_ != 0 ) {
128+ unsigned __clz = __bits_per_word - __first1.__ctz_ ;
129+ difference_type __dn = std::min (static_cast <difference_type>(__clz), __n);
130+ __n -= __dn;
131+ __storage_type __m = (~__storage_type (0 ) << __first1.__ctz_ ) & (~__storage_type (0 ) >> (__clz - __dn));
132+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
133+ return false ;
134+ ++__first2.__seg_ ;
135+ ++__first1.__seg_ ;
136+ // __first1.__ctz_ = 0;
137+ // __first2.__ctz_ = 0;
138+ }
139+ // __first1.__ctz_ == 0;
140+ // __first2.__ctz_ == 0;
141+ // do middle words
142+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_ , ++__first2.__seg_ )
143+ if (*__first2.__seg_ != *__first1.__seg_ )
144+ return false ;
145+ // do last word
146+ if (__n > 0 ) {
147+ __storage_type __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
148+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
149+ return false ;
150+ }
151+ }
152+ return true ;
153+ }
154+
155+ template <class _Cp ,
156+ bool _IC1,
157+ bool _IC2,
158+ class _BinaryPredicate ,
159+ __enable_if_t <std::is_same<_BinaryPredicate, __equal_to>::value, int > = 0 >
160+ [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
161+ __bit_iterator<_Cp, _IC1> __first1,
162+ __bit_iterator<_Cp, _IC1> __last1,
163+ __bit_iterator<_Cp, _IC2> __first2,
164+ _BinaryPredicate) {
165+ if (__first1.__ctz_ == __first2.__ctz_ )
166+ return std::__equal_aligned (__first1, __last1, __first2);
167+ return std::__equal_unaligned (__first1, __last1, __first2);
168+ }
169+
36170template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
37171[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
38172 _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) {
@@ -94,6 +228,32 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&,
94228 return std::__constexpr_memcmp_equal (__first1, __first2, __element_count (__last1 - __first1));
95229}
96230
231+ template <class _Cp ,
232+ bool _IC1,
233+ bool _IC2,
234+ class _Pred ,
235+ class _Proj1 ,
236+ class _Proj2 ,
237+ __enable_if_t <(is_same<_Pred, __equal_to>::value
238+ # if _LIBCPP_STD_VER >= 20
239+ || is_same<_Pred, ranges::equal_to>::value
240+ # endif
241+ ) &&
242+ __desugars_to_v<__equal_tag, _Pred, bool , bool > && __is_identity<_Proj1>::value &&
243+ __is_identity<_Proj2>::value,
244+ int > = 0 >
245+ [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl (
246+ __bit_iterator<_Cp, _IC1> __first1,
247+ __bit_iterator<_Cp, _IC1> __last1,
248+ __bit_iterator<_Cp, _IC2> __first2,
249+ __bit_iterator<_Cp, _IC2>,
250+ _Pred&,
251+ _Proj1&,
252+ _Proj2&) {
253+ __equal_to __pred;
254+ return std::__equal_iter_impl (__first1, __last1, __first2, __pred);
255+ }
256+
97257template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
98258[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
99259equal (_InputIterator1 __first1,
0 commit comments