From 8d19fdc676ecd43946b39f44becfcfd4b4539d35 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Mon, 13 Apr 2015 11:40:49 +0900 Subject: [PATCH] add while_loop, until_loop utilities --- sprout/algorithm/fold_until.hpp | 70 ++++++++++++++++++++++++++ sprout/algorithm/fold_while.hpp | 70 ++++++++++++++++++++++++++ sprout/algorithm/non_modifying.hpp | 2 + sprout/utility.hpp | 1 + sprout/utility/loop.hpp | 15 ++++++ sprout/utility/until_loop.hpp | 81 ++++++++++++++++++++++++++++++ sprout/utility/while_loop.hpp | 81 ++++++++++++++++++++++++++++++ 7 files changed, 320 insertions(+) create mode 100644 sprout/algorithm/fold_until.hpp create mode 100644 sprout/algorithm/fold_while.hpp create mode 100644 sprout/utility/loop.hpp create mode 100644 sprout/utility/until_loop.hpp create mode 100644 sprout/utility/while_loop.hpp diff --git a/sprout/algorithm/fold_until.hpp b/sprout/algorithm/fold_until.hpp new file mode 100644 index 00000000..c5266fe5 --- /dev/null +++ b/sprout/algorithm/fold_until.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + Copyright (c) 2011-2015 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + 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) +=============================================================================*/ +#ifndef SPROUT_ALGORITHM_FOLD_UNTIL_HPP +#define SPROUT_ALGORITHM_FOLD_UNTIL_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair + fold_until_impl_1( + sprout::pair const& current, + InputIterator last, BinaryOperation binary_op, Predicate pred, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.first == last || pred(current.second) ? current + : n == 1 ? type(sprout::next(current.first), binary_op(current.second, *current.first)) + : sprout::detail::fold_until_impl_1( + sprout::detail::fold_until_impl_1( + current, + last, binary_op, pred, n / 2 + ), + last, binary_op, pred, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + fold_until_impl( + sprout::pair const& current, + InputIterator last, BinaryOperation binary_op, Predicate pred, typename std::iterator_traits::difference_type n + ) + { + return current.first == last || pred(current.second) ? current + : sprout::detail::fold_until_impl( + sprout::detail::fold_until_impl_1( + current, + last, binary_op, pred, n + ), + last, binary_op, pred, n * 2 + ) + ; + } + } // namespace detail + + // + // fold_until + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR T + fold_until(InputIterator first, InputIterator last, T init, BinaryOperation binary_op, Predicate pred) { + typedef sprout::pair type; + return sprout::detail::fold_until_impl(type(first, init), last, binary_op, pred, 1).second; + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FOLD_UNTIL_HPP diff --git a/sprout/algorithm/fold_while.hpp b/sprout/algorithm/fold_while.hpp new file mode 100644 index 00000000..185f015e --- /dev/null +++ b/sprout/algorithm/fold_while.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + Copyright (c) 2011-2015 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + 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) +=============================================================================*/ +#ifndef SPROUT_ALGORITHM_FOLD_WHILE_HPP +#define SPROUT_ALGORITHM_FOLD_WHILE_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair + fold_while_impl_1( + sprout::pair const& current, + InputIterator last, BinaryOperation binary_op, Predicate pred, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.first == last || !pred(current.second) ? current + : n == 1 ? type(sprout::next(current.first), binary_op(current.second, *current.first)) + : sprout::detail::fold_while_impl_1( + sprout::detail::fold_while_impl_1( + current, + last, binary_op, pred, n / 2 + ), + last, binary_op, pred, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + fold_while_impl( + sprout::pair const& current, + InputIterator last, BinaryOperation binary_op, Predicate pred, typename std::iterator_traits::difference_type n + ) + { + return current.first == last || !pred(current.second) ? current + : sprout::detail::fold_while_impl( + sprout::detail::fold_while_impl_1( + current, + last, binary_op, pred, n + ), + last, binary_op, pred, n * 2 + ) + ; + } + } // namespace detail + + // + // fold_while + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR T + fold_while(InputIterator first, InputIterator last, T init, BinaryOperation binary_op, Predicate pred) { + typedef sprout::pair type; + return sprout::detail::fold_while_impl(type(first, init), last, binary_op, pred, 1).second; + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FOLD_WHILE_HPP diff --git a/sprout/algorithm/non_modifying.hpp b/sprout/algorithm/non_modifying.hpp index 65b14d92..ed9d2881 100644 --- a/sprout/algorithm/non_modifying.hpp +++ b/sprout/algorithm/non_modifying.hpp @@ -61,6 +61,8 @@ #include #include #include +#include +#include #include #endif // #ifndef SPROUT_ALGORITHM_NON_MODIFYIING_HPP diff --git a/sprout/utility.hpp b/sprout/utility.hpp index f25e1708..8411ccd6 100644 --- a/sprout/utility.hpp +++ b/sprout/utility.hpp @@ -21,5 +21,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_UTILITY_HPP diff --git a/sprout/utility/loop.hpp b/sprout/utility/loop.hpp new file mode 100644 index 00000000..79890db5 --- /dev/null +++ b/sprout/utility/loop.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2011-2015 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + 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) +=============================================================================*/ +#ifndef SPROUT_UTILITY_LOOP_HPP +#define SPROUT_UTILITY_LOOP_HPP + +#include +#include +#include + +#endif // #ifndef SPROUT_UTILITY_LOOP_HPP diff --git a/sprout/utility/until_loop.hpp b/sprout/utility/until_loop.hpp new file mode 100644 index 00000000..0cdfe5a8 --- /dev/null +++ b/sprout/utility/until_loop.hpp @@ -0,0 +1,81 @@ +/*============================================================================= + Copyright (c) 2011-2015 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + 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) +=============================================================================*/ +#ifndef SPROUT_UTILITY_UNTIL_LOOP_HPP +#define SPROUT_UTILITY_UNTIL_LOOP_HPP + +#include +#include + +namespace sprout { +#ifdef SPROUT_CONFIG_DISABLE_CXX14_CONSTEXPR + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair + until_loop_check(T const& init, Predicate pred) { + return sprout::pair(init, pred(init)); + } + template + inline SPROUT_CONSTEXPR sprout::pair + until_loop_impl_1(sprout::pair const& current, UnaryOperation unary_op, Predicate pred, std::size_t n) { + return current.second || pred(current.first) ? current + : n == 1 ? sprout::detail::until_loop_check(unary_op(current.first), pred) + : sprout::detail::until_loop_impl_1( + sprout::detail::until_loop_impl_1( + current, + unary_op, pred, n / 2 + ), + unary_op, pred, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + until_loop_impl(sprout::pair const& current, UnaryOperation unary_op, Predicate pred, std::size_t n) { + return current.second || pred(current.first) ? current + : sprout::detail::until_loop_impl( + sprout::detail::until_loop_impl_1( + current, + unary_op, pred, n + ), + unary_op, pred, n * 2 + ) + ; + } + } // namespace detail + + // + // until_loop + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR T + until_loop(T init, UnaryOperation unary_op, Predicate pred) { + typedef sprout::pair type; + return sprout::detail::until_loop_impl(type(init, false), unary_op, pred, 1).second; + } +#else + // + // until_loop + // + // recursion depth: + // 0 + // + template + inline SPROUT_CXX14_CONSTEXPR T + until_loop(T init, UnaryOperation unary_op, Predicate pred) { + while (!pred(init)) { + init = unary_op(init); + } + return init; + } +#endif +} // namespace sprout + +#endif // #ifndef SPROUT_UTILITY_UNTIL_LOOP_HPP diff --git a/sprout/utility/while_loop.hpp b/sprout/utility/while_loop.hpp new file mode 100644 index 00000000..3e2f638d --- /dev/null +++ b/sprout/utility/while_loop.hpp @@ -0,0 +1,81 @@ +/*============================================================================= + Copyright (c) 2011-2015 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + 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) +=============================================================================*/ +#ifndef SPROUT_UTILITY_WHILE_LOOP_HPP +#define SPROUT_UTILITY_WHILE_LOOP_HPP + +#include +#include + +namespace sprout { +#ifdef SPROUT_CONFIG_DISABLE_CXX14_CONSTEXPR + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair + while_loop_check(T const& init, Predicate pred) { + return sprout::pair(init, !pred(init)); + } + template + inline SPROUT_CONSTEXPR sprout::pair + while_loop_impl_1(sprout::pair const& current, UnaryOperation unary_op, Predicate pred, std::size_t n) { + return current.second || !pred(current.first) ? current + : n == 1 ? sprout::detail::while_loop_check(unary_op(current.first), pred) + : sprout::detail::while_loop_impl_1( + sprout::detail::while_loop_impl_1( + current, + unary_op, pred, n / 2 + ), + unary_op, pred, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + while_loop_impl(sprout::pair const& current, UnaryOperation unary_op, Predicate pred, std::size_t n) { + return current.second || !pred(current.first) ? current + : sprout::detail::while_loop_impl( + sprout::detail::while_loop_impl_1( + current, + unary_op, pred, n + ), + unary_op, pred, n * 2 + ) + ; + } + } // namespace detail + + // + // while_loop + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR T + while_loop(T init, UnaryOperation unary_op, Predicate pred) { + typedef sprout::pair type; + return sprout::detail::while_loop_impl(type(init, false), unary_op, pred, 1).second; + } +#else + // + // while_loop + // + // recursion depth: + // 0 + // + template + inline SPROUT_CXX14_CONSTEXPR T + while_loop(T init, UnaryOperation unary_op, Predicate pred) { + while (pred(init)) { + init = unary_op(init); + } + return init; + } +#endif +} // namespace sprout + +#endif // #ifndef SPROUT_UTILITY_WHILE_LOOP_HPP