From 0201107eec41959fcb48c1338a68a23b77d4a9af Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 15 Dec 2012 23:48:52 +0900 Subject: [PATCH] fix recursion depth: includes --- libs/algorithm/test/binary_search.cpp | 41 ++++++++++ libs/algorithm/test/equal_range.cpp | 45 +++++++++++ libs/algorithm/test/find_first_of.cpp | 2 +- libs/algorithm/test/includes.cpp | 103 ++++++++++++++++++++++++++ libs/algorithm/test/lower_bound.cpp | 41 ++++++++++ libs/algorithm/test/non_modifying.cpp | 10 +++ libs/algorithm/test/upper_bound.cpp | 41 ++++++++++ sprout/algorithm/binary_search.hpp | 48 ++++++------ sprout/algorithm/equal_range.hpp | 21 ++++-- sprout/algorithm/includes.hpp | 97 +++++++++++++++++++----- sprout/algorithm/is_sorted.hpp | 5 ++ sprout/algorithm/is_sorted_until.hpp | 5 ++ sprout/algorithm/lower_bound.hpp | 27 ++++--- sprout/algorithm/upper_bound.hpp | 27 ++++--- 14 files changed, 442 insertions(+), 71 deletions(-) create mode 100644 libs/algorithm/test/binary_search.cpp create mode 100644 libs/algorithm/test/equal_range.cpp create mode 100644 libs/algorithm/test/includes.cpp create mode 100644 libs/algorithm/test/lower_bound.cpp create mode 100644 libs/algorithm/test/upper_bound.cpp diff --git a/libs/algorithm/test/binary_search.cpp b/libs/algorithm/test/binary_search.cpp new file mode 100644 index 00000000..5a7176c9 --- /dev/null +++ b/libs/algorithm/test/binary_search.cpp @@ -0,0 +1,41 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_BINARY_SEARCH_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_BINARY_SEARCH_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_binary_search_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5, 6, 7, 7, 7, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::binary_search( + sprout::begin(arr1), + sprout::end(arr1), + 7 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::binary_search( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 7, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_binary_search_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_BINARY_SEARCH_CPP diff --git a/libs/algorithm/test/equal_range.cpp b/libs/algorithm/test/equal_range.cpp new file mode 100644 index 00000000..2b659b07 --- /dev/null +++ b/libs/algorithm/test/equal_range.cpp @@ -0,0 +1,45 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_EQUAL_RANGE_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_EQUAL_RANGE_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_equal_range_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5, 6, 7, 7, 7, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::equal_range( + sprout::begin(arr1), + sprout::end(arr1), + 7 + ); + TESTSPR_BOTH_ASSERT(found.first == sprout::begin(arr1) + 6); + TESTSPR_BOTH_ASSERT(found.second == sprout::begin(arr1) + 9); + TESTSPR_BOTH_ASSERT(found.second - found.first == 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::equal_range( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 7, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found.first == sprout::begin(arr1) + 5); + TESTSPR_BOTH_ASSERT(found.second == sprout::begin(arr1) + 5); + TESTSPR_BOTH_ASSERT(found.second - found.first == 0); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_equal_range_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_EQUAL_RANGE_CPP diff --git a/libs/algorithm/test/find_first_of.cpp b/libs/algorithm/test/find_first_of.cpp index c4034212..df9d0ddb 100644 --- a/libs/algorithm/test/find_first_of.cpp +++ b/libs/algorithm/test/find_first_of.cpp @@ -12,7 +12,7 @@ namespace testspr { { SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; SPROUT_STATIC_CONSTEXPR auto arr2 = array{{4, 5, 6}}; - SPROUT_STATIC_CONSTEXPR auto arr3 = array{{11, 12 ,13}}; + SPROUT_STATIC_CONSTEXPR auto arr3 = array{{11, 12, 13}}; { SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( diff --git a/libs/algorithm/test/includes.cpp b/libs/algorithm/test/includes.cpp new file mode 100644 index 00000000..9005af25 --- /dev/null +++ b/libs/algorithm/test/includes.cpp @@ -0,0 +1,103 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_INCLUDES_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_INCLUDES_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_includes_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{{4, 5, 6}}; + SPROUT_STATIC_CONSTEXPR auto arr3 = array{{1, 2, 12}}; + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::includes( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::includes( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::includes( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::includes( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(!result); + } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::includes( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::includes( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::includes( + 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::includes( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_includes_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_INCLUDES_CPP diff --git a/libs/algorithm/test/lower_bound.cpp b/libs/algorithm/test/lower_bound.cpp new file mode 100644 index 00000000..5442d142 --- /dev/null +++ b/libs/algorithm/test/lower_bound.cpp @@ -0,0 +1,41 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_LOWER_BOUND_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_LOWER_BOUND_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_lower_bound_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5, 6, 7, 7, 7, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::lower_bound( + sprout::begin(arr1), + sprout::end(arr1), + 7 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 6); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::lower_bound( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 7, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_lower_bound_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_LOWER_BOUND_CPP diff --git a/libs/algorithm/test/non_modifying.cpp b/libs/algorithm/test/non_modifying.cpp index c6e391db..ce492e87 100644 --- a/libs/algorithm/test/non_modifying.cpp +++ b/libs/algorithm/test/non_modifying.cpp @@ -27,6 +27,11 @@ #include "./partition_point.cpp" #include "./is_sorted.cpp" #include "./is_sorted_until.cpp" +#include "./lower_bound.cpp" +#include "./upper_bound.cpp" +#include "./equal_range.cpp" +#include "./binary_search.cpp" +#include "./includes.cpp" #ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP # undef TESTSPR_CPP_INCLUDE @@ -55,6 +60,11 @@ namespace testspr { testspr::algorithm_partition_point_test(); testspr::algorithm_is_sorted_test(); testspr::algorithm_is_sorted_until_test(); + testspr::algorithm_lower_bound_test(); + testspr::algorithm_upper_bound_test(); + testspr::algorithm_equal_range_test(); + testspr::algorithm_binary_search_test(); + testspr::algorithm_includes_test(); } } // namespace testspr diff --git a/libs/algorithm/test/upper_bound.cpp b/libs/algorithm/test/upper_bound.cpp new file mode 100644 index 00000000..8f846bd3 --- /dev/null +++ b/libs/algorithm/test/upper_bound.cpp @@ -0,0 +1,41 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_UPPER_BOUND_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_UPPER_BOUND_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_upper_bound_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5, 6, 7, 7, 7, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::upper_bound( + sprout::begin(arr1), + sprout::end(arr1), + 7 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 9); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::upper_bound( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 7, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_upper_bound_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_UPPER_BOUND_CPP diff --git a/sprout/algorithm/binary_search.hpp b/sprout/algorithm/binary_search.hpp index f2793160..45f1add6 100644 --- a/sprout/algorithm/binary_search.hpp +++ b/sprout/algorithm/binary_search.hpp @@ -2,37 +2,37 @@ #define SPROUT_ALGORITHM_BINARY_SEARCH_HPP #include -#include -#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) + namespace detail { + template + inline SPROUT_CONSTEXPR bool + binary_search_impl(ForwardIterator first, ForwardIterator last, T const& value, Compare comp) { + return (first != last && !comp(value, *first)); + } + } // namespace detail // 25.4.3.4 binary_search - template - inline SPROUT_CONSTEXPR bool - binary_search(ForwardIterator first, ForwardIterator last, T const& value) { - return first == last ? false - : sprout::next(first) == last ? !(*first < value) && !(value < *first) ? true : false - : *sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2) < value - ? sprout::binary_search(sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), last, value) - : value < *sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last)) / 2 - ? sprout::binary_search(first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), value) - : true - ; - } - + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool binary_search(ForwardIterator first, ForwardIterator last, T const& value, Compare comp) { - return first == last ? false - : sprout::next(first) == last ? !comp(*first, value) && !comp(value, *first) ? true : false - : comp(*sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), value) - ? sprout::binary_search(sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), last, value) - : comp(value, *sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last)) / 2) - ? sprout::binary_search(first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), value) - : true - ; + return sprout::detail::binary_search_impl(sprout::lower_bound(first, last, value), last, value, comp); + } + + template + inline SPROUT_CONSTEXPR bool + binary_search(ForwardIterator first, ForwardIterator last, T const& value) { + return sprout::binary_search( + first, last, value, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); } } // namespace sprout diff --git a/sprout/algorithm/equal_range.hpp b/sprout/algorithm/equal_range.hpp index b4b48cb6..bd79726d 100644 --- a/sprout/algorithm/equal_range.hpp +++ b/sprout/algorithm/equal_range.hpp @@ -5,22 +5,31 @@ #include #include #include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { // Copyright (C) 2011 RiSK (sscrisk) // 25.4.3.3 equal_range - template - inline SPROUT_CONSTEXPR sprout::pair - equal_range(ForwardIterator first, ForwardIterator last, T const& value) { - return {sprout::lower_bound(first, last, value), sprout::upper_bound(first, last, value)}; - } - + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR pair equal_range(ForwardIterator first, ForwardIterator last, T const& value, Compare comp) { return {sprout::lower_bound(first, last, value, comp), sprout::upper_bound(first, last, value, comp)}; } + + template + inline SPROUT_CONSTEXPR sprout::pair + equal_range(ForwardIterator first, ForwardIterator last, T const& value) { + return sprout::equal_range( + first, last, value, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_EQUAL_RANGE_HPP diff --git a/sprout/algorithm/includes.hpp b/sprout/algorithm/includes.hpp index e689b29a..09ab9b28 100644 --- a/sprout/algorithm/includes.hpp +++ b/sprout/algorithm/includes.hpp @@ -1,33 +1,94 @@ #ifndef SPROUT_ALGORITHM_INCLUDES_HPP #define SPROUT_ALGORITHM_INCLUDES_HPP +#include #include #include +#include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) + namespace detail { + template + inline SPROUT_CONSTEXPR RandomAccessIterator2 + includes_impl_ra( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, Compare comp, + typename std::iterator_traits::difference_type pivot + ) + { + return first2 == last2 ? first2 + : pivot == 0 ? (!comp(*first1, *first2) && !comp(*first2, *first1) ? sprout::next(first2) : first2) + : sprout::detail::includes_impl_ra( + sprout::next(first1, pivot), last1, + sprout::detail::includes_impl_ra( + first1, sprout::next(first1, pivot), + first2, + last2, comp, + pivot / 2 + ), + last2, comp, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) - pivot) / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR bool + includes( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, Compare comp, + std::random_access_iterator_tag* + ) + { + return first1 == last1 ? first2 == last2 + : sprout::detail::includes_impl_ra( + first1, last1, first2, last2, comp, + NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) / 2 + ) + == last2 + ; + } + + // Copyright (C) 2011 RiSK (sscrisk) + template + inline SPROUT_CONSTEXPR bool + includes_impl(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) { + return first2 == last2 ? true + : first1 == last1 ? false + : !comp(*first1, *first2) && !comp(*first2, *first1) + ? sprout::detail::includes_impl(sprout::next(first1), last1, sprout::next(first2), last2) + : sprout::detail::includes_impl(sprout::next(first1), last1, first2, last2) + ; + } + template + inline SPROUT_CONSTEXPR bool + includes( + InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp, + void* + ) + { + return sprout::detail::includes_impl(first1, last1, first2, comp); + } + } //namespace detail // 25.4.5.1 includes - template - inline SPROUT_CONSTEXPR bool - includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { - return first2 == last2 ? true - : first1 == last1 ? false - : !(*first1 < *first2) && !(*first2 < *first1) - ? sprout::includes(sprout::next(first1), last1, sprout::next(first2), last2) - : sprout::includes(sprout::next(first1), last1, first2, last2) - ; - } - + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) { - return first2 == last2 ? true - : first1 == last1 ? false - : !comp(*first1, *first2) && !comp(*first2, *first1) - ? sprout::includes(sprout::next(first1), last1, sprout::next(first2), last2) - : sprout::includes(sprout::next(first1), last1, first2, last2) - ; + typedef typename std::iterator_traits::iterator_category* category; + return sprout::detail::includes(first1, last1, first2, last2, comp, category()); + } + + template + inline SPROUT_CONSTEXPR bool + includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { + return sprout::includes( + first1, last1, first2, last2, + sprout::less<>() + ); } } // namespace sprout diff --git a/sprout/algorithm/is_sorted.hpp b/sprout/algorithm/is_sorted.hpp index 824cebf0..acb4b5fa 100644 --- a/sprout/algorithm/is_sorted.hpp +++ b/sprout/algorithm/is_sorted.hpp @@ -56,6 +56,11 @@ namespace sprout { } //namespace detail // 25.4.1.5 is_sorted + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool is_sorted(ForwardIterator first, ForwardIterator last, Compare comp) { diff --git a/sprout/algorithm/is_sorted_until.hpp b/sprout/algorithm/is_sorted_until.hpp index 20543ceb..e299b677 100644 --- a/sprout/algorithm/is_sorted_until.hpp +++ b/sprout/algorithm/is_sorted_until.hpp @@ -69,6 +69,11 @@ namespace sprout { } //namespace detail // 25.4.1.5 is_sorted + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last, Compare comp) { diff --git a/sprout/algorithm/lower_bound.hpp b/sprout/algorithm/lower_bound.hpp index 07a0e4ed..b5783b05 100644 --- a/sprout/algorithm/lower_bound.hpp +++ b/sprout/algorithm/lower_bound.hpp @@ -1,25 +1,21 @@ #ifndef SPROUT_ALGORITHM_LOWER_BOUND_HPP #define SPROUT_ALGORITHM_LOWER_BOUND_HPP +#include #include #include #include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { // Copyright (C) 2011 RiSK (sscrisk) // 25.4.3.1 lower_bound - template - inline SPROUT_CONSTEXPR ForwardIterator - lower_bound(ForwardIterator first, ForwardIterator last, T const& value) { - return first == last ? last - : sprout::next(first) == last ? *first < value ? last : first - : *sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2) < value - ? sprout::lower_bound(sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), last, value) - : sprout::lower_bound(first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), value) - ; - } - + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, T const& value, Compare comp) { @@ -30,6 +26,15 @@ namespace sprout { : sprout::lower_bound(first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), value, comp) ; } + + template + inline SPROUT_CONSTEXPR ForwardIterator + lower_bound(ForwardIterator first, ForwardIterator last, T const& value) { + return sprout::lower_bound( + first, last, value, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_LOWER_BOUND_HPP diff --git a/sprout/algorithm/upper_bound.hpp b/sprout/algorithm/upper_bound.hpp index d6dfd977..a8b5de7a 100644 --- a/sprout/algorithm/upper_bound.hpp +++ b/sprout/algorithm/upper_bound.hpp @@ -1,25 +1,21 @@ #ifndef SPROUT_ALGORITHM_UPPER_BOUND_HPP #define SPROUT_ALGORITHM_UPPER_BOUND_HPP +#include #include #include #include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { // Copyright (C) 2011 RiSK (sscrisk) // 25.4.3.2 upper_bound - template - inline SPROUT_CONSTEXPR ForwardIterator - upper_bound(ForwardIterator first, ForwardIterator last, T const& value) { - return first == last ? last - : sprout::next(first) == last ? !(value < *first) ? last : first - : !(value < *sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2)) - ? upper_bound(sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), last, value) - : sprout::upper_bound(first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), value) - ; - } - + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, T const& value, Compare comp) { @@ -30,6 +26,15 @@ namespace sprout { : sprout::upper_bound(first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2), value, comp) ; } + + template + inline SPROUT_CONSTEXPR ForwardIterator + upper_bound(ForwardIterator first, ForwardIterator last, T const& value) { + return sprout::upper_bound( + first, last, value, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_UPPER_BOUND_HPP