From 8cb5c0f093475f7a58cb8bc622eeb2c6eafe4ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 25 Apr 2026 01:04:16 +0200 Subject: [PATCH] Make segmented_copy multi segmented --- .../experimental/segmented_reverse_copy.hpp | 180 +++++++++++++++--- 1 file changed, 158 insertions(+), 22 deletions(-) diff --git a/include/boost/container/experimental/segmented_reverse_copy.hpp b/include/boost/container/experimental/segmented_reverse_copy.hpp index 6d29e65..d360e34 100644 --- a/include/boost/container/experimental/segmented_reverse_copy.hpp +++ b/include/boost/container/experimental/segmented_reverse_copy.hpp @@ -31,53 +31,187 @@ OutIter segmented_reverse_copy(BidirIter first, BidirIter last, OutIter result); namespace detail_algo { -template -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 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 -OutIter segmented_reverse_copy_dispatch - (RAIter first, RAIter last, OutIter result, non_segmented_iterator_tag, const std::random_access_iterator_tag &) +template +BOOST_CONTAINER_FORCEINLINE segduo 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::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(last, dst_first); } #endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING +template +BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c >::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(last, dst_first); +} + +template +segduo segmented_reverse_copy_dst_bounded + (BidirIter first, BidirIter last, SegDstIter dst_first, SegDstIter dst_last, + segmented_iterator_tag, SrcCat) +{ + typedef segmented_iterator_traits 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::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 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(r.first, dst_traits::compose(sfirst, r.second)); + } + else { + segduo 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(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(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(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 +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 +SegDstIter segmented_reverse_copy_dst_dispatch + (BidirIter first, BidirIter last, SegDstIter result, + const segmented_iterator_tag &, Cat) +{ + typedef segmented_iterator_traits 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::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 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 +BOOST_CONTAINER_FORCEINLINE +typename algo_enable_if_c::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 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 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 BOOST_CONTAINER_FORCEINLINE OutIter segmented_reverse_copy(BidirIter first, BidirIter last, OutIter result)