From ddac080ec02b599889c39b472a7c79daadbba749 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Fri, 21 Dec 2012 23:12:54 +0900 Subject: [PATCH] add tristate_lexicographical_compare --- sprout/algorithm/equal.hpp | 1 + sprout/algorithm/is_permutation.hpp | 1 + sprout/algorithm/lexicographical_compare.hpp | 1 + sprout/algorithm/non_modifying.hpp | 1 + .../tristate_lexicographical_compare.hpp | 135 ++++++++++++++++++ sprout/detail/algorithm/search_one.hpp | 1 + sprout/string/char_traits.hpp | 47 +++--- 7 files changed, 167 insertions(+), 20 deletions(-) create mode 100644 sprout/algorithm/tristate_lexicographical_compare.hpp diff --git a/sprout/algorithm/equal.hpp b/sprout/algorithm/equal.hpp index b9dee566..acca2728 100644 --- a/sprout/algorithm/equal.hpp +++ b/sprout/algorithm/equal.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT diff --git a/sprout/algorithm/is_permutation.hpp b/sprout/algorithm/is_permutation.hpp index f0e88a17..8ba3d5e8 100644 --- a/sprout/algorithm/is_permutation.hpp +++ b/sprout/algorithm/is_permutation.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/sprout/algorithm/lexicographical_compare.hpp b/sprout/algorithm/lexicographical_compare.hpp index 676df525..a0bf9079 100644 --- a/sprout/algorithm/lexicographical_compare.hpp +++ b/sprout/algorithm/lexicographical_compare.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/sprout/algorithm/non_modifying.hpp b/sprout/algorithm/non_modifying.hpp index bf06ff8b..e05e0b98 100644 --- a/sprout/algorithm/non_modifying.hpp +++ b/sprout/algorithm/non_modifying.hpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/sprout/algorithm/tristate_lexicographical_compare.hpp b/sprout/algorithm/tristate_lexicographical_compare.hpp new file mode 100644 index 00000000..9c2f911c --- /dev/null +++ b/sprout/algorithm/tristate_lexicographical_compare.hpp @@ -0,0 +1,135 @@ +#ifndef SPROUT_ALGORITHM_TRISTATE_LEXICOGRAPHICAL_COMPARE_HPP +#define SPROUT_ALGORITHM_TRISTATE_LEXICOGRAPHICAL_COMPARE_HPP + +#include +#include +#include +#include +#include +#include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR int + tristate_lexicographical_compare_impl_ra_2( + RandomAccessIterator1 last1, RandomAccessIterator2 last2, Compare comp, + sprout::pair const& found + ) + { + return found.second == last2 ? (found.first == last1 ? 0 : 1) + : found.first == last1 ? -1 + : comp(*found.first, *found.second) ? -1 + : comp(*found.second, *found.first) ? 1 + : 0 + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + tristate_lexicographical_compare_impl_ra_1( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, Compare comp, + typename std::iterator_traits::difference_type pivot, sprout::pair const& found + ) + { + typedef sprout::pair found_type; + return found.first != first1 ? found + : pivot == 0 ? (comp(*first1, *first2) || comp(*first2, *first1) ? found_type(first1, first2) : found_type(last1, last2)) + : sprout::detail::tristate_lexicographical_compare_impl_ra_1( + sprout::next(first1, pivot), last1, sprout::next(first2, pivot), last2, comp, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) - pivot) / 2, + sprout::detail::tristate_lexicographical_compare_impl_ra_1( + first1, sprout::next(first1, pivot), first2, sprout::next(first2, pivot), comp, + pivot / 2, + found_type(first1, first2) + ) + ) + ; + } + template + inline SPROUT_CONSTEXPR int + tristate_lexicographical_compare_impl_ra( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, Compare comp, + typename std::iterator_traits::difference_type size + ) + { + typedef sprout::pair found_type; + return sprout::detail::tristate_lexicographical_compare_impl_ra_2( + last1, last2, comp, + sprout::detail::tristate_lexicographical_compare_impl_ra_1( + first1, sprout::next(first1, size), first2, sprout::next(first2, size), comp, + size / 2, found_type(first1, first2) + ) + ); + } + template + inline SPROUT_CONSTEXPR int + tristate_lexicographical_compare( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, Compare comp, + std::random_access_iterator_tag* + ) + { + return first2 == last2 ? (first1 == last1 ? 0 : 1) + : first1 == last1 ? -1 + : sprout::detail::tristate_lexicographical_compare_impl_ra( + first1, last1, first2, last2, comp, + sprout::min(NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1), NS_SSCRISK_CEL_OR_SPROUT::distance(first2, last2)) + ) + ; + } + + // Copyright (C) 2011 RiSK (sscrisk) + template + inline SPROUT_CONSTEXPR int + tristate_lexicographical_compare_impl(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) { + return first2 == last2 ? (first1 == last1 ? 0 : 1) + : first1 == last1 || comp(*first1, *first2) ? -1 + : comp(*first2, *first1) ? 1 + : sprout::detail::tristate_lexicographical_compare_impl(sprout::next(first1), last1, sprout::next(first2), last2, comp) + ; + } + template + inline SPROUT_CONSTEXPR int + tristate_lexicographical_compare( + InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp, + void* + ) + { + return sprout::detail::tristate_lexicographical_compare_impl(first1, last1, first2, last2, comp); + } + } //namespace detail + + // + // tristate_lexicographical_compare + // + // recursion depth: + // [first1, last1), [first2, last2) are RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // + template + inline SPROUT_CONSTEXPR int + tristate_lexicographical_compare( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef typename sprout::common_iterator_category::type* category; + return sprout::detail::tristate_lexicographical_compare(first1, last1, first2, last2, comp, category()); + } + + template + inline SPROUT_CONSTEXPR int + tristate_lexicographical_compare( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::tristate_lexicographical_compare( + first1, last1, first2, last2, + sprout::less<>() + ); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_TRISTATE_LEXICOGRAPHICAL_COMPARE_HPP diff --git a/sprout/detail/algorithm/search_one.hpp b/sprout/detail/algorithm/search_one.hpp index 02a869f0..0bbbdecb 100644 --- a/sprout/detail/algorithm/search_one.hpp +++ b/sprout/detail/algorithm/search_one.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT diff --git a/sprout/string/char_traits.hpp b/sprout/string/char_traits.hpp index b7c4b699..7de7a07c 100644 --- a/sprout/string/char_traits.hpp +++ b/sprout/string/char_traits.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT #include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT @@ -31,6 +32,12 @@ namespace sprout { return eq(c1, c2); } }; + struct lt_ { + public: + SPROUT_CONSTEXPR bool operator()(char_type c1, char_type c2) const SPROUT_NOEXCEPT { + return lt(c1, c2); + } + }; private: static SPROUT_CONSTEXPR char_type const* find_impl(char_type const* found, char_type const* last) { return found == last ? nullptr @@ -48,11 +55,11 @@ namespace sprout { return impl_type::lt(c1, c2); } static SPROUT_CONSTEXPR int compare(char_type const* s1, char_type const* s2, std::size_t n) { - return !n ? 0 - : lt(*s1, *s2) ? -1 - : lt(*s2, *s1) ? 1 - : compare(s1 + 1, s2 + 1, n - 1) - ; + return sprout::tristate_lexicographical_compare( + sprout::as_iterator(s1), sprout::as_iterator(s1, n), + sprout::as_iterator(s2), sprout::as_iterator(s2, n), + lt_() + ); } static SPROUT_CONSTEXPR std::size_t length(char_type const* s) { return !*s ? 0 @@ -97,27 +104,27 @@ namespace sprout { #if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION template static SPROUT_CONSTEXPR int compare(char_type const* s1, ConstIterator s2, std::size_t n) { - return !n ? 0 - : lt(*s1, *s2) ? -1 - : lt(*s2, *s1) ? 1 - : compare(s1 + 1, s2 + 1, n - 1) - ; + return sprout::tristate_lexicographical_compare( + sprout::as_iterator(s1), sprout::as_iterator(s1, n), + s2, s2 + n, + lt_() + ); } template static SPROUT_CONSTEXPR int compare(ConstIterator s1, char_type const* s2, std::size_t n) { - return !n ? 0 - : lt(*s1, *s2) ? -1 - : lt(*s2, *s1) ? 1 - : compare(s1 + 1, s2 + 1, n - 1) - ; + return sprout::tristate_lexicographical_compare( + s1, s1 + n, + sprout::as_iterator(s2), sprout::as_iterator(s2, n), + lt_() + ); } template static SPROUT_CONSTEXPR int compare(ConstIterator1 s1, ConstIterator2 s2, std::size_t n) { - return !n ? 0 - : lt(*s1, *s2) ? -1 - : lt(*s2, *s1) ? 1 - : compare(s1 + 1, s2 + 1, n - 1) - ; + return sprout::tristate_lexicographical_compare( + s1, s1 + n, + s2, s2 + n, + lt_() + ); } template static SPROUT_CONSTEXPR std::size_t length(ConstIterator s) {