From 568bfdfc2b71be39cfcda62758a5ef9164db223a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Mar 2026 18:53:13 +0200 Subject: [PATCH] Unroll segmented_reverse --- .../experimental/segmented_reverse.hpp | 105 +++++++++++++++--- 1 file changed, 92 insertions(+), 13 deletions(-) diff --git a/include/boost/container/experimental/segmented_reverse.hpp b/include/boost/container/experimental/segmented_reverse.hpp index 05eb06c..210d26e 100644 --- a/include/boost/container/experimental/segmented_reverse.hpp +++ b/include/boost/container/experimental/segmented_reverse.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace boost { namespace container { @@ -30,15 +31,46 @@ namespace detail_algo { //Same-segment reverse: simply a reverse loop with move-swaps. No segmentation template -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 +void segmented_reverse_dispatch(RAIter first, RAIter last, non_segmented_iterator_tag, const std::random_access_iterator_tag &) +{ + typedef typename iterator_traits::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 -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 -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::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 +void segmented_reverse_disjoint_ranges(It& f, It f_end, It l_beg, It& l, segmented_iterator_tag, const Cat&) { typedef segmented_iterator_traits traits; typedef typename traits::segment_iterator segment_iterator; typedef typename traits::local_iterator local_iterator; typedef typename segmented_iterator_traits ::is_segmented_iterator is_local_seg_t; + typedef typename iterator_traits + ::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 -void segmented_reverse_dispatch(SegIt first, SegIt last, segmented_iterator_tag) +template +void segmented_reverse_dispatch(SegIt first, SegIt last, segmented_iterator_tag, const Cat &) { typedef segmented_iterator_traits traits; typedef typename traits::segment_iterator segment_iterator; typedef typename traits::local_iterator local_iterator; typedef typename segmented_iterator_traits ::is_segmented_iterator is_local_seg_t; + typedef typename iterator_traits + ::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 traits; detail_algo::segmented_reverse_dispatch - (first, last, typename traits::is_segmented_iterator()); + ( first, last + , typename traits::is_segmented_iterator() + , typename iterator_traits::iterator_category()); } } // namespace container