diff --git a/include/boost/algorithm/cxx17/exclusive_scan.hpp b/include/boost/algorithm/cxx17/exclusive_scan.hpp new file mode 100644 index 0000000..03ecea5 --- /dev/null +++ b/include/boost/algorithm/cxx17/exclusive_scan.hpp @@ -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 // for std::plus +#include // for std::iterator_traits + +#include +#include +#include + +namespace boost { namespace algorithm { + +template +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 +OutputIterator exclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, T init) +{ + typedef typename std::iterator_traits::value_type VT; + return exclusive_scan(first, last, result, init, std::plus()); +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP diff --git a/include/boost/algorithm/cxx17/for_each_n.hpp b/include/boost/algorithm/cxx17/for_each_n.hpp new file mode 100644 index 0000000..b8134cc --- /dev/null +++ b/include/boost/algorithm/cxx17/for_each_n.hpp @@ -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 // 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 +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 diff --git a/include/boost/algorithm/cxx17/inclusive_scan.hpp b/include/boost/algorithm/cxx17/inclusive_scan.hpp new file mode 100644 index 0000000..cd015f1 --- /dev/null +++ b/include/boost/algorithm/cxx17/inclusive_scan.hpp @@ -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 // for std::plus +#include // for std::iterator_traits + +#include +#include +#include + +namespace boost { namespace algorithm { + +template +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 +OutputIterator inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, BinaryOperation bOp) +{ + if (first != last) { + typename std::iterator_traits::value_type init = *first; + *result++ = init; + if (++first != last) + return inclusive_scan(first, last, result, bOp, init); + } + + return result; +} + +template +OutputIterator inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result) +{ + typedef typename std::iterator_traits::value_type VT; + return inclusive_scan(first, last, result, std::plus()); +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP diff --git a/include/boost/algorithm/cxx17/reduce.hpp b/include/boost/algorithm/cxx17/reduce.hpp new file mode 100644 index 0000000..f47695b --- /dev/null +++ b/include/boost/algorithm/cxx17/reduce.hpp @@ -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 // for std::plus +#include // for std::iterator_traits + +#include +#include +#include + +namespace boost { namespace algorithm { + +template +T reduce(InputIterator first, InputIterator last, T init, BinaryOperation bOp) +{ + ; + for (; first != last; ++first) + init = bOp(init, *first); + return init; +} + +template +T reduce(InputIterator first, InputIterator last, T init) +{ + typedef typename std::iterator_traits::value_type VT; + return reduce(first, last, init, std::plus()); +} + +template +typename std::iterator_traits::value_type +reduce(InputIterator first, InputIterator last) +{ + return reduce(first, last, + typename std::iterator_traits::value_type()); +} + +template +typename boost::range_value::type +reduce(const Range &r) +{ + return reduce(boost::begin(r), boost::end(r)); +} + +// Not sure that this won't be ambiguous (1) +template +T reduce(const Range &r, T init) +{ + return reduce(boost::begin (r), boost::end (r), init); +} + + +// Not sure that this won't be ambiguous (2) +template +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 diff --git a/include/boost/algorithm/cxx17/transform_exclusive_scan.hpp b/include/boost/algorithm/cxx17/transform_exclusive_scan.hpp new file mode 100644 index 0000000..d3b4329 --- /dev/null +++ b/include/boost/algorithm/cxx17/transform_exclusive_scan.hpp @@ -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 // for std::plus +#include // for std::iterator_traits + +#include +#include +#include + +namespace boost { namespace algorithm { + +template +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 diff --git a/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp b/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp new file mode 100644 index 0000000..476c117 --- /dev/null +++ b/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp @@ -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 // for std::plus +#include // for std::iterator_traits + +#include +#include +#include + +namespace boost { namespace algorithm { + +template +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 +OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, + BinaryOperation bOp, UnaryOperation uOp) +{ + if (first != last) { + typename std::iterator_traits::value_type init = uOp(*first); + *result++ = init; + if (++first != last) + return transform_inclusive_scan(first, last, result, bOp, uOp, init); + } + + return result; +} + + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP diff --git a/include/boost/algorithm/cxx17/transform_reduce.hpp b/include/boost/algorithm/cxx17/transform_reduce.hpp new file mode 100644 index 0000000..7ebde7d --- /dev/null +++ b/include/boost/algorithm/cxx17/transform_reduce.hpp @@ -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 // for std::plus +#include // for std::iterator_traits + +#include +#include +#include + +namespace boost { namespace algorithm { + +template +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 +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 +T transform_reduce(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, T init) +{ + return transform_reduce(first1, last1, first2, init, + std::plus(), std::multiplies()); +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fad1578..e32bc53 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -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,7 +80,7 @@ alias unit_test_framework # Is_palindrome tests [ run is_palindrome_test.cpp unit_test_framework : : : : is_palindrome_test ] - + # Is_partitioned_until tests [ run is_partitioned_until_test.cpp unit_test_framework : : : : is_partitioned_until_test ] ; diff --git a/test/exclusive_scan_test.cpp b/test/exclusive_scan_test.cpp new file mode 100644 index 0000000..2df3769 --- /dev/null +++ b/test/exclusive_scan_test.cpp @@ -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 +#include +#include +#include + +#include +#include +#include + +#include "iterator_test.hpp" + +#define BOOST_TEST_MAIN +#include + +namespace ba = boost::algorithm; + +int triangle(int n) { return n*(n+1)/2; } + +void basic_tests_init() +{ + { + std::vector 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 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 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(); +} diff --git a/test/for_each_n_test.cpp b/test/for_each_n_test.cpp new file mode 100644 index 0000000..8d55ba4 --- /dev/null +++ b/test/for_each_n_test.cpp @@ -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 +#include + +#include "iterator_test.hpp" + +#define BOOST_TEST_MAIN +#include + +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 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(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(i+2)); + } +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + test_for_each_n (); +} diff --git a/test/inclusive_scan_test.cpp b/test/inclusive_scan_test.cpp new file mode 100644 index 0000000..66dc998 --- /dev/null +++ b/test/inclusive_scan_test.cpp @@ -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 +#include +#include +#include + +#include +#include +#include + +#include "iterator_test.hpp" + +#define BOOST_TEST_MAIN +#include + +namespace ba = boost::algorithm; + +int triangle(int n) { return n*(n+1)/2; } + +void basic_tests_op() +{ + { + std::vector v(10); + std::fill(v.begin(), v.end(), 3); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus()); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == (int)(i+1) * 3); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 0); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus()); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == triangle(i)); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 1); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus()); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == triangle(i + 1)); + } + + { + std::vector v, res; + ba::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus()); + assert(res.empty()); + } +} + +void test_inclusive_scan_op() +{ + basic_tests_op(); + BOOST_CHECK(true); +} + +void basic_tests_init() +{ + { + std::vector v(10); + std::fill(v.begin(), v.end(), 3); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), 50); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 50 + (int)(i+1) * 3); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 0); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), 40); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 40 + triangle(i)); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 1); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), 30); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 30 + triangle(i + 1)); + } + + { + std::vector v, res; + ba::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus(), 40); + assert(res.empty()); + } +} + + +void test_inclusive_scan_init() +{ + basic_tests_init(); + BOOST_CHECK(true); +} + +void basic_tests_op_init() +{ + { + std::vector v(10); + std::fill(v.begin(), v.end(), 3); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), 50); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 50 + (int)(i+1) * 3); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 0); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), 40); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 40 + triangle(i)); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 1); + ba::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), 30); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 30 + triangle(i + 1)); + } + + { + std::vector v, res; + ba::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus(), 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(); +} diff --git a/test/reduce_test.cpp b/test/reduce_test.cpp new file mode 100644 index 0000000..ec47db2 --- /dev/null +++ b/test/reduce_test.cpp @@ -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 +#include + +#include +#include + +#include "iterator_test.hpp" + +#define BOOST_TEST_MAIN +#include + +namespace ba = boost::algorithm; + +template +void +test_reduce(Iter first, Iter last, T init, Op op, T x) +{ + BOOST_CHECK(ba::reduce(first, last, init, op) == x); +} + +template +void +test_reduce(Iter first, Iter last, Op op, T x) +{ + BOOST_CHECK(ba::reduce(first, last, op) == x); +} + +template +void +test_reduce(Iter first, Iter last, T x) +{ + BOOST_CHECK(ba::reduce(first, last) == x); +} + +template +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(), 0); + test_reduce(Iter(ia), Iter(ia), 1, std::multiplies(), 1); + test_reduce(Iter(ia), Iter(ia+1), 0, std::plus(), 1); + test_reduce(Iter(ia), Iter(ia+1), 2, std::multiplies(), 2); + test_reduce(Iter(ia), Iter(ia+2), 0, std::plus(), 3); + test_reduce(Iter(ia), Iter(ia+2), 3, std::multiplies(), 6); + test_reduce(Iter(ia), Iter(ia+sa), 0, std::plus(), 21); + test_reduce(Iter(ia), Iter(ia+sa), 4, std::multiplies(), 2880); +} + +void test_reduce_init_op() +{ + test_init_op >(); + test_init_op >(); + test_init_op >(); + test_init_op >(); + test_init_op(); + + { + 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()); + BOOST_CHECK(res == 40320); // 8! will not fit into a char + } +} + +template +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 >(); + test_init >(); + test_init >(); + test_init >(); + test_init(); +} + + +template +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 >(); + test >(); + test >(); + test >(); + test(); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + test_reduce(); + test_reduce_init(); + test_reduce_init_op(); +} diff --git a/test/transform_exclusive_scan_test.cpp b/test/transform_exclusive_scan_test.cpp new file mode 100644 index 0000000..6259f2b --- /dev/null +++ b/test/transform_exclusive_scan_test.cpp @@ -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 +#include +#include + +#include +#include +#include + +#include "iterator_test.hpp" + +#define BOOST_TEST_MAIN +#include + +namespace ba = boost::algorithm; + +int triangle(int n) { return n*(n+1)/2; } + +template +struct identity +{ + const _Tp& operator()(const _Tp& __x) const { return __x;} +}; + + +template +void +test(Iter1 first, Iter1 last, BOp bop, UOp uop, T init, Iter2 rFirst, Iter2 rLast) +{ + std::vector::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 +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(), identity(), 0, pResI0, pResI0 + i); + test(Iter(ia), Iter(ia + i), std::multiplies(), identity(), 0, mResI0, mResI0 + i); + test(Iter(ia), Iter(ia + i), std::plus(), std::negate(), 0, pResN0, pResN0 + i); + test(Iter(ia), Iter(ia + i), std::multiplies(), std::negate(), 0, mResN0, mResN0 + i); + test(Iter(ia), Iter(ia + i), std::plus(), identity(), 2, pResI2, pResI2 + i); + test(Iter(ia), Iter(ia + i), std::multiplies(), identity(), 2, mResI2, mResI2 + i); + test(Iter(ia), Iter(ia + i), std::plus(), std::negate(), 2, pResN2, pResN2 + i); + test(Iter(ia), Iter(ia + i), std::multiplies(), std::negate(), 2, mResN2, mResN2 + i); + } +} + +void basic_tests() +{ + { + std::vector v(10); + std::fill(v.begin(), v.end(), 3); + ba::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 50, std::plus(), identity()); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 50 + (int) i * 3); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 0); + ba::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 30, std::plus(), identity()); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 30 + triangle(i-1)); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 1); + ba::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 40, std::plus(), identity()); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 40 + triangle(i)); + } + + { + std::vector v, res; + ba::transform_exclusive_scan(v.begin(), v.end(), std::back_inserter(res), 40, std::plus(), identity()); + BOOST_CHECK(res.empty()); + } +} + + +void test_transform_exclusive_scan_init() +{ + basic_tests(); +// All the iterator categories + test >(); + test >(); + test >(); + test >(); + test(); + test< int*>(); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + test_transform_exclusive_scan_init(); +} diff --git a/test/transform_inclusive_scan_test.cpp b/test/transform_inclusive_scan_test.cpp new file mode 100644 index 0000000..1ce01c6 --- /dev/null +++ b/test/transform_inclusive_scan_test.cpp @@ -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 +#include +#include + +#include +#include +#include + +#include "iterator_test.hpp" + +#define BOOST_TEST_MAIN +#include + +namespace ba = boost::algorithm; + +int triangle(int n) { return n*(n+1)/2; } + +template +struct identity +{ + const _Tp& operator()(const _Tp& __x) const { return __x;} +}; + + +template +void +transform_inclusive_scan_test(Iter1 first, Iter1 last, BOp bop, UOp uop, Iter2 rFirst, Iter2 rLast) +{ + std::vector::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 +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(), identity(), pResI0, pResI0 + i); + transform_inclusive_scan_test(Iter(ia), Iter(ia + i), std::multiplies(), identity(), mResI0, mResI0 + i); + transform_inclusive_scan_test(Iter(ia), Iter(ia + i), std::plus(), std::negate(), pResN0, pResN0 + i); + transform_inclusive_scan_test(Iter(ia), Iter(ia + i), std::multiplies(), std::negate(), mResN0, mResN0 + i); + } +} + + +// Basic sanity +void basic_transform_inclusive_scan_tests() +{ + { + std::vector v(10); + std::fill(v.begin(), v.end(), 3); + ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), identity()); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == (int)(i+1) * 3); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 0); + ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), identity()); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == triangle(i)); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 1); + ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), identity()); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == triangle(i + 1)); + } + + { + std::vector v, res; + ba::transform_inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus(), identity()); + BOOST_CHECK(res.empty()); + } +} + +void test_transform_inclusive_scan() +{ + basic_transform_inclusive_scan_tests(); + +// All the iterator categories + transform_inclusive_scan_test >(); + transform_inclusive_scan_test >(); + transform_inclusive_scan_test >(); + transform_inclusive_scan_test >(); + transform_inclusive_scan_test(); + transform_inclusive_scan_test< int*>(); +} + + +template +void +transform_inclusive_scan_init_test(Iter1 first, Iter1 last, BOp bop, UOp uop, T init, Iter2 rFirst, Iter2 rLast) +{ + std::vector::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 +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(), identity(), 0, pResI0, pResI0 + i); + transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies(), identity(), 0, mResI0, mResI0 + i); + transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::plus(), std::negate(), 0, pResN0, pResN0 + i); + transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies(), std::negate(), 0, mResN0, mResN0 + i); + transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::plus(), identity(), 2, pResI2, pResI2 + i); + transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies(), identity(), 2, mResI2, mResI2 + i); + transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::plus(), std::negate(), 2, pResN2, pResN2 + i); + transform_inclusive_scan_init_test(Iter(ia), Iter(ia + i), std::multiplies(), std::negate(), 2, mResN2, mResN2 + i); + } +} + + +// Basic sanity +void basic_transform_inclusive_scan_init_tests() +{ + { + std::vector v(10); + std::fill(v.begin(), v.end(), 3); + ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), identity(), 50); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 50 + (int) (i + 1) * 3); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 0); + ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), identity(), 30); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 30 + triangle(i)); + } + + { + std::vector v(10); + ba::iota(v.begin(), v.end(), 1); + ba::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus(), identity(), 40); + for (size_t i = 0; i < v.size(); ++i) + BOOST_CHECK(v[i] == 40 + triangle(i + 1)); + } + + { + std::vector v, res; + ba::transform_inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus(), identity(), 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 >(); + transform_inclusive_scan_init_test >(); + transform_inclusive_scan_init_test >(); + transform_inclusive_scan_init_test >(); + transform_inclusive_scan_init_test(); + transform_inclusive_scan_init_test< int*>(); + +} + + +BOOST_AUTO_TEST_CASE( test_main ) +{ + test_transform_inclusive_scan(); + test_transform_inclusive_scan_init(); +} diff --git a/test/transform_reduce_test.cpp b/test/transform_reduce_test.cpp new file mode 100644 index 0000000..796dd8c --- /dev/null +++ b/test/transform_reduce_test.cpp @@ -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 +#include + +#include "iterator_test.hpp" + +#define BOOST_TEST_MAIN +#include + +namespace ba = boost::algorithm; + +template +struct identity +{ + const _Tp& operator()(const _Tp& __x) const { return __x;} +}; + +template +struct twice +{ + const _Tp operator()(const _Tp& __x) const { return 2 * __x; } +}; + + +template +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 +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(), identity(), 0); + test_init_bop_uop(Iter(ia), Iter(ia), 1, std::multiplies(), identity(), 1); + test_init_bop_uop(Iter(ia), Iter(ia+1), 0, std::multiplies(), identity(), 0); + test_init_bop_uop(Iter(ia), Iter(ia+1), 2, std::plus(), identity(), 3); + test_init_bop_uop(Iter(ia), Iter(ia+2), 0, std::plus(), identity(), 3); + test_init_bop_uop(Iter(ia), Iter(ia+2), 3, std::multiplies(), identity(), 6); + test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::multiplies(), identity(), 2880); + test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::plus(), identity(), 25); + + test_init_bop_uop(Iter(ia), Iter(ia), 0, std::plus(), twice(), 0); + test_init_bop_uop(Iter(ia), Iter(ia), 1, std::multiplies(), twice(), 1); + test_init_bop_uop(Iter(ia), Iter(ia+1), 0, std::multiplies(), twice(), 0); + test_init_bop_uop(Iter(ia), Iter(ia+1), 2, std::plus(), twice(), 4); + test_init_bop_uop(Iter(ia), Iter(ia+2), 0, std::plus(), twice(), 6); + test_init_bop_uop(Iter(ia), Iter(ia+2), 3, std::multiplies(), twice(), 24); + test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::multiplies(), twice(), 184320); // 64 * 2880 + test_init_bop_uop(Iter(ia), Iter(ia+sa), 4, std::plus(), twice(), 46); +} + +void test_transform_reduce_init_bop_uop() +{ + BOOST_CHECK ( true ); +} + +template +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 +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(), std::multiplies(), 0); + test_init_bop_bop(UIter(ua), UIter(ua), SIter(ia), 1, std::multiplies(), std::plus(), 1); + test_init_bop_bop(SIter(ia), SIter(ia+1), UIter(ua), 0, std::multiplies(), std::plus(), 0); + test_init_bop_bop(UIter(ua), UIter(ua+1), SIter(ia), 2, std::plus(), std::multiplies(), 4); + test_init_bop_bop(SIter(ia), SIter(ia+2), UIter(ua), 0, std::plus(), std::multiplies(), 10); + test_init_bop_bop(UIter(ua), UIter(ua+2), SIter(ia), 3, std::multiplies(), std::plus(), 54); + test_init_bop_bop(SIter(ia), SIter(ia+sa), UIter(ua), 4, std::multiplies(), std::plus(), 2099520); + test_init_bop_bop(UIter(ua), UIter(ua+sa), SIter(ia), 4, std::plus(), std::multiplies(), 186); +} + +void test_transform_reduce_init_bop_bop() +{ +// All the iterator categories + test_init_bop_bop, input_iterator >(); + test_init_bop_bop, forward_iterator >(); + test_init_bop_bop, bidirectional_iterator >(); + test_init_bop_bop, random_access_iterator >(); + + test_init_bop_bop, input_iterator >(); + test_init_bop_bop, forward_iterator >(); + test_init_bop_bop, bidirectional_iterator >(); + test_init_bop_bop, random_access_iterator >(); + + test_init_bop_bop, input_iterator >(); + test_init_bop_bop, forward_iterator >(); + test_init_bop_bop, bidirectional_iterator >(); + test_init_bop_bop, random_access_iterator >(); + + test_init_bop_bop, input_iterator >(); + test_init_bop_bop, forward_iterator >(); + test_init_bop_bop, bidirectional_iterator >(); + test_init_bop_bop, random_access_iterator >(); + +// just plain pointers (const vs. non-const, too) + test_init_bop_bop(); + test_init_bop_bop(); + test_init_bop_bop< int*, const unsigned int *>(); + test_init_bop_bop< int*, unsigned int *>(); +} + +template +void +test_init(Iter1 first1, Iter1 last1, Iter2 first2, T init, T x) +{ + BOOST_CHECK(ba::transform_reduce(first1, last1, first2, init) == x); +} + +template +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 >(); + test_init, forward_iterator >(); + test_init, bidirectional_iterator >(); + test_init, random_access_iterator >(); + + test_init, input_iterator >(); + test_init, forward_iterator >(); + test_init, bidirectional_iterator >(); + test_init, random_access_iterator >(); + + test_init, input_iterator >(); + test_init, forward_iterator >(); + test_init, bidirectional_iterator >(); + test_init, random_access_iterator >(); + + test_init, input_iterator >(); + test_init, forward_iterator >(); + test_init, bidirectional_iterator >(); + test_init, random_access_iterator >(); + +// just plain pointers (const vs. non-const, too) + test_init(); + test_init(); + 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(); +}