diff --git a/include/boost/container/experimental/segmented_copy.hpp b/include/boost/container/experimental/segmented_copy.hpp index 7cb3fdc..3a48837 100644 --- a/include/boost/container/experimental/segmented_copy.hpp +++ b/include/boost/container/experimental/segmented_copy.hpp @@ -109,6 +109,26 @@ segmented_copy_dst_bounded return segduo(first, dst_first); } +#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION) + +template +BOOST_CONTAINER_FORCEINLINE +typename iterator_enable_if_tag + >::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::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 segduo segmented_copy_dst_bounded (SrcIter first, Sent last, SegDstIter dst_first, SegDstIter dst_last, diff --git a/include/boost/container/experimental/segmented_copy_if.hpp b/include/boost/container/experimental/segmented_copy_if.hpp index 4c39337..b14bf0e 100644 --- a/include/boost/container/experimental/segmented_copy_if.hpp +++ b/include/boost/container/experimental/segmented_copy_if.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace boost { @@ -97,6 +98,36 @@ segmented_copy_if_dst_bounded return segduo(first, dst_first); } +#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION) + +template +BOOST_CONTAINER_FORCEINLINE +typename iterator_enable_if_tag + >::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::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(dst_first) + , make_wrapped_iterator(dst_last) + , pred, non_segmented_iterator_tag(), src_tag); + } +} + +#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION + template segduo segmented_copy_if_dst_bounded (SrcIter first, Sent last, SegDstIter dst_first, SegDstIter dst_last, Pred pred, diff --git a/include/boost/container/experimental/segmented_copy_n.hpp b/include/boost/container/experimental/segmented_copy_n.hpp index c7b2f39..9366ca0 100644 --- a/include/boost/container/experimental/segmented_copy_n.hpp +++ b/include/boost/container/experimental/segmented_copy_n.hpp @@ -99,6 +99,26 @@ segmented_copy_n_dst_bounded return segduo(first, dst_first); } +#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION) + +template +BOOST_CONTAINER_FORCEINLINE +typename iterator_enable_if_tag + >::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::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 segduo 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 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 } diff --git a/include/boost/container/experimental/segmented_equal.hpp b/include/boost/container/experimental/segmented_equal.hpp index f8ba540..0d6c406 100644 --- a/include/boost/container/experimental/segmented_equal.hpp +++ b/include/boost/container/experimental/segmented_equal.hpp @@ -54,6 +54,7 @@ struct equal_pred #if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) template +BOOST_CONTAINER_FORCEINLINE segduo 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 segmented_equal_iter2_bounded #endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING template +BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c >::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(first1, first2); } +#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION) + +template +BOOST_CONTAINER_FORCEINLINE +typename iterator_enable_if_tag + >::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::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 segduo segmented_equal_iter2_bounded (SrcIter first1, Sent last1, SegIter2 iter2_first, SegIter2 iter2_last, BinaryPred pred, diff --git a/include/boost/container/experimental/segmented_mismatch.hpp b/include/boost/container/experimental/segmented_mismatch.hpp index e8effa6..66eb640 100644 --- a/include/boost/container/experimental/segmented_mismatch.hpp +++ b/include/boost/container/experimental/segmented_mismatch.hpp @@ -64,6 +64,7 @@ struct mismatch_equal #if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) template +BOOST_CONTAINER_FORCEINLINE segduo 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 segmented_mismatch_iter2_bounded #endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING template +BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c >::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(first1, first2); } +#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION) + +template +BOOST_CONTAINER_FORCEINLINE +typename iterator_enable_if_tag + >::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::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 segduo segmented_mismatch_iter2_bounded (SrcIter first1, Sent last1, SegIter2 iter2_first, SegIter2 iter2_last, BinaryPred pred, diff --git a/include/boost/container/experimental/segmented_remove_copy_if.hpp b/include/boost/container/experimental/segmented_remove_copy_if.hpp index f878a3f..5dd5c7f 100644 --- a/include/boost/container/experimental/segmented_remove_copy_if.hpp +++ b/include/boost/container/experimental/segmented_remove_copy_if.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,8 @@ namespace detail_algo { #if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) template -BOOST_CONTAINER_FORCEINLINE segduo segmented_remove_copy_if_dst_bounded +BOOST_CONTAINER_FORCEINLINE +segduo 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(first, dst_first); } +#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION) + +template +BOOST_CONTAINER_FORCEINLINE +typename iterator_enable_if_tag + >::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::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)(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) + ( first, last + , make_wrapped_iterator(dst_first) + , make_wrapped_iterator(dst_last) + , pred, non_segmented_iterator_tag(), src_tag); + } +} + +#endif //BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION + template segduo segmented_remove_copy_if_dst_bounded (SrcIter first, Sent last, SegDstIter dst_first, SegDstIter dst_last, Pred pred, diff --git a/include/boost/container/experimental/segmented_reverse_copy.hpp b/include/boost/container/experimental/segmented_reverse_copy.hpp index d360e34..071389d 100644 --- a/include/boost/container/experimental/segmented_reverse_copy.hpp +++ b/include/boost/container/experimental/segmented_reverse_copy.hpp @@ -109,6 +109,26 @@ segmented_reverse_copy_dst_bounded return segduo(last, dst_first); } +#if defined(BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION) + +template +BOOST_CONTAINER_FORCEINLINE +typename iterator_enable_if_tag + >::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::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 segduo segmented_reverse_copy_dst_bounded (BidirIter first, BidirIter last, SegDstIter dst_first, SegDstIter dst_last,