1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2015-2016.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/move for documentation.
9 //
10 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_MOVE_MERGE_HPP
12 #define BOOST_MOVE_MERGE_HPP
13 
14 #include <boost/core/ignore_unused.hpp>
15 #include <boost/move/algo/move.hpp>
16 #include <boost/move/adl_move_swap.hpp>
17 #include <boost/move/algo/detail/basic_op.hpp>
18 #include <boost/move/detail/iterator_traits.hpp>
19 #include <boost/move/detail/destruct_n.hpp>
20 #include <boost/move/algo/predicate.hpp>
21 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
22 #include <boost/assert.hpp>
23 #include <cstddef>
24 
25 namespace boost {
26 namespace movelib {
27 
28 template<class T, class RandRawIt = T*, class SizeType = typename iterator_traits<RandRawIt>::size_type>
29 class adaptive_xbuf
30 {
31    adaptive_xbuf(const adaptive_xbuf &);
32    adaptive_xbuf & operator=(const adaptive_xbuf &);
33 
34    #if !defined(UINTPTR_MAX)
35    typedef std::size_t uintptr_t;
36    #endif
37 
38    public:
39    typedef RandRawIt iterator;
40    typedef SizeType  size_type;
41 
adaptive_xbuf()42    adaptive_xbuf()
43       : m_ptr(), m_size(0), m_capacity(0)
44    {}
45 
adaptive_xbuf(RandRawIt raw_memory,size_type capacity)46    adaptive_xbuf(RandRawIt raw_memory, size_type capacity)
47       : m_ptr(raw_memory), m_size(0), m_capacity(capacity)
48    {}
49 
50    template<class RandIt>
move_assign(RandIt first,size_type n)51    void move_assign(RandIt first, size_type n)
52    {
53       if(n <= m_size){
54          boost::move(first, first+n, m_ptr);
55          size_type size = m_size;
56          while(size-- != n){
57             m_ptr[size].~T();
58          }
59          m_size = n;
60       }
61       else{
62          RandRawIt result = boost::move(first, first+m_size, m_ptr);
63          boost::uninitialized_move(first+m_size, first+n, result);
64          m_size = n;
65       }
66    }
67 
68    template<class RandIt>
push_back(RandIt first,size_type n)69    void push_back(RandIt first, size_type n)
70    {
71       BOOST_ASSERT(m_capacity - m_size >= n);
72       boost::uninitialized_move(first, first+n, m_ptr+m_size);
73       m_size += n;
74    }
75 
76    template<class RandIt>
add(RandIt it)77    iterator add(RandIt it)
78    {
79       BOOST_ASSERT(m_size < m_capacity);
80       RandRawIt p_ret = m_ptr + m_size;
81       ::new(&*p_ret) T(::boost::move(*it));
82       ++m_size;
83       return p_ret;
84    }
85 
86    template<class RandIt>
insert(iterator pos,RandIt it)87    void insert(iterator pos, RandIt it)
88    {
89       if(pos == (m_ptr + m_size)){
90          this->add(it);
91       }
92       else{
93          this->add(m_ptr+m_size-1);
94          //m_size updated
95          boost::move_backward(pos, m_ptr+m_size-2, m_ptr+m_size-1);
96          *pos = boost::move(*it);
97       }
98    }
99 
set_size(size_type size)100    void set_size(size_type size)
101    {
102       m_size = size;
103    }
104 
shrink_to_fit(size_type const size)105    void shrink_to_fit(size_type const size)
106    {
107       if(m_size > size){
108          for(size_type szt_i = size; szt_i != m_size; ++szt_i){
109             m_ptr[szt_i].~T();
110          }
111          m_size = size;
112       }
113    }
114 
initialize_until(size_type const size,T & t)115    void initialize_until(size_type const size, T &t)
116    {
117       BOOST_ASSERT(m_size < m_capacity);
118       if(m_size < size){
119          BOOST_TRY
120          {
121             ::new((void*)&m_ptr[m_size]) T(::boost::move(t));
122             ++m_size;
123             for(; m_size != size; ++m_size){
124                ::new((void*)&m_ptr[m_size]) T(::boost::move(m_ptr[m_size-1]));
125             }
126             t = ::boost::move(m_ptr[m_size-1]);
127          }
128          BOOST_CATCH(...)
129          {
130             while(m_size)
131             {
132                --m_size;
133                m_ptr[m_size].~T();
134             }
135          }
136          BOOST_CATCH_END
137       }
138    }
139 
140    private:
141    template<class RIt>
is_raw_ptr(RIt)142    static bool is_raw_ptr(RIt)
143    {
144       return false;
145    }
146 
is_raw_ptr(T *)147    static bool is_raw_ptr(T*)
148    {
149       return true;
150    }
151 
152    public:
153    template<class U>
supports_aligned_trailing(size_type size,size_type trail_count) const154    bool supports_aligned_trailing(size_type size, size_type trail_count) const
155    {
156       if(this->is_raw_ptr(this->data()) && m_capacity){
157          uintptr_t u_addr_sz = uintptr_t(&*(this->data()+size));
158          uintptr_t u_addr_cp = uintptr_t(&*(this->data()+this->capacity()));
159          u_addr_sz = ((u_addr_sz + sizeof(U)-1)/sizeof(U))*sizeof(U);
160          return (u_addr_cp >= u_addr_sz) && ((u_addr_cp - u_addr_sz)/sizeof(U) >= trail_count);
161       }
162       return false;
163    }
164 
165    template<class U>
aligned_trailing() const166    U *aligned_trailing() const
167    {
168       return this->aligned_trailing<U>(this->size());
169    }
170 
171    template<class U>
aligned_trailing(size_type pos) const172    U *aligned_trailing(size_type pos) const
173    {
174       uintptr_t u_addr = uintptr_t(&*(this->data()+pos));
175       u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U);
176       return (U*)u_addr;
177    }
178 
~adaptive_xbuf()179    ~adaptive_xbuf()
180    {
181       this->clear();
182    }
183 
capacity() const184    size_type capacity() const
185    {  return m_capacity;   }
186 
data() const187    iterator data() const
188    {  return m_ptr;   }
189 
begin() const190    iterator begin() const
191    {  return m_ptr;   }
192 
end() const193    iterator end() const
194    {  return m_ptr+m_size;   }
195 
size() const196    size_type size() const
197    {  return m_size;   }
198 
empty() const199    bool empty() const
200    {  return !m_size;   }
201 
clear()202    void clear()
203    {
204       this->shrink_to_fit(0u);
205    }
206 
207    private:
208    RandRawIt m_ptr;
209    size_type m_size;
210    size_type m_capacity;
211 };
212 
213 template<class Iterator, class SizeType, class Op>
214 class range_xbuf
215 {
216    range_xbuf(const range_xbuf &);
217    range_xbuf & operator=(const range_xbuf &);
218 
219    public:
220    typedef SizeType size_type;
221    typedef Iterator iterator;
222 
range_xbuf(Iterator first,Iterator last)223    range_xbuf(Iterator first, Iterator last)
224       : m_first(first), m_last(first), m_cap(last)
225    {}
226 
227    template<class RandIt>
move_assign(RandIt first,size_type n)228    void move_assign(RandIt first, size_type n)
229    {
230       BOOST_ASSERT(size_type(n) <= size_type(m_cap-m_first));
231       m_last = Op()(forward_t(), first, first+n, m_first);
232    }
233 
~range_xbuf()234    ~range_xbuf()
235    {}
236 
capacity() const237    size_type capacity() const
238    {  return m_cap-m_first;   }
239 
data() const240    Iterator data() const
241    {  return m_first;   }
242 
end() const243    Iterator end() const
244    {  return m_last;   }
245 
size() const246    size_type size() const
247    {  return m_last-m_first;   }
248 
empty() const249    bool empty() const
250    {  return m_first == m_last;   }
251 
clear()252    void clear()
253    {
254       m_last = m_first;
255    }
256 
257    template<class RandIt>
add(RandIt it)258    iterator add(RandIt it)
259    {
260       Iterator pos(m_last);
261       *pos = boost::move(*it);
262       ++m_last;
263       return pos;
264    }
265 
set_size(size_type size)266    void set_size(size_type size)
267    {
268       m_last  = m_first;
269       m_last += size;
270    }
271 
272    private:
273    Iterator const m_first;
274    Iterator m_last;
275    Iterator const m_cap;
276 };
277 
278 
279 
280 // @cond
281 
282 /*
283 template<typename Unsigned>
284 inline Unsigned gcd(Unsigned x, Unsigned y)
285 {
286    if(0 == ((x &(x-1)) | (y & (y-1)))){
287       return x < y ? x : y;
288    }
289    else{
290       do
291       {
292          Unsigned t = x % y;
293          x = y;
294          y = t;
295       } while (y);
296       return x;
297    }
298 }
299 */
300 
301 //Modified version from "An Optimal In-Place Array Rotation Algorithm", Ching-Kuang Shene
302 template<typename Unsigned>
gcd(Unsigned x,Unsigned y)303 Unsigned gcd(Unsigned x, Unsigned y)
304 {
305    if(0 == ((x &(x-1)) | (y & (y-1)))){
306       return x < y ? x : y;
307    }
308    else{
309       Unsigned z = 1;
310       while((!(x&1)) & (!(y&1))){
311          z <<=1, x>>=1, y>>=1;
312       }
313       while(x && y){
314          if(!(x&1))
315             x >>=1;
316          else if(!(y&1))
317             y >>=1;
318          else if(x >=y)
319             x = (x-y) >> 1;
320          else
321             y = (y-x) >> 1;
322       }
323       return z*(x+y);
324    }
325 }
326 
327 template<typename RandIt>
rotate_gcd(RandIt first,RandIt middle,RandIt last)328 RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
329 {
330    typedef typename iterator_traits<RandIt>::size_type size_type;
331    typedef typename iterator_traits<RandIt>::value_type value_type;
332 
333    if(first == middle)
334       return last;
335    if(middle == last)
336       return first;
337    const size_type middle_pos = size_type(middle - first);
338    RandIt ret = last - middle_pos;
339    if (middle == ret){
340       boost::adl_move_swap_ranges(first, middle, middle);
341    }
342    else{
343       const size_type length = size_type(last - first);
344       for( RandIt it_i(first), it_gcd(it_i + gcd(length, middle_pos))
345          ; it_i != it_gcd
346          ; ++it_i){
347          value_type temp(boost::move(*it_i));
348          RandIt it_j = it_i;
349          RandIt it_k = it_j+middle_pos;
350          do{
351             *it_j = boost::move(*it_k);
352             it_j = it_k;
353             size_type const left = size_type(last - it_j);
354             it_k = left > middle_pos ? it_j + middle_pos : first + (middle_pos - left);
355          } while(it_k != it_i);
356          *it_j = boost::move(temp);
357       }
358    }
359    return ret;
360 }
361 
362 template <class RandIt, class T, class Compare>
lower_bound(RandIt first,const RandIt last,const T & key,Compare comp)363 RandIt lower_bound
364    (RandIt first, const RandIt last, const T& key, Compare comp)
365 {
366    typedef typename iterator_traits
367       <RandIt>::size_type size_type;
368    size_type len = size_type(last - first);
369    RandIt middle;
370 
371    while (len) {
372       size_type step = len >> 1;
373       middle = first;
374       middle += step;
375 
376       if (comp(*middle, key)) {
377          first = ++middle;
378          len -= step + 1;
379       }
380       else{
381          len = step;
382       }
383    }
384    return first;
385 }
386 
387 template <class RandIt, class T, class Compare>
upper_bound(RandIt first,const RandIt last,const T & key,Compare comp)388 RandIt upper_bound
389    (RandIt first, const RandIt last, const T& key, Compare comp)
390 {
391    typedef typename iterator_traits
392       <RandIt>::size_type size_type;
393    size_type len = size_type(last - first);
394    RandIt middle;
395 
396    while (len) {
397       size_type step = len >> 1;
398       middle = first;
399       middle += step;
400 
401       if (!comp(key, *middle)) {
402          first = ++middle;
403          len -= step + 1;
404       }
405       else{
406          len = step;
407       }
408    }
409    return first;
410 }
411 
412 
413 template<class RandIt, class Compare, class Op>
op_merge_left(RandIt buf_first,RandIt first1,RandIt const last1,RandIt const last2,Compare comp,Op op)414 void op_merge_left( RandIt buf_first
415                     , RandIt first1
416                     , RandIt const last1
417                     , RandIt const last2
418                     , Compare comp
419                     , Op op)
420 {
421    for(RandIt first2=last1; first2 != last2; ++buf_first){
422       if(first1 == last1){
423          op(forward_t(), first2, last2, buf_first);
424          return;
425       }
426       else if(comp(*first2, *first1)){
427          op(first2, buf_first);
428          ++first2;
429       }
430       else{
431          op(first1, buf_first);
432          ++first1;
433       }
434    }
435    if(buf_first != first1){//In case all remaining elements are in the same place
436                            //(e.g. buffer is exactly the size of the second half
437                            //and all elements from the second half are less)
438       op(forward_t(), first1, last1, buf_first);
439    }
440 }
441 
442 // [buf_first, first1) -> buffer
443 // [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
444 // Elements from buffer are moved to [last2 - (first1-buf_first), last2)
445 // Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
446 template<class RandIt, class Compare>
merge_left(RandIt buf_first,RandIt first1,RandIt const last1,RandIt const last2,Compare comp)447 void merge_left
448    (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
449 {
450    op_merge_left(buf_first, first1, last1, last2, comp, move_op());
451 }
452 
453 // [buf_first, first1) -> buffer
454 // [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
455 // Elements from buffer are swapped to [last2 - (first1-buf_first), last2)
456 // Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
457 template<class RandIt, class Compare>
swap_merge_left(RandIt buf_first,RandIt first1,RandIt const last1,RandIt const last2,Compare comp)458 void swap_merge_left
459    (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
460 {
461    op_merge_left(buf_first, first1, last1, last2, comp, swap_op());
462 }
463 
464 template<class RandIt, class Compare, class Op>
op_merge_right(RandIt const first1,RandIt last1,RandIt last2,RandIt buf_last,Compare comp,Op op)465 void op_merge_right
466    (RandIt const first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp, Op op)
467 {
468    RandIt const first2 = last1;
469    while(first1 != last1){
470       if(last2 == first2){
471          op(backward_t(), first1, last1, buf_last);
472          return;
473       }
474       --last2;
475       --last1;
476       --buf_last;
477       if(comp(*last2, *last1)){
478          op(last1, buf_last);
479          ++last2;
480       }
481       else{
482          op(last2, buf_last);
483          ++last1;
484       }
485    }
486    if(last2 != buf_last){  //In case all remaining elements are in the same place
487                            //(e.g. buffer is exactly the size of the first half
488                            //and all elements from the second half are less)
489       op(backward_t(), first2, last2, buf_last);
490    }
491 }
492 
493 // [last2, buf_last) - buffer
494 // [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
495 // Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
496 template<class RandIt, class Compare>
merge_right(RandIt first1,RandIt last1,RandIt last2,RandIt buf_last,Compare comp)497 void merge_right
498    (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
499 {
500    op_merge_right(first1, last1, last2, buf_last, comp, move_op());
501 }
502 
503 // [last2, buf_last) - buffer
504 // [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
505 // Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
506 template<class RandIt, class Compare>
swap_merge_right(RandIt first1,RandIt last1,RandIt last2,RandIt buf_last,Compare comp)507 void swap_merge_right
508    (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
509 {
510    op_merge_right(first1, last1, last2, buf_last, comp, swap_op());
511 }
512 
513 ///////////////////////////////////////////////////////////////////////////////
514 //
515 //                            BUFFERED MERGE
516 //
517 ///////////////////////////////////////////////////////////////////////////////
518 template<class RandIt, class Compare, class Op, class Buf>
op_buffered_merge(RandIt first,RandIt const middle,RandIt last,Compare comp,Op op,Buf & xbuf)519 void op_buffered_merge
520       ( RandIt first, RandIt const middle, RandIt last
521       , Compare comp, Op op
522       , Buf &xbuf)
523 {
524    if(first != middle && middle != last && comp(*middle, middle[-1])){
525       typedef typename iterator_traits<RandIt>::size_type   size_type;
526       size_type const len1 = size_type(middle-first);
527       size_type const len2 = size_type(last-middle);
528       if(len1 <= len2){
529          first = boost::movelib::upper_bound(first, middle, *middle, comp);
530          xbuf.move_assign(first, size_type(middle-first));
531          op_merge_with_right_placed
532             (xbuf.data(), xbuf.end(), first, middle, last, comp, op);
533       }
534       else{
535          last = boost::movelib::lower_bound(middle, last, middle[-1], comp);
536          xbuf.move_assign(middle, size_type(last-middle));
537          op_merge_with_left_placed
538             (first, middle, last, xbuf.data(), xbuf.end(), comp, op);
539       }
540    }
541 }
542 
543 template<class RandIt, class Compare, class XBuf>
buffered_merge(RandIt first,RandIt const middle,RandIt last,Compare comp,XBuf & xbuf)544 void buffered_merge
545       ( RandIt first, RandIt const middle, RandIt last
546       , Compare comp
547       , XBuf &xbuf)
548 {
549    op_buffered_merge(first, middle, last, comp, move_op(), xbuf);
550 }
551 
552 //Complexity: min(len1,len2)^2 + max(len1,len2)
553 template<class RandIt, class Compare>
merge_bufferless_ON2(RandIt first,RandIt middle,RandIt last,Compare comp)554 void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp)
555 {
556    if((middle - first) < (last - middle)){
557       while(first != middle){
558          RandIt const old_last1 = middle;
559          middle = boost::movelib::lower_bound(middle, last, *first, comp);
560          first = rotate_gcd(first, old_last1, middle);
561          if(middle == last){
562             break;
563          }
564          do{
565             ++first;
566          } while(first != middle && !comp(*middle, *first));
567       }
568    }
569    else{
570       while(middle != last){
571          RandIt p = boost::movelib::upper_bound(first, middle, last[-1], comp);
572          last = rotate_gcd(p, middle, last);
573          middle = p;
574          if(middle == first){
575             break;
576          }
577          --p;
578          do{
579             --last;
580          } while(middle != last && !comp(last[-1], *p));
581       }
582    }
583 }
584 
585 static const std::size_t MergeBufferlessONLogNRotationThreshold = 16u;
586 
587 template <class RandIt, class Compare>
merge_bufferless_ONlogN_recursive(RandIt first,RandIt middle,RandIt last,typename iterator_traits<RandIt>::size_type len1,typename iterator_traits<RandIt>::size_type len2,Compare comp)588 void merge_bufferless_ONlogN_recursive
589    ( RandIt first, RandIt middle, RandIt last
590    , typename iterator_traits<RandIt>::size_type len1
591    , typename iterator_traits<RandIt>::size_type len2
592    , Compare comp)
593 {
594    typedef typename iterator_traits<RandIt>::size_type size_type;
595 
596    while(1) {
597       //trivial cases
598       if (!len2) {
599          return;
600       }
601       else if (!len1) {
602          return;
603       }
604       else if (size_type(len1 | len2) == 1u) {
605          if (comp(*middle, *first))
606             adl_move_swap(*first, *middle);
607          return;
608       }
609       else if(size_type(len1+len2) < MergeBufferlessONLogNRotationThreshold){
610          merge_bufferless_ON2(first, middle, last, comp);
611          return;
612       }
613 
614       RandIt first_cut = first;
615       RandIt second_cut = middle;
616       size_type len11 = 0;
617       size_type len22 = 0;
618       if (len1 > len2) {
619          len11 = len1 / 2;
620          first_cut +=  len11;
621          second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp);
622          len22 = size_type(second_cut - middle);
623       }
624       else {
625          len22 = len2 / 2;
626          second_cut += len22;
627          first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
628          len11 = size_type(first_cut - first);
629       }
630       RandIt new_middle = rotate_gcd(first_cut, middle, second_cut);
631 
632       //Avoid one recursive call doing a manual tail call elimination on the biggest range
633       const size_type len_internal = len11+len22;
634       if( len_internal < (len1 + len2 - len_internal) ) {
635          merge_bufferless_ONlogN_recursive(first, first_cut,  new_middle, len11, len22,        comp);
636          first = new_middle;
637          middle = second_cut;
638          len1 -= len11;
639          len2 -= len22;
640       }
641       else {
642          merge_bufferless_ONlogN_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
643          middle = first_cut;
644          last = new_middle;
645          len1 = len11;
646          len2 = len22;
647       }
648    }
649 }
650 
651 
652 //Complexity: NlogN
653 template<class RandIt, class Compare>
merge_bufferless_ONlogN(RandIt first,RandIt middle,RandIt last,Compare comp)654 void merge_bufferless_ONlogN(RandIt first, RandIt middle, RandIt last, Compare comp)
655 {
656    typedef typename iterator_traits<RandIt>::size_type size_type;
657    merge_bufferless_ONlogN_recursive
658       (first, middle, last, size_type(middle - first), size_type(last - middle), comp);
659 }
660 
661 template<class RandIt, class Compare>
merge_bufferless(RandIt first,RandIt middle,RandIt last,Compare comp)662 void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
663 {
664    #define BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
665    #ifdef BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
666    merge_bufferless_ONlogN(first, middle, last, comp);
667    #else
668    merge_bufferless_ON2(first, middle, last, comp);
669    #endif   //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
670 }
671 
672 // [r_first, r_last) are already in the right part of the destination range.
673 template <class Compare, class InputIterator, class InputOutIterator, class Op>
op_merge_with_right_placed(InputIterator first,InputIterator last,InputOutIterator dest_first,InputOutIterator r_first,InputOutIterator r_last,Compare comp,Op op)674 void op_merge_with_right_placed
675    ( InputIterator first, InputIterator last
676    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
677    , Compare comp, Op op)
678 {
679    BOOST_ASSERT((last - first) == (r_first - dest_first));
680    while ( first != last ) {
681       if (r_first == r_last) {
682          InputOutIterator end = op(forward_t(), first, last, dest_first);
683          BOOST_ASSERT(end == r_last);
684          boost::ignore_unused(end);
685          return;
686       }
687       else if (comp(*r_first, *first)) {
688          op(r_first, dest_first);
689          ++r_first;
690       }
691       else {
692          op(first, dest_first);
693          ++first;
694       }
695       ++dest_first;
696    }
697    // Remaining [r_first, r_last) already in the correct place
698 }
699 
700 template <class Compare, class InputIterator, class InputOutIterator>
swap_merge_with_right_placed(InputIterator first,InputIterator last,InputOutIterator dest_first,InputOutIterator r_first,InputOutIterator r_last,Compare comp)701 void swap_merge_with_right_placed
702    ( InputIterator first, InputIterator last
703    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
704    , Compare comp)
705 {
706    op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, swap_op());
707 }
708 
709 // [first, last) are already in the right part of the destination range.
710 template <class Compare, class Op, class BidirIterator, class BidirOutIterator>
op_merge_with_left_placed(BidirOutIterator const first,BidirOutIterator last,BidirOutIterator dest_last,BidirIterator const r_first,BidirIterator r_last,Compare comp,Op op)711 void op_merge_with_left_placed
712    ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
713    , BidirIterator const r_first, BidirIterator r_last
714    , Compare comp, Op op)
715 {
716    BOOST_ASSERT((dest_last - last) == (r_last - r_first));
717    while( r_first != r_last ) {
718       if(first == last) {
719          BidirOutIterator res = op(backward_t(), r_first, r_last, dest_last);
720          BOOST_ASSERT(last == res);
721          boost::ignore_unused(res);
722          return;
723       }
724       --r_last;
725       --last;
726       if(comp(*r_last, *last)){
727          ++r_last;
728          --dest_last;
729          op(last, dest_last);
730       }
731       else{
732          ++last;
733          --dest_last;
734          op(r_last, dest_last);
735       }
736    }
737    // Remaining [first, last) already in the correct place
738 }
739 
740 // @endcond
741 
742 // [first, last) are already in the right part of the destination range.
743 template <class Compare, class BidirIterator, class BidirOutIterator>
merge_with_left_placed(BidirOutIterator const first,BidirOutIterator last,BidirOutIterator dest_last,BidirIterator const r_first,BidirIterator r_last,Compare comp)744 void merge_with_left_placed
745    ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
746    , BidirIterator const r_first, BidirIterator r_last
747    , Compare comp)
748 {
749    op_merge_with_left_placed(first, last, dest_last, r_first, r_last, comp, move_op());
750 }
751 
752 // [r_first, r_last) are already in the right part of the destination range.
753 template <class Compare, class InputIterator, class InputOutIterator>
merge_with_right_placed(InputIterator first,InputIterator last,InputOutIterator dest_first,InputOutIterator r_first,InputOutIterator r_last,Compare comp)754 void merge_with_right_placed
755    ( InputIterator first, InputIterator last
756    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
757    , Compare comp)
758 {
759    op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, move_op());
760 }
761 
762 // [r_first, r_last) are already in the right part of the destination range.
763 // [dest_first, r_first) is uninitialized memory
764 template <class Compare, class InputIterator, class InputOutIterator>
uninitialized_merge_with_right_placed(InputIterator first,InputIterator last,InputOutIterator dest_first,InputOutIterator r_first,InputOutIterator r_last,Compare comp)765 void uninitialized_merge_with_right_placed
766    ( InputIterator first, InputIterator last
767    , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
768    , Compare comp)
769 {
770    BOOST_ASSERT((last - first) == (r_first - dest_first));
771    typedef typename iterator_traits<InputOutIterator>::value_type value_type;
772    InputOutIterator const original_r_first = r_first;
773 
774    destruct_n<value_type, InputOutIterator> d(dest_first);
775 
776    while ( first != last && dest_first != original_r_first ) {
777       if (r_first == r_last) {
778          for(; dest_first != original_r_first; ++dest_first, ++first){
779             ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
780             d.incr();
781          }
782          d.release();
783          InputOutIterator end = ::boost::move(first, last, original_r_first);
784          BOOST_ASSERT(end == r_last);
785          boost::ignore_unused(end);
786          return;
787       }
788       else if (comp(*r_first, *first)) {
789          ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*r_first));
790          d.incr();
791          ++r_first;
792       }
793       else {
794          ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
795          d.incr();
796          ++first;
797       }
798       ++dest_first;
799    }
800    d.release();
801    merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
802 }
803 
804 /// This is a helper function for the merge routines.
805 template<typename BidirectionalIterator1, typename BidirectionalIterator2>
806    BidirectionalIterator1
rotate_adaptive(BidirectionalIterator1 first,BidirectionalIterator1 middle,BidirectionalIterator1 last,typename iterator_traits<BidirectionalIterator1>::size_type len1,typename iterator_traits<BidirectionalIterator1>::size_type len2,BidirectionalIterator2 buffer,typename iterator_traits<BidirectionalIterator1>::size_type buffer_size)807    rotate_adaptive(BidirectionalIterator1 first,
808       BidirectionalIterator1 middle,
809       BidirectionalIterator1 last,
810       typename iterator_traits<BidirectionalIterator1>::size_type len1,
811       typename iterator_traits<BidirectionalIterator1>::size_type len2,
812       BidirectionalIterator2 buffer,
813       typename iterator_traits<BidirectionalIterator1>::size_type buffer_size)
814 {
815    if (len1 > len2 && len2 <= buffer_size)
816    {
817       if(len2) //Protect against self-move ranges
818       {
819          BidirectionalIterator2 buffer_end = boost::move(middle, last, buffer);
820          boost::move_backward(first, middle, last);
821          return boost::move(buffer, buffer_end, first);
822       }
823       else
824          return first;
825    }
826    else if (len1 <= buffer_size)
827    {
828       if(len1) //Protect against self-move ranges
829       {
830          BidirectionalIterator2 buffer_end = boost::move(first, middle, buffer);
831          BidirectionalIterator1 ret = boost::move(middle, last, first);
832          boost::move(buffer, buffer_end, ret);
833          return ret;
834       }
835       else
836          return last;
837    }
838    else
839       return rotate_gcd(first, middle, last);
840 }
841 
842 template<typename BidirectionalIterator,
843    typename Pointer, typename Compare>
merge_adaptive_ONlogN_recursive(BidirectionalIterator first,BidirectionalIterator middle,BidirectionalIterator last,typename iterator_traits<BidirectionalIterator>::size_type len1,typename iterator_traits<BidirectionalIterator>::size_type len2,Pointer buffer,typename iterator_traits<BidirectionalIterator>::size_type buffer_size,Compare comp)844    void merge_adaptive_ONlogN_recursive
845    (BidirectionalIterator first,
846       BidirectionalIterator middle,
847       BidirectionalIterator last,
848       typename iterator_traits<BidirectionalIterator>::size_type len1,
849       typename iterator_traits<BidirectionalIterator>::size_type len2,
850       Pointer buffer,
851       typename iterator_traits<BidirectionalIterator>::size_type buffer_size,
852       Compare comp)
853 {
854    typedef typename iterator_traits<BidirectionalIterator>::size_type size_type;
855    //trivial cases
856    if (!len2 || !len1) {
857       return;
858    }
859    else if (len1 <= buffer_size || len2 <= buffer_size)
860    {
861       range_xbuf<Pointer, size_type, move_op> rxbuf(buffer, buffer + buffer_size);
862       buffered_merge(first, middle, last, comp, rxbuf);
863    }
864    else if (size_type(len1 + len2) == 2u) {
865       if (comp(*middle, *first))
866          adl_move_swap(*first, *middle);
867       return;
868    }
869    else if (size_type(len1 + len2) < MergeBufferlessONLogNRotationThreshold) {
870       merge_bufferless_ON2(first, middle, last, comp);
871       return;
872    }
873    BidirectionalIterator first_cut = first;
874    BidirectionalIterator second_cut = middle;
875    size_type len11 = 0;
876    size_type len22 = 0;
877    if (len1 > len2)  //(len1 < len2)
878    {
879       len11 = len1 / 2;
880       first_cut += len11;
881       second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp);
882       len22 = second_cut - middle;
883    }
884    else
885    {
886       len22 = len2 / 2;
887       second_cut += len22;
888       first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
889       len11 = first_cut - first;
890    }
891 
892    BidirectionalIterator new_middle
893       = rotate_adaptive(first_cut, middle, second_cut,
894          size_type(len1 - len11), len22, buffer,
895          buffer_size);
896    merge_adaptive_ONlogN_recursive(first, first_cut, new_middle, len11,
897       len22, buffer, buffer_size, comp);
898    merge_adaptive_ONlogN_recursive(new_middle, second_cut, last,
899       len1 - len11, len2 - len22, buffer, buffer_size, comp);
900 }
901 
902 
903 template<typename BidirectionalIterator, typename Compare, typename RandRawIt>
merge_adaptive_ONlogN(BidirectionalIterator first,BidirectionalIterator middle,BidirectionalIterator last,Compare comp,RandRawIt uninitialized,typename iterator_traits<BidirectionalIterator>::size_type uninitialized_len)904 void merge_adaptive_ONlogN(BidirectionalIterator first,
905 		                     BidirectionalIterator middle,
906 		                     BidirectionalIterator last,
907 		                     Compare comp,
908                            RandRawIt uninitialized,
909                            typename iterator_traits<BidirectionalIterator>::size_type uninitialized_len)
910 {
911    typedef typename iterator_traits<BidirectionalIterator>::value_type  value_type;
912    typedef typename iterator_traits<BidirectionalIterator>::size_type   size_type;
913 
914    if (first == middle || middle == last)
915       return;
916 
917    if(uninitialized_len)
918    {
919       const size_type len1 = size_type(middle - first);
920       const size_type len2 = size_type(last - middle);
921 
922       ::boost::movelib::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
923       xbuf.initialize_until(uninitialized_len, *first);
924 	   merge_adaptive_ONlogN_recursive(first, middle, last, len1, len2, xbuf.begin(), uninitialized_len, comp);
925    }
926    else
927    {
928       merge_bufferless(first, middle, last, comp);
929    }
930 }
931 
932 
933 }  //namespace movelib {
934 }  //namespace boost {
935 
936 #endif   //#define BOOST_MOVE_MERGE_HPP
937