mirror of
https://github.com/boostorg/algorithm.git
synced 2025-06-25 20:11:50 +02:00
Compare commits
29 Commits
boost-1.62
...
boost-1.65
Author | SHA1 | Date | |
---|---|---|---|
daef6d41c5 | |||
f14719c3a9 | |||
6bd8bc197a | |||
334737eebe | |||
055075aa61 | |||
d6b7f3da90 | |||
0e62dfb92e | |||
f250014931 | |||
56d88410c6 | |||
5d76dab9b8 | |||
6f34145390 | |||
a446ef0758 | |||
383e800df9 | |||
a838feb81a | |||
17d4f70e97 | |||
d22c60c2d4 | |||
037fe4e33d | |||
25d54bd1e8 | |||
e442420d49 | |||
42db8a4403 | |||
9b19fc00c2 | |||
7977bd0cdc | |||
efd7a8b544 | |||
8dfebc4580 | |||
6a650ade1d | |||
303ff13b86 | |||
d029402f05 | |||
eccac19108 | |||
8627d02f20 |
@ -16,17 +16,17 @@ using quickbook ;
|
||||
using doxygen ;
|
||||
using boostbook ;
|
||||
|
||||
doxygen autodoc
|
||||
:
|
||||
[ glob ../../../boost/algorithm/*.hpp
|
||||
doxygen autodoc
|
||||
:
|
||||
[ glob ../../../boost/algorithm/*.hpp
|
||||
../../../boost/algorithm/searching/*.hpp
|
||||
../../../boost/algorithm/cxx11/*.hpp
|
||||
../../../boost/algorithm/cxx14/*.hpp
|
||||
]
|
||||
:
|
||||
:
|
||||
<doxygen:param>"PREDEFINED=\"BOOST_ALGORITHM_DOXYGEN=1\""
|
||||
<doxygen:param>WARNINGS=YES # Default NO, but useful to see warnings, especially in a logfile.
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
xml algorithm : algorithm.qbk ;
|
||||
@ -35,7 +35,7 @@ boostbook standalone
|
||||
:
|
||||
algorithm
|
||||
:
|
||||
<dependency>autodoc
|
||||
<dependency>autodoc
|
||||
<xsl:param>boost.root=../../../..
|
||||
<xsl:param>"boost.doxygen.reftitle=Boost.Algorithms C++ Reference"
|
||||
<xsl:param>chapter.autolabel=0
|
||||
@ -44,3 +44,13 @@ boostbook standalone
|
||||
<xsl:param>toc.max.depth=2
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc
|
||||
: ../string/doc/string_algo.xml
|
||||
:
|
||||
: <dependency>../string/doc//autodoc
|
||||
: ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : standalone ;
|
||||
explicit boostrelease ;
|
||||
|
@ -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]
|
||||
|
||||
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
~boyer_moore ();
|
||||
|
||||
template <typename corpusIter>
|
||||
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last );
|
||||
pair<corpusIter, corpusIter> operator () ( corpusIter corpus_first, corpusIter corpus_last );
|
||||
};
|
||||
``
|
||||
|
||||
@ -45,14 +45,28 @@ and here is the corresponding procedural interface:
|
||||
|
||||
``
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter boyer_moore_search (
|
||||
pair<corpusIter, corpusIter> 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]
|
||||
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
~boyer_moore_horspool ();
|
||||
|
||||
template <typename corpusIter>
|
||||
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last );
|
||||
pair<corpusIter, corpusIter> operator () ( corpusIter corpus_first, corpusIter corpus_last );
|
||||
};
|
||||
``
|
||||
|
||||
@ -43,14 +43,28 @@ and here is the corresponding procedural interface:
|
||||
|
||||
``
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter boyer_moore_horspool_search (
|
||||
pair<corpusIter, corpusIter> 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]
|
||||
|
||||
|
@ -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]
|
||||
|
||||
|
67
doc/is_partitioned_until.qbk
Normal file
67
doc/is_partitioned_until.qbk
Normal file
@ -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 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 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<typename InputIterator, typename Predicate>
|
||||
InputIterator is_partitioned_until ( InputIterator first, InputIterator last, Predicate p );
|
||||
template<typename Range, typename Predicate>
|
||||
typename boost::range_iterator<const Range>::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 and single-element 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).
|
||||
]
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
~knuth_morris_pratt ();
|
||||
|
||||
template <typename corpusIter>
|
||||
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last );
|
||||
pair<corpusIter, corpusIter> operator () ( corpusIter corpus_first, corpusIter corpus_last );
|
||||
};
|
||||
``
|
||||
|
||||
@ -47,15 +47,28 @@ and here is the corresponding procedural interface:
|
||||
|
||||
``
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter knuth_morris_pratt_search (
|
||||
pair<corpusIter, corpusIter> 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.
|
||||
|
@ -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;
|
||||
|
||||
|
70
example/is_partitioned_until_example.cpp
Normal file
70
example/is_partitioned_until_example.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.by>, 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 <vector>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/algorithm/is_partitioned_until.hpp>
|
||||
|
||||
|
||||
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<int> good({1, 2, 4});
|
||||
std::vector<int> 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;
|
||||
}
|
@ -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 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.
|
||||
/// 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
|
||||
|
@ -13,7 +13,6 @@
|
||||
#define BOOST_ALGORITHM_EQUAL_HPP
|
||||
|
||||
#include <algorithm> // for std::equal
|
||||
#include <functional> // for std::binary_function
|
||||
#include <iterator>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
@ -21,7 +20,7 @@ namespace boost { namespace algorithm {
|
||||
namespace detail {
|
||||
|
||||
template <class T1, class T2>
|
||||
struct eq : public std::binary_function<T1, T2, bool> {
|
||||
struct eq {
|
||||
bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;}
|
||||
};
|
||||
|
||||
|
52
include/boost/algorithm/cxx17/exclusive_scan.hpp
Normal file
52
include/boost/algorithm/cxx17/exclusive_scan.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2017.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
|
||||
*/
|
||||
|
||||
/// \file exclusive_scan.hpp
|
||||
/// \brief ???
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
|
||||
#define BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
|
||||
|
||||
#include <functional> // for std::plus
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
|
||||
OutputIterator exclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result, T init, BinaryOperation bOp)
|
||||
{
|
||||
if (first != last)
|
||||
{
|
||||
T saved = init;
|
||||
do
|
||||
{
|
||||
init = bOp(init, *first);
|
||||
*result = saved;
|
||||
saved = init;
|
||||
++result;
|
||||
} while (++first != last);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class InputIterator, class OutputIterator, class T>
|
||||
OutputIterator exclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result, T init)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type VT;
|
||||
return exclusive_scan(first, last, result, init, std::plus<VT>());
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
|
37
include/boost/algorithm/cxx17/for_each_n.hpp
Normal file
37
include/boost/algorithm/cxx17/for_each_n.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2017.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
|
||||
*/
|
||||
|
||||
/// \file for_each_n.hpp
|
||||
/// \brief Apply a functor to the elements of a sequence
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_FOR_EACH_N_HPP
|
||||
#define BOOST_ALGORITHM_FOR_EACH_N_HPP
|
||||
|
||||
#include <utility> // for std::pair
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/// \fn for_each_n(InputIterator first, Size n, Function f);
|
||||
/// \return first + n
|
||||
///
|
||||
/// \param first The start of the first range.
|
||||
/// \param n One past the end of the first range.
|
||||
/// \param f A functor to apply to the elements of the sequence
|
||||
/// \note If f returns a result, the result is ignored.
|
||||
template<class InputIterator, class Size, class Function>
|
||||
InputIterator for_each_n(InputIterator first, Size n, Function f)
|
||||
{
|
||||
for ( ; n > 0; --n, ++first )
|
||||
f(*first);
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_FOR_EACH_N_HPP
|
60
include/boost/algorithm/cxx17/inclusive_scan.hpp
Normal file
60
include/boost/algorithm/cxx17/inclusive_scan.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2017.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
|
||||
*/
|
||||
|
||||
/// \file transform_reduce.hpp
|
||||
/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
||||
#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
||||
|
||||
#include <functional> // for std::plus
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
|
||||
OutputIterator inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result, BinaryOperation bOp, T init)
|
||||
{
|
||||
for (; first != last; ++first, (void) ++result) {
|
||||
init = bOp(init, *first);
|
||||
*result = init;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<class InputIterator, class OutputIterator, class BinaryOperation>
|
||||
OutputIterator inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result, BinaryOperation bOp)
|
||||
{
|
||||
if (first != last) {
|
||||
typename std::iterator_traits<InputIterator>::value_type init = *first;
|
||||
*result++ = init;
|
||||
if (++first != last)
|
||||
return inclusive_scan(first, last, result, bOp, init);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class InputIterator, class OutputIterator>
|
||||
OutputIterator inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type VT;
|
||||
return inclusive_scan(first, last, result, std::plus<VT>());
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
72
include/boost/algorithm/cxx17/reduce.hpp
Normal file
72
include/boost/algorithm/cxx17/reduce.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2017.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
|
||||
*/
|
||||
|
||||
/// \file reduce.hpp
|
||||
/// \brief Combine the elements of a sequence into a single value
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_REDUCE_HPP
|
||||
#define BOOST_ALGORITHM_REDUCE_HPP
|
||||
|
||||
#include <functional> // for std::plus
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
template<class InputIterator, class T, class BinaryOperation>
|
||||
T reduce(InputIterator first, InputIterator last, T init, BinaryOperation bOp)
|
||||
{
|
||||
;
|
||||
for (; first != last; ++first)
|
||||
init = bOp(init, *first);
|
||||
return init;
|
||||
}
|
||||
|
||||
template<class InputIterator, class T>
|
||||
T reduce(InputIterator first, InputIterator last, T init)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type VT;
|
||||
return reduce(first, last, init, std::plus<VT>());
|
||||
}
|
||||
|
||||
template<class InputIterator>
|
||||
typename std::iterator_traits<InputIterator>::value_type
|
||||
reduce(InputIterator first, InputIterator last)
|
||||
{
|
||||
return reduce(first, last,
|
||||
typename std::iterator_traits<InputIterator>::value_type());
|
||||
}
|
||||
|
||||
template<class Range>
|
||||
typename boost::range_value<Range>::type
|
||||
reduce(const Range &r)
|
||||
{
|
||||
return reduce(boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
// Not sure that this won't be ambiguous (1)
|
||||
template<class Range, class T>
|
||||
T reduce(const Range &r, T init)
|
||||
{
|
||||
return reduce(boost::begin (r), boost::end (r), init);
|
||||
}
|
||||
|
||||
|
||||
// Not sure that this won't be ambiguous (2)
|
||||
template<class Range, class T, class BinaryOperation>
|
||||
T reduce(const Range &r, T init, BinaryOperation bOp)
|
||||
{
|
||||
return reduce(boost::begin(r), boost::end(r), init, bOp);
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_REDUCE_HPP
|
46
include/boost/algorithm/cxx17/transform_exclusive_scan.hpp
Normal file
46
include/boost/algorithm/cxx17/transform_exclusive_scan.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2017.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
|
||||
*/
|
||||
|
||||
/// \file transform_exclusive_scan.hpp
|
||||
/// \brief ????
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
|
||||
#define BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
|
||||
|
||||
#include <functional> // for std::plus
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
template<class InputIterator, class OutputIterator, class T,
|
||||
class BinaryOperation, class UnaryOperation>
|
||||
OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result, T init,
|
||||
BinaryOperation bOp, UnaryOperation uOp)
|
||||
{
|
||||
if (first != last)
|
||||
{
|
||||
T saved = init;
|
||||
do
|
||||
{
|
||||
init = bOp(init, uOp(*first));
|
||||
*result = saved;
|
||||
saved = init;
|
||||
++result;
|
||||
} while (++first != last);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
|
58
include/boost/algorithm/cxx17/transform_inclusive_scan.hpp
Normal file
58
include/boost/algorithm/cxx17/transform_inclusive_scan.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2017.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
|
||||
*/
|
||||
|
||||
/// \file transform_reduce.hpp
|
||||
/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
||||
#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
||||
|
||||
#include <functional> // for std::plus
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
template<class InputIterator, class OutputIterator,
|
||||
class BinaryOperation, class UnaryOperation, class T>
|
||||
OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result,
|
||||
BinaryOperation bOp, UnaryOperation uOp,
|
||||
T init)
|
||||
{
|
||||
for (; first != last; ++first, (void) ++result) {
|
||||
init = bOp(init, uOp(*first));
|
||||
*result = init;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class InputIterator, class OutputIterator,
|
||||
class BinaryOperation, class UnaryOperation>
|
||||
OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result,
|
||||
BinaryOperation bOp, UnaryOperation uOp)
|
||||
{
|
||||
if (first != last) {
|
||||
typename std::iterator_traits<InputIterator>::value_type init = uOp(*first);
|
||||
*result++ = init;
|
||||
if (++first != last)
|
||||
return transform_inclusive_scan(first, last, result, bOp, uOp, init);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
55
include/boost/algorithm/cxx17/transform_reduce.hpp
Normal file
55
include/boost/algorithm/cxx17/transform_reduce.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2017.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
|
||||
*/
|
||||
|
||||
/// \file transform_reduce.hpp
|
||||
/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
||||
#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
||||
|
||||
#include <functional> // for std::plus
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
template<class InputIterator1, class InputIterator2, class T,
|
||||
class BinaryOperation1, class BinaryOperation2>
|
||||
T transform_reduce(InputIterator1 first1, InputIterator1 last1,
|
||||
InputIterator2 first2, T init,
|
||||
BinaryOperation1 bOp1, BinaryOperation2 bOp2)
|
||||
{
|
||||
for (; first1 != last1; ++first1, (void) ++first2)
|
||||
init = bOp1(init, bOp2(*first1, *first2));
|
||||
return init;
|
||||
}
|
||||
|
||||
template<class InputIterator, class T,
|
||||
class BinaryOperation, class UnaryOperation>
|
||||
T transform_reduce(InputIterator first, InputIterator last,
|
||||
T init, BinaryOperation bOp, UnaryOperation uOp)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
init = bOp(init, uOp(*first));
|
||||
return init;
|
||||
}
|
||||
|
||||
template<class InputIterator1, class InputIterator2, class T>
|
||||
T transform_reduce(InputIterator1 first1, InputIterator1 last1,
|
||||
InputIterator2 first2, T init)
|
||||
{
|
||||
return transform_reduce(first1, last1, first2, init,
|
||||
std::plus<T>(), std::multiplies<T>());
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
|
@ -73,7 +73,7 @@ namespace detail {
|
||||
else if ( c >= 'A' && c <= 'F' ) retval = c - 'A' + 10;
|
||||
else if ( c >= 'a' && c <= 'f' ) retval = c - 'a' + 10;
|
||||
else BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c));
|
||||
return retval;
|
||||
return static_cast<char>(retval);
|
||||
}
|
||||
|
||||
// My own iterator_traits class.
|
||||
|
@ -35,7 +35,7 @@ namespace boost { namespace algorithm {
|
||||
/// For other sequences function will return false.
|
||||
/// Complexity: O(N).
|
||||
template <typename BidirectionalIterator, typename Predicate>
|
||||
bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p )
|
||||
bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p)
|
||||
{
|
||||
if(begin == end)
|
||||
{
|
||||
@ -63,7 +63,7 @@ bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predi
|
||||
/// \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 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.
|
||||
@ -71,26 +71,8 @@ bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predi
|
||||
template <typename BidirectionalIterator>
|
||||
bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end)
|
||||
{
|
||||
if(begin == end)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
--end;
|
||||
while(begin != end)
|
||||
{
|
||||
if(!(*begin == *end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
++begin;
|
||||
if(begin == end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
--end;
|
||||
}
|
||||
return true;
|
||||
return is_palindrome(begin, end,
|
||||
std::equal_to<typename std::iterator_traits<BidirectionalIterator>::value_type> ());
|
||||
}
|
||||
|
||||
/// \fn is_palindrome ( const R& range )
|
||||
@ -122,7 +104,6 @@ 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
|
||||
///
|
||||
@ -138,7 +119,6 @@ bool is_palindrome(const char* str)
|
||||
return is_palindrome(str, str + strlen(str));
|
||||
}
|
||||
|
||||
|
||||
/// \fn is_palindrome ( const char* str, Predicate p )
|
||||
/// \return true if the entire sequence is palindrome
|
||||
///
|
||||
@ -155,7 +135,6 @@ bool is_palindrome(const char* str, Predicate p)
|
||||
return true;
|
||||
return is_palindrome(str, str + strlen(str), p);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_IS_PALINDROME_HPP
|
||||
|
63
include/boost/algorithm/is_partitioned_until.hpp
Normal file
63
include/boost/algorithm/is_partitioned_until.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.by>, 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 <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
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.
|
||||
/// 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
|
||||
/// \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 InputIterator, typename UnaryPredicate>
|
||||
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.
|
||||
/// 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
|
||||
///
|
||||
/// \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 Range, typename UnaryPredicate>
|
||||
typename boost::range_iterator<const Range>::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
|
@ -152,8 +152,8 @@ Requirements:
|
||||
|
||||
|
||||
template<typename Iter, typename Container>
|
||||
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 );
|
||||
|
||||
@ -161,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<typename std::iterator_traits<patIter>::value_type> reversed(count);
|
||||
(void) std::reverse_copy ( pat_first, pat_last, reversed.begin ());
|
||||
(void) std::reverse_copy ( first, last, reversed.begin ());
|
||||
|
||||
std::vector<difference_type> prefix (count);
|
||||
compute_bm_prefix ( pat_first, pat_last, prefix );
|
||||
compute_bm_prefix ( first, last, prefix );
|
||||
|
||||
std::vector<difference_type> prefix_reversed (count);
|
||||
compute_bm_prefix ( reversed.begin (), reversed.end (), prefix_reversed );
|
||||
|
@ -155,9 +155,9 @@ namespace boost { namespace algorithm {
|
||||
|
||||
|
||||
void preKmp ( patIter first, patIter last ) {
|
||||
const /*std::size_t*/ int count = std::distance ( first, last );
|
||||
const difference_type count = std::distance ( first, last );
|
||||
|
||||
int i, j;
|
||||
difference_type i, j;
|
||||
|
||||
i = 0;
|
||||
j = skip_[0] = -1;
|
||||
@ -177,7 +177,7 @@ namespace boost { namespace algorithm {
|
||||
void init_skip_table ( patIter first, patIter last ) {
|
||||
const difference_type count = std::distance ( first, last );
|
||||
|
||||
int j;
|
||||
difference_type j;
|
||||
skip_ [ 0 ] = -1;
|
||||
for ( int i = 1; i <= count; ++i ) {
|
||||
j = skip_ [ i - 1 ];
|
||||
|
@ -30,8 +30,10 @@ namespace boost {
|
||||
|
||||
// a tolower functor
|
||||
template<typename CharT>
|
||||
struct to_lowerF : public std::unary_function<CharT, CharT>
|
||||
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<typename CharT>
|
||||
struct to_upperF : public std::unary_function<CharT, CharT>
|
||||
struct to_upperF
|
||||
{
|
||||
typedef CharT argument_type;
|
||||
typedef CharT result_type;
|
||||
// Constructor
|
||||
to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {}
|
||||
|
||||
|
@ -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) {}
|
||||
|
@ -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<IteratorT>, SeqT >
|
||||
struct copy_iterator_rangeF
|
||||
{
|
||||
typedef iterator_range<IteratorT> argument_type;
|
||||
typedef SeqT result_type;
|
||||
SeqT operator()( const iterator_range<IteratorT>& Range ) const
|
||||
{
|
||||
return copy_range<SeqT>(Range);
|
||||
|
@ -12,7 +12,7 @@ import testing ;
|
||||
alias unit_test_framework
|
||||
: # sources
|
||||
/boost//unit_test_framework
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
{
|
||||
@ -31,13 +31,13 @@ alias unit_test_framework
|
||||
[ run clamp_test.cpp unit_test_framework : : : : clamp_test ]
|
||||
[ run power_test.cpp unit_test_framework : : : : power_test ]
|
||||
[ compile-fail power_fail1.cpp : : : : ]
|
||||
|
||||
|
||||
# Cxx11 tests
|
||||
[ run all_of_test.cpp unit_test_framework : : : : all_of_test ]
|
||||
[ run any_of_test.cpp unit_test_framework : : : : any_of_test ]
|
||||
[ run none_of_test.cpp unit_test_framework : : : : none_of_test ]
|
||||
[ run one_of_test.cpp unit_test_framework : : : : one_of_test ]
|
||||
|
||||
|
||||
[ run ordered_test.cpp unit_test_framework : : : : ordered_test ]
|
||||
[ run find_if_not_test1.cpp unit_test_framework : : : : find_if_not_test1 ]
|
||||
[ run copy_if_test1.cpp unit_test_framework : : : : copy_if_test1 ]
|
||||
@ -53,6 +53,16 @@ alias unit_test_framework
|
||||
[ run equal_test.cpp unit_test_framework : : : : equal_test ]
|
||||
[ run mismatch_test.cpp unit_test_framework : : : : mismatch_test ]
|
||||
|
||||
# Cxx17 tests
|
||||
[ run for_each_n_test.cpp unit_test_framework : : : : for_each_n_test ]
|
||||
[ run reduce_test.cpp unit_test_framework : : : : reduce_test ]
|
||||
[ run transform_reduce_test.cpp unit_test_framework : : : : transform_reduce_test ]
|
||||
[ run inclusive_scan_test.cpp unit_test_framework : : : : inclusive_scan_test ]
|
||||
[ run exclusive_scan_test.cpp unit_test_framework : : : : exclusive_scan_test ]
|
||||
[ run transform_inclusive_scan_test.cpp unit_test_framework : : : : transform_inclusive_scan_test ]
|
||||
[ run transform_exclusive_scan_test.cpp unit_test_framework : : : : transform_exclusive_scan_test ]
|
||||
# Maybe GCD and LCM as well
|
||||
|
||||
# Hex tests
|
||||
[ run hex_test1.cpp unit_test_framework : : : : hex_test1 ]
|
||||
[ run hex_test2.cpp unit_test_framework : : : : hex_test2 ]
|
||||
@ -70,6 +80,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 ]
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <list>
|
||||
|
||||
template<typename T>
|
||||
struct is_ : public std::unary_function<T, bool> {
|
||||
struct is_ {
|
||||
is_ ( T v ) : val_ ( v ) {}
|
||||
~is_ () {}
|
||||
bool operator () ( T comp ) const { return val_ == comp; }
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <list>
|
||||
|
||||
template<typename T>
|
||||
struct is_ : public std::unary_function<T, bool> {
|
||||
struct is_ {
|
||||
is_ ( T v ) : val_ ( v ) {}
|
||||
~is_ () {}
|
||||
bool operator () ( T comp ) const { return val_ == comp; }
|
||||
|
72
test/exclusive_scan_test.cpp
Normal file
72
test/exclusive_scan_test.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 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 <vector>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/cxx11/iota.hpp>
|
||||
#include <boost/algorithm/cxx17/exclusive_scan.hpp>
|
||||
|
||||
#include "iterator_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
int triangle(int n) { return n*(n+1)/2; }
|
||||
|
||||
void basic_tests_init()
|
||||
{
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
std::fill(v.begin(), v.end(), 3);
|
||||
ba::exclusive_scan(v.begin(), v.end(), v.begin(), 50);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 50 + (int) i * 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 0);
|
||||
ba::exclusive_scan(v.begin(), v.end(), v.begin(), 30);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 30 + triangle(i-1));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 1);
|
||||
ba::exclusive_scan(v.begin(), v.end(), v.begin(), 40);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 40 + triangle(i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_exclusive_scan_init()
|
||||
{
|
||||
basic_tests_init();
|
||||
}
|
||||
|
||||
void test_exclusive_scan_init_op()
|
||||
{
|
||||
BOOST_CHECK(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_exclusive_scan_init();
|
||||
test_exclusive_scan_init_op();
|
||||
}
|
66
test/for_each_n_test.cpp
Normal file
66
test/for_each_n_test.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2013.
|
||||
|
||||
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 <boost/config.hpp>
|
||||
#include <boost/algorithm/cxx17/for_each_n.hpp>
|
||||
|
||||
#include "iterator_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
struct for_each_test
|
||||
{
|
||||
for_each_test() {}
|
||||
static int count;
|
||||
void operator()(int& i) {++i; ++count;}
|
||||
};
|
||||
|
||||
int for_each_test::count = 0;
|
||||
|
||||
void test_for_each_n ()
|
||||
{
|
||||
typedef input_iterator<int*> Iter;
|
||||
int ia[] = {0, 1, 2, 3, 4, 5};
|
||||
const unsigned s = sizeof(ia)/sizeof(ia[0]);
|
||||
|
||||
{
|
||||
for_each_test::count = 0;
|
||||
Iter it = ba::for_each_n(Iter(ia), 0, for_each_test());
|
||||
BOOST_CHECK(it == Iter(ia));
|
||||
BOOST_CHECK(for_each_test::count == 0);
|
||||
}
|
||||
|
||||
{
|
||||
for_each_test::count = 0;
|
||||
Iter it = ba::for_each_n(Iter(ia), s, for_each_test());
|
||||
|
||||
BOOST_CHECK(it == Iter(ia+s));
|
||||
BOOST_CHECK(for_each_test::count == s);
|
||||
for (unsigned i = 0; i < s; ++i)
|
||||
BOOST_CHECK(ia[i] == static_cast<int>(i+1));
|
||||
}
|
||||
|
||||
{
|
||||
for_each_test::count = 0;
|
||||
Iter it = ba::for_each_n(Iter(ia), 1, for_each_test());
|
||||
|
||||
BOOST_CHECK(it == Iter(ia+1));
|
||||
BOOST_CHECK(for_each_test::count == 1);
|
||||
for (unsigned i = 0; i < 1; ++i)
|
||||
BOOST_CHECK(ia[i] == static_cast<int>(i+2));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_for_each_n ();
|
||||
}
|
153
test/inclusive_scan_test.cpp
Normal file
153
test/inclusive_scan_test.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 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 <vector>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/cxx11/iota.hpp>
|
||||
#include <boost/algorithm/cxx17/inclusive_scan.hpp>
|
||||
|
||||
#include "iterator_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
int triangle(int n) { return n*(n+1)/2; }
|
||||
|
||||
void basic_tests_op()
|
||||
{
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
std::fill(v.begin(), v.end(), 3);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
assert(v[i] == (int)(i+1) * 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 0);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
assert(v[i] == triangle(i));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 1);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
assert(v[i] == triangle(i + 1));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v, res;
|
||||
ba::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<int>());
|
||||
assert(res.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void test_inclusive_scan_op()
|
||||
{
|
||||
basic_tests_op();
|
||||
BOOST_CHECK(true);
|
||||
}
|
||||
|
||||
void basic_tests_init()
|
||||
{
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
std::fill(v.begin(), v.end(), 3);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), 50);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
assert(v[i] == 50 + (int)(i+1) * 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 0);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), 40);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
assert(v[i] == 40 + triangle(i));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 1);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), 30);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
assert(v[i] == 30 + triangle(i + 1));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v, res;
|
||||
ba::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<int>(), 40);
|
||||
assert(res.empty());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_inclusive_scan_init()
|
||||
{
|
||||
basic_tests_init();
|
||||
BOOST_CHECK(true);
|
||||
}
|
||||
|
||||
void basic_tests_op_init()
|
||||
{
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
std::fill(v.begin(), v.end(), 3);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), 50);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 50 + (int)(i+1) * 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 0);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), 40);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 40 + triangle(i));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 1);
|
||||
ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), 30);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 30 + triangle(i + 1));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v, res;
|
||||
ba::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<int>(), 40);
|
||||
BOOST_CHECK(res.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void test_inclusive_scan_op_init()
|
||||
{
|
||||
basic_tests_op_init();
|
||||
BOOST_CHECK(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_inclusive_scan_op();
|
||||
test_inclusive_scan_init();
|
||||
test_inclusive_scan_op_init();
|
||||
}
|
@ -38,9 +38,6 @@ struct functorComparator
|
||||
}
|
||||
};
|
||||
|
||||
#define Begin(arr) (arr)
|
||||
#define End(arr) (arr+(sizeof(arr)/(sizeof(arr[0]))))
|
||||
|
||||
void test_is_palindrome()
|
||||
{
|
||||
const std::list<int> empty;
|
||||
@ -54,14 +51,14 @@ void test_is_palindrome()
|
||||
// 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)));
|
||||
BOOST_CHECK (!ba::is_palindrome(boost::begin(oddNonPalindrome), boost::end(oddNonPalindrome)));
|
||||
BOOST_CHECK ( ba::is_palindrome(boost::begin(oddPalindrome), boost::end(oddPalindrome)));
|
||||
BOOST_CHECK ( ba::is_palindrome(boost::begin(evenPalindrome), boost::end(evenPalindrome)));
|
||||
BOOST_CHECK (!ba::is_palindrome(boost::begin(evenNonPalindrome), boost::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<int>));
|
||||
BOOST_CHECK (!ba::is_palindrome(boost::begin(oddNonPalindrome), boost::end(oddNonPalindrome), funcComparator<int>));
|
||||
BOOST_CHECK ( ba::is_palindrome(evenPalindrome, std::equal_to<int>()));
|
||||
|
||||
//Test C-strings like cases
|
||||
|
63
test/is_partitioned_until_test.cpp
Normal file
63
test/is_partitioned_until_test.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012, Alexander Zaitsev <zamazan4ik@gmail.com>, 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 <iostream>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/is_partitioned_until.hpp>
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
// namespace ba = boost;
|
||||
|
||||
template <typename T>
|
||||
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<int> v;
|
||||
|
||||
v.clear ();
|
||||
for ( int i = 5; i < 15; ++i )
|
||||
v.push_back ( i );
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( v, less_than<int>(3)) == v.end()); // no elements
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( v, less_than<int>(6)) == v.end()); // only the first element
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( v, less_than<int>(10)) == v.end()); // in the middle somewhere
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( v, less_than<int>(99)) == v.end()); // all elements satisfy
|
||||
// With bidirectional iterators.
|
||||
std::list<int> l;
|
||||
for ( int i = 5; i < 15; ++i )
|
||||
l.push_back ( i );
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than<int>(3)) == l.end()); // no elements
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than<int>(6)) == l.end()); // only the first element
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than<int>(10)) == l.end()); // in the middle somewhere
|
||||
BOOST_CHECK ( ba::is_partitioned_until ( l.begin (), l.end (), less_than<int>(99)) == l.end()); // all elements satisfy
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_sequence1 ();
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
#include <list>
|
||||
|
||||
template<typename T>
|
||||
struct is_ : public std::unary_function<T, bool> {
|
||||
struct is_ {
|
||||
is_ ( T v ) : val_ ( v ) {}
|
||||
~is_ () {}
|
||||
bool operator () ( T comp ) const { return val_ == comp; }
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <list>
|
||||
|
||||
template<typename T>
|
||||
struct is_ : public std::unary_function<T, bool> {
|
||||
struct is_ {
|
||||
is_ ( T v ) : val_ ( v ) {}
|
||||
~is_ () {}
|
||||
bool operator () ( T comp ) const { return val_ == comp; }
|
||||
|
@ -7,6 +7,20 @@
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <random>
|
||||
|
||||
std::default_random_engine gen;
|
||||
template<typename RandomIt>
|
||||
void do_shuffle(RandomIt first, RandomIt last)
|
||||
{ std::shuffle(first, last, gen); }
|
||||
#else
|
||||
template<typename RandomIt>
|
||||
void do_shuffle(RandomIt first, RandomIt last)
|
||||
{ std::random_shuffle(first, last); }
|
||||
#endif
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
template <typename Iter>
|
||||
@ -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<int>());
|
||||
check_sequence (b, v.end(), b + 7, b + 8, std::greater<int>());
|
||||
|
||||
// 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<int>());
|
||||
check_sequence (b, v.end(), b + 7, v.end(), std::greater<int>());
|
||||
|
||||
@ -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<int>());
|
||||
check_sequence (b, v.end(), b, b + 2, std::greater<int>());
|
||||
|
||||
@ -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<int>());
|
||||
check_sequence (b, v.end(), b, b, std::greater<int>());
|
||||
|
||||
// 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<int>());
|
||||
check_sequence (b, v.end(), b, v.end(), std::greater<int>());
|
||||
}
|
||||
|
128
test/reduce_test.cpp
Normal file
128
test/reduce_test.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2013.
|
||||
|
||||
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 <vector>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/cxx17/reduce.hpp>
|
||||
|
||||
#include "iterator_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
template <class Iter, class T, class Op>
|
||||
void
|
||||
test_reduce(Iter first, Iter last, T init, Op op, T x)
|
||||
{
|
||||
BOOST_CHECK(ba::reduce(first, last, init, op) == x);
|
||||
}
|
||||
|
||||
template <class Iter, class T, class Op>
|
||||
void
|
||||
test_reduce(Iter first, Iter last, Op op, T x)
|
||||
{
|
||||
BOOST_CHECK(ba::reduce(first, last, op) == x);
|
||||
}
|
||||
|
||||
template <class Iter, class T>
|
||||
void
|
||||
test_reduce(Iter first, Iter last, T x)
|
||||
{
|
||||
BOOST_CHECK(ba::reduce(first, last) == x);
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
void
|
||||
test_init_op()
|
||||
{
|
||||
int ia[] = {1, 2, 3, 4, 5, 6};
|
||||
unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
test_reduce(Iter(ia), Iter(ia), 0, std::plus<int>(), 0);
|
||||
test_reduce(Iter(ia), Iter(ia), 1, std::multiplies<int>(), 1);
|
||||
test_reduce(Iter(ia), Iter(ia+1), 0, std::plus<int>(), 1);
|
||||
test_reduce(Iter(ia), Iter(ia+1), 2, std::multiplies<int>(), 2);
|
||||
test_reduce(Iter(ia), Iter(ia+2), 0, std::plus<int>(), 3);
|
||||
test_reduce(Iter(ia), Iter(ia+2), 3, std::multiplies<int>(), 6);
|
||||
test_reduce(Iter(ia), Iter(ia+sa), 0, std::plus<int>(), 21);
|
||||
test_reduce(Iter(ia), Iter(ia+sa), 4, std::multiplies<int>(), 2880);
|
||||
}
|
||||
|
||||
void test_reduce_init_op()
|
||||
{
|
||||
test_init_op<input_iterator<const int*> >();
|
||||
test_init_op<forward_iterator<const int*> >();
|
||||
test_init_op<bidirectional_iterator<const int*> >();
|
||||
test_init_op<random_access_iterator<const int*> >();
|
||||
test_init_op<const int*>();
|
||||
|
||||
{
|
||||
char ia[] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
unsigned res = boost::algorithm::reduce(ia, ia+sa, 1U, std::multiplies<unsigned>());
|
||||
BOOST_CHECK(res == 40320); // 8! will not fit into a char
|
||||
}
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
void
|
||||
test_init()
|
||||
{
|
||||
int ia[] = {1, 2, 3, 4, 5, 6};
|
||||
unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
test_reduce(Iter(ia), Iter(ia), 0, 0);
|
||||
test_reduce(Iter(ia), Iter(ia), 1, 1);
|
||||
test_reduce(Iter(ia), Iter(ia+1), 0, 1);
|
||||
test_reduce(Iter(ia), Iter(ia+1), 2, 3);
|
||||
test_reduce(Iter(ia), Iter(ia+2), 0, 3);
|
||||
test_reduce(Iter(ia), Iter(ia+2), 3, 6);
|
||||
test_reduce(Iter(ia), Iter(ia+sa), 0, 21);
|
||||
test_reduce(Iter(ia), Iter(ia+sa), 4, 25);
|
||||
}
|
||||
|
||||
void test_reduce_init()
|
||||
{
|
||||
test_init<input_iterator<const int*> >();
|
||||
test_init<forward_iterator<const int*> >();
|
||||
test_init<bidirectional_iterator<const int*> >();
|
||||
test_init<random_access_iterator<const int*> >();
|
||||
test_init<const int*>();
|
||||
}
|
||||
|
||||
|
||||
template <class Iter>
|
||||
void
|
||||
test()
|
||||
{
|
||||
int ia[] = {1, 2, 3, 4, 5, 6};
|
||||
unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
test_reduce(Iter(ia), Iter(ia), 0);
|
||||
test_reduce(Iter(ia), Iter(ia+1), 1);
|
||||
test_reduce(Iter(ia), Iter(ia+2), 3);
|
||||
test_reduce(Iter(ia), Iter(ia+sa), 21);
|
||||
}
|
||||
|
||||
void test_reduce()
|
||||
{
|
||||
test<input_iterator<const int*> >();
|
||||
test<forward_iterator<const int*> >();
|
||||
test<bidirectional_iterator<const int*> >();
|
||||
test<random_access_iterator<const int*> >();
|
||||
test<const int*>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_reduce();
|
||||
test_reduce_init();
|
||||
test_reduce_init_op();
|
||||
}
|
@ -7,6 +7,20 @@
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <random>
|
||||
|
||||
std::default_random_engine gen;
|
||||
template<typename RandomIt>
|
||||
void do_shuffle(RandomIt first, RandomIt last)
|
||||
{ std::shuffle(first, last, gen); }
|
||||
#else
|
||||
template<typename RandomIt>
|
||||
void do_shuffle(RandomIt first, RandomIt last)
|
||||
{ std::random_shuffle(first, last); }
|
||||
#endif
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
template <typename Iter>
|
||||
@ -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<int>());
|
||||
check_sequence (b, v.end(), b + 7, b + 8, std::greater<int>());
|
||||
|
||||
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<int>());
|
||||
check_sequence (b, v.end(), b + 7, v.end(), std::greater<int>());
|
||||
|
||||
@ -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<int>());
|
||||
check_sequence (b, v.end(), b, b + 2, std::greater<int>());
|
||||
|
||||
@ -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<int>());
|
||||
check_sequence (b, v.end(), b, b, std::greater<int>());
|
||||
|
||||
// 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<int>());
|
||||
check_sequence (b, v.end(), b, v.end(), std::greater<int>());
|
||||
}
|
||||
|
137
test/transform_exclusive_scan_test.cpp
Normal file
137
test/transform_exclusive_scan_test.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 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 <vector>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/cxx11/iota.hpp>
|
||||
#include <boost/algorithm/cxx17/transform_exclusive_scan.hpp>
|
||||
|
||||
#include "iterator_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
int triangle(int n) { return n*(n+1)/2; }
|
||||
|
||||
template <class _Tp>
|
||||
struct identity
|
||||
{
|
||||
const _Tp& operator()(const _Tp& __x) const { return __x;}
|
||||
};
|
||||
|
||||
|
||||
template <class Iter1, class BOp, class UOp, class T, class Iter2>
|
||||
void
|
||||
test(Iter1 first, Iter1 last, BOp bop, UOp uop, T init, Iter2 rFirst, Iter2 rLast)
|
||||
{
|
||||
std::vector<typename std::iterator_traits<Iter1>::value_type> v;
|
||||
// Test not in-place
|
||||
ba::transform_exclusive_scan(first, last, std::back_inserter(v), init, bop, uop);
|
||||
BOOST_CHECK(std::distance(rFirst, rLast) == v.size());
|
||||
BOOST_CHECK(std::equal(v.begin(), v.end(), rFirst));
|
||||
|
||||
// Test in-place
|
||||
v.clear();
|
||||
v.assign(first, last);
|
||||
ba::transform_exclusive_scan(v.begin(), v.end(), v.begin(), init, bop, uop);
|
||||
BOOST_CHECK(std::distance(rFirst, rLast) == v.size());
|
||||
BOOST_CHECK(std::equal(v.begin(), v.end(), rFirst));
|
||||
}
|
||||
|
||||
|
||||
template <class Iter>
|
||||
void
|
||||
test()
|
||||
{
|
||||
int ia[] = { 1, 3, 5, 7, 9};
|
||||
const int pResI0[] = { 0, 1, 4, 9, 16}; // with identity
|
||||
const int mResI0[] = { 0, 0, 0, 0, 0};
|
||||
const int pResN0[] = { 0, -1, -4, -9, -16}; // with negate
|
||||
const int mResN0[] = { 0, 0, 0, 0, 0};
|
||||
const int pResI2[] = { 2, 3, 6, 11, 18}; // with identity
|
||||
const int mResI2[] = { 2, 2, 6, 30, 210};
|
||||
const int pResN2[] = { 2, 1, -2, -7, -14}; // with negate
|
||||
const int mResN2[] = { 2, -2, 6, -30, 210};
|
||||
const unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
BOOST_CHECK(sa == sizeof(pResI0) / sizeof(pResI0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResI0) / sizeof(mResI0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(pResN0) / sizeof(pResN0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResN0) / sizeof(mResN0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(pResI2) / sizeof(pResI2[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResI2) / sizeof(mResI2[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(pResN2) / sizeof(pResN2[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResN2) / sizeof(mResN2[0])); // just to be sure
|
||||
|
||||
for (unsigned int i = 0; i < sa; ++i ) {
|
||||
test(Iter(ia), Iter(ia + i), std::plus<int>(), identity<int>(), 0, pResI0, pResI0 + i);
|
||||
test(Iter(ia), Iter(ia + i), std::multiplies<int>(), identity<int>(), 0, mResI0, mResI0 + i);
|
||||
test(Iter(ia), Iter(ia + i), std::plus<int>(), std::negate<int>(), 0, pResN0, pResN0 + i);
|
||||
test(Iter(ia), Iter(ia + i), std::multiplies<int>(), std::negate<int>(), 0, mResN0, mResN0 + i);
|
||||
test(Iter(ia), Iter(ia + i), std::plus<int>(), identity<int>(), 2, pResI2, pResI2 + i);
|
||||
test(Iter(ia), Iter(ia + i), std::multiplies<int>(), identity<int>(), 2, mResI2, mResI2 + i);
|
||||
test(Iter(ia), Iter(ia + i), std::plus<int>(), std::negate<int>(), 2, pResN2, pResN2 + i);
|
||||
test(Iter(ia), Iter(ia + i), std::multiplies<int>(), std::negate<int>(), 2, mResN2, mResN2 + i);
|
||||
}
|
||||
}
|
||||
|
||||
void basic_tests()
|
||||
{
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
std::fill(v.begin(), v.end(), 3);
|
||||
ba::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 50, std::plus<int>(), identity<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 50 + (int) i * 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 0);
|
||||
ba::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 30, std::plus<int>(), identity<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 30 + triangle(i-1));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 1);
|
||||
ba::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 40, std::plus<int>(), identity<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 40 + triangle(i));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v, res;
|
||||
ba::transform_exclusive_scan(v.begin(), v.end(), std::back_inserter(res), 40, std::plus<int>(), identity<int>());
|
||||
BOOST_CHECK(res.empty());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_transform_exclusive_scan_init()
|
||||
{
|
||||
basic_tests();
|
||||
// All the iterator categories
|
||||
test<input_iterator <const int*> >();
|
||||
test<forward_iterator <const int*> >();
|
||||
test<bidirectional_iterator<const int*> >();
|
||||
test<random_access_iterator<const int*> >();
|
||||
test<const int*>();
|
||||
test< int*>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_transform_exclusive_scan_init();
|
||||
}
|
233
test/transform_inclusive_scan_test.cpp
Normal file
233
test/transform_inclusive_scan_test.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 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 <vector>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/cxx11/iota.hpp>
|
||||
#include <boost/algorithm/cxx17/transform_inclusive_scan.hpp>
|
||||
|
||||
#include "iterator_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
int triangle(int n) { return n*(n+1)/2; }
|
||||
|
||||
template <class _Tp>
|
||||
struct identity
|
||||
{
|
||||
const _Tp& operator()(const _Tp& __x) const { return __x;}
|
||||
};
|
||||
|
||||
|
||||
template <class Iter1, class BOp, class UOp, class Iter2>
|
||||
void
|
||||
transform_inclusive_scan_test(Iter1 first, Iter1 last, BOp bop, UOp uop, Iter2 rFirst, Iter2 rLast)
|
||||
{
|
||||
std::vector<typename std::iterator_traits<Iter1>::value_type> v;
|
||||
// Test not in-place
|
||||
ba::transform_inclusive_scan(first, last, std::back_inserter(v), bop, uop);
|
||||
BOOST_CHECK(std::distance(first, last) == v.size());
|
||||
BOOST_CHECK(std::equal(v.begin(), v.end(), rFirst));
|
||||
|
||||
// Test in-place
|
||||
v.clear();
|
||||
v.assign(first, last);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), bop, uop);
|
||||
BOOST_CHECK(std::distance(first, last) == v.size());
|
||||
BOOST_CHECK(std::equal(v.begin(), v.end(), rFirst));
|
||||
}
|
||||
|
||||
|
||||
template <class Iter>
|
||||
void
|
||||
transform_inclusive_scan_test()
|
||||
{
|
||||
int ia[] = { 1, 3, 5, 7, 9};
|
||||
const int pResI0[] = { 1, 4, 9, 16, 25}; // with identity
|
||||
const int mResI0[] = { 1, 3, 15, 105, 945};
|
||||
const int pResN0[] = { -1, -4, -9, -16, -25}; // with negate
|
||||
const int mResN0[] = { -1, 3, -15, 105, -945};
|
||||
const unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
BOOST_CHECK(sa == sizeof(pResI0) / sizeof(pResI0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResI0) / sizeof(mResI0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(pResN0) / sizeof(pResN0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResN0) / sizeof(mResN0[0])); // just to be sure
|
||||
|
||||
for (unsigned int i = 0; i < sa; ++i ) {
|
||||
transform_inclusive_scan_test(Iter(ia), Iter(ia + i), std::plus<int>(), identity<int>(), pResI0, pResI0 + i);
|
||||
transform_inclusive_scan_test(Iter(ia), Iter(ia + i), std::multiplies<int>(), identity<int>(), mResI0, mResI0 + i);
|
||||
transform_inclusive_scan_test(Iter(ia), Iter(ia + i), std::plus<int>(), std::negate<int>(), pResN0, pResN0 + i);
|
||||
transform_inclusive_scan_test(Iter(ia), Iter(ia + i), std::multiplies<int>(), std::negate<int>(), mResN0, mResN0 + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Basic sanity
|
||||
void basic_transform_inclusive_scan_tests()
|
||||
{
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
std::fill(v.begin(), v.end(), 3);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), identity<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == (int)(i+1) * 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 0);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), identity<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == triangle(i));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 1);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), identity<int>());
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == triangle(i + 1));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v, res;
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<int>(), identity<int>());
|
||||
BOOST_CHECK(res.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void test_transform_inclusive_scan()
|
||||
{
|
||||
basic_transform_inclusive_scan_tests();
|
||||
|
||||
// All the iterator categories
|
||||
transform_inclusive_scan_test<input_iterator <const int*> >();
|
||||
transform_inclusive_scan_test<forward_iterator <const int*> >();
|
||||
transform_inclusive_scan_test<bidirectional_iterator<const int*> >();
|
||||
transform_inclusive_scan_test<random_access_iterator<const int*> >();
|
||||
transform_inclusive_scan_test<const int*>();
|
||||
transform_inclusive_scan_test< int*>();
|
||||
}
|
||||
|
||||
|
||||
template <class Iter1, class BOp, class UOp, class T, class Iter2>
|
||||
void
|
||||
transform_inclusive_scan_init_test(Iter1 first, Iter1 last, BOp bop, UOp uop, T init, Iter2 rFirst, Iter2 rLast)
|
||||
{
|
||||
std::vector<typename std::iterator_traits<Iter1>::value_type> v;
|
||||
// Test not in-place
|
||||
ba::transform_inclusive_scan(first, last, std::back_inserter(v), bop, uop, init);
|
||||
BOOST_CHECK(std::distance(rFirst, rLast) == v.size());
|
||||
BOOST_CHECK(std::equal(v.begin(), v.end(), rFirst));
|
||||
|
||||
// Test in-place
|
||||
v.clear();
|
||||
v.assign(first, last);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), bop, uop, init);
|
||||
BOOST_CHECK(std::distance(rFirst, rLast) == v.size());
|
||||
BOOST_CHECK(std::equal(v.begin(), v.end(), rFirst));
|
||||
}
|
||||
|
||||
|
||||
template <class Iter>
|
||||
void
|
||||
transform_inclusive_scan_init_test()
|
||||
{
|
||||
int ia[] = { 1, 3, 5, 7, 9};
|
||||
const int pResI0[] = { 1, 4, 9, 16, 25}; // with identity
|
||||
const int mResI0[] = { 0, 0, 0, 0, 0};
|
||||
const int pResN0[] = { -1, -4, -9, -16, -25}; // with negate
|
||||
const int mResN0[] = { 0, 0, 0, 0, 0};
|
||||
const int pResI2[] = { 3, 6, 11, 18, 27}; // with identity
|
||||
const int mResI2[] = { 2, 6, 30, 210, 1890};
|
||||
const int pResN2[] = { 1, -2, -7, -14, -23}; // with negate
|
||||
const int mResN2[] = { -2, 6, -30, 210, -1890};
|
||||
const unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
BOOST_CHECK(sa == sizeof(pResI0) / sizeof(pResI0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResI0) / sizeof(mResI0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(pResN0) / sizeof(pResN0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResN0) / sizeof(mResN0[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(pResI2) / sizeof(pResI2[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResI2) / sizeof(mResI2[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(pResN2) / sizeof(pResN2[0])); // just to be sure
|
||||
BOOST_CHECK(sa == sizeof(mResN2) / sizeof(mResN2[0])); // just to be sure
|
||||
|
||||
for (unsigned int i = 0; i < sa; ++i ) {
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::plus<int>(), identity<int>(), 0, pResI0, pResI0 + i);
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies<int>(), identity<int>(), 0, mResI0, mResI0 + i);
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::plus<int>(), std::negate<int>(), 0, pResN0, pResN0 + i);
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies<int>(), std::negate<int>(), 0, mResN0, mResN0 + i);
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::plus<int>(), identity<int>(), 2, pResI2, pResI2 + i);
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies<int>(), identity<int>(), 2, mResI2, mResI2 + i);
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::plus<int>(), std::negate<int>(), 2, pResN2, pResN2 + i);
|
||||
transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies<int>(), std::negate<int>(), 2, mResN2, mResN2 + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Basic sanity
|
||||
void basic_transform_inclusive_scan_init_tests()
|
||||
{
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
std::fill(v.begin(), v.end(), 3);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), identity<int>(), 50);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 50 + (int) (i + 1) * 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 0);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), identity<int>(), 30);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 30 + triangle(i));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
ba::iota(v.begin(), v.end(), 1);
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<int>(), identity<int>(), 40);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
BOOST_CHECK(v[i] == 40 + triangle(i + 1));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> v, res;
|
||||
ba::transform_inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<int>(), identity<int>(), 1);
|
||||
BOOST_CHECK(res.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void test_transform_inclusive_scan_init()
|
||||
{
|
||||
basic_transform_inclusive_scan_init_tests();
|
||||
|
||||
// All the iterator categories
|
||||
transform_inclusive_scan_init_test<input_iterator <const int*> >();
|
||||
transform_inclusive_scan_init_test<forward_iterator <const int*> >();
|
||||
transform_inclusive_scan_init_test<bidirectional_iterator<const int*> >();
|
||||
transform_inclusive_scan_init_test<random_access_iterator<const int*> >();
|
||||
transform_inclusive_scan_init_test<const int*>();
|
||||
transform_inclusive_scan_init_test< int*>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_transform_inclusive_scan();
|
||||
test_transform_inclusive_scan_init();
|
||||
}
|
188
test/transform_reduce_test.cpp
Normal file
188
test/transform_reduce_test.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2013.
|
||||
|
||||
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 <boost/config.hpp>
|
||||
#include <boost/algorithm/cxx17/transform_reduce.hpp>
|
||||
|
||||
#include "iterator_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
template <class _Tp>
|
||||
struct identity
|
||||
{
|
||||
const _Tp& operator()(const _Tp& __x) const { return __x;}
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct twice
|
||||
{
|
||||
const _Tp operator()(const _Tp& __x) const { return 2 * __x; }
|
||||
};
|
||||
|
||||
|
||||
template <class Iter1, class T, class BOp, class UOp>
|
||||
void
|
||||
test_init_bop_uop(Iter1 first1, Iter1 last1, T init, BOp bOp, UOp uOp, T x)
|
||||
{
|
||||
BOOST_CHECK(ba::transform_reduce(first1, last1, init, bOp, uOp) == x);
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
void
|
||||
test_init_bop_uop()
|
||||
{
|
||||
int ia[] = {1, 2, 3, 4, 5, 6};
|
||||
unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
|
||||
test_init_bop_uop(Iter(ia), Iter(ia), 0, std::plus<int>(), identity<int>(), 0);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia), 1, std::multiplies<int>(), identity<int>(), 1);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+1), 0, std::multiplies<int>(), identity<int>(), 0);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+1), 2, std::plus<int>(), identity<int>(), 3);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+2), 0, std::plus<int>(), identity<int>(), 3);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+2), 3, std::multiplies<int>(), identity<int>(), 6);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::multiplies<int>(), identity<int>(), 2880);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::plus<int>(), identity<int>(), 25);
|
||||
|
||||
test_init_bop_uop(Iter(ia), Iter(ia), 0, std::plus<int>(), twice<int>(), 0);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia), 1, std::multiplies<int>(), twice<int>(), 1);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+1), 0, std::multiplies<int>(), twice<int>(), 0);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+1), 2, std::plus<int>(), twice<int>(), 4);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+2), 0, std::plus<int>(), twice<int>(), 6);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+2), 3, std::multiplies<int>(), twice<int>(), 24);
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::multiplies<int>(), twice<int>(), 184320); // 64 * 2880
|
||||
test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::plus<int>(), twice<int>(), 46);
|
||||
}
|
||||
|
||||
void test_transform_reduce_init_bop_uop()
|
||||
{
|
||||
BOOST_CHECK ( true );
|
||||
}
|
||||
|
||||
template <class Iter1, class Iter2, class T, class Op1, class Op2>
|
||||
void
|
||||
test_init_bop_bop(Iter1 first1, Iter1 last1, Iter2 first2, T init, Op1 op1, Op2 op2, T x)
|
||||
{
|
||||
BOOST_CHECK(ba::transform_reduce(first1, last1, first2, init, op1, op2) == x);
|
||||
}
|
||||
|
||||
template <class SIter, class UIter>
|
||||
void
|
||||
test_init_bop_bop()
|
||||
{
|
||||
int ia[] = {1, 2, 3, 4, 5, 6};
|
||||
unsigned int ua[] = {2, 4, 6, 8, 10,12};
|
||||
unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
BOOST_CHECK(sa == sizeof(ua) / sizeof(ua[0])); // just to be sure
|
||||
|
||||
test_init_bop_bop(SIter(ia), SIter(ia), UIter(ua), 0, std::plus<int>(), std::multiplies<int>(), 0);
|
||||
test_init_bop_bop(UIter(ua), UIter(ua), SIter(ia), 1, std::multiplies<int>(), std::plus<int>(), 1);
|
||||
test_init_bop_bop(SIter(ia), SIter(ia+1), UIter(ua), 0, std::multiplies<int>(), std::plus<int>(), 0);
|
||||
test_init_bop_bop(UIter(ua), UIter(ua+1), SIter(ia), 2, std::plus<int>(), std::multiplies<int>(), 4);
|
||||
test_init_bop_bop(SIter(ia), SIter(ia+2), UIter(ua), 0, std::plus<int>(), std::multiplies<int>(), 10);
|
||||
test_init_bop_bop(UIter(ua), UIter(ua+2), SIter(ia), 3, std::multiplies<int>(), std::plus<int>(), 54);
|
||||
test_init_bop_bop(SIter(ia), SIter(ia+sa), UIter(ua), 4, std::multiplies<int>(), std::plus<int>(), 2099520);
|
||||
test_init_bop_bop(UIter(ua), UIter(ua+sa), SIter(ia), 4, std::plus<int>(), std::multiplies<int>(), 186);
|
||||
}
|
||||
|
||||
void test_transform_reduce_init_bop_bop()
|
||||
{
|
||||
// All the iterator categories
|
||||
test_init_bop_bop<input_iterator <const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<input_iterator <const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<input_iterator <const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init_bop_bop<input_iterator <const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
test_init_bop_bop<forward_iterator <const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<forward_iterator <const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<forward_iterator <const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init_bop_bop<forward_iterator <const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
test_init_bop_bop<bidirectional_iterator<const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<bidirectional_iterator<const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<bidirectional_iterator<const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init_bop_bop<bidirectional_iterator<const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
test_init_bop_bop<random_access_iterator<const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<random_access_iterator<const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init_bop_bop<random_access_iterator<const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init_bop_bop<random_access_iterator<const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
// just plain pointers (const vs. non-const, too)
|
||||
test_init_bop_bop<const int*, const unsigned int *>();
|
||||
test_init_bop_bop<const int*, unsigned int *>();
|
||||
test_init_bop_bop< int*, const unsigned int *>();
|
||||
test_init_bop_bop< int*, unsigned int *>();
|
||||
}
|
||||
|
||||
template <class Iter1, class Iter2, class T>
|
||||
void
|
||||
test_init(Iter1 first1, Iter1 last1, Iter2 first2, T init, T x)
|
||||
{
|
||||
BOOST_CHECK(ba::transform_reduce(first1, last1, first2, init) == x);
|
||||
}
|
||||
|
||||
template <class SIter, class UIter>
|
||||
void
|
||||
test_init()
|
||||
{
|
||||
int ia[] = {1, 2, 3, 4, 5, 6};
|
||||
unsigned int ua[] = {2, 4, 6, 8, 10,12};
|
||||
unsigned sa = sizeof(ia) / sizeof(ia[0]);
|
||||
BOOST_CHECK(sa == sizeof(ua) / sizeof(ua[0])); // just to be sure
|
||||
|
||||
test_init(SIter(ia), SIter(ia), UIter(ua), 0, 0);
|
||||
test_init(UIter(ua), UIter(ua), SIter(ia), 1, 1);
|
||||
test_init(SIter(ia), SIter(ia+1), UIter(ua), 0, 2);
|
||||
test_init(UIter(ua), UIter(ua+1), SIter(ia), 2, 4);
|
||||
test_init(SIter(ia), SIter(ia+2), UIter(ua), 0, 10);
|
||||
test_init(UIter(ua), UIter(ua+2), SIter(ia), 3, 13);
|
||||
test_init(SIter(ia), SIter(ia+sa), UIter(ua), 0, 182);
|
||||
test_init(UIter(ua), UIter(ua+sa), SIter(ia), 4, 186);
|
||||
}
|
||||
|
||||
void test_transform_reduce_init()
|
||||
{
|
||||
// All the iterator categories
|
||||
test_init<input_iterator <const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init<input_iterator <const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init<input_iterator <const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init<input_iterator <const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
test_init<forward_iterator <const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init<forward_iterator <const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init<forward_iterator <const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init<forward_iterator <const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
test_init<bidirectional_iterator<const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init<bidirectional_iterator<const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init<bidirectional_iterator<const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init<bidirectional_iterator<const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
test_init<random_access_iterator<const int*>, input_iterator <const unsigned int*> >();
|
||||
test_init<random_access_iterator<const int*>, forward_iterator <const unsigned int*> >();
|
||||
test_init<random_access_iterator<const int*>, bidirectional_iterator<const unsigned int*> >();
|
||||
test_init<random_access_iterator<const int*>, random_access_iterator<const unsigned int*> >();
|
||||
|
||||
// just plain pointers (const vs. non-const, too)
|
||||
test_init<const int*, const unsigned int *>();
|
||||
test_init<const int*, unsigned int *>();
|
||||
test_init< int*, const unsigned int *>();
|
||||
test_init< int*, unsigned int *>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_transform_reduce_init();
|
||||
test_transform_reduce_init_bop_uop();
|
||||
test_transform_reduce_init_bop_bop();
|
||||
}
|
Reference in New Issue
Block a user