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,136 @@ _LIBCPP_PUSH_MACROS
3341
3442_LIBCPP_BEGIN_NAMESPACE_STD
3543
44+ template <class _Cp , bool _IsConst1, bool _IsConst2>
45+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool
46+ __equal_unaligned (__bit_iterator<_Cp, _IsConst1> __first1,
47+ __bit_iterator<_Cp, _IsConst1> __last1,
48+ __bit_iterator<_Cp, _IsConst2> __first2) {
49+ using _It = __bit_iterator<_Cp, _IsConst1>;
50+ using difference_type = typename _It::difference_type;
51+ using __storage_type = typename _It::__storage_type;
52+
53+ const int __bits_per_word = _It::__bits_per_word;
54+ difference_type __n = __last1 - __first1;
55+ if (__n > 0 ) {
56+ // do first word
57+ if (__first1.__ctz_ != 0 ) {
58+ unsigned __clz_f = __bits_per_word - __first1.__ctz_ ;
59+ difference_type __dn = std::min (static_cast <difference_type>(__clz_f), __n);
60+ __n -= __dn;
61+ __storage_type __m = (~__storage_type (0 ) << __first1.__ctz_ ) & (~__storage_type (0 ) >> (__clz_f - __dn));
62+ __storage_type __b = *__first1.__seg_ & __m;
63+ unsigned __clz_r = __bits_per_word - __first2.__ctz_ ;
64+ __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
65+ __m = (~__storage_type (0 ) << __first2.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __ddn));
66+ if (__first2.__ctz_ > __first1.__ctz_ ) {
67+ if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_ )))
68+ return false ;
69+ } else {
70+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_ )))
71+ return false ;
72+ }
73+ __first2.__seg_ += (__ddn + __first2.__ctz_ ) / __bits_per_word;
74+ __first2.__ctz_ = static_cast <unsigned >((__ddn + __first2.__ctz_ ) % __bits_per_word);
75+ __dn -= __ddn;
76+ if (__dn > 0 ) {
77+ __m = ~__storage_type (0 ) >> (__bits_per_word - __dn);
78+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn)))
79+ return false ;
80+ __first2.__ctz_ = static_cast <unsigned >(__dn);
81+ }
82+ ++__first1.__seg_ ;
83+ // __first1.__ctz_ = 0;
84+ }
85+ // __first1.__ctz_ == 0;
86+ // do middle words
87+ unsigned __clz_r = __bits_per_word - __first2.__ctz_ ;
88+ __storage_type __m = ~__storage_type (0 ) << __first2.__ctz_ ;
89+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_ ) {
90+ __storage_type __b = *__first1.__seg_ ;
91+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_ ))
92+ return false ;
93+ ++__first2.__seg_ ;
94+ if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r))
95+ return false ;
96+ }
97+ // do last word
98+ if (__n > 0 ) {
99+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
100+ __storage_type __b = *__first1.__seg_ & __m;
101+ __storage_type __dn = std::min (__n, static_cast <difference_type>(__clz_r));
102+ __m = (~__storage_type (0 ) << __first2.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __dn));
103+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_ ))
104+ return false ;
105+ __first2.__seg_ += (__dn + __first2.__ctz_ ) / __bits_per_word;
106+ __first2.__ctz_ = static_cast <unsigned >((__dn + __first2.__ctz_ ) % __bits_per_word);
107+ __n -= __dn;
108+ if (__n > 0 ) {
109+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
110+ if ((*__first2.__seg_ & __m) != (__b >> __dn))
111+ return false ;
112+ }
113+ }
114+ }
115+ return true ;
116+ }
117+
118+ template <class _Cp , bool _IsConst1, bool _IsConst2>
119+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool
120+ __equal_aligned (__bit_iterator<_Cp, _IsConst1> __first1,
121+ __bit_iterator<_Cp, _IsConst1> __last1,
122+ __bit_iterator<_Cp, _IsConst2> __first2) {
123+ using _It = __bit_iterator<_Cp, _IsConst1>;
124+ using difference_type = typename _It::difference_type;
125+ using __storage_type = typename _It::__storage_type;
126+
127+ const int __bits_per_word = _It::__bits_per_word;
128+ difference_type __n = __last1 - __first1;
129+ if (__n > 0 ) {
130+ // do first word
131+ if (__first1.__ctz_ != 0 ) {
132+ unsigned __clz = __bits_per_word - __first1.__ctz_ ;
133+ difference_type __dn = std::min (static_cast <difference_type>(__clz), __n);
134+ __n -= __dn;
135+ __storage_type __m = (~__storage_type (0 ) << __first1.__ctz_ ) & (~__storage_type (0 ) >> (__clz - __dn));
136+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
137+ return false ;
138+ ++__first2.__seg_ ;
139+ ++__first1.__seg_ ;
140+ // __first1.__ctz_ = 0;
141+ // __first2.__ctz_ = 0;
142+ }
143+ // __first1.__ctz_ == 0;
144+ // __first2.__ctz_ == 0;
145+ // do middle words
146+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_ , ++__first2.__seg_ )
147+ if (*__first2.__seg_ != *__first1.__seg_ )
148+ return false ;
149+ // do last word
150+ if (__n > 0 ) {
151+ __storage_type __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
152+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
153+ return false ;
154+ }
155+ }
156+ return true ;
157+ }
158+
159+ template <class _Cp ,
160+ bool _IsConst1,
161+ bool _IsConst2,
162+ class _BinaryPredicate ,
163+ __enable_if_t <__desugars_to_v<__equal_tag, _BinaryPredicate, bool , bool >, int > = 0 >
164+ [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
165+ __bit_iterator<_Cp, _IsConst1> __first1,
166+ __bit_iterator<_Cp, _IsConst1> __last1,
167+ __bit_iterator<_Cp, _IsConst2> __first2,
168+ _BinaryPredicate) {
169+ if (__first1.__ctz_ == __first2.__ctz_ )
170+ return std::__equal_aligned (__first1, __last1, __first2);
171+ return std::__equal_unaligned (__first1, __last1, __first2);
172+ }
173+
36174template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
37175[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
38176 _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) {
@@ -94,6 +232,28 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&,
94232 return std::__constexpr_memcmp_equal (__first1, __first2, __element_count (__last1 - __first1));
95233}
96234
235+ template <class _Cp ,
236+ bool _IsConst1,
237+ bool _IsConst2,
238+ class _Pred ,
239+ class _Proj1 ,
240+ class _Proj2 ,
241+ __enable_if_t <__desugars_to_v<__equal_tag, _Pred, bool , bool > && __is_identity<_Proj1>::value &&
242+ __is_identity<_Proj2>::value,
243+ int > = 0 >
244+ [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl (
245+ __bit_iterator<_Cp, _IsConst1> __first1,
246+ __bit_iterator<_Cp, _IsConst1> __last1,
247+ __bit_iterator<_Cp, _IsConst2> __first2,
248+ __bit_iterator<_Cp, _IsConst2>,
249+ _Pred&,
250+ _Proj1&,
251+ _Proj2&) {
252+ if (__first1.__ctz_ == __first2.__ctz_ )
253+ return std::__equal_aligned (__first1, __last1, __first2);
254+ return std::__equal_unaligned (__first1, __last1, __first2);
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