diff --git a/include/boost/container/experimental/segmented_copy_if.hpp b/include/boost/container/experimental/segmented_copy_if.hpp index 4c39337..12554a0 100644 --- a/include/boost/container/experimental/segmented_copy_if.hpp +++ b/include/boost/container/experimental/segmented_copy_if.hpp @@ -54,22 +54,43 @@ BOOST_CONTAINER_FORCEINLINE segduo segmented_copy_if_dst_bou difference_type n = last - first; while(n >= difference_type(4)) { - if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first; - if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first; - if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first; - if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first; + if(pred(*first)) { + if(dst_first == dst_last) goto out_path; + *dst_first = *first; ++dst_first; + } ++first; + if(pred(*first)) { + if(dst_first == dst_last) goto out_path; + *dst_first = *first; ++dst_first; + } ++first; + if(pred(*first)) { + if(dst_first == dst_last) goto out_path; + *dst_first = *first; ++dst_first; + } ++first; + if(pred(*first)) { + if(dst_first == dst_last) goto out_path; + *dst_first = *first; ++dst_first; + } ++first; n -= 4; } switch(n) { case 3: - if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first; + if(pred(*first)) { + if(dst_first == dst_last) goto out_path; + *dst_first = *first; ++dst_first; + } ++first; BOOST_FALLTHROUGH; case 2: - if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first; + if(pred(*first)) { + if(dst_first == dst_last) goto out_path; + *dst_first = *first; ++dst_first; + } ++first; BOOST_FALLTHROUGH; case 1: - if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first; + if(pred(*first)) { + if(dst_first == dst_last) goto out_path; + *dst_first = *first; ++dst_first; + } ++first; BOOST_FALLTHROUGH; default: break; diff --git a/include/boost/container/experimental/segmented_count.hpp b/include/boost/container/experimental/segmented_count.hpp index db5f367..2316a98 100644 --- a/include/boost/container/experimental/segmented_count.hpp +++ b/include/boost/container/experimental/segmented_count.hpp @@ -20,20 +20,115 @@ #include #include -#include +#include #include -#include namespace boost { namespace container { +template +typename boost::container::iterator_traits::difference_type +segmented_count(InpIter first, Sent last, const T& value); + +namespace detail_algo { + +#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) + +template +typename iterator_traits::difference_type +segmented_count_dispatch + (RAIter first, RAIter last, const T& value, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &) +{ + typedef typename iterator_traits::difference_type difference_type; + + difference_type n = last - first; + difference_type count = 0; + while(n >= difference_type(4)) { + if(*first == value) ++count; + ++first; + if(*first == value) ++count; + ++first; + if(*first == value) ++count; + ++first; + if(*first == value) ++count; + ++first; + n -= 4; + } + + switch(n) { + case 3: + if(*first == value) ++count; + ++first; + BOOST_FALLTHROUGH; + case 2: + if(*first == value) ++count; + ++first; + BOOST_FALLTHROUGH; + case 1: + if(*first == value) ++count; + ++first; + BOOST_FALLTHROUGH; + default: + break; + } + return count; +} + +#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING + +template +typename algo_enable_if_c< + !Tag::value || is_sentinel::value, + typename boost::container::iterator_traits::difference_type>::type +segmented_count_dispatch + (InpIter first, Sent last, const T& value, Tag, Cat) +{ + typedef typename boost::container::iterator_traits::difference_type diff_t; + diff_t n = 0; + + for (; first != last; ++first) + if (*first == value) ++n; + return n; +} + +template +typename boost::container::iterator_traits::difference_type + segmented_count_dispatch(SegIter first, SegIter last, const T& value, segmented_iterator_tag, Cat) +{ + typedef segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator; + typedef typename segmented_iterator_traits::is_segmented_iterator is_local_seg_t; + typedef typename iterator_traits::iterator_category local_cat_t; + + segment_iterator sfirst = traits::segment(first); + segment_iterator slast = traits::segment(last); + + if(sfirst == slast) { + return (segmented_count_dispatch)(traits::local(first), traits::local(last), value, is_local_seg_t(), local_cat_t()); + } + else { + typename boost::container::iterator_traits::difference_type result = 0; + result += (segmented_count_dispatch)(traits::local(first), traits::end(sfirst), value, is_local_seg_t(), local_cat_t()); + + for(++sfirst; sfirst != slast; ++sfirst) + result += (segmented_count_dispatch)(traits::begin(sfirst), traits::end(sfirst), value, is_local_seg_t(), local_cat_t()); + + return result += (segmented_count_dispatch)(traits::begin(sfirst), traits::local(last), value, is_local_seg_t(), local_cat_t()); + } +} + +} // namespace detail_algo + //! Returns the number of elements equal to \c value in [first, last). template BOOST_CONTAINER_FORCEINLINE typename boost::container::iterator_traits::difference_type segmented_count(InpIter first, Sent last, const T& value) { - return boost::container::segmented_count_if(first, last, equal_to_value(value)); + typedef segmented_iterator_traits traits; + return detail_algo::segmented_count_dispatch(first, last, value, + typename traits::is_segmented_iterator(), typename iterator_traits::iterator_category()); } } // namespace container diff --git a/include/boost/container/experimental/segmented_count_if.hpp b/include/boost/container/experimental/segmented_count_if.hpp index fb5c939..e4c6891 100644 --- a/include/boost/container/experimental/segmented_count_if.hpp +++ b/include/boost/container/experimental/segmented_count_if.hpp @@ -44,22 +44,29 @@ segmented_count_if_dispatch difference_type n = last - first; difference_type count = 0; while(n >= difference_type(4)) { - count += static_cast(pred(*first)); ++first; - count += static_cast(pred(*first)); ++first; - count += static_cast(pred(*first)); ++first; - count += static_cast(pred(*first)); ++first; + if(pred(*first)) ++count; + ++first; + if(pred(*first)) ++count; + ++first; + if(pred(*first)) ++count; + ++first; + if(pred(*first)) ++count; + ++first; n -= 4; } switch(n) { case 3: - count += static_cast(pred(*first)); ++first; + if(pred(*first)) ++count; + ++first; BOOST_FALLTHROUGH; case 2: - count += static_cast(pred(*first)); ++first; + if(pred(*first)) ++count; + ++first; BOOST_FALLTHROUGH; case 1: - count += static_cast(pred(*first)); ++first; + if(pred(*first)) ++count; + ++first; BOOST_FALLTHROUGH; default: break; @@ -80,7 +87,7 @@ segmented_count_if_dispatch diff_t n = 0; for (; first != last; ++first) - n += static_cast(pred(*first)); + if (pred(*first)) ++n; return n; } diff --git a/include/boost/container/experimental/segmented_partition.hpp b/include/boost/container/experimental/segmented_partition.hpp index cfc8d41..697d1be 100644 --- a/include/boost/container/experimental/segmented_partition.hpp +++ b/include/boost/container/experimental/segmented_partition.hpp @@ -39,6 +39,7 @@ namespace detail_algo { ////////////////////////////////////////////// template +BOOST_CONTAINER_FORCEINLINE OutIter partition_scan(FwdIt first, Sent last, OutIter result, Pred pred, non_segmented_iterator_tag, const std::forward_iterator_tag &) { for(; first != last; ++first) { @@ -55,6 +56,7 @@ OutIter partition_scan(FwdIt first, Sent last, OutIter result, Pred pred, non_se ////////////////////////////////////////////// template +BOOST_CONTAINER_FORCEINLINE BidirIt partition_scan(BidirIt first, BidirIt last, Pred pred, non_segmented_iterator_tag, const Cat&) { while(true) { @@ -77,6 +79,7 @@ BidirIt partition_scan(BidirIt first, BidirIt last, Pred pred, non_segmented_ite #if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) template +BOOST_CONTAINER_FORCEINLINE RAIter partition_scan(RAIter first, RAIter last, Pred pred, non_segmented_iterator_tag, const std::random_access_iterator_tag&) { typedef typename iterator_traits::difference_type difference_type; @@ -265,7 +268,6 @@ SegIt partition_scan(SegIt first, SegIt last, Pred pred, segmented_iterator_tag, ////////////////////////////////////////////// template -BOOST_CONTAINER_FORCEINLINE FwdIt segmented_partition_dispatch(FwdIt first, Sent last, Pred pred, Tag tag, const std::forward_iterator_tag &cat) { first = (segmented_find_if_not)(first, last, pred); diff --git a/include/boost/container/experimental/segmented_remove_copy.hpp b/include/boost/container/experimental/segmented_remove_copy.hpp index 19a4aa8..a60e818 100644 --- a/include/boost/container/experimental/segmented_remove_copy.hpp +++ b/include/boost/container/experimental/segmented_remove_copy.hpp @@ -45,22 +45,43 @@ segduo segmented_remove_copy_dst_bounded difference_type n = last - first; while(n >= difference_type(4)) { - if(!(*first == value)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; - if(!(*first == value)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; - if(!(*first == value)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; - if(!(*first == value)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!(*first == value)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; + if(!(*first == value)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; + if(!(*first == value)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; + if(!(*first == value)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; n -= 4; } switch(n) { case 3: - if(!(*first == value)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!(*first == value)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; BOOST_FALLTHROUGH; case 2: - if(!(*first == value)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!(*first == value)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; BOOST_FALLTHROUGH; case 1: - if(!(*first == value)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!(*first == value)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; BOOST_FALLTHROUGH; default: break; diff --git a/include/boost/container/experimental/segmented_remove_copy_if.hpp b/include/boost/container/experimental/segmented_remove_copy_if.hpp index b63dcb3..3b179ad 100644 --- a/include/boost/container/experimental/segmented_remove_copy_if.hpp +++ b/include/boost/container/experimental/segmented_remove_copy_if.hpp @@ -58,22 +58,43 @@ segduo segmented_remove_copy_if_dst_bounded difference_type n = last - first; while(n >= difference_type(4)) { - if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; - if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; - if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; - if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!pred(*first)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; + if(!pred(*first)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; + if(!pred(*first)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; + if(!pred(*first)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; n -= 4; } switch(n) { case 3: - if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!pred(*first)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; BOOST_FALLTHROUGH; case 2: - if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!pred(*first)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; BOOST_FALLTHROUGH; case 1: - if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op::apply(*dst_first, *first); ++dst_first; } ++first; + if(!pred(*first)) { + if(dst_first == dst_last) goto out_path; + transfer_op::apply(*dst_first, *first); ++dst_first; + } ++first; BOOST_FALLTHROUGH; default: break;