Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:40:51

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2015-2016.
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // See http://www.boost.org/libs/move for documentation.
0009 //
0010 //////////////////////////////////////////////////////////////////////////////
0011 #ifndef BOOST_MOVE_MERGE_HPP
0012 #define BOOST_MOVE_MERGE_HPP
0013 
0014 #include <boost/move/adl_move_swap.hpp>
0015 #include <boost/move/algo/detail/basic_op.hpp>
0016 #include <boost/move/detail/iterator_traits.hpp>
0017 #include <boost/move/detail/destruct_n.hpp>
0018 #include <boost/move/algo/predicate.hpp>
0019 #include <boost/move/algo/detail/search.hpp>
0020 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
0021 #include <cassert>
0022 #include <cstddef>
0023 
0024 #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
0025 #pragma GCC diagnostic push
0026 #pragma GCC diagnostic ignored "-Wsign-conversion"
0027 #endif
0028 
0029 namespace boost {
0030 namespace movelib {
0031 
0032 template<class T, class RandRawIt = T*, class SizeType = typename iter_size<RandRawIt>::type>
0033 class adaptive_xbuf
0034 {
0035    adaptive_xbuf(const adaptive_xbuf &);
0036    adaptive_xbuf & operator=(const adaptive_xbuf &);
0037 
0038    #if !defined(UINTPTR_MAX)
0039    typedef std::size_t uintptr_t;
0040    #endif
0041 
0042    public:
0043    typedef RandRawIt iterator;
0044    typedef SizeType  size_type;
0045 
0046    BOOST_MOVE_FORCEINLINE adaptive_xbuf()
0047       : m_ptr(), m_size(0), m_capacity(0)
0048    {}
0049 
0050    BOOST_MOVE_FORCEINLINE adaptive_xbuf(RandRawIt raw_memory, size_type cap)
0051       : m_ptr(raw_memory), m_size(0), m_capacity(cap)
0052    {}
0053 
0054    template<class RandIt>
0055    void move_assign(RandIt first, size_type n)
0056    {
0057       typedef typename iterator_traits<RandIt>::difference_type rand_diff_t;
0058       if(n <= m_size){
0059          boost::move(first, first+rand_diff_t(n), m_ptr);
0060          size_type sz = m_size;
0061          while(sz-- != n){
0062             m_ptr[sz].~T();
0063          }
0064          m_size = n;
0065       }
0066       else{
0067          RandRawIt result = boost::move(first, first+rand_diff_t(m_size), m_ptr);
0068          boost::uninitialized_move(first+rand_diff_t(m_size), first+rand_diff_t(n), result);
0069          m_size = n;
0070       }
0071    }
0072 
0073    template<class RandIt>
0074    void push_back(RandIt first, size_type n)
0075    {
0076       assert(m_capacity - m_size >= n);
0077       boost::uninitialized_move(first, first+n, m_ptr+m_size);
0078       m_size += n;
0079    }
0080 
0081    template<class RandIt>
0082    iterator add(RandIt it)
0083    {
0084       assert(m_size < m_capacity);
0085       RandRawIt p_ret = m_ptr + m_size;
0086       ::new(&*p_ret) T(::boost::move(*it));
0087       ++m_size;
0088       return p_ret;
0089    }
0090 
0091    template<class RandIt>
0092    void insert(iterator pos, RandIt it)
0093    {
0094       if(pos == (m_ptr + m_size)){
0095          this->add(it);
0096       }
0097       else{
0098          this->add(m_ptr+m_size-1);
0099          //m_size updated
0100          boost::move_backward(pos, m_ptr+m_size-2, m_ptr+m_size-1);
0101          *pos = boost::move(*it);
0102       }
0103    }
0104 
0105    BOOST_MOVE_FORCEINLINE void set_size(size_type sz)
0106    {
0107       m_size = sz;
0108    }
0109 
0110    void shrink_to_fit(size_type const sz)
0111    {
0112       if(m_size > sz){
0113          for(size_type szt_i = sz; szt_i != m_size; ++szt_i){
0114             m_ptr[szt_i].~T();
0115          }
0116          m_size = sz;
0117       }
0118    }
0119 
0120    void initialize_until(size_type const sz, T &t)
0121    {
0122       assert(m_size < m_capacity);
0123       if(m_size < sz){
0124          BOOST_MOVE_TRY
0125          {
0126             ::new((void*)&m_ptr[m_size]) T(::boost::move(t));
0127             ++m_size;
0128             for(; m_size != sz; ++m_size){
0129                ::new((void*)&m_ptr[m_size]) T(::boost::move(m_ptr[m_size-1]));
0130             }
0131             t = ::boost::move(m_ptr[m_size-1]);
0132          }
0133          BOOST_MOVE_CATCH(...)
0134          {
0135             while(m_size)
0136             {
0137                --m_size;
0138                m_ptr[m_size].~T();
0139             }
0140          }
0141          BOOST_MOVE_CATCH_END
0142       }
0143    }
0144 
0145    private:
0146    template<class RIt>
0147    BOOST_MOVE_FORCEINLINE static bool is_raw_ptr(RIt)
0148    {
0149       return false;
0150    }
0151 
0152    BOOST_MOVE_FORCEINLINE static bool is_raw_ptr(T*)
0153    {
0154       return true;
0155    }
0156 
0157    public:
0158    template<class U>
0159    bool supports_aligned_trailing(size_type sz, size_type trail_count) const
0160    {
0161       if(this->is_raw_ptr(this->data()) && m_capacity){
0162          uintptr_t u_addr_sz = uintptr_t(&*(this->data()+sz));
0163          uintptr_t u_addr_cp = uintptr_t(&*(this->data()+this->capacity()));
0164          u_addr_sz = ((u_addr_sz + sizeof(U)-1)/sizeof(U))*sizeof(U);
0165          return (u_addr_cp >= u_addr_sz) && ((u_addr_cp - u_addr_sz)/sizeof(U) >= trail_count);
0166       }
0167       return false;
0168    }
0169 
0170    template<class U>
0171    BOOST_MOVE_FORCEINLINE U *aligned_trailing() const
0172    {
0173       return this->aligned_trailing<U>(this->size());
0174    }
0175 
0176    template<class U>
0177    BOOST_MOVE_FORCEINLINE U *aligned_trailing(size_type pos) const
0178    {
0179       uintptr_t u_addr = uintptr_t(&*(this->data()+pos));
0180       u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U);
0181       return (U*)u_addr;
0182    }
0183 
0184    BOOST_MOVE_FORCEINLINE ~adaptive_xbuf()
0185    {
0186       this->clear();
0187    }
0188 
0189    BOOST_MOVE_FORCEINLINE size_type capacity() const
0190    {  return m_capacity;   }
0191 
0192    BOOST_MOVE_FORCEINLINE iterator data() const
0193    {  return m_ptr;   }
0194 
0195    BOOST_MOVE_FORCEINLINE iterator begin() const
0196    {  return m_ptr;   }
0197 
0198    BOOST_MOVE_FORCEINLINE iterator end() const
0199    {  return m_ptr+m_size;   }
0200 
0201    BOOST_MOVE_FORCEINLINE size_type size() const
0202    {  return m_size;   }
0203 
0204    BOOST_MOVE_FORCEINLINE bool empty() const
0205    {  return !m_size;   }
0206 
0207    BOOST_MOVE_FORCEINLINE void clear()
0208    {
0209       this->shrink_to_fit(0u);
0210    }
0211 
0212    private:
0213    RandRawIt m_ptr;
0214    size_type m_size;
0215    size_type m_capacity;
0216 };
0217 
0218 template<class Iterator, class SizeType, class Op>
0219 class range_xbuf
0220 {
0221    range_xbuf(const range_xbuf &);
0222    range_xbuf & operator=(const range_xbuf &);
0223 
0224    public:
0225    typedef SizeType size_type;
0226    typedef Iterator iterator;
0227 
0228    range_xbuf(Iterator first, Iterator last)
0229       : m_first(first), m_last(first), m_cap(last)
0230    {}
0231 
0232    template<class RandIt>
0233    void move_assign(RandIt first, size_type n)
0234    {
0235       assert(size_type(n) <= size_type(m_cap-m_first));
0236       typedef typename iter_difference<RandIt>::type d_type;
0237       m_last = Op()(forward_t(), first, first+d_type(n), m_first);
0238    }
0239 
0240    ~range_xbuf()
0241    {}
0242 
0243    size_type capacity() const
0244    {  return m_cap-m_first;   }
0245 
0246    Iterator data() const
0247    {  return m_first;   }
0248 
0249    Iterator end() const
0250    {  return m_last;   }
0251 
0252    size_type size() const
0253    {  return m_last-m_first;   }
0254 
0255    bool empty() const
0256    {  return m_first == m_last;   }
0257 
0258    void clear()
0259    {
0260       m_last = m_first;
0261    }
0262 
0263    template<class RandIt>
0264    iterator add(RandIt it)
0265    {
0266       Iterator pos(m_last);
0267       *pos = boost::move(*it);
0268       ++m_last;
0269       return pos;
0270    }
0271 
0272    void set_size(size_type sz)
0273    {
0274       m_last  = m_first;
0275       m_last += sz;
0276    }
0277 
0278    private:
0279    Iterator const m_first;
0280    Iterator m_last;
0281    Iterator const m_cap;
0282 };
0283 
0284 
0285 
0286 // @cond
0287 
0288 /*
0289 template<typename Unsigned>
0290 inline Unsigned gcd(Unsigned x, Unsigned y)
0291 {
0292    if(0 == ((x &(x-1)) | (y & (y-1)))){
0293       return x < y ? x : y;
0294    }
0295    else{
0296       do
0297       {
0298          Unsigned t = x % y;
0299          x = y;
0300          y = t;
0301       } while (y);
0302       return x;
0303    }
0304 }
0305 */
0306 
0307 //Modified version from "An Optimal In-Place Array Rotation Algorithm", Ching-Kuang Shene
0308 template<typename Unsigned>
0309 Unsigned gcd(Unsigned x, Unsigned y)
0310 {
0311    if(0 == ((x &(x-1)) | (y & (y-1)))){
0312       return x < y ? x : y;
0313    }
0314    else{
0315       Unsigned z = 1;
0316       while((!(x&1)) & (!(y&1))){
0317          z = Unsigned(z << 1);
0318          x = Unsigned(x >> 1);
0319          y = Unsigned(y >> 1);
0320       }
0321       while(x && y){
0322          if(!(x&1))
0323             x = Unsigned(x >> 1);
0324          else if(!(y&1))
0325             y = Unsigned (y >> 1);
0326          else if(x >=y)
0327             x = Unsigned((x-y) >> 1u);
0328          else
0329             y = Unsigned((y-x) >> 1);
0330       }
0331       return Unsigned(z*(x+y));
0332    }
0333 }
0334 
0335 template<typename RandIt>
0336 RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
0337 {
0338    typedef typename iter_size<RandIt>::type size_type;
0339    typedef typename iterator_traits<RandIt>::value_type value_type;
0340 
0341    if(first == middle)
0342       return last;
0343    if(middle == last)
0344       return first;
0345    const size_type middle_pos = size_type(middle - first);
0346    RandIt ret = last - middle_pos;
0347    if (middle == ret){
0348       boost::adl_move_swap_ranges(first, middle, middle);
0349    }
0350    else{
0351       const size_type length = size_type(last - first);
0352       for( RandIt it_i(first), it_gcd(it_i + gcd(length, middle_pos))
0353          ; it_i != it_gcd
0354          ; ++it_i){
0355          value_type temp(boost::move(*it_i));
0356          RandIt it_j = it_i;
0357          RandIt it_k = it_j+middle_pos;
0358          do{
0359             *it_j = boost::move(*it_k);
0360             it_j = it_k;
0361             size_type const left = size_type(last - it_j);
0362             it_k = left > middle_pos ? it_j + middle_pos : first + middle_pos - left;
0363          } while(it_k != it_i);
0364          *it_j = boost::move(temp);
0365       }
0366    }
0367    return ret;
0368 }
0369 
0370 template<class RandIt, class Compare, class Op>
0371 void op_merge_left( RandIt buf_first
0372                     , RandIt first1
0373                     , RandIt const last1
0374                     , RandIt const last2
0375                     , Compare comp
0376                     , Op op)
0377 {
0378    for(RandIt first2=last1; first2 != last2; ++buf_first){
0379       if(first1 == last1){
0380          op(forward_t(), first2, last2, buf_first);
0381          return;
0382       }
0383       else if(comp(*first2, *first1)){
0384          op(first2, buf_first);
0385          ++first2;
0386       }
0387       else{
0388          op(first1, buf_first);
0389          ++first1;
0390       }
0391    }
0392    if(buf_first != first1){//In case all remaining elements are in the same place
0393                            //(e.g. buffer is exactly the size of the second half
0394                            //and all elements from the second half are less)
0395       op(forward_t(), first1, last1, buf_first);
0396    }
0397 }
0398 
0399 // [buf_first, first1) -> buffer
0400 // [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
0401 // Elements from buffer are moved to [last2 - (first1-buf_first), last2)
0402 // Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
0403 template<class RandIt, class Compare>
0404 void merge_left
0405    (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
0406 {
0407    op_merge_left(buf_first, first1, last1, last2, comp, move_op());
0408 }
0409 
0410 // [buf_first, first1) -> buffer
0411 // [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
0412 // Elements from buffer are swapped to [last2 - (first1-buf_first), last2)
0413 // Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
0414 template<class RandIt, class Compare>
0415 void swap_merge_left
0416    (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
0417 {
0418    op_merge_left(buf_first, first1, last1, last2, comp, swap_op());
0419 }
0420 
0421 template<class RandIt, class Compare, class Op>
0422 void op_merge_right
0423    (RandIt const first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp, Op op)
0424 {
0425    RandIt const first2 = last1;
0426    while(first1 != last1){
0427       if(last2 == first2){
0428          op(backward_t(), first1, last1, buf_last);
0429          return;
0430       }
0431       --last2;
0432       --last1;
0433       --buf_last;
0434       if(comp(*last2, *last1)){
0435          op(last1, buf_last);
0436          ++last2;
0437       }
0438       else{
0439          op(last2, buf_last);
0440          ++last1;
0441       }
0442    }
0443    if(last2 != buf_last){  //In case all remaining elements are in the same place
0444                            //(e.g. buffer is exactly the size of the first half
0445                            //and all elements from the second half are less)
0446       op(backward_t(), first2, last2, buf_last);
0447    }
0448 }
0449 
0450 // [last2, buf_last) - buffer
0451 // [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
0452 // Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
0453 template<class RandIt, class Compare>
0454 void merge_right
0455    (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
0456 {
0457    op_merge_right(first1, last1, last2, buf_last, comp, move_op());
0458 }
0459 
0460 // [last2, buf_last) - buffer
0461 // [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
0462 // Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
0463 template<class RandIt, class Compare>
0464 void swap_merge_right
0465    (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
0466 {
0467    op_merge_right(first1, last1, last2, buf_last, comp, swap_op());
0468 }
0469 
0470 ///////////////////////////////////////////////////////////////////////////////
0471 //
0472 //                            BUFFERED MERGE
0473 //
0474 ///////////////////////////////////////////////////////////////////////////////
0475 template<class RandIt, class Compare, class Op, class Buf>
0476 void op_buffered_merge
0477       ( RandIt first, RandIt const middle, RandIt last
0478       , Compare comp, Op op
0479       , Buf &xbuf)
0480 {
0481    if(first != middle && middle != last && comp(*middle, middle[-1])){
0482       typedef typename iter_size<RandIt>::type   size_type;
0483       size_type const len1 = size_type(middle-first);
0484       size_type const len2 = size_type(last-middle);
0485       if(len1 <= len2){
0486          first = boost::movelib::upper_bound(first, middle, *middle, comp);
0487          xbuf.move_assign(first, size_type(middle-first));
0488          op_merge_with_right_placed
0489             (xbuf.data(), xbuf.end(), first, middle, last, comp, op);
0490       }
0491       else{
0492          last = boost::movelib::lower_bound(middle, last, middle[-1], comp);
0493          xbuf.move_assign(middle, size_type(last-middle));
0494          op_merge_with_left_placed
0495             (first, middle, last, xbuf.data(), xbuf.end(), comp, op);
0496       }
0497    }
0498 }
0499 
0500 template<class RandIt, class Compare, class XBuf>
0501 void buffered_merge
0502       ( RandIt first, RandIt const middle, RandIt last
0503       , Compare comp
0504       , XBuf &xbuf)
0505 {
0506    op_buffered_merge(first, middle, last, comp, move_op(), xbuf);
0507 }
0508 
0509 //Complexity: min(len1,len2)^2 + max(len1,len2)
0510 template<class RandIt, class Compare>
0511 void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp)
0512 {
0513    if((middle - first) < (last - middle)){
0514       while(first != middle){
0515          RandIt const old_last1 = middle;
0516          middle = boost::movelib::lower_bound(middle, last, *first, comp);
0517          first = rotate_gcd(first, old_last1, middle);
0518          if(middle == last){
0519             break;
0520          }
0521          do{
0522             ++first;
0523          } while(first != middle && !comp(*middle, *first));
0524       }
0525    }
0526    else{
0527       while(middle != last){
0528          RandIt p = boost::movelib::upper_bound(first, middle, last[-1], comp);
0529          last = rotate_gcd(p, middle, last);
0530          middle = p;
0531          if(middle == first){
0532             break;
0533          }
0534          --p;
0535          do{
0536             --last;
0537          } while(middle != last && !comp(last[-1], *p));
0538       }
0539    }
0540 }
0541 
0542 static const std::size_t MergeBufferlessONLogNRotationThreshold = 16u;
0543 
0544 template <class RandIt, class Compare>
0545 void merge_bufferless_ONlogN_recursive
0546    ( RandIt first, RandIt middle, RandIt last
0547    , typename iter_size<RandIt>::type len1
0548    , typename iter_size<RandIt>::type len2
0549    , Compare comp)
0550 {
0551    typedef typename iter_size<RandIt>::type size_type;
0552 
0553    while(1) {
0554       //trivial cases
0555       if (!len2) {
0556          return;
0557       }
0558       else if (!len1) {
0559          return;
0560       }
0561       else if (size_type(len1 | len2) == 1u) {
0562          if (comp(*middle, *first))
0563             adl_move_swap(*first, *middle);  
0564          return;
0565       }
0566       else if(size_type(len1+len2) < MergeBufferlessONLogNRotationThreshold){
0567          merge_bufferless_ON2(first, middle, last, comp);
0568          return;
0569       }
0570 
0571       RandIt first_cut = first;
0572       RandIt second_cut = middle;
0573       size_type len11 = 0;
0574       size_type len22 = 0;
0575       if (len1 > len2) {
0576          len11 = len1 / 2;
0577          first_cut +=  len11;
0578          second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp);
0579          len22 = size_type(second_cut - middle);
0580       }
0581       else {
0582          len22 = len2 / 2;
0583          second_cut += len22;
0584          first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
0585          len11 = size_type(first_cut - first);
0586       }
0587       RandIt new_middle = rotate_gcd(first_cut, middle, second_cut);
0588 
0589       //Avoid one recursive call doing a manual tail call elimination on the biggest range
0590       const size_type len_internal = size_type(len11+len22);
0591       if( len_internal < (len1 + len2 - len_internal) ) {
0592          merge_bufferless_ONlogN_recursive(first, first_cut,  new_middle, len11, len22, comp);
0593          first = new_middle;
0594          middle = second_cut;
0595          len1 = size_type(len1-len11);
0596          len2 = size_type(len2-len22);
0597       }
0598       else {
0599          merge_bufferless_ONlogN_recursive
0600             (new_middle, second_cut, last, size_type(len1 - len11), size_type(len2 - len22), comp);
0601          middle = first_cut;
0602          last = new_middle;
0603          len1 = len11;
0604          len2 = len22;
0605       }
0606    }
0607 }
0608 
0609 
0610 //Complexity: NlogN
0611 template<class RandIt, class Compare>
0612 void merge_bufferless_ONlogN(RandIt first, RandIt middle, RandIt last, Compare comp)
0613 {
0614    typedef typename iter_size<RandIt>::type size_type;
0615    merge_bufferless_ONlogN_recursive
0616       (first, middle, last, size_type(middle - first), size_type(last - middle), comp);
0617 }
0618 
0619 template<class RandIt, class Compare>
0620 void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
0621 {
0622    #define BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
0623    #ifdef BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
0624    merge_bufferless_ONlogN(first, middle, last, comp);
0625    #else
0626    merge_bufferless_ON2(first, middle, last, comp);
0627    #endif   //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
0628 }
0629 
0630 // [r_first, r_last) are already in the right part of the destination range.
0631 template <class Compare, class InputIterator, class InputOutIterator, class Op>
0632 void op_merge_with_right_placed
0633    ( InputIterator first, InputIterator last
0634    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
0635    , Compare comp, Op op)
0636 {
0637    assert((last - first) == (r_first - dest_first));
0638    while ( first != last ) {
0639       if (r_first == r_last) {
0640          InputOutIterator end = op(forward_t(), first, last, dest_first);
0641          assert(end == r_last);
0642          boost::movelib::ignore(end);
0643          return;
0644       }
0645       else if (comp(*r_first, *first)) {
0646          op(r_first, dest_first);
0647          ++r_first;
0648       }
0649       else {
0650          op(first, dest_first);
0651          ++first;
0652       }
0653       ++dest_first;
0654    }
0655    // Remaining [r_first, r_last) already in the correct place
0656 }
0657 
0658 template <class Compare, class InputIterator, class InputOutIterator>
0659 void swap_merge_with_right_placed
0660    ( InputIterator first, InputIterator last
0661    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
0662    , Compare comp)
0663 {
0664    op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, swap_op());
0665 }
0666 
0667 // [first, last) are already in the right part of the destination range.
0668 template <class Compare, class Op, class BidirIterator, class BidirOutIterator>
0669 void op_merge_with_left_placed
0670    ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
0671    , BidirIterator const r_first, BidirIterator r_last
0672    , Compare comp, Op op)
0673 {
0674    assert((dest_last - last) == (r_last - r_first));
0675    while( r_first != r_last ) {
0676       if(first == last) {
0677          BidirOutIterator res = op(backward_t(), r_first, r_last, dest_last);
0678          assert(last == res);
0679          boost::movelib::ignore(res);
0680          return;
0681       }
0682       --r_last;
0683       --last;
0684       if(comp(*r_last, *last)){
0685          ++r_last;
0686          --dest_last;
0687          op(last, dest_last);
0688       }
0689       else{
0690          ++last;
0691          --dest_last;
0692          op(r_last, dest_last);
0693       }
0694    }
0695    // Remaining [first, last) already in the correct place
0696 }
0697 
0698 // @endcond
0699 
0700 // [first, last) are already in the right part of the destination range.
0701 template <class Compare, class BidirIterator, class BidirOutIterator>
0702 void merge_with_left_placed
0703    ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
0704    , BidirIterator const r_first, BidirIterator r_last
0705    , Compare comp)
0706 {
0707    op_merge_with_left_placed(first, last, dest_last, r_first, r_last, comp, move_op());
0708 }
0709 
0710 // [r_first, r_last) are already in the right part of the destination range.
0711 template <class Compare, class InputIterator, class InputOutIterator>
0712 void merge_with_right_placed
0713    ( InputIterator first, InputIterator last
0714    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
0715    , Compare comp)
0716 {
0717    op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, move_op());
0718 }
0719 
0720 // [r_first, r_last) are already in the right part of the destination range.
0721 // [dest_first, r_first) is uninitialized memory
0722 template <class Compare, class InputIterator, class InputOutIterator>
0723 void uninitialized_merge_with_right_placed
0724    ( InputIterator first, InputIterator last
0725    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
0726    , Compare comp)
0727 {
0728    assert((last - first) == (r_first - dest_first));
0729    typedef typename iterator_traits<InputOutIterator>::value_type value_type;
0730    InputOutIterator const original_r_first = r_first;
0731 
0732    destruct_n<value_type, InputOutIterator> d(dest_first);
0733 
0734    while ( first != last && dest_first != original_r_first ) {
0735       if (r_first == r_last) {
0736          for(; dest_first != original_r_first; ++dest_first, ++first){
0737             ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
0738             d.incr();
0739          }
0740          d.release();
0741          InputOutIterator end = ::boost::move(first, last, original_r_first);
0742          assert(end == r_last);
0743          boost::movelib::ignore(end);
0744          return;
0745       }
0746       else if (comp(*r_first, *first)) {
0747          ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*r_first));
0748          d.incr();
0749          ++r_first;
0750       }
0751       else {
0752          ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
0753          d.incr();
0754          ++first;
0755       }
0756       ++dest_first;
0757    }
0758    d.release();
0759    merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
0760 }
0761 
0762 /// This is a helper function for the merge routines.
0763 template<typename BidirectionalIterator1, typename BidirectionalIterator2>
0764    BidirectionalIterator1
0765    rotate_adaptive(BidirectionalIterator1 first,
0766       BidirectionalIterator1 middle,
0767       BidirectionalIterator1 last,
0768       typename iter_size<BidirectionalIterator1>::type len1,
0769       typename iter_size<BidirectionalIterator1>::type len2,
0770       BidirectionalIterator2 buffer,
0771       typename iter_size<BidirectionalIterator1>::type buffer_size)
0772 {
0773    if (len1 > len2 && len2 <= buffer_size)
0774    {
0775       if(len2) //Protect against self-move ranges
0776       {
0777          BidirectionalIterator2 buffer_end = boost::move(middle, last, buffer);
0778          boost::move_backward(first, middle, last);
0779          return boost::move(buffer, buffer_end, first);
0780       }
0781       else
0782          return first;
0783    }
0784    else if (len1 <= buffer_size)
0785    {
0786       if(len1) //Protect against self-move ranges
0787       {
0788          BidirectionalIterator2 buffer_end = boost::move(first, middle, buffer);
0789          BidirectionalIterator1 ret = boost::move(middle, last, first);
0790          boost::move(buffer, buffer_end, ret);
0791          return ret;
0792       }
0793       else
0794          return last;
0795    }
0796    else
0797       return rotate_gcd(first, middle, last);
0798 }
0799 
0800 template<typename BidirectionalIterator,
0801    typename Pointer, typename Compare>
0802    void merge_adaptive_ONlogN_recursive
0803    (BidirectionalIterator first,
0804       BidirectionalIterator middle,
0805       BidirectionalIterator last,
0806       typename  iter_size<BidirectionalIterator>::type len1,
0807       typename  iter_size<BidirectionalIterator>::type len2,
0808       Pointer buffer,
0809       typename  iter_size<BidirectionalIterator>::type buffer_size,
0810       Compare comp)
0811 {
0812    typedef typename  iter_size<BidirectionalIterator>::type size_type;
0813    //trivial cases
0814    if (!len2 || !len1) {
0815       // no-op
0816    }
0817    else if (len1 <= buffer_size || len2 <= buffer_size) {
0818       range_xbuf<Pointer, size_type, move_op> rxbuf(buffer, buffer + buffer_size);
0819       buffered_merge(first, middle, last, comp, rxbuf);
0820    }
0821    else if (size_type(len1 + len2) == 2u) {
0822       if (comp(*middle, *first))
0823          adl_move_swap(*first, *middle);
0824    }
0825    else if (size_type(len1 + len2) < MergeBufferlessONLogNRotationThreshold) {
0826       merge_bufferless_ON2(first, middle, last, comp);
0827    }
0828    else {
0829       BidirectionalIterator first_cut = first;
0830       BidirectionalIterator second_cut = middle;
0831       size_type len11 = 0;
0832       size_type len22 = 0;
0833       if (len1 > len2)  //(len1 < len2)
0834       {
0835          len11 = len1 / 2;
0836          first_cut += len11;
0837          second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp);
0838          len22 = size_type(second_cut - middle);
0839       }
0840       else
0841       {
0842          len22 = len2 / 2;
0843          second_cut += len22;
0844          first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
0845          len11 = size_type(first_cut - first);
0846       }
0847 
0848       BidirectionalIterator new_middle
0849          = rotate_adaptive(first_cut, middle, second_cut,
0850             size_type(len1 - len11), len22, buffer,
0851             buffer_size);
0852       merge_adaptive_ONlogN_recursive(first, first_cut, new_middle, len11,
0853          len22, buffer, buffer_size, comp);
0854       merge_adaptive_ONlogN_recursive(new_middle, second_cut, last,
0855          size_type(len1 - len11), size_type(len2 - len22), buffer, buffer_size, comp);
0856    }
0857 }
0858 
0859 
0860 template<typename BidirectionalIterator, typename Compare, typename RandRawIt>
0861 void merge_adaptive_ONlogN(BidirectionalIterator first,
0862                              BidirectionalIterator middle,
0863                              BidirectionalIterator last,
0864                              Compare comp,
0865                            RandRawIt uninitialized,
0866                            typename  iter_size<BidirectionalIterator>::type uninitialized_len)
0867 {
0868    typedef typename iterator_traits<BidirectionalIterator>::value_type  value_type;
0869    typedef typename  iter_size<BidirectionalIterator>::type   size_type;
0870 
0871    if (first == middle || middle == last)
0872       return;
0873 
0874    if(uninitialized_len)
0875    {
0876       const size_type len1 = size_type(middle - first);
0877       const size_type len2 = size_type(last - middle);
0878 
0879       ::boost::movelib::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
0880       xbuf.initialize_until(uninitialized_len, *first);
0881        merge_adaptive_ONlogN_recursive(first, middle, last, len1, len2, xbuf.begin(), uninitialized_len, comp);
0882    }
0883    else
0884    {
0885       merge_bufferless(first, middle, last, comp);
0886    }
0887 }
0888 
0889 }  //namespace movelib {
0890 }  //namespace boost {
0891 
0892 #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
0893 #pragma GCC diagnostic pop
0894 #endif
0895 
0896 #endif   //#define BOOST_MOVE_MERGE_HPP