mirror of
https://github.com/boostorg/container.git
synced 2026-07-05 13:20:46 +02:00
Unroll segmented_reverse
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/experimental/segmented_iterator_traits.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
@@ -30,15 +31,46 @@ namespace detail_algo {
|
||||
|
||||
//Same-segment reverse: simply a reverse loop with move-swaps. No segmentation
|
||||
template <class BidirIt>
|
||||
void segmented_reverse_dispatch(BidirIt first, BidirIt last, non_segmented_iterator_tag)
|
||||
void segmented_reverse_dispatch(BidirIt first, BidirIt last, non_segmented_iterator_tag, const std::bidirectional_iterator_tag &)
|
||||
{
|
||||
while(first != last && first != --last) {
|
||||
boost::adl_move_swap(*first, *last);
|
||||
++first;
|
||||
}
|
||||
}
|
||||
#define BOOST_CONTAINER_SEGMENTED_REVERSE_RECURSIVE
|
||||
#ifdef BOOST_CONTAINER_SEGMENTED_REVERSE_RECURSIVE
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class RAIter>
|
||||
void segmented_reverse_dispatch(RAIter first, RAIter last, non_segmented_iterator_tag, const std::random_access_iterator_tag &)
|
||||
{
|
||||
typedef typename iterator_traits<RAIter>::difference_type difference_type;
|
||||
difference_type pairs = (last - first) / difference_type(2);
|
||||
|
||||
while(pairs >= difference_type(4)) {
|
||||
--last; boost::adl_move_swap(*first, *last); ++first;
|
||||
--last; boost::adl_move_swap(*first, *last); ++first;
|
||||
--last; boost::adl_move_swap(*first, *last); ++first;
|
||||
--last; boost::adl_move_swap(*first, *last); ++first;
|
||||
pairs -= 4;
|
||||
}
|
||||
|
||||
switch (pairs % 4) {
|
||||
case 3:
|
||||
--last; boost::adl_move_swap(*first, *last); ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
--last; boost::adl_move_swap(*first, *last); ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
--last; boost::adl_move_swap(*first, *last); //No need to increment first since we're done after this.
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// segmented_reverse_disjoint_ranges: swaps elements between
|
||||
@@ -48,7 +80,8 @@ void segmented_reverse_dispatch(BidirIt first, BidirIt last, non_segmented_itera
|
||||
//////////////////////////////////////////////
|
||||
|
||||
template <class It>
|
||||
void segmented_reverse_disjoint_ranges(It& f_out, It const f_end, It const l_beg, It& l_out, non_segmented_iterator_tag)
|
||||
void segmented_reverse_disjoint_ranges
|
||||
(It& f_out, It const f_end, It const l_beg, It& l_out, non_segmented_iterator_tag, const std::bidirectional_iterator_tag &)
|
||||
{
|
||||
It f = f_out;
|
||||
It l = l_out;
|
||||
@@ -62,14 +95,58 @@ void segmented_reverse_disjoint_ranges(It& f_out, It const f_end, It const l_beg
|
||||
l_out = l;
|
||||
}
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class It>
|
||||
void segmented_reverse_disjoint_ranges(It& f, It f_end, It l_beg, It& l, segmented_iterator_tag)
|
||||
void segmented_reverse_disjoint_ranges
|
||||
(It& f_out, It const f_end, It const l_beg, It& l_out, non_segmented_iterator_tag, const std::random_access_iterator_tag &)
|
||||
{
|
||||
typedef typename iterator_traits<It>::difference_type difference_type;
|
||||
|
||||
It f = f_out;
|
||||
It l = l_out;
|
||||
difference_type n_f = f_end - f;
|
||||
difference_type n_l = l - l_beg;
|
||||
difference_type n = n_f < n_l ? n_f : n_l;
|
||||
|
||||
while(n >= difference_type(4)) {
|
||||
--l; boost::adl_move_swap(*f, *l); ++f;
|
||||
--l; boost::adl_move_swap(*f, *l); ++f;
|
||||
--l; boost::adl_move_swap(*f, *l); ++f;
|
||||
--l; boost::adl_move_swap(*f, *l); ++f;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch (n % 4) {
|
||||
case 3:
|
||||
--l; boost::adl_move_swap(*f, *l); ++f;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
--l; boost::adl_move_swap(*f, *l); ++f;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
--l; boost::adl_move_swap(*f, *l); ++f;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
f_out = f;
|
||||
l_out = l;
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
template <class It, class Cat>
|
||||
void segmented_reverse_disjoint_ranges(It& f, It f_end, It l_beg, It& l, segmented_iterator_tag, const Cat&)
|
||||
{
|
||||
typedef segmented_iterator_traits<It> traits;
|
||||
typedef typename traits::segment_iterator segment_iterator;
|
||||
typedef typename traits::local_iterator local_iterator;
|
||||
typedef typename segmented_iterator_traits
|
||||
<local_iterator>::is_segmented_iterator is_local_seg_t;
|
||||
typedef typename iterator_traits
|
||||
<local_iterator>::iterator_category local_cat_t;
|
||||
|
||||
//Nothing to swap here if a range is empty
|
||||
if (f == f_end || l == l_beg)
|
||||
@@ -89,7 +166,7 @@ void segmented_reverse_disjoint_ranges(It& f, It f_end, It l_beg, It& l, segment
|
||||
//since the ranges are guaranteed not to overlap
|
||||
while (true) {
|
||||
//Reverse the front and back segments recursively
|
||||
segmented_reverse_disjoint_ranges(fi, fi_end, li_beg, li, is_local_seg_t());
|
||||
segmented_reverse_disjoint_ranges(fi, fi_end, li_beg, li, is_local_seg_t(), local_cat_t());
|
||||
|
||||
//Independent advancement of forward and backward segments since ranges do not to overlap
|
||||
|
||||
@@ -123,16 +200,16 @@ void segmented_reverse_disjoint_ranges(It& f, It f_end, It l_beg, It& l, segment
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_CONTAINER_SEGMENTED_REVERSE_RECURSIVE
|
||||
|
||||
template <class SegIt>
|
||||
void segmented_reverse_dispatch(SegIt first, SegIt last, segmented_iterator_tag)
|
||||
template <class SegIt, class Cat>
|
||||
void segmented_reverse_dispatch(SegIt first, SegIt last, segmented_iterator_tag, const Cat &)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegIt> traits;
|
||||
typedef typename traits::segment_iterator segment_iterator;
|
||||
typedef typename traits::local_iterator local_iterator;
|
||||
typedef typename segmented_iterator_traits
|
||||
<local_iterator>::is_segmented_iterator is_local_seg_t;
|
||||
typedef typename iterator_traits
|
||||
<local_iterator>::iterator_category local_cat_t;
|
||||
|
||||
segment_iterator sf = traits::segment(first);
|
||||
segment_iterator sl = traits::segment(last);
|
||||
@@ -144,7 +221,7 @@ void segmented_reverse_dispatch(SegIt first, SegIt last, segmented_iterator_tag)
|
||||
local_iterator l_beg = traits::begin(sl);
|
||||
|
||||
while (true) {
|
||||
segmented_reverse_disjoint_ranges(f_loc, f_end, l_beg, l_loc, is_local_seg_t());
|
||||
segmented_reverse_disjoint_ranges(f_loc, f_end, l_beg, l_loc, is_local_seg_t(), local_cat_t());
|
||||
|
||||
//Check if the backward side reached the end of its segment
|
||||
if (l_loc == l_beg) {
|
||||
@@ -180,7 +257,7 @@ void segmented_reverse_dispatch(SegIt first, SegIt last, segmented_iterator_tag)
|
||||
}
|
||||
}
|
||||
//Final reverse loop within the final segment
|
||||
segmented_reverse_dispatch(f_loc, l_loc, is_local_seg_t());
|
||||
segmented_reverse_dispatch(f_loc, l_loc, is_local_seg_t(), local_cat_t());
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
@@ -194,7 +271,9 @@ void segmented_reverse(BidirIter first, BidirIter last)
|
||||
{
|
||||
typedef segmented_iterator_traits<BidirIter> traits;
|
||||
detail_algo::segmented_reverse_dispatch
|
||||
(first, last, typename traits::is_segmented_iterator());
|
||||
( first, last
|
||||
, typename traits::is_segmented_iterator()
|
||||
, typename iterator_traits<BidirIter>::iterator_category());
|
||||
}
|
||||
|
||||
} // namespace container
|
||||
|
||||
Reference in New Issue
Block a user