File indexing completed on 2026-05-03 08:13:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___CXX03___ALGORITHM_IS_PERMUTATION_H
0011 #define _LIBCPP___CXX03___ALGORITHM_IS_PERMUTATION_H
0012
0013 #include <__cxx03/__algorithm/comp.h>
0014 #include <__cxx03/__algorithm/iterator_operations.h>
0015 #include <__cxx03/__config>
0016 #include <__cxx03/__functional/identity.h>
0017 #include <__cxx03/__functional/invoke.h>
0018 #include <__cxx03/__iterator/concepts.h>
0019 #include <__cxx03/__iterator/distance.h>
0020 #include <__cxx03/__iterator/iterator_traits.h>
0021 #include <__cxx03/__iterator/next.h>
0022 #include <__cxx03/__type_traits/is_callable.h>
0023 #include <__cxx03/__utility/move.h>
0024
0025 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0026 # pragma GCC system_header
0027 #endif
0028
0029 _LIBCPP_PUSH_MACROS
0030 #include <__cxx03/__undef_macros>
0031
0032 _LIBCPP_BEGIN_NAMESPACE_STD
0033
0034 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class = void>
0035 struct _ConstTimeDistance : false_type {};
0036
0037 #if _LIBCPP_STD_VER >= 20
0038
0039 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2>
0040 struct _ConstTimeDistance<_Iter1,
0041 _Sent1,
0042 _Iter2,
0043 _Sent2,
0044 __enable_if_t< sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2> >>
0045 : true_type {};
0046
0047 #else
0048
0049 template <class _Iter1, class _Iter2>
0050 struct _ConstTimeDistance<
0051 _Iter1,
0052 _Iter1,
0053 _Iter2,
0054 _Iter2,
0055 __enable_if_t< is_same<typename iterator_traits<_Iter1>::iterator_category, random_access_iterator_tag>::value &&
0056 is_same<typename iterator_traits<_Iter2>::iterator_category, random_access_iterator_tag>::value > >
0057 : true_type {};
0058
0059 #endif
0060
0061
0062
0063
0064 template <class _AlgPolicy,
0065 class _Iter1,
0066 class _Sent1,
0067 class _Iter2,
0068 class _Sent2,
0069 class _Proj1,
0070 class _Proj2,
0071 class _Pred>
0072 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation_impl(
0073 _Iter1 __first1,
0074 _Sent1 __last1,
0075 _Iter2 __first2,
0076 _Sent2 __last2,
0077 _Pred&& __pred,
0078 _Proj1&& __proj1,
0079 _Proj2&& __proj2) {
0080 using _D1 = __iter_diff_t<_Iter1>;
0081
0082 for (auto __i = __first1; __i != __last1; ++__i) {
0083
0084 auto __match = __first1;
0085 for (; __match != __i; ++__match) {
0086 if (std::__invoke(__pred, std::__invoke(__proj1, *__match), std::__invoke(__proj1, *__i)))
0087 break;
0088 }
0089
0090 if (__match == __i) {
0091
0092 _D1 __c2 = 0;
0093 for (auto __j = __first2; __j != __last2; ++__j) {
0094 if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj2, *__j)))
0095 ++__c2;
0096 }
0097 if (__c2 == 0)
0098 return false;
0099
0100
0101 _D1 __c1 = 1;
0102 for (auto __j = _IterOps<_AlgPolicy>::next(__i); __j != __last1; ++__j) {
0103 if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj1, *__j)))
0104 ++__c1;
0105 }
0106 if (__c1 != __c2)
0107 return false;
0108 }
0109 }
0110
0111 return true;
0112 }
0113
0114
0115 template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _BinaryPredicate>
0116 _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
0117 _ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _BinaryPredicate&& __pred) {
0118
0119 for (; __first1 != __last1; ++__first1, (void)++__first2) {
0120 if (!__pred(*__first1, *__first2))
0121 break;
0122 }
0123
0124 if (__first1 == __last1)
0125 return true;
0126
0127
0128 using _D1 = __iter_diff_t<_ForwardIterator1>;
0129 _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
0130 if (__l1 == _D1(1))
0131 return false;
0132 auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1);
0133
0134 return std::__is_permutation_impl<_AlgPolicy>(
0135 std::move(__first1),
0136 std::move(__last1),
0137 std::move(__first2),
0138 std::move(__last2),
0139 __pred,
0140 __identity(),
0141 __identity());
0142 }
0143
0144
0145 template <class _AlgPolicy,
0146 class _Iter1,
0147 class _Sent1,
0148 class _Iter2,
0149 class _Sent2,
0150 class _Proj1,
0151 class _Proj2,
0152 class _Pred>
0153 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
0154 _Iter1 __first1,
0155 _Sent1 __last1,
0156 _Iter2 __first2,
0157 _Sent2 __last2,
0158 _Pred&& __pred,
0159 _Proj1&& __proj1,
0160 _Proj2&& __proj2,
0161 false_type) {
0162
0163 while (__first1 != __last1 && __first2 != __last2) {
0164 if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
0165 break;
0166 ++__first1;
0167 ++__first2;
0168 }
0169
0170 if (__first1 == __last1)
0171 return __first2 == __last2;
0172 if (__first2 == __last2)
0173 return false;
0174
0175 using _D1 = __iter_diff_t<_Iter1>;
0176 _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
0177
0178 using _D2 = __iter_diff_t<_Iter2>;
0179 _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2);
0180 if (__l1 != __l2)
0181 return false;
0182
0183 return std::__is_permutation_impl<_AlgPolicy>(
0184 std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2);
0185 }
0186
0187
0188 template <class _AlgPolicy,
0189 class _Iter1,
0190 class _Sent1,
0191 class _Iter2,
0192 class _Sent2,
0193 class _Proj1,
0194 class _Proj2,
0195 class _Pred>
0196 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
0197 _Iter1 __first1,
0198 _Sent1 __last1,
0199 _Iter2 __first2,
0200 _Sent2 __last2,
0201 _Pred&& __pred,
0202 _Proj1&& __proj1,
0203 _Proj2&& __proj2,
0204 true_type) {
0205 if (std::distance(__first1, __last1) != std::distance(__first2, __last2))
0206 return false;
0207 return std::__is_permutation<_AlgPolicy>(
0208 std::move(__first1),
0209 std::move(__last1),
0210 std::move(__first2),
0211 std::move(__last2),
0212 __pred,
0213 __proj1,
0214 __proj2,
0215 false_type());
0216 }
0217
0218
0219 template <class _AlgPolicy,
0220 class _Iter1,
0221 class _Sent1,
0222 class _Iter2,
0223 class _Sent2,
0224 class _Proj1,
0225 class _Proj2,
0226 class _Pred>
0227 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
0228 _Iter1 __first1,
0229 _Sent1 __last1,
0230 _Iter2 __first2,
0231 _Sent2 __last2,
0232 _Pred&& __pred,
0233 _Proj1&& __proj1,
0234 _Proj2&& __proj2) {
0235 return std::__is_permutation<_AlgPolicy>(
0236 std::move(__first1),
0237 std::move(__last1),
0238 std::move(__first2),
0239 std::move(__last2),
0240 __pred,
0241 __proj1,
0242 __proj2,
0243 _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>());
0244 }
0245
0246
0247
0248
0249 template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
0250 _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
0251 _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __pred) {
0252 static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
0253 "The predicate has to be callable");
0254
0255 return std::__is_permutation<_ClassicAlgPolicy>(std::move(__first1), std::move(__last1), std::move(__first2), __pred);
0256 }
0257
0258
0259 template <class _ForwardIterator1, class _ForwardIterator2>
0260 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
0261 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
0262 return std::is_permutation(__first1, __last1, __first2, __equal_to());
0263 }
0264
0265 #if _LIBCPP_STD_VER >= 14
0266
0267
0268 template <class _ForwardIterator1, class _ForwardIterator2>
0269 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
0270 _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
0271 return std::__is_permutation<_ClassicAlgPolicy>(
0272 std::move(__first1),
0273 std::move(__last1),
0274 std::move(__first2),
0275 std::move(__last2),
0276 __equal_to(),
0277 __identity(),
0278 __identity());
0279 }
0280
0281
0282 template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
0283 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
0284 _ForwardIterator1 __first1,
0285 _ForwardIterator1 __last1,
0286 _ForwardIterator2 __first2,
0287 _ForwardIterator2 __last2,
0288 _BinaryPredicate __pred) {
0289 static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
0290 "The predicate has to be callable");
0291
0292 return std::__is_permutation<_ClassicAlgPolicy>(
0293 std::move(__first1),
0294 std::move(__last1),
0295 std::move(__first2),
0296 std::move(__last2),
0297 __pred,
0298 __identity(),
0299 __identity());
0300 }
0301
0302 #endif
0303
0304 _LIBCPP_END_NAMESPACE_STD
0305
0306 _LIBCPP_POP_MACROS
0307
0308 #endif