mirror of
https://github.com/boostorg/container.git
synced 2026-07-07 13:00:49 +02:00
Make segmented_copy multi segmented
This commit is contained in:
@@ -31,53 +31,187 @@ OutIter segmented_reverse_copy(BidirIter first, BidirIter last, OutIter result);
|
||||
|
||||
namespace detail_algo {
|
||||
|
||||
template <class BidirIter, class OutIter, class Cat>
|
||||
OutIter segmented_reverse_copy_dispatch
|
||||
(BidirIter first, BidirIter last, OutIter result, non_segmented_iterator_tag, const Cat &)
|
||||
{
|
||||
while(first != last) {
|
||||
--last;
|
||||
*result = *last;
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Bounded destination helper: reverse-copies from [first, last) into
|
||||
// [dst_first, dst_last), reading backward from last toward first,
|
||||
// writing forward into dst.
|
||||
// Returns segduo<BidirIter, DstIter> where .first is the updated source
|
||||
// read position (last, moved backward) and .second is the updated dst.
|
||||
// When dst_last is unreachable_sentinel_t the destination-full check
|
||||
// is optimised away, giving the same code as an unbounded loop.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class RAIter, class OutIter>
|
||||
OutIter segmented_reverse_copy_dispatch
|
||||
(RAIter first, RAIter last, OutIter result, non_segmented_iterator_tag, const std::random_access_iterator_tag &)
|
||||
template <class RAIter, class DstIter, class DstSent>
|
||||
BOOST_CONTAINER_FORCEINLINE segduo<RAIter, DstIter> segmented_reverse_copy_dst_bounded
|
||||
(RAIter first, RAIter last, DstIter dst_first, DstSent dst_last,
|
||||
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
{
|
||||
typedef typename iterator_traits<RAIter>::difference_type difference_type;
|
||||
|
||||
difference_type n = last - first;
|
||||
|
||||
while(n >= difference_type(4)) {
|
||||
--last; *result = *last; ++result;
|
||||
--last; *result = *last; ++result;
|
||||
--last; *result = *last; ++result;
|
||||
--last; *result = *last; ++result;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last; *dst_first = *last; ++dst_first;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last; *dst_first = *last; ++dst_first;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last; *dst_first = *last; ++dst_first;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last; *dst_first = *last; ++dst_first;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch(n) {
|
||||
case 3:
|
||||
--last; *result = *last; ++result;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last; *dst_first = *last; ++dst_first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
--last; *result = *last; ++result;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last; *dst_first = *last; ++dst_first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
--last; *result = *last; ++result;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last; *dst_first = *last; ++dst_first;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
out_path:
|
||||
return segduo<RAIter, DstIter>(last, dst_first);
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
template <class BidirIter, class DstIter, class DstSent, class DstTag, class SrcCat>
|
||||
BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c<!DstTag::value, segduo<BidirIter, DstIter> >::type
|
||||
segmented_reverse_copy_dst_bounded
|
||||
(BidirIter first, BidirIter last, DstIter dst_first, DstSent dst_last, DstTag, SrcCat)
|
||||
{
|
||||
while(first != last) {
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
--last;
|
||||
*dst_first = *last;
|
||||
++dst_first;
|
||||
}
|
||||
out_path:
|
||||
return segduo<BidirIter, DstIter>(last, dst_first);
|
||||
}
|
||||
|
||||
template <class BidirIter, class SegDstIter, class SrcCat>
|
||||
segduo<BidirIter, SegDstIter> segmented_reverse_copy_dst_bounded
|
||||
(BidirIter first, BidirIter last, SegDstIter dst_first, SegDstIter dst_last,
|
||||
segmented_iterator_tag, SrcCat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
dst_segment_iterator sfirst = dst_traits::segment(dst_first);
|
||||
const dst_segment_iterator slast = dst_traits::segment(dst_last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
segduo<BidirIter, dst_local_iterator> r = (segmented_reverse_copy_dst_bounded)
|
||||
(first, last, dst_traits::local(dst_first), dst_traits::local(dst_last), dst_is_local_seg_t(), SrcCat());
|
||||
return segduo<BidirIter, SegDstIter>(r.first, dst_traits::compose(sfirst, r.second));
|
||||
}
|
||||
else {
|
||||
segduo<BidirIter, dst_local_iterator> r = (segmented_reverse_copy_dst_bounded)
|
||||
(first, last, dst_traits::local(dst_first), dst_traits::end(sfirst), dst_is_local_seg_t(), SrcCat());
|
||||
last = r.first;
|
||||
if(first == last)
|
||||
return segduo<BidirIter, SegDstIter>(last, dst_traits::compose(sfirst, r.second));
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst) {
|
||||
r = (segmented_reverse_copy_dst_bounded)
|
||||
(first, last, dst_traits::begin(sfirst), dst_traits::end(sfirst), dst_is_local_seg_t(), SrcCat());
|
||||
last = r.first;
|
||||
if(first == last)
|
||||
return segduo<BidirIter, SegDstIter>(last, dst_traits::compose(sfirst, r.second));
|
||||
}
|
||||
|
||||
r = (segmented_reverse_copy_dst_bounded)
|
||||
(first, last, dst_traits::begin(slast), dst_traits::local(dst_last), dst_is_local_seg_t(), SrcCat());
|
||||
return segduo<BidirIter, SegDstIter>(r.first, dst_traits::compose(sfirst, r.second));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Destination dispatch: routes to bounded helper.
|
||||
// Non-segmented destination: single unbounded call (unreachable_sentinel_t).
|
||||
// Segmented destination: loop over destination segments, bounded per segment.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class BidirIter, class DstIter, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE DstIter segmented_reverse_copy_dst_dispatch
|
||||
(BidirIter first, BidirIter last, DstIter result,
|
||||
const non_segmented_iterator_tag &, Cat)
|
||||
{
|
||||
return (segmented_reverse_copy_dst_bounded)
|
||||
(first, last, result, unreachable_sentinel_t(), non_segmented_iterator_tag(), Cat()).second;
|
||||
}
|
||||
|
||||
template <class BidirIter, class SegDstIter, class Cat>
|
||||
SegDstIter segmented_reverse_copy_dst_dispatch
|
||||
(BidirIter first, BidirIter last, SegDstIter result,
|
||||
const segmented_iterator_tag &, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
if(first == last)
|
||||
return result;
|
||||
|
||||
dst_segment_iterator dst_seg = dst_traits::segment(result);
|
||||
dst_local_iterator dst_local = dst_traits::local(result);
|
||||
|
||||
while(1) {
|
||||
const dst_local_iterator dst_end = dst_traits::end(dst_seg);
|
||||
const segduo<BidirIter, dst_local_iterator> r = (segmented_reverse_copy_dst_bounded)
|
||||
(first, last, dst_local, dst_end, dst_is_local_seg_t(), Cat());
|
||||
last = r.first;
|
||||
if(first != last) {
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
else
|
||||
return dst_traits::compose(dst_seg, r.second);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Source dispatch: walks the source (read pointer) segments in reverse
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class BidirIter, class OutIter, class Tag, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename algo_enable_if_c<!Tag::value, OutIter>::type
|
||||
segmented_reverse_copy_dispatch(BidirIter first, BidirIter last, OutIter result, Tag, Cat)
|
||||
{
|
||||
#if !defined(BOOST_CONTAINER_DISABLE_MULTI_SEGMENTED_ALGO)
|
||||
typedef segmented_iterator_traits<OutIter> dst_traits;
|
||||
return (segmented_reverse_copy_dst_dispatch)
|
||||
(first, last, result, typename dst_traits::is_segmented_iterator(), Cat());
|
||||
#else
|
||||
return (segmented_reverse_copy_dst_dispatch)
|
||||
(first, last, result, non_segmented_iterator_tag(), Cat());
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class SegIter, class OutIter, class Cat>
|
||||
OutIter segmented_reverse_copy_dispatch
|
||||
(SegIter first, SegIter last, OutIter result, segmented_iterator_tag, Cat)
|
||||
@@ -111,6 +245,8 @@ OutIter segmented_reverse_copy_dispatch
|
||||
//! in reverse order. When the source range uses segmented iterators,
|
||||
//! exploits segmentation by walking segments in reverse order, processing
|
||||
//! each local range without per-element segment-boundary overhead.
|
||||
//! When the output range also uses segmented iterators, walks output
|
||||
//! segments as well (dual-segmented / multi-segmented dispatch).
|
||||
//! Returns the output iterator past the last element written.
|
||||
template <class BidirIter, class OutIter>
|
||||
BOOST_CONTAINER_FORCEINLINE OutIter segmented_reverse_copy(BidirIter first, BidirIter last, OutIter result)
|
||||
|
||||
Reference in New Issue
Block a user