From eea1c2bbc1c55892b6a3b50cbfa1eae93fa2acc1 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 15 Dec 2012 17:41:20 +0900 Subject: [PATCH] fix rexursion depth: is_pertitioned, partition_point, is_sorted, is_sorted_until --- libs/algorithm/test/is_partitioned.cpp | 56 ++++++++++++++++ libs/algorithm/test/is_sorted.cpp | 54 +++++++++++++++ libs/algorithm/test/is_sorted_until.cpp | 54 +++++++++++++++ libs/algorithm/test/non_modifying.cpp | 8 +++ libs/algorithm/test/partition_point.cpp | 40 ++++++++++++ sprout/algorithm/adjacent_find.hpp | 1 + sprout/algorithm/find_end.hpp | 31 ++++++--- sprout/algorithm/is_partitioned.hpp | 24 +++---- sprout/algorithm/is_sorted.hpp | 68 ++++++++++++++++--- sprout/algorithm/is_sorted_until.hpp | 87 +++++++++++++++++++++---- sprout/algorithm/partition_point.hpp | 5 ++ sprout/iterator/distance.hpp | 32 ++++++++- 12 files changed, 410 insertions(+), 50 deletions(-) create mode 100644 libs/algorithm/test/is_partitioned.cpp create mode 100644 libs/algorithm/test/is_sorted.cpp create mode 100644 libs/algorithm/test/is_sorted_until.cpp create mode 100644 libs/algorithm/test/partition_point.cpp diff --git a/libs/algorithm/test/is_partitioned.cpp b/libs/algorithm/test/is_partitioned.cpp new file mode 100644 index 00000000..14233e6d --- /dev/null +++ b/libs/algorithm/test/is_partitioned.cpp @@ -0,0 +1,56 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_PERTITIONED_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_IS_PERTITIONED_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_is_partitioned_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned( + sprout::begin(arr1), + sprout::end(arr1), + testspr::is_odd() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned( + sprout::begin(arr1), + sprout::end(arr1), + testspr::less_than(6) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::is_odd() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::less_than(6) + ); + TESTSPR_BOTH_ASSERT(result); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_partitioned_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_PERTITIONED_CPP diff --git a/libs/algorithm/test/is_sorted.cpp b/libs/algorithm/test/is_sorted.cpp new file mode 100644 index 00000000..864e2973 --- /dev/null +++ b/libs/algorithm/test/is_sorted.cpp @@ -0,0 +1,54 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_is_sorted_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted( + sprout::begin(arr1), + sprout::end(arr1) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted( + sprout::begin(arr1), + sprout::begin(arr1) + 5 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted( + sprout::begin(arr1), + sprout::end(arr1), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_sorted_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_CPP diff --git a/libs/algorithm/test/is_sorted_until.cpp b/libs/algorithm/test/is_sorted_until.cpp new file mode 100644 index 00000000..81032a98 --- /dev/null +++ b/libs/algorithm/test/is_sorted_until.cpp @@ -0,0 +1,54 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_UNTIL_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_UNTIL_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_is_sorted_until_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until( + sprout::begin(arr1), + sprout::end(arr1) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until( + sprout::begin(arr1), + sprout::begin(arr1) + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until( + sprout::begin(arr1), + sprout::end(arr1), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_sorted_until_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_UNTIL_CPP diff --git a/libs/algorithm/test/non_modifying.cpp b/libs/algorithm/test/non_modifying.cpp index 033c8043..c6e391db 100644 --- a/libs/algorithm/test/non_modifying.cpp +++ b/libs/algorithm/test/non_modifying.cpp @@ -23,6 +23,10 @@ #include "./is_permutation.cpp" #include "./search.cpp" #include "./search_n.cpp" +#include "./is_partitioned.cpp" +#include "./partition_point.cpp" +#include "./is_sorted.cpp" +#include "./is_sorted_until.cpp" #ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP # undef TESTSPR_CPP_INCLUDE @@ -47,6 +51,10 @@ namespace testspr { testspr::algorithm_is_permutation_test(); testspr::algorithm_search_test(); testspr::algorithm_search_n_test(); + testspr::algorithm_is_partitioned_test(); + testspr::algorithm_partition_point_test(); + testspr::algorithm_is_sorted_test(); + testspr::algorithm_is_sorted_until_test(); } } // namespace testspr diff --git a/libs/algorithm/test/partition_point.cpp b/libs/algorithm/test/partition_point.cpp new file mode 100644 index 00000000..5c59b012 --- /dev/null +++ b/libs/algorithm/test/partition_point.cpp @@ -0,0 +1,40 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_PERTITION_POINT_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_PERTITION_POINT_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_partition_point_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::partition_point( + sprout::begin(arr1), + sprout::end(arr1), + testspr::is_odd() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::partition_point( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::is_odd() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_partition_point_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_PERTITION_POINT_CPP diff --git a/sprout/algorithm/adjacent_find.hpp b/sprout/algorithm/adjacent_find.hpp index b5e991ab..b53cf6ee 100644 --- a/sprout/algorithm/adjacent_find.hpp +++ b/sprout/algorithm/adjacent_find.hpp @@ -4,6 +4,7 @@ #include #include #include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { diff --git a/sprout/algorithm/find_end.hpp b/sprout/algorithm/find_end.hpp index 95fa98c5..213fdffb 100644 --- a/sprout/algorithm/find_end.hpp +++ b/sprout/algorithm/find_end.hpp @@ -6,9 +6,17 @@ #include #include #include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT namespace sprout { namespace detail { + template + inline SPROUT_CONSTEXPR RandomAccessIterator1 + find_end_impl_ra_1(RandomAccessIterator1 first1, RandomAccessIterator1 result, RandomAccessIterator1 searched) { + return searched == first1 ? searched + : result + ; + } template inline SPROUT_CONSTEXPR RandomAccessIterator1 find_end_impl_ra( @@ -19,16 +27,21 @@ namespace sprout { RandomAccessIterator1 searched ) { - return searched < first1 ? sprout::detail::find_end_impl_ra( - sprout::next(first1, pivot), last1, first2, last2, pred, - (NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) - pivot) / 2, last1_, searched, - sprout::detail::find_end_impl_ra( - first1, sprout::next(first1, pivot), first2, last2, pred, - pivot / 2, last1_, searched, - first1 + return searched == last1_ ? result + : searched < first1 ? pivot == 0 + ? sprout::detail::find_end_impl_ra_1( + first1, searched, + sprout::detail::search_one(first1, last1_, first2, last2, pred) + ) + : sprout::detail::find_end_impl_ra( + sprout::next(first1, pivot), last1, first2, last2, pred, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) - pivot) / 2, last1_, searched, + sprout::detail::find_end_impl_ra( + first1, sprout::next(first1, pivot), first2, last2, pred, + pivot / 2, last1_, searched, + first1 + ) ) - ) - : searched == last1_ ? result : pivot == 0 ? sprout::detail::search_one(first1, last1_, first2, last2, pred) : sprout::detail::find_end_impl_ra( sprout::next(first1, pivot), last1, first2, last2, pred, diff --git a/sprout/algorithm/is_partitioned.hpp b/sprout/algorithm/is_partitioned.hpp index b7bea467..74f6543d 100644 --- a/sprout/algorithm/is_partitioned.hpp +++ b/sprout/algorithm/is_partitioned.hpp @@ -2,28 +2,20 @@ #define SPROUT_ALGORITHM_IS_PARTITIONED_HPP #include -#include +#include +#include namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) - - namespace detail { - template - inline SPROUT_CONSTEXPR bool - is_partitioned_impl(InputIterator first, InputIterator last, Predicate pred, bool cond = true) { - return first == last ? true - : cond ? sprout::detail::is_partitioned_impl(sprout::next(first), last, pred, pred(*first)) - : pred(*first) ? false - : sprout::detail::is_partitioned_impl(sprout::next(first), last, pred, false) - ; - } - } // namespace detail - // 25.3.13 Partitions + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool is_partitioned(InputIterator first, InputIterator last, Predicate pred) { - return sprout::detail::is_partitioned_impl(first, last, pred); + return sprout::none_of(sprout::find_if_not(first, last, pred), last, pred); } } // namespace sprout diff --git a/sprout/algorithm/is_sorted.hpp b/sprout/algorithm/is_sorted.hpp index d66410a7..824cebf0 100644 --- a/sprout/algorithm/is_sorted.hpp +++ b/sprout/algorithm/is_sorted.hpp @@ -1,23 +1,75 @@ #ifndef SPROUT_ALGORITHM_IS_SORTED_HPP #define SPROUT_ALGORITHM_IS_SORTED_HPP +#include #include +#include #include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) + namespace detail { + template + inline SPROUT_CONSTEXPR bool + is_sorted_impl_ra( + RandomAccessIterator first, RandomAccessIterator last, Compare comp, + typename std::iterator_traits::difference_type pivot + ) + { + return pivot == 0 ? !comp(*last, *first) + : sprout::detail::is_sorted_impl_ra( + first, sprout::next(first, pivot), comp, + pivot / 2 + ) + && sprout::detail::is_sorted_impl_ra( + sprout::next(first, pivot), last, comp, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - pivot) / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR bool + is_sorted( + RandomAccessIterator first, RandomAccessIterator last, Compare comp, + std::random_access_iterator_tag* + ) + { + return first == last || NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) == 1 ? true + : sprout::detail::is_sorted_impl_ra( + first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1), comp, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1) / 2 + ) + ; + } + + // Copyright (C) 2011 RiSK (sscrisk) + template + inline SPROUT_CONSTEXPR bool + is_sorted( + ForwardIterator first, ForwardIterator last, Compare comp, + void* + ) + { + return sprout::is_sorted_until(first, last, comp) == last; + } + } //namespace detail // 25.4.1.5 is_sorted - template - inline SPROUT_CONSTEXPR bool - is_sorted(ForwardIterator first, ForwardIterator last) { - return sprout::is_sorted_until(first, last) == last; - } - template inline SPROUT_CONSTEXPR bool is_sorted(ForwardIterator first, ForwardIterator last, Compare comp) { - return sprout::is_sorted_until(first, last, comp) == last; + typedef typename std::iterator_traits::iterator_category* category; + return sprout::detail::is_sorted(first, last, comp, category()); + } + + template + inline SPROUT_CONSTEXPR bool + is_sorted(ForwardIterator first, ForwardIterator last) { + return sprout::is_sorted( + first, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); } } // namespace sprout diff --git a/sprout/algorithm/is_sorted_until.hpp b/sprout/algorithm/is_sorted_until.hpp index e5d03b79..20543ceb 100644 --- a/sprout/algorithm/is_sorted_until.hpp +++ b/sprout/algorithm/is_sorted_until.hpp @@ -1,29 +1,88 @@ #ifndef SPROUT_ALGORITHM_IS_SORTED_UNTIL_HPP #define SPROUT_ALGORITHM_IS_SORTED_UNTIL_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) + namespace detail { + template + inline SPROUT_CONSTEXPR RandomAccessIterator + is_sorted_until_impl_ra( + RandomAccessIterator first, RandomAccessIterator last, Compare comp, + typename std::iterator_traits::difference_type pivot, RandomAccessIterator found + ) + { + return found != first ? found + : pivot == 0 ? (comp(*last, *first) ? first : last) + : sprout::detail::is_sorted_until_impl_ra( + sprout::next(first, pivot), last, comp, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - pivot) / 2, + sprout::detail::is_sorted_until_impl_ra( + first, sprout::next(first, pivot), comp, + pivot / 2, + first + ) + ) + ; + } + template + inline SPROUT_CONSTEXPR RandomAccessIterator + is_sorted_until( + RandomAccessIterator first, RandomAccessIterator last, Compare comp, + std::random_access_iterator_tag* + ) + { + return first == last || NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) == 1 ? last + : sprout::next( + sprout::detail::is_sorted_until_impl_ra( + first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1), comp, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1) / 2, first + ) + ) + ; + } + + // Copyright (C) 2011 RiSK (sscrisk) + template + inline SPROUT_CONSTEXPR ForwardIterator + is_sorted_until_impl(ForwardIterator first, ForwardIterator next, ForwardIterator last, Compare comp) { + return next == last ? last + : comp(*next, *first) ? first + : sprout::detail::is_sorted_until_impl(next, sprout::next(next), last, comp) + ; + } + template + inline SPROUT_CONSTEXPR ForwardIterator + is_sorted_until( + ForwardIterator first, ForwardIterator last, Compare comp, + void* + ) + { + return first == last ? last + : sprout::detail::is_sorted_until_impl(first, sprout::next(first), last, comp) + ; + } + } //namespace detail // 25.4.1.5 is_sorted - template - inline SPROUT_CONSTEXPR ForwardIterator - is_sorted_until(ForwardIterator first, ForwardIterator last) { - return first == last || sprout::next(first) == last ? last - : *(sprout::next(first)) < *first ? sprout::next(first) - : sprout::is_sorted_until(sprout::next(first), last) - ; - } - template inline SPROUT_CONSTEXPR ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last, Compare comp) { - return first == last || sprout::next(first) == last ? last - : comp(*(sprout::next(first)), *first) ? sprout::next(first) - : sprout::is_sorted_until(sprout::next(first), last) - ; + typedef typename std::iterator_traits::iterator_category* category; + return sprout::detail::is_sorted_until(first, last, comp, category()); + } + + template + inline SPROUT_CONSTEXPR ForwardIterator + is_sorted_until(ForwardIterator first, ForwardIterator last) { + return sprout::is_sorted_until( + first, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); } } // namespace sprout diff --git a/sprout/algorithm/partition_point.hpp b/sprout/algorithm/partition_point.hpp index 54837be5..b061e911 100644 --- a/sprout/algorithm/partition_point.hpp +++ b/sprout/algorithm/partition_point.hpp @@ -26,6 +26,11 @@ namespace sprout { } // namespace detail // 25.3.13 Partitions + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, Predicate pred) { diff --git a/sprout/iterator/distance.hpp b/sprout/iterator/distance.hpp index f11e438f..bbb73118 100644 --- a/sprout/iterator/distance.hpp +++ b/sprout/iterator/distance.hpp @@ -2,6 +2,7 @@ #define SPROUT_ITERATOR_DISTANCE_HPP #include +#include #include #include #include @@ -12,14 +13,34 @@ namespace sprout_adl { namespace sprout { namespace iterator_detail { + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !std::is_pointer::value, + typename std::iterator_traits::difference_type + >::type + iterator_distance(RandomAccessIterator first, RandomAccessIterator last, std::random_access_iterator_tag*) { + return last - first; + } + // Copyright (C) 2011 RiSK (sscrisk) + template + inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type + iterator_distance_impl(InputIterator first, InputIterator last) { + return first == last ? 0 + : 1 + sprout::iterator_detail::iterator_distance_impl(sprout::next(first), last) + ; + } + template + inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type + iterator_distance(InputIterator first, InputIterator last, void*) { + return sprout::iterator_detail::iterator_distance_impl(first, last); + } template inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type iterator_distance(InputIterator first, InputIterator last) { - return first == last ? 0 - : 1 + sprout::iterator_detail::iterator_distance(sprout::next(first), last) - ; + typedef typename std::iterator_traits::iterator_category* category; + return sprout::iterator_detail::iterator_distance(first, last, category()); } } // namespace iterator_detail } // namespace sprout @@ -38,6 +59,11 @@ namespace sprout { // // distance // + // effect: + // ADL callable iterator_distance(first, last) -> iterator_distance(first, last) + // [first, last) is RandomAccessIterator && not Pointer -> last - first + // otherwise -> linearly count: first to last + // template inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type distance(InputIterator first, InputIterator last) {