From 750e3b944d2bcb05a6ba7af90491d323edb0dabf Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Mon, 17 Dec 2012 00:14:24 +0900 Subject: [PATCH] fix recursion depth: lexicographical_compare --- .../test/lexicographical_compare.cpp | 160 ++++++++++++++++++ libs/algorithm/test/non_modifying.cpp | 2 + sprout/algorithm/find_end.hpp | 7 + sprout/algorithm/lexicographical_compare.hpp | 105 +++++++++++- 4 files changed, 266 insertions(+), 8 deletions(-) create mode 100644 libs/algorithm/test/lexicographical_compare.cpp diff --git a/libs/algorithm/test/lexicographical_compare.cpp b/libs/algorithm/test/lexicographical_compare.cpp new file mode 100644 index 00000000..4d0b6f04 --- /dev/null +++ b/libs/algorithm/test/lexicographical_compare.cpp @@ -0,0 +1,160 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_LEXICOGRAPHICAL_COMPARE_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_LEXICOGRAPHICAL_COMPARE_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_lexicographical_compare_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; + SPROUT_STATIC_CONSTEXPR auto arr2 = array{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; + SPROUT_STATIC_CONSTEXPR auto arr3 = array{{1, 2, 3, 4, 5, 6, 7, 1, 2, 3}}; + SPROUT_STATIC_CONSTEXPR auto arr4 = array{{1, 2, 3, 4, 5, 6, 7, 11, 12, 13}}; + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr4), + sprout::end(arr4) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr4), + sprout::end(arr4) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::begin(arr2) + 5 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr4), + sprout::end(arr4), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::end(arr2), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr4), + sprout::end(arr4), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::lexicographical_compare( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::begin(arr2) + 5, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_lexicographical_compare_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_LEXICOGRAPHICAL_COMPARE_CPP diff --git a/libs/algorithm/test/non_modifying.cpp b/libs/algorithm/test/non_modifying.cpp index 0e39abbb..3e95cc59 100644 --- a/libs/algorithm/test/non_modifying.cpp +++ b/libs/algorithm/test/non_modifying.cpp @@ -40,6 +40,7 @@ #include "./min_element.cpp" #include "./max_element.cpp" #include "./minmax_element.cpp" +#include "./lexicographical_compare.cpp" #ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP # undef TESTSPR_CPP_INCLUDE @@ -81,6 +82,7 @@ namespace testspr { testspr::algorithm_min_element_test(); testspr::algorithm_max_element_test(); testspr::algorithm_minmax_element_test(); + testspr::algorithm_lexicographical_compare_test(); } } // namespace testspr diff --git a/sprout/algorithm/find_end.hpp b/sprout/algorithm/find_end.hpp index 213fdffb..1f36d02e 100644 --- a/sprout/algorithm/find_end.hpp +++ b/sprout/algorithm/find_end.hpp @@ -107,6 +107,13 @@ namespace sprout { } // namespace detail // 25.2.6 Find end + // + // recursion depth: + // [first1, last1) is RandomAccessIterator -> O(log N1) + // otherwise -> O(N1) + // [first2, last2) is RandomAccessIterator -> O(log N2) + // otherwise -> O(N2) + // template inline SPROUT_CONSTEXPR ForwardIterator1 find_end( diff --git a/sprout/algorithm/lexicographical_compare.hpp b/sprout/algorithm/lexicographical_compare.hpp index 550dc0e9..676df525 100644 --- a/sprout/algorithm/lexicographical_compare.hpp +++ b/sprout/algorithm/lexicographical_compare.hpp @@ -3,12 +3,104 @@ #include #include -#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT +#include +#include +#include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) + namespace detail { + template + inline SPROUT_CONSTEXPR bool + lexicographical_compare_impl_ra_2( + RandomAccessIterator1 last1, RandomAccessIterator2 last2, Compare comp, + sprout::pair const& found + ) + { + return found.second == last2 ? false + : found.first == last1 || comp(*found.first, *found.second) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + 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::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::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 bool + 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::lexicographical_compare_impl_ra_2( + last1, last2, comp, + sprout::detail::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 bool + lexicographical_compare( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, Compare comp, + std::random_access_iterator_tag* + ) + { + return first2 == last2 ? false + : first1 == last1 ? true + : sprout::detail::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 bool + lexicographical_compare_impl(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) { + return first2 == last2 ? false + : first1 == last1 || comp(*first1, *first2) ? true + : comp(*first2, *first1) ? false + : sprout::detail::lexicographical_compare_impl(sprout::next(first1), last1, sprout::next(first2), last2, comp) + ; + } + template + inline SPROUT_CONSTEXPR bool + lexicographical_compare( + InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp, + void* + ) + { + return sprout::detail::lexicographical_compare_impl(first1, last1, first2, last2, comp); + } + } //namespace detail // 25.4.8 Lexicographical comparison + // + // recursion depth: + // [first1, last1), [first2, last2) are RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool lexicographical_compare( @@ -17,11 +109,8 @@ namespace sprout { Compare comp ) { - return first2 == last2 ? false - : first1 == last1 || comp(*first1, *first2) ? true - : comp(*first2, *first1) ? false - : sprout::lexicographical_compare(sprout::next(first1), last1, sprout::next(first2), last2, comp) - ; + typedef typename sprout::common_iterator_category::type* category; + return sprout::detail::lexicographical_compare(first1, last1, first2, last2, comp, category()); } template @@ -33,7 +122,7 @@ namespace sprout { { return sprout::lexicographical_compare( first1, last1, first2, last2, - NS_SSCRISK_CEL_OR_SPROUT::less() + sprout::less<>() ); } } // namespace sprout