Use segmented_find_if_not to simplify the implementation and improve multi-level segmentation support.

This commit is contained in:
Ion Gaztañaga
2026-03-20 13:42:09 +01:00
parent 9ae621b01d
commit 34636439eb
@@ -21,6 +21,7 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/experimental/segmented_iterator_traits.hpp>
#include <boost/container/experimental/segmented_find_if_not.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <boost/container/detail/iterator.hpp>
@@ -49,7 +50,7 @@ OutIter partition_scan(FwdIt first, Sent last, OutIter result, Pred pred, non_se
}
template <class SegIt, class OutIter, class Pred>
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<SegIt> 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 <class FwdIt, class Sent, class Pred, class Tag>
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 <class FwdIt, class Sent, class Pred, class Tag>
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 <class FwdIt, class Sent, class Pred, class Tag>
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<class It, class Sent, class Seg, class Tag>
struct sent_filter
{