From 383e800df9cf59b8cdcdb3c40a11d5981cf2b7ba Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Tue, 14 Feb 2017 15:59:07 +0300 Subject: [PATCH] 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 (); +}