diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 6af1129..360b973 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -44,3 +44,13 @@ boostbook standalone toc.max.depth=2 generate.section.toc.level=1 ; + +############################################################################### +alias boostdoc + : ../string/doc/string_algo.xml + : + : ../string/doc//autodoc + : ; +explicit boostdoc ; +alias boostrelease : standalone ; +explicit boostrelease ; diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index 66971d1..1568fb5 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -66,6 +66,7 @@ Thanks to all the people who have reviewed this library and made suggestions for [include clamp-hpp.qbk] [include gather.qbk] [include hex.qbk] +[include is_palindrome.qbk] [endsect] diff --git a/doc/all_of.qbk b/doc/all_of.qbk index 91b7b36..5b0b8af 100644 --- a/doc/all_of.qbk +++ b/doc/all_of.qbk @@ -73,7 +73,7 @@ All of the variants of `all_of` and `all_of_equal` take their parameters by valu [heading Notes] -* The routine `all_of` is part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. +* The routine `all_of` is also available as part of the C++11 standard. * `all_of` and `all_of_equal` both return true for empty ranges, no matter what is passed to test against. When there are no items in the sequence to test, they all satisfy the condition to be tested against. diff --git a/doc/any_of.qbk b/doc/any_of.qbk index 61a6603..4a50861 100644 --- a/doc/any_of.qbk +++ b/doc/any_of.qbk @@ -73,7 +73,7 @@ All of the variants of `any_of` and `any_of_equal` take their parameters by valu [heading Notes] -* The routine `any_of` is part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. +* The routine `any_of` is also available as part of the C++11 standard. * `any_of` and `any_of_equal` both return false for empty ranges, no matter what is passed to test against. diff --git a/doc/boyer_moore.qbk b/doc/boyer_moore.qbk index 13c9666..1651133 100644 --- a/doc/boyer_moore.qbk +++ b/doc/boyer_moore.qbk @@ -37,7 +37,7 @@ public: ~boyer_moore (); template - corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ); + pair operator () ( corpusIter corpus_first, corpusIter corpus_last ); }; `` @@ -45,14 +45,28 @@ and here is the corresponding procedural interface: `` template -corpusIter boyer_moore_search ( +pair boyer_moore_search ( corpusIter corpus_first, corpusIter corpus_last, patIter pat_first, patIter pat_last ); `` Each of the functions is passed two pairs of iterators. The first two define the corpus and the second two define the pattern. Note that the two pairs need not be of the same type, but they do need to "point" at the same type. In other words, `patIter::value_type` and `curpusIter::value_type` need to be the same type. -The return value of the function is an iterator pointing to the start of the pattern in the corpus. If the pattern is not found, it returns the end of the corpus (`corpus_last`). +The return value of the function is a pair of iterators pointing to the position of the pattern in the corpus. If the pattern is empty, it returns at empty range at the start of the corpus (`corpus_first`, `corpus_first`). If the pattern is not found, it returns at empty range at the end of the corpus (`corpus_last`, `corpus_last`). + +[heading Compatibility Note] + +Earlier versions of this searcher returned only a single iterator. As explained in [@https://cplusplusmusings.wordpress.com/2016/02/01/sometimes-you-get-things-wrong/], this was a suboptimal interface choice, and has been changed, starting in the 1.62.0 release. Old code that is expecting a single iterator return value can be updated by replacing the return value of the searcher's `operator ()` with the `.first` field of the pair. + +Instead of: +`` +iterator foo = searcher(a, b); +`` + +you now write: +`` +iterator foo = searcher(a, b).first; +`` [heading Performance] diff --git a/doc/boyer_moore_horspool.qbk b/doc/boyer_moore_horspool.qbk index 3a10c32..5b8491a 100644 --- a/doc/boyer_moore_horspool.qbk +++ b/doc/boyer_moore_horspool.qbk @@ -35,7 +35,7 @@ public: ~boyer_moore_horspool (); template - corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ); + pair operator () ( corpusIter corpus_first, corpusIter corpus_last ); }; `` @@ -43,14 +43,28 @@ and here is the corresponding procedural interface: `` template -corpusIter boyer_moore_horspool_search ( +pair boyer_moore_horspool_search ( corpusIter corpus_first, corpusIter corpus_last, patIter pat_first, patIter pat_last ); `` Each of the functions is passed two pairs of iterators. The first two define the corpus and the second two define the pattern. Note that the two pairs need not be of the same type, but they do need to "point" at the same type. In other words, `patIter::value_type` and `curpusIter::value_type` need to be the same type. -The return value of the function is an iterator pointing to the start of the pattern in the corpus. If the pattern is not found, it returns the end of the corpus (`corpus_last`). +The return value of the function is a pair of iterators pointing to the position of the pattern in the corpus. If the pattern is empty, it returns at empty range at the start of the corpus (`corpus_first`, `corpus_first`). If the pattern is not found, it returns at empty range at the end of the corpus (`corpus_last`, `corpus_last`). + +[heading Compatibility Note] + +Earlier versions of this searcher returned only a single iterator. As explained in [@https://cplusplusmusings.wordpress.com/2016/02/01/sometimes-you-get-things-wrong/], this was a suboptimal interface choice, and has been changed, starting in the 1.62.0 release. Old code that is expecting a single iterator return value can be updated by replacing the return value of the searcher's `operator ()` with the `.first` field of the pair. + +Instead of: +`` +iterator foo = searcher(a, b); +`` + +you now write: +`` +iterator foo = searcher(a, b).first; +`` [heading Performance] diff --git a/doc/is_palindrome.qbk b/doc/is_palindrome.qbk new file mode 100644 index 0000000..783305f --- /dev/null +++ b/doc/is_palindrome.qbk @@ -0,0 +1,98 @@ +[/ File is_palindrome.qbk] + +[section:is_palindrome is_palindrome] + +[/license +Copyright (c) 2016 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 'is_palindrome.hpp' contains six variants of a single algorithm, is_palindrome. +The algorithm tests the sequence and returns true if the sequence is a palindrome; i.e, it is identical when traversed either backwards or frontwards. + +The routine `is_palindrome` takes a sequence and, optionally, a predicate. It will return true if the predicate returns true for tested elements by algorithm in the sequence. + +The routine come in 6 forms; the first one takes two iterators to define the range. The second form takes two iterators to define the range and a predicate. +The third form takes a single range parameter, and uses Boost.Range to traverse it. The fourth form takes a single range parameter ( uses Boost.Range to traverse it) and a predicate. +The fifth form takes a single C-string and a predicate. The sixth form takes a single C-string. + + +[heading interface] + +The function `is_palindrome` returns true if the predicate returns true any tested by algorithm items in the sequence. +There are six versions: +1) takes two iterators. +2) takes two iterators and a predicate. +3) takes a range. +4) takes a range and a predicate. +5) takes a C-string and a predicate. +6) takes a C-string. + +`` +template + bool is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end ); +template + bool is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end, Predicate p ); +template + bool is_palindrome ( const Range &r ); +template + bool is_palindrome ( const Range &r, Predicate p ); +template + bool is_palindrome ( const char* str, Predicate p ); +bool is_palindrome(const char* str); +`` + + +[heading Examples] + +Given the containers: +const std::list empty, +const std::vector singleElement{'z'}, +int oddNonPalindrome[] = {3,2,2}, +const int oddPalindrome[] = {1,2,3,2,1}, +const int evenPalindrome[] = {1,2,2,1}, +int evenNonPalindrome[] = {1,4,8,8}, then +`` + +is_palindrome(empty)) --> true //empty range +is_palindrome(singleElement)) --> true +is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome))) --> false +is_palindrome(std::begin(evenPalindrome), std::end(evenPalindrome))) --> true +is_palindrome(empty.begin(), empty.end(), functorComparator())) --> true //empty range +is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome), funcComparator)) --> false +is_palindrome(std::begin(oddPalindrome), std::end(oddPalindrome)) --> true +is_palindrome(evenPalindrome, std::equal_to())) --> true +is_palindrome(std::begin(evenNonPalindrome), std::end(evenNonPalindrome)) --> false +is_palindrome("a") --> true +is_palindrome("aba", std::equal_to()) --> true +`` + +[heading Iterator Requirements] + +`is_palindrome` work on Bidirectional and RandomAccess iterators. + +[heading Complexity] + +All of the variants of `is_palindrome` run in ['O(N)] (linear) time; that is, they compare against each element in the list once. If any of the comparisons not succeed, the algorithm will terminate immediately, without examining the remaining members of the sequence. + +[heading Exception Safety] + +All of the variants of `is_palindrome` take their parameters by value, const pointer or const reference, and do not depend upon any global state. Therefore, all the routines in this file provide the strong exception guarantee. + +[heading Notes] + +* `is_palindrome` returns true for empty ranges, const char* null pointers and for single element ranges. + +* If you use version of 'is_palindrome' without custom predicate, 'is_palindrome' uses default 'operator==()' for elements. + +* Be careful with using not null pointer 'const char*' without '\0' - if you use it with 'is_palindrome', it's a undefined behaviour. + +[endsect] + +[/ File is_palindrome.qbk +Copyright 2016 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). +] diff --git a/doc/is_partitioned.qbk b/doc/is_partitioned.qbk index 16dce6a..7a6c458 100644 --- a/doc/is_partitioned.qbk +++ b/doc/is_partitioned.qbk @@ -55,7 +55,7 @@ Both of the variants of `is_partitioned` take their parameters by value or const [heading Notes] -* The iterator-based version of the routine `is_partitioned` is part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. +* The iterator-based version of the routine `is_partitioned` is also available as part of the C++11 standard. * `is_partitioned` returns true for empty ranges, no matter what predicate is passed to test against. diff --git a/doc/is_permutation.qbk b/doc/is_permutation.qbk index 267bfab..e8753ba 100644 --- a/doc/is_permutation.qbk +++ b/doc/is_permutation.qbk @@ -71,7 +71,7 @@ All of the variants of `is_permutation` take their parameters by value, and do n [heading Notes] -* The three iterator versions of the routine `is_permutation` are part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. +* The three iterator versions of the routine `is_permutation` are also available as part of the C++11 standard. * The four iterator versions of the routine `is_permutation` are part of the proposed C++14 standard. When C++14 standard libraries become available, the implementation should be changed to use the implementation from the standard library (if available). diff --git a/doc/knuth_morris_pratt.qbk b/doc/knuth_morris_pratt.qbk index 7b184cf..b2620f1 100644 --- a/doc/knuth_morris_pratt.qbk +++ b/doc/knuth_morris_pratt.qbk @@ -39,7 +39,7 @@ public: ~knuth_morris_pratt (); template - corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ); + pair operator () ( corpusIter corpus_first, corpusIter corpus_last ); }; `` @@ -47,15 +47,28 @@ and here is the corresponding procedural interface: `` template -corpusIter knuth_morris_pratt_search ( +pair knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last, patIter pat_first, patIter pat_last ); `` Each of the functions is passed two pairs of iterators. The first two define the corpus and the second two define the pattern. Note that the two pairs need not be of the same type, but they do need to "point" at the same type. In other words, `patIter::value_type` and `curpusIter::value_type` need to be the same type. -The return value of the function is an iterator pointing to the start of the pattern in the corpus. If the pattern is not found, it returns the end of the corpus (`corpus_last`). +The return value of the function is a pair of iterators pointing to the position of the pattern in the corpus. If the pattern is empty, it returns at empty range at the start of the corpus (`corpus_first`, `corpus_first`). If the pattern is not found, it returns at empty range at the end of the corpus (`corpus_last`, `corpus_last`). +[heading Compatibility Note] + +Earlier versions of this searcher returned only a single iterator. As explained in [@https://cplusplusmusings.wordpress.com/2016/02/01/sometimes-you-get-things-wrong/], this was a suboptimal interface choice, and has been changed, starting in the 1.62.0 release. Old code that is expecting a single iterator return value can be updated by replacing the return value of the searcher's `operator ()` with the `.first` field of the pair. + +Instead of: +`` +iterator foo = searcher(a, b); +`` + +you now write: +`` +iterator foo = searcher(a, b).first; +`` [heading Performance] The execution time of the Knuth-Morris-Pratt algorithm is linear in the size of the string being searched. Generally the algorithm gets faster as the pattern being searched for becomes longer. Its efficiency derives from the fact that with each unsuccessful attempt to find a match between the search string and the text it is searching, it uses the information gained from that attempt to rule out as many positions of the text as possible where the string cannot match. diff --git a/doc/none_of.qbk b/doc/none_of.qbk index 3cda5f9..f0b93b7 100644 --- a/doc/none_of.qbk +++ b/doc/none_of.qbk @@ -74,7 +74,7 @@ All of the variants of `none_of` and `none_of_equal` take their parameters by va [heading Notes] -* The routine `none_of` is part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. +* The routine `none_of` is also available as part of the C++11 standard. * `none_of` and `none_of_equal` both return true for empty ranges, no matter what is passed to test against. diff --git a/doc/partition_point.qbk b/doc/partition_point.qbk index 8d1f76c..813a27b 100644 --- a/doc/partition_point.qbk +++ b/doc/partition_point.qbk @@ -54,7 +54,7 @@ Both of the variants of `partition_point` take their parameters by value or cons [heading Notes] -* The iterator-based version of the routine `partition_point` is part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. +* The iterator-based version of the routine `partition_point` is also available as part of the C++11 standard. * For empty ranges, the partition point is the end of the range. diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 1d8e3b5..ce067cf 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -20,3 +20,5 @@ project /boost/algorithm/example exe clamp_example : clamp_example.cpp ; exe search_example : search_example.cpp ; +exe is_palindrome_example : is_palindrome_example.cpp; + diff --git a/example/is_palindrome_example.cpp b/example/is_palindrome_example.cpp new file mode 100644 index 0000000..cefc782 --- /dev/null +++ b/example/is_palindrome_example.cpp @@ -0,0 +1,99 @@ +/* + Copyright (c) Alexander Zaitsev , 2016 + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include +#include +#include + +#include + + +namespace ba = boost::algorithm; + +template +bool funcComparator(const T& v1, const T& v2) +{ + return v1 == v2; +} + +struct functorComparator +{ + template + bool operator()(const T& v1, const T& v2) const + { + return v1 == v2; + } +}; + + +int main ( int /*argc*/, char * /*argv*/ [] ) +{ + //You can this algorithm with iterators(minimum Bidirectional) + std::vector vec{1,2,1}; + if(ba::is_palindrome(vec.begin(), vec.end())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //Of course, you can use const iterators + if(ba::is_palindrome(vec.cbegin(), vec.cend())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //Example with bidirectional iterators + std::list list{1,2,1}; + if(ba::is_palindrome(list.begin(), list.end())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //You can use custom comparators like functions, functors, lambdas + auto lambdaComparator = [](int v1, int v2){ return v1 == v2; }; + auto objFunc = std::function(lambdaComparator); + + if(ba::is_palindrome(vec.begin(), vec.end(), lambdaComparator)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + if(ba::is_palindrome(vec.begin(), vec.end(), funcComparator)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + if(ba::is_palindrome(vec.begin(), vec.end(), functorComparator())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + if(ba::is_palindrome(vec.begin(), vec.end(), objFunc)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //You can use ranges + if(ba::is_palindrome(vec)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + //You can use C-strings + if(ba::is_palindrome("aba")) + std::cout << "This C-string is palindrome" << std::endl; + else + std::cout << "This C-string is not palindrome" << std::endl; + return 0; +} diff --git a/include/boost/algorithm/cxx11/all_of.hpp b/include/boost/algorithm/cxx11/all_of.hpp index ae8ca9f..527bbd5 100644 --- a/include/boost/algorithm/cxx11/all_of.hpp +++ b/include/boost/algorithm/cxx11/all_of.hpp @@ -12,7 +12,6 @@ #ifndef BOOST_ALGORITHM_ALL_OF_HPP #define BOOST_ALGORITHM_ALL_OF_HPP -#include // for std::all_of, if available #include #include @@ -27,8 +26,6 @@ namespace boost { namespace algorithm { /// \param p A predicate for testing the elements of the sequence /// /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template BOOST_CXX14_CONSTEXPR bool all_of ( InputIterator first, InputIterator last, Predicate p ) { diff --git a/include/boost/algorithm/cxx11/any_of.hpp b/include/boost/algorithm/cxx11/any_of.hpp index 6d30d08..d9e2414 100644 --- a/include/boost/algorithm/cxx11/any_of.hpp +++ b/include/boost/algorithm/cxx11/any_of.hpp @@ -14,7 +14,6 @@ #ifndef BOOST_ALGORITHM_ANY_OF_HPP #define BOOST_ALGORITHM_ANY_OF_HPP -#include // for std::any_of, if available #include #include diff --git a/include/boost/algorithm/cxx11/copy_if.hpp b/include/boost/algorithm/cxx11/copy_if.hpp index ec311e7..dc1fdef 100644 --- a/include/boost/algorithm/cxx11/copy_if.hpp +++ b/include/boost/algorithm/cxx11/copy_if.hpp @@ -12,7 +12,7 @@ #ifndef BOOST_ALGORITHM_COPY_IF_HPP #define BOOST_ALGORITHM_COPY_IF_HPP -#include // for std::copy_if, if available +#include // for std::pair, std::make_pair #include #include @@ -28,8 +28,6 @@ namespace boost { namespace algorithm { /// \param result An output iterator to write the results into /// \param p A predicate for testing the elements of the range /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template BOOST_CXX14_CONSTEXPR OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) { diff --git a/include/boost/algorithm/cxx11/copy_n.hpp b/include/boost/algorithm/cxx11/copy_n.hpp index 842718f..e4bebd0 100644 --- a/include/boost/algorithm/cxx11/copy_n.hpp +++ b/include/boost/algorithm/cxx11/copy_n.hpp @@ -12,8 +12,6 @@ #ifndef BOOST_ALGORITHM_COPY_N_HPP #define BOOST_ALGORITHM_COPY_N_HPP -#include // for std::copy_n, if available - namespace boost { namespace algorithm { /// \fn copy_n ( InputIterator first, Size n, OutputIterator result ) @@ -25,8 +23,6 @@ namespace boost { namespace algorithm { /// \param n The number of elements to copy /// \param result An output iterator to write the results into /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template BOOST_CXX14_CONSTEXPR OutputIterator copy_n ( InputIterator first, Size n, OutputIterator result ) { diff --git a/include/boost/algorithm/cxx11/find_if_not.hpp b/include/boost/algorithm/cxx11/find_if_not.hpp index 735c719..6f5799a 100644 --- a/include/boost/algorithm/cxx11/find_if_not.hpp +++ b/include/boost/algorithm/cxx11/find_if_not.hpp @@ -12,8 +12,6 @@ #ifndef BOOST_ALGORITHM_FIND_IF_NOT_HPP #define BOOST_ALGORITHM_FIND_IF_NOT_HPP -#include // for std::find_if_not, if it exists - #include #include @@ -27,8 +25,6 @@ namespace boost { namespace algorithm { /// \param last One past the end of the input sequence /// \param p A predicate for testing the elements of the range /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template BOOST_CXX14_CONSTEXPR InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p ) { diff --git a/include/boost/algorithm/cxx11/iota.hpp b/include/boost/algorithm/cxx11/iota.hpp index 0cfffb7..6efc4d8 100644 --- a/include/boost/algorithm/cxx11/iota.hpp +++ b/include/boost/algorithm/cxx11/iota.hpp @@ -12,8 +12,6 @@ #ifndef BOOST_ALGORITHM_IOTA_HPP #define BOOST_ALGORITHM_IOTA_HPP -#include - #include #include @@ -26,8 +24,6 @@ namespace boost { namespace algorithm { /// \param last One past the end of the input sequence /// \param value The initial value of the sequence to be generated /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template BOOST_CXX14_CONSTEXPR void iota ( ForwardIterator first, ForwardIterator last, T value ) { diff --git a/include/boost/algorithm/cxx11/is_partitioned.hpp b/include/boost/algorithm/cxx11/is_partitioned.hpp index 2d9236e..aea9b63 100644 --- a/include/boost/algorithm/cxx11/is_partitioned.hpp +++ b/include/boost/algorithm/cxx11/is_partitioned.hpp @@ -12,8 +12,6 @@ #ifndef BOOST_ALGORITHM_IS_PARTITIONED_HPP #define BOOST_ALGORITHM_IS_PARTITIONED_HPP -#include // for std::is_partitioned, if available - #include #include @@ -26,8 +24,6 @@ namespace boost { namespace algorithm { /// \param last One past the end of the input sequence /// \param p The predicate to test the values with /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template BOOST_CXX14_CONSTEXPR bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p ) { diff --git a/include/boost/algorithm/cxx11/is_permutation.hpp b/include/boost/algorithm/cxx11/is_permutation.hpp index ec902dc..0098cd5 100644 --- a/include/boost/algorithm/cxx11/is_permutation.hpp +++ b/include/boost/algorithm/cxx11/is_permutation.hpp @@ -12,8 +12,8 @@ #ifndef BOOST_ALGORITHM_IS_PERMUTATION11_HPP #define BOOST_ALGORITHM_IS_PERMUTATION11_HPP -#include // for std::less, tie, mismatch and is_permutation (if available) -#include // for std::make_pair +#include // for std::find_if, count_if, mismatch +#include // for std::pair #include // for std::equal_to #include @@ -108,8 +108,6 @@ namespace detail { /// \param p The predicate to compare elements with /// /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate p ) @@ -135,8 +133,6 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, /// \param last2 One past the end of the input sequence /// \param first2 The start of the second sequence /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template< class ForwardIterator1, class ForwardIterator2 > bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2 ) { diff --git a/include/boost/algorithm/cxx11/is_sorted.hpp b/include/boost/algorithm/cxx11/is_sorted.hpp index a0770f1..2766211 100644 --- a/include/boost/algorithm/cxx11/is_sorted.hpp +++ b/include/boost/algorithm/cxx11/is_sorted.hpp @@ -13,7 +13,6 @@ #ifndef BOOST_ALGORITHM_ORDERED_HPP #define BOOST_ALGORITHM_ORDERED_HPP -#include #include #include diff --git a/include/boost/algorithm/cxx11/none_of.hpp b/include/boost/algorithm/cxx11/none_of.hpp index cf02e86..e537c26 100644 --- a/include/boost/algorithm/cxx11/none_of.hpp +++ b/include/boost/algorithm/cxx11/none_of.hpp @@ -12,7 +12,6 @@ #ifndef BOOST_ALGORITHM_NONE_OF_HPP #define BOOST_ALGORITHM_NONE_OF_HPP -#include // for std::none_of, if available #include #include @@ -29,9 +28,9 @@ namespace boost { namespace algorithm { template BOOST_CXX14_CONSTEXPR bool none_of ( InputIterator first, InputIterator last, Predicate p ) { -for ( ; first != last; ++first ) - if ( p(*first)) - return false; + for ( ; first != last; ++first ) + if ( p(*first)) + return false; return true; } diff --git a/include/boost/algorithm/cxx11/partition_copy.hpp b/include/boost/algorithm/cxx11/partition_copy.hpp index 20c939f..635b1e7 100644 --- a/include/boost/algorithm/cxx11/partition_copy.hpp +++ b/include/boost/algorithm/cxx11/partition_copy.hpp @@ -12,8 +12,7 @@ #ifndef BOOST_ALGORITHM_PARTITION_COPY_HPP #define BOOST_ALGORITHM_PARTITION_COPY_HPP -#include // for std::partition_copy, if available -#include // for make_pair +#include // for std::pair #include #include @@ -35,8 +34,6 @@ namespace boost { namespace algorithm { /// \param p A predicate for dividing the elements of the input sequence. /// /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template BOOST_CXX14_CONSTEXPR std::pair diff --git a/include/boost/algorithm/cxx11/partition_point.hpp b/include/boost/algorithm/cxx11/partition_point.hpp index f1310c3..2c2767a 100644 --- a/include/boost/algorithm/cxx11/partition_point.hpp +++ b/include/boost/algorithm/cxx11/partition_point.hpp @@ -12,7 +12,7 @@ #ifndef BOOST_ALGORITHM_PARTITION_POINT_HPP #define BOOST_ALGORITHM_PARTITION_POINT_HPP -#include // for std::partition_point, if available +#include // for std::distance, advance #include #include @@ -27,8 +27,6 @@ namespace boost { namespace algorithm { /// \param last One past the end of the input sequence /// \param p The predicate to test the values with /// \note This function is part of the C++2011 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template ForwardIterator partition_point ( ForwardIterator first, ForwardIterator last, Predicate p ) { diff --git a/include/boost/algorithm/cxx14/equal.hpp b/include/boost/algorithm/cxx14/equal.hpp index becaed2..4d7b063 100644 --- a/include/boost/algorithm/cxx14/equal.hpp +++ b/include/boost/algorithm/cxx14/equal.hpp @@ -13,7 +13,7 @@ #define BOOST_ALGORITHM_EQUAL_HPP #include // for std::equal -#include // for std::equal_to +#include #ifdef __cpp_lib_array_constexpr // or cpp17 compiler // if compiled according to C++17 standard or std functions are constexpr diff --git a/include/boost/algorithm/cxx14/is_permutation.hpp b/include/boost/algorithm/cxx14/is_permutation.hpp index 9346881..639446b 100644 --- a/include/boost/algorithm/cxx14/is_permutation.hpp +++ b/include/boost/algorithm/cxx14/is_permutation.hpp @@ -12,8 +12,7 @@ #ifndef BOOST_ALGORITHM_IS_PERMUTATION14_HPP #define BOOST_ALGORITHM_IS_PERMUTATION14_HPP -#include // for std::less, tie, mismatch and is_permutation (if available) -#include // for std::make_pair +#include // for std::pair #include // for std::equal_to #include @@ -31,8 +30,6 @@ namespace boost { namespace algorithm { /// \param first2 The start of the second sequence /// \param last1 One past the end of the second sequence /// \note This function is part of the C++2014 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template< class ForwardIterator1, class ForwardIterator2 > bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 ) @@ -62,8 +59,6 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, /// \param pred The predicate to compare elements with /// /// \note This function is part of the C++2014 standard library. -/// We will use the standard one if it is available, -/// otherwise we have our own implementation. template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, diff --git a/include/boost/algorithm/cxx14/mismatch.hpp b/include/boost/algorithm/cxx14/mismatch.hpp index 33cd609..bc80860 100644 --- a/include/boost/algorithm/cxx14/mismatch.hpp +++ b/include/boost/algorithm/cxx14/mismatch.hpp @@ -12,7 +12,6 @@ #ifndef BOOST_ALGORITHM_MISMATCH_HPP #define BOOST_ALGORITHM_MISMATCH_HPP -#include // for std::mismatch #include // for std::pair #include diff --git a/include/boost/algorithm/hex.hpp b/include/boost/algorithm/hex.hpp index 145a414..739e89f 100644 --- a/include/boost/algorithm/hex.hpp +++ b/include/boost/algorithm/hex.hpp @@ -1,9 +1,9 @@ -/* +/* Copyright (c) Marshall Clow 2011-2012. 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) - + Thanks to Nevin for his comments/help. */ @@ -13,7 +13,7 @@ */ /// \file hex.hpp -/// \brief Convert sequence of integral types into a sequence of hexadecimal +/// \brief Convert sequence of integral types into a sequence of hexadecimal /// characters and back. Based on the MySQL functions HEX and UNHEX /// \author Marshall Clow @@ -25,7 +25,9 @@ #include #include -#include +#include +#include +#include #include #include @@ -33,17 +35,17 @@ namespace boost { namespace algorithm { -/*! - \struct hex_decode_error - \brief Base exception class for all hex decoding errors +/*! + \struct hex_decode_error + \brief Base exception class for all hex decoding errors */ /*! - \struct non_hex_input + \struct non_hex_input \brief Thrown when a non-hex value (0-9, A-F) encountered when decoding. Contains the offending character -*/ /*! - \struct not_enough_input +*/ /*! + \struct not_enough_input \brief Thrown when the input sequence unexpectedly ends - + */ struct hex_decode_error : virtual boost::exception, virtual std::exception {}; struct not_enough_input : virtual hex_decode_error {}; @@ -54,12 +56,12 @@ namespace detail { /// \cond DOXYGEN_HIDE template - OutputIterator encode_one ( T val, OutputIterator out ) { + OutputIterator encode_one ( T val, OutputIterator out, const char * hexDigits ) { const std::size_t num_hex_digits = 2 * sizeof ( T ); char res [ num_hex_digits ]; char *p = res + num_hex_digits; for ( std::size_t i = 0; i < num_hex_digits; ++i, val >>= 4 ) - *--p = "0123456789ABCDEF" [ val & 0x0F ]; + *--p = hexDigits [ val & 0x0F ]; return std::copy ( res, res + num_hex_digits, out ); } @@ -106,12 +108,12 @@ namespace detail { typedef T value_type; }; - template + template bool iter_end ( Iterator current, Iterator last ) { return current == last; } - + template bool ptr_end ( const T* ptr, const T* /*end*/ ) { return *ptr == '\0'; } - + // What can we assume here about the inputs? // is std::iterator_traits::value_type always 'char' ? // Could it be wchar_t, say? Does it matter? @@ -124,11 +126,11 @@ namespace detail { // Need to make sure that we get can read that many chars here. for ( std::size_t i = 0; i < 2 * sizeof ( T ); ++i, ++first ) { - if ( pred ( first, last )) + if ( pred ( first, last )) BOOST_THROW_EXCEPTION (not_enough_input ()); res = ( 16 * res ) + hex_char_to_int (*first); } - + *out = res; return ++out; } @@ -138,7 +140,7 @@ namespace detail { /// \fn hex ( InputIterator first, InputIterator last, OutputIterator out ) /// \brief Converts a sequence of integral types into a hexadecimal sequence of characters. -/// +/// /// \param first The start of the input sequence /// \param last One past the end of the input sequence /// \param out An output iterator to the results into @@ -148,14 +150,31 @@ template typename boost::enable_if::value_type>, OutputIterator>::type hex ( InputIterator first, InputIterator last, OutputIterator out ) { for ( ; first != last; ++first ) - out = detail::encode_one ( *first, out ); + out = detail::encode_one ( *first, out, "0123456789ABCDEF" ); return out; } - + + +/// \fn hex_lower ( InputIterator first, InputIterator last, OutputIterator out ) +/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters. +/// +/// \param first The start of the input sequence +/// \param last One past the end of the input sequence +/// \param out An output iterator to the results into +/// \return The updated output iterator +/// \note Based on the MySQL function of the same name +template +typename boost::enable_if::value_type>, OutputIterator>::type +hex_lower ( InputIterator first, InputIterator last, OutputIterator out ) { + for ( ; first != last; ++first ) + out = detail::encode_one ( *first, out, "0123456789abcdef" ); + return out; + } + /// \fn hex ( const T *ptr, OutputIterator out ) /// \brief Converts a sequence of integral types into a hexadecimal sequence of characters. -/// +/// /// \param ptr A pointer to a 0-terminated sequence of data. /// \param out An output iterator to the results into /// \return The updated output iterator @@ -164,13 +183,30 @@ template typename boost::enable_if, OutputIterator>::type hex ( const T *ptr, OutputIterator out ) { while ( *ptr ) - out = detail::encode_one ( *ptr++, out ); + out = detail::encode_one ( *ptr++, out, "0123456789ABCDEF" ); return out; } + +/// \fn hex_lower ( const T *ptr, OutputIterator out ) +/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters. +/// +/// \param ptr A pointer to a 0-terminated sequence of data. +/// \param out An output iterator to the results into +/// \return The updated output iterator +/// \note Based on the MySQL function of the same name +template +typename boost::enable_if, OutputIterator>::type +hex_lower ( const T *ptr, OutputIterator out ) { + while ( *ptr ) + out = detail::encode_one ( *ptr++, out, "0123456789abcdef" ); + return out; + } + + /// \fn hex ( const Range &r, OutputIterator out ) /// \brief Converts a sequence of integral types into a hexadecimal sequence of characters. -/// +/// /// \param r The input range /// \param out An output iterator to the results into /// \return The updated output iterator @@ -182,9 +218,23 @@ hex ( const Range &r, OutputIterator out ) { } +/// \fn hex_lower ( const Range &r, OutputIterator out ) +/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters. +/// +/// \param r The input range +/// \param out An output iterator to the results into +/// \return The updated output iterator +/// \note Based on the MySQL function of the same name +template +typename boost::enable_if::value_type>, OutputIterator>::type +hex_lower ( const Range &r, OutputIterator out ) { + return hex_lower (boost::begin(r), boost::end(r), out); +} + + /// \fn unhex ( InputIterator first, InputIterator last, OutputIterator out ) /// \brief Converts a sequence of hexadecimal characters into a sequence of integers. -/// +/// /// \param first The start of the input sequence /// \param last One past the end of the input sequence /// \param out An output iterator to the results into @@ -200,7 +250,7 @@ OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator o /// \fn unhex ( const T *ptr, OutputIterator out ) /// \brief Converts a sequence of hexadecimal characters into a sequence of integers. -/// +/// /// \param ptr A pointer to a null-terminated input sequence. /// \param out An output iterator to the results into /// \return The updated output iterator @@ -218,7 +268,7 @@ OutputIterator unhex ( const T *ptr, OutputIterator out ) { /// \fn OutputIterator unhex ( const Range &r, OutputIterator out ) /// \brief Converts a sequence of hexadecimal characters into a sequence of integers. -/// +/// /// \param r The input range /// \param out An output iterator to the results into /// \return The updated output iterator @@ -231,7 +281,7 @@ OutputIterator unhex ( const Range &r, OutputIterator out ) { /// \fn String hex ( const String &input ) /// \brief Converts a sequence of integral types into a hexadecimal sequence of characters. -/// +/// /// \param input A container to be converted /// \return A container with the encoded text template @@ -242,9 +292,24 @@ String hex ( const String &input ) { return output; } + +/// \fn String hex_lower ( const String &input ) +/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters. +/// +/// \param input A container to be converted +/// \return A container with the encoded text +template +String hex_lower ( const String &input ) { + String output; + output.reserve (input.size () * (2 * sizeof (typename String::value_type))); + (void) hex_lower (input, std::back_inserter (output)); + return output; + } + + /// \fn String unhex ( const String &input ) /// \brief Converts a sequence of hexadecimal characters into a sequence of characters. -/// +/// /// \param input A container to be converted /// \return A container with the decoded text template diff --git a/include/boost/algorithm/is_palindrome.hpp b/include/boost/algorithm/is_palindrome.hpp new file mode 100644 index 0000000..0988110 --- /dev/null +++ b/include/boost/algorithm/is_palindrome.hpp @@ -0,0 +1,140 @@ +/* + Copyright (c) Alexander Zaitsev , 2016 + + 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. +*/ + +/// \file is_palindrome.hpp +/// \brief Checks the input sequence on palindrome. +/// \author Alexander Zaitsev + +#ifndef BOOST_ALGORITHM_IS_PALINDROME_HPP +#define BOOST_ALGORITHM_IS_PALINDROME_HPP + +#include +#include +#include + +#include +#include + +namespace boost { namespace algorithm { + +/// \fn is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end, Predicate p ) +/// \return true if the entire sequence is palindrome +/// +/// \param begin The start of the input sequence +/// \param end One past the end of the input sequence +/// \param p A predicate used to compare the values. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p) +{ + if(begin == end) + { + return true; + } + + --end; + while(begin != end) + { + if(!p(*begin, *end)) + { + return false; + } + ++begin; + if(begin == end) + { + break; + } + --end; + } + return true; +} + +/// \fn is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end ) +/// \return true if the entire sequence is palindrome +/// +/// \param begin The start of the input sequence +/// \param end One past the end of the input sequence +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end) +{ + return is_palindrome(begin, end, + std::equal_to::value_type> ()); +} + +/// \fn is_palindrome ( const R& range ) +/// \return true if the entire sequence is palindrome +/// +/// \param range The range to be tested. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(const R& range) +{ + return is_palindrome(boost::begin(range), boost::end(range)); +} + +/// \fn is_palindrome ( const R& range, Predicate p ) +/// \return true if the entire sequence is palindrome +/// +/// \param range The range to be tested. +/// \param p A predicate used to compare the values. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(const R& range, Predicate p) +{ + return is_palindrome(boost::begin(range), boost::end(range), p); +} + +/// \fn is_palindrome ( const char* str ) +/// \return true if the entire sequence is palindrome +/// +/// \param str C-string to be tested. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +bool is_palindrome(const char* str) +{ + if(!str) + return true; + return is_palindrome(str, str + strlen(str)); +} + +/// \fn is_palindrome ( const char* str, Predicate p ) +/// \return true if the entire sequence is palindrome +/// +/// \param str C-string to be tested. +/// \param p A predicate used to compare the values. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(const char* str, Predicate p) +{ + if(!str) + return true; + return is_palindrome(str, str + strlen(str), p); +} +}} + +#endif // BOOST_ALGORITHM_IS_PALINDROME_HPP diff --git a/include/boost/algorithm/searching/boyer_moore.hpp b/include/boost/algorithm/searching/boyer_moore.hpp index c5fe9fa..192d4de 100644 --- a/include/boost/algorithm/searching/boyer_moore.hpp +++ b/include/boost/algorithm/searching/boyer_moore.hpp @@ -75,25 +75,27 @@ Requirements: /// \param corpus_last One past the end of the data to search /// template - corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const { + std::pair + operator () ( corpusIter corpus_first, corpusIter corpus_last ) const { BOOST_STATIC_ASSERT (( boost::is_same< typename std::iterator_traits::value_type, typename std::iterator_traits::value_type>::value )); - if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it! - if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start + if ( corpus_first == corpus_last ) return std::make_pair(corpus_last, corpus_last); // if nothing to search, we didn't find it! + if ( pat_first == pat_last ) return std::make_pair(corpus_first, corpus_first); // empty pattern matches at start const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last ); // If the pattern is larger than the corpus, we can't find it! if ( k_corpus_length < k_pattern_length ) - return corpus_last; + return std::make_pair(corpus_last, corpus_last); // Do the search - return this->do_search ( corpus_first, corpus_last ); + return this->do_search ( corpus_first, corpus_last ); } template - typename boost::range_iterator::type operator () ( Range &r ) const { + std::pair::type, typename boost::range_iterator::type> + operator () ( Range &r ) const { return (*this) (boost::begin(r), boost::end(r)); } @@ -112,7 +114,8 @@ Requirements: /// \param p A predicate used for the search comparisons. /// template - corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last ) const { + std::pair + do_search ( corpusIter corpus_first, corpusIter corpus_last ) const { /* ---- Do the matching ---- */ corpusIter curPos = corpus_first; const corpusIter lastPos = corpus_last - k_pattern_length; @@ -126,7 +129,7 @@ Requirements: j--; // We matched - we're done! if ( j == 0 ) - return curPos; + return std::make_pair(curPos, curPos + k_pattern_length); } // Since we didn't match, figure out how far to skip forward @@ -138,7 +141,7 @@ Requirements: curPos += suffix_ [ j ]; } - return corpus_last; // We didn't find anything + return std::make_pair(corpus_last, corpus_last); // We didn't find anything } @@ -149,8 +152,8 @@ Requirements: template - void compute_bm_prefix ( Iter pat_first, Iter pat_last, Container &prefix ) { - const std::size_t count = std::distance ( pat_first, pat_last ); + void compute_bm_prefix ( Iter first, Iter last, Container &prefix ) { + const std::size_t count = std::distance ( first, last ); BOOST_ASSERT ( count > 0 ); BOOST_ASSERT ( prefix.size () == count ); @@ -158,26 +161,26 @@ Requirements: std::size_t k = 0; for ( std::size_t i = 1; i < count; ++i ) { BOOST_ASSERT ( k < count ); - while ( k > 0 && ( pat_first[k] != pat_first[i] )) { + while ( k > 0 && ( first[k] != first[i] )) { BOOST_ASSERT ( k < count ); k = prefix [ k - 1 ]; } - if ( pat_first[k] == pat_first[i] ) + if ( first[k] == first[i] ) k++; prefix [ i ] = k; } } - void build_suffix_table ( patIter pat_first, patIter pat_last ) { - const std::size_t count = (std::size_t) std::distance ( pat_first, pat_last ); + void build_suffix_table ( patIter first, patIter last ) { + const std::size_t count = (std::size_t) std::distance ( first, last ); if ( count > 0 ) { // empty pattern std::vector::value_type> reversed(count); - (void) std::reverse_copy ( pat_first, pat_last, reversed.begin ()); + (void) std::reverse_copy ( first, last, reversed.begin ()); std::vector prefix (count); - compute_bm_prefix ( pat_first, pat_last, prefix ); + compute_bm_prefix ( first, last, prefix ); std::vector prefix_reversed (count); compute_bm_prefix ( reversed.begin (), reversed.end (), prefix_reversed ); @@ -211,7 +214,7 @@ Requirements: /// \param pat_last One past the end of the data to search for /// template - corpusIter boyer_moore_search ( + std::pair boyer_moore_search ( corpusIter corpus_first, corpusIter corpus_last, patIter pat_first, patIter pat_last ) { @@ -220,7 +223,7 @@ Requirements: } template - corpusIter boyer_moore_search ( + std::pair boyer_moore_search ( corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern ) { typedef typename boost::range_iterator::type pattern_iterator; @@ -229,8 +232,9 @@ Requirements: } template - typename boost::lazy_disable_if_c< - boost::is_same::value, typename boost::range_iterator > + typename boost::disable_if_c< + boost::is_same::value, + std::pair::type, typename boost::range_iterator::type> > ::type boyer_moore_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last ) { @@ -239,7 +243,7 @@ Requirements: } template - typename boost::range_iterator::type + std::pair::type, typename boost::range_iterator::type> boyer_moore_search ( CorpusRange &corpus, const PatternRange &pattern ) { typedef typename boost::range_iterator::type pattern_iterator; diff --git a/include/boost/algorithm/searching/boyer_moore_horspool.hpp b/include/boost/algorithm/searching/boyer_moore_horspool.hpp index 758ded2..aacb5cb 100644 --- a/include/boost/algorithm/searching/boyer_moore_horspool.hpp +++ b/include/boost/algorithm/searching/boyer_moore_horspool.hpp @@ -64,33 +64,34 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html ~boyer_moore_horspool () {} - /// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p ) + /// \fn operator ( corpusIter corpus_first, corpusIter corpus_last) /// \brief Searches the corpus for the pattern that was passed into the constructor /// /// \param corpus_first The start of the data to search (Random Access Iterator) /// \param corpus_last One past the end of the data to search - /// \param p A predicate used for the search comparisons. /// template - corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const { + std::pair + operator () ( corpusIter corpus_first, corpusIter corpus_last ) const { BOOST_STATIC_ASSERT (( boost::is_same< typename std::iterator_traits::value_type, typename std::iterator_traits::value_type>::value )); - if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it! - if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start + if ( corpus_first == corpus_last ) return std::make_pair(corpus_last, corpus_last); // if nothing to search, we didn't find it! + if ( pat_first == pat_last ) return std::make_pair(corpus_first, corpus_first); // empty pattern matches at start const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last ); // If the pattern is larger than the corpus, we can't find it! if ( k_corpus_length < k_pattern_length ) - return corpus_last; + return std::make_pair(corpus_last, corpus_last); // Do the search return this->do_search ( corpus_first, corpus_last ); } template - typename boost::range_iterator::type operator () ( Range &r ) const { + std::pair::type, typename boost::range_iterator::type> + operator () ( Range &r ) const { return (*this) (boost::begin(r), boost::end(r)); } @@ -108,7 +109,8 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html /// \param k_corpus_length The length of the corpus to search /// template - corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last ) const { + std::pair + do_search ( corpusIter corpus_first, corpusIter corpus_last ) const { corpusIter curPos = corpus_first; const corpusIter lastPos = corpus_last - k_pattern_length; while ( curPos <= lastPos ) { @@ -117,14 +119,14 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html while ( pat_first [j] == curPos [j] ) { // We matched - we're done! if ( j == 0 ) - return curPos; + return std::make_pair(curPos, curPos + k_pattern_length); j--; } curPos += skip_ [ curPos [ k_pattern_length - 1 ]]; } - return corpus_last; + return std::make_pair(corpus_last, corpus_last); } // \endcond }; @@ -142,7 +144,7 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html /// \param pat_last One past the end of the data to search for /// template - corpusIter boyer_moore_horspool_search ( + std::pair boyer_moore_horspool_search ( corpusIter corpus_first, corpusIter corpus_last, patIter pat_first, patIter pat_last ) { @@ -151,7 +153,7 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html } template - corpusIter boyer_moore_horspool_search ( + std::pair boyer_moore_horspool_search ( corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern ) { typedef typename boost::range_iterator::type pattern_iterator; @@ -160,8 +162,9 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html } template - typename boost::lazy_disable_if_c< - boost::is_same::value, typename boost::range_iterator > + typename boost::disable_if_c< + boost::is_same::value, + std::pair::type, typename boost::range_iterator::type> > ::type boyer_moore_horspool_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last ) { @@ -170,7 +173,7 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html } template - typename boost::range_iterator::type + std::pair::type, typename boost::range_iterator::type> boyer_moore_horspool_search ( CorpusRange &corpus, const PatternRange &pattern ) { typedef typename boost::range_iterator::type pattern_iterator; diff --git a/include/boost/algorithm/searching/detail/bm_traits.hpp b/include/boost/algorithm/searching/detail/bm_traits.hpp index b39e539..1214363 100644 --- a/include/boost/algorithm/searching/detail/bm_traits.hpp +++ b/include/boost/algorithm/searching/detail/bm_traits.hpp @@ -79,7 +79,7 @@ namespace boost { namespace algorithm { namespace detail { skip_map skip_; const value_type k_default_value; public: - skip_table ( std::size_t patSize, value_type default_value ) : k_default_value ( default_value ) { + skip_table ( std::size_t /*patSize*/, value_type default_value ) : k_default_value ( default_value ) { std::fill_n ( skip_.begin(), skip_.size(), default_value ); } diff --git a/include/boost/algorithm/searching/knuth_morris_pratt.hpp b/include/boost/algorithm/searching/knuth_morris_pratt.hpp index aaeeb51..c890c9c 100644 --- a/include/boost/algorithm/searching/knuth_morris_pratt.hpp +++ b/include/boost/algorithm/searching/knuth_morris_pratt.hpp @@ -69,23 +69,26 @@ namespace boost { namespace algorithm { /// \param p A predicate used for the search comparisons. /// template - corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const { + std::pair + operator () ( corpusIter corpus_first, corpusIter corpus_last ) const { BOOST_STATIC_ASSERT (( boost::is_same< typename std::iterator_traits::value_type, typename std::iterator_traits::value_type>::value )); - if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it! - if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start + + if ( corpus_first == corpus_last ) return std::make_pair(corpus_last, corpus_last); // if nothing to search, we didn't find it! + if ( pat_first == pat_last ) return std::make_pair(corpus_first, corpus_first); // empty pattern matches at start const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last ); // If the pattern is larger than the corpus, we can't find it! if ( k_corpus_length < k_pattern_length ) - return corpus_last; + return std::make_pair(corpus_last, corpus_last); - return do_search ( corpus_first, corpus_last, k_corpus_length ); + return do_search ( corpus_first, corpus_last, k_corpus_length ); } template - typename boost::range_iterator::type operator () ( Range &r ) const { + std::pair::type, typename boost::range_iterator::type> + operator () ( Range &r ) const { return (*this) (boost::begin(r), boost::end(r)); } @@ -103,7 +106,8 @@ namespace boost { namespace algorithm { /// \param p A predicate used for the search comparisons. /// template - corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last, + std::pair + do_search ( corpusIter corpus_first, corpusIter corpus_last, difference_type k_corpus_length ) const { difference_type match_start = 0; // position in the corpus that we're matching @@ -135,7 +139,7 @@ namespace boost { namespace algorithm { while ( match_start <= last_match ) { while ( pat_first [ idx ] == corpus_first [ match_start + idx ] ) { if ( ++idx == k_pattern_length ) - return corpus_first + match_start; + return std::make_pair(corpus_first + match_start, corpus_first + match_start + k_pattern_length); } // Figure out where to start searching again // assert ( idx - skip_ [ idx ] > 0 ); // we're always moving forward @@ -146,7 +150,7 @@ namespace boost { namespace algorithm { #endif // We didn't find anything - return corpus_last; + return std::make_pair(corpus_last, corpus_last); } @@ -202,7 +206,7 @@ namespace boost { namespace algorithm { /// \param pat_last One past the end of the data to search for /// template - corpusIter knuth_morris_pratt_search ( + std::pair knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last, patIter pat_first, patIter pat_last ) { @@ -211,7 +215,7 @@ namespace boost { namespace algorithm { } template - corpusIter knuth_morris_pratt_search ( + std::pair knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern ) { typedef typename boost::range_iterator::type pattern_iterator; @@ -220,8 +224,9 @@ namespace boost { namespace algorithm { } template - typename boost::lazy_disable_if_c< - boost::is_same::value, typename boost::range_iterator > + typename boost::disable_if_c< + boost::is_same::value, + std::pair::type, typename boost::range_iterator::type> > ::type knuth_morris_pratt_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last ) { @@ -230,7 +235,7 @@ namespace boost { namespace algorithm { } template - typename boost::range_iterator::type + std::pair::type, typename boost::range_iterator::type> knuth_morris_pratt_search ( CorpusRange &corpus, const PatternRange &pattern ) { typedef typename boost::range_iterator::type pattern_iterator; diff --git a/include/boost/algorithm/string/detail/case_conv.hpp b/include/boost/algorithm/string/detail/case_conv.hpp index 42621c7..233912c 100644 --- a/include/boost/algorithm/string/detail/case_conv.hpp +++ b/include/boost/algorithm/string/detail/case_conv.hpp @@ -30,8 +30,10 @@ namespace boost { // a tolower functor template - struct to_lowerF : public std::unary_function + struct to_lowerF { + typedef CharT argument_type; + typedef CharT result_type; // Constructor to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {} @@ -50,8 +52,10 @@ namespace boost { // a toupper functor template - struct to_upperF : public std::unary_function + struct to_upperF { + typedef CharT argument_type; + typedef CharT result_type; // Constructor to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {} diff --git a/include/boost/algorithm/string/detail/find_iterator.hpp b/include/boost/algorithm/string/detail/find_iterator.hpp index 9b78a0f..4f90a98 100644 --- a/include/boost/algorithm/string/detail/find_iterator.hpp +++ b/include/boost/algorithm/string/detail/find_iterator.hpp @@ -40,7 +40,7 @@ namespace boost { // Protected construction/destruction // Default constructor - find_iterator_base() {}; + find_iterator_base() {} // Copy construction find_iterator_base( const find_iterator_base& Other ) : m_Finder(Other.m_Finder) {} diff --git a/include/boost/algorithm/string/detail/util.hpp b/include/boost/algorithm/string/detail/util.hpp index cf4a8b1..7844b67 100644 --- a/include/boost/algorithm/string/detail/util.hpp +++ b/include/boost/algorithm/string/detail/util.hpp @@ -89,9 +89,10 @@ namespace boost { template< typename SeqT, typename IteratorT=BOOST_STRING_TYPENAME SeqT::const_iterator > - struct copy_iterator_rangeF : - public std::unary_function< iterator_range, SeqT > + struct copy_iterator_rangeF { + typedef iterator_range argument_type; + typedef SeqT result_type; SeqT operator()( const iterator_range& Range ) const { return copy_range(Range); diff --git a/include/boost/algorithm/string/replace.hpp b/include/boost/algorithm/string/replace.hpp index 0c04e47..2adb031 100644 --- a/include/boost/algorithm/string/replace.hpp +++ b/include/boost/algorithm/string/replace.hpp @@ -401,7 +401,6 @@ namespace boost { \param Search A substring to be searched for \param Format A substitute string \param Loc A locale used for case insensitive comparison - \return A reference to the modified input */ template inline void ireplace_last( @@ -643,7 +642,6 @@ namespace boost { \param Input An input string \param Search A substring to be searched for \param Format A substitute string - \return A reference to the modified input */ template inline void replace_all( diff --git a/minmax/example/minmax_ex.cpp b/minmax/example/minmax_ex.cpp index d806709..d77820b 100644 --- a/minmax/example/minmax_ex.cpp +++ b/minmax/example/minmax_ex.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index dd18ef8..fb00843 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -68,6 +68,8 @@ alias unit_test_framework [ run sort_subrange_test.cpp unit_test_framework : : : : sort_subrange_test ] [ run partition_subrange_test.cpp unit_test_framework : : : : partition_subrange_test ] +# Is_palindrome tests + [ run is_palindrome_test.cpp unit_test_framework : : : : is_palindrome_test ] ; } diff --git a/test/all_of_test.cpp b/test/all_of_test.cpp index 79e25a2..4bd3512 100644 --- a/test/all_of_test.cpp +++ b/test/all_of_test.cpp @@ -20,7 +20,6 @@ template struct is_ : public std::unary_function { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} - BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value diff --git a/test/any_of_test.cpp b/test/any_of_test.cpp index 6193a2f..ac089d6 100644 --- a/test/any_of_test.cpp +++ b/test/any_of_test.cpp @@ -20,7 +20,6 @@ template struct is_ : public std::unary_function { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} - BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value diff --git a/test/empty_search_test.cpp b/test/empty_search_test.cpp index 22317f1..cb37678 100644 --- a/test/empty_search_test.cpp +++ b/test/empty_search_test.cpp @@ -26,56 +26,56 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK ( boost::algorithm::boyer_moore_search ( cs.begin (), cs.end (), estr.begin (), estr.end ()) - == cs.begin () + == std::make_pair(cs.begin(), cs.begin()) ); BOOST_CHECK ( boost::algorithm::boyer_moore_horspool_search ( cs.begin (), cs.end (), estr.begin (), estr.end ()) - == cs.begin () + == std::make_pair(cs.begin(), cs.begin()) ); BOOST_CHECK ( boost::algorithm::knuth_morris_pratt_search ( cs.begin (), cs.end (), estr.begin (), estr.end ()) - == cs.begin () + == std::make_pair(cs.begin(), cs.begin()) ); // empty corpus, non-empty pattern BOOST_CHECK ( boost::algorithm::boyer_moore_search ( estr.begin (), estr.end (), str.begin (), str.end ()) - == estr.end () + == std::make_pair(estr.end(), estr.end()) ); BOOST_CHECK ( boost::algorithm::boyer_moore_horspool_search ( estr.begin (), estr.end (), str.begin (), str.end ()) - == estr.end () + == std::make_pair(estr.end(), estr.end()) ); BOOST_CHECK ( boost::algorithm::knuth_morris_pratt_search ( estr.begin (), estr.end (), str.begin (), str.end ()) - == estr.end () + == std::make_pair(estr.end(), estr.end()) ); // non-empty corpus, empty pattern BOOST_CHECK ( boost::algorithm::boyer_moore_search ( str.begin (), str.end (), estr.begin (), estr.end ()) - == str.begin () + == std::make_pair(str.begin(), str.begin()) ); BOOST_CHECK ( boost::algorithm::boyer_moore_horspool_search ( str.begin (), str.end (), estr.begin (), estr.end ()) - == str.begin () + == std::make_pair(str.begin(), str.begin()) ); BOOST_CHECK ( boost::algorithm::knuth_morris_pratt_search ( str.begin (), str.end (), estr.begin (), estr.end ()) - == str.begin () + == std::make_pair(str.begin(), str.begin()) ); } diff --git a/test/hex_test1.cpp b/test/hex_test1.cpp index d9f5364..31e3f9d 100644 --- a/test/hex_test1.cpp +++ b/test/hex_test1.cpp @@ -9,6 +9,7 @@ #include #include +#include #define BOOST_TEST_MAIN #include @@ -42,6 +43,31 @@ void test_to_hex ( const typename String::value_type ** tests ) { } } +template +void test_to_hex_lower ( const typename String::value_type ** tests ) { + for ( const typename String::value_type **p = tests; *p; p++ ) { + String arg, argh, one, two, three, four; + arg.assign ( *p ); + boost::algorithm::hex_lower ( *p, std::back_inserter ( one )); + boost::algorithm::hex_lower ( arg, std::back_inserter ( two )); + boost::algorithm::hex_lower ( arg.begin (), arg.end (), std::back_inserter ( three )); + four = boost::algorithm::hex_lower ( arg ); + BOOST_CHECK ( one == two ); + BOOST_CHECK ( one == three ); + BOOST_CHECK ( one == four ); + argh = one; + one.clear (); two.clear (); three.clear (); four.clear (); + boost::algorithm::unhex ( argh.c_str (), std::back_inserter ( one )); + boost::algorithm::unhex ( argh, std::back_inserter ( two )); + boost::algorithm::unhex ( argh.begin (), argh.end (), std::back_inserter ( three )); + four = boost::algorithm::unhex ( argh ); + BOOST_CHECK ( one == two ); + BOOST_CHECK ( one == three ); + BOOST_CHECK ( one == four ); + BOOST_CHECK ( one == arg ); + } + } + template void test_from_hex_success ( const typename String::value_type ** tests ) { @@ -61,6 +87,11 @@ void test_from_hex_success ( const typename String::value_type ** tests ) { boost::algorithm::hex ( argh, std::back_inserter ( two )); boost::algorithm::hex ( argh.begin (), argh.end (), std::back_inserter ( three )); four = boost::algorithm::hex ( argh ); + boost::algorithm::to_lower( arg ); + boost::algorithm::to_lower( one ); + boost::algorithm::to_lower( two ); + boost::algorithm::to_lower( three ); + boost::algorithm::to_lower( four ); BOOST_CHECK ( one == two ); BOOST_CHECK ( one == three ); BOOST_CHECK ( one == four ); @@ -113,6 +144,7 @@ const wchar_t *tohex_w [] = { const char *fromhex [] = { "20", "2122234556FF", + "2122234556ff", NULL // End of the list }; @@ -120,6 +152,7 @@ const char *fromhex [] = { const wchar_t *fromhex_w [] = { L"00101020", L"2122234556FF3456", + L"2122234556ff3456", NULL // End of the list }; @@ -129,6 +162,8 @@ const char *fromhex_fail [] = { "H", "234", "21222G4556FF", + "h", + "21222g4556ff", NULL // End of the list }; @@ -139,6 +174,8 @@ const wchar_t *fromhex_fail_w [] = { L"H", L"234", L"21222G4556FF", + L"h", + L"21222g4556ff", NULL // End of the list }; @@ -146,10 +183,12 @@ const wchar_t *fromhex_fail_w [] = { BOOST_AUTO_TEST_CASE( test_main ) { test_to_hex ( tohex ); + test_to_hex_lower ( tohex ); test_from_hex_success ( fromhex ); test_from_hex_failure ( fromhex_fail ); test_to_hex ( tohex_w ); + test_to_hex_lower ( tohex_w ); test_from_hex_success ( fromhex_w ); test_from_hex_failure ( fromhex_fail_w ); } diff --git a/test/hex_test4.cpp b/test/hex_test4.cpp index df6e8d8..ba1ee34 100644 --- a/test/hex_test4.cpp +++ b/test/hex_test4.cpp @@ -11,6 +11,7 @@ Try ostream_iterators #include #include +#include #define BOOST_TEST_MAIN #include diff --git a/test/is_palindrome_test.cpp b/test/is_palindrome_test.cpp new file mode 100644 index 0000000..c668e9d --- /dev/null +++ b/test/is_palindrome_test.cpp @@ -0,0 +1,79 @@ +/* + Copyright (c) Alexander Zaitsev , 2016 + + 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 + +#define BOOST_TEST_MAIN +#include + +#include +#include +#include +#include + + +namespace ba = boost::algorithm; + + +template +bool funcComparator(const T& v1, const T& v2) +{ + return v1 == v2; +} + +struct functorComparator +{ + template + bool operator()(const T& v1, const T& v2) const + { + return v1 == v2; + } +}; + +#define Begin(arr) (arr) +#define End(arr) (arr+(sizeof(arr)/(sizeof(arr[0])))) + +void test_is_palindrome() +{ + const std::list empty; + const std::vector singleElement(1, 'z'); + int oddNonPalindrome[] = {3,2,2}; + const int oddPalindrome[] = {1,2,3,2,1}; + const int evenPalindrome[] = {1,2,2,1}; + int evenNonPalindrome[] = {1,4,8,8}; + const char* stringNullPtr = NULL; + + // Test a default operator== + BOOST_CHECK ( ba::is_palindrome(empty)); + BOOST_CHECK ( ba::is_palindrome(singleElement)); + BOOST_CHECK (!ba::is_palindrome(Begin(oddNonPalindrome), End(oddNonPalindrome))); + BOOST_CHECK ( ba::is_palindrome(Begin(oddPalindrome), End(oddPalindrome))); + BOOST_CHECK ( ba::is_palindrome(Begin(evenPalindrome), End(evenPalindrome))); + BOOST_CHECK (!ba::is_palindrome(Begin(evenNonPalindrome), End(evenNonPalindrome))); + + //Test the custom comparators + BOOST_CHECK ( ba::is_palindrome(empty.begin(), empty.end(), functorComparator())); + BOOST_CHECK (!ba::is_palindrome(Begin(oddNonPalindrome), End(oddNonPalindrome), funcComparator)); + BOOST_CHECK ( ba::is_palindrome(evenPalindrome, std::equal_to())); + + //Test C-strings like cases + BOOST_CHECK ( ba::is_palindrome(stringNullPtr)); + BOOST_CHECK ( ba::is_palindrome("")); + BOOST_CHECK ( ba::is_palindrome("a")); + BOOST_CHECK ( ba::is_palindrome("abacaba", std::equal_to())); + BOOST_CHECK ( ba::is_palindrome("abba")); + BOOST_CHECK (!ba::is_palindrome("acab")); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + test_is_palindrome (); +} diff --git a/test/none_of_test.cpp b/test/none_of_test.cpp index dc7b30b..d4226e2 100644 --- a/test/none_of_test.cpp +++ b/test/none_of_test.cpp @@ -20,7 +20,6 @@ template struct is_ : public std::unary_function { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} - BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value diff --git a/test/one_of_test.cpp b/test/one_of_test.cpp index 49e3d5a..807a937 100644 --- a/test/one_of_test.cpp +++ b/test/one_of_test.cpp @@ -20,7 +20,6 @@ template struct is_ : public std::unary_function { BOOST_CXX14_CONSTEXPR is_ ( T v ) : val_ ( v ) {} - BOOST_CXX14_CONSTEXPR bool operator () ( T comp ) const { return val_ == comp; } private: is_ (); // need a value diff --git a/test/partition_subrange_test.cpp b/test/partition_subrange_test.cpp index 018f140..c33fb46 100644 --- a/test/partition_subrange_test.cpp +++ b/test/partition_subrange_test.cpp @@ -7,6 +7,20 @@ #include #include + +#if __cplusplus >= 201103L +#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 + namespace ba = boost::algorithm; template @@ -72,14 +86,14 @@ BOOST_AUTO_TEST_CASE( test_main ) // BOOST_CHECK_EQUAL(v[5], 5); // Mix them up and try again - single element - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b + 7, b + 8); check_sequence (b, v.end(), b + 7, b + 8); // BOOST_CHECK_EQUAL(v[7], 7); // Mix them up and try again - at the end - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b + 7, v.end()); check_sequence (b, v.end(), b + 7, v.end()); @@ -88,7 +102,7 @@ BOOST_AUTO_TEST_CASE( test_main ) // BOOST_CHECK_EQUAL(v[9], 9); // Mix them up and try again - at the beginning - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b, b + 2); check_sequence (b, v.end(), b, b + 2); @@ -96,12 +110,12 @@ BOOST_AUTO_TEST_CASE( test_main ) // BOOST_CHECK_EQUAL(v[1], 1); // Mix them up and try again - empty subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b, b); check_sequence (b, v.end(), b, b); // Mix them up and try again - entire subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b, v.end()); check_sequence (b, v.end(), b, v.end()); } @@ -120,14 +134,14 @@ BOOST_AUTO_TEST_CASE( test_main ) // BOOST_CHECK_EQUAL(v[5], 4); // Mix them up and try again - single element - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b + 7, b + 8, std::greater()); check_sequence (b, v.end(), b + 7, b + 8, std::greater()); // BOOST_CHECK_EQUAL(v[7], 2); // Mix them up and try again - at the end - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b + 7, v.end(), std::greater()); check_sequence (b, v.end(), b + 7, v.end(), std::greater()); @@ -136,7 +150,7 @@ BOOST_AUTO_TEST_CASE( test_main ) // BOOST_CHECK_EQUAL(v[9], 0); // Mix them up and try again - at the beginning - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b, b + 2, std::greater()); check_sequence (b, v.end(), b, b + 2, std::greater()); @@ -144,12 +158,12 @@ BOOST_AUTO_TEST_CASE( test_main ) // BOOST_CHECK_EQUAL(v[1], 8); // Mix them up and try again - empty subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b, b, std::greater()); check_sequence (b, v.end(), b, b, std::greater()); // Mix them up and try again - entire subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::partition_subrange(b, v.end(), b, v.end(), std::greater()); check_sequence (b, v.end(), b, v.end(), std::greater()); } diff --git a/test/search_test1.cpp b/test/search_test1.cpp index 7c49a3a..3fe3b91 100644 --- a/test/search_test1.cpp +++ b/test/search_test1.cpp @@ -34,6 +34,7 @@ namespace { template void check_one_iter ( const Container &haystack, const std::string &needle, int expected ) { typedef typename Container::const_iterator iter_type; + typedef typename std::pair ret_type; typedef std::string::const_iterator pattern_type; iter_type hBeg = haystack.begin (); @@ -41,33 +42,40 @@ namespace { pattern_type nBeg = needle.begin (); pattern_type nEnd = needle.end (); +// iter_type ret0 = std::search (hBeg, hEnd, nBeg, nEnd); + ret_type ret1 = ba::boyer_moore_search (hBeg, hEnd, nBeg, nEnd); + ret_type ret1r = ba::boyer_moore_search (haystack, nBeg, nEnd); + ret_type ret2 = ba::boyer_moore_horspool_search (hBeg, hEnd, nBeg, nEnd); + ret_type ret3 = ba::knuth_morris_pratt_search (hBeg, hEnd, nBeg, nEnd); + iter_type it0 = std::search (hBeg, hEnd, nBeg, nEnd); - iter_type it1 = ba::boyer_moore_search (hBeg, hEnd, nBeg, nEnd); - iter_type it1r = ba::boyer_moore_search (haystack, nBeg, nEnd); - iter_type it2 = ba::boyer_moore_horspool_search (hBeg, hEnd, nBeg, nEnd); - iter_type it3 = ba::knuth_morris_pratt_search (hBeg, hEnd, nBeg, nEnd); - const int dist = it1 == hEnd ? -1 : std::distance ( hBeg, it1 ); +// iter_type it1 = ret1.first; +// iter_type it1r = ret1r.first; +// iter_type it2 = ret2.first; +// iter_type it3 = ret3.first; + const int dist = ret1.first == hEnd ? -1 : std::distance ( hBeg, ret1.first ); std::cout << "(Iterators) Pattern is " << needle.length () << ", haysstack is " << haystack.length () << " chars long; " << std::endl; try { - if ( it0 != it1 ) { + if ( it0 != ret1.first ) { throw std::runtime_error ( std::string ( "results mismatch between std::search and boyer-moore search" )); } - if ( it1 != it1r ) { + if ( ret1.first != ret1r.first || ret1.second != ret1r.second ) { throw std::runtime_error ( std::string ( "results mismatch between iterator and range boyer_moore search" )); } - if ( it1 != it2 ) { + if ( ret1.first != ret2.first || ret1.second != ret2.second ) { throw std::runtime_error ( std::string ( "results mismatch between boyer-moore and boyer-moore-horspool search" )); } - if ( it1 != it3 ) + if ( ret1.first != ret3.first || ret1.second != ret3.second ) { throw std::runtime_error ( std::string ( "results mismatch between boyer-moore and knuth-morris-pratt search" )); + } } @@ -75,10 +83,10 @@ namespace { std::cout << "Searching for: " << needle << std::endl; std::cout << "Expected: " << expected << "\n"; std::cout << " std: " << std::distance ( hBeg, it0 ) << "\n"; - std::cout << " bm: " << std::distance ( hBeg, it1 ) << "\n"; - std::cout << " bm(r): " << std::distance ( hBeg, it1r ) << "\n"; - std::cout << " bmh: " << std::distance ( hBeg, it2 ) << "\n"; - std::cout << " kpm: " << std::distance ( hBeg, it3 )<< "\n"; + std::cout << " bm: " << std::distance ( hBeg, ret1.first ) << "\n"; + std::cout << " bm(r): " << std::distance ( hBeg, ret1r.first ) << "\n"; + std::cout << " bmh: " << std::distance ( hBeg, ret2.first ) << "\n"; + std::cout << " kpm: " << std::distance ( hBeg, ret3.first )<< "\n"; std::cout << std::flush; throw ; } @@ -91,32 +99,35 @@ namespace { template void check_one_pointer ( const Container &haystack, const std::string &needle, int expected ) { typedef const typename Container::value_type *ptr_type; + typedef typename std::pair ret_type; + ptr_type hBeg = haystack.size () == 0 ? NULL : &*haystack.begin (); ptr_type hEnd = hBeg + haystack.size (); ptr_type nBeg = needle.size () == 0 ? NULL : &*needle.begin (); ptr_type nEnd = nBeg + needle.size (); ptr_type it0 = std::search (hBeg, hEnd, nBeg, nEnd); - ptr_type it1 = ba::boyer_moore_search (hBeg, hEnd, nBeg, nEnd); - ptr_type it2 = ba::boyer_moore_horspool_search (hBeg, hEnd, nBeg, nEnd); - ptr_type it3 = ba::knuth_morris_pratt_search (hBeg, hEnd, nBeg, nEnd); - const int dist = it1 == hEnd ? -1 : std::distance ( hBeg, it1 ); + ret_type ret1 = ba::boyer_moore_search (hBeg, hEnd, nBeg, nEnd); + ret_type ret2 = ba::boyer_moore_horspool_search (hBeg, hEnd, nBeg, nEnd); + ret_type ret3 = ba::knuth_morris_pratt_search (hBeg, hEnd, nBeg, nEnd); + const int dist = ret1.first == hEnd ? -1 : std::distance ( hBeg, ret1.first ); std::cout << "(Pointers) Pattern is " << needle.length () << ", haysstack is " << haystack.length () << " chars long; " << std::endl; try { - if ( it0 != it1 ) { + if ( it0 != ret1.first ) { throw std::runtime_error ( std::string ( "results mismatch between std::search and boyer-moore search" )); } - if ( it1 != it2 ) { + if ( ret1.first != ret2.first || ret1.second != ret2.second ) { throw std::runtime_error ( std::string ( "results mismatch between boyer-moore and boyer-moore-horspool search" )); } - if ( it1 != it3 ) + if ( ret1.first != ret3.first || ret1.second != ret3.second ) { throw std::runtime_error ( std::string ( "results mismatch between boyer-moore and knuth-morris-pratt search" )); + } } @@ -124,9 +135,9 @@ namespace { std::cout << "Searching for: " << needle << std::endl; std::cout << "Expected: " << expected << "\n"; std::cout << " std: " << std::distance ( hBeg, it0 ) << "\n"; - std::cout << " bm: " << std::distance ( hBeg, it1 ) << "\n"; - std::cout << " bmh: " << std::distance ( hBeg, it2 ) << "\n"; - std::cout << " kpm: " << std::distance ( hBeg, it3 )<< "\n"; + std::cout << " bm: " << std::distance ( hBeg, ret1.first ) << "\n"; + std::cout << " bmh: " << std::distance ( hBeg, ret2.first ) << "\n"; + std::cout << " kpm: " << std::distance ( hBeg, ret3.first )<< "\n"; std::cout << std::flush; throw ; } @@ -138,6 +149,7 @@ namespace { template void check_one_object ( const Container &haystack, const std::string &needle, int expected ) { typedef typename Container::const_iterator iter_type; + typedef typename std::pair ret_type; typedef std::string::const_iterator pattern_type; iter_type hBeg = haystack.begin (); @@ -150,58 +162,59 @@ namespace { ba::boyer_moore_horspool bmh ( nBeg, nEnd ); ba::knuth_morris_pratt kmp ( nBeg, nEnd ); - iter_type it0 = std::search (hBeg, hEnd, nBeg, nEnd); - iter_type it1 = bm (hBeg, hEnd); - iter_type it1r = bm (haystack); - iter_type rt1 = bm_r (hBeg, hEnd); - iter_type rt1r = bm_r (haystack); - iter_type it2 = bmh (hBeg, hEnd); - iter_type it3 = kmp (hBeg, hEnd); - const int dist = it1 == hEnd ? -1 : std::distance ( hBeg, it1 ); + iter_type it0 = std::search (hBeg, hEnd, nBeg, nEnd); + ret_type ret1 = bm (hBeg, hEnd); + ret_type ret1r = bm (haystack); + ret_type retr1 = bm_r (hBeg, hEnd); + ret_type retr1r = bm_r (haystack); + ret_type ret2 = bmh (hBeg, hEnd); + ret_type ret3 = kmp (hBeg, hEnd); + const int dist = ret1.first == hEnd ? -1 : std::distance ( hBeg, ret1.first ); std::cout << "(Objects) Pattern is " << needle.length () << ", haysstack is " << haystack.length () << " chars long; " << std::endl; try { - if ( it0 != it1 ) { + if ( it0 != ret1.first ) { throw std::runtime_error ( std::string ( "results mismatch between std::search and boyer-moore search" )); } - if ( it1 != it1r ) { + if ( ret1.first != ret1r.first || ret1.second != ret1r.second ) { throw std::runtime_error ( std::string ( "results mismatch between iterator and range boyer_moore search(1)" )); } - if ( it1 != rt1 ) { + if ( ret1.first != retr1.first || ret1.second != retr1.second ) { throw std::runtime_error ( std::string ( "results mismatch between iterator and range boyer_moore search(2)" )); } - if ( rt1 != rt1r ) { + if ( ret1.first != retr1r.first || ret1.second != retr1r.second ) { throw std::runtime_error ( std::string ( "results mismatch between iterator and range boyer_moore search(3)" )); } - if ( it1 != it2 ) { + if ( ret1.first != ret2.first || ret1.second != ret2.second ) { throw std::runtime_error ( std::string ( "results mismatch between boyer-moore and boyer-moore-horspool search" )); } - if ( it1 != it3 ) + if ( ret1.first != ret3.first || ret1.second != ret3.second ) { throw std::runtime_error ( std::string ( "results mismatch between boyer-moore and knuth-morris-pratt search" )); + } } catch ( ... ) { std::cout << "Searching for: " << needle << std::endl; - std::cout << "Expected: " << expected << "\n"; - std::cout << " std: " << std::distance ( hBeg, it0 ) << "\n"; - std::cout << " bm: " << std::distance ( hBeg, it1 ) << "\n"; - std::cout << " bm(r1): " << std::distance ( hBeg, it1r ) << "\n"; - std::cout << " bm(r2): " << std::distance ( hBeg, rt1 ) << "\n"; - std::cout << " bm(r3): " << std::distance ( hBeg, rt1r ) << "\n"; - std::cout << " bmh: " << std::distance ( hBeg, it2 ) << "\n"; - std::cout << " kpm: " << std::distance ( hBeg, it3 )<< "\n"; + std::cout << "Expected: " << expected << "\n"; + std::cout << " std: " << std::distance ( hBeg, it0 ) << "\n"; + std::cout << " bm: " << std::distance ( hBeg, ret1.first ) << "\n"; + std::cout << " bm(r1): " << std::distance ( hBeg, ret1r.first ) << "\n"; + std::cout << " bm(r2): " << std::distance ( hBeg, retr1.first ) << "\n"; + std::cout << " bm(r3): " << std::distance ( hBeg, retr1r.first ) << "\n"; + std::cout << " bmh: " << std::distance ( hBeg, ret2.first ) << "\n"; + std::cout << " kpm: " << std::distance ( hBeg, ret3.first )<< "\n"; std::cout << std::flush; throw ; } diff --git a/test/search_test2.cpp b/test/search_test2.cpp index 4d772ca..eba105e 100644 --- a/test/search_test2.cpp +++ b/test/search_test2.cpp @@ -33,8 +33,8 @@ typedef std::vector vec; needle.begin (), needle.end ()); \ if ( res != exp ) { \ std::cout << "On run # " << i << " expected " \ - << exp - haystack.begin () << " got " \ - << res - haystack.begin () << std::endl; \ + << exp.first - haystack.begin () << " got " \ + << res.first - haystack.begin () << std::endl; \ throw std::runtime_error \ ( "Unexpected result from " #call ); \ } \ @@ -51,8 +51,8 @@ typedef std::vector vec; res = s_o ( haystack.begin (), haystack.end ()); \ if ( res != exp ) { \ std::cout << "On run # " << i << " expected " \ - << exp - haystack.begin () << " got " \ - << res - haystack.begin () << std::endl; \ + << exp.first - haystack.begin () << " got " \ + << res.first - haystack.begin () << std::endl; \ throw std::runtime_error \ ( "Unexpected result from " #obj " object" ); \ } \ @@ -90,27 +90,33 @@ namespace { std::clock_t sTime; unsigned long stdDiff; - vec::const_iterator res; - vec::const_iterator exp; // the expected result + std::pair res; + std::pair exp; // the expected result + vec::const_iterator exp_start; if ( expected >= 0 ) - exp = haystack.begin () + expected; + exp_start = haystack.begin () + expected; else if ( expected == -1 ) - exp = haystack.end (); // we didn't find it! + exp_start = haystack.end (); // we didn't find it! else if ( expected == -2 ) - exp = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); + exp_start = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); else throw std::logic_error ( "Expected must be -2, -1, or >= 0" ); + if ( expected == -1 ) + exp = std::make_pair(haystack.end(), haystack.end()); + else + exp = std::make_pair(exp_start, exp_start + needle.size()); + std::cout << "Pattern is " << needle.size () << " entries long" << std::endl; std::cout << "Corpus is " << haystack.size () << " entries long" << std::endl; // First, the std library search sTime = std::clock (); for ( i = 0; i < NUM_TRIES; ++i ) { - res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); - if ( res != exp ) { - std::cout << "On run # " << i << " expected " << exp - haystack.begin () << " got " << res - haystack.begin () << std::endl; + vec::const_iterator s_res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); + if ( s_res != exp.first ) { + std::cout << "On run # " << i << " expected " << exp.first - haystack.begin () << " got " << s_res - haystack.begin () << std::endl; throw std::runtime_error ( "Unexpected result from std::search" ); } } diff --git a/test/search_test3.cpp b/test/search_test3.cpp index 96226cd..e4c7661 100644 --- a/test/search_test3.cpp +++ b/test/search_test3.cpp @@ -34,8 +34,8 @@ typedef std::vector vec; needle.begin (), needle.end ()); \ if ( res != exp ) { \ std::cout << "On run # " << i << " expected " \ - << exp - haystack.begin () << " got " \ - << res - haystack.begin () << std::endl; \ + << exp.first - haystack.begin () << " got " \ + << res.first - haystack.begin () << std::endl; \ throw std::runtime_error \ ( "Unexpected result from " #call ); \ } \ @@ -52,8 +52,8 @@ typedef std::vector vec; res = s_o ( haystack.begin (), haystack.end ()); \ if ( res != exp ) { \ std::cout << "On run # " << i << " expected " \ - << exp - haystack.begin () << " got " \ - << res - haystack.begin () << std::endl; \ + << exp.first - haystack.begin () << " got " \ + << res.first - haystack.begin () << std::endl; \ throw std::runtime_error \ ( "Unexpected result from " #obj " object" ); \ } \ @@ -90,27 +90,33 @@ namespace { std::clock_t sTime; unsigned long stdDiff; - vec::const_iterator res; - vec::const_iterator exp; // the expected result + std::pair res; + std::pair exp; // the expected result + vec::const_iterator exp_start; if ( expected >= 0 ) - exp = haystack.begin () + expected; + exp_start = haystack.begin () + expected; else if ( expected == -1 ) - exp = haystack.end (); // we didn't find it1 + exp_start = haystack.end (); // we didn't find it1 else if ( expected == -2 ) - exp = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); + exp_start = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); else throw std::logic_error ( "Expected must be -2, -1, or >= 0" ); + if ( expected == -1 ) + exp = std::make_pair(haystack.end(), haystack.end()); + else + exp = std::make_pair(exp_start, exp_start + needle.size()); + std::cout << "Pattern is " << needle.size () << " entries long" << std::endl; std::cout << "Corpus is " << haystack.size () << " entries long" << std::endl; // First, the std library search sTime = std::clock (); for ( i = 0; i < NUM_TRIES; ++i ) { - res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); - if ( res != exp ) { - std::cout << "On run # " << i << " expected " << exp - haystack.begin () << " got " << res - haystack.begin () << std::endl; + vec::const_iterator s_res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); + if ( s_res != exp.first ) { + std::cout << "On run # " << i << " expected " << exp.first - haystack.begin () << " got " << s_res - haystack.begin () << std::endl; throw std::runtime_error ( "Unexpected result from std::search" ); } } diff --git a/test/search_test4.cpp b/test/search_test4.cpp index 2b83267..997e359 100644 --- a/test/search_test4.cpp +++ b/test/search_test4.cpp @@ -30,8 +30,8 @@ typedef std::vector vec; res = boost::algorithm::call ( haystack, needle ); \ if ( res != exp ) { \ std::cout << "Expected " \ - << exp - haystack.begin () << " got " \ - << res - haystack.begin () << std::endl; \ + << exp.first - haystack.begin () << " got " \ + << res.first - haystack.begin () << std::endl; \ throw std::runtime_error \ ( "Unexpected result from " #call ); \ } \ @@ -43,8 +43,8 @@ typedef std::vector vec; res = s_o ( haystack ); \ if ( res != exp ) { \ std::cout << "Expected " \ - << exp - haystack.begin () << " got " \ - << res - haystack.begin () << std::endl; \ + << exp.first - haystack.begin () << " got " \ + << res.first - haystack.begin () << std::endl; \ throw std::runtime_error \ ( "Unexpected result from " #obj " object" ); \ } \ @@ -64,25 +64,31 @@ namespace { void check_one ( const vec &haystack, const vec &needle, int expected ) { - vec::const_iterator res; - vec::const_iterator exp; // the expected result + std::pair res; + std::pair exp; // the expected result + vec::const_iterator exp_start; if ( expected >= 0 ) - exp = haystack.begin () + expected; + exp_start = haystack.begin () + expected; else if ( expected == -1 ) - exp = haystack.end (); // we didn't find it1 + exp_start = haystack.end (); // we didn't find it1 else if ( expected == -2 ) - exp = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); + exp_start = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); else throw std::logic_error ( "Expected must be -2, -1, or >= 0" ); + if ( expected == -1 ) + exp = std::make_pair(haystack.end(), haystack.end()); + else + exp = std::make_pair(exp_start, exp_start + needle.size()); + std::cout << "Pattern is " << needle.size () << " entries long" << std::endl; std::cout << "Corpus is " << haystack.size () << " entries long" << std::endl; // First, the std library search - res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); - if ( res != exp ) { - std::cout << "Expected " << exp - haystack.begin () << " got " << res - haystack.begin () << std::endl; + vec::const_iterator s_res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ()); + if ( s_res != exp.first ) { + std::cout << "Expected " << exp.first - haystack.begin () << " got " << s_res - haystack.begin () << std::endl; throw std::runtime_error ( "Unexpected result from std::search" ); } diff --git a/test/sort_subrange_test.cpp b/test/sort_subrange_test.cpp index 4c1192e..de6a3fa 100644 --- a/test/sort_subrange_test.cpp +++ b/test/sort_subrange_test.cpp @@ -7,6 +7,20 @@ #include #include + +#if __cplusplus >= 201103L +#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 + namespace ba = boost::algorithm; template @@ -53,14 +67,14 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(v[5], 5); // Mix them up and try again - single element - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b + 7, b + 8); check_sequence (b, v.end(), b + 7, b + 8); BOOST_CHECK_EQUAL(v[7], 7); // Mix them up and try again - at the end - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b + 7, v.end()); check_sequence (b, v.end(), b + 7, v.end()); @@ -69,7 +83,7 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(v[9], 9); // Mix them up and try again - at the beginning - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b, b + 2); check_sequence (b, v.end(), b, b + 2); @@ -77,12 +91,12 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(v[1], 1); // Mix them up and try again - empty subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b, b); check_sequence (b, v.end(), b, b); // Mix them up and try again - entire subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b, v.end()); check_sequence (b, v.end(), b, v.end()); } @@ -101,14 +115,14 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(v[5], 4); // Mix them up and try again - single element - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b + 7, b + 8, std::greater()); check_sequence (b, v.end(), b + 7, b + 8, std::greater()); BOOST_CHECK_EQUAL(v[7], 2); // Mix them up and try again - at the end - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b + 7, v.end(), std::greater()); check_sequence (b, v.end(), b + 7, v.end(), std::greater()); @@ -117,7 +131,7 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(v[9], 0); // Mix them up and try again - at the beginning - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b, b + 2, std::greater()); check_sequence (b, v.end(), b, b + 2, std::greater()); @@ -125,12 +139,12 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(v[1], 8); // Mix them up and try again - empty subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b, b, std::greater()); check_sequence (b, v.end(), b, b, std::greater()); // Mix them up and try again - entire subrange - std::random_shuffle(v.begin(), v.end()); + do_shuffle(v.begin(), v.end()); ba::sort_subrange(b, v.end(), b, v.end(), std::greater()); check_sequence (b, v.end(), b, v.end(), std::greater()); }