Merge from develop: clean up is_permutation; fix clamp interface, and merge fix for bug #9335 as well

This commit is contained in:
Marshall Clow
2014-03-31 12:03:45 -07:00
5 changed files with 92 additions and 185 deletions

View File

@ -76,8 +76,8 @@ namespace boost { namespace algorithm {
} }
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out, /// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type lo, /// std::iterator_traits<InputIterator>::value_type const & lo,
/// std::iterator_traits<InputIterator>::value_type hi ) /// std::iterator_traits<InputIterator>::value_type const & hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// ///
/// \param first The start of the range of values /// \param first The start of the range of values
@ -88,8 +88,8 @@ namespace boost { namespace algorithm {
/// ///
template<typename InputIterator, typename OutputIterator> template<typename InputIterator, typename OutputIterator>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type lo, typename std::iterator_traits<InputIterator>::value_type const & lo,
typename std::iterator_traits<InputIterator>::value_type hi ) typename std::iterator_traits<InputIterator>::value_type const & hi )
{ {
// this could also be written with bind and std::transform // this could also be written with bind and std::transform
while ( first != last ) while ( first != last )
@ -98,8 +98,8 @@ namespace boost { namespace algorithm {
} }
/// \fn clamp_range ( const Range &r, OutputIterator out, /// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo, /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi ) /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// ///
/// \param r The range of values to be clamped /// \param r The range of values to be clamped
@ -110,16 +110,16 @@ namespace boost { namespace algorithm {
template<typename Range, typename OutputIterator> template<typename Range, typename OutputIterator>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out, clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo, typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi ) typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi )
{ {
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi ); return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi );
} }
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out, /// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type lo, /// std::iterator_traits<InputIterator>::value_type const & lo,
/// std::iterator_traits<InputIterator>::value_type hi, Pred p ) /// std::iterator_traits<InputIterator>::value_type const & hi, Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p. /// using the comparison predicate p.
/// ///
@ -134,8 +134,8 @@ namespace boost { namespace algorithm {
/// ///
template<typename InputIterator, typename OutputIterator, typename Pred> template<typename InputIterator, typename OutputIterator, typename Pred>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type lo, typename std::iterator_traits<InputIterator>::value_type const & lo,
typename std::iterator_traits<InputIterator>::value_type hi, Pred p ) typename std::iterator_traits<InputIterator>::value_type const & hi, Pred p )
{ {
// this could also be written with bind and std::transform // this could also be written with bind and std::transform
while ( first != last ) while ( first != last )
@ -144,8 +144,8 @@ namespace boost { namespace algorithm {
} }
/// \fn clamp_range ( const Range &r, OutputIterator out, /// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo, /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi, /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi,
/// Pred p ) /// Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p. /// using the comparison predicate p.
@ -162,8 +162,8 @@ namespace boost { namespace algorithm {
template<typename Range, typename OutputIterator, typename Pred> template<typename Range, typename OutputIterator, typename Pred>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out, clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo, typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi, typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi,
Pred p ) Pred p )
{ {
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p ); return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p );

View File

@ -9,8 +9,8 @@
/// \brief Is a sequence a permutation of another sequence /// \brief Is a sequence a permutation of another sequence
/// \author Marshall Clow /// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP #ifndef BOOST_ALGORITHM_IS_PERMUTATION11_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION_HPP #define BOOST_ALGORITHM_IS_PERMUTATION11_HPP
#include <algorithm> // for std::less, tie, mismatch and is_permutation (if available) #include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
#include <utility> // for std::make_pair #include <utility> // for std::make_pair
@ -163,56 +163,6 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIt
#endif #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<typename std::iterator_traits<ForwardIterator1>::value_type> (),
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::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<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
/// \fn is_permutation ( const Range &r, ForwardIterator first2 ) /// \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 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
@ -243,4 +193,4 @@ is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
}} }}
#endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP #endif // BOOST_ALGORITHM_IS_PERMUTATION11_HPP

