11
11
#define _LIBCPP___ALGORITHM_EQUAL_H
12
12
13
13
#include < __algorithm/comp.h>
14
+ #include < __algorithm/min.h>
14
15
#include < __algorithm/unwrap_iter.h>
15
16
#include < __config>
16
17
#include < __functional/identity.h>
18
+ #include < __fwd/bit_reference.h>
17
19
#include < __iterator/distance.h>
18
20
#include < __iterator/iterator_traits.h>
21
+ #include < __memory/pointer_traits.h>
19
22
#include < __string/constexpr_c_functions.h>
20
23
#include < __type_traits/desugars_to.h>
21
24
#include < __type_traits/enable_if.h>
22
25
#include < __type_traits/invoke.h>
23
26
#include < __type_traits/is_equality_comparable.h>
27
+ #include < __type_traits/is_same.h>
24
28
#include < __type_traits/is_volatile.h>
25
29
#include < __utility/move.h>
26
30
31
+ #if _LIBCPP_STD_VER >= 20
32
+ # include < __functional/ranges_operations.h>
33
+ #endif
34
+
27
35
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
28
36
# pragma GCC system_header
29
37
#endif
@@ -33,6 +41,136 @@ _LIBCPP_PUSH_MACROS
33
41
34
42
_LIBCPP_BEGIN_NAMESPACE_STD
35
43
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
+
36
174
template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
37
175
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
38
176
_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) {
@@ -94,6 +232,28 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&,
94
232
return std::__constexpr_memcmp_equal (__first1, __first2, __element_count (__last1 - __first1));
95
233
}
96
234
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
+
97
257
template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
98
258
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
99
259
equal (_InputIterator1 __first1,
0 commit comments