From b9d89c559b2e6ad8abbab3dddf1364d08218579b Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 20 May 2013 15:37:50 +0000 Subject: [PATCH] Better 'is_permutation' implementation, tests [SVN r84389] --- .../boost/algorithm/cxx11/is_permutation.hpp | 159 +++++++++++-- .../boost/algorithm/cxx14/is_permutation.hpp | 130 ----------- test/equal_test.cpp | 159 ++++++------- test/is_permutation_test1.cpp | 87 ++++++- test/mismatch_test.cpp | 220 +++++++++--------- 5 files changed, 414 insertions(+), 341 deletions(-) delete mode 100644 include/boost/algorithm/cxx14/is_permutation.hpp diff --git a/include/boost/algorithm/cxx11/is_permutation.hpp b/include/boost/algorithm/cxx11/is_permutation.hpp index b30166c..3eff5ce 100644 --- a/include/boost/algorithm/cxx11/is_permutation.hpp +++ b/include/boost/algorithm/cxx11/is_permutation.hpp @@ -24,10 +24,6 @@ namespace boost { namespace algorithm { -#if __cplusplus >= 201103L -// Use the C++11 versions of is_permutation if it is available -using std::is_permutation; // Section 25.2.12 -#else /// \cond DOXYGEN_HIDE namespace detail { template @@ -37,18 +33,82 @@ namespace detail { template bool operator () ( const T1 &t1 ) const { return p_ ( *it_, t1 ); } private: - Predicate &p_; + Predicate p_; Iterator it_; }; + +// Preconditions: +// 1. The sequences are the same length +// 2. Any common elements on the front have been removed (not necessary for correctness, just for performance) + template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > + bool is_permutation_inner ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate p ) { + // for each unique value in the sequence [first1,last1), count how many times + // it occurs, and make sure it occurs the same number of times in [first2, last2) + for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) { + value_predicate pred ( p, iter ); + + /* For each value we haven't seen yet... */ + if ( std::find_if ( first1, iter, pred ) == iter ) { + std::size_t dest_count = std::count_if ( first2, last2, pred ); + if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred )) + return false; + } + } + + return true; + } + + template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> + bool is_permutation_tag ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate p, + std::forward_iterator_tag, std::forward_iterator_tag ) { + + // Skip the common prefix (if any) + while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) { + ++first1; + ++first2; + } + if ( first1 != last1 && first2 != last2 ) + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, + std::equal_to::value_type> ()); + return first1 == last1 && first2 == last2; + } + + template + bool is_permutation_tag ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, + RandomAccessIterator2 first2, RandomAccessIterator2 last2, + BinaryPredicate p, + std::random_access_iterator_tag, std::random_access_iterator_tag ) { + // Cheap check + if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 )) + return false; + // Skip the common prefix (if any) + while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) { + ++first1; + ++first2; + } + + if ( first1 != last1 && first2 != last2 ) + return is_permutation_inner (first1, last1, first2, last2, p); + return first1 == last1 && first2 == last2; + } + } /// \endcond +#if __cplusplus >= 201103L +// Use the C++11 versions of is_permutation if it is available +using std::is_permutation; // Section 25.2.12 +#else /// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p ) /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 /// -/// \param first The start of the input sequence -/// \param last One past the end of the input sequence +/// \param first1 The start of the input sequence +/// \param last1 One past the end of the input sequence /// \param first2 The start of the second sequence /// \param p The predicate to compare elements with /// @@ -67,19 +127,7 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, // Create last2 ForwardIterator2 last2 = first2; std::advance ( last2, std::distance (first1, last1)); - - // for each unique value in the sequence [first1,last1), count how many times - // it occurs, and make sure it occurs the same number of times in [first2, last2) - for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) { - detail::value_predicate pred ( p, iter ); - - /* For each value we haven't seen yet... */ - if ( std::find_if ( first1, iter, pred ) == iter ) { - std::size_t dest_count = std::count_if ( first2, last2, pred ); - if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred )) - return false; - } - } + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, p ); } return true; @@ -88,23 +136,84 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, /// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 ) /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 /// -/// \param first The start of the input sequence -/// \param last One past the end of the input sequence +/// \param first1 The start of the input sequence +/// \param last2 One past the end of the input sequence /// \param first2 The start of the second sequence /// \note This function is part of the C++2011 standard library. /// We will use the standard one if it is available, /// otherwise we have our own implementation. template< class ForwardIterator1, class ForwardIterator2 > -bool is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 ) +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2 ) { // How should I deal with the idea that ForwardIterator1::value_type // and ForwardIterator2::value_type could be different? Define my own comparison predicate? - return boost::algorithm::is_permutation ( first, last, first2, - std::equal_to::value_type> ()); +// Skip the common prefix (if any) + std::pair eq = std::mismatch (first1, last1, first2 ); + first1 = eq.first; + first2 = eq.second; + if ( first1 != last1 ) { + // Create last2 + ForwardIterator2 last2 = first2; + std::advance ( last2, std::distance (first1, last1)); + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, + std::equal_to::value_type> ()); + } + return true; } #endif +/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, +/// ForwardIterator2 first2, ForwardIterator2 last2 ) +/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 +/// +/// \param first1 The start of the input sequence +/// \param last2 One past the end of the input sequence +/// \param first2 The start of the second sequence +/// \param last1 One past the end of the second sequence +/// \note This function is part of the C++2011 standard library. +/// We will use the standard one if it is available, +/// otherwise we have our own implementation. +template< class ForwardIterator1, class ForwardIterator2 > +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2 ) +{ +// How should I deal with the idea that ForwardIterator1::value_type +// and ForwardIterator2::value_type could be different? Define my own comparison predicate? + return boost::algorithm::detail::is_permutation_tag ( + first1, last1, first2, last2, + std::equal_to::value_type> (), + typename std::iterator_traits::iterator_category (), + typename std::iterator_traits::iterator_category ()); +} + +/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, +/// ForwardIterator2 first2, ForwardIterator2 last2, +/// BinaryPredicate p ) +/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 +/// +/// \param first1 The start of the input sequence +/// \param last1 One past the end of the input sequence +/// \param first2 The start of the second sequence +/// \param last2 One past the end of the second sequence +/// \param pred The predicate to compare elements with +/// +/// \note This function is part of the C++2011 standard library. +/// We will use the standard one if it is available, +/// otherwise we have our own implementation. +template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred ) +{ + return boost::algorithm::detail::is_permutation_tag ( + first1, last1, first2, last2, pred, + typename std::iterator_traits::iterator_category (), + typename std::iterator_traits::iterator_category ()); +} + + + /// \fn is_permutation ( const Range &r, ForwardIterator first2 ) /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 /// diff --git a/include/boost/algorithm/cxx14/is_permutation.hpp b/include/boost/algorithm/cxx14/is_permutation.hpp deleted file mode 100644 index 779acef..0000000 --- a/include/boost/algorithm/cxx14/is_permutation.hpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright (c) Marshall Clow 2013 - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -*/ - -/// \file equal.hpp -/// \brief Determines if one -/// \author Marshall Clow - -#ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP -#define BOOST_ALGORITHM_IS_PERMUTATION_HPP - -#include -#include // for std::equal_to - -namespace boost { namespace algorithm { - -namespace detail { - - template - struct is_perm_eq : public std::binary_function { - bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} - }; - - - template - bool is_permutation ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, - RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, - std::random_access_iterator_tag, std::random_access_iterator_tag ) - { - // Random-access iterators let is check the sizes in constant time - if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 )) - return false; - // If we know that the sequences are the same size, the original version is fine - return std::is_permutation ( first1, last1, first2, pred ); - } - - - template - bool is_permutation ( - ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2, - BinaryPredicate pred, - std::forward_iterator_tag, std::forward_iterator_tag ) - { - - // Look for common prefix - for (; first1 != last1 && first2 != last2; ++first1, ++first2) - if (!pred(*first1, *first2)) - goto not_done; - // We've reached the end of one of the sequences without a mismatch. - return first1 == last1 && first2 == last2; - not_done: - - // Check and make sure that we have the same # of elements left - typedef typename std::iterator_traits::difference_type diff1_t; - diff1_t len1 = _VSTD::distance(first1, last1); - typedef typename std::iterator_traits::difference_type diff2_t; - diff2_t len2 = _VSTD::distance(first2, last2); - if (len1 != len2) - return false; - - // For each element in [f1, l1) see if there are the - // same number of equal elements in [f2, l2) - for ( ForwardIterator1 i = first1; i != last1; ++i ) - { - // Have we already counted this value? - ForwardIterator1 j; - for ( j = first1; j != i; ++j ) - if (pred(*j, *i)) - break; - if ( j == i ) // didn't find it... - { - // Count number of *i in [f2, l2) - diff1_t c2 = 0; - for ( ForwardIterator2 iter2 = first2; iter2 != last2; ++iter2 ) - if (pred(*i, *iter2)) - ++c2; - if (c2 == 0) - return false; - - // Count number of *i in [i, l1) - diff1_t c1 = 0; - for (_ForwardIterator1 iter1 = i; iter1 != last1; ++iter1 ) - if (pred(*i, *iter1)) - ++c1; - if (c1 != c2) - return false; - } - } - return true; - } - -} - - -template -bool is_permutation ( - ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2, - BinaryPredicate pred ) -{ - return boost::algorithm::detail::is_permutation ( - first1, last1, first2, last2, pred, - typename std::iterator_traits::iterator_category (), - typename std::iterator_traits::iterator_category ()); -} - -template -bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2 ) -{ - typedef typename iterator_traits<_ForwardIterator1>::value_type value1_t; - typedef typename iterator_traits<_ForwardIterator2>::value_type value2_t; - return boost::algorithm::detail::is_permutation ( - first1, last1, first2, last2, - boost::algorithm::detail::is_perm_eq< - typename std::iterator_traits::value_type, - typename std::iterator_traits::value_type> (), - typename std::iterator_traits::iterator_category (), - typename std::iterator_traits::iterator_category ()); -} - -// There are already range-based versions of these. - -}} // namespace boost and algorithm - -#endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP diff --git a/test/equal_test.cpp b/test/equal_test.cpp index a1bda1a..c54e64d 100644 --- a/test/equal_test.cpp +++ b/test/equal_test.cpp @@ -24,9 +24,9 @@ bool never_eq ( const T&, const T& ) { return false; } int comparison_count = 0; template bool counting_equals ( const T &a, const T &b ) { - ++comparison_count; - return a == b; - } + ++comparison_count; + return a == b; + } namespace ba = boost::algorithm; @@ -37,86 +37,89 @@ void test_equal () const int sz = sizeof (num)/sizeof(num[0]); -// Empty sequences are equal to each other, but not to non-empty sequences - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num), - never_eq )); - BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num), - random_access_iterator(num), random_access_iterator(num), - never_eq )); - - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num + 1))); - BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + 2), - input_iterator(num), input_iterator(num))); - BOOST_CHECK (!ba::equal ( random_access_iterator(num + 1), random_access_iterator(num + 2), - random_access_iterator(num), random_access_iterator(num))); +// Empty sequences are equal to each other, but not to non-empty sequences + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num), + never_eq )); + BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num), random_access_iterator(num), + never_eq )); + + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num + 1))); + BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + 2), + input_iterator(num), input_iterator(num))); + BOOST_CHECK (!ba::equal ( random_access_iterator(num + 1), random_access_iterator(num + 2), + random_access_iterator(num), random_access_iterator(num))); -// Single element sequences are equal if they contain the same value - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1), - eq )); - BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1), - never_eq )); - BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - never_eq )); +// Single element sequences are equal if they contain the same value + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1), + eq )); + BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1), + never_eq )); + BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + never_eq )); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2), - eq )); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2), + eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1))); - BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1), - eq )); - -// Identical long sequences are equal. - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - never_eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1))); + BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1), + eq )); + +// Identical long sequences are equal. + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + never_eq )); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz), + eq )); -// different sequences are different - BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz))); - BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz - 1))); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz - 1), - eq )); +// different sequences are different + BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz))); + BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz - 1))); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz - 1), + eq )); -// When there's a cheap check, bail early - comparison_count = 0; - BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + sz), - random_access_iterator(num), random_access_iterator(num + sz - 1), - counting_equals )); - BOOST_CHECK ( comparison_count == 0 ); -// And when there's not, we can't - comparison_count = 0; - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz - 1), - counting_equals )); - BOOST_CHECK ( comparison_count > 0 ); - +// When there's a cheap check, bail early + comparison_count = 0; + BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz - 1), + counting_equals )); + BOOST_CHECK ( comparison_count == 0 ); +// And when there's not, we can't + comparison_count = 0; + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz - 1), + counting_equals )); + BOOST_CHECK ( comparison_count > 0 ); + } diff --git a/test/is_permutation_test1.cpp b/test/is_permutation_test1.cpp index 2ccd06a..e819643 100644 --- a/test/is_permutation_test1.cpp +++ b/test/is_permutation_test1.cpp @@ -19,10 +19,95 @@ #include #include +#include "iterator_test.hpp" + +template +bool eq ( const T& a, const T& b ) { return a == b; } + +template +bool never_eq ( const T&, const T& ) { return false; } + namespace ba = boost::algorithm; -// namespace ba = boost; void test_sequence1 () { + int num[] = { 1, 1, 2, 3, 5 }; + const int sz = sizeof (num)/sizeof(num[0]); + +// Empty sequences + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num), forward_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num), random_access_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num), + never_eq )); // Since the sequences are empty, the pred is never called + +// Empty vs. non-empty + BOOST_CHECK ( ! + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num), forward_iterator(num + 1))); + + BOOST_CHECK ( ! + ba::is_permutation ( + forward_iterator(num + 1), forward_iterator(num + 2), + forward_iterator(num), forward_iterator(num))); + + BOOST_CHECK ( ! + ba::is_permutation ( + random_access_iterator(num + 1), random_access_iterator(num + 2), + random_access_iterator(num), random_access_iterator(num))); + + BOOST_CHECK ( ! + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num + 1), random_access_iterator(num + 2))); + +// Something should be a permutation of itself + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num), eq )); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num), forward_iterator(num + sz ))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num), forward_iterator(num + sz ), + eq )); + + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz))); + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz), + eq )); + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num + sz), + forward_iterator(num), forward_iterator(num + sz), + eq )); + + std::vector v, v1; v.clear (); diff --git a/test/mismatch_test.cpp b/test/mismatch_test.cpp index 19e0477..61a7506 100644 --- a/test/mismatch_test.cpp +++ b/test/mismatch_test.cpp @@ -24,9 +24,9 @@ bool never_eq ( const T&, const T& ) { return false; } namespace ba = boost::algorithm; template -bool iter_eq ( std::pair pr, Iter1 first, Iter2 second ) { - return pr.first == first && pr.second == second; - } +bool iter_eq ( std::pair pr, Iter1 first, Iter2 second ) { + return pr.first == first && pr.second == second; + } void test_mismatch () { @@ -35,123 +35,129 @@ void test_mismatch () const int sz = sizeof (num)/sizeof(num[0]); -// No mismatch for empty sequences - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num)), - input_iterator(num), input_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num), - never_eq ), - input_iterator(num), input_iterator(num))); +// No mismatch for empty sequences + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num)), + input_iterator(num), input_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num), + never_eq ), + input_iterator(num), input_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num), random_access_iterator(num), - random_access_iterator(num), random_access_iterator(num), - never_eq ), - random_access_iterator(num), random_access_iterator(num))); - -// Empty vs. non-empty mismatch immediately - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num + 1)), - input_iterator(num), input_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num), random_access_iterator(num), + never_eq ), + random_access_iterator(num), random_access_iterator(num))); + +// Empty vs. non-empty mismatch immediately + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num + 1)), + input_iterator(num), input_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 1), input_iterator(num + 2), - input_iterator(num), input_iterator(num)), - input_iterator(num + 1), input_iterator(num))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num + 1), random_access_iterator(num + 2), - random_access_iterator(num), random_access_iterator(num)), - random_access_iterator(num + 1), random_access_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 1), input_iterator(num + 2), + input_iterator(num), input_iterator(num)), + input_iterator(num + 1), input_iterator(num))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num + 1), random_access_iterator(num + 2), + random_access_iterator(num), random_access_iterator(num)), + random_access_iterator(num + 1), random_access_iterator(num))); -// Single element sequences are equal if they contain the same value - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1)), - input_iterator(num + 1), input_iterator(num + 1))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), +// Single element sequences are equal if they contain the same value + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1)), + input_iterator(num + 1), input_iterator(num + 1))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), input_iterator(num), input_iterator(num + 1), - eq ), - input_iterator(num + 1), input_iterator(num + 1))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - eq ), - random_access_iterator(num + 1), random_access_iterator(num + 1))); + eq ), + input_iterator(num + 1), input_iterator(num + 1))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + eq ), + random_access_iterator(num + 1), random_access_iterator(num + 1))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1), - never_eq ), - input_iterator(num), input_iterator(num))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - never_eq ), - random_access_iterator(num), random_access_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1), + never_eq ), + input_iterator(num), input_iterator(num))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + never_eq ), + random_access_iterator(num), random_access_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2)), - input_iterator(num + 1), input_iterator(num + 2))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2)), + input_iterator(num + 1), input_iterator(num + 2))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2), - eq ), - input_iterator(num + 1), input_iterator(num + 2))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2), + eq ), + input_iterator(num + 1), input_iterator(num + 2))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1)), - input_iterator(num + 2), input_iterator(num))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1), - eq ), - input_iterator(num + 2), input_iterator(num))); - - - -// Identical long sequences are equal. - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz)), - input_iterator(num + sz), input_iterator(num + sz))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1)), + input_iterator(num + 2), input_iterator(num))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1), + eq ), + input_iterator(num + 2), input_iterator(num))); + + + +// Identical long sequences are equal. + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz)), + input_iterator(num + sz), input_iterator(num + sz))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq ), - input_iterator(num + sz), input_iterator(num + sz))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq ), + input_iterator(num + sz), input_iterator(num + sz))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - never_eq ), - input_iterator(num), input_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + never_eq ), + input_iterator(num), input_iterator(num))); -// different sequences are different - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz)), - input_iterator(num + 2), input_iterator(num + 1))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz), + never_eq ), + input_iterator(num), random_access_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq ), - input_iterator(num + 2), input_iterator(num + 1))); +// different sequences are different + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz)), + input_iterator(num + 2), input_iterator(num + 1))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq ), + input_iterator(num + 2), input_iterator(num + 1))); }