/*============================================================================= Copyright (c) 2011-2019 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_FIXED_NEXT_PERMUTATION_HPP #define SPROUT_ALGORITHM_FIXED_NEXT_PERMUTATION_HPP #include #include #include #include #include #include #include #include #if SPROUT_GCC_EARLIER(4, 8, 2) # include # include #else # include # include #endif #include #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { namespace fixed { namespace detail { template inline SPROUT_CONSTEXPR Result next_permutation_impl_4(Container const& cont, Difference d) { return Result( #if SPROUT_GCC_EARLIER(4, 8, 2) sprout::range::fixed::copy_backward(sprout::fit::reverse_copy(sprout::next(sprout::begin(cont), d), sprout::end(cont), cont), cont), #else sprout::fixed::copy_backward(sprout::make_reverse_iterator(sprout::end(cont)), sprout::make_reverse_iterator(sprout::next(sprout::begin(cont), d)), cont), #endif true ); } template inline SPROUT_CONSTEXPR Result next_permutation_impl_3( Container const& cont, Compare comp, BidirectionalIterator const& first, BidirectionalIterator const& last, BidirectionalIterator const& i, BidirectionalIterator const& ii, BidirectionalIterator const& j ) { return !comp(*i, *sprout::prev(j)) ? sprout::fixed::detail::next_permutation_impl_3( cont, comp, first, last, i, ii, sprout::prev(j) ) : sprout::fixed::detail::next_permutation_impl_4( sprout::fixed::swap_element(cont, i, sprout::prev(j)), sprout::distance(first, ii) ) ; } template inline SPROUT_CONSTEXPR Result next_permutation_impl_2( Container const& cont, Compare comp, BidirectionalIterator const& first, BidirectionalIterator const& last, BidirectionalIterator const& i, BidirectionalIterator const& ii ) { return comp(*i, *ii) ? sprout::fixed::detail::next_permutation_impl_3( cont, comp, first, last, i, ii, last ) : i == first ? Result(sprout::fixed::reverse_copy(first, last, cont), false) : sprout::fixed::detail::next_permutation_impl_2( cont, comp, first, last, sprout::prev(i), i ) ; } template inline SPROUT_CONSTEXPR Result next_permutation_impl_1( Container const& cont, Compare comp, BidirectionalIterator const& first, BidirectionalIterator const& last, BidirectionalIterator const& i ) { return i == last ? Result(sprout::deep_copy(cont), false) : sprout::fixed::detail::next_permutation_impl_2( cont, comp, first, last, sprout::prev(last, 2), sprout::prev(last) ) ; } template inline SPROUT_CONSTEXPR Result next_permutation_impl(Container const& cont, Compare comp, BidirectionalIterator const& first, BidirectionalIterator const& last) { return first == last ? Result(sprout::deep_copy(cont), false) : sprout::fixed::detail::next_permutation_impl_1( cont, comp, first, last, sprout::next(first) ); } } // namespace detail // // next_permutation // template inline SPROUT_CONSTEXPR sprout::pair::type, bool> next_permutation(Container const& cont, Compare comp) { typedef sprout::pair::type, bool> type; return sprout::fixed::detail::next_permutation_impl( cont, comp, sprout::begin(cont), sprout::end(cont) ); } template inline SPROUT_CONSTEXPR sprout::pair::type, bool> next_permutation(Container const& cont) { typedef sprout::pair::type, bool> type; return sprout::fixed::detail::next_permutation_impl( cont, NS_SSCRISK_CEL_OR_SPROUT::less::value_type>(), sprout::begin(cont), sprout::end(cont) ); } } // namespace fixed using sprout::fixed::next_permutation; } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_NEXT_PERMUTATION_HPP