////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2015-2016. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// //! \file #ifndef BOOST_MOVE_ALGO_BUFFERLESS_MERGE_SORT_HPP #define BOOST_MOVE_ALGO_BUFFERLESS_MERGE_SORT_HPP #ifndef BOOST_CONFIG_HPP # include #endif # #if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include #include #include #include #include #include #include #include #include namespace boost { namespace movelib { // @cond namespace detail_bufferless_mergesort { static const std::size_t UnbufferedMergeSortInsertionSortThreshold = 16; //A in-placed version based on: //Jyrki Katajainen, Tomi Pasanen, Jukka Teuhola. //``Practical in-place mergesort''. Nordic Journal of Computing, 1996. template void bufferless_merge_sort(RandIt first, RandIt last, Compare comp); template void swap_sort(RandIt const first, RandIt const last, RandIt const buffer_first, RandIt const buffer_last, Compare comp, bool buffer_at_right) { typedef typename iterator_traits::size_type size_type; if (size_type(last - first) > UnbufferedMergeSortInsertionSortThreshold) { RandIt m = first + (last - first) / 2; bufferless_merge_sort(first, m, comp); bufferless_merge_sort(m, last, comp); if(buffer_at_right){ //Use antistable to minimize movements (if equal, move first half elements //to maximize the chance last half elements are already in place. boost::movelib::swap_merge_right(first, m, last, buffer_last, boost::movelib::antistable(comp)); } else{ boost::movelib::swap_merge_left(buffer_first, first, m, last, comp); } } else boost::movelib::insertion_sort_swap(first, last, buffer_first, comp); } template void bufferless_merge_sort(RandIt const first, RandIt const last, Compare comp) { typedef typename iterator_traits::size_type size_type; size_type len = size_type(last - first); if (len > size_type(UnbufferedMergeSortInsertionSortThreshold)) { len /= 2; RandIt h = last - len; //ceil(half) RandIt f = h - len; //ceil(first) swap_sort(f, h, h, last, comp, true); //[h, last) contains sorted elements //Divide unsorted first half in two len = size_type(h - first); while (len > size_type(UnbufferedMergeSortInsertionSortThreshold)) { len /= 2; RandIt n = h; //new end h = n - len; //ceil(half') f = h - len; //ceil(first') swap_sort(h, n, f, h, comp, false); // the first half of the previous working area [f, h) //contains sorted elements: working area in the middle [h, n) //Now merge small (left) sorted with big (right) sorted (buffer is between them) swap_merge_with_right_placed(f, h, h, n, last, comp); } boost::movelib::insertion_sort(first, h, comp); boost::movelib::merge_bufferless(first, h, last, comp); } else{ boost::movelib::insertion_sort(first, last, comp); } } } //namespace detail_bufferless_mergesort { // @endcond //Unstable bufferless merge sort template void bufferless_merge_sort(RandIt first, RandIt last, Compare comp) { detail_bufferless_mergesort::bufferless_merge_sort(first, last, comp); } }} //namespace boost::movelib #include #endif //#ifndef BOOST_MOVE_ALGO_BUFFERLESS_MERGE_SORT_HPP