annotate DEPENDENCIES/generic/include/boost/algorithm/cxx11/is_permutation.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 /*
Chris@16 2 Copyright (c) Marshall Clow 2011-2012.
Chris@16 3
Chris@16 4 Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6 */
Chris@16 7
Chris@16 8 /// \file is_permutation.hpp
Chris@16 9 /// \brief Is a sequence a permutation of another sequence
Chris@16 10 /// \author Marshall Clow
Chris@16 11
Chris@101 12 #ifndef BOOST_ALGORITHM_IS_PERMUTATION11_HPP
Chris@101 13 #define BOOST_ALGORITHM_IS_PERMUTATION11_HPP
Chris@16 14
Chris@16 15 #include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
Chris@16 16 #include <utility> // for std::make_pair
Chris@16 17 #include <functional> // for std::equal_to
Chris@16 18 #include <iterator>
Chris@16 19
Chris@16 20 #include <boost/range/begin.hpp>
Chris@16 21 #include <boost/range/end.hpp>
Chris@16 22 #include <boost/utility/enable_if.hpp>
Chris@16 23 #include <boost/type_traits/is_same.hpp>
Chris@16 24
Chris@16 25 namespace boost { namespace algorithm {
Chris@16 26
Chris@16 27 /// \cond DOXYGEN_HIDE
Chris@16 28 namespace detail {
Chris@16 29 template <typename Predicate, typename Iterator>
Chris@16 30 struct value_predicate {
Chris@16 31 value_predicate ( Predicate p, Iterator it ) : p_ ( p ), it_ ( it ) {}
Chris@16 32
Chris@16 33 template <typename T1>
Chris@16 34 bool operator () ( const T1 &t1 ) const { return p_ ( *it_, t1 ); }
Chris@16 35 private:
Chris@16 36 Predicate p_;
Chris@16 37 Iterator it_;
Chris@16 38 };
Chris@16 39
Chris@16 40 // Preconditions:
Chris@16 41 // 1. The sequences are the same length
Chris@16 42 // 2. Any common elements on the front have been removed (not necessary for correctness, just for performance)
Chris@16 43 template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
Chris@16 44 bool is_permutation_inner ( ForwardIterator1 first1, ForwardIterator1 last1,
Chris@16 45 ForwardIterator2 first2, ForwardIterator2 last2,
Chris@16 46 BinaryPredicate p ) {
Chris@16 47 // for each unique value in the sequence [first1,last1), count how many times
Chris@16 48 // it occurs, and make sure it occurs the same number of times in [first2, last2)
Chris@16 49 for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) {
Chris@16 50 value_predicate<BinaryPredicate, ForwardIterator1> pred ( p, iter );
Chris@16 51
Chris@16 52 /* For each value we haven't seen yet... */
Chris@16 53 if ( std::find_if ( first1, iter, pred ) == iter ) {
Chris@16 54 std::size_t dest_count = std::count_if ( first2, last2, pred );
Chris@16 55 if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred ))
Chris@16 56 return false;
Chris@16 57 }
Chris@16 58 }
Chris@16 59
Chris@16 60 return true;
Chris@16 61 }
Chris@16 62
Chris@16 63 template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
Chris@16 64 bool is_permutation_tag ( ForwardIterator1 first1, ForwardIterator1 last1,
Chris@16 65 ForwardIterator2 first2, ForwardIterator2 last2,
Chris@16 66 BinaryPredicate p,
Chris@16 67 std::forward_iterator_tag, std::forward_iterator_tag ) {
Chris@16 68
Chris@16 69 // Skip the common prefix (if any)
Chris@16 70 while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) {
Chris@16 71 ++first1;
Chris@16 72 ++first2;
Chris@16 73 }
Chris@16 74 if ( first1 != last1 && first2 != last2 )
Chris@16 75 return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2,
Chris@16 76 std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ());
Chris@16 77 return first1 == last1 && first2 == last2;
Chris@16 78 }
Chris@16 79
Chris@16 80 template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate>
Chris@16 81 bool is_permutation_tag ( RandomAccessIterator1 first1, RandomAccessIterator1 last1,
Chris@16 82 RandomAccessIterator2 first2, RandomAccessIterator2 last2,
Chris@16 83 BinaryPredicate p,
Chris@16 84 std::random_access_iterator_tag, std::random_access_iterator_tag ) {
Chris@16 85 // Cheap check
Chris@16 86 if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 ))
Chris@16 87 return false;
Chris@16 88 // Skip the common prefix (if any)
Chris@16 89 while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) {
Chris@16 90 ++first1;
Chris@16 91 ++first2;
Chris@16 92 }
Chris@16 93
Chris@16 94 if ( first1 != last1 && first2 != last2 )
Chris@16 95 return is_permutation_inner (first1, last1, first2, last2, p);
Chris@16 96 return first1 == last1 && first2 == last2;
Chris@16 97 }
Chris@16 98
Chris@16 99 }
Chris@16 100 /// \endcond
Chris@16 101
Chris@16 102 /// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p )
Chris@16 103 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
Chris@16 104 ///
Chris@16 105 /// \param first1 The start of the input sequence
Chris@16 106 /// \param last1 One past the end of the input sequence
Chris@16 107 /// \param first2 The start of the second sequence
Chris@16 108 /// \param p The predicate to compare elements with
Chris@16 109 ///
Chris@16 110 /// \note This function is part of the C++2011 standard library.
Chris@16 111 /// We will use the standard one if it is available,
Chris@16 112 /// otherwise we have our own implementation.
Chris@16 113 template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
Chris@16 114 bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
Chris@16 115 ForwardIterator2 first2, BinaryPredicate p )
Chris@16 116 {
Chris@16 117 // Skip the common prefix (if any)
Chris@16 118 std::pair<ForwardIterator1, ForwardIterator2> eq = std::mismatch (first1, last1, first2, p);
Chris@16 119 first1 = eq.first;
Chris@16 120 first2 = eq.second;
Chris@16 121 if ( first1 != last1 ) {
Chris@16 122 // Create last2
Chris@16 123 ForwardIterator2 last2 = first2;
Chris@16 124 std::advance ( last2, std::distance (first1, last1));
Chris@16 125 return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, p );
Chris@16 126 }
Chris@16 127
Chris@16 128 return true;
Chris@16 129 }
Chris@16 130
Chris@16 131 /// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 )
Chris@16 132 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
Chris@16 133 ///
Chris@16 134 /// \param first1 The start of the input sequence
Chris@16 135 /// \param last2 One past the end of the input sequence
Chris@16 136 /// \param first2 The start of the second sequence
Chris@16 137 /// \note This function is part of the C++2011 standard library.
Chris@16 138 /// We will use the standard one if it is available,
Chris@16 139 /// otherwise we have our own implementation.
Chris@16 140 template< class ForwardIterator1, class ForwardIterator2 >
Chris@16 141 bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2 )
Chris@16 142 {
Chris@16 143 // How should I deal with the idea that ForwardIterator1::value_type
Chris@16 144 // and ForwardIterator2::value_type could be different? Define my own comparison predicate?
Chris@16 145 // Skip the common prefix (if any)
Chris@16 146 std::pair<ForwardIterator1, ForwardIterator2> eq = std::mismatch (first1, last1, first2 );
Chris@16 147 first1 = eq.first;
Chris@16 148 first2 = eq.second;
Chris@16 149 if ( first1 != last1 ) {
Chris@16 150 // Create last2
Chris@16 151 ForwardIterator2 last2 = first2;
Chris@16 152 std::advance ( last2, std::distance (first1, last1));
Chris@16 153 return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2,
Chris@16 154 std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ());
Chris@16 155 }
Chris@16 156 return true;
Chris@16 157 }
Chris@16 158
Chris@16 159
Chris@16 160 /// \fn is_permutation ( const Range &r, ForwardIterator first2 )
Chris@16 161 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
Chris@16 162 ///
Chris@16 163 /// \param r The input range
Chris@16 164 /// \param first2 The start of the second sequence
Chris@16 165 template <typename Range, typename ForwardIterator>
Chris@16 166 bool is_permutation ( const Range &r, ForwardIterator first2 )
Chris@16 167 {
Chris@16 168 return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2 );
Chris@16 169 }
Chris@16 170
Chris@16 171 /// \fn is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
Chris@16 172 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
Chris@16 173 ///
Chris@16 174 /// \param r The input range
Chris@16 175 /// \param first2 The start of the second sequence
Chris@16 176 /// \param pred The predicate to compare elements with
Chris@16 177 ///
Chris@16 178 // Disable this template when the first two parameters are the same type
Chris@16 179 // That way the non-range version will be chosen.
Chris@16 180 template <typename Range, typename ForwardIterator, typename BinaryPredicate>
Chris@16 181 typename boost::disable_if_c<boost::is_same<Range, ForwardIterator>::value, bool>::type
Chris@16 182 is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
Chris@16 183 {
Chris@16 184 return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2, pred );
Chris@16 185 }
Chris@16 186
Chris@16 187 }}
Chris@16 188
Chris@101 189 #endif // BOOST_ALGORITHM_IS_PERMUTATION11_HPP