From 75983a43cef9bca4cdd5490b10075de468c0ce63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 13 May 2016 00:26:54 +0200 Subject: [PATCH] Added "negate" functor and merge_bufferless_ONlogN implementation --- include/boost/move/algo/detail/merge.hpp | 153 ++++++++++++++++++++++- 1 file changed, 151 insertions(+), 2 deletions(-) diff --git a/include/boost/move/algo/detail/merge.hpp b/include/boost/move/algo/detail/merge.hpp index 59a04df..11d5740 100644 --- a/include/boost/move/algo/detail/merge.hpp +++ b/include/boost/move/algo/detail/merge.hpp @@ -257,9 +257,104 @@ void swap_merge_right op_merge_right(first1, last1, last2, buf_last, comp, swap_op()); } +template +void merge_bufferless_ONlogN_recursive + (BidirIt first, BidirIt middle, BidirIt last, Distance len1, Distance len2, Compare comp) +{ + typedef typename iterator_traits::size_type size_type; + while(1) { + //#define MERGE_BUFFERLESS_RECURSIVE_OPT + #ifndef MERGE_BUFFERLESS_RECURSIVE_OPT + if (len2 == 0) { + return; + } + + if (!len1) { + return; + } + + if ((len1 | len2) == 1) { + if (comp(*middle, *first)) + adl_move_swap(*first, *middle); + return; + } + #else + if (len2 == 0) { + return; + } + + if (!len1) { + return; + } + BidirIt middle_prev = middle; --middle_prev; + if(!comp(*middle, *middle_prev)) + return; + + while(true) { + if (comp(*middle, *first)) + break; + ++first; + if(--len1 == 1) + break; + } + + if (len1 == 1 && len2 == 1) { + //comp(*middle, *first) == true already tested in the loop + adl_move_swap(*first, *middle); + return; + } + #endif + + BidirIt first_cut = first; + BidirIt second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) { + len11 = len1 / 2; + first_cut += len11; + second_cut = lower_bound(middle, last, *first_cut, comp); + len22 = size_type(second_cut - middle); + } + else { + len22 = len2 / 2; + second_cut += len22; + first_cut = upper_bound(first, middle, *second_cut, comp); + len11 = size_type(first_cut - first); + } + BidirIt new_middle = rotate_gcd(first_cut, middle, second_cut); + + //Avoid one recursive call doing a manual tail call elimination on the biggest range + const Distance len_internal = len11+len22; + if( len_internal < (len1 + len2 - len_internal) ) { + merge_bufferless_ONlogN_recursive(first, first_cut, new_middle, len11, len22, comp); + //merge_bufferless_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp); + first = new_middle; + middle = second_cut; + len1 -= len11; + len2 -= len22; + } + else { + //merge_bufferless_recursive(first, first_cut, new_middle, len11, len22, comp); + merge_bufferless_ONlogN_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp); + middle = first_cut; + last = new_middle; + len1 = len11; + len2 = len22; + } + } +} + +//Complexity: NlogN +template +void merge_bufferless_ONlogN(BidirIt first, BidirIt middle, BidirIt last, Compare comp) +{ + merge_bufferless_ONlogN_recursive + (first, middle, last, middle - first, last - middle, comp); +} + //Complexity: min(len1,len2)^2 + max(len1,len2) template -void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp) +void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp) { if((middle - first) < (last - middle)){ while(first != middle){ @@ -290,10 +385,21 @@ void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp) } } +template +void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp) +{ + //#define BOOST_ADAPTIVE_MERGE_NLOGN_MERGE + #ifdef BOOST_ADAPTIVE_MERGE_NLOGN_MERGE + merge_bufferless_ONlogN(first, middle, last, comp); + #else + merge_bufferless_ON2(first, middle, last, comp); + #endif //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE +} + template struct antistable { - antistable(Comp &comp) + explicit antistable(Comp &comp) : m_comp(comp) {} @@ -306,6 +412,49 @@ struct antistable Comp &m_comp; }; +template +class negate +{ + public: + negate() + {} + + explicit negate(Comp comp) + : m_comp(comp) + {} + + template + bool operator()(const T1& l, const T2& r) + { + return !m_comp(l, r); + } + + private: + Comp m_comp; +}; + + +template +class inverse +{ + public: + inverse() + {} + + explicit inverse(Comp comp) + : m_comp(comp) + {} + + template + bool operator()(const T1& l, const T2& r) + { + return m_comp(r, l); + } + + private: + Comp m_comp; +}; + // [r_first, r_last) are already in the right part of the destination range. template void op_merge_with_right_placed