From c3c79053bba33fada8d1b64bcbd86458e2710d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Mar 2026 17:52:42 +0200 Subject: [PATCH] Unrolled segmented_remove_copy --- .../experimental/segmented_remove_copy_if.hpp | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/include/boost/container/experimental/segmented_remove_copy_if.hpp b/include/boost/container/experimental/segmented_remove_copy_if.hpp index 9c51390..e7df74b 100644 --- a/include/boost/container/experimental/segmented_remove_copy_if.hpp +++ b/include/boost/container/experimental/segmented_remove_copy_if.hpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace boost { namespace container { @@ -30,11 +31,46 @@ OutIter segmented_remove_copy_if(InIter first, Sent last, OutIter result, Pred p namespace detail_algo { -template +#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) + +template +OutIter segmented_remove_copy_if_dispatch + (InIter first, InIter last, OutIter result, Pred pred, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &) +{ + typedef typename iterator_traits::difference_type difference_type; + difference_type n = last - first; + + while(n >= difference_type(4)) { + if(!pred(*first)) { *result = *first; ++result; } ++first; + if(!pred(*first)) { *result = *first; ++result; } ++first; + if(!pred(*first)) { *result = *first; ++result; } ++first; + if(!pred(*first)) { *result = *first; ++result; } ++first; + n -= 4; + } + + switch (n % 4) { + case 3: + if(!pred(*first)) { *result = *first; ++result; } ++first; + BOOST_FALLTHROUGH; + case 2: + if(!pred(*first)) { *result = *first; ++result; } ++first; + BOOST_FALLTHROUGH; + case 1: + if (!pred(*first)) { *result = *first; ++result; } //No need to increment first since we're done after this. + BOOST_FALLTHROUGH; + default: + break; + } + return result; +} + +#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING + +template typename algo_enable_if_c< !Tag::value || is_sentinel::value, OutIter>::type segmented_remove_copy_if_dispatch - (InIter first, Sent last, OutIter result, Pred pred, Tag) + (InIter first, Sent last, OutIter result, Pred pred, Tag, Cat) { for(; first != last; ++first) { if(!pred(*first)) { @@ -45,9 +81,9 @@ segmented_remove_copy_if_dispatch return result; } -template +template OutIter segmented_remove_copy_if_dispatch - (SegIter first, SegIter last, OutIter result, Pred pred, segmented_iterator_tag) + (SegIter first, SegIter last, OutIter result, Pred pred, segmented_iterator_tag, Cat) { typedef segmented_iterator_traits traits; typedef typename traits::local_iterator local_iterator; @@ -58,15 +94,15 @@ OutIter segmented_remove_copy_if_dispatch segment_iterator slast = traits::segment(last); if(sfirst == slast) { - return (segmented_remove_copy_if_dispatch)(traits::local(first), traits::local(last), result, pred, is_local_seg_t()); + return (segmented_remove_copy_if_dispatch)(traits::local(first), traits::local(last), result, pred, is_local_seg_t(), Cat()); } else { - result = (segmented_remove_copy_if_dispatch)(traits::local(first), traits::end(sfirst), result, pred, is_local_seg_t()); + result = (segmented_remove_copy_if_dispatch)(traits::local(first), traits::end(sfirst), result, pred, is_local_seg_t(), Cat()); for(++sfirst; sfirst != slast; ++sfirst) - result = (segmented_remove_copy_if_dispatch)(traits::begin(sfirst), traits::end(sfirst), result, pred, is_local_seg_t()); + result = (segmented_remove_copy_if_dispatch)(traits::begin(sfirst), traits::end(sfirst), result, pred, is_local_seg_t(), Cat()); - return (segmented_remove_copy_if_dispatch)(traits::begin(sfirst), traits::local(last), result, pred, is_local_seg_t()); + return (segmented_remove_copy_if_dispatch)(traits::begin(sfirst), traits::local(last), result, pred, is_local_seg_t(), Cat()); } } @@ -81,7 +117,7 @@ OutIter segmented_remove_copy_if(InIter first, Sent last, OutIter result, Pred p { typedef segmented_iterator_traits traits; return detail_algo::segmented_remove_copy_if_dispatch - (first, last, result, pred, typename traits::is_segmented_iterator()); + (first, last, result, pred, typename traits::is_segmented_iterator(), typename iterator_traits::iterator_category()); } } // namespace container