From 20cd8402b7aea43820259d5792eaae4ce3295485 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 5 Apr 2014 20:54:11 +0900 Subject: [PATCH] add C++14 constexpr nth_element --- sprout/algorithm/cxx14/detail/sort_tool.hpp | 182 ++++++++++++++++++++ sprout/algorithm/cxx14/nth_element.hpp | 170 +++++++++++++++++- sprout/algorithm/cxx14/sort.hpp | 173 +------------------ 3 files changed, 354 insertions(+), 171 deletions(-) create mode 100644 sprout/algorithm/cxx14/detail/sort_tool.hpp diff --git a/sprout/algorithm/cxx14/detail/sort_tool.hpp b/sprout/algorithm/cxx14/detail/sort_tool.hpp new file mode 100644 index 00000000..be56c60d --- /dev/null +++ b/sprout/algorithm/cxx14/detail/sort_tool.hpp @@ -0,0 +1,182 @@ +/*============================================================================= + 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_SORT_TOOL_HPP +#define SPROUT_ALGORITHM_CXX14_DETAIL_SORT_TOOL_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CXX14_CONSTEXPR unsigned + sort3(ForwardIterator x, ForwardIterator y, ForwardIterator z, Compare comp) { + unsigned r = 0; + if (!comp(*y, *x)) { + if (!comp(*z, *y)) + return r; + sprout::swap(*y, *z); + r = 1; + if (comp(*y, *x)) { + sprout::swap(*x, *y); + r = 2; + } + return r; + } + if (comp(*z, *y)) { + sprout::swap(*x, *z); + r = 1; + return r; + } + sprout::swap(*x, *y); + r = 1; + if (comp(*z, *y)) { + sprout::swap(*y, *z); + r = 2; + } + return r; + } + template + inline SPROUT_CXX14_CONSTEXPR unsigned + sort4(ForwardIterator x1, ForwardIterator x2, ForwardIterator x3, ForwardIterator x4, Compare comp) { + unsigned r = sprout::detail::sort3(x1, x2, x3, comp); + if (comp(*x4, *x3)) { + sprout::swap(*x3, *x4); + ++r; + if (comp(*x3, *x2)) { + sprout::swap(*x2, *x3); + ++r; + if (comp(*x2, *x1)) { + sprout::swap(*x1, *x2); + ++r; + } + } + } + return r; + } + template + inline SPROUT_CXX14_CONSTEXPR unsigned + sort5(ForwardIterator x1, ForwardIterator x2, ForwardIterator x3, ForwardIterator x4, ForwardIterator x5, Compare comp) { + unsigned r = sprout::detail::sort4(x1, x2, x3, x4, comp); + if (comp(*x5, *x4)) { + sprout::swap(*x4, *x5); + ++r; + if (comp(*x4, *x3)) { + sprout::swap(*x3, *x4); + ++r; + if (comp(*x3, *x2)) { + sprout::swap(*x2, *x3); + ++r; + if (comp(*x2, *x1)) { + sprout::swap(*x1, *x2); + ++r; + } + } + } + } + return r; + } + template + inline SPROUT_CXX14_CONSTEXPR void + selection_sort(BirdirectionalIterator first, BirdirectionalIterator last, Compare comp) { + BirdirectionalIterator lm1 = last; + for (--lm1; first != lm1; ++first) { + BirdirectionalIterator i = sprout::min_element(first, last, comp); + if (i != first) { + sprout::swap(*first, *i); + } + } + } + template + inline SPROUT_CXX14_CONSTEXPR void + insertion_sort(BirdirectionalIterator first, BirdirectionalIterator last, Compare comp) { + typedef typename std::iterator_traits::value_type value_type; + if (first != last) { + BirdirectionalIterator i = first; + for (++i; i != last; ++i) { + BirdirectionalIterator j = i; + value_type t(sprout::move(*j)); + for (BirdirectionalIterator k = i; k != first && comp(t, *--k); --j) { + *j = sprout::move(*k); + } + *j = sprout::move(t); + } + } + } + template + inline SPROUT_CXX14_CONSTEXPR void + insertion_sort_3(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + typedef typename std::iterator_traits::value_type value_type; + RandomAccessIterator j = first + 2; + sprout::detail::sort3(first, first + 1, j, comp); + for (RandomAccessIterator i = j + 1; i != last; ++i) { + if (comp(*i, *j)) { + value_type t(sprout::move(*i)); + RandomAccessIterator k = j; + j = i; + do { + *j = sprout::move(*k); + j = k; + } while (j != first && comp(t, *--k)); + *j = sprout::move(t); + } + j = i; + } + } + template + inline SPROUT_CXX14_CONSTEXPR bool + insertion_sort_incomplete(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + switch (last - first) { + case 0: + case 1: + return true; + case 2: + if (comp(*--last, *first)) { + sprout::swap(*first, *last); + } + return true; + case 3: + sprout::detail::sort3(first, first + 1, --last, comp); + return true; + case 4: + sprout::detail::sort4(first, first + 1, first + 2, --last, comp); + return true; + case 5: + sprout::detail::sort5(first, first + 1, first + 2, first + 3, --last, comp); + return true; + } + typedef typename std::iterator_traits::value_type value_type; + RandomAccessIterator j = first+2; + sprout::detail::sort3(first, first + 1, j, comp); + unsigned const limit = 8; + unsigned count = 0; + for (RandomAccessIterator i = j + 1; i != last; ++i) { + if (comp(*i, *j)) { + value_type t(sprout::move(*i)); + RandomAccessIterator k = j; + j = i; + do { + *j = sprout::move(*k); + j = k; + } while (j != first && comp(t, *--k)); + *j = sprout::move(t); + if (++count == limit) { + return ++i == last; + } + } + j = i; + } + return true; + } + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_CXX14_DETAIL_SORT_TOOL_HPP diff --git a/sprout/algorithm/cxx14/nth_element.hpp b/sprout/algorithm/cxx14/nth_element.hpp index 0fdab292..82b3f321 100644 --- a/sprout/algorithm/cxx14/nth_element.hpp +++ b/sprout/algorithm/cxx14/nth_element.hpp @@ -8,20 +8,178 @@ #ifndef SPROUT_ALGORITHM_CXX14_NTH_ELEMENT_HPP #define SPROUT_ALGORITHM_CXX14_NTH_ELEMENT_HPP +#include +#include #include +#include +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { + namespace detail { + template + inline SPROUT_CXX14_CONSTEXPR void + nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp) { + typedef typename std::iterator_traits::difference_type difference_type; + difference_type const limit = 7; + while (true) { + if (nth == last) { + return; + } + difference_type len = last - first; + switch (len) { + case 0: + case 1: + return; + case 2: + if (comp(*--last, *first)) { + sprout::swap(*first, *last); + } + return; + case 3: + { + RandomAccessIterator m = first; + sprout::detail::sort3(first, ++m, --last, comp); + } + return; + } + if (len <= limit) { + sprout::detail::selection_sort(first, last, comp); + return; + } + RandomAccessIterator m = first + len / 2; + RandomAccessIterator lm1 = last; + unsigned n_swaps = sprout::detail::sort3(first, m, --lm1, comp); + RandomAccessIterator i = first; + RandomAccessIterator j = lm1; + if (!comp(*i, *m)) { + bool restart_flag = false; + while (true) { + if (i == --j) { + ++i; + j = last; + if (!comp(*first, *--j)) { + while (true) { + if (i == j) { + return; + } + if (comp(*first, *i)) { + sprout::swap(*i, *j); + ++n_swaps; + ++i; + break; + } + ++i; + } + } + if (i == j) { + return; + } + while (true) { + while (!comp(*first, *i)) { + ++i; + } + while (comp(*first, *--j)) + ; + if (i >= j) { + break; + } + sprout::swap(*i, *j); + ++n_swaps; + ++i; + } + if (nth < i) { + return; + } + first = i; + restart_flag = true; + break; + } + if (comp(*j, *m)) { + sprout::swap(*i, *j); + ++n_swaps; + break; + } + } + if (restart_flag) { + continue; + } + } + ++i; + if (i < j) { + while (true) { + while (comp(*i, *m)) { + ++i; + } + while (!comp(*--j, *m)) + ; + if (i >= j) { + break; + } + sprout::swap(*i, *j); + ++n_swaps; + if (m == i) { + m = j; + } + ++i; + } + } + if (i != m && comp(*m, *i)) { + sprout::swap(*i, *m); + ++n_swaps; + } + if (nth == i) { + return; + } + do { + if (n_swaps == 0) { + if (nth < i) { + j = m = first; + while (++j != i) { + if (comp(*j, *m)) { + break; + } + m = j; + } + return; + } else { + j = m = i; + while (++j != last) { + if (comp(*j, *m)) { + break; + } + m = j; + } + return; + } + } + } while (false); + if (nth < i) { + last = i; + } else { + first = ++i; + } + } + } + } // namespace detail // // 25.4.2 Nth element // - // !!! TODO: implementation - template - inline SPROUT_CXX14_CONSTEXPR void - nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); - template inline SPROUT_CXX14_CONSTEXPR void - nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); + nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp) { + typedef typename std::add_lvalue_reference::type compare_ref; + sprout::detail::nth_element(first, nth, last, comp); + } + + template + inline SPROUT_CXX14_CONSTEXPR void + nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last) { + sprout::nth_element( + first, nth, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_CXX14_NTH_ELEMENT_HPP diff --git a/sprout/algorithm/cxx14/sort.hpp b/sprout/algorithm/cxx14/sort.hpp index f599d496..2d10f0af 100644 --- a/sprout/algorithm/cxx14/sort.hpp +++ b/sprout/algorithm/cxx14/sort.hpp @@ -9,176 +9,16 @@ #define SPROUT_ALGORITHM_CXX14_SORT_HPP #include +#include #include -#include -#include -#include +#include #include #include -#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT + namespace sprout { namespace detail { - template - inline SPROUT_CXX14_CONSTEXPR unsigned - sort3(ForwardIterator x, ForwardIterator y, ForwardIterator z, Compare comp) { - unsigned r = 0; - if (!comp(*y, *x)) { - if (!comp(*z, *y)) - return r; - sprout::swap(*y, *z); - r = 1; - if (comp(*y, *x)) { - sprout::swap(*x, *y); - r = 2; - } - return r; - } - if (comp(*z, *y)) { - sprout::swap(*x, *z); - r = 1; - return r; - } - sprout::swap(*x, *y); - r = 1; - if (comp(*z, *y)) { - sprout::swap(*y, *z); - r = 2; - } - return r; - } - template - inline SPROUT_CXX14_CONSTEXPR unsigned - sort4(ForwardIterator x1, ForwardIterator x2, ForwardIterator x3, ForwardIterator x4, Compare comp) { - unsigned r = sprout::detail::sort3(x1, x2, x3, comp); - if (comp(*x4, *x3)) { - sprout::swap(*x3, *x4); - ++r; - if (comp(*x3, *x2)) { - sprout::swap(*x2, *x3); - ++r; - if (comp(*x2, *x1)) { - sprout::swap(*x1, *x2); - ++r; - } - } - } - return r; - } - template - inline SPROUT_CXX14_CONSTEXPR unsigned - sort5(ForwardIterator x1, ForwardIterator x2, ForwardIterator x3, ForwardIterator x4, ForwardIterator x5, Compare comp) { - unsigned r = sprout::detail::sort4(x1, x2, x3, x4, comp); - if (comp(*x5, *x4)) { - sprout::swap(*x4, *x5); - ++r; - if (comp(*x4, *x3)) { - sprout::swap(*x3, *x4); - ++r; - if (comp(*x3, *x2)) { - sprout::swap(*x2, *x3); - ++r; - if (comp(*x2, *x1)) { - sprout::swap(*x1, *x2); - ++r; - } - } - } - } - return r; - } - template - inline SPROUT_CXX14_CONSTEXPR void - selection_sort(BirdirectionalIterator first, BirdirectionalIterator last, Compare comp) { - BirdirectionalIterator lm1 = last; - for (--lm1; first != lm1; ++first) { - BirdirectionalIterator i = sprout::min_element(first, last, comp); - if (i != first) { - sprout::swap(*first, *i); - } - } - } - template - inline SPROUT_CXX14_CONSTEXPR void - insertion_sort(BirdirectionalIterator first, BirdirectionalIterator last, Compare comp) { - typedef typename std::iterator_traits::value_type value_type; - if (first != last) { - BirdirectionalIterator i = first; - for (++i; i != last; ++i) { - BirdirectionalIterator j = i; - value_type t(sprout::move(*j)); - for (BirdirectionalIterator k = i; k != first && comp(t, *--k); --j) { - *j = sprout::move(*k); - } - *j = sprout::move(t); - } - } - } - template - inline SPROUT_CXX14_CONSTEXPR void - insertion_sort_3(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { - typedef typename std::iterator_traits::value_type value_type; - RandomAccessIterator j = first + 2; - sprout::detail::sort3(first, first + 1, j, comp); - for (RandomAccessIterator i = j + 1; i != last; ++i) { - if (comp(*i, *j)) { - value_type t(sprout::move(*i)); - RandomAccessIterator k = j; - j = i; - do { - *j = sprout::move(*k); - j = k; - } while (j != first && comp(t, *--k)); - *j = sprout::move(t); - } - j = i; - } - } - template - inline SPROUT_CXX14_CONSTEXPR bool - insertion_sort_incomplete(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { - switch (last - first) { - case 0: - case 1: - return true; - case 2: - if (comp(*--last, *first)) { - sprout::swap(*first, *last); - } - return true; - case 3: - sprout::detail::sort3(first, first + 1, --last, comp); - return true; - case 4: - sprout::detail::sort4(first, first + 1, first + 2, --last, comp); - return true; - case 5: - sprout::detail::sort5(first, first + 1, first + 2, first + 3, --last, comp); - return true; - } - typedef typename std::iterator_traits::value_type value_type; - RandomAccessIterator j = first+2; - sprout::detail::sort3(first, first + 1, j, comp); - unsigned const limit = 8; - unsigned count = 0; - for (RandomAccessIterator i = j + 1; i != last; ++i) { - if (comp(*i, *j)) { - value_type t(sprout::move(*i)); - RandomAccessIterator k = j; - j = i; - do { - *j = sprout::move(*k); - j = k; - } while (j != first && comp(t, *--k)); - *j = sprout::move(t); - if (++count == limit) { - return ++i == last; - } - } - j = i; - } - return true; - } template SPROUT_CXX14_CONSTEXPR void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); @@ -349,7 +189,10 @@ namespace sprout { template inline SPROUT_CXX14_CONSTEXPR void sort(RandomAccessIterator first, RandomAccessIterator last) { - sprout::sort(first, last, sprout::less::value_type>()); + sprout::sort( + first, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); } } // namespace sprout