From 8d095e9d300821c8b02f1917cdbbd6795adec206 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 25 Jan 2016 13:11:01 +0300 Subject: [PATCH 01/20] Added constexpr modifiers for C++14 mode and some tests --- include/boost/algorithm/algorithm.hpp | 4 +-- include/boost/algorithm/clamp.hpp | 12 +++---- include/boost/algorithm/cxx11/all_of.hpp | 8 ++--- include/boost/algorithm/cxx11/any_of.hpp | 8 ++--- include/boost/algorithm/cxx11/copy_if.hpp | 12 +++---- include/boost/algorithm/cxx11/copy_n.hpp | 2 +- include/boost/algorithm/cxx11/find_if_not.hpp | 4 +-- include/boost/algorithm/cxx11/iota.hpp | 6 ++-- .../boost/algorithm/cxx11/is_partitioned.hpp | 4 +-- include/boost/algorithm/cxx11/is_sorted.hpp | 32 +++++++++---------- include/boost/algorithm/cxx11/none_of.hpp | 8 ++--- include/boost/algorithm/cxx11/one_of.hpp | 4 +-- .../boost/algorithm/cxx11/partition_copy.hpp | 5 +-- include/boost/algorithm/cxx14/equal.hpp | 4 +-- include/boost/algorithm/cxx14/mismatch.hpp | 5 +-- test/all_of_test.cpp | 17 +++++++--- test/any_of_test.cpp | 17 +++++++--- test/clamp_test.cpp | 4 +++ test/copy_if_test1.cpp | 26 ++++++++++++--- 19 files changed, 111 insertions(+), 71 deletions(-) diff --git a/include/boost/algorithm/algorithm.hpp b/include/boost/algorithm/algorithm.hpp index ab0d4af..96b3b48 100644 --- a/include/boost/algorithm/algorithm.hpp +++ b/include/boost/algorithm/algorithm.hpp @@ -40,7 +40,7 @@ T identity_operation ( std::plus ) { return T(0); } // \remark Taken from Knuth, The Art of Computer Programming, Volume 2: // Seminumerical Algorithms, Section 4.6.3 template -typename boost::enable_if, T>::type +BOOST_CXX14_CONSTEXPR typename boost::enable_if, T>::type power (T x, Integer n) { T y = 1; // Should be "T y{1};" if (n == 0) return y; @@ -67,7 +67,7 @@ power (T x, Integer n) { // \remark Taken from Knuth, The Art of Computer Programming, Volume 2: // Seminumerical Algorithms, Section 4.6.3 template -typename boost::enable_if, T>::type +BOOST_CXX14_CONSTEXPR typename boost::enable_if, T>::type power (T x, Integer n, Operation op) { T y = identity_operation(op); if (n == 0) return y; diff --git a/include/boost/algorithm/clamp.hpp b/include/boost/algorithm/clamp.hpp index 7bfa47e..a179d26 100644 --- a/include/boost/algorithm/clamp.hpp +++ b/include/boost/algorithm/clamp.hpp @@ -46,7 +46,7 @@ namespace boost { namespace algorithm { /// p ( a, b ) returns a boolean. /// template - T const & clamp ( T const& val, + BOOST_CXX14_CONSTEXPR T const & clamp ( T const& val, typename boost::mpl::identity::type const & lo, typename boost::mpl::identity::type const & hi, Pred p ) { @@ -68,7 +68,7 @@ namespace boost { namespace algorithm { /// \param hi The upper bound of the range to be clamped to /// template - T const& clamp ( const T& val, + BOOST_CXX14_CONSTEXPR T const& clamp ( const T& val, typename boost::mpl::identity::type const & lo, typename boost::mpl::identity::type const & hi ) { @@ -87,7 +87,7 @@ namespace boost { namespace algorithm { /// \param hi The upper bound of the range to be clamped to /// template - OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, + BOOST_CXX14_CONSTEXPR OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, typename std::iterator_traits::value_type const & lo, typename std::iterator_traits::value_type const & hi ) { @@ -108,7 +108,7 @@ namespace boost { namespace algorithm { /// \param hi The upper bound of the range to be clamped to /// template - typename boost::disable_if_c::value, OutputIterator>::type + BOOST_CXX14_CONSTEXPR typename boost::disable_if_c::value, OutputIterator>::type clamp_range ( const Range &r, OutputIterator out, typename std::iterator_traits::type>::value_type const & lo, typename std::iterator_traits::type>::value_type const & hi ) @@ -133,7 +133,7 @@ namespace boost { namespace algorithm { /// template - OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, + BOOST_CXX14_CONSTEXPR OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, typename std::iterator_traits::value_type const & lo, typename std::iterator_traits::value_type const & hi, Pred p ) { @@ -160,7 +160,7 @@ namespace boost { namespace algorithm { // Disable this template if the first two parameters are the same type; // In that case, the user will get the two iterator version. template - typename boost::disable_if_c::value, OutputIterator>::type + BOOST_CXX14_CONSTEXPR typename boost::disable_if_c::value, OutputIterator>::type clamp_range ( const Range &r, OutputIterator out, typename std::iterator_traits::type>::value_type const & lo, typename std::iterator_traits::type>::value_type const & hi, diff --git a/include/boost/algorithm/cxx11/all_of.hpp b/include/boost/algorithm/cxx11/all_of.hpp index 39cab39..ae8ca9f 100644 --- a/include/boost/algorithm/cxx11/all_of.hpp +++ b/include/boost/algorithm/cxx11/all_of.hpp @@ -30,7 +30,7 @@ namespace boost { namespace algorithm { /// We will use the standard one if it is available, /// otherwise we have our own implementation. template -bool all_of ( InputIterator first, InputIterator last, Predicate p ) +BOOST_CXX14_CONSTEXPR bool all_of ( InputIterator first, InputIterator last, Predicate p ) { for ( ; first != last; ++first ) if ( !p(*first)) @@ -46,7 +46,7 @@ bool all_of ( InputIterator first, InputIterator last, Predicate p ) /// \param p A predicate for testing the elements of the range /// template -bool all_of ( const Range &r, Predicate p ) +BOOST_CXX14_CONSTEXPR bool all_of ( const Range &r, Predicate p ) { return boost::algorithm::all_of ( boost::begin (r), boost::end (r), p ); } @@ -60,7 +60,7 @@ bool all_of ( const Range &r, Predicate p ) /// \param val A value to compare against /// template -bool all_of_equal ( InputIterator first, InputIterator last, const T &val ) +BOOST_CXX14_CONSTEXPR bool all_of_equal ( InputIterator first, InputIterator last, const T &val ) { for ( ; first != last; ++first ) if ( val != *first ) @@ -76,7 +76,7 @@ bool all_of_equal ( InputIterator first, InputIterator last, const T &val ) /// \param val A value to compare against /// template -bool all_of_equal ( const Range &r, const T &val ) +BOOST_CXX14_CONSTEXPR bool all_of_equal ( const Range &r, const T &val ) { return boost::algorithm::all_of_equal ( boost::begin (r), boost::end (r), val ); } diff --git a/include/boost/algorithm/cxx11/any_of.hpp b/include/boost/algorithm/cxx11/any_of.hpp index cf69348..6d30d08 100644 --- a/include/boost/algorithm/cxx11/any_of.hpp +++ b/include/boost/algorithm/cxx11/any_of.hpp @@ -29,7 +29,7 @@ namespace boost { namespace algorithm { /// \param p A predicate for testing the elements of the sequence /// template -bool any_of ( InputIterator first, InputIterator last, Predicate p ) +BOOST_CXX14_CONSTEXPR bool any_of ( InputIterator first, InputIterator last, Predicate p ) { for ( ; first != last; ++first ) if ( p(*first)) @@ -45,7 +45,7 @@ bool any_of ( InputIterator first, InputIterator last, Predicate p ) /// \param p A predicate for testing the elements of the range /// template -bool any_of ( const Range &r, Predicate p ) +BOOST_CXX14_CONSTEXPR bool any_of ( const Range &r, Predicate p ) { return boost::algorithm::any_of (boost::begin (r), boost::end (r), p); } @@ -59,7 +59,7 @@ bool any_of ( const Range &r, Predicate p ) /// \param val A value to compare against /// template -bool any_of_equal ( InputIterator first, InputIterator last, const V &val ) +BOOST_CXX14_CONSTEXPR bool any_of_equal ( InputIterator first, InputIterator last, const V &val ) { for ( ; first != last; ++first ) if ( val == *first ) @@ -75,7 +75,7 @@ bool any_of_equal ( InputIterator first, InputIterator last, const V &val ) /// \param val A value to compare against /// template -bool any_of_equal ( const Range &r, const V &val ) +BOOST_CXX14_CONSTEXPR bool any_of_equal ( const Range &r, const V &val ) { return boost::algorithm::any_of_equal (boost::begin (r), boost::end (r), val); } diff --git a/include/boost/algorithm/cxx11/copy_if.hpp b/include/boost/algorithm/cxx11/copy_if.hpp index d869caf..ec311e7 100644 --- a/include/boost/algorithm/cxx11/copy_if.hpp +++ b/include/boost/algorithm/cxx11/copy_if.hpp @@ -31,7 +31,7 @@ namespace boost { namespace algorithm { /// We will use the standard one if it is available, /// otherwise we have our own implementation. template -OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) +BOOST_CXX14_CONSTEXPR OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) { for ( ; first != last; ++first ) if (p(*first)) @@ -49,7 +49,7 @@ OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator /// \param p A predicate for testing the elements of the range /// template -OutputIterator copy_if ( const Range &r, OutputIterator result, Predicate p ) +BOOST_CXX14_CONSTEXPR OutputIterator copy_if ( const Range &r, OutputIterator result, Predicate p ) { return boost::algorithm::copy_if (boost::begin (r), boost::end(r), result, p); } @@ -66,7 +66,7 @@ OutputIterator copy_if ( const Range &r, OutputIterator result, Predicate p ) /// \param p A predicate for testing the elements of the range /// template -std::pair +BOOST_CXX14_CONSTEXPR std::pair copy_while ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) { for ( ; first != last && p(*first); ++first ) @@ -84,7 +84,7 @@ copy_while ( InputIterator first, InputIterator last, OutputIterator result, Pre /// \param p A predicate for testing the elements of the range /// template -std::pair::type, OutputIterator> +BOOST_CXX14_CONSTEXPR std::pair::type, OutputIterator> copy_while ( const Range &r, OutputIterator result, Predicate p ) { return boost::algorithm::copy_while (boost::begin (r), boost::end(r), result, p); @@ -102,7 +102,7 @@ copy_while ( const Range &r, OutputIterator result, Predicate p ) /// \param p A predicate for testing the elements of the range /// template -std::pair +BOOST_CXX14_CONSTEXPR std::pair copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) { for ( ; first != last && !p(*first); ++first ) @@ -120,7 +120,7 @@ copy_until ( InputIterator first, InputIterator last, OutputIterator result, Pre /// \param p A predicate for testing the elements of the range /// template -std::pair::type, OutputIterator> +BOOST_CXX14_CONSTEXPR std::pair::type, OutputIterator> copy_until ( const Range &r, OutputIterator result, Predicate p ) { return boost::algorithm::copy_until (boost::begin (r), boost::end(r), result, p); diff --git a/include/boost/algorithm/cxx11/copy_n.hpp b/include/boost/algorithm/cxx11/copy_n.hpp index ebfe889..842718f 100644 --- a/include/boost/algorithm/cxx11/copy_n.hpp +++ b/include/boost/algorithm/cxx11/copy_n.hpp @@ -28,7 +28,7 @@ namespace boost { namespace algorithm { /// We will use the standard one if it is available, /// otherwise we have our own implementation. template -OutputIterator copy_n ( InputIterator first, Size n, OutputIterator result ) +BOOST_CXX14_CONSTEXPR OutputIterator copy_n ( InputIterator first, Size n, OutputIterator result ) { for ( ; n > 0; --n, ++first, ++result ) *result = *first; diff --git a/include/boost/algorithm/cxx11/find_if_not.hpp b/include/boost/algorithm/cxx11/find_if_not.hpp index 414697c..735c719 100644 --- a/include/boost/algorithm/cxx11/find_if_not.hpp +++ b/include/boost/algorithm/cxx11/find_if_not.hpp @@ -30,7 +30,7 @@ namespace boost { namespace algorithm { /// We will use the standard one if it is available, /// otherwise we have our own implementation. template -InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p ) +BOOST_CXX14_CONSTEXPR InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p ) { for ( ; first != last; ++first ) if ( !p(*first)) @@ -46,7 +46,7 @@ InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p /// \param p A predicate for testing the elements of the range /// template -typename boost::range_iterator::type find_if_not ( const Range &r, Predicate p ) +BOOST_CXX14_CONSTEXPR typename boost::range_iterator::type find_if_not ( const Range &r, Predicate p ) { return boost::algorithm::find_if_not (boost::begin (r), boost::end(r), p); } diff --git a/include/boost/algorithm/cxx11/iota.hpp b/include/boost/algorithm/cxx11/iota.hpp index 2e638ec..0cfffb7 100644 --- a/include/boost/algorithm/cxx11/iota.hpp +++ b/include/boost/algorithm/cxx11/iota.hpp @@ -29,7 +29,7 @@ namespace boost { namespace algorithm { /// We will use the standard one if it is available, /// otherwise we have our own implementation. template -void iota ( ForwardIterator first, ForwardIterator last, T value ) +BOOST_CXX14_CONSTEXPR void iota ( ForwardIterator first, ForwardIterator last, T value ) { for ( ; first != last; ++first, ++value ) *first = value; @@ -42,7 +42,7 @@ void iota ( ForwardIterator first, ForwardIterator last, T value ) /// \param value The initial value of the sequence to be generated /// template -void iota ( Range &r, T value ) +BOOST_CXX14_CONSTEXPR void iota ( Range &r, T value ) { boost::algorithm::iota (boost::begin(r), boost::end(r), value); } @@ -56,7 +56,7 @@ void iota ( Range &r, T value ) /// \param n The number of items to write /// template -OutputIterator iota_n ( OutputIterator out, T value, std::size_t n ) +BOOST_CXX14_CONSTEXPR OutputIterator iota_n ( OutputIterator out, T value, std::size_t n ) { for ( ; n > 0; --n, ++value ) *out++ = value; diff --git a/include/boost/algorithm/cxx11/is_partitioned.hpp b/include/boost/algorithm/cxx11/is_partitioned.hpp index cdabd97..2d9236e 100644 --- a/include/boost/algorithm/cxx11/is_partitioned.hpp +++ b/include/boost/algorithm/cxx11/is_partitioned.hpp @@ -29,7 +29,7 @@ namespace boost { namespace algorithm { /// We will use the standard one if it is available, /// otherwise we have our own implementation. template -bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p ) +BOOST_CXX14_CONSTEXPR bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p ) { // Run through the part that satisfy the predicate for ( ; first != last; ++first ) @@ -49,7 +49,7 @@ bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p /// \param p The predicate to test the values with /// template -bool is_partitioned ( const Range &r, UnaryPredicate p ) +BOOST_CXX14_CONSTEXPR bool is_partitioned ( const Range &r, UnaryPredicate p ) { return boost::algorithm::is_partitioned (boost::begin(r), boost::end(r), p); } diff --git a/include/boost/algorithm/cxx11/is_sorted.hpp b/include/boost/algorithm/cxx11/is_sorted.hpp index f6062da..a0770f1 100644 --- a/include/boost/algorithm/cxx11/is_sorted.hpp +++ b/include/boost/algorithm/cxx11/is_sorted.hpp @@ -35,7 +35,7 @@ namespace boost { namespace algorithm { /// \param p A binary predicate that returns true if two elements are ordered. /// template - ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p ) + BOOST_CXX14_CONSTEXPR ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p ) { if ( first == last ) return last; // the empty sequence is ordered ForwardIterator next = first; @@ -55,7 +55,7 @@ namespace boost { namespace algorithm { /// \param last One past the end of the sequence /// template - ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last ) + BOOST_CXX14_CONSTEXPR ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last ) { typedef typename std::iterator_traits::value_type value_type; return boost::algorithm::is_sorted_until ( first, last, std::less()); @@ -70,7 +70,7 @@ namespace boost { namespace algorithm { /// \param p A binary predicate that returns true if two elements are ordered. /// template - bool is_sorted ( ForwardIterator first, ForwardIterator last, Pred p ) + BOOST_CXX14_CONSTEXPR bool is_sorted ( ForwardIterator first, ForwardIterator last, Pred p ) { return boost::algorithm::is_sorted_until (first, last, p) == last; } @@ -82,7 +82,7 @@ namespace boost { namespace algorithm { /// \param last One past the end of the sequence /// template - bool is_sorted ( ForwardIterator first, ForwardIterator last ) + BOOST_CXX14_CONSTEXPR bool is_sorted ( ForwardIterator first, ForwardIterator last ) { return boost::algorithm::is_sorted_until (first, last) == last; } @@ -99,7 +99,7 @@ namespace boost { namespace algorithm { /// \param p A binary predicate that returns true if two elements are ordered. /// template - typename boost::lazy_disable_if_c< + BOOST_CXX14_CONSTEXPR typename boost::lazy_disable_if_c< boost::is_same::value, typename boost::range_iterator >::type is_sorted_until ( const R &range, Pred p ) @@ -114,7 +114,7 @@ namespace boost { namespace algorithm { /// \param range The range to be tested. /// template - typename boost::range_iterator::type is_sorted_until ( const R &range ) + BOOST_CXX14_CONSTEXPR typename boost::range_iterator::type is_sorted_until ( const R &range ) { return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range )); } @@ -127,7 +127,7 @@ namespace boost { namespace algorithm { /// \param p A binary predicate that returns true if two elements are ordered. /// template - typename boost::lazy_disable_if_c< boost::is_same::value, boost::mpl::identity >::type + BOOST_CXX14_CONSTEXPR typename boost::lazy_disable_if_c< boost::is_same::value, boost::mpl::identity >::type is_sorted ( const R &range, Pred p ) { return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ), p ); @@ -140,7 +140,7 @@ namespace boost { namespace algorithm { /// \param range The range to be tested. /// template - bool is_sorted ( const R &range ) + BOOST_CXX14_CONSTEXPR bool is_sorted ( const R &range ) { return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range )); } @@ -160,7 +160,7 @@ namespace boost { namespace algorithm { /// \note This function will return true for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_strictly_increasing instead. template - bool is_increasing ( ForwardIterator first, ForwardIterator last ) + BOOST_CXX14_CONSTEXPR bool is_increasing ( ForwardIterator first, ForwardIterator last ) { typedef typename std::iterator_traits::value_type value_type; return boost::algorithm::is_sorted (first, last, std::less()); @@ -176,7 +176,7 @@ namespace boost { namespace algorithm { /// \note This function will return true for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_strictly_increasing instead. template - bool is_increasing ( const R &range ) + BOOST_CXX14_CONSTEXPR bool is_increasing ( const R &range ) { return is_increasing ( boost::begin ( range ), boost::end ( range )); } @@ -193,7 +193,7 @@ namespace boost { namespace algorithm { /// \note This function will return true for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_strictly_decreasing instead. template - bool is_decreasing ( ForwardIterator first, ForwardIterator last ) + BOOST_CXX14_CONSTEXPR bool is_decreasing ( ForwardIterator first, ForwardIterator last ) { typedef typename std::iterator_traits::value_type value_type; return boost::algorithm::is_sorted (first, last, std::greater()); @@ -208,7 +208,7 @@ namespace boost { namespace algorithm { /// \note This function will return true for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_strictly_decreasing instead. template - bool is_decreasing ( const R &range ) + BOOST_CXX14_CONSTEXPR bool is_decreasing ( const R &range ) { return is_decreasing ( boost::begin ( range ), boost::end ( range )); } @@ -225,7 +225,7 @@ namespace boost { namespace algorithm { /// \note This function will return false for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_increasing instead. template - bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last ) + BOOST_CXX14_CONSTEXPR bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last ) { typedef typename std::iterator_traits::value_type value_type; return boost::algorithm::is_sorted (first, last, std::less_equal()); @@ -240,7 +240,7 @@ namespace boost { namespace algorithm { /// \note This function will return false for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_increasing instead. template - bool is_strictly_increasing ( const R &range ) + BOOST_CXX14_CONSTEXPR bool is_strictly_increasing ( const R &range ) { return is_strictly_increasing ( boost::begin ( range ), boost::end ( range )); } @@ -256,7 +256,7 @@ namespace boost { namespace algorithm { /// \note This function will return false for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_decreasing instead. template - bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last ) + BOOST_CXX14_CONSTEXPR bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last ) { typedef typename std::iterator_traits::value_type value_type; return boost::algorithm::is_sorted (first, last, std::greater_equal()); @@ -271,7 +271,7 @@ namespace boost { namespace algorithm { /// \note This function will return false for sequences that contain items that compare /// equal. If that is not what you intended, you should use is_decreasing instead. template - bool is_strictly_decreasing ( const R &range ) + BOOST_CXX14_CONSTEXPR bool is_strictly_decreasing ( const R &range ) { return is_strictly_decreasing ( boost::begin ( range ), boost::end ( range )); } diff --git a/include/boost/algorithm/cxx11/none_of.hpp b/include/boost/algorithm/cxx11/none_of.hpp index 67be3d1..cf02e86 100644 --- a/include/boost/algorithm/cxx11/none_of.hpp +++ b/include/boost/algorithm/cxx11/none_of.hpp @@ -27,7 +27,7 @@ namespace boost { namespace algorithm { /// \param p A predicate for testing the elements of the sequence /// template -bool none_of ( InputIterator first, InputIterator last, Predicate p ) +BOOST_CXX14_CONSTEXPR bool none_of ( InputIterator first, InputIterator last, Predicate p ) { for ( ; first != last; ++first ) if ( p(*first)) @@ -43,7 +43,7 @@ for ( ; first != last; ++first ) /// \param p A predicate for testing the elements of the range /// template -bool none_of ( const Range &r, Predicate p ) +BOOST_CXX14_CONSTEXPR bool none_of ( const Range &r, Predicate p ) { return boost::algorithm::none_of (boost::begin (r), boost::end (r), p ); } @@ -57,7 +57,7 @@ bool none_of ( const Range &r, Predicate p ) /// \param val A value to compare against /// template -bool none_of_equal ( InputIterator first, InputIterator last, const V &val ) +BOOST_CXX14_CONSTEXPR bool none_of_equal ( InputIterator first, InputIterator last, const V &val ) { for ( ; first != last; ++first ) if ( val == *first ) @@ -73,7 +73,7 @@ bool none_of_equal ( InputIterator first, InputIterator last, const V &val ) /// \param val A value to compare against /// template -bool none_of_equal ( const Range &r, const V & val ) +BOOST_CXX14_CONSTEXPR bool none_of_equal ( const Range &r, const V & val ) { return boost::algorithm::none_of_equal (boost::begin (r), boost::end (r), val); } diff --git a/include/boost/algorithm/cxx11/one_of.hpp b/include/boost/algorithm/cxx11/one_of.hpp index b6e8c77..f4e2b38 100644 --- a/include/boost/algorithm/cxx11/one_of.hpp +++ b/include/boost/algorithm/cxx11/one_of.hpp @@ -28,7 +28,7 @@ namespace boost { namespace algorithm { /// \param p A predicate for testing the elements of the sequence /// template -bool one_of ( InputIterator first, InputIterator last, Predicate p ) +BOOST_CXX14_CONSTEXPR bool one_of ( InputIterator first, InputIterator last, Predicate p ) { InputIterator i = std::find_if (first, last, p); if (i == last) @@ -43,7 +43,7 @@ bool one_of ( InputIterator first, InputIterator last, Predicate p ) /// \param p A predicate for testing the elements of the range /// template -bool one_of ( const Range &r, Predicate p ) +BOOST_CXX14_CONSTEXPR bool one_of ( const Range &r, Predicate p ) { return boost::algorithm::one_of ( boost::begin (r), boost::end (r), p ); } diff --git a/include/boost/algorithm/cxx11/partition_copy.hpp b/include/boost/algorithm/cxx11/partition_copy.hpp index 2d8c3e9..20c939f 100644 --- a/include/boost/algorithm/cxx11/partition_copy.hpp +++ b/include/boost/algorithm/cxx11/partition_copy.hpp @@ -15,6 +15,7 @@ #include // for std::partition_copy, if available #include // for make_pair +#include #include #include @@ -38,7 +39,7 @@ namespace boost { namespace algorithm { /// otherwise we have our own implementation. template -std::pair +BOOST_CXX14_CONSTEXPR std::pair partition_copy ( InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p ) { @@ -60,7 +61,7 @@ partition_copy ( InputIterator first, InputIterator last, /// template -std::pair +BOOST_CXX14_CONSTEXPR std::pair partition_copy ( const Range &r, OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p ) { diff --git a/include/boost/algorithm/cxx14/equal.hpp b/include/boost/algorithm/cxx14/equal.hpp index cfc62d5..78587fc 100644 --- a/include/boost/algorithm/cxx14/equal.hpp +++ b/include/boost/algorithm/cxx14/equal.hpp @@ -21,7 +21,7 @@ namespace detail { template struct eq : public std::binary_function { - bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} + BOOST_CONSTEXPR bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} }; template @@ -37,7 +37,7 @@ namespace detail { } template - bool equal ( InputIterator1 first1, InputIterator1 last1, + BOOST_CXX14_CONSTEXPR bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred, std::input_iterator_tag, std::input_iterator_tag ) { diff --git a/include/boost/algorithm/cxx14/mismatch.hpp b/include/boost/algorithm/cxx14/mismatch.hpp index 926ab19..33cd609 100644 --- a/include/boost/algorithm/cxx14/mismatch.hpp +++ b/include/boost/algorithm/cxx14/mismatch.hpp @@ -14,6 +14,7 @@ #include // for std::mismatch #include // for std::pair +#include namespace boost { namespace algorithm { @@ -28,7 +29,7 @@ namespace boost { namespace algorithm { /// \param last2 One past the end of the second range. /// \param pred A predicate for comparing the elements of the ranges template -std::pair mismatch ( +BOOST_CXX14_CONSTEXPR std::pair mismatch ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred ) @@ -48,7 +49,7 @@ std::pair mismatch ( /// \param first2 The start of the second range. /// \param last2 One past the end of the second range. template -std::pair mismatch ( +BOOST_CXX14_CONSTEXPR std::pair mismatch ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2 ) { diff --git a/test/all_of_test.cpp b/test/all_of_test.cpp index 36918d5..79e25a2 100644 --- a/test/all_of_test.cpp +++ b/test/all_of_test.cpp @@ -19,9 +19,9 @@ template struct is_ : public std::unary_function { - is_ ( T v ) : val_ ( v ) {} - ~is_ () {} - bool operator () ( T comp ) const { return val_ == comp; } + BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} + + BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value @@ -33,7 +33,7 @@ namespace ba = boost::algorithm; void test_all () { // Note: The literal values here are tested against directly, careful if you change them: - int some_numbers[] = { 1, 1, 1, 18, 10 }; + BOOST_CXX14_CONSTEXPR int some_numbers[] = { 1, 1, 1, 18, 10 }; std::vector vi(some_numbers, some_numbers + 5); std::list li(vi.begin(), vi.end ()); @@ -77,7 +77,14 @@ void test_all () l_iter++; l_iter++; l_iter++; BOOST_CHECK ( ba::all_of_equal ( li.begin(), l_iter, 1 )); BOOST_CHECK ( ba::all_of ( li.begin(), l_iter, is_ ( 1 ))); - + + BOOST_CXX14_CONSTEXPR bool constexpr_res = ( + !ba::all_of_equal ( some_numbers, 1 ) + && !ba::all_of ( some_numbers, is_ ( 1 )) + && ba::all_of_equal ( some_numbers, some_numbers + 3, 1 ) + && ba::all_of ( some_numbers, some_numbers + 3, is_ ( 1 )) + ); + BOOST_CHECK ( constexpr_res ); } diff --git a/test/any_of_test.cpp b/test/any_of_test.cpp index a3267c5..6193a2f 100644 --- a/test/any_of_test.cpp +++ b/test/any_of_test.cpp @@ -19,9 +19,9 @@ template struct is_ : public std::unary_function { - is_ ( T v ) : val_ ( v ) {} - ~is_ () {} - bool operator () ( T comp ) const { return val_ == comp; } + BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} + + BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value @@ -33,7 +33,7 @@ namespace ba = boost::algorithm; void test_any () { // Note: The literal values here are tested against directly, careful if you change them: - int some_numbers[] = { 1, 5, 0, 18, 10 }; + BOOST_CXX14_CONSTEXPR int some_numbers[] = { 1, 5, 0, 18, 10 }; std::vector vi(some_numbers, some_numbers + 5); std::list li(vi.begin(), vi.end ()); @@ -97,6 +97,15 @@ void test_any () BOOST_CHECK ( ba::any_of ( li.begin(), l_iter, is_ ( 5 ))); BOOST_CHECK (!ba::any_of_equal ( li.begin(), l_iter, 18 )); BOOST_CHECK (!ba::any_of ( li.begin(), l_iter, is_ ( 18 ))); + + + BOOST_CXX14_CONSTEXPR bool constexpr_res = ( + ba::any_of_equal ( some_numbers, 1 ) + && ba::any_of ( some_numbers, is_ ( 1 )) + && !ba::any_of_equal ( some_numbers, some_numbers + 3, 777 ) + && !ba::any_of ( some_numbers, some_numbers + 3, is_ ( 777 )) + ); + BOOST_CHECK ( constexpr_res ); } diff --git a/test/clamp_test.cpp b/test/clamp_test.cpp index 3519659..a8aacc7 100644 --- a/test/clamp_test.cpp +++ b/test/clamp_test.cpp @@ -45,6 +45,10 @@ void test_ints() BOOST_CHECK_EQUAL ( 1, ba::clamp ( 0, 1, 10 )); BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, 1, 10 )); BOOST_CHECK_EQUAL ( 10, ba::clamp ( 11, 1, 10 )); + BOOST_CXX14_CONSTEXPR bool constexpr_res = ( + ba::clamp ( 3, 1, 10 ) == 3 + ); + BOOST_CHECK( constexpr_res ); BOOST_CHECK_EQUAL ( 3, ba::clamp ( 3, 10, 1, intGreater )); BOOST_CHECK_EQUAL ( 1, ba::clamp ( 1, 10, 1, intGreater )); diff --git a/test/copy_if_test1.cpp b/test/copy_if_test1.cpp index 59944bc..1e093fd 100644 --- a/test/copy_if_test1.cpp +++ b/test/copy_if_test1.cpp @@ -25,10 +25,25 @@ namespace ba = boost::algorithm; // namespace ba = boost; -bool is_true ( int v ) { return true; } -bool is_false ( int v ) { return false; } -bool is_even ( int v ) { return v % 2 == 0; } -bool is_odd ( int v ) { return v % 2 == 1; } +BOOST_CXX14_CONSTEXPR bool is_true ( int v ) { return true; } +BOOST_CXX14_CONSTEXPR bool is_false ( int v ) { return false; } +BOOST_CXX14_CONSTEXPR bool is_even ( int v ) { return v % 2 == 0; } +BOOST_CXX14_CONSTEXPR bool is_odd ( int v ) { return v % 2 == 1; } + +BOOST_CXX14_CONSTEXPR inline bool constexpr_helper(const int* from, const int* to) { + bool res = true; + + int out_data[64] = {0}; + int* out = out_data; + ba::copy_if ( from, to, out, is_false); + + res = (res && out == out_data); + ba::copy_if ( from, to, out, is_true); + + res = (res && out == out_data + (to - from)); + + return res; +} template void test_copy_if ( Container const &c ) { @@ -164,6 +179,9 @@ void test_sequence1 () { test_copy_while ( v ); test_copy_until ( v ); + BOOST_CXX14_CONSTEXPR bool constexpr_res = constexpr_helper(0, 0); + BOOST_CHECK ( constexpr_res ); + std::list l; for ( int i = 25; i > 15; --i ) l.push_back ( i ); From dfa332e9152906011a93d20144451ae64a1c07ae Mon Sep 17 00:00:00 2001 From: MMaximoff Date: Fri, 7 Apr 2017 22:31:23 +0300 Subject: [PATCH 02/20] Updated constexpr tests for all affected modules. Added conditional constexpr to equal, which uses std::distance. --- include/boost/algorithm/cxx14/equal.hpp | 13 +- test/clamp_test.cpp | 106 +++++++++++++++ test/copy_if_test1.cpp | 91 ++++++++++--- test/copy_n_test1.cpp | 32 +++++ test/equal_test.cpp | 38 +++++- test/find_if_not_test1.cpp | 23 ++++ test/iota_test1.cpp | 36 +++++- test/is_partitioned_test1.cpp | 19 ++- test/iterator_test.hpp | 144 ++++++++++----------- test/mismatch_test.cpp | 165 ++++++++++++++---------- test/none_of_test.cpp | 16 ++- test/one_of_test.cpp | 14 +- test/ordered_test.cpp | 35 +++-- test/partition_copy_test1.cpp | 28 +++- test/power_test.cpp | 50 ++++++- 15 files changed, 625 insertions(+), 185 deletions(-) diff --git a/include/boost/algorithm/cxx14/equal.hpp b/include/boost/algorithm/cxx14/equal.hpp index 78587fc..becaed2 100644 --- a/include/boost/algorithm/cxx14/equal.hpp +++ b/include/boost/algorithm/cxx14/equal.hpp @@ -15,6 +15,13 @@ #include // for std::equal #include // for std::equal_to +#ifdef __cpp_lib_array_constexpr // or cpp17 compiler +// if compiled according to C++17 standard or std functions are constexpr +#define BOOST_CONSTEXPR_IF_STD_CONSTEXPR constexpr +#else +#define BOOST_CONSTEXPR_IF_STD_CONSTEXPR +#endif + namespace boost { namespace algorithm { namespace detail { @@ -25,6 +32,7 @@ namespace detail { }; template + BOOST_CONSTEXPR_IF_STD_CONSTEXPR bool equal ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, std::random_access_iterator_tag, std::random_access_iterator_tag ) @@ -37,7 +45,8 @@ namespace detail { } template - BOOST_CXX14_CONSTEXPR bool equal ( InputIterator1 first1, InputIterator1 last1, + BOOST_CXX14_CONSTEXPR + bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred, std::input_iterator_tag, std::input_iterator_tag ) { @@ -60,6 +69,7 @@ namespace detail { /// \param last2 One past the end of the second range. /// \param pred A predicate for comparing the elements of the ranges template +BOOST_CXX14_CONSTEXPR bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred ) { @@ -78,6 +88,7 @@ bool equal ( InputIterator1 first1, InputIterator1 last1, /// \param first2 The start of the second range. /// \param last2 One past the end of the second range. template +BOOST_CXX14_CONSTEXPR bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2 ) { diff --git a/test/clamp_test.cpp b/test/clamp_test.cpp index a8aacc7..2513cf8 100644 --- a/test/clamp_test.cpp +++ b/test/clamp_test.cpp @@ -210,6 +210,110 @@ void test_int_range () BOOST_CHECK ( std::equal ( b_e(junk), outputs )); } +void test_constexpr() +{ + +// Inside the range, equal to the endpoints, and outside the endpoints. + { + BOOST_CXX14_CONSTEXPR bool check_inside = (3 == ba::clamp ( 3, 1, 10 )); + BOOST_CHECK(check_inside); + BOOST_CXX14_CONSTEXPR bool check_min = (1 == ba::clamp ( 1, 1, 10 )); + BOOST_CHECK(check_min); + BOOST_CXX14_CONSTEXPR bool check_min_out = (1 == ba::clamp ( 0, 1, 10 )); + BOOST_CHECK(check_min_out); + BOOST_CXX14_CONSTEXPR bool check_max = (10 == ba::clamp ( 10, 1, 10 )); + BOOST_CHECK(check_max); + BOOST_CXX14_CONSTEXPR bool check_max_out = (10 == ba::clamp ( 11, 1, 10 )); + BOOST_CHECK(check_max_out); + } + { + BOOST_CXX14_CONSTEXPR bool check_inside = (3 == ba::clamp ( 3, 10, 1, intGreater )); + BOOST_CHECK(check_inside); + BOOST_CXX14_CONSTEXPR bool check_min = (1 == ba::clamp ( 1, 10, 1, intGreater )); + BOOST_CHECK(check_min); + BOOST_CXX14_CONSTEXPR bool check_min_out = (1 == ba::clamp ( 0, 10, 1, intGreater )); + BOOST_CHECK(check_min_out); + BOOST_CXX14_CONSTEXPR bool check_max = (10 == ba::clamp ( 10, 10, 1, intGreater )); + BOOST_CHECK(check_max); + BOOST_CXX14_CONSTEXPR bool check_max_out = (10 == ba::clamp ( 11, 10, 1, intGreater )); + BOOST_CHECK(check_max_out); + } + +// Negative numbers + { + BOOST_CXX14_CONSTEXPR bool check_inside = (-3 == ba::clamp ( -3, -10, -1 )); + BOOST_CHECK(check_inside); + BOOST_CXX14_CONSTEXPR bool check_max = (-1 == ba::clamp ( -1, -10, -1 )); + BOOST_CHECK(check_max); + BOOST_CXX14_CONSTEXPR bool check_max_out = (-1 == ba::clamp ( 0, -10, -1 )); + BOOST_CHECK(check_max_out); + BOOST_CXX14_CONSTEXPR bool check_min = (-10 == ba::clamp ( -10, -10, -1 )); + BOOST_CHECK(check_min); + BOOST_CXX14_CONSTEXPR bool check_min_out = (-10 == ba::clamp ( -11, -10, -1 )); + BOOST_CHECK(check_min_out); + } + +// Mixed positive and negative numbers + { + BOOST_CXX14_CONSTEXPR bool check_inside = (5 == ba::clamp ( 5, -10, 10 )); + BOOST_CHECK(check_inside); + BOOST_CXX14_CONSTEXPR bool check_min = (-10 == ba::clamp ( -10, -10, 10 )); + BOOST_CHECK(check_min); + BOOST_CXX14_CONSTEXPR bool check_min_out = (-10 == ba::clamp ( -15, -10, 10 )); + BOOST_CHECK(check_min_out); + BOOST_CXX14_CONSTEXPR bool check_max = (10 == ba::clamp ( 10, -10, 10 )); + BOOST_CHECK(check_max); + BOOST_CXX14_CONSTEXPR bool check_max_out = (10 == ba::clamp ( 15, -10, 10 )); + BOOST_CHECK(check_max_out); + } +// Unsigned + { + BOOST_CXX14_CONSTEXPR bool check_inside = (5U == ba::clamp ( 5U, 1U, 10U )); + BOOST_CHECK(check_inside); + BOOST_CXX14_CONSTEXPR bool check_min = (1U == ba::clamp ( 1U, 1U, 10U )); + BOOST_CHECK(check_min); + BOOST_CXX14_CONSTEXPR bool check_min_out = (1U == ba::clamp ( 0U, 1U, 10U )); + BOOST_CHECK(check_min_out); + BOOST_CXX14_CONSTEXPR bool check_max = (10U == ba::clamp ( 10U, 1U, 10U )); + BOOST_CHECK(check_max); + BOOST_CXX14_CONSTEXPR bool check_max_out = (10U == ba::clamp ( 15U, 1U, 10U )); + BOOST_CHECK(check_max_out); + } +// Mixed (1) + { + BOOST_CXX14_CONSTEXPR bool check_inside = (5U == ba::clamp ( 5U, 1, 10 )); + BOOST_CHECK(check_inside); + BOOST_CXX14_CONSTEXPR bool check_min = (1U == ba::clamp ( 1U, 1, 10 )); + BOOST_CHECK(check_min); + BOOST_CXX14_CONSTEXPR bool check_min_out = (1U == ba::clamp ( 0U, 1, 10 )); + BOOST_CHECK(check_min_out); + BOOST_CXX14_CONSTEXPR bool check_max = (10U == ba::clamp ( 10U, 1, 10 )); + BOOST_CHECK(check_max); + BOOST_CXX14_CONSTEXPR bool check_max_out = (10U == ba::clamp ( 15U, 1, 10 )); + BOOST_CHECK(check_max_out); + } +// Mixed (3) + { + BOOST_CXX14_CONSTEXPR bool check_inside = (5U == ba::clamp ( 5U, 1, 10. )); + BOOST_CHECK(check_inside); + BOOST_CXX14_CONSTEXPR bool check_min = (1U == ba::clamp ( 1U, 1, 10. )); + BOOST_CHECK(check_min); + BOOST_CXX14_CONSTEXPR bool check_min_out = (1U == ba::clamp ( 0U, 1, 10. )); + BOOST_CHECK(check_min_out); + BOOST_CXX14_CONSTEXPR bool check_max = (10U == ba::clamp ( 10U, 1, 10. )); + BOOST_CHECK(check_max); + BOOST_CXX14_CONSTEXPR bool check_max_out = (10U == ba::clamp ( 15U, 1, 10. )); + BOOST_CHECK(check_max_out); + } + { + short foo = 50; + BOOST_CXX14_CONSTEXPR bool check_float = ( 56 == ba::clamp ( foo, 56.9, 129 )); + BOOST_CHECK(check_float); + BOOST_CXX14_CONSTEXPR bool check_over = ( 24910 == ba::clamp ( foo, 12345678, 123456999 )); + BOOST_CHECK(check_over); + } +} + BOOST_AUTO_TEST_CASE( test_main ) { test_ints (); @@ -217,6 +321,8 @@ BOOST_AUTO_TEST_CASE( test_main ) test_custom (); test_int_range (); + + test_constexpr (); // test_float_range (); // test_custom_range (); } diff --git a/test/copy_if_test1.cpp b/test/copy_if_test1.cpp index 1e093fd..b275f5f 100644 --- a/test/copy_if_test1.cpp +++ b/test/copy_if_test1.cpp @@ -10,6 +10,8 @@ #include #include +#include "iterator_test.hpp" + #define BOOST_TEST_MAIN #include @@ -20,6 +22,7 @@ #include #include +#include #include namespace ba = boost::algorithm; @@ -29,21 +32,8 @@ BOOST_CXX14_CONSTEXPR bool is_true ( int v ) { return true; } BOOST_CXX14_CONSTEXPR bool is_false ( int v ) { return false; } BOOST_CXX14_CONSTEXPR bool is_even ( int v ) { return v % 2 == 0; } BOOST_CXX14_CONSTEXPR bool is_odd ( int v ) { return v % 2 == 1; } +BOOST_CXX14_CONSTEXPR bool is_zero ( int v ) { return v == 0; } -BOOST_CXX14_CONSTEXPR inline bool constexpr_helper(const int* from, const int* to) { - bool res = true; - - int out_data[64] = {0}; - int* out = out_data; - ba::copy_if ( from, to, out, is_false); - - res = (res && out == out_data); - ba::copy_if ( from, to, out, is_true); - - res = (res && out == out_data + (to - from)); - - return res; -} template void test_copy_if ( Container const &c ) { @@ -170,6 +160,71 @@ void test_copy_until ( Container const &c ) { BOOST_CHECK ( ba::none_of ( v.begin (), v.end (), is_even )); BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ())); } + + +BOOST_CXX14_CONSTEXPR inline bool constexpr_test_copy_if() { + const int sz = 64; + int in_data[sz] = {0}; + bool res = true; + + const int* from = in_data; + const int* to = in_data + sz; + + int out_data[sz] = {0}; + int* out = out_data; + out = ba::copy_if ( from, to, out, is_false ); // copy none + res = (res && out == out_data); + + out = ba::copy_if ( from, to, out, is_true ); // copy all + res = (res && out == out_data + sz + && ba::equal( input_iterator(out_data), input_iterator(out_data + sz), + input_iterator(from), input_iterator(to))); + + return res; + } + +BOOST_CXX14_CONSTEXPR inline bool constexpr_test_copy_while() { + const int sz = 64; + int in_data[sz] = {0}; + bool res = true; + + const int* from = in_data; + const int* to = in_data + sz; + + int out_data[sz] = {0}; + int* out = out_data; + out = ba::copy_while ( from, to, out, is_false ).second; // copy none + res = (res && out == out_data && ba::all_of(out, out + sz, is_zero)); + + out = ba::copy_while ( from, to, out, is_true ).second; // copy all + res = (res && out == out_data + sz + && ba::equal( input_iterator(out_data), input_iterator(out_data + sz), + input_iterator(from), input_iterator(to))); + + return res; + } + +BOOST_CXX14_CONSTEXPR inline bool constexpr_test_copy_until() { + const int sz = 64; + int in_data[sz] = {0}; + bool res = true; + + const int* from = in_data; + const int* to = in_data + sz; + + int out_data[sz] = {0}; + int* out = out_data; + out = ba::copy_until ( from, to, out, is_true ).second; // copy none + res = (res && out == out_data && ba::all_of(out, out + sz, is_zero)); + + out = ba::copy_until ( from, to, out, is_false ).second; // copy all + res = (res && out == out_data + sz + && ba::equal( input_iterator(out_data), input_iterator(out_data + sz), + input_iterator(from), input_iterator(to))); + + return res; + } + void test_sequence1 () { std::vector v; @@ -179,8 +234,12 @@ void test_sequence1 () { test_copy_while ( v ); test_copy_until ( v ); - BOOST_CXX14_CONSTEXPR bool constexpr_res = constexpr_helper(0, 0); - BOOST_CHECK ( constexpr_res ); + BOOST_CXX14_CONSTEXPR bool constexpr_res_if = constexpr_test_copy_if(); + BOOST_CHECK ( constexpr_res_if ); + BOOST_CXX14_CONSTEXPR bool constexpr_res_while = constexpr_test_copy_while(); + BOOST_CHECK ( constexpr_res_while ); + BOOST_CXX14_CONSTEXPR bool constexpr_res_until = constexpr_test_copy_until(); + BOOST_CHECK ( constexpr_res_until ); std::list l; for ( int i = 25; i > 15; --i ) diff --git a/test/copy_n_test1.cpp b/test/copy_n_test1.cpp index a61c108..68284b3 100644 --- a/test/copy_n_test1.cpp +++ b/test/copy_n_test1.cpp @@ -9,6 +9,10 @@ #include #include +#include +#include + +#include "iterator_test.hpp" #define BOOST_TEST_MAIN #include @@ -21,6 +25,8 @@ namespace ba = boost::algorithm; // namespace ba = boost; +BOOST_CXX14_CONSTEXPR bool is_zero( int v ) { return v == 0; } + template void test_sequence ( Container const &c ) { @@ -67,12 +73,38 @@ void test_sequence ( Container const &c ) { } +BOOST_CXX14_CONSTEXPR inline bool test_constexpr() { + const size_t sz = 64; + int in_data[sz] = {0}; + bool res = true; + + const int* from = in_data; + const int* to = in_data + sz; + + int out_data[sz] = {0}; + int* out = out_data; + + out = ba::copy_n ( from, 0, out ); // Copy none + res = (res && out == out_data && ba::all_of(out, out + sz, is_zero)); + + out = ba::copy_n ( from, sz, out ); // Copy all + res = (res && out == out_data + sz + && ba::equal( input_iterator(out_data), input_iterator(out_data + sz), + input_iterator(from), input_iterator(to))); + + return res; + } + + void test_sequence1 () { std::vector v; for ( int i = 5; i < 15; ++i ) v.push_back ( i ); test_sequence ( v ); + BOOST_CXX14_CONSTEXPR bool constexpr_res = test_constexpr(); + BOOST_CHECK(constexpr_res); + std::list l; for ( int i = 25; i > 15; --i ) l.push_back ( i ); diff --git a/test/equal_test.cpp b/test/equal_test.cpp index c54e64d..3932098 100644 --- a/test/equal_test.cpp +++ b/test/equal_test.cpp @@ -16,7 +16,7 @@ #include template -bool eq ( const T& a, const T& b ) { return a == b; } +BOOST_CXX14_CONSTEXPR bool eq ( const T& a, const T& b ) { return a == b; } template bool never_eq ( const T&, const T& ) { return false; } @@ -123,7 +123,43 @@ void test_equal () } +BOOST_CXX14_CONSTEXPR bool test_constexpr_equal() { + int num[] = { 1, 1, 2, 3, 5}; + const int sz = sizeof (num)/sizeof(num[0]); + bool res = true; +// Empty sequences are equal to each other + res = ( ba::equal ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num)) +// Identical long sequences are equal + && ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq ) +// Different sequences are different + && !ba::equal ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz)) + ); +#ifdef __cpp_lib_array_constexpr // or cpp17 compiler +// Turn on tests for random_access_iterator, because std functions used in equal are marked constexpr_res + res = ( res +// Empty sequences are equal to each other + && ba::equal ( random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num), random_access_iterator(num)) +// Identical long sequences are equal + && ba::equal ( random_access_iterator(num), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz), + eq ) +// Different sequences are different + && !ba::equal ( random_access_iterator(num + 1), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz)) + ); +#endif + return res; + } + + BOOST_AUTO_TEST_CASE( test_main ) { test_equal (); + BOOST_CXX14_CONSTEXPR bool constexpr_res = test_constexpr_equal (); + BOOST_CHECK (constexpr_res); } diff --git a/test/find_if_not_test1.cpp b/test/find_if_not_test1.cpp index 1a17d95..2d79555 100644 --- a/test/find_if_not_test1.cpp +++ b/test/find_if_not_test1.cpp @@ -22,6 +22,29 @@ namespace ba = boost::algorithm; // namespace ba = boost; +BOOST_CXX14_CONSTEXPR bool is_true ( int v ) { return true; } +BOOST_CXX14_CONSTEXPR bool is_false ( int v ) { return false; } +BOOST_CXX14_CONSTEXPR bool is_not_three ( int v ) { return v != 3; } + +BOOST_CXX14_CONSTEXPR bool check_constexpr() { + int in_data[] = {1, 2, 3, 4, 5}; + bool res = true; + + const int* from = in_data; + const int* to = in_data + 5; + + const int* start = ba::find_if_not (from, to, is_false); // stops on first + res = (res && start == from); + + const int* end = ba::find_if_not(from, to, is_true); // stops on the end + res = (res && end == to); + + const int* three = ba::find_if_not(from, to, is_not_three); // stops on third element + res = (res && three == in_data + 2); + + return res; +} + template typename Container::iterator offset_to_iter ( Container &v, int offset ) { typename Container::iterator retval; diff --git a/test/iota_test1.cpp b/test/iota_test1.cpp index 747691f..dfc047d 100644 --- a/test/iota_test1.cpp +++ b/test/iota_test1.cpp @@ -20,7 +20,7 @@ // Test to make sure a sequence is "correctly formed"; i.e, ascending by one template -bool test_iota_results ( Iterator first, Iterator last, T initial_value ) { +BOOST_CXX14_CONSTEXPR bool test_iota_results ( Iterator first, Iterator last, T initial_value ) { if ( first == last ) return true; if ( initial_value != *first ) return false; Iterator prev = first; @@ -32,12 +32,13 @@ bool test_iota_results ( Iterator first, Iterator last, T initial_value ) { return true; } + template -bool test_iota_results ( const Range &r, T initial_value ) { +BOOST_CXX14_CONSTEXPR bool test_iota_results ( const Range &r, T initial_value ) { return test_iota_results (boost::begin (r), boost::end (r), initial_value ); } - + void test_ints () { std::vector v; std::list l; @@ -76,9 +77,38 @@ void test_ints () { boost::algorithm::iota_n ( std::front_inserter(l), 123, 20 ); BOOST_CHECK ( test_iota_results ( l.rbegin (), l.rend (), 123 )); } + +BOOST_CXX14_CONSTEXPR inline bool test_constexpr_iota() { + bool res = true; + int data[] = {0, 0, 0}; + boost::algorithm::iota(data, data, 1); // fill none + res = (res && data[0] == 0); + + boost::algorithm::iota(data, data + 3, 1); // fill all + res = (res && test_iota_results(data, data + 3, 1)); + + return res; + } + + +BOOST_CXX14_CONSTEXPR inline bool test_constexpr_iota_n() { + bool res = true; + int data[] = {0, 0, 0}; + boost::algorithm::iota_n(data, 1, 0); // fill none + res = (res && data[0] == 0); + + boost::algorithm::iota_n(data, 1, 3); // fill all + res = (res && test_iota_results(data, 1)); + + return res; + } BOOST_AUTO_TEST_CASE( test_main ) { test_ints (); + BOOST_CXX14_CONSTEXPR bool constexpr_iota_res = test_constexpr_iota (); + BOOST_CHECK(constexpr_iota_res); + BOOST_CXX14_CONSTEXPR bool constexpr_iota_n_res = test_constexpr_iota_n (); + BOOST_CHECK(constexpr_iota_n_res); } diff --git a/test/is_partitioned_test1.cpp b/test/is_partitioned_test1.cpp index 835de2d..d538a06 100644 --- a/test/is_partitioned_test1.cpp +++ b/test/is_partitioned_test1.cpp @@ -25,16 +25,27 @@ namespace ba = boost::algorithm; template struct less_than { public: - less_than ( T foo ) : val ( foo ) {} - less_than ( const less_than &rhs ) : val ( rhs.val ) {} + BOOST_CXX14_CONSTEXPR less_than ( T foo ) : val ( foo ) {} + BOOST_CXX14_CONSTEXPR less_than ( const less_than &rhs ) : val ( rhs.val ) {} - bool operator () ( const T &v ) const { return v < val; } + BOOST_CXX14_CONSTEXPR bool operator () ( const T &v ) const { return v < val; } private: less_than (); less_than operator = ( const less_than &rhs ); T val; }; + +BOOST_CXX14_CONSTEXPR bool test_constexpr() { + int v[] = { 4, 5, 6, 7, 8, 9, 10 }; + bool res = true; + res = ( res && ba::is_partitioned ( v, less_than(3))); // no elements + res = ( res && ba::is_partitioned ( v, less_than(5))); // only the first element + res = ( res && ba::is_partitioned ( v, less_than(8))); // in the middle somewhere + res = ( res && ba::is_partitioned ( v, less_than(99))); // all elements + return res; + } + void test_sequence1 () { std::vector v; @@ -61,4 +72,6 @@ void test_sequence1 () { BOOST_AUTO_TEST_CASE( test_main ) { test_sequence1 (); + BOOST_CXX14_CONSTEXPR bool constexpr_res = test_constexpr (); + BOOST_CHECK ( constexpr_res ); } diff --git a/test/iterator_test.hpp b/test/iterator_test.hpp index a79e7cf..da54456 100644 --- a/test/iterator_test.hpp +++ b/test/iterator_test.hpp @@ -30,23 +30,23 @@ public: typedef It pointer; typedef typename std::iterator_traits::reference reference; - It base() const {return it_;} + BOOST_CXX14_CONSTEXPR It base() const {return it_;} - input_iterator() : it_() {} - explicit input_iterator(It it) : it_(it) {} + BOOST_CXX14_CONSTEXPR input_iterator() : it_() {} + BOOST_CXX14_CONSTEXPR explicit input_iterator(It it) : it_(it) {} template - input_iterator(const input_iterator& u) :it_(u.it_) {} + BOOST_CXX14_CONSTEXPR input_iterator(const input_iterator& u) :it_(u.it_) {} - reference operator*() const {return *it_;} - pointer operator->() const {return it_;} + BOOST_CXX14_CONSTEXPR reference operator*() const {return *it_;} + BOOST_CXX14_CONSTEXPR pointer operator->() const {return it_;} - input_iterator& operator++() {++it_; return *this;} - input_iterator operator++(int) {input_iterator tmp(*this); ++(*this); return tmp;} + BOOST_CXX14_CONSTEXPR input_iterator& operator++() {++it_; return *this;} + BOOST_CXX14_CONSTEXPR input_iterator operator++(int) {input_iterator tmp(*this); ++(*this); return tmp;} - friend bool operator==(const input_iterator& x, const input_iterator& y) + BOOST_CXX14_CONSTEXPR friend bool operator==(const input_iterator& x, const input_iterator& y) {return x.it_ == y.it_;} - friend bool operator!=(const input_iterator& x, const input_iterator& y) + BOOST_CXX14_CONSTEXPR friend bool operator!=(const input_iterator& x, const input_iterator& y) {return !(x == y);} private: @@ -55,14 +55,14 @@ private: }; template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator==(const input_iterator& x, const input_iterator& y) { return x.base() == y.base(); } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator!=(const input_iterator& x, const input_iterator& y) { return !(x == y); @@ -79,22 +79,22 @@ public: typedef It pointer; typedef typename std::iterator_traits::reference reference; - It base() const {return it_;} + BOOST_CXX14_CONSTEXPR It base() const {return it_;} - forward_iterator() : it_() {} - explicit forward_iterator(It it) : it_(it) {} + BOOST_CXX14_CONSTEXPR forward_iterator() : it_() {} + BOOST_CXX14_CONSTEXPR explicit forward_iterator(It it) : it_(it) {} template - forward_iterator(const forward_iterator& u) :it_(u.it_) {} + BOOST_CXX14_CONSTEXPR forward_iterator(const forward_iterator& u) :it_(u.it_) {} - reference operator*() const {return *it_;} - pointer operator->() const {return it_;} + BOOST_CXX14_CONSTEXPR reference operator*() const {return *it_;} + BOOST_CXX14_CONSTEXPR pointer operator->() const {return it_;} - forward_iterator& operator++() {++it_; return *this;} - forward_iterator operator++(int) {forward_iterator tmp(*this); ++(*this); return tmp;} + BOOST_CXX14_CONSTEXPR forward_iterator& operator++() {++it_; return *this;} + BOOST_CXX14_CONSTEXPR forward_iterator operator++(int) {forward_iterator tmp(*this); ++(*this); return tmp;} - friend bool operator==(const forward_iterator& x, const forward_iterator& y) + BOOST_CXX14_CONSTEXPR friend bool operator==(const forward_iterator& x, const forward_iterator& y) {return x.it_ == y.it_;} - friend bool operator!=(const forward_iterator& x, const forward_iterator& y) + BOOST_CXX14_CONSTEXPR friend bool operator!=(const forward_iterator& x, const forward_iterator& y) {return !(x == y);} private: It it_; @@ -103,14 +103,14 @@ private: }; template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator==(const forward_iterator& x, const forward_iterator& y) { return x.base() == y.base(); } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator!=(const forward_iterator& x, const forward_iterator& y) { return !(x == y); @@ -127,35 +127,35 @@ public: typedef It pointer; typedef typename std::iterator_traits::reference reference; - It base() const {return it_;} + BOOST_CXX14_CONSTEXPR It base() const {return it_;} - bidirectional_iterator() : it_() {} - explicit bidirectional_iterator(It it) : it_(it) {} + BOOST_CXX14_CONSTEXPR bidirectional_iterator() : it_() {} + BOOST_CXX14_CONSTEXPR explicit bidirectional_iterator(It it) : it_(it) {} template - bidirectional_iterator(const bidirectional_iterator& u) :it_(u.it_) {} + BOOST_CXX14_CONSTEXPR bidirectional_iterator(const bidirectional_iterator& u) :it_(u.it_) {} - reference operator*() const {return *it_;} - pointer operator->() const {return it_;} + BOOST_CXX14_CONSTEXPR reference operator*() const {return *it_;} + BOOST_CXX14_CONSTEXPR pointer operator->() const {return it_;} - bidirectional_iterator& operator++() {++it_; return *this;} - bidirectional_iterator operator++(int) {bidirectional_iterator tmp(*this); ++(*this); return tmp;} + BOOST_CXX14_CONSTEXPR bidirectional_iterator& operator++() {++it_; return *this;} + BOOST_CXX14_CONSTEXPR bidirectional_iterator operator++(int) {bidirectional_iterator tmp(*this); ++(*this); return tmp;} - bidirectional_iterator& operator--() {--it_; return *this;} - bidirectional_iterator operator--(int) {bidirectional_iterator tmp(*this); --(*this); return tmp;} + BOOST_CXX14_CONSTEXPR bidirectional_iterator& operator--() {--it_; return *this;} + BOOST_CXX14_CONSTEXPR bidirectional_iterator operator--(int) {bidirectional_iterator tmp(*this); --(*this); return tmp;} private: It it_; template friend class bidirectional_iterator; }; template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator==(const bidirectional_iterator& x, const bidirectional_iterator& y) { return x.base() == y.base(); } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator!=(const bidirectional_iterator& x, const bidirectional_iterator& y) { return !(x == y); @@ -172,30 +172,30 @@ public: typedef It pointer; typedef typename std::iterator_traits::reference reference; - It base() const {return it_;} + BOOST_CXX14_CONSTEXPR It base() const {return it_;} - random_access_iterator() : it_() {} - explicit random_access_iterator(It it) : it_(it) {} + BOOST_CXX14_CONSTEXPR random_access_iterator() : it_() {} + BOOST_CXX14_CONSTEXPR explicit random_access_iterator(It it) : it_(it) {} template - random_access_iterator(const random_access_iterator& u) :it_(u.it_) {} + BOOST_CXX14_CONSTEXPR random_access_iterator(const random_access_iterator& u) :it_(u.it_) {} - reference operator*() const {return *it_;} - pointer operator->() const {return it_;} + BOOST_CXX14_CONSTEXPR reference operator*() const {return *it_;} + BOOST_CXX14_CONSTEXPR pointer operator->() const {return it_;} - random_access_iterator& operator++() {++it_; return *this;} - random_access_iterator operator++(int) {random_access_iterator tmp(*this); ++(*this); return tmp;} + BOOST_CXX14_CONSTEXPR random_access_iterator& operator++() {++it_; return *this;} + BOOST_CXX14_CONSTEXPR random_access_iterator operator++(int) {random_access_iterator tmp(*this); ++(*this); return tmp;} - random_access_iterator& operator--() {--it_; return *this;} - random_access_iterator operator--(int) {random_access_iterator tmp(*this); --(*this); return tmp;} + BOOST_CXX14_CONSTEXPR random_access_iterator& operator--() {--it_; return *this;} + BOOST_CXX14_CONSTEXPR random_access_iterator operator--(int) {random_access_iterator tmp(*this); --(*this); return tmp;} - random_access_iterator& operator+=(difference_type n) {it_ += n; return *this;} - random_access_iterator operator+ (difference_type n) const {random_access_iterator tmp(*this); tmp += n; return tmp;} - friend random_access_iterator operator+(difference_type n, random_access_iterator x) {x += n; return x;} + BOOST_CXX14_CONSTEXPR random_access_iterator& operator+=(difference_type n) {it_ += n; return *this;} + BOOST_CXX14_CONSTEXPR random_access_iterator operator+ (difference_type n) const {random_access_iterator tmp(*this); tmp += n; return tmp;} + BOOST_CXX14_CONSTEXPR friend random_access_iterator operator+(difference_type n, random_access_iterator x) {x += n; return x;} - random_access_iterator& operator-=(difference_type n) {return *this += -n;} - random_access_iterator operator- (difference_type n) const {random_access_iterator tmp(*this); tmp -= n; return tmp;} + BOOST_CXX14_CONSTEXPR random_access_iterator& operator-=(difference_type n) {return *this += -n;} + BOOST_CXX14_CONSTEXPR random_access_iterator operator- (difference_type n) const {random_access_iterator tmp(*this); tmp -= n; return tmp;} - reference operator[](difference_type n) const {return it_[n];} + BOOST_CXX14_CONSTEXPR reference operator[](difference_type n) const {return it_[n];} private: It it_; @@ -203,49 +203,49 @@ private: }; template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator==(const random_access_iterator& x, const random_access_iterator& y) { return x.base() == y.base(); } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator!=(const random_access_iterator& x, const random_access_iterator& y) { return !(x == y); } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator<(const random_access_iterator& x, const random_access_iterator& y) { return x.base() < y.base(); } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator<=(const random_access_iterator& x, const random_access_iterator& y) { return !(y < x); } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator>(const random_access_iterator& x, const random_access_iterator& y) { return y < x; } template -inline bool +BOOST_CXX14_CONSTEXPR inline bool operator>=(const random_access_iterator& x, const random_access_iterator& y) { return !(x < y); } template -inline typename std::iterator_traits::difference_type +BOOST_CXX14_CONSTEXPR inline typename std::iterator_traits::difference_type operator-(const random_access_iterator& x, const random_access_iterator& y) { return x.base() - y.base(); @@ -262,18 +262,18 @@ public: typedef It pointer; typedef typename std::iterator_traits::reference reference; - It base() const {return it_;} + BOOST_CXX14_CONSTEXPR It base() const {return it_;} - output_iterator () {} - explicit output_iterator(It it) : it_(it) {} + BOOST_CXX14_CONSTEXPR output_iterator () {} + BOOST_CXX14_CONSTEXPR explicit output_iterator(It it) : it_(it) {} template - output_iterator(const output_iterator& u) :it_(u.it_) {} + BOOST_CXX14_CONSTEXPR output_iterator(const output_iterator& u) :it_(u.it_) {} - reference operator*() const {return *it_;} + BOOST_CXX14_CONSTEXPR reference operator*() const {return *it_;} - output_iterator& operator++() {++it_; return *this;} - output_iterator operator++(int) {output_iterator tmp(*this); ++(*this); return tmp;} + BOOST_CXX14_CONSTEXPR output_iterator& operator++() {++it_; return *this;} + BOOST_CXX14_CONSTEXPR output_iterator operator++(int) {output_iterator tmp(*this); ++(*this); return tmp;} private: It it_; @@ -285,21 +285,21 @@ private: // == Get the base of an iterator; used for comparisons == template -inline Iter base(output_iterator i) { return i.base(); } +BOOST_CXX14_CONSTEXPR inline Iter base(output_iterator i) { return i.base(); } template -inline Iter base(input_iterator i) { return i.base(); } +BOOST_CXX14_CONSTEXPR inline Iter base(input_iterator i) { return i.base(); } template -inline Iter base(forward_iterator i) { return i.base(); } +BOOST_CXX14_CONSTEXPR inline Iter base(forward_iterator i) { return i.base(); } template -inline Iter base(bidirectional_iterator i) { return i.base(); } +BOOST_CXX14_CONSTEXPR inline Iter base(bidirectional_iterator i) { return i.base(); } template -inline Iter base(random_access_iterator i) { return i.base(); } +BOOST_CXX14_CONSTEXPR inline Iter base(random_access_iterator i) { return i.base(); } template // everything else -inline Iter base(Iter i) { return i; } +BOOST_CXX14_CONSTEXPR inline Iter base(Iter i) { return i; } #endif // ITERATORS_H diff --git a/test/mismatch_test.cpp b/test/mismatch_test.cpp index 61a7506..1c056c7 100644 --- a/test/mismatch_test.cpp +++ b/test/mismatch_test.cpp @@ -16,149 +16,176 @@ #include template -bool eq ( const T& a, const T& b ) { return a == b; } +BOOST_CXX14_CONSTEXPR bool eq ( const T& a, const T& b ) { return a == b; } template -bool never_eq ( const T&, const T& ) { return false; } +BOOST_CXX14_CONSTEXPR bool never_eq ( const T&, const T& ) { return false; } namespace ba = boost::algorithm; template -bool iter_eq ( std::pair pr, Iter1 first, Iter2 second ) { +BOOST_CXX14_CONSTEXPR bool iter_eq ( std::pair pr, Iter1 first, Iter2 second ) { return pr.first == first && pr.second == second; } void test_mismatch () { // Note: The literal values here are tested against directly, careful if you change them: - int num[] = { 1, 1, 2, 3, 5 }; + BOOST_CXX14_CONSTEXPR int num[] = { 1, 1, 2, 3, 5 }; 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))); + 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), + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num), never_eq ), - input_iterator(num), input_iterator(num))); + 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), + 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))); + 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))); + 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))); + 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))); + 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))); + 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), + 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))); + 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), + 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))); + 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), + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1), never_eq ), - input_iterator(num), input_iterator(num))); + 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), + 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))); + 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))); + 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), + 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))); + 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))); + 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), + 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))); + 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))); + 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), + 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))); + 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), + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), never_eq ), - input_iterator(num), input_iterator(num))); + input_iterator(num), input_iterator(num))); BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + sz), - random_access_iterator(num), random_access_iterator(num + sz), + 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))); + input_iterator(num), random_access_iterator(num))); -// different sequences are different +// 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))); + 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), + 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))); - + input_iterator(num + 2), input_iterator(num + 1))); + +// Checks constexpr + BOOST_CXX14_CONSTEXPR bool res = ( +// No mismatch for empty + iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num)), + input_iterator(num), input_iterator(num)) +// Empty vs. non-empty mismatch immediately + && iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num + 1)), + input_iterator(num), input_iterator(num)) +// Single element sequences are equal if they contain the same value + && 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)) +// Identical long sequences are equal. + && 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 ( res ); } diff --git a/test/none_of_test.cpp b/test/none_of_test.cpp index fc74945..dc7b30b 100644 --- a/test/none_of_test.cpp +++ b/test/none_of_test.cpp @@ -19,9 +19,9 @@ template struct is_ : public std::unary_function { - is_ ( T v ) : val_ ( v ) {} - ~is_ () {} - bool operator () ( T comp ) const { return val_ == comp; } + BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} + + BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value @@ -33,7 +33,7 @@ namespace ba = boost::algorithm; void test_none() { // Note: The literal values here are tested against directly, careful if you change them: - int some_numbers[] = { 1, 5, 0, 18, 1 }; + BOOST_CXX14_CONSTEXPR int some_numbers[] = { 1, 5, 0, 18, 1 }; std::vector vi(some_numbers, some_numbers + 5); std::list li(vi.begin(), vi.end ()); @@ -89,6 +89,14 @@ void test_none() BOOST_CHECK ( ba::none_of_equal ( li.begin(), l_iter, 18 )); BOOST_CHECK ( ba::none_of ( li.begin(), l_iter, is_ ( 18 ))); BOOST_CHECK (!ba::none_of ( li.begin(), l_iter, is_ ( 5 ))); + + BOOST_CXX14_CONSTEXPR bool constexpr_res = ( + !ba::none_of_equal ( some_numbers, 1 ) + && !ba::none_of ( some_numbers, is_ ( 1 )) + && ba::none_of_equal ( some_numbers, some_numbers + 3, 100 ) + && ba::none_of ( some_numbers, some_numbers + 3, is_ ( 100 )) + ); + BOOST_CHECK ( constexpr_res ); } BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/one_of_test.cpp b/test/one_of_test.cpp index 9422881..49e3d5a 100644 --- a/test/one_of_test.cpp +++ b/test/one_of_test.cpp @@ -19,9 +19,9 @@ template struct is_ : public std::unary_function { - is_ ( T v ) : val_ ( v ) {} - ~is_ () {} - bool operator () ( T comp ) const { return val_ == comp; } + BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} + + BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value @@ -33,7 +33,7 @@ namespace ba = boost::algorithm; void test_one () { // Note: The literal values here are tested against directly, careful if you change them: - int some_numbers[] = { 1, 1, 2, 3, 5 }; + BOOST_CXX14_CONSTEXPR int some_numbers[] = { 1, 1, 2, 3, 5 }; std::vector vi(some_numbers, some_numbers + 5); std::list li(vi.begin(), vi.end ()); @@ -92,7 +92,13 @@ void test_one () BOOST_CHECK ( ba::one_of ( li.begin(), l_iter, is_ ( 2 ))); BOOST_CHECK (!ba::one_of_equal ( li.begin(), l_iter, 3 )); BOOST_CHECK (!ba::one_of ( li.begin(), l_iter, is_ ( 3 ))); + + BOOST_CXX14_CONSTEXPR bool constexpr_res = ( + !ba::one_of ( some_numbers, is_ ( 6 )) + && ba::one_of ( some_numbers, some_numbers + 3, is_ ( 1 )) + ); + BOOST_CHECK ( constexpr_res ); } diff --git a/test/ordered_test.cpp b/test/ordered_test.cpp index dbaf940..f2cbdd7 100644 --- a/test/ordered_test.cpp +++ b/test/ordered_test.cpp @@ -29,11 +29,13 @@ using namespace boost; namespace ba = boost::algorithm; +BOOST_CXX14_CONSTEXPR bool less( int x, int y ) { return x < y; } + static void test_ordered(void) { - const int strictlyIncreasingValues[] = { 1, 2, 3, 4, 5 }; - const int randomValues[] = { 3, 6, 1, 2, 7 }; + BOOST_CXX14_CONSTEXPR const int strictlyIncreasingValues[] = { 1, 2, 3, 4, 5 }; + BOOST_CXX14_CONSTEXPR const int randomValues[] = { 3, 6, 1, 2, 7 }; const int constantValues[] = { 1, 2, 2, 2, 5 }; int nonConstantArray[] = { 1, 2, 2, 2, 5 }; const int inOrderUntilTheEnd [] = { 0, 1, 2, 3, 4, 5, 6, 7, 6 }; @@ -74,18 +76,26 @@ test_ordered(void) BOOST_CHECK ( ba::is_sorted_until ( a_begin(randomValues), a_begin(randomValues)) == a_begin(randomValues)); BOOST_CHECK ( ba::is_sorted_until ( a_begin(randomValues), a_begin(randomValues) + 1, std::equal_to()) == a_begin(randomValues) + 1); BOOST_CHECK ( ba::is_sorted_until ( a_begin(randomValues), a_begin(randomValues) + 1 ) == a_begin(randomValues) + 1); + + BOOST_CXX14_CONSTEXPR bool constexpr_res = ( + ba::is_sorted ( boost::begin(strictlyIncreasingValues), boost::end(strictlyIncreasingValues) ) + && !ba::is_sorted (a_range(randomValues)) + && ba::is_sorted_until ( boost::begin(strictlyIncreasingValues), boost::end(strictlyIncreasingValues), less) == a_end(strictlyIncreasingValues) + && ba::is_sorted_until ( randomValues, less) == &randomValues[2] + ); + BOOST_CHECK ( constexpr_res ); } static void test_increasing_decreasing(void) { - const int strictlyIncreasingValues[] = { 1, 2, 3, 4, 5 }; - const int strictlyDecreasingValues[] = { 9, 8, 7, 6, 5 }; - const int increasingValues[] = { 1, 2, 2, 2, 5 }; - const int decreasingValues[] = { 9, 7, 7, 7, 5 }; - const int randomValues[] = { 3, 6, 1, 2, 7 }; - const int constantValues[] = { 7, 7, 7, 7, 7 }; + BOOST_CXX14_CONSTEXPR const int strictlyIncreasingValues[] = { 1, 2, 3, 4, 5 }; + BOOST_CXX14_CONSTEXPR const int strictlyDecreasingValues[] = { 9, 8, 7, 6, 5 }; + BOOST_CXX14_CONSTEXPR const int increasingValues[] = { 1, 2, 2, 2, 5 }; + BOOST_CXX14_CONSTEXPR const int decreasingValues[] = { 9, 7, 7, 7, 5 }; + BOOST_CXX14_CONSTEXPR const int randomValues[] = { 3, 6, 1, 2, 7 }; + BOOST_CXX14_CONSTEXPR const int constantValues[] = { 7, 7, 7, 7, 7 }; // Test a strictly increasing sequence BOOST_CHECK ( ba::is_strictly_increasing (b_e(strictlyIncreasingValues))); @@ -146,6 +156,15 @@ test_increasing_decreasing(void) BOOST_CHECK ( !ba::is_strictly_decreasing (strictlyIncreasingValues, strictlyIncreasingValues+2)); BOOST_CHECK ( !ba::is_decreasing (strictlyIncreasingValues, strictlyIncreasingValues+2)); + BOOST_CXX14_CONSTEXPR bool constexpr_res = ( + ba::is_increasing (boost::begin(increasingValues), boost::end(increasingValues)) + && ba::is_decreasing (boost::begin(decreasingValues), boost::end(decreasingValues)) + && ba::is_strictly_increasing (boost::begin(strictlyIncreasingValues), boost::end(strictlyIncreasingValues)) + && ba::is_strictly_decreasing (boost::begin(strictlyDecreasingValues), boost::end(strictlyDecreasingValues)) + && !ba::is_strictly_increasing (boost::begin(increasingValues), boost::end(increasingValues)) + && !ba::is_strictly_decreasing (boost::begin(decreasingValues), boost::end(decreasingValues)) + ); + BOOST_CHECK ( constexpr_res ); } BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/partition_copy_test1.cpp b/test/partition_copy_test1.cpp index c3afb1e..4499f40 100644 --- a/test/partition_copy_test1.cpp +++ b/test/partition_copy_test1.cpp @@ -47,10 +47,10 @@ void test_sequence ( const Container &c, Predicate comp ) { template struct less_than { public: - less_than ( T foo ) : val ( foo ) {} - less_than ( const less_than &rhs ) : val ( rhs.val ) {} + BOOST_CXX14_CONSTEXPR less_than ( T foo ) : val ( foo ) {} + BOOST_CXX14_CONSTEXPR less_than ( const less_than &rhs ) : val ( rhs.val ) {} - bool operator () ( const T &v ) const { return v < val; } + BOOST_CXX14_CONSTEXPR bool operator () ( const T &v ) const { return v < val; } private: less_than (); less_than operator = ( const less_than &rhs ); @@ -81,8 +81,30 @@ void test_sequence1 () { } + +BOOST_CXX14_CONSTEXPR bool test_constexpr () { + int in[] = {1, 1, 2}; + int out_true[3] = {0}; + int out_false[3] = {0}; + bool res = true; + ba::partition_copy( in, in + 3, out_true, out_false, less_than(2) ); + res = (res && ba::all_of(out_true, out_true + 2, less_than(2)) ); + res = (res && ba::none_of(out_false, out_false + 1, less_than(2)) ); + +// clear elements + out_true [0] = 0; + out_true [1] = 0; + out_false[0] = 0; + + ba::partition_copy( in, out_true, out_false, less_than(2)); + res = ( res && ba::all_of(out_true, out_true + 2, less_than(2))); + res = ( res && ba::none_of(out_false, out_false + 1, less_than(2))); + return res; + } BOOST_AUTO_TEST_CASE( test_main ) { test_sequence1 (); + BOOST_CXX14_CONSTEXPR bool constexpr_res = test_constexpr (); + BOOST_CHECK ( constexpr_res ); } diff --git a/test/power_test.cpp b/test/power_test.cpp index c1d5c23..c608a8b 100644 --- a/test/power_test.cpp +++ b/test/power_test.cpp @@ -18,7 +18,7 @@ namespace ba = boost::algorithm; -BOOST_AUTO_TEST_CASE( test_main ) +void test_power () { BOOST_CHECK ( ba::power(0, 0) == 1); BOOST_CHECK ( ba::power(5, 0) == 1); @@ -34,3 +34,51 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK ( ba::power(3,2) == ba::power(3,2, std::multiplies())); BOOST_CHECK ( ba::power(3,2, std::plus()) == 6); } + + +void test_power_constexpr () +{ + BOOST_CXX14_CONSTEXPR bool check_zero_power1 = + ba::power(0, 0) == 1; + BOOST_CHECK(check_zero_power1); + BOOST_CXX14_CONSTEXPR bool check_zero_power2 = + ba::power(5, 0) == 1; + BOOST_CHECK(check_zero_power2); + BOOST_CXX14_CONSTEXPR bool check_one_base1 = + ba::power(1, 1) == 1; + BOOST_CHECK(check_one_base1); + BOOST_CXX14_CONSTEXPR bool check_one_base2 = + ba::power(1, 4) == 1; + BOOST_CHECK(check_one_base2); + BOOST_CXX14_CONSTEXPR bool check_power1 = + ba::power(3, 2) == 9; + BOOST_CHECK(check_power1); + BOOST_CXX14_CONSTEXPR bool check_power2 = + ba::power(2, 3) == 8; + BOOST_CHECK(check_power2); + BOOST_CXX14_CONSTEXPR bool check_power3 = + ba::power(3, 3) == 27; + BOOST_CHECK(check_power1); + BOOST_CXX14_CONSTEXPR bool check_power4 = + ba::power(2, 30) == 0x40000000; + BOOST_CHECK(check_power4); + BOOST_CXX14_CONSTEXPR bool check_power5 = + ba::power(5L, 10) == 3125*3125; + BOOST_CHECK(check_power5); + BOOST_CXX14_CONSTEXPR bool check_power6 = + ba::power(18, 3) == 18*18*18; + BOOST_CHECK(check_power6); + + BOOST_CXX14_CONSTEXPR bool check_multiple = + ba::power(3, 2, std::multiplies()) == ba::power(3, 2); + BOOST_CHECK(check_multiple); + BOOST_CXX14_CONSTEXPR bool check_plus = + ba::power(3, 2, std::plus()) == 6; + BOOST_CHECK(check_plus); +} + + +BOOST_AUTO_TEST_CASE( test_main ) { + test_power (); + test_power_constexpr (); +} From 1ed284d6961505a1d57d94b4ab07fdb2b0eff2e5 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Thu, 18 May 2017 20:38:07 -0600 Subject: [PATCH 03/20] Added initial for apply_permutation --- example/apply_permutation_example.cpp | 68 ++++++++++ include/boost/algorithm/apply_permutation.hpp | 122 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 example/apply_permutation_example.cpp create mode 100644 include/boost/algorithm/apply_permutation.hpp diff --git a/example/apply_permutation_example.cpp b/example/apply_permutation_example.cpp new file mode 100644 index 0000000..feaa9f2 --- /dev/null +++ b/example/apply_permutation_example.cpp @@ -0,0 +1,68 @@ +/* + Copyright (c) Alexander Zaitsev , 2017 + + 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) + + See http://www.boost.org/ for latest version. +*/ + +#include +#include + +#include + + +namespace ba = boost::algorithm; + +int main ( int /*argc*/, char * /*argv*/ [] ) +{ + { + std::cout << "apply_permutation with iterators:\n"; + std::vector vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0}; + + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + for (const auto& x : vec) + { + std::cout << x << ", "; + } + std::cout << std::endl; + } + { + std::cout << "apply_reverse_permutation with iterators:\n"; + std::vector vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0}; + + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + for (const auto& x : vec) + { + std::cout << x << ", "; + } + std::cout << std::endl; + } + { + std::cout << "apply_reverse_permutation with ranges:\n"; + std::vector vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0}; + + ba::apply_reverse_permutation(vec, order); + for (const auto& x : vec) + { + std::cout << x << ", "; + } + std::cout << std::endl; + } + { + std::cout << "apply_permutation with ranges:\n"; + std::vector vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0}; + + ba::apply_permutation(vec, order); + for (const auto& x : vec) + { + std::cout << x << ", "; + } + std::cout << std::endl; + } + + return 0; +} + diff --git a/include/boost/algorithm/apply_permutation.hpp b/include/boost/algorithm/apply_permutation.hpp new file mode 100644 index 0000000..f14ba65 --- /dev/null +++ b/include/boost/algorithm/apply_permutation.hpp @@ -0,0 +1,122 @@ +/* + Copyright (c) Alexander Zaitsev , 2017 + + 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) + + See http://www.boost.org/ for latest version. + + + Based on https://blogs.msdn.microsoft.com/oldnewthing/20170104-00/?p=95115 +*/ + +/// \file apply_permutation.hpp +/// \brief Apply permutation to a sequence. +/// \author Alexander Zaitsev + +#ifndef BOOST_ALGORITHM_APPLY_PERMUTATION_HPP +#define BOOST_ALGORITHM_APPLY_PERMUTATION_HPP + +#include +#include + +#include +#include + +namespace boost { namespace algorithm +{ + +/// \fn apply_permutation ( RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, RandomAccessIterator2 ind_begin ) +/// \brief Reorder item sequence with index sequence order +/// +/// \param item_begin The start of the item sequence +/// \param item_end One past the end of the item sequence +/// \param ind_begin The start of the index sequence. +/// +/// \note Item sequence size should be equal to index size. Otherwise behavior is undefined. +/// Complexity: O(N). +template +void +apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, + RandomAccessIterator2 ind_begin) +{ + using Diff = typename std::iterator_traits::difference_type; + Diff size = std::distance(item_begin, item_end); + for (Diff i = 0; i < size; i++) + { + auto current = i; + while (i != ind_begin[current]) + { + auto next = ind_begin[current]; + std::swap(item_begin[current], item_begin[next]); + ind_begin[current] = current; + current = next; + } + ind_begin[current] = current; + } +} + +/// \fn apply_reverse_permutation ( RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, RandomAccessIterator2 ind_begin ) +/// \brief Reorder item sequence with index sequence order +/// +/// \param item_begin The start of the item sequence +/// \param item_end One past the end of the item sequence +/// \param ind_begin The start of the index sequence. +/// +/// \note Item sequence size should be equal to index size. Otherwise behavior is undefined. +/// Complexity: O(N). +template +void +apply_reverse_permutation( + RandomAccessIterator1 item_begin, + RandomAccessIterator1 item_end, + RandomAccessIterator2 ind_begin) +{ + using Diff = typename std::iterator_traits::difference_type; + Diff length = std::distance(item_begin, item_end); + for (Diff i = 0; i < length; i++) + { + while (i != ind_begin[i]) + { + Diff next = ind_begin[i]; + std::swap(item_begin[i], item_begin[next]); + std::swap(ind_begin[i], ind_begin[next]); + } + } +} + +/// \fn apply_permutation ( Range1 item_range, Range2 ind_range ) +/// \brief Reorder item sequence with index sequence order +/// +/// \param item_range The item sequence +/// \param ind_range The index sequence +/// +/// \note Item sequence size should be equal to index size. Otherwise behavior is undefined. +/// Complexity: O(N). +template +void +apply_permutation(Range1& item_range, Range2& ind_range) +{ + apply_permutation(boost::begin(item_range), boost::end(item_range), + boost::begin(ind_range)); +} + +/// \fn apply_reverse_permutation ( Range1 item_range, Range2 ind_range ) +/// \brief Reorder item sequence with index sequence order +/// +/// \param item_range The item sequence +/// \param ind_range The index sequence +/// +/// \note Item sequence size should be equal to index size. Otherwise behavior is undefined. +/// Complexity: O(N). +template +void +apply_reverse_permutation(Range1& item_range, Range2& ind_range) +{ + apply_reverse_permutation(boost::begin(item_range), boost::end(item_range), + boost::begin(ind_range)); +} + +}} +#endif //BOOST_ALGORITHM_APPLY_PERMUTATION_HPP From 1970454ecbe0a5964a3b21552fcae6ecc27436a6 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Thu, 18 May 2017 23:33:26 -0600 Subject: [PATCH 04/20] Added test --- test/apply_permutation_test.cpp | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 test/apply_permutation_test.cpp diff --git a/test/apply_permutation_test.cpp b/test/apply_permutation_test.cpp new file mode 100644 index 0000000..4716520 --- /dev/null +++ b/test/apply_permutation_test.cpp @@ -0,0 +1,122 @@ +/* + Copyright (c) Alexander Zaitsev , 2017 + + 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) + + See http://www.boost.org/ for latest version. +*/ + +#include +#include +#include +#include +#include + +#include + +#define BOOST_TEST_MAIN + +#include + +namespace ba = boost::algorithm; + + +void test_apply_permutation() +{ + //Empty + { + std::vector vec, order, result; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //1 element + { + std::vector vec{1}, order{0}, result{1}; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //2 elements, no changes + { + std::vector vec{1, 2}, order{0, 1}, result{1, 2}; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //2 elements, changed + { + std::vector vec{1, 2}, order{1, 0}, result{2, 1}; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //Multiple elements, no changes + { + std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //Multiple elements, changed + { + std::vector vec{1, 2, 3, 4, 5}, order{4, 3, 2, 1, 0}, result{5, 4, 3, 2, 1}; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //Just test range interface + { + std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + ba::apply_permutation(vec, order); + BOOST_CHECK(vec == result); + } +} + +void test_apply_reverse_permutation() +{ + //Empty + { + std::vector vec, order, result; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //1 element + { + std::vector vec{1}, order{0}, result{1}; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //2 elements, no changes + { + std::vector vec{1, 2}, order{0, 1}, result{1, 2}; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //2 elements, changed + { + std::vector vec{1, 2}, order{1, 0}, result{2, 1}; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //Multiple elements, no changes + { + std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //Multiple elements, changed + { + std::vector vec{1, 2, 3, 4, 5}, order{4, 3, 2, 1, 0}, result{5, 4, 3, 2, 1}; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + BOOST_CHECK(vec == result); + } + //Just test range interface + { + std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + ba::apply_reverse_permutation(vec, order); + BOOST_CHECK(vec == result); + } +} + +BOOST_AUTO_TEST_CASE(test_main) +{ + test_apply_permutation(); + test_apply_reverse_permutation(); +} From ba7655eb3a7ac2cab16f6d573355fce4a497a933 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Fri, 19 May 2017 16:59:11 -0600 Subject: [PATCH 05/20] Add documentation --- doc/apply_permutation.qbk | 85 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 doc/apply_permutation.qbk diff --git a/doc/apply_permutation.qbk b/doc/apply_permutation.qbk new file mode 100644 index 0000000..952195d --- /dev/null +++ b/doc/apply_permutation.qbk @@ -0,0 +1,85 @@ +[/ File apply_permutation.qbk] + +[section:apply_permutation apply_permutation] + +[/license +Copyright (c) 2017 Alexander Zaitsev + +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) +] + +The header file 'apply_permutation.hpp' contains two algorithms, apply_permutation and apply_reverse_permutation. Also there are range-based versions. +The algorithms transform the item sequence according to index sequence order. + +The routine `apply_permutation` takes a item sequence and a order sequence. It reshuffles item sequence according to order sequence. Every value in order sequence means where the item comes from. +The routine `apply_reverse_permutation` takes a item sequence and a order sequence. It will reshuffle item sequence according to order sequence. Every value in order sequence means where the item goes to. + +The routines come in 2 forms; the first one takes two iterators to define the item range and one iterator to define the beginning of index range. The second form takes range to define the item sequence and range to define index sequence. + + +[heading interface] + +There are two versions of algorithms: +1) takes three iterators. +2) takes two ranges. +`` +template +void apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, + RandomAccessIterator2 ind_begin); +template +void apply_permutation(Range1& item_range, Range2& ind_range); +template +void apply_reverse_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, + RandomAccessIterator2 ind_begin); +template +void apply_reverse_permutation(Range1& item_range, Range2& ind_range); +`` + + +[heading Examples] + +Given the containers: +std::vector emp_vec, emp_order, +std::vector one{1}, one_order{0}, +std::vector two{1,2}, two_order{1,0}, +std::vector vec{1, 2, 3, 4, 5}, +std::vector order{4, 2, 3, 1, 0}, then +`` + +apply_permutation(emp_vec, emp_order)) --> no changes +apply_reverse_permutation(emp_vec, emp_order)) --> no changes +apply_permutation(one, one_order) --> no changes +apply_reverse_permutation(one, one_order) --> no changes +apply_permutation(two, two_order) --> two:{2,1} +apply_reverse_permutation(two, two_order) --> two:{2,1} +apply_permutation(vec, order) --> vec:{5, 3, 4, 2, 1} +apply_reverse_permutation(vec, order) --> vec:{5, 4, 2, 3, 1} +`` + +[heading Iterator Requirements] + +`apply_permutation` and 'apply_reverse_permutation' work only on RandomAccess iterators. RandomAccess iterators required both for item and index sequences. + +[heading Complexity] + +All of the variants of `apply_permutation` and `apply_reverse_permutation` run in ['O(N)] (linear) time. + +[heading Exception Safety] + +All of the variants of `apply_permutation` and `apply_reverse_permutation` take their parameters by iterators or reference, and do not depend upon any global state. Therefore, all the routines in this file provide the strong exception guarantee. + +[heading Notes] +* If ItemSequence and IndexSequence are not equal, behavior is undefined. + +* `apply_permutation` and `apply_reverse_permutation` work also on empty sequences. + +* Order sequence must be zero-indexed. + +[endsect] + +[/ File apply_permutation.qbk +Copyright 2017 Alexander Zaitsev +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). +] From e07e8e65c680026aa9859a0fdc13751b0d18a6ed Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Fri, 19 May 2017 18:50:03 -0600 Subject: [PATCH 06/20] Fixed references --- doc/algorithm.qbk | 1 + example/Jamfile.v2 | 2 +- test/Jamfile.v2 | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index becad46..8ce6685 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -68,6 +68,7 @@ Thanks to all the people who have reviewed this library and made suggestions for [include hex.qbk] [include is_palindrome.qbk] [include is_partitioned_until.qbk] +[include apply_permutation.qbk] [endsect] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 4512a53..100878c 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -22,4 +22,4 @@ exe clamp_example : clamp_example.cpp ; exe search_example : search_example.cpp ; exe is_palindrome_example : is_palindrome_example.cpp; exe is_partitioned_until_example : is_partitioned_until_example.cpp; - +exe apply_permutation_example : apply_permutation_example.cpp; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fad1578..0b5ae35 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -73,6 +73,9 @@ alias unit_test_framework # Is_partitioned_until tests [ run is_partitioned_until_test.cpp unit_test_framework : : : : is_partitioned_until_test ] + +# Apply_permutation tests + [ run apply_permutation_test.cpp unit_test_framework : : : : apply_permutation_test ] ; } From 000040b3d996f1ab888596597dfc0d2387e1304c Mon Sep 17 00:00:00 2001 From: Mike Maximoff Date: Mon, 19 Jun 2017 19:03:00 +0300 Subject: [PATCH 07/20] binary_function is removed from equal and unary_function removed from tests. --- include/boost/algorithm/cxx14/equal.hpp | 2 +- test/all_of_test.cpp | 2 +- test/any_of_test.cpp | 2 +- test/none_of_test.cpp | 2 +- test/one_of_test.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/algorithm/cxx14/equal.hpp b/include/boost/algorithm/cxx14/equal.hpp index 4d7b063..857435b 100644 --- a/include/boost/algorithm/cxx14/equal.hpp +++ b/include/boost/algorithm/cxx14/equal.hpp @@ -27,7 +27,7 @@ namespace boost { namespace algorithm { namespace detail { template - struct eq : public std::binary_function { + struct eq { BOOST_CONSTEXPR bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} }; diff --git a/test/all_of_test.cpp b/test/all_of_test.cpp index 4bd3512..a720b0c 100644 --- a/test/all_of_test.cpp +++ b/test/all_of_test.cpp @@ -18,7 +18,7 @@ #include template -struct is_ : public std::unary_function { +struct is_ { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: diff --git a/test/any_of_test.cpp b/test/any_of_test.cpp index ac089d6..193356c 100644 --- a/test/any_of_test.cpp +++ b/test/any_of_test.cpp @@ -18,7 +18,7 @@ #include template -struct is_ : public std::unary_function { +struct is_ { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: diff --git a/test/none_of_test.cpp b/test/none_of_test.cpp index d4226e2..9522175 100644 --- a/test/none_of_test.cpp +++ b/test/none_of_test.cpp @@ -18,7 +18,7 @@ #include template -struct is_ : public std::unary_function { +struct is_ { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: diff --git a/test/one_of_test.cpp b/test/one_of_test.cpp index 807a937..22ccca2 100644 --- a/test/one_of_test.cpp +++ b/test/one_of_test.cpp @@ -18,7 +18,7 @@ #include template -struct is_ : public std::unary_function { +struct is_ { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: @@ -94,7 +94,7 @@ void test_one () BOOST_CXX14_CONSTEXPR bool constexpr_res = ( !ba::one_of ( some_numbers, is_ ( 6 )) - && ba::one_of ( some_numbers, some_numbers + 3, is_ ( 1 )) + && ba::one_of ( some_numbers + 1, some_numbers + 3, is_ ( 1 )) ); BOOST_CHECK ( constexpr_res ); From 15c7ff3828578cab37f2a4403c6f126fef90ef92 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Wed, 19 Jul 2017 02:15:06 +0300 Subject: [PATCH 08/20] Fixed compatibility with old compilers --- example/apply_permutation_example.cpp | 1 + include/boost/algorithm/apply_permutation.hpp | 18 ++--- test/apply_permutation_test.cpp | 79 +++++++++++++++---- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/example/apply_permutation_example.cpp b/example/apply_permutation_example.cpp index feaa9f2..16c84b6 100644 --- a/example/apply_permutation_example.cpp +++ b/example/apply_permutation_example.cpp @@ -18,6 +18,7 @@ namespace ba = boost::algorithm; int main ( int /*argc*/, char * /*argv*/ [] ) { + // WARNING: Example require C++11 or newer compiler { std::cout << "apply_permutation with iterators:\n"; std::vector vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0}; diff --git a/include/boost/algorithm/apply_permutation.hpp b/include/boost/algorithm/apply_permutation.hpp index f14ba65..1f1cdcf 100644 --- a/include/boost/algorithm/apply_permutation.hpp +++ b/include/boost/algorithm/apply_permutation.hpp @@ -19,7 +19,7 @@ #define BOOST_ALGORITHM_APPLY_PERMUTATION_HPP #include -#include +#include #include #include @@ -41,14 +41,14 @@ void apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, RandomAccessIterator2 ind_begin) { - using Diff = typename std::iterator_traits::difference_type; + typedef typename std::iterator_traits::difference_type Diff; Diff size = std::distance(item_begin, item_end); - for (Diff i = 0; i < size; i++) + for (Diff i = 0; i < size; ++i) { - auto current = i; + Diff current = i; while (i != ind_begin[current]) { - auto next = ind_begin[current]; + Diff next = static_cast(ind_begin[current]); std::swap(item_begin[current], item_begin[next]); ind_begin[current] = current; current = next; @@ -68,14 +68,12 @@ apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_e /// Complexity: O(N). template void -apply_reverse_permutation( - RandomAccessIterator1 item_begin, - RandomAccessIterator1 item_end, +apply_reverse_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, RandomAccessIterator2 ind_begin) { - using Diff = typename std::iterator_traits::difference_type; + typedef typename std::iterator_traits::difference_type Diff; Diff length = std::distance(item_begin, item_end); - for (Diff i = 0; i < length; i++) + for (Diff i = 0; i < length; ++i) { while (i != ind_begin[i]) { diff --git a/test/apply_permutation_test.cpp b/test/apply_permutation_test.cpp index 4716520..4dc08e7 100644 --- a/test/apply_permutation_test.cpp +++ b/test/apply_permutation_test.cpp @@ -9,13 +9,10 @@ */ #include -#include -#include -#include -#include #include +#define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #include @@ -28,42 +25,67 @@ void test_apply_permutation() //Empty { std::vector vec, order, result; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //1 element { - std::vector vec{1}, order{0}, result{1}; + std::vector vec, order, result; + vec.push_back(1); + order.push_back(0); + result = vec; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //2 elements, no changes { - std::vector vec{1, 2}, order{0, 1}, result{1, 2}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); + order.push_back(0); order.push_back(1); + result = vec; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //2 elements, changed { - std::vector vec{1, 2}, order{1, 0}, result{2, 1}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); + order.push_back(1); order.push_back(0); + result.push_back(2); result.push_back(1); + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //Multiple elements, no changes { - std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); + order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4); + result = vec; + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //Multiple elements, changed { - std::vector vec{1, 2, 3, 4, 5}, order{4, 3, 2, 1, 0}, result{5, 4, 3, 2, 1}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); + order.push_back(4); order.push_back(3); order.push_back(2); order.push_back(1); order.push_back(0); + result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1); + ba::apply_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //Just test range interface { - std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); + order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4); + result = vec; + ba::apply_permutation(vec, order); BOOST_CHECK(vec == result); } @@ -74,42 +96,67 @@ void test_apply_reverse_permutation() //Empty { std::vector vec, order, result; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //1 element { - std::vector vec{1}, order{0}, result{1}; + std::vector vec, order, result; + vec.push_back(1); + order.push_back(0); + result = vec; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //2 elements, no changes { - std::vector vec{1, 2}, order{0, 1}, result{1, 2}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); + order.push_back(0); order.push_back(1); + result = vec; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //2 elements, changed { - std::vector vec{1, 2}, order{1, 0}, result{2, 1}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); + order.push_back(1); order.push_back(0); + result.push_back(2); result.push_back(1); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //Multiple elements, no changes { - std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); + order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4); + result = vec; + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //Multiple elements, changed { - std::vector vec{1, 2, 3, 4, 5}, order{4, 3, 2, 1, 0}, result{5, 4, 3, 2, 1}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); + order.push_back(4); order.push_back(3); order.push_back(2); order.push_back(1); order.push_back(0); + result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); BOOST_CHECK(vec == result); } //Just test range interface { - std::vector vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5}; + std::vector vec, order, result; + vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); + order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4); + result = vec; + ba::apply_reverse_permutation(vec, order); BOOST_CHECK(vec == result); } From 32016b3c79a9c0c36724e56831964f603b85d398 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Wed, 19 Jul 2017 22:10:29 +0300 Subject: [PATCH 09/20] Fixed missed header for std::swap --- include/boost/algorithm/apply_permutation.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/algorithm/apply_permutation.hpp b/include/boost/algorithm/apply_permutation.hpp index 1f1cdcf..d4aa958 100644 --- a/include/boost/algorithm/apply_permutation.hpp +++ b/include/boost/algorithm/apply_permutation.hpp @@ -19,6 +19,7 @@ #define BOOST_ALGORITHM_APPLY_PERMUTATION_HPP #include +#include #include #include From 8ae18ae4550ac2b3b94e64f7730965d57d1efdd0 Mon Sep 17 00:00:00 2001 From: Daniela Engert Date: Sat, 22 Apr 2017 17:13:39 +0200 Subject: [PATCH 10/20] Conditionally replace deprecated c++98 features by c++11 ones change std::random_shuffle -> std::shuffle + random_engine if indicated by the supported language level or Boost configuration macro. Signed-off-by: Daniela Engert --- minmax/test/minmax_element_test.cpp | 19 ++++++++++++++++--- test/partition_subrange_test.cpp | 10 +++++----- test/sort_subrange_test.cpp | 8 ++++---- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/minmax/test/minmax_element_test.cpp b/minmax/test/minmax_element_test.cpp index b8c02f5..11cf2c4 100644 --- a/minmax/test/minmax_element_test.cpp +++ b/minmax/test/minmax_element_test.cpp @@ -20,6 +20,19 @@ #define BOOST_TEST_MAIN #include +#if (__cplusplus >= 201103L) || defined(BOOST_NO_CXX98_RANDOM_SHUFFLE) +#include + +std::default_random_engine gen; +template +void do_shuffle(RandomIt first, RandomIt last) +{ std::shuffle(first, last, gen); } +#else +template +void do_shuffle(RandomIt first, RandomIt last) +{ std::random_shuffle(first, last); } +#endif + class custom { int m_x; friend bool operator<(custom const& x, custom const& y); @@ -117,7 +130,7 @@ void test_minmax(CIterator first, CIterator last, int n) CHECK_EQUAL_ITERATORS( min, std::min_element(first, last), first ); CHECK_EQUAL_ITERATORS( max, std::max_element(first, last), first ); - + // second version, comp function object (keeps a counter!) lc.reset(); tie( boost::minmax_element(first, last, lc), min, max ); @@ -183,7 +196,7 @@ void test_minmax(CIterator first, CIterator last, int n) template void test_container(Iterator first, Iterator last, int n, - Container* dummy = 0 + Container* /* dummy */ = 0 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Value) ) { Container c(first, last); @@ -223,7 +236,7 @@ void test(int n BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Value)) test_range(first, last, n); // Populate test vector with random values - std::random_shuffle(first, last); + do_shuffle(first, last); test_range(first, last, n); } diff --git a/test/partition_subrange_test.cpp b/test/partition_subrange_test.cpp index c33fb46..3604fba 100644 --- a/test/partition_subrange_test.cpp +++ b/test/partition_subrange_test.cpp @@ -8,7 +8,7 @@ #include #include -#if __cplusplus >= 201103L +#if (__cplusplus >= 201103L) || defined(BOOST_NO_CXX98_RANDOM_SHUFFLE) #include std::default_random_engine gen; @@ -34,7 +34,7 @@ void check_sequence ( Iter first, Iter last, Iter sf, Iter sl ) // } // if (sl == last) std::cout << "<"; // std::cout << '\n'; - + if (sf == sl) return; for (Iter i = first; i < sf; ++i) BOOST_CHECK(*i < *sf); @@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE( test_main ) std::vector v; for ( int i = 0; i < 10; ++i ) v.push_back(i); - + const std::vector::iterator b = v.begin(); ba::partition_subrange(b, v.end(), b + 3, b + 6); check_sequence (b, v.end(), b + 3, b + 6); @@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE( test_main ) // BOOST_CHECK_EQUAL(v[3], 3); // BOOST_CHECK_EQUAL(v[4], 4); // BOOST_CHECK_EQUAL(v[5], 5); - + // Mix them up and try again - single element do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b + 7, b + 8); @@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE( test_main ) std::vector v; for ( int i = 0; i < 10; ++i ) v.push_back(i); - + const std::vector::iterator b = v.begin(); ba::partition_subrange(b, v.end(), b + 3, b + 6, std::greater()); check_sequence (b, v.end(), b + 3, b + 6, std::greater()); diff --git a/test/sort_subrange_test.cpp b/test/sort_subrange_test.cpp index de6a3fa..0694af4 100644 --- a/test/sort_subrange_test.cpp +++ b/test/sort_subrange_test.cpp @@ -8,7 +8,7 @@ #include #include -#if __cplusplus >= 201103L +#if (__cplusplus >= 201103L) || defined(BOOST_NO_CXX98_RANDOM_SHUFFLE) #include std::default_random_engine gen; @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE( test_main ) std::vector v; for ( int i = 0; i < 10; ++i ) v.push_back(i); - + const std::vector::iterator b = v.begin(); ba::sort_subrange(b, v.end(), b + 3, b + 6); check_sequence (b, v.end(), b + 3, b + 6); @@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(v[3], 3); BOOST_CHECK_EQUAL(v[4], 4); BOOST_CHECK_EQUAL(v[5], 5); - + // Mix them up and try again - single element do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b + 7, b + 8); @@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE( test_main ) std::vector v; for ( int i = 0; i < 10; ++i ) v.push_back(i); - + const std::vector::iterator b = v.begin(); ba::sort_subrange(b, v.end(), b + 3, b + 6, std::greater()); check_sequence (b, v.end(), b + 3, b + 6, std::greater()); From 7df35ffd5676cebf2ac4f0ac51dd4107087c3925 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Wed, 30 Aug 2017 20:25:15 +0300 Subject: [PATCH 11/20] Different fixes --- doc/apply_permutation.qbk | 21 ++++++++--- example/apply_permutation_example.cpp | 4 +-- include/boost/algorithm/apply_permutation.hpp | 36 ++++++++++--------- test/apply_permutation_test.cpp | 24 ++++++------- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/doc/apply_permutation.qbk b/doc/apply_permutation.qbk index 952195d..7f11457 100644 --- a/doc/apply_permutation.qbk +++ b/doc/apply_permutation.qbk @@ -12,8 +12,16 @@ Distributed under the Boost Software License, Version 1.0. The header file 'apply_permutation.hpp' contains two algorithms, apply_permutation and apply_reverse_permutation. Also there are range-based versions. The algorithms transform the item sequence according to index sequence order. -The routine `apply_permutation` takes a item sequence and a order sequence. It reshuffles item sequence according to order sequence. Every value in order sequence means where the item comes from. -The routine `apply_reverse_permutation` takes a item sequence and a order sequence. It will reshuffle item sequence according to order sequence. Every value in order sequence means where the item goes to. +The routine `apply_permutation` takes a item sequence and a order sequence. It reshuffles item sequence according to order sequence. Every value in order sequence means where the item comes from. Order sequence needs to be exactly a permutation of the sequence [0, 1, ... , N], where N is the biggest index in the item sequence (zero-indexed). +The routine `apply_reverse_permutation` takes a item sequence and a order sequence. It will reshuffle item sequence according to order sequence. Every value in order sequence means where the item goes to. Order sequence needs to be exactly a permutation of the sequence [0, 1, ... , N], where N is the biggest index in the item sequence (zero-indexed). + +Implementations are based on these articles: +https://blogs.msdn.microsoft.com/oldnewthing/20170102-00/?p=95095 +https://blogs.msdn.microsoft.com/oldnewthing/20170103-00/?p=95105 +https://blogs.msdn.microsoft.com/oldnewthing/20170104-00/?p=95115 +https://blogs.msdn.microsoft.com/oldnewthing/20170109-00/?p=95145 +https://blogs.msdn.microsoft.com/oldnewthing/20170110-00/?p=95155 +https://blogs.msdn.microsoft.com/oldnewthing/20170111-00/?p=95165 The routines come in 2 forms; the first one takes two iterators to define the item range and one iterator to define the beginning of index range. The second form takes range to define the item sequence and range to define index sequence. @@ -21,17 +29,17 @@ The routines come in 2 forms; the first one takes two iterators to define the it [heading interface] There are two versions of algorithms: -1) takes three iterators. +1) takes four iterators. 2) takes two ranges. `` template void apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, - RandomAccessIterator2 ind_begin); + RandomAccessIterator2 ind_begin, RandomAccessIterator2 ind_end); template void apply_permutation(Range1& item_range, Range2& ind_range); template void apply_reverse_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, - RandomAccessIterator2 ind_begin); + RandomAccessIterator2 ind_begin, RandomAccessIterator2 ind_end); template void apply_reverse_permutation(Range1& item_range, Range2& ind_range); `` @@ -64,6 +72,7 @@ apply_reverse_permutation(vec, order) --> vec:{5, 4, 2, 3, 1} [heading Complexity] All of the variants of `apply_permutation` and `apply_reverse_permutation` run in ['O(N)] (linear) time. +More [heading Exception Safety] @@ -76,6 +85,8 @@ All of the variants of `apply_permutation` and `apply_reverse_permutation` take * Order sequence must be zero-indexed. +* Order sequence gets permuted. + [endsect] [/ File apply_permutation.qbk diff --git a/example/apply_permutation_example.cpp b/example/apply_permutation_example.cpp index 16c84b6..7ed91ae 100644 --- a/example/apply_permutation_example.cpp +++ b/example/apply_permutation_example.cpp @@ -23,7 +23,7 @@ int main ( int /*argc*/, char * /*argv*/ [] ) std::cout << "apply_permutation with iterators:\n"; std::vector vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0}; - ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); for (const auto& x : vec) { std::cout << x << ", "; @@ -34,7 +34,7 @@ int main ( int /*argc*/, char * /*argv*/ [] ) std::cout << "apply_reverse_permutation with iterators:\n"; std::vector vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0}; - ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); for (const auto& x : vec) { std::cout << x << ", "; diff --git a/include/boost/algorithm/apply_permutation.hpp b/include/boost/algorithm/apply_permutation.hpp index d4aa958..c844cfc 100644 --- a/include/boost/algorithm/apply_permutation.hpp +++ b/include/boost/algorithm/apply_permutation.hpp @@ -19,8 +19,7 @@ #define BOOST_ALGORITHM_APPLY_PERMUTATION_HPP #include -#include -#include +#include #include #include @@ -40,17 +39,18 @@ namespace boost { namespace algorithm template void apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, - RandomAccessIterator2 ind_begin) + RandomAccessIterator2 ind_begin, RandomAccessIterator2 ind_end) { - typedef typename std::iterator_traits::difference_type Diff; + using Diff = typename std::iterator_traits::difference_type; + using std::swap; Diff size = std::distance(item_begin, item_end); - for (Diff i = 0; i < size; ++i) + for (Diff i = 0; i < size; i++) { - Diff current = i; + auto current = i; while (i != ind_begin[current]) { - Diff next = static_cast(ind_begin[current]); - std::swap(item_begin[current], item_begin[next]); + auto next = ind_begin[current]; + swap(item_begin[current], item_begin[next]); ind_begin[current] = current; current = next; } @@ -69,18 +69,22 @@ apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_e /// Complexity: O(N). template void -apply_reverse_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, - RandomAccessIterator2 ind_begin) +apply_reverse_permutation( + RandomAccessIterator1 item_begin, + RandomAccessIterator1 item_end, + RandomAccessIterator2 ind_begin, + RandomAccessIterator2 ind_end) { - typedef typename std::iterator_traits::difference_type Diff; + using Diff = typename std::iterator_traits::difference_type; + using std::swap; Diff length = std::distance(item_begin, item_end); - for (Diff i = 0; i < length; ++i) + for (Diff i = 0; i < length; i++) { while (i != ind_begin[i]) { Diff next = ind_begin[i]; - std::swap(item_begin[i], item_begin[next]); - std::swap(ind_begin[i], ind_begin[next]); + swap(item_begin[i], item_begin[next]); + swap(ind_begin[i], ind_begin[next]); } } } @@ -98,7 +102,7 @@ void apply_permutation(Range1& item_range, Range2& ind_range) { apply_permutation(boost::begin(item_range), boost::end(item_range), - boost::begin(ind_range)); + boost::begin(ind_range), boost::end(ind_range)); } /// \fn apply_reverse_permutation ( Range1 item_range, Range2 ind_range ) @@ -114,7 +118,7 @@ void apply_reverse_permutation(Range1& item_range, Range2& ind_range) { apply_reverse_permutation(boost::begin(item_range), boost::end(item_range), - boost::begin(ind_range)); + boost::begin(ind_range), boost::end(ind_range)); } }} diff --git a/test/apply_permutation_test.cpp b/test/apply_permutation_test.cpp index 4dc08e7..e9ab970 100644 --- a/test/apply_permutation_test.cpp +++ b/test/apply_permutation_test.cpp @@ -26,7 +26,7 @@ void test_apply_permutation() { std::vector vec, order, result; - ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //1 element @@ -36,7 +36,7 @@ void test_apply_permutation() order.push_back(0); result = vec; - ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //2 elements, no changes @@ -46,7 +46,7 @@ void test_apply_permutation() order.push_back(0); order.push_back(1); result = vec; - ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //2 elements, changed @@ -56,7 +56,7 @@ void test_apply_permutation() order.push_back(1); order.push_back(0); result.push_back(2); result.push_back(1); - ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //Multiple elements, no changes @@ -66,7 +66,7 @@ void test_apply_permutation() order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4); result = vec; - ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //Multiple elements, changed @@ -76,7 +76,7 @@ void test_apply_permutation() order.push_back(4); order.push_back(3); order.push_back(2); order.push_back(1); order.push_back(0); result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1); - ba::apply_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //Just test range interface @@ -97,7 +97,7 @@ void test_apply_reverse_permutation() { std::vector vec, order, result; - ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //1 element @@ -107,7 +107,7 @@ void test_apply_reverse_permutation() order.push_back(0); result = vec; - ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //2 elements, no changes @@ -117,7 +117,7 @@ void test_apply_reverse_permutation() order.push_back(0); order.push_back(1); result = vec; - ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //2 elements, changed @@ -127,7 +127,7 @@ void test_apply_reverse_permutation() order.push_back(1); order.push_back(0); result.push_back(2); result.push_back(1); - ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //Multiple elements, no changes @@ -137,7 +137,7 @@ void test_apply_reverse_permutation() order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4); result = vec; - ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //Multiple elements, changed @@ -147,7 +147,7 @@ void test_apply_reverse_permutation() order.push_back(4); order.push_back(3); order.push_back(2); order.push_back(1); order.push_back(0); result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1); - ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin()); + ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); BOOST_CHECK(vec == result); } //Just test range interface From 0539e0d84aba6953814c5b3c2a0c9f54dadedf87 Mon Sep 17 00:00:00 2001 From: Daniela Engert Date: Sun, 8 Oct 2017 10:33:22 +0200 Subject: [PATCH 12/20] Copy-and-paste error ... Signed-off-by: Daniela Engert --- test/power_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/power_test.cpp b/test/power_test.cpp index c608a8b..f4372e8 100644 --- a/test/power_test.cpp +++ b/test/power_test.cpp @@ -58,7 +58,7 @@ void test_power_constexpr () BOOST_CHECK(check_power2); BOOST_CXX14_CONSTEXPR bool check_power3 = ba::power(3, 3) == 27; - BOOST_CHECK(check_power1); + BOOST_CHECK(check_power3); BOOST_CXX14_CONSTEXPR bool check_power4 = ba::power(2, 30) == 0x40000000; BOOST_CHECK(check_power4); From 63c85e7c5ea56a82b723eedfc5d8902ba2ee5474 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 10 Jan 2018 10:26:21 -0800 Subject: [PATCH 13/20] Qualify calls to Boost.Algorithm algs that have the same name as ones in the standard; prevents ADL ambiguities. Thanks to Billy O'Neill for the heads up. --- include/boost/algorithm/clamp.hpp | 10 +++++----- include/boost/algorithm/cxx17/exclusive_scan.hpp | 2 +- include/boost/algorithm/cxx17/inclusive_scan.hpp | 4 ++-- include/boost/algorithm/cxx17/reduce.hpp | 10 +++++----- .../boost/algorithm/cxx17/transform_inclusive_scan.hpp | 3 ++- include/boost/algorithm/cxx17/transform_reduce.hpp | 2 +- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/boost/algorithm/clamp.hpp b/include/boost/algorithm/clamp.hpp index a179d26..d027acd 100644 --- a/include/boost/algorithm/clamp.hpp +++ b/include/boost/algorithm/clamp.hpp @@ -72,7 +72,7 @@ namespace boost { namespace algorithm { typename boost::mpl::identity::type const & lo, typename boost::mpl::identity::type const & hi ) { - return (clamp) ( val, lo, hi, std::less()); + return boost::algorithm::clamp ( val, lo, hi, std::less()); } /// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out, @@ -93,7 +93,7 @@ namespace boost { namespace algorithm { { // this could also be written with bind and std::transform while ( first != last ) - *out++ = clamp ( *first++, lo, hi ); + *out++ = boost::algorithm::clamp ( *first++, lo, hi ); return out; } @@ -113,7 +113,7 @@ namespace boost { namespace algorithm { typename std::iterator_traits::type>::value_type const & lo, typename std::iterator_traits::type>::value_type const & hi ) { - return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi ); + return boost::algorithm::clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi ); } @@ -139,7 +139,7 @@ namespace boost { namespace algorithm { { // this could also be written with bind and std::transform while ( first != last ) - *out++ = clamp ( *first++, lo, hi, p ); + *out++ = boost::algorithm::clamp ( *first++, lo, hi, p ); return out; } @@ -166,7 +166,7 @@ namespace boost { namespace algorithm { typename std::iterator_traits::type>::value_type const & hi, Pred p ) { - return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p ); + return boost::algorithm::clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p ); } diff --git a/include/boost/algorithm/cxx17/exclusive_scan.hpp b/include/boost/algorithm/cxx17/exclusive_scan.hpp index 03ecea5..6549db7 100644 --- a/include/boost/algorithm/cxx17/exclusive_scan.hpp +++ b/include/boost/algorithm/cxx17/exclusive_scan.hpp @@ -44,7 +44,7 @@ OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init) { typedef typename std::iterator_traits::value_type VT; - return exclusive_scan(first, last, result, init, std::plus()); + return boost::algorithm::exclusive_scan(first, last, result, init, std::plus()); } }} // namespace boost and algorithm diff --git a/include/boost/algorithm/cxx17/inclusive_scan.hpp b/include/boost/algorithm/cxx17/inclusive_scan.hpp index cd015f1..e16a983 100644 --- a/include/boost/algorithm/cxx17/inclusive_scan.hpp +++ b/include/boost/algorithm/cxx17/inclusive_scan.hpp @@ -41,7 +41,7 @@ OutputIterator inclusive_scan(InputIterator first, InputIterator last, typename std::iterator_traits::value_type init = *first; *result++ = init; if (++first != last) - return inclusive_scan(first, last, result, bOp, init); + return boost::algorithm::inclusive_scan(first, last, result, bOp, init); } return result; @@ -52,7 +52,7 @@ OutputIterator inclusive_scan(InputIterator first, InputIterator last, OutputIterator result) { typedef typename std::iterator_traits::value_type VT; - return inclusive_scan(first, last, result, std::plus()); + return boost::algorithm::inclusive_scan(first, last, result, std::plus()); } }} // namespace boost and algorithm diff --git a/include/boost/algorithm/cxx17/reduce.hpp b/include/boost/algorithm/cxx17/reduce.hpp index f47695b..e5d4942 100644 --- a/include/boost/algorithm/cxx17/reduce.hpp +++ b/include/boost/algorithm/cxx17/reduce.hpp @@ -34,14 +34,14 @@ template T reduce(InputIterator first, InputIterator last, T init) { typedef typename std::iterator_traits::value_type VT; - return reduce(first, last, init, std::plus()); + return boost::algorithm::reduce(first, last, init, std::plus()); } template typename std::iterator_traits::value_type reduce(InputIterator first, InputIterator last) { - return reduce(first, last, + return boost::algorithm::reduce(first, last, typename std::iterator_traits::value_type()); } @@ -49,14 +49,14 @@ template typename boost::range_value::type reduce(const Range &r) { - return reduce(boost::begin(r), boost::end(r)); + return boost::algorithm::reduce(boost::begin(r), boost::end(r)); } // Not sure that this won't be ambiguous (1) template T reduce(const Range &r, T init) { - return reduce(boost::begin (r), boost::end (r), init); + return boost::algorithm::reduce(boost::begin (r), boost::end (r), init); } @@ -64,7 +64,7 @@ T reduce(const Range &r, T init) template T reduce(const Range &r, T init, BinaryOperation bOp) { - return reduce(boost::begin(r), boost::end(r), init, bOp); + return boost::algorithm::reduce(boost::begin(r), boost::end(r), init, bOp); } }} // namespace boost and algorithm diff --git a/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp b/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp index 476c117..f4456d7 100644 --- a/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp +++ b/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp @@ -46,7 +46,8 @@ OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, typename std::iterator_traits::value_type init = uOp(*first); *result++ = init; if (++first != last) - return transform_inclusive_scan(first, last, result, bOp, uOp, init); + return boost::algorithm::transform_inclusive_scan + (first, last, result, bOp, uOp, init); } return result; diff --git a/include/boost/algorithm/cxx17/transform_reduce.hpp b/include/boost/algorithm/cxx17/transform_reduce.hpp index 7ebde7d..fe14d8d 100644 --- a/include/boost/algorithm/cxx17/transform_reduce.hpp +++ b/include/boost/algorithm/cxx17/transform_reduce.hpp @@ -46,7 +46,7 @@ template T transform_reduce(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init) { - return transform_reduce(first1, last1, first2, init, + return boost::algorithm::transform_reduce(first1, last1, first2, init, std::plus(), std::multiplies()); } From 298310f521853b1d5caaf3ca13bef4c9b0018915 Mon Sep 17 00:00:00 2001 From: "Jeremy W. Murphy" Date: Tue, 6 Feb 2018 00:45:21 +1100 Subject: [PATCH 14/20] Add BOOST_CXX14_CONSTEXPR to identity_operation. --- include/boost/algorithm/algorithm.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/algorithm/algorithm.hpp b/include/boost/algorithm/algorithm.hpp index 96b3b48..2bbee1d 100644 --- a/include/boost/algorithm/algorithm.hpp +++ b/include/boost/algorithm/algorithm.hpp @@ -25,10 +25,10 @@ namespace boost { namespace algorithm { template -T identity_operation ( std::multiplies ) { return T(1); } +BOOST_CXX14_CONSTEXPR T identity_operation ( std::multiplies ) { return T(1); } template -T identity_operation ( std::plus ) { return T(0); } +BOOST_CXX14_CONSTEXPR T identity_operation ( std::plus ) { return T(0); } /// \fn power ( T x, Integer n ) From 50a211523642530e718c6bf1dcf61df344a98883 Mon Sep 17 00:00:00 2001 From: samuela Date: Tue, 20 Mar 2018 17:50:04 -0700 Subject: [PATCH 15/20] docstring fix for `first_finder` --- include/boost/algorithm/string/finder.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/algorithm/string/finder.hpp b/include/boost/algorithm/string/finder.hpp index 93f7ec3..0273b33 100644 --- a/include/boost/algorithm/string/finder.hpp +++ b/include/boost/algorithm/string/finder.hpp @@ -43,7 +43,6 @@ namespace boost { The result is given as an \c iterator_range delimiting the match. \param Search A substring to be searched for. - \param Comp An element comparison predicate \return An instance of the \c first_finder object */ template From d6c8b271b369730f6c6f8b3f536789888867e123 Mon Sep 17 00:00:00 2001 From: samuela Date: Tue, 20 Mar 2018 17:53:09 -0700 Subject: [PATCH 16/20] remove other incorrect docstring params --- include/boost/algorithm/string/finder.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/boost/algorithm/string/finder.hpp b/include/boost/algorithm/string/finder.hpp index 0273b33..61f6e41 100644 --- a/include/boost/algorithm/string/finder.hpp +++ b/include/boost/algorithm/string/finder.hpp @@ -83,7 +83,6 @@ namespace boost { The result is given as an \c iterator_range delimiting the match. \param Search A substring to be searched for. - \param Comp An element comparison predicate \return An instance of the \c last_finder object */ template @@ -123,7 +122,6 @@ namespace boost { \param Search A substring to be searched for. \param Nth An index of the match to be find - \param Comp An element comparison predicate \return An instance of the \c nth_finder object */ template @@ -229,7 +227,6 @@ namespace boost { \param Begin Beginning of the range \param End End of the range - \param Range The range. \return An instance of the \c range_finger object */ template< typename ForwardIteratorT > From aa8cce5bb473b8054f3f1d58e2717c9cf7886260 Mon Sep 17 00:00:00 2001 From: samuela Date: Tue, 20 Mar 2018 17:57:58 -0700 Subject: [PATCH 17/20] Fix clang "parameter not found" warning --- include/boost/algorithm/string/formatter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/algorithm/string/formatter.hpp b/include/boost/algorithm/string/formatter.hpp index de8681b..78325a4 100644 --- a/include/boost/algorithm/string/formatter.hpp +++ b/include/boost/algorithm/string/formatter.hpp @@ -83,7 +83,7 @@ namespace boost { template inline detail::empty_formatF< BOOST_STRING_TYPENAME range_value::type> - empty_formatter(const RangeT&) + empty_formatter(const RangeT& Input) { return detail::empty_formatF< BOOST_STRING_TYPENAME range_value::type>(); From c34713b9835dab68853b1a96c254e2539ee02597 Mon Sep 17 00:00:00 2001 From: Samuel Ainsworth Date: Tue, 20 Mar 2018 19:01:56 -0700 Subject: [PATCH 18/20] Revert "Fix clang "parameter not found" warning" This reverts commit aa8cce5bb473b8054f3f1d58e2717c9cf7886260. --- include/boost/algorithm/string/formatter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/algorithm/string/formatter.hpp b/include/boost/algorithm/string/formatter.hpp index 78325a4..de8681b 100644 --- a/include/boost/algorithm/string/formatter.hpp +++ b/include/boost/algorithm/string/formatter.hpp @@ -83,7 +83,7 @@ namespace boost { template inline detail::empty_formatF< BOOST_STRING_TYPENAME range_value::type> - empty_formatter(const RangeT& Input) + empty_formatter(const RangeT&) { return detail::empty_formatF< BOOST_STRING_TYPENAME range_value::type>(); From b0f04afcb066ba4b4b4e0879a8860e4ed731f4e9 Mon Sep 17 00:00:00 2001 From: Daniela Engert Date: Sun, 25 Mar 2018 17:45:50 +0200 Subject: [PATCH 19/20] functions used in constexpr context must be marked 'constexpr' Signed-off-by: Daniela Engert --- test/clamp_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/clamp_test.cpp b/test/clamp_test.cpp index 2513cf8..c3e9433 100644 --- a/test/clamp_test.cpp +++ b/test/clamp_test.cpp @@ -14,8 +14,8 @@ namespace ba = boost::algorithm; -bool intGreater ( int lhs, int rhs ) { return lhs > rhs; } -bool doubleGreater ( double lhs, double rhs ) { return lhs > rhs; } +BOOST_CONSTEXPR bool intGreater ( int lhs, int rhs ) { return lhs > rhs; } +BOOST_CONSTEXPR bool doubleGreater ( double lhs, double rhs ) { return lhs > rhs; } class custom { public: From 3af7acabc703ccad806213ceef73a2c24faef684 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 4 Apr 2018 11:18:38 -0700 Subject: [PATCH 20/20] fix constexpr-ness of a couple of algorithhms - and tests. Based on Pull Request #44 by Flast - thanks! --- include/boost/algorithm/cxx11/one_of.hpp | 27 +++++++++++++++--------- include/boost/algorithm/cxx14/equal.hpp | 20 +++++++----------- test/all_of_test.cpp | 13 ++++++------ test/any_of_test.cpp | 14 ++++++------ test/clamp_test.cpp | 2 +- test/none_of_test.cpp | 15 +++++++------ test/one_of_test.cpp | 8 +++---- 7 files changed, 52 insertions(+), 47 deletions(-) diff --git a/include/boost/algorithm/cxx11/one_of.hpp b/include/boost/algorithm/cxx11/one_of.hpp index f4e2b38..3b95180 100644 --- a/include/boost/algorithm/cxx11/one_of.hpp +++ b/include/boost/algorithm/cxx11/one_of.hpp @@ -12,7 +12,6 @@ #ifndef BOOST_ALGORITHM_ONE_OF_HPP #define BOOST_ALGORITHM_ONE_OF_HPP -#include // for std::find and std::find_if #include #include @@ -30,10 +29,14 @@ namespace boost { namespace algorithm { template BOOST_CXX14_CONSTEXPR bool one_of ( InputIterator first, InputIterator last, Predicate p ) { - InputIterator i = std::find_if (first, last, p); - if (i == last) +// find_if + for (; first != last; ++first) + if (p(*first)) + break; + + if (first == last) return false; // Didn't occur at all - return boost::algorithm::none_of (++i, last, p); + return boost::algorithm::none_of (++first, last, p); } /// \fn one_of ( const Range &r, Predicate p ) @@ -43,7 +46,7 @@ BOOST_CXX14_CONSTEXPR bool one_of ( InputIterator first, InputIterator last, Pre /// \param p A predicate for testing the elements of the range /// template -BOOST_CXX14_CONSTEXPR bool one_of ( const Range &r, Predicate p ) +BOOST_CXX14_CONSTEXPR bool one_of ( const Range &r, Predicate p ) { return boost::algorithm::one_of ( boost::begin (r), boost::end (r), p ); } @@ -57,12 +60,16 @@ BOOST_CXX14_CONSTEXPR bool one_of ( const Range &r, Predicate p ) /// \param val A value to compare against /// template -bool one_of_equal ( InputIterator first, InputIterator last, const V &val ) +BOOST_CXX14_CONSTEXPR bool one_of_equal ( InputIterator first, InputIterator last, const V &val ) { - InputIterator i = std::find (first, last, val); // find first occurrence of 'val' - if (i == last) +// find + for (; first != last; ++first) + if (*first == val) + break; + + if (first == last) return false; // Didn't occur at all - return boost::algorithm::none_of_equal (++i, last, val); + return boost::algorithm::none_of_equal (++first, last, val); } /// \fn one_of_equal ( const Range &r, const V &val ) @@ -72,7 +79,7 @@ bool one_of_equal ( InputIterator first, InputIterator last, const V &val ) /// \param val A value to compare against /// template -bool one_of_equal ( const Range &r, const V &val ) +BOOST_CXX14_CONSTEXPR bool one_of_equal ( const Range &r, const V &val ) { return boost::algorithm::one_of_equal ( boost::begin (r), boost::end (r), val ); } diff --git a/include/boost/algorithm/cxx14/equal.hpp b/include/boost/algorithm/cxx14/equal.hpp index 857435b..526aae9 100644 --- a/include/boost/algorithm/cxx14/equal.hpp +++ b/include/boost/algorithm/cxx14/equal.hpp @@ -12,16 +12,8 @@ #ifndef BOOST_ALGORITHM_EQUAL_HPP #define BOOST_ALGORITHM_EQUAL_HPP -#include // for std::equal #include -#ifdef __cpp_lib_array_constexpr // or cpp17 compiler -// if compiled according to C++17 standard or std functions are constexpr -#define BOOST_CONSTEXPR_IF_STD_CONSTEXPR constexpr -#else -#define BOOST_CONSTEXPR_IF_STD_CONSTEXPR -#endif - namespace boost { namespace algorithm { namespace detail { @@ -32,7 +24,7 @@ namespace detail { }; template - BOOST_CONSTEXPR_IF_STD_CONSTEXPR + BOOST_CXX14_CONSTEXPR bool equal ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, std::random_access_iterator_tag, std::random_access_iterator_tag ) @@ -40,12 +32,16 @@ namespace detail { // 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::equal ( first1, last1, first2, pred ); + + // std::equal + for (; first1 != last1; ++first1, ++first2) + if (!pred(*first1, *first2)) + return false; + return true; } template - BOOST_CXX14_CONSTEXPR + BOOST_CXX14_CONSTEXPR bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred, std::input_iterator_tag, std::input_iterator_tag ) diff --git a/test/all_of_test.cpp b/test/all_of_test.cpp index a720b0c..a6fdfd6 100644 --- a/test/all_of_test.cpp +++ b/test/all_of_test.cpp @@ -77,12 +77,13 @@ void test_all () BOOST_CHECK ( ba::all_of_equal ( li.begin(), l_iter, 1 )); BOOST_CHECK ( ba::all_of ( li.begin(), l_iter, is_ ( 1 ))); - BOOST_CXX14_CONSTEXPR bool constexpr_res = ( - !ba::all_of_equal ( some_numbers, 1 ) - && !ba::all_of ( some_numbers, is_ ( 1 )) - && ba::all_of_equal ( some_numbers, some_numbers + 3, 1 ) - && ba::all_of ( some_numbers, some_numbers + 3, is_ ( 1 )) - ); + BOOST_CXX14_CONSTEXPR bool constexpr_res = + !ba::all_of_equal ( some_numbers, 1 ) && + !ba::all_of ( some_numbers, is_ ( 1 )) && + ba::all_of_equal ( some_numbers, some_numbers + 3, 1 ) && + ba::all_of ( some_numbers, some_numbers + 3, is_ ( 1 )) && + true; + BOOST_CHECK ( constexpr_res ); } diff --git a/test/any_of_test.cpp b/test/any_of_test.cpp index 193356c..288c0cc 100644 --- a/test/any_of_test.cpp +++ b/test/any_of_test.cpp @@ -97,13 +97,13 @@ void test_any () BOOST_CHECK (!ba::any_of_equal ( li.begin(), l_iter, 18 )); BOOST_CHECK (!ba::any_of ( li.begin(), l_iter, is_ ( 18 ))); - - BOOST_CXX14_CONSTEXPR bool constexpr_res = ( - ba::any_of_equal ( some_numbers, 1 ) - && ba::any_of ( some_numbers, is_ ( 1 )) - && !ba::any_of_equal ( some_numbers, some_numbers + 3, 777 ) - && !ba::any_of ( some_numbers, some_numbers + 3, is_ ( 777 )) - ); + BOOST_CXX14_CONSTEXPR bool constexpr_res = + ba::any_of_equal ( some_numbers, 1 ) && + ba::any_of ( some_numbers, is_ ( 1 )) && + !ba::any_of_equal ( some_numbers, some_numbers + 3, 777 ) && + !ba::any_of ( some_numbers, some_numbers + 3, is_ ( 777 )) && + true; + BOOST_CHECK ( constexpr_res ); } diff --git a/test/clamp_test.cpp b/test/clamp_test.cpp index c3e9433..a6e73b5 100644 --- a/test/clamp_test.cpp +++ b/test/clamp_test.cpp @@ -306,7 +306,7 @@ void test_constexpr() BOOST_CHECK(check_max_out); } { - short foo = 50; + BOOST_CXX14_CONSTEXPR short foo = 50; BOOST_CXX14_CONSTEXPR bool check_float = ( 56 == ba::clamp ( foo, 56.9, 129 )); BOOST_CHECK(check_float); BOOST_CXX14_CONSTEXPR bool check_over = ( 24910 == ba::clamp ( foo, 12345678, 123456999 )); diff --git a/test/none_of_test.cpp b/test/none_of_test.cpp index 9522175..0a20ff4 100644 --- a/test/none_of_test.cpp +++ b/test/none_of_test.cpp @@ -88,13 +88,14 @@ void test_none() BOOST_CHECK ( ba::none_of_equal ( li.begin(), l_iter, 18 )); BOOST_CHECK ( ba::none_of ( li.begin(), l_iter, is_ ( 18 ))); BOOST_CHECK (!ba::none_of ( li.begin(), l_iter, is_ ( 5 ))); - - BOOST_CXX14_CONSTEXPR bool constexpr_res = ( - !ba::none_of_equal ( some_numbers, 1 ) - && !ba::none_of ( some_numbers, is_ ( 1 )) - && ba::none_of_equal ( some_numbers, some_numbers + 3, 100 ) - && ba::none_of ( some_numbers, some_numbers + 3, is_ ( 100 )) - ); + + BOOST_CXX14_CONSTEXPR bool constexpr_res = + !ba::none_of_equal ( some_numbers, 1 ) && + !ba::none_of ( some_numbers, is_ ( 1 )) && + ba::none_of_equal ( some_numbers, some_numbers + 3, 100 ) && + ba::none_of ( some_numbers, some_numbers + 3, is_ ( 100 )) && + true; + BOOST_CHECK ( constexpr_res ); } diff --git a/test/one_of_test.cpp b/test/one_of_test.cpp index 22ccca2..8403a8e 100644 --- a/test/one_of_test.cpp +++ b/test/one_of_test.cpp @@ -92,10 +92,10 @@ void test_one () BOOST_CHECK (!ba::one_of_equal ( li.begin(), l_iter, 3 )); BOOST_CHECK (!ba::one_of ( li.begin(), l_iter, is_ ( 3 ))); - BOOST_CXX14_CONSTEXPR bool constexpr_res = ( - !ba::one_of ( some_numbers, is_ ( 6 )) - && ba::one_of ( some_numbers + 1, some_numbers + 3, is_ ( 1 )) - ); + BOOST_CXX14_CONSTEXPR bool constexpr_res = + !ba::one_of ( some_numbers, is_ ( 6 )) && + ba::one_of ( some_numbers + 1, some_numbers + 3, is_ ( 1 )) && + true; BOOST_CHECK ( constexpr_res ); }