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,132 @@ _LIBCPP_PUSH_MACROS
33
41
34
42
_LIBCPP_BEGIN_NAMESPACE_STD
35
43
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
+
36
170
template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
37
171
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl (
38
172
_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) {
@@ -94,6 +228,31 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&,
94
228
return std::__constexpr_memcmp_equal (__first1, __first2, __element_count (__last1 - __first1));
95
229
}
96
230
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
+ return std::__equal_iter_impl (__first1, __last1, __first2, __equal_to ());
254
+ }
255
+
97
256
template <class _InputIterator1 , class _InputIterator2 , class _BinaryPredicate >
98
257
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
99
258
equal (_InputIterator1 __first1,
0 commit comments