fix recursion depth: find_first_of, adjacent_find

This commit is contained in:
bolero-MURAKAMI 2012-12-11 12:59:36 +09:00
parent 54400ea7d0
commit b5bdde21c4
10 changed files with 455 additions and 29 deletions

View file

@ -0,0 +1,55 @@
#ifndef SPROUT_LIBS_ALGORITHM_TEST_ADJACENT_FIND_CPP
#define SPROUT_LIBS_ALGORITHM_TEST_ADJACENT_FIND_CPP
#include <sprout/algorithm/adjacent_find.hpp>
#include <sprout/array.hpp>
#include <sprout/container.hpp>
#include <testspr/tools.hpp>
namespace testspr {
static void algorithm_adjacent_find_test() {
using namespace sprout;
{
SPROUT_STATIC_CONSTEXPR auto arr1 = array<int, 12>{{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<int>()
);
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<int>()
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
}
}
} // namespace testspr
#ifndef TESTSPR_CPP_INCLUDE
# define TESTSPR_TEST_FUNCTION testspr::algorithm_adjacent_find_test
# include <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_ADJACENT_FIND_CPP

View file

@ -0,0 +1,103 @@
#ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_END_CPP
#define SPROUT_LIBS_ALGORITHM_TEST_FIND_END_CPP
#include <sprout/algorithm/find_end.hpp>
#include <sprout/array.hpp>
#include <sprout/container.hpp>
#include <testspr/tools.hpp>
namespace testspr {
static void algorithm_find_end_test() {
using namespace sprout;
{
SPROUT_STATIC_CONSTEXPR auto arr1 = array<int, 10>{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}};
SPROUT_STATIC_CONSTEXPR auto arr2 = array<int, 3>{{4, 5, 6}};
SPROUT_STATIC_CONSTEXPR auto arr3 = array<int, 3>{{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<int>()
);
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<int>()
);
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<int>()
);
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<int>()
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
}
}
} // namespace testspr
#ifndef TESTSPR_CPP_INCLUDE
# define TESTSPR_TEST_FUNCTION testspr::algorithm_find_end_test
# include <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_END_CPP

View file

@ -0,0 +1,103 @@
#ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_FIRST_OF_CPP
#define SPROUT_LIBS_ALGORITHM_TEST_FIND_FIRST_OF_CPP
#include <sprout/algorithm/find_first_of.hpp>
#include <sprout/array.hpp>
#include <sprout/container.hpp>
#include <testspr/tools.hpp>
namespace testspr {
static void algorithm_find_first_of_test() {
using namespace sprout;
{
SPROUT_STATIC_CONSTEXPR auto arr1 = array<int, 10>{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}};
SPROUT_STATIC_CONSTEXPR auto arr2 = array<int, 3>{{4, 5, 6}};
SPROUT_STATIC_CONSTEXPR auto arr3 = array<int, 3>{{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<int>()
);
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<int>()
);
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<int>()
);
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<int>()
);
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 <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_FIND_FIRST_OF_CPP

View file

@ -13,6 +13,9 @@
#include "./find.cpp" #include "./find.cpp"
#include "./find_if.cpp" #include "./find_if.cpp"
#include "./find_if_not.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 #ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP
# undef TESTSPR_CPP_INCLUDE # undef TESTSPR_CPP_INCLUDE
@ -27,6 +30,9 @@ namespace testspr {
testspr::algorithm_find_test(); testspr::algorithm_find_test();
testspr::algorithm_find_if_test(); testspr::algorithm_find_if_test();
testspr::algorithm_find_if_not_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 } // namespace testspr

View file

@ -7,16 +7,80 @@
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT
namespace sprout { namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk) namespace detail {
template<typename RandomAccessIterator>
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<typename RandomAccessIterator, typename BinaryPredicate>
inline SPROUT_CONSTEXPR RandomAccessIterator
adjacent_find_impl_ra(
RandomAccessIterator first, RandomAccessIterator last, BinaryPredicate pred,
typename std::iterator_traits<RandomAccessIterator>::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<typename RandomAccessIterator, typename BinaryPredicate>
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<typename ForwardIterator, typename BinaryPredicate>
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<typename ForwardIterator, typename BinaryPredicate>
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 // 25.2.8 Adjacent find
template<typename ForwardIterator, typename BinaryPredicate> template<typename ForwardIterator, typename BinaryPredicate>
inline SPROUT_CONSTEXPR ForwardIterator inline SPROUT_CONSTEXPR ForwardIterator
adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) {
return first == last || sprout::next(first) == last ? last typedef typename std::iterator_traits<ForwardIterator>::iterator_category* category;
: pred(*first, *(sprout::next(first))) ? first return sprout::detail::adjacent_find(first, last, pred, category());
: sprout::adjacent_find(sprout::next(first), last, pred)
;
} }
template<typename ForwardIterator> template<typename ForwardIterator>

