mirror of
https://github.com/bolero-MURAKAMI/Sprout.git
synced 2025-07-04 14:14:09 +00:00
Merge pull request #69 from kariya-mitsuru/fix-minmax_element
minmax_element: reduce complexity
This commit is contained in:
commit
157e8268c6
1 changed files with 73 additions and 15 deletions
|
@ -35,28 +35,37 @@ namespace sprout {
|
||||||
comp(*b, *sprout::second(a)) ? sprout::second(a) : b
|
comp(*b, *sprout::second(a)) ? sprout::second(a) : b
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
template<typename ForwardIterator, typename Compare>
|
||||||
|
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, ForwardIterator>
|
||||||
|
iter_minmax(ForwardIterator a, ForwardIterator b, Compare comp) {
|
||||||
|
typedef sprout::pair<ForwardIterator, ForwardIterator> type;
|
||||||
|
return comp(*b, *a)
|
||||||
|
? type(b, a)
|
||||||
|
: type(a, b)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename RandomAccessIterator, typename Compare>
|
template<typename RandomAccessIterator, typename Compare>
|
||||||
inline SPROUT_CONSTEXPR sprout::pair<RandomAccessIterator, RandomAccessIterator>
|
inline SPROUT_CONSTEXPR sprout::pair<RandomAccessIterator, RandomAccessIterator>
|
||||||
minmax_element_impl_ra(
|
minmax_element_impl_ra(
|
||||||
RandomAccessIterator first, RandomAccessIterator last, Compare comp,
|
RandomAccessIterator first, Compare comp,
|
||||||
typename std::iterator_traits<RandomAccessIterator>::difference_type pivot
|
typename std::iterator_traits<RandomAccessIterator>::difference_type half
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return pivot == 0 ? sprout::pair<RandomAccessIterator, RandomAccessIterator>(first, first)
|
return half == 1
|
||||||
|
? iter_minmax(first, sprout::next(first), comp)
|
||||||
: sprout::detail::iter_minmax_pair(
|
: sprout::detail::iter_minmax_pair(
|
||||||
sprout::detail::minmax_element_impl_ra(
|
sprout::detail::minmax_element_impl_ra(
|
||||||
first, sprout::next(first, pivot), comp,
|
first, comp, half / 2
|
||||||
pivot / 2
|
|
||||||
),
|
),
|
||||||
sprout::detail::minmax_element_impl_ra(
|
sprout::detail::minmax_element_impl_ra(
|
||||||
sprout::next(first, pivot), last, comp,
|
sprout::next(first, half - (half & 1)), comp, (half + 1) / 2
|
||||||
(sprout::distance(first, last) - pivot) / 2
|
|
||||||
),
|
),
|
||||||
comp
|
comp
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RandomAccessIterator, typename Compare>
|
template<typename RandomAccessIterator, typename Compare>
|
||||||
inline SPROUT_CONSTEXPR typename std::enable_if<
|
inline SPROUT_CONSTEXPR typename std::enable_if<
|
||||||
sprout::is_constant_distance_iterator<RandomAccessIterator>::value,
|
sprout::is_constant_distance_iterator<RandomAccessIterator>::value,
|
||||||
|
@ -67,11 +76,44 @@ namespace sprout {
|
||||||
std::random_access_iterator_tag*
|
std::random_access_iterator_tag*
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return first == last ? sprout::pair<RandomAccessIterator, RandomAccessIterator>(last, last)
|
return first == last || sprout::next(first) == last
|
||||||
: sprout::detail::minmax_element_impl_ra(
|
? sprout::pair<RandomAccessIterator, RandomAccessIterator>(first, first)
|
||||||
first, last, comp,
|
: sprout::distance(first, last) % 2 == 0
|
||||||
|
? sprout::detail::minmax_element_impl_ra(
|
||||||
|
first, comp,
|
||||||
sprout::distance(first, last) / 2
|
sprout::distance(first, last) / 2
|
||||||
)
|
)
|
||||||
|
: sprout::detail::iter_minmax(
|
||||||
|
sprout::detail::minmax_element_impl_ra(
|
||||||
|
first, comp,
|
||||||
|
sprout::distance(first, last) / 2
|
||||||
|
),
|
||||||
|
sprout::prev(last),
|
||||||
|
comp
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ForwardIterator, typename Compare>
|
||||||
|
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, sprout::pair<ForwardIterator, ForwardIterator> >
|
||||||
|
minmax_element_impl_3(
|
||||||
|
sprout::pair<ForwardIterator, ForwardIterator> minmax,
|
||||||
|
ForwardIterator first, ForwardIterator next,
|
||||||
|
ForwardIterator last, Compare comp) {
|
||||||
|
typedef sprout::pair<ForwardIterator, sprout::pair<ForwardIterator, ForwardIterator> > type;
|
||||||
|
return next == last
|
||||||
|
? type(
|
||||||
|
next,
|
||||||
|
sprout::detail::iter_minmax(minmax, first, comp)
|
||||||
|
)
|
||||||
|
: type(
|
||||||
|
sprout::next(next),
|
||||||
|
sprout::detail::iter_minmax_pair(
|
||||||
|
minmax,
|
||||||
|
sprout::detail::iter_minmax(first, next, comp),
|
||||||
|
comp
|
||||||
|
)
|
||||||
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +124,10 @@ namespace sprout {
|
||||||
ForwardIterator last, Compare comp, typename std::iterator_traits<ForwardIterator>::difference_type n
|
ForwardIterator last, Compare comp, typename std::iterator_traits<ForwardIterator>::difference_type n
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
typedef sprout::pair<ForwardIterator, sprout::pair<ForwardIterator, ForwardIterator> > type;
|
|
||||||
return current.first == last ? current
|
return current.first == last ? current
|
||||||
: n == 1 ? type(sprout::next(current.first), sprout::detail::iter_minmax(current.second, current.first, comp))
|
: n == 1 ? sprout::detail::minmax_element_impl_3(
|
||||||
|
current.second, current.first, sprout::next(current.first),
|
||||||
|
last, comp)
|
||||||
: sprout::detail::minmax_element_impl_1(
|
: sprout::detail::minmax_element_impl_1(
|
||||||
sprout::detail::minmax_element_impl_1(
|
sprout::detail::minmax_element_impl_1(
|
||||||
current,
|
current,
|
||||||
|
@ -94,6 +137,7 @@ namespace sprout {
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardIterator, typename Compare>
|
template<typename ForwardIterator, typename Compare>
|
||||||
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, sprout::pair<ForwardIterator, ForwardIterator> >
|
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, sprout::pair<ForwardIterator, ForwardIterator> >
|
||||||
minmax_element_impl(
|
minmax_element_impl(
|
||||||
|
@ -111,6 +155,19 @@ namespace sprout {
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ForwardIterator, typename Compare>
|
||||||
|
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, sprout::pair<ForwardIterator, ForwardIterator> >
|
||||||
|
minmax_element_impl_2(
|
||||||
|
ForwardIterator first, ForwardIterator next, ForwardIterator last, Compare comp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef sprout::pair<ForwardIterator, ForwardIterator> type;
|
||||||
|
return next == last ? sprout::pair<ForwardIterator, type>(next, type(first, first))
|
||||||
|
: sprout::pair<ForwardIterator, type>(sprout::next(next), iter_minmax(first, next, comp))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ForwardIterator, typename Compare>
|
template<typename ForwardIterator, typename Compare>
|
||||||
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, ForwardIterator>
|
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, ForwardIterator>
|
||||||
minmax_element(
|
minmax_element(
|
||||||
|
@ -118,9 +175,10 @@ namespace sprout {
|
||||||
std::forward_iterator_tag*
|
std::forward_iterator_tag*
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
typedef sprout::pair<ForwardIterator, sprout::pair<ForwardIterator, ForwardIterator> > type;
|
|
||||||
return first == last ? sprout::pair<ForwardIterator, ForwardIterator>(first, first)
|
return first == last ? sprout::pair<ForwardIterator, ForwardIterator>(first, first)
|
||||||
: sprout::detail::minmax_element_impl(type(sprout::next(first), sprout::pair<ForwardIterator, ForwardIterator>(first, first)), last, comp, 1).second
|
: sprout::detail::minmax_element_impl(
|
||||||
|
sprout::detail::minmax_element_impl_2(first, sprout::next(first), last, comp),
|
||||||
|
last, comp, 1).second
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue