File indexing completed on 2025-01-18 09:40:51
0001
0002
0003
0004
0005
0006
0007
0008
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
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
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
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){
0393
0394
0395 op(forward_t(), first1, last1, buf_first);
0396 }
0397 }
0398
0399
0400
0401
0402
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
0411
0412
0413
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){
0444
0445
0446 op(backward_t(), first2, last2, buf_last);
0447 }
0448 }
0449
0450
0451
0452
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
0461
0462
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
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
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
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
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
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
0628 }
0629
0630
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
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
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
0696 }
0697
0698
0699
0700
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
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
0721
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
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)
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)
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
0814 if (!len2 || !len1) {
0815
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)
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 }
0890 }
0891
0892 #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
0893 #pragma GCC diagnostic pop
0894 #endif
0895
0896 #endif