View File

@ -1,130 +1,86 @@
/* /*
Copyright (c) Marshall Clow 2013 Copyright (c) Marshall Clow 2014.
Distributed under the Boost Software License, Version 1.0. (See accompanying 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
/// \file equal.hpp /// \file is_permutation.hpp
/// \brief Determines if one /// \brief Is a sequence a permutation of another sequence (four iterator versions)
/// \author Marshall Clow /// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP #ifndef BOOST_ALGORITHM_IS_PERMUTATION14_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION_HPP #define BOOST_ALGORITHM_IS_PERMUTATION14_HPP
#include <algorithm> #include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
#include <utility> // for std::make_pair
#include <functional> // for std::equal_to #include <functional> // for std::equal_to
#include <iterator>
#include <boost/algorithm/cxx11/is_permutation.hpp>
#include <boost/algorithm/cxx14/mismatch.hpp>
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
namespace detail { #if __cplusplus <= 201103L
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last,
template <class T1, class T2> /// ForwardIterator2 first2, ForwardIterator2 last2 )
struct is_perm_eq : public std::binary_function<T1, T2, bool> { /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} ///
}; /// \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
template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate> /// \param last1 One past the end of the second sequence
bool is_permutation ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, /// \note This function is part of the C++2014 standard library.
RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, /// We will use the standard one if it is available,
std::random_access_iterator_tag, std::random_access_iterator_tag ) /// otherwise we have our own implementation.
{
// 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<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
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<ForwardIterator1>::difference_type diff1_t;
diff1_t len1 = _VSTD::distance(first1, last1);
typedef typename std::iterator_traits<ForwardIterator2>::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<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 (
first1, last1, first2, last2, pred,
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
template< class ForwardIterator1, class ForwardIterator2 > template< class ForwardIterator1, class ForwardIterator2 >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2 ) ForwardIterator2 first2, ForwardIterator2 last2 )
{ {
typedef typename iterator_traits<_ForwardIterator1>::value_type value1_t; // How should I deal with the idea that ForwardIterator1::value_type
typedef typename iterator_traits<_ForwardIterator2>::value_type value2_t; // and ForwardIterator2::value_type could be different? Define my own comparison predicate?
return boost::algorithm::detail::is_permutation ( std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch
first1, last1, first2, last2, ( first1, last1, first2, last2 );
boost::algorithm::detail::is_perm_eq< if ( eq.first == last1 && eq.second == last2)
typename std::iterator_traits<InputIterator1>::value_type, return true;
typename std::iterator_traits<InputIterator2>::value_type> (), return boost::algorithm::detail::is_permutation_tag (
eq.first, last1, eq.second, last2,
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> (),
typename std::iterator_traits<ForwardIterator1>::iterator_category (), typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ()); typename std::iterator_traits<ForwardIterator2>::iterator_category ());
} }
// There are already range-based versions of these. /// \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++2014 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 )
{
std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch
( first1, last1, first2, last2, pred );
if ( eq.first == last1 && eq.second == last2)
return true;
return boost::algorithm::detail::is_permutation_tag (
first1, last1, first2, last2, pred,
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
#endif
}} // namespace boost and algorithm }}
#endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP #endif // BOOST_ALGORITHM_IS_PERMUTATION14_HPP

View File

@ -230,7 +230,7 @@ namespace boost {
\post eof()==true \post eof()==true
*/ */
split_iterator() {} split_iterator() { m_bEof = true; }
//! Copy constructor //! Copy constructor
/*! /*!
Construct a copy of the split_iterator Construct a copy of the split_iterator

View File

@ -11,6 +11,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/algorithm/cxx11/is_permutation.hpp> #include <boost/algorithm/cxx11/is_permutation.hpp>
#include <boost/algorithm/cxx14/is_permutation.hpp>
#define BOOST_TEST_MAIN #define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>