From 856fb90150d4a921ec355003fe4d9886bea82a7d Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Mon, 7 Apr 2014 20:01:38 +0900 Subject: [PATCH] add C++14 constexpr stable_partition, stable_sort, inplace_merge --- .../algorithm/cxx14/detail/insertion_sort.hpp | 53 ++++++++++++++ sprout/algorithm/cxx14/inplace_merge.hpp | 71 +++++++++++++++++-- sprout/algorithm/cxx14/stable_partition.hpp | 33 ++++++++- sprout/algorithm/cxx14/stable_sort.hpp | 35 +++++++-- 4 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 sprout/algorithm/cxx14/detail/insertion_sort.hpp diff --git a/sprout/algorithm/cxx14/detail/insertion_sort.hpp b/sprout/algorithm/cxx14/detail/insertion_sort.hpp new file mode 100644 index 00000000..4e91d7da --- /dev/null +++ b/sprout/algorithm/cxx14/detail/insertion_sort.hpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2011-2014 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_CXX14_DETAIL_INSERTION_SORT_HPP +#define SPROUT_ALGORITHM_CXX14_DETAIL_INSERTION_SORT_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CXX14_CONSTEXPR void + unguarded_linear_insert(RandomAccessIterator last, Compare comp) { + typedef typename std::iterator_traits::value_type value_type; + value_type val = sprout::move(*last); + RandomAccessIterator next = last; + --next; + while (comp(val, *next)) { + *last = sprout::move(*next); + last = next; + --next; + } + *last = sprout::move(val); + } + + template + inline SPROUT_CXX14_CONSTEXPR void + insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + typedef typename std::iterator_traits::value_type value_type; + if (first == last) { + return; + } + for (RandomAccessIterator i = first + 1; i != last; ++i) { + if (comp(*i, *first)) { + value_type val = sprout::move(*i); + sprout::move_backward(first, i, i + 1); + *first = sprout::move(val); + } else { + sprout::detail::unguarded_linear_insert(i, comp); + } + } + } + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_CXX14_DETAIL_INSERTION_SORT_HPP diff --git a/sprout/algorithm/cxx14/inplace_merge.hpp b/sprout/algorithm/cxx14/inplace_merge.hpp index b6940625..ab3d32cd 100644 --- a/sprout/algorithm/cxx14/inplace_merge.hpp +++ b/sprout/algorithm/cxx14/inplace_merge.hpp @@ -8,20 +8,79 @@ #ifndef SPROUT_ALGORITHM_CXX14_INPLACE_MERGE_HPP #define SPROUT_ALGORITHM_CXX14_INPLACE_MERGE_HPP +#include #include +#include +#include +#include +#include +#include +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { + namespace detail { + template + inline SPROUT_CXX14_CONSTEXPR void + inplace_merge( + BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, + Distance len1, Distance len2, Compare comp + ) + { + if (len1 == 0 || len2 == 0) { + return; + } + if (len1 + len2 == 2) { + if (comp(*middle, *first)) { + sprout::iter_swap(first, middle); + } + return; + } + BidirectionalIterator first_cut = first; + BidirectionalIterator second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) { + len11 = len1 / 2; + sprout::advance(first_cut, len11); + second_cut = sprout::lower_bound(middle, last, *first_cut, comp); + len22 = sprout::distance(middle, second_cut); + } else { + len22 = len2 / 2; + sprout::advance(second_cut, len22); + first_cut = sprout::upper_bound(first, middle, *second_cut, comp); + len11 = sprout::distance(first, first_cut); + } + sprout::rotate(first_cut, middle, second_cut); + BidirectionalIterator new_middle = first_cut; + sprout::advance(new_middle, sprout::distance(middle, second_cut)); + sprout::detail::inplace_merge(first, first_cut, new_middle, len11, len22, comp); + sprout::detail::inplace_merge(new_middle, second_cut, last, len1 - len11, len2 - len22, comp); + } + } // namespace detail // // 25.4.4 Merge // - // !!! TODO: implementation - template - inline SPROUT_CXX14_CONSTEXPR void - inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); - template inline SPROUT_CXX14_CONSTEXPR void - inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); + inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp) { + typedef typename std::iterator_traits::difference_type difference_type; + if (first == middle || middle == last) { + return; + } + difference_type const len1 = sprout::distance(first, middle); + difference_type const len2 = sprout::distance(middle, last); + sprout::detail::inplace_merge(first, middle, last, len1, len2, comp); + } + + template + inline SPROUT_CXX14_CONSTEXPR void + inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last) { + sprout::inplace_merge( + first, middle, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_CXX14_INPLACE_MERGE_HPP diff --git a/sprout/algorithm/cxx14/stable_partition.hpp b/sprout/algorithm/cxx14/stable_partition.hpp index ef059999..8347ee38 100644 --- a/sprout/algorithm/cxx14/stable_partition.hpp +++ b/sprout/algorithm/cxx14/stable_partition.hpp @@ -9,15 +9,44 @@ #define SPROUT_ALGORITHM_CXX14_STABLE_PARTITION_HPP #include +#include +#include +#include +#include +#include namespace sprout { + namespace detail { + template + inline SPROUT_CXX14_CONSTEXPR BidirectionalIterator + inplace_stable_partition(BidirectionalIterator first, Predicate pred, Distance len) { + if (len == 1) { + return first; + } + BidirectionalIterator middle = first; + sprout::advance(middle, len / 2); + BidirectionalIterator left_split = sprout::detail::inplace_stable_partition(first, pred, len / 2); + Distance right_len = len - len / 2; + BidirectionalIterator right_split = sprout::find_if_not(middle, sprout::next(middle, right_len), pred); + if (right_len) { + right_split = sprout::detail::inplace_stable_partition(middle, pred, right_len); + } + sprout::rotate(left_split, middle, right_split); + sprout::advance(left_split, sprout::distance(middle, right_split)); + return left_split; + } + } // namespace sprout // // 25.3.13 Partitions // - // !!! TODO: implementation template inline SPROUT_CXX14_CONSTEXPR BidirectionalIterator - stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); + stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred) { + first = sprout::find_if_not(first, last, pred); + return first == last ? first + : sprout::detail::inplace_stable_partition(first, pred, sprout::distance(first, last)) + ; + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_CXX14_STABLE_PARTITION_HPP diff --git a/sprout/algorithm/cxx14/stable_sort.hpp b/sprout/algorithm/cxx14/stable_sort.hpp index 6a5f936c..cc5f836e 100644 --- a/sprout/algorithm/cxx14/stable_sort.hpp +++ b/sprout/algorithm/cxx14/stable_sort.hpp @@ -9,19 +9,42 @@ #define SPROUT_ALGORITHM_CXX14_STABLE_SORT_HPP #include +#include +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { + namespace detail { + template + inline SPROUT_CXX14_CONSTEXPR void + inplace_stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + if (last - first < 15) { + sprout::detail::insertion_sort(first, last, comp); + return; + } + RandomAccessIterator middle = first + (last - first) / 2; + sprout::detail::inplace_stable_sort(first, middle, comp); + sprout::detail::inplace_stable_sort(middle, last, comp); + sprout::detail::inplace_merge(first, middle, last, middle - first, last - middle, comp); + } + } // namespace detail // // 25.4.1.2 stable_sort // - // !!! TODO: implementation - template - inline SPROUT_CXX14_CONSTEXPR void - stable_sort(RandomAccessIterator first, RandomAccessIterator last); - template inline SPROUT_CXX14_CONSTEXPR void - stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); + stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + sprout::detail::inplace_stable_sort(first, last, comp); + } + + template + inline SPROUT_CXX14_CONSTEXPR void + stable_sort(RandomAccessIterator first, RandomAccessIterator last) { + sprout::stable_sort( + first, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_CXX14_STABLE_SORT_HPP