From 84508d6a6cc50948dc3801573f50a34e78248bed Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 12 Jan 2013 03:41:13 +0900 Subject: [PATCH] fix recursion depth: all algorithms --- libs/algorithm/test/all_of_equal.cpp | 36 +++++ libs/algorithm/test/any_of_equal.cpp | 68 +++++++++ libs/algorithm/test/is_decreasing.cpp | 34 +++++ libs/algorithm/test/is_increasing.cpp | 34 +++++ .../algorithm/test/is_strictly_decreasing.cpp | 62 +++++++++ .../algorithm/test/is_strictly_increasing.cpp | 62 +++++++++ libs/algorithm/test/none_of_equal.cpp | 68 +++++++++ libs/algorithm/test/one_of_equal.cpp | 68 +++++++++ sprout/algorithm/all_of_equal.hpp | 52 +++++-- sprout/algorithm/any_of_equal.hpp | 52 +++++-- sprout/algorithm/is_decreasing.hpp | 3 +- sprout/algorithm/is_increasing.hpp | 3 +- sprout/algorithm/is_strictly_decreasing.hpp | 3 +- sprout/algorithm/is_strictly_increasing.hpp | 3 +- sprout/algorithm/lexicographical_compare.hpp | 6 +- sprout/algorithm/none_of_equal.hpp | 52 +++++-- sprout/algorithm/one_of_equal.hpp | 120 ++++++++++++++-- .../tristate_lexicographical_compare.hpp | 131 ++++++++++++++---- 18 files changed, 781 insertions(+), 76 deletions(-) diff --git a/libs/algorithm/test/all_of_equal.cpp b/libs/algorithm/test/all_of_equal.cpp index 7233a536..f48a3ab9 100644 --- a/libs/algorithm/test/all_of_equal.cpp +++ b/libs/algorithm/test/all_of_equal.cpp @@ -28,6 +28,42 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(result); } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::all_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + 1 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::all_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + 1 + ); + TESTSPR_BOTH_ASSERT(result); + } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::all_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + 1 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::all_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + 1 + ); + TESTSPR_BOTH_ASSERT(result); + } +#endif } } } // namespace testspr diff --git a/libs/algorithm/test/any_of_equal.cpp b/libs/algorithm/test/any_of_equal.cpp index 2026b344..f9c7adb2 100644 --- a/libs/algorithm/test/any_of_equal.cpp +++ b/libs/algorithm/test/any_of_equal.cpp @@ -44,6 +44,74 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(!result); } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + 10 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + 11 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + 10 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + 11 + ); + TESTSPR_BOTH_ASSERT(!result); + } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + 10 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + 11 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + 10 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::any_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + 11 + ); + TESTSPR_BOTH_ASSERT(!result); + } +#endif } } } // namespace testspr diff --git a/libs/algorithm/test/is_decreasing.cpp b/libs/algorithm/test/is_decreasing.cpp index e4617b8a..74f0a1c0 100644 --- a/libs/algorithm/test/is_decreasing.cpp +++ b/libs/algorithm/test/is_decreasing.cpp @@ -26,6 +26,40 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(result); } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_decreasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_decreasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } +#endif + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_decreasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_decreasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } +#endif } } } // namespace testspr diff --git a/libs/algorithm/test/is_increasing.cpp b/libs/algorithm/test/is_increasing.cpp index 2440b9f6..55b29446 100644 --- a/libs/algorithm/test/is_increasing.cpp +++ b/libs/algorithm/test/is_increasing.cpp @@ -26,6 +26,40 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(result); } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_increasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_increasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } +#endif + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_increasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_increasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } +#endif } } } // namespace testspr diff --git a/libs/algorithm/test/is_strictly_decreasing.cpp b/libs/algorithm/test/is_strictly_decreasing.cpp index 863e1e56..357ffa9d 100644 --- a/libs/algorithm/test/is_strictly_decreasing.cpp +++ b/libs/algorithm/test/is_strictly_decreasing.cpp @@ -41,6 +41,68 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(!result); } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_forward(sprout::begin(arr2)), + testspr::reduct_forward(sprout::end(arr2)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_forward(sprout::begin(arr2)), + testspr::reduct_forward(sprout::begin(arr2) + 5) + ); + TESTSPR_BOTH_ASSERT(!result); + } +#endif + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::end(arr2)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_decreasing( + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::begin(arr2) + 5) + ); + TESTSPR_BOTH_ASSERT(!result); + } +#endif } } } // namespace testspr diff --git a/libs/algorithm/test/is_strictly_increasing.cpp b/libs/algorithm/test/is_strictly_increasing.cpp index 4c38c8cb..39961399 100644 --- a/libs/algorithm/test/is_strictly_increasing.cpp +++ b/libs/algorithm/test/is_strictly_increasing.cpp @@ -41,6 +41,68 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(!result); } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_forward(sprout::begin(arr2)), + testspr::reduct_forward(sprout::end(arr2)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_forward(sprout::begin(arr1)), + testspr::reduct_forward(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_forward(sprout::begin(arr2)), + testspr::reduct_forward(sprout::begin(arr2) + 5) + ); + TESTSPR_BOTH_ASSERT(!result); + } +#endif + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::end(arr2)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_strictly_increasing( + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::begin(arr2) + 5) + ); + TESTSPR_BOTH_ASSERT(!result); + } +#endif } } } // namespace testspr diff --git a/libs/algorithm/test/none_of_equal.cpp b/libs/algorithm/test/none_of_equal.cpp index 07068150..647d61a1 100644 --- a/libs/algorithm/test/none_of_equal.cpp +++ b/libs/algorithm/test/none_of_equal.cpp @@ -44,6 +44,74 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(result); } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + 10 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + 11 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + 10 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + 11 + ); + TESTSPR_BOTH_ASSERT(result); + } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + 10 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + 11 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + 10 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::none_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + 11 + ); + TESTSPR_BOTH_ASSERT(result); + } +#endif } } } // namespace testspr diff --git a/libs/algorithm/test/one_of_equal.cpp b/libs/algorithm/test/one_of_equal.cpp index a8479899..ba2d4931 100644 --- a/libs/algorithm/test/one_of_equal.cpp +++ b/libs/algorithm/test/one_of_equal.cpp @@ -44,6 +44,74 @@ namespace testspr { ); TESTSPR_BOTH_ASSERT(!result); } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + 5 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + 10 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + 5 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + 10 + ); + TESTSPR_BOTH_ASSERT(!result); + } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + 5 + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + 10 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + 5 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::one_of_equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + 10 + ); + TESTSPR_BOTH_ASSERT(!result); + } +#endif } } } // namespace testspr diff --git a/sprout/algorithm/all_of_equal.hpp b/sprout/algorithm/all_of_equal.hpp index a8533f82..52044c13 100644 --- a/sprout/algorithm/all_of_equal.hpp +++ b/sprout/algorithm/all_of_equal.hpp @@ -2,8 +2,11 @@ #define SPROUT_ALGORITHM_ALL_OF_EQUAL_HPP #include +#include #include #include +#include +#include namespace sprout { namespace detail { @@ -26,7 +29,10 @@ namespace sprout { ; } template - inline SPROUT_CONSTEXPR bool + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value, + bool + >::type all_of_equal( RandomAccessIterator first, RandomAccessIterator last, T const& value, std::random_access_iterator_tag* @@ -38,10 +44,40 @@ namespace sprout { } template - inline SPROUT_CONSTEXPR bool - all_of_equal_impl(InputIterator first, InputIterator last, T const& value) { - return first == last ? true - : *first == value && sprout::detail::all_of_equal_impl(sprout::next(first), last, value) + inline SPROUT_CONSTEXPR sprout::pair + all_of_equal_impl_1( + sprout::pair const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return !current.second || current.first == last ? current + : n == 1 ? *current.first == value ? type(sprout::next(current.first), true) : type(current.first, false) + : sprout::detail::all_of_equal_impl_1( + sprout::detail::all_of_equal_impl_1( + current, + last, value, n / 2 + ), + last, value, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + all_of_equal_impl( + sprout::pair const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return !current.second || current.first == last ? current + : sprout::detail::all_of_equal_impl( + sprout::detail::all_of_equal_impl_1( + current, + last, value, n + ), + last, value, n * 2 + ) ; } template @@ -51,7 +87,8 @@ namespace sprout { void* ) { - return sprout::detail::all_of_equal_impl(first, last, value); + typedef sprout::pair type; + return sprout::detail::all_of_equal_impl(type(first, true), last, value, 1).second; } } // namespace detail @@ -59,8 +96,7 @@ namespace sprout { // all_of_equal // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool diff --git a/sprout/algorithm/any_of_equal.hpp b/sprout/algorithm/any_of_equal.hpp index 4429eaff..05469673 100644 --- a/sprout/algorithm/any_of_equal.hpp +++ b/sprout/algorithm/any_of_equal.hpp @@ -2,8 +2,11 @@ #define SPROUT_ALGORITHM_ANY_OF_EQUAL_HPP #include +#include #include #include +#include +#include namespace sprout { namespace detail { @@ -26,7 +29,10 @@ namespace sprout { ; } template - inline SPROUT_CONSTEXPR bool + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value, + bool + >::type any_of_equal( RandomAccessIterator first, RandomAccessIterator last, T const& value, std::random_access_iterator_tag* @@ -38,10 +44,40 @@ namespace sprout { } template - inline SPROUT_CONSTEXPR bool - any_of_equal_impl(InputIterator first, InputIterator last, T const& value) { - return first == last ? false - : *first == value || sprout::detail::any_of_equal_impl(sprout::next(first), last, value) + inline SPROUT_CONSTEXPR sprout::pair + any_of_equal_impl_1( + sprout::pair const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.second || current.first == last ? current + : n == 1 ? *current.first == value ? type(current.first, true) : type(sprout::next(current.first), false) + : sprout::detail::any_of_equal_impl_1( + sprout::detail::any_of_equal_impl_1( + current, + last, value, n / 2 + ), + last, value, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + any_of_equal_impl( + sprout::pair const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.second || current.first == last ? current + : sprout::detail::any_of_equal_impl( + sprout::detail::any_of_equal_impl_1( + current, + last, value, n + ), + last, value, n * 2 + ) ; } template @@ -51,7 +87,8 @@ namespace sprout { void* ) { - return sprout::detail::any_of_equal_impl(first, last, value); + typedef sprout::pair type; + return sprout::detail::any_of_equal_impl(type(first, false), last, value, 1).second; } } // namespace detail @@ -59,8 +96,7 @@ namespace sprout { // any_of_equal // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool diff --git a/sprout/algorithm/is_decreasing.hpp b/sprout/algorithm/is_decreasing.hpp index e674589b..577f2eeb 100644 --- a/sprout/algorithm/is_decreasing.hpp +++ b/sprout/algorithm/is_decreasing.hpp @@ -11,8 +11,7 @@ namespace sprout { // is_decreasing // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool diff --git a/sprout/algorithm/is_increasing.hpp b/sprout/algorithm/is_increasing.hpp index 247d3f25..26fe26b7 100644 --- a/sprout/algorithm/is_increasing.hpp +++ b/sprout/algorithm/is_increasing.hpp @@ -11,8 +11,7 @@ namespace sprout { // is_increasing // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool diff --git a/sprout/algorithm/is_strictly_decreasing.hpp b/sprout/algorithm/is_strictly_decreasing.hpp index cd183f2e..16c1be38 100644 --- a/sprout/algorithm/is_strictly_decreasing.hpp +++ b/sprout/algorithm/is_strictly_decreasing.hpp @@ -11,8 +11,7 @@ namespace sprout { // is_strictly_decreasing // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool diff --git a/sprout/algorithm/is_strictly_increasing.hpp b/sprout/algorithm/is_strictly_increasing.hpp index 07f668a3..4da01763 100644 --- a/sprout/algorithm/is_strictly_increasing.hpp +++ b/sprout/algorithm/is_strictly_increasing.hpp @@ -11,8 +11,7 @@ namespace sprout { // is_strictly_increasing // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool diff --git a/sprout/algorithm/lexicographical_compare.hpp b/sprout/algorithm/lexicographical_compare.hpp index 0bc171f8..bb836bd4 100644 --- a/sprout/algorithm/lexicographical_compare.hpp +++ b/sprout/algorithm/lexicographical_compare.hpp @@ -13,11 +13,11 @@ namespace sprout { namespace detail { - template + template inline SPROUT_CONSTEXPR bool lexicographical_compare_impl_check( - RandomAccessIterator1 last1, RandomAccessIterator2 last2, Compare comp, - sprout::pair const& found + InputIterator1 last1, InputIterator2 last2, Compare comp, + sprout::pair const& found ) { return found.second == last2 ? false diff --git a/sprout/algorithm/none_of_equal.hpp b/sprout/algorithm/none_of_equal.hpp index 8a1995a8..07203205 100644 --- a/sprout/algorithm/none_of_equal.hpp +++ b/sprout/algorithm/none_of_equal.hpp @@ -2,8 +2,11 @@ #define SPROUT_ALGORITHM_NONE_OF_EQUAL_HPP #include +#include #include #include +#include +#include namespace sprout { namespace detail { @@ -26,7 +29,10 @@ namespace sprout { ; } template - inline SPROUT_CONSTEXPR bool + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value, + bool + >::type none_of_equal( RandomAccessIterator first, RandomAccessIterator last, T const& value, std::random_access_iterator_tag* @@ -38,10 +44,40 @@ namespace sprout { } template - inline SPROUT_CONSTEXPR bool - none_of_equal_impl(InputIterator first, InputIterator last, T const& value) { - return first == last ? true - : !(*first == value) && sprout::detail::none_of_equal_impl(sprout::next(first), last, value) + inline SPROUT_CONSTEXPR sprout::pair + none_of_equal_impl_1( + sprout::pair const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return !current.second || current.first == last ? current + : n == 1 ? !(*current.first == value) ? type(sprout::next(current.first), true) : type(current.first, false) + : sprout::detail::none_of_equal_impl_1( + sprout::detail::none_of_equal_impl_1( + current, + last, value, n / 2 + ), + last, value, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + none_of_equal_impl( + sprout::pair const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return !current.second || current.first == last ? current + : sprout::detail::none_of_equal_impl( + sprout::detail::none_of_equal_impl_1( + current, + last, value, n + ), + last, value, n * 2 + ) ; } template @@ -51,7 +87,8 @@ namespace sprout { void* ) { - return sprout::detail::none_of_equal_impl(first, last, value); + typedef sprout::pair type; + return sprout::detail::none_of_equal_impl(type(first, true), last, value, 1).second; } } // namespace detail @@ -59,8 +96,7 @@ namespace sprout { // none_of_equal // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool diff --git a/sprout/algorithm/one_of_equal.hpp b/sprout/algorithm/one_of_equal.hpp index 0362fbb1..f47d4b88 100644 --- a/sprout/algorithm/one_of_equal.hpp +++ b/sprout/algorithm/one_of_equal.hpp @@ -1,19 +1,118 @@ #ifndef SPROUT_ALGORITHM_ONE_OF_EQUAL_HPP #define SPROUT_ALGORITHM_ONE_OF_EQUAL_HPP +#include +#include #include #include -#include -#include +#include +#include namespace sprout { namespace detail { + template + inline SPROUT_CONSTEXPR bool + one_of_equal_impl_ra_1( + RandomAccessIterator first, RandomAccessIterator last, T const& value, + typename std::iterator_traits::difference_type pivot + ) + { + return pivot == 0 ? !(*first == value) + : sprout::detail::one_of_equal_impl_ra_1( + first, sprout::next(first, pivot), value, + pivot / 2 + ) + && sprout::detail::one_of_equal_impl_ra_1( + sprout::next(first, pivot), last, value, + (sprout::distance(first, last) - pivot) / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR bool + one_of_equal_impl_ra( + RandomAccessIterator first, RandomAccessIterator last, T const& value, + typename std::iterator_traits::difference_type pivot + ) + { + return pivot == 0 ? *first == value + : sprout::detail::one_of_equal_impl_ra( + first, sprout::next(first, pivot), value, + pivot / 2 + ) + ? sprout::detail::one_of_equal_impl_ra_1( + sprout::next(first, pivot), last, value, + (sprout::distance(first, last) - pivot) / 2 + ) + : sprout::detail::one_of_equal_impl_ra( + sprout::next(first, pivot), last, value, + (sprout::distance(first, last) - pivot) / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value, + bool + >::type + one_of_equal( + RandomAccessIterator first, RandomAccessIterator last, T const& value, + std::random_access_iterator_tag* + ) + { + return first == last ? true + : sprout::detail::one_of_equal_impl_ra(first, last, value, sprout::distance(first, last) / 2) + ; + } + + template + inline SPROUT_CONSTEXPR sprout::pair::difference_type> + one_of_equal_impl_1( + sprout::pair::difference_type> const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair::difference_type> type; + return current.second > 1 || current.first == last ? current + : n == 1 ? current.second == 0 + ? type(sprout::next(current.first), *current.first == value ? 1 : 0) + : !(*current.first == value) ? type(sprout::next(current.first), 1) : type(current.first, 2) + : sprout::detail::one_of_equal_impl_1( + sprout::detail::one_of_equal_impl_1( + current, + last, value, n / 2 + ), + last, value, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair::difference_type> + one_of_equal_impl( + sprout::pair::difference_type> const& current, + InputIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair::difference_type> type; + return current.second > 1 || current.first == last ? current + : sprout::detail::one_of_equal_impl( + sprout::detail::one_of_equal_impl_1( + current, + last, value, n + ), + last, value, n * 2 + ) + ; + } template inline SPROUT_CONSTEXPR bool - one_of_equal_impl(InputIterator found, InputIterator last, T const& value) { - return found != last - && sprout::none_of_equal(sprout::next(found), last, value) - ; + one_of_equal( + InputIterator first, InputIterator last, T const& value, + void* + ) + { + typedef sprout::pair::difference_type> type; + return sprout::detail::one_of_equal_impl(type(first, 0), last, value, 1).second == 1; } } // namespace detail @@ -21,16 +120,13 @@ namespace sprout { // one_of_equal // // recursion depth: - // [first, last) is RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log N) // template inline SPROUT_CONSTEXPR bool one_of_equal(InputIterator first, InputIterator last, T const& value) { - return sprout::detail::one_of_equal_impl( - sprout::find(first, last, value), last, - value - ); + typedef typename std::iterator_traits::iterator_category* category; + return sprout::detail::one_of_equal(first, last, value, category()); } } // namespace sprout diff --git a/sprout/algorithm/tristate_lexicographical_compare.hpp b/sprout/algorithm/tristate_lexicographical_compare.hpp index fcdcf752..8ceea0c3 100644 --- a/sprout/algorithm/tristate_lexicographical_compare.hpp +++ b/sprout/algorithm/tristate_lexicographical_compare.hpp @@ -1,8 +1,11 @@ #ifndef SPROUT_ALGORITHM_TRISTATE_LEXICOGRAPHICAL_COMPARE_HPP #define SPROUT_ALGORITHM_TRISTATE_LEXICOGRAPHICAL_COMPARE_HPP +#include +#include #include #include +#include #include #include #include @@ -10,11 +13,11 @@ namespace sprout { namespace detail { - template + template inline SPROUT_CONSTEXPR int - tristate_lexicographical_compare_impl_ra_2( - RandomAccessIterator1 last1, RandomAccessIterator2 last2, Compare comp, - sprout::pair const& found + tristate_lexicographical_compare_impl_check( + InputIterator1 last1, InputIterator2 last2, Compare comp, + sprout::pair const& found ) { return found.second == last2 ? (found.first == last1 ? 0 : 1) @@ -24,6 +27,7 @@ namespace sprout { : 0 ; } + template inline SPROUT_CONSTEXPR sprout::pair tristate_lexicographical_compare_impl_ra_1( @@ -53,7 +57,7 @@ namespace sprout { ) { typedef sprout::pair found_type; - return sprout::detail::tristate_lexicographical_compare_impl_ra_2( + return sprout::detail::tristate_lexicographical_compare_impl_check( last1, last2, comp, sprout::detail::tristate_lexicographical_compare_impl_ra_1( first1, sprout::next(first1, size), first2, sprout::next(first2, size), comp, @@ -62,7 +66,10 @@ namespace sprout { ); } template - inline SPROUT_CONSTEXPR int + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value, + int + >::type tristate_lexicographical_compare( RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, Compare comp, std::random_access_iterator_tag* @@ -77,14 +84,45 @@ namespace sprout { ; } - // 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) + inline SPROUT_CONSTEXPR sprout::pair + tristate_lexicographical_compare_impl_1( + sprout::pair current, + InputIterator1 last1, InputIterator2 last2, Compare comp, + typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.second == last2 || current.first == last1 ? current + : n == 1 ? comp(*current.first, *current.second) ? type(last1, current.second) + : comp(*current.second, *current.first) ? type(current.first, last2) + : type(sprout::next(current.first), sprout::next(current.second)) + : sprout::detail::tristate_lexicographical_compare_impl_1( + sprout::detail::tristate_lexicographical_compare_impl_1( + current, + last1, last2, comp, n / 2 + ), + last1, last2, comp, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + tristate_lexicographical_compare_impl( + sprout::pair current, + InputIterator1 last1, InputIterator2 last2, Compare comp, + typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.second == last2 || current.first == last1 ? current + : sprout::detail::tristate_lexicographical_compare_impl( + sprout::detail::tristate_lexicographical_compare_impl_1( + current, + last1, last2, comp, n + ), + last1, last2, comp, n * 2 + ) ; } template @@ -94,7 +132,11 @@ namespace sprout { void* ) { - return sprout::detail::tristate_lexicographical_compare_impl(first1, last1, first2, last2, comp); + typedef sprout::pair type; + return sprout::detail::tristate_lexicographical_compare_impl_check( + last1, last2, comp, + sprout::detail::tristate_lexicographical_compare_impl(type(first1, first2), last1, last2, comp, 1) + ); } } // namespace detail @@ -102,8 +144,7 @@ namespace sprout { // tristate_lexicographical_compare // // recursion depth: - // [first1, last1), [first2, last2) are RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log(N1+N2)) // template inline SPROUT_CONSTEXPR int @@ -209,29 +250,62 @@ namespace sprout { } template - inline SPROUT_CONSTEXPR int - tristate_lexicographical_compare_2_impl( - InputIterator1 first1, InputIterator1 last1, T1 const& delim1, - InputIterator2 first2, InputIterator2 last2, T2 const& delim2, - Compare comp + inline SPROUT_CONSTEXPR sprout::pair + tristate_lexicographical_compare_impl_1( + sprout::pair current, + InputIterator1 last1, T1 const& delim1, InputIterator2 last2, T2 const& delim2, Compare comp, + typename std::iterator_traits::difference_type n ) { - return first2 == last2 || (!comp(*first2, delim2) && !comp(delim2, *first2)) ? (first1 == last1 || (!comp(*first1, delim1) && !comp(delim1, *first1)) ? 0 : 1) - : first1 == last1 || (!comp(*first1, delim1) && !comp(delim1, *first1)) || comp(*first1, *first2) ? -1 - : comp(*first2, *first1) ? 1 - : sprout::detail::tristate_lexicographical_compare_2_impl(sprout::next(first1), last1, delim1, sprout::next(first2), last2, delim2, comp) + typedef sprout::pair type; + return current.second == last2 || current.first == last1 ? current + : !comp(*current.second, delim2) && !comp(delim2, *current.second) ? type(!comp(*current.first, delim1) && !comp(delim1, *current.first) ? last1 : current.first, last2) + : !comp(*current.first, delim1) && !comp(delim1, *current.first) ? type(last1, current.second) + : n == 1 ? comp(*current.first, *current.second) ? type(last1, current.second) + : comp(*current.second, *current.first) ? type(current.first, last2) + : type(sprout::next(current.first), sprout::next(current.second)) + : sprout::detail::tristate_lexicographical_compare_impl_1( + sprout::detail::tristate_lexicographical_compare_impl_1( + current, + last1, delim1, last2, delim2, comp, n / 2 + ), + last1, delim1, last2, delim2, comp, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + tristate_lexicographical_compare_impl( + sprout::pair current, + InputIterator1 last1, T1 const& delim1, InputIterator2 last2, T2 const& delim2, Compare comp, + typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.second == last2 || current.first == last1 ? current + : sprout::detail::tristate_lexicographical_compare_impl( + sprout::detail::tristate_lexicographical_compare_impl_1( + current, + last1, delim1, last2, delim2, comp, n + ), + last1, delim1, last2, delim2, comp, n * 2 + ) ; } template inline SPROUT_CONSTEXPR int - tristate_lexicographical_compare_2( + tristate_lexicographical_compare( InputIterator1 first1, InputIterator1 last1, T1 const& delim1, InputIterator2 first2, InputIterator2 last2, T2 const& delim2, Compare comp, void* ) { - return sprout::detail::tristate_lexicographical_compare_2_impl(first1, last1, delim1, first2, last2, delim2, comp); + typedef sprout::pair type; + return sprout::detail::tristate_lexicographical_compare_impl_check( + last1, last2, comp, + sprout::detail::tristate_lexicographical_compare_impl(type(first1, first2), last1, delim1, last2, delim2, comp, 1) + ); } } // namespace detail @@ -239,8 +313,7 @@ namespace sprout { // tristate_lexicographical_compare // // recursion depth: - // [first1, last1), [first2, last2) are RandomAccessIterator -> O(log N) - // otherwise -> O(N) + // O(log(N1+N2)) // template inline SPROUT_CONSTEXPR int