diff --git a/include/boost/container/experimental/segmented_mismatch.hpp b/include/boost/container/experimental/segmented_mismatch.hpp index 65ff719..d49e746 100644 --- a/include/boost/container/experimental/segmented_mismatch.hpp +++ b/include/boost/container/experimental/segmented_mismatch.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace boost { @@ -40,12 +41,62 @@ struct mismatch_equal BOOST_CONTAINER_FORCEINLINE bool operator()(const T& a, const U& b) const { return a == b; } }; -template +#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) + +template +std::pair segmented_mismatch_dispatch + (RAIter1 first1, RAIter1 last1, RAIter2 first2, BinaryPred pred, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &) +{ + typedef typename iterator_traits::difference_type difference_type; + + difference_type n = last1 - first1; + while(n >= difference_type(4)) { + if(!pred(*first1, *first2)) + goto final_result; + ++first1; ++first2; + if(!pred(*first1, *first2)) + goto final_result; + ++first1; ++first2; + if(!pred(*first1, *first2)) + goto final_result; + ++first1; ++first2; + if(!pred(*first1, *first2)) + goto final_result; + ++first1; ++first2; + n -= 4; + } + + switch (n % 4) { + case 3: + if(!pred(*first1, *first2)) + break; + ++first1; ++first2; + BOOST_FALLTHROUGH; + case 2: + if(!pred(*first1, *first2)) + break; + ++first1; ++first2; + BOOST_FALLTHROUGH; + case 1: + if(!pred(*first1, *first2)) + break; + ++first1; ++first2; + BOOST_FALLTHROUGH; + default: + break; + } + final_result: + return std::pair(first1, first2); +} + +#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING + +template typename algo_enable_if_c < !Tag::value || is_sentinel::value , std::pair >::type -segmented_mismatch_dispatch(InpIter1 first1, Sent last1, InpIter2 first2, BinaryPred pred, Tag) +segmented_mismatch_dispatch(InpIter1 first1, Sent last1, InpIter2 first2, BinaryPred pred, Tag, Cat) { while (first1 != last1 && pred(*first1, *first2)) { ++first1, ++first2; @@ -54,9 +105,9 @@ segmented_mismatch_dispatch(InpIter1 first1, Sent last1, InpIter2 first2, Binary return std::pair(first1, first2); } -template +template std::pair segmented_mismatch_dispatch - (SegIter first1, SegIter last1, InpIter2 first2, BinaryPred pred, segmented_iterator_tag) + (SegIter first1, SegIter last1, InpIter2 first2, BinaryPred pred, segmented_iterator_tag, Cat) { typedef segmented_iterator_traits traits; typedef typename traits::local_iterator local_iterator; @@ -70,26 +121,26 @@ std::pair segmented_mismatch_dispatch segment_iterator const slast = traits::segment(last1); if(sfirst == slast) { - const local_return_t r = (segmented_mismatch_dispatch)(traits::local(first1), traits::local(last1), first2, pred, is_local_seg_t()); + const local_return_t r = (segmented_mismatch_dispatch)(traits::local(first1), traits::local(last1), first2, pred, is_local_seg_t(), Cat()); return return_t(traits::compose(sfirst, r.first), r.second); } else { // First segment local_iterator le = traits::end(sfirst); - local_return_t r = (segmented_mismatch_dispatch)(traits::local(first1), le, first2, pred, is_local_seg_t()); + local_return_t r = (segmented_mismatch_dispatch)(traits::local(first1), le, first2, pred, is_local_seg_t(), Cat()); if (r.first != le) return return_t(traits::compose(sfirst, r.first), r.second); // Middle segments for (++sfirst; sfirst != slast; ++sfirst) { le = traits::end(sfirst); - r = (segmented_mismatch_dispatch)(traits::begin(sfirst), le, r.second, pred, is_local_seg_t()); + r = (segmented_mismatch_dispatch)(traits::begin(sfirst), le, r.second, pred, is_local_seg_t(), Cat()); if (r.first != le) return return_t(traits::compose(sfirst, r.first), r.second); } // Last segment - r = (segmented_mismatch_dispatch)(traits::begin(slast), traits::local(last1), r.second, pred, is_local_seg_t()); + r = (segmented_mismatch_dispatch)(traits::begin(slast), traits::local(last1), r.second, pred, is_local_seg_t(), Cat()); return return_t(traits::compose(sfirst, r.first), r.second); } } @@ -105,7 +156,7 @@ segmented_mismatch(InpIter1 first1, Sent last1, InpIter2 first2, BinaryPred pred { typedef segmented_iterator_traits traits; return detail_algo::segmented_mismatch_dispatch - (first1, last1, first2, pred, typename traits::is_segmented_iterator()); + (first1, last1, first2, pred, typename traits::is_segmented_iterator(), typename iterator_traits::iterator_category()); } //! Returns a pair of iterators to the first mismatching elements