From 2085b112e201efe205386927faefb2687324b100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 6 May 2026 12:59:45 +0200 Subject: [PATCH] Add BOOST_CONTAINER_SEGMENTED_UNROLL to segmented algorithms --- .../container/experimental/segmented_copy.hpp | 1 + .../container/experimental/segmented_copy_if.hpp | 1 + .../container/experimental/segmented_copy_n.hpp | 1 + .../container/experimental/segmented_count.hpp | 1 + .../experimental/segmented_count_if.hpp | 1 + .../container/experimental/segmented_equal.hpp | 1 + .../container/experimental/segmented_fill.hpp | 1 + .../container/experimental/segmented_fill_n.hpp | 3 +++ .../container/experimental/segmented_find.hpp | 1 + .../container/experimental/segmented_find_if.hpp | 1 + .../experimental/segmented_find_last.hpp | 2 ++ .../experimental/segmented_find_last_if.hpp | 2 ++ .../experimental/segmented_for_each.hpp | 1 + .../experimental/segmented_generate.hpp | 1 + .../experimental/segmented_generate_n.hpp | 3 +++ .../experimental/segmented_is_sorted_until.hpp | 1 + .../experimental/segmented_mismatch.hpp | 1 + .../container/experimental/segmented_none_of.hpp | 1 + .../experimental/segmented_partition.hpp | 1 + .../experimental/segmented_partition_copy.hpp | 1 + .../experimental/segmented_partition_point.hpp | 1 + .../experimental/segmented_remove_copy.hpp | 16 ++++++++-------- .../experimental/segmented_remove_copy_if.hpp | 1 + .../container/experimental/segmented_replace.hpp | 1 + .../experimental/segmented_replace_if.hpp | 1 + .../container/experimental/segmented_reverse.hpp | 4 ++++ .../experimental/segmented_reverse_copy.hpp | 1 + .../experimental/segmented_stable_partition.hpp | 1 + .../experimental/segmented_swap_ranges.hpp | 1 + .../experimental/segmented_transform.hpp | 1 + 30 files changed, 46 insertions(+), 8 deletions(-) diff --git a/include/boost/container/experimental/segmented_copy.hpp b/include/boost/container/experimental/segmented_copy.hpp index 3a48837..3d9911e 100644 --- a/include/boost/container/experimental/segmented_copy.hpp +++ b/include/boost/container/experimental/segmented_copy.hpp @@ -99,6 +99,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c >::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) diff --git a/include/boost/container/experimental/segmented_copy_n.hpp b/include/boost/container/experimental/segmented_copy_n.hpp index c012988..a85a321 100644 --- a/include/boost/container/experimental/segmented_copy_n.hpp +++ b/include/boost/container/experimental/segmented_copy_n.hpp @@ -89,6 +89,7 @@ BOOST_CONTAINER_FORCEINLINE segduo 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; diff --git a/include/boost/container/experimental/segmented_count.hpp b/include/boost/container/experimental/segmented_count.hpp index 16f0be8..e14b55d 100644 --- a/include/boost/container/experimental/segmented_count.hpp +++ b/include/boost/container/experimental/segmented_count.hpp @@ -111,6 +111,7 @@ segmented_count_dispatch typedef typename boost::container::iterator_traits::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(*first == value); diff --git a/include/boost/container/experimental/segmented_count_if.hpp b/include/boost/container/experimental/segmented_count_if.hpp index 45ca816..a7c1e08 100644 --- a/include/boost/container/experimental/segmented_count_if.hpp +++ b/include/boost/container/experimental/segmented_count_if.hpp @@ -109,6 +109,7 @@ segmented_count_if_dispatch typedef typename boost::container::iterator_traits::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(pred(*first)); diff --git a/include/boost/container/experimental/segmented_equal.hpp b/include/boost/container/experimental/segmented_equal.hpp index 0d6c406..33acdab 100644 --- a/include/boost/container/experimental/segmented_equal.hpp +++ b/include/boost/container/experimental/segmented_equal.hpp @@ -110,6 +110,7 @@ typename algo_enable_if_c >::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; diff --git a/include/boost/container/experimental/segmented_fill.hpp b/include/boost/container/experimental/segmented_fill.hpp index 0d15eae..bbdbd1a 100644 --- a/include/boost/container/experimental/segmented_fill.hpp +++ b/include/boost/container/experimental/segmented_fill.hpp @@ -72,6 +72,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c< !Tag::value || is_sentinel::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; } diff --git a/include/boost/container/experimental/segmented_fill_n.hpp b/include/boost/container/experimental/segmented_fill_n.hpp index ceddd6d..6c6855c 100644 --- a/include/boost/container/experimental/segmented_fill_n.hpp +++ b/include/boost/container/experimental/segmented_fill_n.hpp @@ -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 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; diff --git a/include/boost/container/experimental/segmented_find.hpp b/include/boost/container/experimental/segmented_find.hpp index 1b9a164..cc2db8b 100644 --- a/include/boost/container/experimental/segmented_find.hpp +++ b/include/boost/container/experimental/segmented_find.hpp @@ -88,6 +88,7 @@ typename algo_enable_if_c< !Tag::value || is_sentinel::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; diff --git a/include/boost/container/experimental/segmented_find_if.hpp b/include/boost/container/experimental/segmented_find_if.hpp index 047f5a8..01d485f 100644 --- a/include/boost/container/experimental/segmented_find_if.hpp +++ b/include/boost/container/experimental/segmented_find_if.hpp @@ -88,6 +88,7 @@ typename algo_enable_if_c< !Tag::value || is_sentinel::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; diff --git a/include/boost/container/experimental/segmented_find_last.hpp b/include/boost/container/experimental/segmented_find_last.hpp index 0896823..d68eca4 100644 --- a/include/boost/container/experimental/segmented_find_last.hpp +++ b/include/boost/container/experimental/segmented_find_last.hpp @@ -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) diff --git a/include/boost/container/experimental/segmented_find_last_if.hpp b/include/boost/container/experimental/segmented_find_last_if.hpp index 3cdb590..566b18a 100644 --- a/include/boost/container/experimental/segmented_find_last_if.hpp +++ b/include/boost/container/experimental/segmented_find_last_if.hpp @@ -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)) diff --git a/include/boost/container/experimental/segmented_for_each.hpp b/include/boost/container/experimental/segmented_for_each.hpp index 83083d4..5110ffa 100644 --- a/include/boost/container/experimental/segmented_for_each.hpp +++ b/include/boost/container/experimental/segmented_for_each.hpp @@ -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; diff --git a/include/boost/container/experimental/segmented_generate.hpp b/include/boost/container/experimental/segmented_generate.hpp index c19ec6d..b03700a 100644 --- a/include/boost/container/experimental/segmented_generate.hpp +++ b/include/boost/container/experimental/segmented_generate.hpp @@ -73,6 +73,7 @@ template !Tag::value || is_sentinel::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(); } diff --git a/include/boost/container/experimental/segmented_generate_n.hpp b/include/boost/container/experimental/segmented_generate_n.hpp index b2b8cb3..f5f2f98 100644 --- a/include/boost/container/experimental/segmented_generate_n.hpp +++ b/include/boost/container/experimental/segmented_generate_n.hpp @@ -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 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; diff --git a/include/boost/container/experimental/segmented_is_sorted_until.hpp b/include/boost/container/experimental/segmented_is_sorted_until.hpp index d2d3217..f77328c 100644 --- a/include/boost/container/experimental/segmented_is_sorted_until.hpp +++ b/include/boost/container/experimental/segmented_is_sorted_until.hpp @@ -47,6 +47,7 @@ segduo 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; diff --git a/include/boost/container/experimental/segmented_mismatch.hpp b/include/boost/container/experimental/segmented_mismatch.hpp index 59003be..0fd59a8 100644 --- a/include/boost/container/experimental/segmented_mismatch.hpp +++ b/include/boost/container/experimental/segmented_mismatch.hpp @@ -120,6 +120,7 @@ typename algo_enable_if_c >::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; diff --git a/include/boost/container/experimental/segmented_none_of.hpp b/include/boost/container/experimental/segmented_none_of.hpp index 9a1def5..4a3b760 100644 --- a/include/boost/container/experimental/segmented_none_of.hpp +++ b/include/boost/container/experimental/segmented_none_of.hpp @@ -87,6 +87,7 @@ typename algo_enable_if_c< !Tag::value || is_sentinel::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; diff --git a/include/boost/container/experimental/segmented_partition.hpp b/include/boost/container/experimental/segmented_partition.hpp index 9b11fe5..18856b1 100644 --- a/include/boost/container/experimental/segmented_partition.hpp +++ b/include/boost/container/experimental/segmented_partition.hpp @@ -42,6 +42,7 @@ template 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); diff --git a/include/boost/container/experimental/segmented_partition_copy.hpp b/include/boost/container/experimental/segmented_partition_copy.hpp index 1a5bf6e..103ef2d 100644 --- a/include/boost/container/experimental/segmented_partition_copy.hpp +++ b/include/boost/container/experimental/segmented_partition_copy.hpp @@ -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; diff --git a/include/boost/container/experimental/segmented_partition_point.hpp b/include/boost/container/experimental/segmented_partition_point.hpp index 8378840..982f928 100644 --- a/include/boost/container/experimental/segmented_partition_point.hpp +++ b/include/boost/container/experimental/segmented_partition_point.hpp @@ -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; diff --git a/include/boost/container/experimental/segmented_remove_copy.hpp b/include/boost/container/experimental/segmented_remove_copy.hpp index a60e818..ead71be 100644 --- a/include/boost/container/experimental/segmented_remove_copy.hpp +++ b/include/boost/container/experimental/segmented_remove_copy.hpp @@ -97,6 +97,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c 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 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 r = (segmented_remove_copy_dst_bounded) - (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::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 dst_traits; return (segmented_remove_copy_dst_dispatch) (first, last, result, value, typename dst_traits::is_segmented_iterator(), Cat()); -#else +#else*/ return (segmented_remove_copy_dst_dispatch) (first, last, result, value, non_segmented_iterator_tag(), Cat()); -#endif +//#endif } template diff --git a/include/boost/container/experimental/segmented_remove_copy_if.hpp b/include/boost/container/experimental/segmented_remove_copy_if.hpp index 3b179ad..92690e7 100644 --- a/include/boost/container/experimental/segmented_remove_copy_if.hpp +++ b/include/boost/container/experimental/segmented_remove_copy_if.hpp @@ -110,6 +110,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c::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; diff --git a/include/boost/container/experimental/segmented_replace_if.hpp b/include/boost/container/experimental/segmented_replace_if.hpp index 0e3cab4..f15f550 100644 --- a/include/boost/container/experimental/segmented_replace_if.hpp +++ b/include/boost/container/experimental/segmented_replace_if.hpp @@ -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; diff --git a/include/boost/container/experimental/segmented_reverse.hpp b/include/boost/container/experimental/segmented_reverse.hpp index 7ebefe2..30526af 100644 --- a/include/boost/container/experimental/segmented_reverse.hpp +++ b/include/boost/container/experimental/segmented_reverse.hpp @@ -34,6 +34,7 @@ template 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 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 segmented_reverse_disjoint_ranges break; } #else + BOOST_CONTAINER_SEGMENTED_UNROLL(4) for(; n; --n) { --l; boost::adl_move_swap(*f, *l); diff --git a/include/boost/container/experimental/segmented_reverse_copy.hpp b/include/boost/container/experimental/segmented_reverse_copy.hpp index 071389d..23f6434 100644 --- a/include/boost/container/experimental/segmented_reverse_copy.hpp +++ b/include/boost/container/experimental/segmented_reverse_copy.hpp @@ -98,6 +98,7 @@ BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c OuterIter stable_partition_scan(FwdIt first, FwdIt last, OuterIter result, Composer composer, Pred pred, non_segmented_iterator_tag) { typedef typename boost::container::iterator_traits::value_type value_type; + BOOST_CONTAINER_SEGMENTED_UNROLL(4) for(; first != last; ++first) { if(pred(*first)) { value_type tmp = boost::move(*first); diff --git a/include/boost/container/experimental/segmented_swap_ranges.hpp b/include/boost/container/experimental/segmented_swap_ranges.hpp index dad7ab3..5f0f680 100644 --- a/include/boost/container/experimental/segmented_swap_ranges.hpp +++ b/include/boost/container/experimental/segmented_swap_ranges.hpp @@ -37,6 +37,7 @@ typename algo_enable_if_c< !Tag::value || is_sentinel::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); } diff --git a/include/boost/container/experimental/segmented_transform.hpp b/include/boost/container/experimental/segmented_transform.hpp index 90be6bf..c9606fe 100644 --- a/include/boost/container/experimental/segmented_transform.hpp +++ b/include/boost/container/experimental/segmented_transform.hpp @@ -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;