merge.hpp 27 KB

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