View file

@ -35,7 +35,7 @@ namespace sprout {
std::random_access_iterator_tag* 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) : sprout::detail::find_impl_ra(first, last, value, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2, first)
; ;
} }

View file

@ -6,9 +6,9 @@
#include <sprout/algorithm/search.hpp> #include <sprout/algorithm/search.hpp>
namespace sprout { namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail { namespace detail {
// Copyright (C) 2011 RiSK (sscrisk)
template<typename Iterator1, typename Iterator2> template<typename Iterator1, typename Iterator2>
struct iter_equal_to { struct iter_equal_to {
public: public:
@ -23,6 +23,41 @@ namespace sprout {
}; };
} // namespace detail } // namespace detail
namespace detail {
template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
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<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
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 // 25.2.6 Find end
template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate> template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
inline SPROUT_CONSTEXPR ForwardIterator1 inline SPROUT_CONSTEXPR ForwardIterator1
@ -32,12 +67,8 @@ namespace sprout {
BinaryPredicate pred BinaryPredicate pred
) )
{ {
return first1 == last1 || first2 == last2 ? last1 typedef typename std::iterator_traits<ForwardIterator1>::iterator_category* category;
: sprout::search(first1, last1, first2, last2, pred) == first1 return sprout::detail::find_end(first1, last1, first2, last2, pred, category());
&& sprout::search(sprout::next(first1), last1, first2, last2, pred) == last1
? first1
: sprout::find_end(sprout::next(first1), last1, first2, last2, pred)
;
} }
template<typename ForwardIterator1, typename ForwardIterator2> template<typename ForwardIterator1, typename ForwardIterator2>

View file

@ -1,37 +1,101 @@
#ifndef SPROUT_ALGORITHM_FIND_FIRST_OF_HPP #ifndef SPROUT_ALGORITHM_FIND_FIRST_OF_HPP
#define SPROUT_ALGORITHM_FIND_FIRST_OF_HPP #define SPROUT_ALGORITHM_FIND_FIRST_OF_HPP
#include <iterator>
#include <sprout/config.hpp> #include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp> #include <sprout/iterator/operation.hpp>
#include <sprout/functional/equal_to.hpp>
#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT
namespace sprout { namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk) namespace detail {
template<typename RandomAccessIterator1, typename ForwardIterator2, typename BinaryPredicate>
inline SPROUT_CONSTEXPR RandomAccessIterator1
find_first_of_impl_ra(
RandomAccessIterator1 first1, RandomAccessIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred,
typename std::iterator_traits<RandomAccessIterator1>::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<typename RandomAccessIterator1, typename ForwardIterator2, typename BinaryPredicate>
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<typename InputIterator1, typename ForwardIterator2, typename BinaryPredicate>
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<typename InputIterator1, typename ForwardIterator2, typename BinaryPredicate>
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 // 25.2.7 Find first
template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate> template<typename InputIterator1, typename ForwardIterator2, typename BinaryPredicate>
inline SPROUT_CONSTEXPR ForwardIterator1 inline SPROUT_CONSTEXPR InputIterator1
find_first_of( find_first_of(
ForwardIterator1 first1, ForwardIterator1 last1, InputIterator1 first1, InputIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred BinaryPredicate pred
) )
{ {
return first1 == last1 || sprout::find_if(first2, last2, NS_SSCRISK_CEL_OR_SPROUT::bind2nd(pred, *first1)) != last2 ? first1 typedef typename std::iterator_traits<InputIterator1>::iterator_category* category;
: sprout::find_first_of(sprout::next(first1), last1, first2, last2, pred) return sprout::detail::find_first_of(first1, last1, first2, last2, pred, category());
;
} }
template<typename ForwardIterator1, typename ForwardIterator2> template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR ForwardIterator1 inline SPROUT_CONSTEXPR InputIterator1
find_first_of( find_first_of(
ForwardIterator1 first1, ForwardIterator1 last1, InputIterator1 first1, InputIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2 ForwardIterator2 first2, ForwardIterator2 last2
) )
{ {
return first1 == last1 || sprout::find(first2, last2, *first1) != last2 ? first1 return sprout::find_first_of(first1, last1, first2, last2, sprout::equal_to<>());
: sprout::find_first_of(sprout::next(first1), last1, first2, last2)
;
} }
} // namespace sprout } // namespace sprout

View file

@ -35,7 +35,7 @@ namespace sprout {
std::random_access_iterator_tag* 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) : sprout::detail::find_if_impl_ra(first, last, pred, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2, first)
; ;
} }

View file

@ -35,7 +35,7 @@ namespace sprout {
std::random_access_iterator_tag* 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) : sprout::detail::find_if_not_impl_ra(first, last, pred, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) / 2, first)
; ;
} }