Add BOOST_CONTAINER_SEGMENTED_UNROLL to segmented algorithms

This commit is contained in:
Ion Gaztañaga
2026-05-06 12:59:45 +02:00
parent c075bafd70
commit 2085b112e2
30 changed files with 46 additions and 8 deletions
@@ -99,6 +99,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c<!DstTag::value, segduo<Src
segmented_copy_dst_bounded
(SrcIter first, Sent last, DstIter dst_first, DstSent dst_last, DstTag, SrcCat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first) {
if(dst_first == dst_last)
goto out_path;
@@ -107,6 +107,7 @@ typename algo_enable_if_c<!DstTag::value, segduo<SrcIter, DstIter> >::type
segmented_copy_if_dst_bounded
(SrcIter first, Sent last, DstIter dst_first, DstSent dst_last, Pred pred, DstTag, SrcCat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first) {
if(pred(*first)) {
if(dst_first == dst_last)
@@ -89,6 +89,7 @@ BOOST_CONTAINER_FORCEINLINE segduo<SrcIter, DstIter>
segmented_copy_n_src_dst_bounded
(SrcIter first, SrcSent last, Size& BOOST_RESTRICT count, DstIter dst_first, DstSent dst_last)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; count > 0; ++first, --count) {
if(dst_first == dst_last || first == last)
goto out_path;
@@ -111,6 +111,7 @@ segmented_count_dispatch
typedef typename boost::container::iterator_traits<InpIter>::difference_type diff_t;
diff_t n = 0;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for (; first != last; ++first)
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
n += static_cast<diff_t>(*first == value);
@@ -109,6 +109,7 @@ segmented_count_if_dispatch
typedef typename boost::container::iterator_traits<InpIter>::difference_type diff_t;
diff_t n = 0;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for (; first != last; ++first)
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
n += static_cast<diff_t>(pred(*first));
@@ -110,6 +110,7 @@ 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)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first1 != last1; ++first1) {
if(first2 == iter2_last)
goto out_path;
@@ -72,6 +72,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, FwdIt>::value>::type
segmented_fill_range(FwdIt first, Sent last, const T& value, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
*first = value;
}
@@ -65,6 +65,7 @@ OutIter fill_n_scan
break;
}
#else
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(Size cnt = local_count; cnt; ++first, --cnt)
*first = value;
#endif
@@ -80,6 +81,7 @@ OutIter fill_n_scan
{
Size local_count = count;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for (; local_count > 0 && first != last; ++first, --local_count)
*first = value;
@@ -149,6 +151,7 @@ template <class OutIt, class Size, class T>
OutIt segmented_fill_n_ref
(OutIt first, Size count, const T& value, non_segmented_iterator_tag)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; count > 0; ++first, --count)
*first = value;
return first;
@@ -88,6 +88,7 @@ typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, InpIter>::value, InpIter>::type
segmented_find_dispatch(InpIter first, Sent last, const T& value, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
if(*first == value)
break;
@@ -88,6 +88,7 @@ typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, InpIter>::value, InpIter>::type
segmented_find_if_dispatch(InpIter first, Sent last, Pred pred, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
if(pred(*first))
break;
@@ -41,6 +41,7 @@ FwdIt find_last_scan(FwdIt first, Sent last, const T& value,
non_segmented_iterator_tag, const std::forward_iterator_tag&)
{
FwdIt result = last;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for (; first != last; ++first)
if (*first == value)
result = first;
@@ -53,6 +54,7 @@ BidirIt find_last_scan(BidirIt first, BidirIt last, const T& value,
non_segmented_iterator_tag, const std::bidirectional_iterator_tag&)
{
BidirIt cur = last;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
while (cur != first) {
--cur;
if (*cur == value)
@@ -41,6 +41,7 @@ FwdIt find_last_if_scan(FwdIt first, Sent last, Pred pred,
non_segmented_iterator_tag, const std::forward_iterator_tag&)
{
FwdIt result = last;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for (; first != last; ++first)
if (pred(*first))
result = first;
@@ -53,6 +54,7 @@ BidirIt find_last_if_scan(BidirIt first, BidirIt last, Pred pred,
non_segmented_iterator_tag, const std::bidirectional_iterator_tag&)
{
BidirIt cur = last;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
while (cur != first) {
--cur;
if (pred(*cur))
@@ -75,6 +75,7 @@ BOOST_CONTAINER_FORCEINLINE
segmented_for_each_dispatch
(InpIter first, Sent last, F f, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
f(*first);
return f;
@@ -73,6 +73,7 @@ template <class FwdIt, class Sent, class Generator, class Tag, class Cat>
!Tag::value || is_sentinel<Sent, FwdIt>::value>::type
segmented_generate_dispatch(FwdIt first, const Sent last, Generator & BOOST_RESTRICT gen, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
*first = gen();
}
@@ -65,6 +65,7 @@ OutIter generate_n_scan
break;
}
#else
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(Size cnt = local_count; cnt; ++first, --cnt)
*first = gen();
#endif
@@ -80,6 +81,7 @@ OutIter generate_n_scan
{
Size local_count = count;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for (; local_count > 0 && first != last; ++first, --local_count)
*first = gen();
@@ -149,6 +151,7 @@ template <class OutIt, class Size, class Generator>
OutIt segmented_generate_n_ref
(OutIt first, Size count, Generator& BOOST_RESTRICT gen, non_segmented_iterator_tag)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; count > 0; ++first, --count)
*first = gen();
return first;
@@ -47,6 +47,7 @@ segduo<FwdIt, DeepIt> sorted_until_rec
(FwdIt first, Sent last, Comp comp,
DeepIt prev, const non_segmented_iterator_tag &, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for (; first != last; ++first) {
if (comp(*first, *prev))
break;
@@ -120,6 +120,7 @@ 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)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first1 != last1; ++first1) {
if(first2 == iter2_last || !pred(*first1, *first2))
break;
@@ -87,6 +87,7 @@ typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, InpIter>::value, bool>::type
segmented_none_of_dispatch(InpIter first, Sent last, Pred pred, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
if(pred(*first))
return false;
@@ -42,6 +42,7 @@ template <class FwdIt, class Sent, class OutIter, class Pred>
BOOST_CONTAINER_FORCEINLINE
OutIter partition_scan(FwdIt first, Sent last, OutIter result, Pred pred, non_segmented_iterator_tag, const std::forward_iterator_tag &)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first) {
if(pred(*first)) {
boost::adl_move_swap(*result, *first);
@@ -88,6 +88,7 @@ typename algo_enable_if_c<
segmented_partition_copy_dispatch
(InIter first, Sent last, OutIter1 out_true, OutIter2 out_false, Pred pred, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first) {
if(pred(*first)) {
*out_true = *first;
@@ -87,6 +87,7 @@ typename algo_enable_if_c<
segmented_partition_point_dispatch
(FwdIt first, Sent last, Predicate pred, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
if(!pred(*first))
return first;
@@ -97,6 +97,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c<!DstTag::value, segduo<Src
segmented_remove_copy_dst_bounded
(SrcIter first, Sent last, DstIter dst_first, DstSent dst_last, const T& value, DstTag, SrcCat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first) {
if(!(*first == value)) {
if(dst_first == dst_last)
@@ -163,7 +164,7 @@ BOOST_CONTAINER_FORCEINLINE DstIter segmented_remove_copy_dst_dispatch
template <bool Move, class SrcIter, class Sent, class SegDstIter, class T, class Cat>
SegDstIter segmented_remove_copy_dst_dispatch
(SrcIter first, Sent last, SegDstIter result, const T& value,
(SrcIter first, const Sent last, SegDstIter result, const T& value,
const segmented_iterator_tag &, Cat)
{
typedef segmented_iterator_traits<SegDstIter> dst_traits;
@@ -178,11 +179,10 @@ SegDstIter segmented_remove_copy_dst_dispatch
dst_local_iterator dst_local = dst_traits::local(result);
while(1) {
const dst_local_iterator dst_end = dst_traits::end(dst_seg);
const segduo<SrcIter, dst_local_iterator> r = (segmented_remove_copy_dst_bounded<Move>)
(first, last, dst_local, dst_end, value, dst_is_local_seg_t(), Cat());
first = r.first;
if(first != last) {
(first, last, dst_local, dst_traits::end(dst_seg), value, dst_is_local_seg_t(), Cat());
if(r.first != last) {
first = r.first;
++dst_seg;
dst_local = dst_traits::begin(dst_seg);
}
@@ -204,15 +204,15 @@ typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, SrcIter>::value, OutIter>::type
segmented_remove_copy_dispatch
(SrcIter first, Sent last, OutIter result, const T& value, Tag, Cat)
{
{/*
#if !defined(BOOST_CONTAINER_DISABLE_MULTI_SEGMENTED_ALGO)
typedef segmented_iterator_traits<OutIter> dst_traits;
return (segmented_remove_copy_dst_dispatch<Move>)
(first, last, result, value, typename dst_traits::is_segmented_iterator(), Cat());
#else
#else*/
return (segmented_remove_copy_dst_dispatch<Move>)
(first, last, result, value, non_segmented_iterator_tag(), Cat());
#endif
//#endif
}
template <bool Move, class SegIter, class OutIter, class T, class Cat>
@@ -110,6 +110,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c<!DstTag::value, segduo<Src
segmented_remove_copy_if_dst_bounded
(SrcIter first, Sent last, DstIter dst_first, DstSent dst_last, Pred pred, DstTag, SrcCat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first) {
if(!pred(*first)) {
if(dst_first == dst_last)
@@ -73,6 +73,7 @@ typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, FwdIt>::value>::type
segmented_replace_dispatch(FwdIt first, Sent last, const T& BOOST_RESTRICT old_val, const T& BOOST_RESTRICT new_val, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
if(*first == old_val)
*first = new_val;
@@ -73,6 +73,7 @@ typename algo_enable_if_c<
BOOST_CONTAINER_FORCEINLINE
segmented_replace_if_dispatch(FwdIt first, Sent last, Pred pred, const T& BOOST_RESTRICT new_val, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first)
if(pred(*first))
*first = new_val;
@@ -34,6 +34,7 @@ template <class BidirIt, class Cat>
BOOST_CONTAINER_FORCEINLINE
void segmented_reverse_dispatch(BidirIt first, BidirIt last, non_segmented_iterator_tag, const Cat &)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
while(first != last && first != --last) {
boost::adl_move_swap(*first, *last);
++first;
@@ -70,6 +71,7 @@ void segmented_reverse_dispatch(RAIter first, RAIter last, non_segmented_iterato
break;
}
#else
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; pairs; --pairs) {
--last;
boost::adl_move_swap(*first, *last);
@@ -90,6 +92,7 @@ BOOST_CONTAINER_FORCEINLINE
segduo<It, It> segmented_reverse_disjoint_ranges
(It f, It const f_end, It const l_beg, It l, non_segmented_iterator_tag, const Cat &)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
while (f != f_end && l != l_beg) {
--l;
boost::adl_move_swap(*f, *l);
@@ -132,6 +135,7 @@ segduo<It, It> segmented_reverse_disjoint_ranges
break;
}
#else
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; n; --n) {
--l;
boost::adl_move_swap(*f, *l);
@@ -98,6 +98,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c<!DstTag::value, segduo<Bid
segmented_reverse_copy_dst_bounded
(BidirIter first, BidirIter last, DstIter dst_first, DstSent dst_last, DstTag, SrcCat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
while(first != last) {
if(dst_first == dst_last)
goto out_path;
@@ -74,6 +74,7 @@ template <class FwdIt, class OuterIter, class Composer, class Pred>
OuterIter stable_partition_scan(FwdIt first, FwdIt last, OuterIter result, Composer composer, Pred pred, non_segmented_iterator_tag)
{
typedef typename boost::container::iterator_traits<OuterIter>::value_type value_type;
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first) {
if(pred(*first)) {
value_type tmp = boost::move(*first);
@@ -37,6 +37,7 @@ typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, FwdIt1>::value, FwdIt2>::type
segmented_swap_ranges_dispatch (FwdIt1 first1, Sent last1, FwdIt2 first2, Tag)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first1 != last1; ++first1, ++first2) {
boost::adl_move_swap(*first1, *first2);
}
@@ -75,6 +75,7 @@ typename algo_enable_if_c<
segmented_transform_dispatch
(InIter first, Sent last, OutIter result, UnaryOp op, Tag, Cat)
{
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
for(; first != last; ++first, ++result)
*result = op(*first);
return result;