From b5bdde21c4c3c4006e98919675a834464b04958b Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Tue, 11 Dec 2012 12:59:36 +0900 Subject: [PATCH] fix recursion depth: find_first_of, adjacent_find --- libs/algorithm/test/adjacent_find.cpp | 55 ++++++++++++++ libs/algorithm/test/find_end.cpp | 103 ++++++++++++++++++++++++++ libs/algorithm/test/find_first_of.cpp | 103 ++++++++++++++++++++++++++ libs/algorithm/test/non_modifying.cpp | 6 ++ sprout/algorithm/adjacent_find.hpp | 74 ++++++++++++++++-- sprout/algorithm/find.hpp | 2 +- sprout/algorithm/find_end.hpp | 47 ++++++++++-- sprout/algorithm/find_first_of.hpp | 90 ++++++++++++++++++---- sprout/algorithm/find_if.hpp | 2 +- sprout/algorithm/find_if_not.hpp | 2 +- 10 files changed, 455 insertions(+), 29 deletions(-) create mode 100644 libs/algorithm/test/adjacent_find.cpp create mode 100644 libs/algorithm/test/find_end.cpp create mode 100644 libs/algorithm/test/find_first_of.cpp diff --git a/libs/algorithm/test/adjacent_find.cpp b/libs/algorithm/test/adjacent_find.cpp new file mode 100644 index 00000000..ff68b173 --- /dev/null +++ b/libs/algorithm/test/adjacent_find.cpp @@ -0,0 +1,55 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_ADJACENT_FIND_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_ADJACENT_FIND_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_adjacent_find_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::adjacent_find( + sprout::begin(arr1), + sprout::end(arr1) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 4); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::adjacent_find( + sprout::begin(arr1), + sprout::begin(arr1) + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::adjacent_find( + sprout::begin(arr1), + sprout::end(arr1), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 4); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::adjacent_find( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_adjacent_find_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_ADJACENT_FIND_CPP diff --git a/libs/algorithm/test/find_end.cpp b/libs/algorithm/test/find_end.cpp new file mode 100644 index 00000000..a3145232 --- /dev/null +++ b/libs/algorithm/test/find_end.cpp @@ -0,0 +1,103 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_END_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_FIND_END_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_find_end_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{{6, 5, 4}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(found == sprout::end(arr1)); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::end(arr1)); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::end(arr2), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_end( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_find_end_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_END_CPP diff --git a/libs/algorithm/test/find_first_of.cpp b/libs/algorithm/test/find_first_of.cpp new file mode 100644 index 00000000..c4034212 --- /dev/null +++ b/libs/algorithm/test/find_first_of.cpp @@ -0,0 +1,103 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_FIRST_OF_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_FIND_FIRST_OF_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_find_first_of_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{{11, 12 ,13}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(found == sprout::end(arr1)); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::end(arr1)); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::end(arr2), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::find_first_of( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::end(arr3), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_find_first_of_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_FIRST_OF_CPP diff --git a/libs/algorithm/test/non_modifying.cpp b/libs/algorithm/test/non_modifying.cpp index cd2f78a8..3d68cf03 100644 --- a/libs/algorithm/test/non_modifying.cpp +++ b/libs/algorithm/test/non_modifying.cpp @@ -13,6 +13,9 @@ #include "./find.cpp" #include "./find_if.cpp" #include "./find_if_not.cpp" +#include "./find_end.cpp" +#include "./find_first_of.cpp" +#include "./adjacent_find.cpp" #ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP # undef TESTSPR_CPP_INCLUDE @@ -27,6 +30,9 @@ namespace testspr { testspr::algorithm_find_test(); testspr::algorithm_find_if_test(); testspr::algorithm_find_if_not_test(); + testspr::algorithm_find_end_test(); + testspr::algorithm_find_first_of_test(); + testspr::algorithm_adjacent_find_test(); } } // namespace testspr diff --git a/sprout/algorithm/adjacent_find.hpp b/sprout/algorithm/adjacent_find.hpp index 80bc78ca..66fd912b 100644 --- a/sprout/algorithm/adjacent_find.hpp +++ b/sprout/algorithm/adjacent_find.hpp @@ -7,16 +7,80 @@ #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) + namespace detail { + template + inline SPROUT_CONSTEXPR RandomAccessIterator + adjacent_find_impl_ra_1(RandomAccessIterator found, RandomAccessIterator last) { + return NS_SSCRISK_CEL_OR_SPROUT::distance(found, last) == 1 ? last + : found + ; + } + template + inline SPROUT_CONSTEXPR RandomAccessIterator + adjacent_find_impl_ra( + RandomAccessIterator first, RandomAccessIterator last, BinaryPredicate pred, + typename std::iterator_traits::difference_type pivot, RandomAccessIterator found + ) + { + return found != first ? found + : pivot == 0 ? (pred(*first, *last) ? first : last) + : sprout::detail::adjacent_find_impl_ra( + sprout::next(first, pivot), last, pred, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - pivot) / 2, + sprout::detail::adjacent_find_impl_ra( + first, sprout::next(first, pivot), pred, + pivot / 2, + first + ) + ) + ; + } + template + inline SPROUT_CONSTEXPR RandomAccessIterator + adjacent_find( + RandomAccessIterator first, RandomAccessIterator last, BinaryPredicate pred, + std::random_access_iterator_tag* + ) + { + return first == last || NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) == 1 ? last + : adjacent_find_impl_ra_1( + sprout::detail::adjacent_find_impl_ra( + first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1), pred, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1) / 2, first + ), + last + ) + ; + } + + // Copyright (C) 2011 RiSK (sscrisk) + template + inline SPROUT_CONSTEXPR ForwardIterator + adjacent_find_impl(ForwardIterator first, ForwardIterator next, ForwardIterator last, BinaryPredicate pred) { + return next == last ? last + : pred(*first, *next) ? first + : sprout::detail::adjacent_find_impl(next, sprout::next(next), last, pred) + ; + } + template + inline SPROUT_CONSTEXPR ForwardIterator + adjacent_find( + ForwardIterator first, ForwardIterator last, BinaryPredicate pred, + void* + ) + { + return first == last ? last + : sprout::detail::adjacent_find_impl(first, sprout::next(first), last, pred) + ; + } + } //namespace detail // 25.2.8 Adjacent find template inline SPROUT_CONSTEXPR ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { - return first == last || sprout::next(first) == last ? last - : pred(*first, *(sprout::next(first))) ? first - : sprout::adjacent_find(sprout::next(first), last, pred) - ; + typedef typename std::iterator_traits::iterator_category* category; + return sprout::detail::adjacent_find(first, last, pred, category()); } template diff --git a/sprout/algorithm/find.hpp b/sprout/algorithm/find.hpp index 4e110c05..b6a01719 100644 --- a/sprout/algorithm/find.hpp +++ b/sprout/algorithm/find.hpp @@ -35,7 +35,7 @@ namespace sprout { std::random_access_iterator_tag* ) { - return first == last ? first + return first == last ? last : sprout::detail::find_impl_ra(first, last, value, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2, first) ; } diff --git a/sprout/algorithm/find_end.hpp b/sprout/algorithm/find_end.hpp index 9a883ce1..962e9dff 100644 --- a/sprout/algorithm/find_end.hpp +++ b/sprout/algorithm/find_end.hpp @@ -6,9 +6,9 @@ #include namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) - namespace detail { + // Copyright (C) 2011 RiSK (sscrisk) + template struct iter_equal_to { public: @@ -23,6 +23,41 @@ namespace sprout { }; } // namespace detail + namespace detail { + template + inline SPROUT_CONSTEXPR ForwardIterator1 + find_end_impl( + ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred, + ForwardIterator1 result + ) + { + return first1 == last1 ? result + : sprout::detail::find_end_impl( + sprout::search(sprout::next(first1), last1, first2, last2, pred), last1, first2, last2, pred, + first1 + ) + ; + } + template + inline SPROUT_CONSTEXPR ForwardIterator1 + find_end( + ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred, + void* + ) + { + return first2 == last2 ? last1 + : sprout::detail::find_end_impl( + sprout::search(first1, last1, first2, last2, pred), last1, first2, last2, pred, + last1 + ) + ; + } + } // namespace detail + // 25.2.6 Find end template inline SPROUT_CONSTEXPR ForwardIterator1 @@ -32,12 +67,8 @@ namespace sprout { BinaryPredicate pred ) { - return first1 == last1 || first2 == last2 ? last1 - : sprout::search(first1, last1, first2, last2, pred) == first1 - && sprout::search(sprout::next(first1), last1, first2, last2, pred) == last1 - ? first1 - : sprout::find_end(sprout::next(first1), last1, first2, last2, pred) - ; + typedef typename std::iterator_traits::iterator_category* category; + return sprout::detail::find_end(first1, last1, first2, last2, pred, category()); } template diff --git a/sprout/algorithm/find_first_of.hpp b/sprout/algorithm/find_first_of.hpp index 03dfae7a..5ae371ab 100644 --- a/sprout/algorithm/find_first_of.hpp +++ b/sprout/algorithm/find_first_of.hpp @@ -1,37 +1,101 @@ #ifndef SPROUT_ALGORITHM_FIND_FIRST_OF_HPP #define SPROUT_ALGORITHM_FIND_FIRST_OF_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 RandomAccessIterator1 + find_first_of_impl_ra( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred, + typename std::iterator_traits::difference_type pivot, RandomAccessIterator1 found + ) + { + return found != first1 ? found + : pivot == 0 ? sprout::find_if(first2, last2, NS_SSCRISK_CEL_OR_SPROUT::bind2nd(pred, *first1)) != last2 ? first1 : last1 + : sprout::detail::find_first_of_impl_ra( + sprout::next(first1, pivot), last1, first2, last2, pred, + (NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) - pivot) / 2, + sprout::detail::find_first_of_impl_ra( + first1, sprout::next(first1, pivot), first2, last2, pred, + pivot / 2, + first1 + ) + ) + ; + } + template + inline SPROUT_CONSTEXPR RandomAccessIterator1 + find_first_of( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred, + std::random_access_iterator_tag* + ) + { + return first1 == last1 ? last1 + : sprout::detail::find_first_of_impl_ra( + first1, last1, first2, last2, + pred, NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) / 2, first1 + ) + ; + } + + // Copyright (C) 2011 RiSK (sscrisk) + template + inline SPROUT_CONSTEXPR InputIterator1 + find_first_of_impl( + InputIterator1 first1, InputIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred + ) + { + return first1 == last1 || sprout::find_if(first2, last2, NS_SSCRISK_CEL_OR_SPROUT::bind2nd(pred, *first1)) != last2 ? first1 + : sprout::detail::find_first_of_impl(sprout::next(first1), last1, first2, last2, pred) + ; + } + template + inline SPROUT_CONSTEXPR InputIterator1 + find_first_of( + InputIterator1 first1, InputIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred, + void* + ) + { + return sprout::detail::find_first_of_impl(first1, last1, first2, last2, pred); + } + } //namespace detail // 25.2.7 Find first - template - inline SPROUT_CONSTEXPR ForwardIterator1 + template + inline SPROUT_CONSTEXPR InputIterator1 find_first_of( - ForwardIterator1 first1, ForwardIterator1 last1, + InputIterator1 first1, InputIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred ) { - return first1 == last1 || sprout::find_if(first2, last2, NS_SSCRISK_CEL_OR_SPROUT::bind2nd(pred, *first1)) != last2 ? first1 - : sprout::find_first_of(sprout::next(first1), last1, first2, last2, pred) - ; + typedef typename std::iterator_traits::iterator_category* category; + return sprout::detail::find_first_of(first1, last1, first2, last2, pred, category()); } - template - inline SPROUT_CONSTEXPR ForwardIterator1 + template + inline SPROUT_CONSTEXPR InputIterator1 find_first_of( - ForwardIterator1 first1, ForwardIterator1 last1, + InputIterator1 first1, InputIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 ) { - return first1 == last1 || sprout::find(first2, last2, *first1) != last2 ? first1 - : sprout::find_first_of(sprout::next(first1), last1, first2, last2) - ; + return sprout::find_first_of(first1, last1, first2, last2, sprout::equal_to<>()); } } // namespace sprout diff --git a/sprout/algorithm/find_if.hpp b/sprout/algorithm/find_if.hpp index 7d6f7d30..052353da 100644 --- a/sprout/algorithm/find_if.hpp +++ b/sprout/algorithm/find_if.hpp @@ -35,7 +35,7 @@ namespace sprout { std::random_access_iterator_tag* ) { - return first == last ? first + return first == last ? last : sprout::detail::find_if_impl_ra(first, last, pred, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2, first) ; } diff --git a/sprout/algorithm/find_if_not.hpp b/sprout/algorithm/find_if_not.hpp index 18ece86e..da3db726 100644 --- a/sprout/algorithm/find_if_not.hpp +++ b/sprout/algorithm/find_if_not.hpp @@ -35,7 +35,7 @@ namespace sprout { std::random_access_iterator_tag* ) { - return first == last ? first + return first == last ? last : sprout::detail::find_if_not_impl_ra(first, last, pred, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2, first) ; }