mirror of
https://github.com/boostorg/container.git
synced 2026-07-05 18:30:45 +02:00
Use segmented_find_if_not to simplify the implementation and improve multi-level segmentation support.
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user