File indexing completed on 2025-09-17 08:53:27
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
0009 #define CATCH_IS_PERMUTATION_HPP_INCLUDED
0010
0011 #include <algorithm>
0012 #include <iterator>
0013
0014 namespace Catch {
0015 namespace Detail {
0016
0017 template <typename ForwardIter,
0018 typename Sentinel,
0019 typename T,
0020 typename Comparator>
0021 constexpr
0022 ForwardIter find_sentinel( ForwardIter start,
0023 Sentinel sentinel,
0024 T const& value,
0025 Comparator cmp ) {
0026 while ( start != sentinel ) {
0027 if ( cmp( *start, value ) ) { break; }
0028 ++start;
0029 }
0030 return start;
0031 }
0032
0033 template <typename ForwardIter,
0034 typename Sentinel,
0035 typename T,
0036 typename Comparator>
0037 constexpr
0038 std::ptrdiff_t count_sentinel( ForwardIter start,
0039 Sentinel sentinel,
0040 T const& value,
0041 Comparator cmp ) {
0042 std::ptrdiff_t count = 0;
0043 while ( start != sentinel ) {
0044 if ( cmp( *start, value ) ) { ++count; }
0045 ++start;
0046 }
0047 return count;
0048 }
0049
0050 template <typename ForwardIter, typename Sentinel>
0051 constexpr
0052 std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
0053 std::ptrdiff_t>
0054 sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
0055 std::ptrdiff_t dist = 0;
0056 while ( iter != sentinel ) {
0057 ++iter;
0058 ++dist;
0059 }
0060 return dist;
0061 }
0062
0063 template <typename ForwardIter>
0064 constexpr std::ptrdiff_t sentinel_distance( ForwardIter first,
0065 ForwardIter last ) {
0066 return std::distance( first, last );
0067 }
0068
0069 template <typename ForwardIter1,
0070 typename Sentinel1,
0071 typename ForwardIter2,
0072 typename Sentinel2,
0073 typename Comparator>
0074 constexpr bool check_element_counts( ForwardIter1 first_1,
0075 const Sentinel1 end_1,
0076 ForwardIter2 first_2,
0077 const Sentinel2 end_2,
0078 Comparator cmp ) {
0079 auto cursor = first_1;
0080 while ( cursor != end_1 ) {
0081 if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
0082 cursor ) {
0083
0084 const auto count_in_range_2 =
0085 count_sentinel( first_2, end_2, *cursor, cmp );
0086
0087
0088 if ( count_in_range_2 == 0 ) { return false; }
0089
0090 const auto count_in_range_1 =
0091 count_sentinel( cursor, end_1, *cursor, cmp );
0092 if ( count_in_range_1 != count_in_range_2 ) {
0093 return false;
0094 }
0095 }
0096
0097 ++cursor;
0098 }
0099
0100 return true;
0101 }
0102
0103 template <typename ForwardIter1,
0104 typename Sentinel1,
0105 typename ForwardIter2,
0106 typename Sentinel2,
0107 typename Comparator>
0108 constexpr bool is_permutation( ForwardIter1 first_1,
0109 const Sentinel1 end_1,
0110 ForwardIter2 first_2,
0111 const Sentinel2 end_2,
0112 Comparator cmp ) {
0113
0114
0115
0116 while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
0117 ++first_1;
0118 ++first_2;
0119 }
0120
0121
0122 if (first_1 == end_1 || first_2 == end_2) {
0123 return first_1 == end_1 && first_2 == end_2;
0124 }
0125
0126
0127 auto dist_1 = sentinel_distance( first_1, end_1 );
0128 auto dist_2 = sentinel_distance( first_2, end_2 );
0129
0130 if (dist_1 != dist_2) { return false; }
0131
0132
0133
0134
0135 return check_element_counts( first_1, end_1, first_2, end_2, cmp );
0136 }
0137
0138 }
0139 }
0140
0141 #endif