From 34636439ebb63eeeb3c334f67c272017f4da91c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 20 Mar 2026 13:42:09 +0100 Subject: [PATCH] Use segmented_find_if_not to simplify the implementation and improve multi-level segmentation support. --- .../experimental/segmented_partition.hpp | 97 ++++++++++--------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/include/boost/container/experimental/segmented_partition.hpp b/include/boost/container/experimental/segmented_partition.hpp index 0955025..ff8b239 100644 --- a/include/boost/container/experimental/segmented_partition.hpp +++ b/include/boost/container/experimental/segmented_partition.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -49,7 +50,7 @@ OutIter partition_scan(FwdIt first, Sent last, OutIter result, Pred pred, non_se } template -OutIter partition_scan(SegIt first, SegIt last, OutIter result, Pred pred, segmented_iterator_tag, const std::forward_iterator_tag &) +OutIter partition_scan(SegIt first, SegIt last, OutIter result, Pred pred, segmented_iterator_tag, const std::forward_iterator_tag & cat) { typedef segmented_iterator_traits traits; typedef typename traits::local_iterator local_iterator; @@ -61,15 +62,15 @@ OutIter partition_scan(SegIt first, SegIt last, OutIter result, Pred pred, segme local_iterator lcur = traits::local(first); if(scur == slast) { - return partition_scan(lcur, traits::local(last), result, pred, is_local_seg_t()); + return partition_scan(lcur, traits::local(last), result, pred, is_local_seg_t(), cat); } else { - result = partition_scan(lcur, traits::end(scur), result, pred, is_local_seg_t()); + result = partition_scan(lcur, traits::end(scur), result, pred, is_local_seg_t(), cat); for(++scur; scur != slast; ++scur) - result = partition_scan(traits::begin(scur), traits::end(scur), result, pred, is_local_seg_t()); + result = partition_scan(traits::begin(scur), traits::end(scur), result, pred, is_local_seg_t(), cat); - return partition_scan(traits::begin(scur), traits::local(last), result, pred, is_local_seg_t()); + return partition_scan(traits::begin(scur), traits::local(last), result, pred, is_local_seg_t(), cat); } } @@ -112,45 +113,45 @@ SegIt partition_scan(SegIt first, SegIt last, Pred pred, segmented_iterator_tag, local_iterator r = partition_scan(traits::local(first), traits::local(last), pred, is_local_seg_t(), cat); return traits::compose(sf, r); } + else { + local_iterator f_loc = traits::local(first); + local_iterator f_end = traits::end(sf); + local_iterator l_loc = traits::local(last); + local_iterator l_beg = traits::begin(sl); - local_iterator f_loc = traits::local(first); - local_iterator f_end = traits::end(sf); - local_iterator l_loc = traits::local(last); - local_iterator l_beg = traits::begin(sl); + for (;;) { + // Phase 1: advance front to find element NOT satisfying pred + f_loc = boost::container::segmented_find_if_not(f_loc, f_end, pred); - for(;;) { - // Phase 1: advance front to find element NOT satisfying pred - while(f_loc != f_end && pred(*f_loc)) - ++f_loc; - - if(f_loc == f_end) { - ++sf; - if(sf == sl) { - local_iterator r = partition_scan(l_beg, l_loc, pred, is_local_seg_t(), cat); - return traits::compose(sf, r); - } - f_loc = traits::begin(sf); - f_end = traits::end(sf); - continue; - } - - // Phase 2: retreat back to find element satisfying pred - for(;;) { - if(l_loc == l_beg) { - --sl; - if(sf == sl) { - local_iterator r = partition_scan(f_loc, f_end, pred, is_local_seg_t(), cat); + if (f_loc == f_end) { + ++sf; + if (sf == sl) { + local_iterator r = partition_scan(l_beg, l_loc, pred, is_local_seg_t(), cat); return traits::compose(sf, r); } - l_beg = traits::begin(sl); - l_loc = traits::end(sl); + f_loc = traits::begin(sf); + f_end = traits::end(sf); + continue; } - --l_loc; - if(pred(*l_loc)) break; - } - boost::adl_move_swap(*f_loc, *l_loc); - ++f_loc; + // Phase 2: retreat back to find element satisfying pred + for (;;) { + if (l_loc == l_beg) { + --sl; + if (sf == sl) { + local_iterator r = partition_scan(f_loc, f_end, pred, is_local_seg_t(), cat); + return traits::compose(sf, r); + } + l_beg = traits::begin(sl); + l_loc = traits::end(sl); + } + --l_loc; + if (pred(*l_loc)) break; + } + + boost::adl_move_swap(*f_loc, *l_loc); + ++f_loc; + } } } @@ -158,6 +159,18 @@ SegIt partition_scan(SegIt first, SegIt last, Pred pred, segmented_iterator_tag, // Top-level dispatch ////////////////////////////////////////////// +template +BOOST_CONTAINER_FORCEINLINE +FwdIt segmented_partition_dispatch(FwdIt first, Sent last, Pred pred, Tag tag, const std::forward_iterator_tag &cat) +{ + first = (segmented_find_if_not)(first, last, pred); + if (first == last) + return first; + FwdIt next = first; + ++next; + return (partition_scan)(next, last, first, pred, tag, cat); +} + template BOOST_CONTAINER_FORCEINLINE FwdIt segmented_partition_dispatch(FwdIt first, Sent last, Pred pred, Tag tag, const std::bidirectional_iterator_tag& cat) @@ -165,13 +178,7 @@ FwdIt segmented_partition_dispatch(FwdIt first, Sent last, Pred pred, Tag tag, c return (partition_scan)(first, last, pred, tag, cat); } -template -BOOST_CONTAINER_FORCEINLINE -FwdIt segmented_partition_dispatch(FwdIt first, Sent last, Pred pred, Tag tag, const std::forward_iterator_tag &cat) -{ - return (partition_scan)(first, last, first, pred, tag, cat); -} - +//Sentinels may only be used with forward iterators, so we can ignore the segmentation tag in that case. template struct sent_filter {