From 8dfebc4580a16ff4083a5585827c5e9be40dd049 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 25 Oct 2016 14:31:26 +0300 Subject: [PATCH 1/5] Added README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..92a9140 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ + + Coverity Scan Build Status + From a838feb81ad02dabe3e619987990d19fc6bbbcf9 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Tue, 14 Feb 2017 12:22:49 +0300 Subject: [PATCH 2/5] Added is_partitioned_until * Fixed doxygen comment in is_partitioned algorithm. --- .../boost/algorithm/cxx11/is_partitioned.hpp | 2 +- .../boost/algorithm/is_partitioned_until.hpp | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 include/boost/algorithm/is_partitioned_until.hpp diff --git a/include/boost/algorithm/cxx11/is_partitioned.hpp b/include/boost/algorithm/cxx11/is_partitioned.hpp index cb6c71e..80ee577 100644 --- a/include/boost/algorithm/cxx11/is_partitioned.hpp +++ b/include/boost/algorithm/cxx11/is_partitioned.hpp @@ -39,7 +39,7 @@ bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p } /// \fn is_partitioned ( const Range &r, UnaryPredicate p ) -/// \brief Generates an increasing sequence of values, and stores them in the input Range. +/// \brief Tests to see if a sequence is partitioned according to a predicate /// /// \param r The input range /// \param p The predicate to test the values with diff --git a/include/boost/algorithm/is_partitioned_until.hpp b/include/boost/algorithm/is_partitioned_until.hpp new file mode 100644 index 0000000..e188927 --- /dev/null +++ b/include/boost/algorithm/is_partitioned_until.hpp @@ -0,0 +1,61 @@ +/* + Copyright (c) Alexander Zaitsev 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +*/ + +/// \file is_partitioned_until.hpp +/// \brief Tell if a sequence is partitioned +/// \author Alexander Zaitsev + +#ifndef BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP +#define BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP + +#include +#include + +namespace boost { namespace algorithm { + +/// \fn is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p ) +/// \brief Tests to see if a sequence is partitioned according to a predicate +/// +/// \param first The start of the input sequence +/// \param last One past the end of the input sequence +/// \param p The predicate to test the values with +/// +/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. +/// Returns last if the entire sequence is partitioned. +/// Complexity: O(N). +template +InputIterator is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p ) +{ +// Run through the part that satisfy the predicate + for ( ; first != last; ++first ) + if ( !p (*first)) + break; +// Now the part that does not satisfy the predicate + for ( ; first != last; ++first ) + if ( p (*first)) + return first; + return last; +} + +/// \fn is_partitioned_until ( const Range &r, UnaryPredicate p ) +/// \brief Tests to see if a sequence is partitioned according to a predicate +/// +/// \param r The input range +/// \param p The predicate to test the values with +/// +/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. +/// Returns last if the entire sequence is partitioned. +/// Complexity: O(N). +template +typename boost::range_iterator::type is_partitioned_until ( const Range &r, UnaryPredicate p ) +{ + return boost::algorithm::is_partitioned_until (boost::begin(r), boost::end(r), p); +} + +}} + +#endif // BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP From 383e800df9cf59b8cdcdb3c40a11d5981cf2b7ba Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Tue, 14 Feb 2017 15:59:07 +0300 Subject: [PATCH 3/5] Added examples, tests, doc --- doc/algorithm.qbk | 1 + doc/is_partitioned_until.qbk | 67 ++++++++++++++++++ example/Jamfile.v2 | 1 + example/is_partitioned_until_example.cpp | 70 +++++++++++++++++++ .../boost/algorithm/is_partitioned_until.hpp | 4 +- test/Jamfile.v2 | 3 + test/is_partitioned_until_test.cpp | 63 +++++++++++++++++ 7 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 doc/is_partitioned_until.qbk create mode 100644 example/is_partitioned_until_example.cpp create mode 100644 test/is_partitioned_until_test.cpp diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index 1568fb5..becad46 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -67,6 +67,7 @@ Thanks to all the people who have reviewed this library and made suggestions for [include gather.qbk] [include hex.qbk] [include is_palindrome.qbk] +[include is_partitioned_until.qbk] [endsect] diff --git a/doc/is_partitioned_until.qbk b/doc/is_partitioned_until.qbk new file mode 100644 index 0000000..72e2afc --- /dev/null +++ b/doc/is_partitioned_until.qbk @@ -0,0 +1,67 @@ +[/ File is_partitioned_until.qbk] + +[section:is_partitioned_until is_partitioned_until ] + +[/license +Copyright (c) 2017 Alexander Zaitsev + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +] + +The header file 'is_partitioned_until.hpp' contains two variants of a single algorithm, `is_partitioned_until`. The algorithm tests to see if a sequence is partitioned according to a predicate; in other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. + +The routine `is_partitioned_until` takes a sequence and a predicate. It returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. Returns last if the entire sequence is partitioned. + +`is_partitioned_until` come in two forms; the first one takes two iterators to define the range. The second form takes a single range parameter, and uses Boost.Range to traverse it. + + +[heading interface] + +The function `is_partitioned_until` returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. Returns last if the entire sequence is partitioned. There are two versions; one takes two iterators, and the other takes a range. + +`` +template + InputIterator is_partitioned_until ( InputIterator first, InputIterator last, Predicate p ); +template + typename boost::range_iterator::type is_partitioned_until ( const Range &r, Predicate p ); +`` + +[heading Examples] + +Given the container `c` containing `{ 0, 1, 2, 3, 14, 15 }`, then +`` +bool isOdd ( int i ) { return i % 2 == 1; } +bool lessThan10 ( int i ) { return i < 10; } + +is_partitioned_until ( c, isOdd ) --> iterator to '1' +is_partitioned_until ( c, lessThan10 ) --> end +is_partitioned_until ( c.begin (), c.end (), lessThan10 ) --> end +is_partitioned_until ( c.begin (), c.begin () + 3, lessThan10 ) --> end +is_partitioned_until ( c.end (), c.end (), isOdd ) --> end // empty range +`` + +[heading Iterator Requirements] + +`is_partitioned_until` works on all iterators except output iterators. + +[heading Complexity] + +Both of the variants of `is_partitioned_until` run in ['O(N)] (linear) time; that is, they compare against each element in the list once. If the sequence is found to be not partitioned at any point, the routine will terminate immediately, without examining the rest of the elements. + +[heading Exception Safety] + +Both of the variants of `is_partitioned_until` take their parameters by value 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_partitioned_until` returns iterator to the end for empty ranges, no matter what predicate is passed to test against. + +[endsect] + +[/ File is_partitioned_until.qbk +Copyright 2017 Alexander Zaitsev +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). +] + diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index ce067cf..4512a53 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -21,4 +21,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; +exe is_partitioned_until_example : is_partitioned_until_example.cpp; diff --git a/example/is_partitioned_until_example.cpp b/example/is_partitioned_until_example.cpp new file mode 100644 index 0000000..759176b --- /dev/null +++ b/example/is_partitioned_until_example.cpp @@ -0,0 +1,70 @@ +/* + Copyright (c) Alexander Zaitsev , 2017 + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include + +#include + + +namespace ba = boost::algorithm; + +bool isOdd(const int v1) +{ + return v1 % 2 != 0; +} + +struct isOddComp +{ + bool operator()(const int v1) const + { + return v1 % 2 != 0; + } +}; + + +int main ( int /*argc*/, char * /*argv*/ [] ) +{ + std::vector good({1, 2, 4}); + std::vector bad({1, 2, 3}); + + //Use custom function + auto it1 = ba::is_partitioned_until(good.begin(), good.end(), isOdd); + if(it1 == good.end()) + { + std::cout << "The sequence is partitioned\n"; + } + else + { + std::cout << "is_partitioned_until check failed here: " << *it1 << std::endl; + } + + //Use custom comparator + auto it2 = ba::is_partitioned_until(good.begin(), good.end(), isOddComp()); + if(it2 == good.end()) + { + std::cout << "The sequence is partitioned\n"; + } + else + { + std::cout << "is_partitioned_until check failed here: " << *it2 << std::endl; + } + + auto it3 = ba::is_partitioned_until(bad, isOdd); + if(it3 == bad.end()) + { + std::cout << "The sequence is partitioned\n"; + } + else + { + std::cout << "is_partitioned_until check failed here: " << *it3 << std::endl; + } + return 0; +} diff --git a/include/boost/algorithm/is_partitioned_until.hpp b/include/boost/algorithm/is_partitioned_until.hpp index e188927..99e8435 100644 --- a/include/boost/algorithm/is_partitioned_until.hpp +++ b/include/boost/algorithm/is_partitioned_until.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) Alexander Zaitsev 2017. + Copyright (c) Alexander Zaitsev , 2017. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -51,7 +51,7 @@ InputIterator is_partitioned_until ( InputIterator first, InputIterator last, Un /// Returns last if the entire sequence is partitioned. /// Complexity: O(N). template -typename boost::range_iterator::type is_partitioned_until ( const Range &r, UnaryPredicate p ) +typename boost::range_iterator::type is_partitioned_until ( const Range &r, UnaryPredicate p ) { return boost::algorithm::is_partitioned_until (boost::begin(r), boost::end(r), p); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fb00843..fad1578 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -70,6 +70,9 @@ alias unit_test_framework # Is_palindrome tests [ run is_palindrome_test.cpp unit_test_framework : : : : is_palindrome_test ] + +# Is_partitioned_until tests + [ run is_partitioned_until_test.cpp unit_test_framework : : : : is_partitioned_until_test ] ; } diff --git a/test/is_partitioned_until_test.cpp b/test/is_partitioned_until_test.cpp new file mode 100644 index 0000000..379c06e --- /dev/null +++ b/test/is_partitioned_until_test.cpp @@ -0,0 +1,63 @@ +/* + Copyright (c) Marshall Clow 2011-2012, Alexander Zaitsev , 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + For more information, see http://www.boost.org +*/ + +#include + +#include +#include + +#define BOOST_TEST_MAIN +#include + +#include +#include +#include + +namespace ba = boost::algorithm; +// namespace ba = boost; + +template +struct less_than { +public: + less_than ( T foo ) : val ( foo ) {} + less_than ( const less_than &rhs ) : val ( rhs.val ) {} + + bool operator () ( const T &v ) const { return v < val; } +private: + less_than (); + less_than operator = ( const less_than &rhs ); + T val; +}; + + +void test_sequence1 () { + std::vector v; + + v.clear (); + for ( int i = 5; i < 15; ++i ) + v.push_back ( i ); + BOOST_CHECK ( ba::is_partitioned_until ( v, less_than(3)) == v.end()); // no elements + BOOST_CHECK ( ba::is_partitioned_until ( v, less_than(6)) == v.end()); // only the first element + BOOST_CHECK ( ba::is_partitioned_until ( v, less_than(10)) == v.end()); // in the middle somewhere + BOOST_CHECK ( ba::is_partitioned_until ( v, less_than(99)) == v.end()); // all elements satisfy +// With bidirectional iterators. + std::list l; + for ( int i = 5; i < 15; ++i ) + l.push_back ( i ); + BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than(3)) == l.end()); // no elements + BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than(6)) == l.end()); // only the first element + BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than(10)) == l.end()); // in the middle somewhere + BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than(99)) == l.end()); // all elements satisfy +} + + +BOOST_AUTO_TEST_CASE( test_main ) +{ + test_sequence1 (); +} From a446ef0758017ab090630f562bd32e2c21c57941 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 15 Feb 2017 00:11:10 +0300 Subject: [PATCH 4/5] Cleaned README --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 92a9140..8b13789 100644 --- a/README.md +++ b/README.md @@ -1,4 +1 @@ - - Coverity Scan Build Status - + From 6f341453904a46e9cb70256d815307aaa73d4aa5 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Wed, 22 Feb 2017 01:25:38 +0300 Subject: [PATCH 5/5] Removed empty README.md, fixed docs --- README.md | 4 ---- doc/is_partitioned.qbk | 2 +- doc/is_partitioned_until.qbk | 6 +++--- include/boost/algorithm/cxx11/is_partitioned.hpp | 6 ++++-- include/boost/algorithm/is_partitioned_until.hpp | 6 ++++-- 5 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 92a9140..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ - - Coverity Scan Build Status - diff --git a/doc/is_partitioned.qbk b/doc/is_partitioned.qbk index 7a6c458..0ed1f80 100644 --- a/doc/is_partitioned.qbk +++ b/doc/is_partitioned.qbk @@ -57,7 +57,7 @@ Both of the variants of `is_partitioned` take their parameters by value or const * 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. +* `is_partitioned` returns true for empty and single-element ranges, no matter what predicate is passed to test against. [endsect] diff --git a/doc/is_partitioned_until.qbk b/doc/is_partitioned_until.qbk index 72e2afc..9e0879b 100644 --- a/doc/is_partitioned_until.qbk +++ b/doc/is_partitioned_until.qbk @@ -11,14 +11,14 @@ Distributed under the Boost Software License, Version 1.0. The header file 'is_partitioned_until.hpp' contains two variants of a single algorithm, `is_partitioned_until`. The algorithm tests to see if a sequence is partitioned according to a predicate; in other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. -The routine `is_partitioned_until` takes a sequence and a predicate. It returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. Returns last if the entire sequence is partitioned. +The routine `is_partitioned_until` takes a sequence and a predicate. It returns the last iterator 'it' in the sequence [begin, end) for which the is_partitioned(begin, it) is true. `is_partitioned_until` come in two forms; the first one takes two iterators to define the range. The second form takes a single range parameter, and uses Boost.Range to traverse it. [heading interface] -The function `is_partitioned_until` returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. Returns last if the entire sequence is partitioned. There are two versions; one takes two iterators, and the other takes a range. +The function `is_partitioned_until` returns the last iterator 'it' in the sequence [begin, end) for which the is_partitioned(begin, it) is true. There are two versions; one takes two iterators, and the other takes a range. `` template @@ -55,7 +55,7 @@ Both of the variants of `is_partitioned_until` take their parameters by value or [heading Notes] -* `is_partitioned_until` returns iterator to the end for empty ranges, no matter what predicate is passed to test against. +* `is_partitioned_until` returns iterator to the end for empty and single-element ranges, no matter what predicate is passed to test against. [endsect] diff --git a/include/boost/algorithm/cxx11/is_partitioned.hpp b/include/boost/algorithm/cxx11/is_partitioned.hpp index 80ee577..c0076b9 100644 --- a/include/boost/algorithm/cxx11/is_partitioned.hpp +++ b/include/boost/algorithm/cxx11/is_partitioned.hpp @@ -18,7 +18,8 @@ namespace boost { namespace algorithm { /// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p ) -/// \brief Tests to see if a sequence is partitioned according to a predicate +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. /// /// \param first The start of the input sequence /// \param last One past the end of the input sequence @@ -39,7 +40,8 @@ bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p } /// \fn is_partitioned ( const Range &r, UnaryPredicate p ) -/// \brief Tests to see if a sequence is partitioned according to a predicate +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. /// /// \param r The input range /// \param p The predicate to test the values with diff --git a/include/boost/algorithm/is_partitioned_until.hpp b/include/boost/algorithm/is_partitioned_until.hpp index 99e8435..42683e1 100644 --- a/include/boost/algorithm/is_partitioned_until.hpp +++ b/include/boost/algorithm/is_partitioned_until.hpp @@ -18,7 +18,8 @@ namespace boost { namespace algorithm { /// \fn is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p ) -/// \brief Tests to see if a sequence is partitioned according to a predicate +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. /// /// \param first The start of the input sequence /// \param last One past the end of the input sequence @@ -42,7 +43,8 @@ InputIterator is_partitioned_until ( InputIterator first, InputIterator last, Un } /// \fn is_partitioned_until ( const Range &r, UnaryPredicate p ) -/// \brief Tests to see if a sequence is partitioned according to a predicate +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. /// /// \param r The input range /// \param p The predicate to test the values with