Apply dual random access optimization to several algorithms

This commit is contained in:
Ion Gaztañaga
2026-04-26 00:41:41 +02:00
parent aee0821aa4
commit ff744ecf2f
7 changed files with 170 additions and 3 deletions
@@ -109,6 +109,26 @@ segmented_copy_dst_bounded
return segduo<SrcIter, DstIter>(first, dst_first);
}
#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION)
template <class RASrcIter, class RADstIter>
BOOST_CONTAINER_FORCEINLINE
typename iterator_enable_if_tag
<RADstIter, std::random_access_iterator_tag, segduo<RASrcIter, RADstIter> >::type
segmented_copy_dst_bounded
(RASrcIter first, RASrcIter last, RADstIter dst_first, RADstIter dst_last,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag)
{
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
const difference_type src_n = last - first;
const difference_type dst_n = difference_type(dst_last - dst_first);
const difference_type n = src_n < dst_n ? src_n : dst_n;
return (segmented_copy_dst_bounded)(first, first + n, dst_first, unreachable_sentinel_t(),
non_segmented_iterator_tag(), src_tag);
}
#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
template <class SrcIter, class Sent, class SegDstIter, class SrcCat>
segduo<SrcIter, SegDstIter> segmented_copy_dst_bounded
(SrcIter first, Sent last, SegDstIter dst_first, SegDstIter dst_last,
@@ -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/wrapped_iterator.hpp>
#include <boost/container/detail/iterator.hpp>
namespace boost {
@@ -97,6 +98,36 @@ segmented_copy_if_dst_bounded
return segduo<SrcIter, DstIter>(first, dst_first);
}
#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION)
template <class RASrcIter, class RADstIter, class Pred>
BOOST_CONTAINER_FORCEINLINE
typename iterator_enable_if_tag
<RADstIter, std::random_access_iterator_tag, segduo<RASrcIter, RADstIter> >::type
segmented_copy_if_dst_bounded
(RASrcIter first, RASrcIter last, RADstIter dst_first, RADstIter dst_last, Pred pred,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag)
{
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
const difference_type src_n = last - first;
const difference_type dst_n = difference_type(dst_last - dst_first);
if (dst_n >= src_n) {
return (segmented_copy_if_dst_bounded)(first, last, dst_first, unreachable_sentinel_t(),
pred, non_segmented_iterator_tag(), src_tag);
}
else {
//Dispatch to normal loop declaring the destination as bidirectional
//to avoid recursion and stack overflow
return (segmented_copy_if_dst_bounded)
( first, last
, make_wrapped_iterator<std::bidirectional_iterator_tag>(dst_first)
, make_wrapped_iterator<std::bidirectional_iterator_tag>(dst_last)
, pred, non_segmented_iterator_tag(), src_tag);
}
}
#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
template <class SrcIter, class Sent, class SegDstIter, class Pred, class SrcCat>
segduo<SrcIter, SegDstIter> segmented_copy_if_dst_bounded
(SrcIter first, Sent last, SegDstIter dst_first, SegDstIter dst_last, Pred pred,
@@ -99,6 +99,26 @@ segmented_copy_n_dst_bounded
return segduo<SrcIter, DstIter>(first, dst_first);
}
#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION)
template <class RASrcIter, class Size, class RADstIter>
BOOST_CONTAINER_FORCEINLINE
typename iterator_enable_if_tag
<RADstIter, std::random_access_iterator_tag, segduo<RASrcIter, RADstIter> >::type
segmented_copy_n_dst_bounded
(RASrcIter first, Size& count, RADstIter dst_first, RADstIter dst_last,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag)
{
typedef typename iterator_traits<RADstIter>::difference_type difference_type;
const difference_type dst_n = dst_last - dst_first;
Size n = count < Size(dst_n) ? count : Size(dst_n);
count -= n; //Decrement before n is modified
return (segmented_copy_n_dst_bounded)(first, n, dst_first, unreachable_sentinel_t(),
non_segmented_iterator_tag(), src_tag);
}
#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
template <class SrcIter, class Size, class SegDstIter, class SrcCat>
segduo<SrcIter, SegDstIter> segmented_copy_n_dst_bounded
(SrcIter first, Size& count, SegDstIter dst_first, SegDstIter dst_last,
@@ -289,10 +309,10 @@ BOOST_CONTAINER_FORCEINLINE OutIter segmented_copy_n_dispatch
#if !defined(BOOST_CONTAINER_DISABLE_MULTI_SEGMENTED_ALGO)
typedef segmented_iterator_traits<OutIter> dst_traits;
return (segmented_copy_n_dst_dispatch)
(first, count, result, typename dst_traits::is_segmented_iterator(), std::random_access_iterator_tag());
(first, count, result, typename dst_traits::is_segmented_iterator(), src_tag);
#else
return (segmented_copy_n_dst_dispatch)
(first, count, result, non_segmented_iterator_tag(), std::random_access_iterator_tag());
(first, count, result, non_segmented_iterator_tag(), src_tag);
#endif
}
@@ -54,6 +54,7 @@ struct equal_pred
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
template <class RASrcIter, class Iter2, class Iter2Sent, class BinaryPred>
BOOST_CONTAINER_FORCEINLINE
segduo<RASrcIter, Iter2> segmented_equal_iter2_bounded
(RASrcIter first1, RASrcIter last1, Iter2 first2, Iter2Sent iter2_last, BinaryPred pred,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
@@ -104,6 +105,7 @@ segduo<RASrcIter, Iter2> segmented_equal_iter2_bounded
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
template <class SrcIter, class Sent, class Iter2, class Iter2Sent, class BinaryPred, class Iter2Tag, class SrcCat>
BOOST_CONTAINER_FORCEINLINE
typename algo_enable_if_c<!Iter2Tag::value, segduo<SrcIter, Iter2> >::type
segmented_equal_iter2_bounded
(SrcIter first1, Sent last1, Iter2 first2, Iter2Sent iter2_last, BinaryPred pred, Iter2Tag, SrcCat)
@@ -119,6 +121,26 @@ segmented_equal_iter2_bounded
return segduo<SrcIter, Iter2>(first1, first2);
}
#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION)
template <class RASrcIter, class RAIter2, class BinaryPred>
BOOST_CONTAINER_FORCEINLINE
typename iterator_enable_if_tag
<RAIter2, std::random_access_iterator_tag, segduo<RASrcIter, RAIter2> >::type
segmented_equal_iter2_bounded
(RASrcIter first1, RASrcIter last1, RAIter2 first2, RAIter2 iter2_last, BinaryPred pred,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag)
{
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
const difference_type src_n = last1 - first1;
const difference_type iter2_n = difference_type(iter2_last - first2);
const difference_type n = src_n < iter2_n ? src_n : iter2_n;
return (segmented_equal_iter2_bounded)(first1, first1 + n, first2, unreachable_sentinel_t(),
pred, non_segmented_iterator_tag(), src_tag);
}
#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
template <class SrcIter, class Sent, class SegIter2, class BinaryPred, class SrcCat>
segduo<SrcIter, SegIter2> segmented_equal_iter2_bounded
(SrcIter first1, Sent last1, SegIter2 iter2_first, SegIter2 iter2_last, BinaryPred pred,
@@ -64,6 +64,7 @@ struct mismatch_equal
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
template <class RASrcIter, class Iter2, class Iter2Sent, class BinaryPred>
BOOST_CONTAINER_FORCEINLINE
segduo<RASrcIter, Iter2> segmented_mismatch_iter2_bounded
(RASrcIter first1, RASrcIter last1, Iter2 first2, Iter2Sent iter2_last, BinaryPred pred,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
@@ -114,6 +115,7 @@ segduo<RASrcIter, Iter2> segmented_mismatch_iter2_bounded
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
template <class SrcIter, class Sent, class Iter2, class Iter2Sent, class BinaryPred, class Iter2Tag, class SrcCat>
BOOST_CONTAINER_FORCEINLINE
typename algo_enable_if_c<!Iter2Tag::value, segduo<SrcIter, Iter2> >::type
segmented_mismatch_iter2_bounded
(SrcIter first1, Sent last1, Iter2 first2, Iter2Sent iter2_last, BinaryPred pred, Iter2Tag, SrcCat)
@@ -129,6 +131,26 @@ segmented_mismatch_iter2_bounded
return segduo<SrcIter, Iter2>(first1, first2);
}
#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION)
template <class RASrcIter, class RAIter2, class BinaryPred>
BOOST_CONTAINER_FORCEINLINE
typename iterator_enable_if_tag
<RAIter2, std::random_access_iterator_tag, segduo<RASrcIter, RAIter2> >::type
segmented_mismatch_iter2_bounded
(RASrcIter first1, RASrcIter last1, RAIter2 first2, RAIter2 iter2_last, BinaryPred pred,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag)
{
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
const difference_type src_n = last1 - first1;
const difference_type iter2_n = difference_type(iter2_last - first2);
const difference_type n = src_n < iter2_n ? src_n : iter2_n;
return (segmented_mismatch_iter2_bounded)(first1, first1 + n, first2, unreachable_sentinel_t(),
pred, non_segmented_iterator_tag(), src_tag);
}
#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
template <class SrcIter, class Sent, class SegIter2, class BinaryPred, class SrcCat>
segduo<SrcIter, SegIter2> segmented_mismatch_iter2_bounded
(SrcIter first1, Sent last1, SegIter2 iter2_first, SegIter2 iter2_last, BinaryPred pred,
@@ -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/wrapped_iterator.hpp>
#include <boost/container/detail/iterator.hpp>
#include <boost/move/utility_core.hpp>
@@ -48,7 +49,8 @@ namespace detail_algo {
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
template <bool Move, class RASrcIter, class DstIter, class DstSent, class Pred>
BOOST_CONTAINER_FORCEINLINE segduo<RASrcIter, DstIter> segmented_remove_copy_if_dst_bounded
BOOST_CONTAINER_FORCEINLINE
segduo<RASrcIter, DstIter> segmented_remove_copy_if_dst_bounded
(RASrcIter first, RASrcIter last, DstIter dst_first, DstSent dst_last, Pred pred,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
{
@@ -100,6 +102,36 @@ segmented_remove_copy_if_dst_bounded
return segduo<SrcIter, DstIter>(first, dst_first);
}
#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION)
template <bool Move, class RASrcIter, class RADstIter, class Pred>
BOOST_CONTAINER_FORCEINLINE
typename iterator_enable_if_tag
<RADstIter, std::random_access_iterator_tag, segduo<RASrcIter, RADstIter> >::type
segmented_remove_copy_if_dst_bounded
(RASrcIter first, RASrcIter last, RADstIter dst_first, RADstIter dst_last, Pred pred,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag)
{
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
const difference_type src_n = last - first;
const difference_type dst_n = difference_type(dst_last - dst_first);
if (dst_n >= src_n) {
return (segmented_remove_copy_if_dst_bounded<Move>)(first, last, dst_first, unreachable_sentinel_t(),
pred, non_segmented_iterator_tag(), src_tag);
}
else {
//Dispatch to normal loop declaring the destination as bidirectional
//to avoid recursion and stack overflow
return (segmented_remove_copy_if_dst_bounded<Move>)
( first, last
, make_wrapped_iterator<std::bidirectional_iterator_tag>(dst_first)
, make_wrapped_iterator<std::bidirectional_iterator_tag>(dst_last)
, pred, non_segmented_iterator_tag(), src_tag);
}
}
#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
template <bool Move, class SrcIter, class Sent, class SegDstIter, class Pred, class SrcCat>
segduo<SrcIter, SegDstIter> segmented_remove_copy_if_dst_bounded
(SrcIter first, Sent last, SegDstIter dst_first, SegDstIter dst_last, Pred pred,
@@ -109,6 +109,26 @@ segmented_reverse_copy_dst_bounded
return segduo<BidirIter, DstIter>(last, dst_first);
}
#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION)
template <class RASrcIter, class RADstIter>
BOOST_CONTAINER_FORCEINLINE
typename iterator_enable_if_tag
<RADstIter, std::random_access_iterator_tag, segduo<RASrcIter, RADstIter> >::type
segmented_reverse_copy_dst_bounded
(RASrcIter first, RASrcIter last, RADstIter dst_first, RADstIter dst_last,
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag)
{
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
const difference_type src_n = last - first;
const difference_type dst_n = difference_type(dst_last - dst_first);
const difference_type n = src_n < dst_n ? src_n : dst_n;
return (segmented_reverse_copy_dst_bounded)(last - n, last, dst_first, unreachable_sentinel_t(),
non_segmented_iterator_tag(), src_tag);
}
#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
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,