1
0
Fork 0
mirror of https://github.com/bolero-MURAKAMI/Sprout synced 2025-08-03 12:49:50 +00:00

fix recursion depth O(logN): some algorithms

This commit is contained in:
bolero-MURAKAMI 2013-01-03 17:01:50 +09:00
parent 28697ee7a8
commit 5019f6aa96
162 changed files with 3600 additions and 1659 deletions

View file

@ -2,45 +2,68 @@
#define SPROUT_DETAIL_ALGORITHM_COUNT_N_HPP
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/type_traits/is_iterator.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/algorithm/count.hpp>
namespace sprout {
namespace detail {
template<typename InputIterator, typename Size, typename T>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
template<typename RandomAccessIterator, typename T>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_constant_distance_iterator<RandomAccessIterator>::value,
typename std::iterator_traits<RandomAccessIterator>::difference_type
>::type
count_n(
InputIterator first, Size n, T const& value,
RandomAccessIterator first, typename std::iterator_traits<RandomAccessIterator>::difference_type n, T const& value,
std::random_access_iterator_tag*
)
{
return sprout::count(first, sprout::next(first, n), value);
}
template<typename InputIterator, typename Size, typename T>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
count_n_impl(InputIterator first, Size n, T const& value) {
return n == 0 ? 0
: (*first == value ? 1 : 0) + sprout::detail::count_n_impl(sprout::next(first), n - 1, value)
template<typename InputIterator, typename T>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type>
count_n_impl(
sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> const& current,
T const& value, typename std::iterator_traits<InputIterator>::difference_type n
)
{
typedef sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> type;
return n == 1 ? type(sprout::next(current.first), current.second + (*current.first == value ? 1 : 0))
: sprout::detail::count_n_impl(
sprout::detail::count_n_impl(
current,
value, n / 2
),
value, n - n / 2
)
;
}
template<typename InputIterator, typename Size, typename T>
template<typename InputIterator, typename T>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
count_n(
InputIterator first, Size n, T const& value,
InputIterator first, typename std::iterator_traits<InputIterator>::difference_type n, T const& value,
void*
)
{
return sprout::detail::count_n_impl(first, n, value);
typedef sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> type;
return n == 0 ? 0
: sprout::detail::count_n_impl(type(first, 0), value, n).second
;
}
//
// count_n
//
template<typename InputIterator, typename Size, typename T>
// recursion depth:
// O(log N)
//
template<typename InputIterator, typename T>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
count_n(InputIterator first, Size n, T const& value) {
count_n(InputIterator first, typename std::iterator_traits<InputIterator>::difference_type n, T const& value) {
typedef typename std::iterator_traits<InputIterator>::iterator_category* category;
return sprout::detail::count_n(first, n, value, category());
}

View file

@ -2,45 +2,68 @@
#define SPROUT_DETAIL_ALGORITHM_COUNT_N_IF_HPP
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/type_traits/is_iterator.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/algorithm/count_if.hpp>
namespace sprout {
namespace detail {
template<typename InputIterator, typename Size, typename Predicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
template<typename RandomAccessIterator, typename Predicate>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_constant_distance_iterator<RandomAccessIterator>::pred,
typename std::iterator_traits<RandomAccessIterator>::difference_type
>::type
count_n_if(
InputIterator first, Size n, Predicate pred,
RandomAccessIterator first, typename std::iterator_traits<RandomAccessIterator>::difference_type n, Predicate pred,
std::random_access_iterator_tag*
)
{
return sprout::count_if(first, sprout::next(first, n), pred);
return sprout::count(first, sprout::next(first, n), pred);
}
template<typename InputIterator, typename Size, typename Predicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
count_n_if_impl(InputIterator first, Size n, Predicate pred) {
return n == 0 ? 0
: (pred(*first) ? 1 : 0) + sprout::detail::count_n_if(sprout::next(first), n - 1, pred)
template<typename InputIterator, typename Predicate>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type>
count_n_if_impl(
sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> const& current,
Predicate pred, typename std::iterator_traits<InputIterator>::difference_type n
)
{
typedef sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> type;
return n == 1 ? type(sprout::next(current.first), current.second + (pred(*current.first) ? 1 : 0))
: sprout::detail::count_n_if_impl(
sprout::detail::count_n_if_impl(
current,
pred, n / 2
),
pred, n - n / 2
)
;
}
template<typename InputIterator, typename Size, typename Predicate>
template<typename InputIterator, typename Predicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
count_n_if(
InputIterator first, Size n, Predicate pred,
InputIterator first, typename std::iterator_traits<InputIterator>::difference_type n, Predicate pred,
void*
)
{
return sprout::detail::count_n_if_impl(first, n, pred);
typedef sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> type;
return n == 0 ? 0
: sprout::detail::count_n_if_impl(type(first, 0), pred, n).second
;
}
//
// count_n_if
//
template<typename InputIterator, typename Size, typename Predicate>
// recursion depth:
// O(log N)
//
template<typename InputIterator, typename Predicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
count_n_if(InputIterator first, Size n, Predicate pred) {
count_n_if(InputIterator first, typename std::iterator_traits<InputIterator>::difference_type n, Predicate pred) {
typedef typename std::iterator_traits<InputIterator>::iterator_category* category;
return sprout::detail::count_n_if(first, n, pred, category());

View file

@ -4,7 +4,8 @@
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT
#include <sprout/iterator/type_traits/is_iterator.hpp>
#include <sprout/tuple/tuple.hpp>
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT
namespace sprout {
@ -23,52 +24,89 @@ namespace sprout {
)
+ sprout::detail::overlap_count_impl_ra(
sprout::next(first, pivot), last, pred,
(NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - pivot) / 2
(sprout::distance(first, last) - pivot) / 2
)
;
}
template<typename RandomAccessIterator, typename BinaryPredicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<RandomAccessIterator>::difference_type
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_constant_distance_iterator<RandomAccessIterator>::value,
typename std::iterator_traits<RandomAccessIterator>::difference_type
>::type
overlap_count(
RandomAccessIterator first, RandomAccessIterator last, BinaryPredicate pred,
std::random_access_iterator_tag*
)
{
return first == last || NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) == 1 ? 0
return first == last || sprout::distance(first, last) == 1 ? 0
: sprout::detail::overlap_count_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, sprout::next(first, sprout::distance(first, last) - 1), pred,
(sprout::distance(first, last) - 1) / 2
)
;
}
template<typename InputIterator, typename BinaryPredicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
overlap_count_impl(
InputIterator first, InputIterator last, BinaryPredicate pred,
typename std::iterator_traits<InputIterator>::value_type const& value
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator, typename std::iterator_traits<InputIterator>::value_type, typename std::iterator_traits<InputIterator>::difference_type>
overlap_count_impl_1(
sprout::tuples::tuple<InputIterator, typename std::iterator_traits<InputIterator>::value_type, typename std::iterator_traits<InputIterator>::difference_type> const& current,
InputIterator last, BinaryPredicate pred, typename std::iterator_traits<InputIterator>::difference_type n
)
{
return first == last ? 0
: pred(*first, value) ? 1 + sprout::detail::overlap_count_impl(sprout::next(first), last, pred, value)
: sprout::detail::overlap_count_impl(sprout::next(first), last, pred, *first)
typedef sprout::tuples::tuple<InputIterator, typename std::iterator_traits<InputIterator>::value_type, typename std::iterator_traits<InputIterator>::difference_type> type;
return sprout::tuples::get<0>(current) == last ? current
: n == 1 ? type(
sprout::next(sprout::tuples::get<0>(current)), *sprout::tuples::get<0>(current),
sprout::tuples::get<2>(current) + (pred(*sprout::tuples::get<0>(current), sprout::tuples::get<1>(current)) ? 1 : 0)
)
: sprout::detail::overlap_count_impl_1(
sprout::detail::overlap_count_impl_1(
current,
last, pred, n / 2
),
last, pred, n - n / 2
)
;
}
template<typename InputIterator, typename BinaryPredicate>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator, typename std::iterator_traits<InputIterator>::value_type, typename std::iterator_traits<InputIterator>::difference_type>
overlap_count_impl(
sprout::tuples::tuple<InputIterator, typename std::iterator_traits<InputIterator>::value_type, typename std::iterator_traits<InputIterator>::difference_type> const& current,
InputIterator last, BinaryPredicate pred, typename std::iterator_traits<InputIterator>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator, typename std::iterator_traits<InputIterator>::value_type, typename std::iterator_traits<InputIterator>::difference_type> type;
return sprout::tuples::get<0>(current) == last ? current
: sprout::detail::overlap_count_impl(
sprout::detail::overlap_count_impl_1(
current,
last, pred, n
),
last, pred, n * 2
)
;
}
template<typename InputIterator, typename BinaryPredicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
overlap_count_impl(
overlap_count(
InputIterator first, InputIterator last, BinaryPredicate pred,
void*
)
{
typedef sprout::tuples::tuple<InputIterator, typename std::iterator_traits<InputIterator>::value_type, typename std::iterator_traits<InputIterator>::difference_type> type;
return first == last ? 0
: sprout::detail::overlap_count_impl(sprout::next(first), last, pred, *first)
: sprout::tuples::get<2>(
sprout::detail::overlap_count_impl(type(sprout::next(first), *first, 0), last, pred, 1)
)
;
}
//
// overlap_count
//
// recursion depth:
// O(log N)
//
template<typename InputIterator, typename BinaryPredicate>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
overlap_count(InputIterator first, InputIterator last, BinaryPredicate pred) {

View file

@ -7,7 +7,7 @@
#include <sprout/iterator/type_traits/common.hpp>
#include <sprout/functional/equal_to.hpp>
#include <sprout/algorithm/mismatch.hpp>
#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT
#include <sprout/tuple/tuple.hpp>
namespace sprout {
namespace detail {
@ -17,12 +17,7 @@ namespace sprout {
RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred
)
{
return sprout::detail::mismatch_impl_ra(
first1, last1, first2, pred,
NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) / 2, first1
)
== last1
? first1
return sprout::mismatch(first1, last1, first2, pred).first == last1 ? first1
: last1
;
}
@ -33,25 +28,57 @@ namespace sprout {
std::random_access_iterator_tag*
)
{
return NS_SSCRISK_CEL_OR_SPROUT::distance(first1, last1) < NS_SSCRISK_CEL_OR_SPROUT::distance(first2, last2) ? last1
return sprout::distance(first1, last1) < sprout::distance(first2, last2) ? last1
: first1 == last1 ? first1
: sprout::detail::search_one_impl_ra(
first1, sprout::next(first1, NS_SSCRISK_CEL_OR_SPROUT::distance(first2, last2)), first2, last2, pred
first1, sprout::next(first1, sprout::distance(first2, last2)), first2, last2, pred
)
;
}
template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
inline SPROUT_CONSTEXPR ForwardIterator1
search_one_impl(
ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred,
ForwardIterator1 first1_
inline SPROUT_CONSTEXPR sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool>
search_one_impl_1(
sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> const& current,
ForwardIterator1 last1, ForwardIterator2 last2, BinaryPredicate pred,
ForwardIterator1 first1_, typename std::iterator_traits<ForwardIterator1>::difference_type n
)
{
return first2 == last2 ? first1_
: first1 == last1 ? last1
: !pred(*first1, *first2) ? first1
: sprout::detail::search_one_impl(sprout::next(first1), last1, sprout::next(first2), last2, pred, first1_)
typedef sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> type;
return sprout::tuples::get<2>(current) ? current
: sprout::tuples::get<1>(current) == last2 ? type(first1_, last2, true)
: sprout::tuples::get<0>(current) == last1 ? type(last1, last2, true)
: n == 1 ? !pred(*sprout::tuples::get<0>(current), *sprout::tuples::get<1>(current))
? type(sprout::next(sprout::tuples::get<0>(current)), last2, true)
: type(sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)), false)
: sprout::detail::search_one_impl_1(
sprout::detail::search_one_impl_1(
current,
last1, last2, pred, first1_, n / 2
),
last1, last2, pred, first1_, n - n / 2
)
;
}
template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool>
search_one_impl(
sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> const& current,
ForwardIterator1 last1, ForwardIterator2 last2, BinaryPredicate pred,
ForwardIterator1 first1_, typename std::iterator_traits<ForwardIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> type;
return sprout::tuples::get<2>(current) ? current
: sprout::tuples::get<1>(current) == last2 ? type(first1_, last2, true)
: sprout::tuples::get<0>(current) == last1 ? type(last1, last2, true)
: sprout::detail::search_one_impl(
sprout::detail::search_one_impl_1(
current,
last1, last2, pred, first1_, n
),
last1, last2, pred, first1_, n * 2
)
;
}
template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
@ -61,12 +88,18 @@ namespace sprout {
void*
)
{
return sprout::detail::search_one_impl(first1, last1, first2, last2, pred, first1);
typedef sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> type;
return sprout::tuples::get<0>(
sprout::detail::search_one_impl(type(first1, first2, false), last1, last2, pred, first1, 1)
);
}
//
// search_one
//
// recursion depth:
// O(log (N1+N2))
//
template<typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
inline SPROUT_CONSTEXPR ForwardIterator1
search_one(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred) {

View file

@ -4,13 +4,68 @@
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/type_traits/is_iterator.hpp>
#include <sprout/iterator/type_traits/common.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/functional/less.hpp>
namespace sprout {
namespace detail {
template<typename InputIterator1, typename InputIterator2, typename Compare>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, InputIterator2, typename std::iterator_traits<InputIterator1>::difference_type>
set_overlap_count_impl_1(
sprout::tuples::tuple<InputIterator1, InputIterator2, typename std::iterator_traits<InputIterator1>::difference_type> const& current,
InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, InputIterator2, typename std::iterator_traits<InputIterator1>::difference_type> type;
return sprout::tuples::get<0>(current) == last1 || sprout::tuples::get<1>(current) == last2 ? current
: n == 1 ? comp(*sprout::tuples::get<0>(current), *sprout::tuples::get<1>(current)) ? type(
sprout::next(sprout::tuples::get<0>(current)), sprout::tuples::get<1>(current),
sprout::tuples::get<2>(current)
)
: comp(*sprout::tuples::get<1>(current), *sprout::tuples::get<0>(current)) ? type(
sprout::tuples::get<0>(current), sprout::next(sprout::tuples::get<1>(current)),
sprout::tuples::get<2>(current)
)
: type(
sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)),
sprout::tuples::get<2>(current) + 1
)
: sprout::detail::set_overlap_count_impl_1(
sprout::detail::set_overlap_count_impl_1(
current,
last1, last2, comp, n / 2
),
last1, last2, comp, n - n / 2
)
;
}
template<typename InputIterator1, typename InputIterator2, typename Compare>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, InputIterator2, typename std::iterator_traits<InputIterator1>::difference_type>
set_overlap_count_impl(
sprout::tuples::tuple<InputIterator1, InputIterator2, typename std::iterator_traits<InputIterator1>::difference_type> const& current,
InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, InputIterator2, typename std::iterator_traits<InputIterator1>::difference_type> type;
return sprout::tuples::get<0>(current) == last1 || sprout::tuples::get<1>(current) == last2 ? current
: sprout::detail::set_overlap_count_impl(
sprout::detail::set_overlap_count_impl_1(
current,
last1, last2, comp, n
),
last1, last2, comp, n * 2
)
;
}
//
// set_overlap_count
//
// recursion depth:
// O(log N)
//
template<typename InputIterator1, typename InputIterator2, typename Compare>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator1>::difference_type
set_overlap_count(
@ -19,14 +74,10 @@ namespace sprout {
Compare comp
)
{
return first1 != last1 && first2 != last2
? comp(*first1, *first2)
? sprout::detail::set_overlap_count(sprout::next(first1), last1, first2, last2, comp)
: comp(*first2, *first1)
? sprout::detail::set_overlap_count(first1, last1, sprout::next(first2), last2, comp)
: 1 + sprout::detail::set_overlap_count(sprout::next(first1), last1, sprout::next(first2), last2, comp)
: 0
;
typedef sprout::tuples::tuple<InputIterator1, InputIterator2, typename std::iterator_traits<InputIterator1>::difference_type> type;
return sprout::tuples::get<2>(
sprout::detail::set_overlap_count_impl(type(first1, first2, 0), last1, last2, comp, 1)
);
}
template<typename InputIterator1, typename InputIterator2>