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 < __functional/ranges_operations.h>
19+ #include < __fwd/bit_reference.h>
1720#include < __iterator/distance.h>
1821#include < __iterator/iterator_traits.h>
22+ #include < __memory/pointer_traits.h>
1923#include < __string/constexpr_c_functions.h>
2024#include < __type_traits/desugars_to.h>
2125#include < __type_traits/enable_if.h>
2226#include < __type_traits/invoke.h>
2327#include < __type_traits/is_equality_comparable.h>
28+ #include < __type_traits/is_same.h>
2429#include < __type_traits/is_volatile.h>
2530#include < __utility/move.h>
2631
@@ -33,6 +38,132 @@ _LIBCPP_PUSH_MACROS
3338
3439_LIBCPP_BEGIN_NAMESPACE_STD
3540
41+ template <class _Cp , bool _IC1, bool _IC2>
42+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_unaligned (
43+ __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
44+ using _It = __bit_iterator<_Cp, _IC1>;
45+ using difference_type = typename _It::difference_type;
46+ using __storage_type = typename _It::__storage_type;
47+
48+ const int __bits_per_word = _It::__bits_per_word;
49+ difference_type __n = __last1 - __first1;
50+ if (__n > 0 ) {
51+ // do first word
52+ if (__first1.__ctz_ != 0 ) {
53+ unsigned __clz_f = __bits_per_word - __first1.__ctz_ ;
54+ difference_type __dn = std::min (static_cast <difference_type>(__clz_f), __n);
55+ __n -= __dn;
56+ __storage_type __m = (~__storage_type (0 ) << __first1.__ctz_ ) & (~__storage_type (0 ) >> (__clz_f - __dn));
57+ __storage_type __b = *__first1.__seg_ & __m;
58+ unsigned __clz_r = __bits_per_word - __first2.__ctz_ ;
59+ __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
60+ __m = (~__storage_type (0 ) << __first2.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __ddn));
61+ if (__first2.__ctz_ > __first1.__ctz_ ) {
62+ if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_ )))
63+ return false ;
64+ } else {
65+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_ )))
66+ return false ;
67+ }
68+ __first2.__seg_ += (__ddn + __first2.__ctz_ ) / __bits_per_word;
69+ __first2.__ctz_ = static_cast <unsigned >((__ddn + __first2.__ctz_ ) % __bits_per_word);
70+ __dn -= __ddn;
71+ if (__dn > 0 ) {
72+ __m = ~__storage_type (0 ) >> (__bits_per_word - __dn);
73+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn)))
74+ return false ;
75+ __first2.__ctz_ = static_cast <unsigned >(__dn);
76+ }
77+ ++__first1.__seg_ ;
78+ // __first1.__ctz_ = 0;
79+ }
80+ // __first1.__ctz_ == 0;
81+ // do middle words
82+ unsigned __clz_r = __bits_per_word - __first2.__ctz_ ;
83+ __storage_type __m = ~__storage_type (0 ) << __first2.__ctz_ ;
84+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_ ) {
85+ __storage_type __b = *__first1.__seg_ ;
86+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_ ))
87+ return false ;
88+ ++__first2.__seg_ ;
89+ if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r))
90+ return false ;
91+ }
92+ // do last word
93+ if (__n > 0 ) {
94+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
95+ __storage_type __b = *__first1.__seg_ & __m;
96+ __storage_type __dn = std::min (__n, static_cast <difference_type>(__clz_r));
97+ __m = (~__storage_type (0 ) << __first2.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __dn));
98+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_ ))
99+ return false ;
100+ __first2.__seg_ += (__dn + __first2.__ctz_ ) / __bits_per_word;
101+ __first2.__ctz_ = static_cast <unsigned >((__dn + __first2.__ctz_ ) % __bits_per_word);
102+ __n -= __dn;
103+ if (__n > 0 ) {
104+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
105+ if ((*__first2.__seg_ & __m) != (__b >> __dn))
106+ return false ;
107+ }
108+ }
109+ }
110+ return true ;
111+ }
112+
113+ template <class _Cp , bool _IC1, bool _IC2>
114+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_aligned (
115+ __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
116+ using _It = __bit_iterator<_Cp, _IC1>;
117+ using difference_type = typename _It::difference_type;
118+ using __storage_type = typename _It::__storage_type;
119+
120+ const int __bits_per_word = _It::__bits_per_word;
121+ difference_type __n = __last1 - __first1;
122+ if (__n > 0 ) {
123+ // do first word
124+ if (__first1.__ctz_ != 0 ) {
125+ unsigned __clz = __bits_per_word - __first1.__ctz_ ;
126+ difference_type __dn = std::min (static_cast <difference_type>(__clz), __n);
127+ __n -= __dn;
128+ __storage_type __m = (~__storage_type (0 ) << __first1.__ctz_ ) & (~__storage_type (0 ) >> (__clz - __dn));
129+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
130+ return false ;
131+ ++__first2.__seg_ ;
132+ ++__first1.__seg_ ;
133+ // __first1.__ctz_ = 0;
134+ // __first2.__ctz_ = 0;
135+ }
136+ // __first1.__ctz_ == 0;
137+ // __first2.__ctz_ == 0;
138+ // do middle words
139+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_ , ++__first2.__seg_ )
140+ if (*__first2.__seg_ != *__first1.__seg_ )
141+ return false ;
142+ // do last word
143+ if (__n > 0 ) {
144+ __storage_type __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
145+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
146+ return false ;
147+ }
148+ }
149+ return true ;
150+ }
151+
152+ template <class _Cp ,
153+ bool _IC1,
154+ bool _IC2,
155+ class _BinaryPredicate ,
156+ __enable_if_t <std::is_same<_BinaryPredicate, __equal_to>::value, int > = 0 >
157+ [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
158+ __bit_iterator<_Cp, _IC1> __first1,
159+ __bit_iterator<_Cp, _IC1> __last1,
160+ __bit_iterator<_Cp, _IC2> __first2,
161+ _BinaryPredicate) {
162+ if (__first1.__ctz_ == __first2.__ctz_ )
163+ return std::__equal_aligned (__first1, __last1, __first2);
164+ return std::__equal_unaligned (__first1, __last1, __first2);
165+ }
166+
36167template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
37168[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
38169 _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) {
@@ -94,6 +225,26 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&,
94225 return std::__constexpr_memcmp_equal (__first1, __first2, __element_count (__last1 - __first1));
95226}
96227
228+ template <class _Cp ,
229+ bool _IC1,
230+ bool _IC2,
231+ class _Pred ,
232+ class _Proj1 ,
233+ class _Proj2 ,
234+ __enable_if_t <(is_same<_Pred, ranges::equal_to>::value || is_same<_Pred, __equal_to>::value) &&
235+ __is_identity<_Proj1>::value && __is_identity<_Proj2>::value,
236+ int > = 0 >
237+ [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl (
238+ __bit_iterator<_Cp, _IC1> __first1,
239+ __bit_iterator<_Cp, _IC1> __last1,
240+ __bit_iterator<_Cp, _IC2> __first2,
241+ __bit_iterator<_Cp, _IC2>,
242+ _Pred&,
243+ _Proj1&,
244+ _Proj2&) {
245+ return std::__equal_iter_impl (__first1, __last1, __first2, __equal_to ());
246+ }
247+
97248template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
98249[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
99250equal (_InputIterator1 __first1,
0 commit comments