123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- #ifndef BOOST_MOVE_ADAPTIVE_MERGE_HPP
- #define BOOST_MOVE_ADAPTIVE_MERGE_HPP
- #include <boost/move/detail/config_begin.hpp>
- #include <boost/move/algo/detail/adaptive_sort_merge.hpp>
- #include <cassert>
- #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wsign-conversion"
- #pragma GCC diagnostic ignored "-Wconversion"
- #endif
- namespace boost {
- namespace movelib {
- namespace detail_adaptive {
- template<class RandIt, class Compare, class XBuf>
- inline void adaptive_merge_combine_blocks( RandIt first
- , typename iter_size<RandIt>::type len1
- , typename iter_size<RandIt>::type len2
- , typename iter_size<RandIt>::type collected
- , typename iter_size<RandIt>::type n_keys
- , typename iter_size<RandIt>::type l_block
- , bool use_internal_buf
- , bool xbuf_used
- , Compare comp
- , XBuf & xbuf
- )
- {
- typedef typename iter_size<RandIt>::type size_type;
- size_type const len = size_type(len1+len2);
- size_type const l_combine = size_type(len-collected);
- size_type const l_combine1 = size_type(len1-collected);
- if(n_keys){
- RandIt const first_data = first+collected;
- RandIt const keys = first;
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combine: ", len);
- if(xbuf_used){
- if(xbuf.size() < l_block){
- xbuf.initialize_until(l_block, *first);
- }
- assert(xbuf.size() >= l_block);
- size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
- combine_params( keys, comp, l_combine
- , l_combine1, l_block, xbuf
- , n_block_a, n_block_b, l_irreg1, l_irreg2);
- op_merge_blocks_with_buf
- (keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, move_op(), xbuf.data());
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A mrg xbf: ", len);
- }
- else{
- size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
- combine_params( keys, comp, l_combine
- , l_combine1, l_block, xbuf
- , n_block_a, n_block_b, l_irreg1, l_irreg2);
- if(use_internal_buf){
- op_merge_blocks_with_buf
- ( keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b
- , l_irreg2, comp, swap_op(), first_data-l_block);
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A mrg buf: ", len);
- }
- else{
- merge_blocks_bufferless
- (keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp);
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A mrg nbf: ", len);
- }
- }
- }
- else{
- xbuf.shrink_to_fit(l_block);
- if(xbuf.size() < l_block){
- xbuf.initialize_until(l_block, *first);
- }
- size_type *const uint_keys = xbuf.template aligned_trailing<size_type>(l_block);
- size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
- combine_params( uint_keys, less(), l_combine
- , l_combine1, l_block, xbuf
- , n_block_a, n_block_b, l_irreg1, l_irreg2, true);
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combine: ", len);
- assert(xbuf.size() >= l_block);
- op_merge_blocks_with_buf
- (uint_keys, less(), first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, move_op(), xbuf.data());
- xbuf.clear();
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A mrg buf: ", len);
- }
- }
- template<class RandIt, class Compare, class XBuf>
- inline void adaptive_merge_final_merge( RandIt first
- , typename iter_size<RandIt>::type len1
- , typename iter_size<RandIt>::type len2
- , typename iter_size<RandIt>::type collected
- , typename iter_size<RandIt>::type l_intbuf
- , typename iter_size<RandIt>::type //l_block
- , bool //use_internal_buf
- , bool xbuf_used
- , Compare comp
- , XBuf & xbuf
- )
- {
- typedef typename iter_size<RandIt>::type size_type;
- size_type n_keys = size_type(collected-l_intbuf);
- size_type len = size_type(len1+len2);
- if (!xbuf_used || n_keys) {
- xbuf.clear();
- const size_type middle = xbuf_used && n_keys ? n_keys: collected;
- unstable_sort(first, first + middle, comp, xbuf);
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A k/b srt: ", len);
- stable_merge(first, first + middle, first + len, comp, xbuf);
- }
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A fin mrg: ", len);
- }
- template<class SizeType>
- inline static SizeType adaptive_merge_n_keys_without_external_keys(SizeType l_block, SizeType len1, SizeType len2, SizeType l_intbuf)
- {
- typedef SizeType size_type;
-
- size_type n_keys = size_type(len1/l_block + len2/l_block);
- const size_type second_half_blocks = size_type(len2/l_block);
- const size_type first_half_aux = size_type(len1 - l_intbuf);
- while(n_keys >= ((first_half_aux-n_keys)/l_block + second_half_blocks)){
- --n_keys;
- }
- ++n_keys;
- return n_keys;
- }
- template<class SizeType>
- inline static SizeType adaptive_merge_n_keys_with_external_keys(SizeType l_block, SizeType len1, SizeType len2, SizeType l_intbuf)
- {
- typedef SizeType size_type;
-
- size_type n_keys = size_type((len1-l_intbuf)/l_block + len2/l_block);
- return n_keys;
- }
- template<class SizeType, class Xbuf>
- inline SizeType adaptive_merge_n_keys_intbuf(SizeType &rl_block, SizeType len1, SizeType len2, Xbuf & xbuf, SizeType &l_intbuf_inout)
- {
- typedef SizeType size_type;
- size_type l_block = rl_block;
- size_type l_intbuf = xbuf.capacity() >= l_block ? 0u : l_block;
- if (xbuf.capacity() > l_block){
- l_block = xbuf.capacity();
- }
-
- size_type n_keys = adaptive_merge_n_keys_without_external_keys(l_block, len1, len2, l_intbuf);
- assert(n_keys >= ((len1-l_intbuf-n_keys)/l_block + len2/l_block));
- if(xbuf.template supports_aligned_trailing<size_type>
- ( l_block
- , adaptive_merge_n_keys_with_external_keys(l_block, len1, len2, l_intbuf)))
- {
- n_keys = 0u;
- }
- l_intbuf_inout = l_intbuf;
- rl_block = l_block;
- return n_keys;
- }
- template<class RandIt, class Compare, class XBuf>
- void adaptive_merge_impl
- ( RandIt first
- , typename iter_size<RandIt>::type len1
- , typename iter_size<RandIt>::type len2
- , Compare comp
- , XBuf & xbuf
- )
- {
- typedef typename iter_size<RandIt>::type size_type;
- if(xbuf.capacity() >= min_value<size_type>(len1, len2)){
- buffered_merge( first, first+len1
- , first + len1+len2, comp, xbuf);
- }
- else{
- const size_type len = size_type(len1+len2);
-
- size_type l_block = size_type(ceil_sqrt(len));
-
-
- if(len1 <= l_block*2 || len2 <= l_block*2){
- merge_bufferless(first, first+len1, first+len1+len2, comp);
- return;
- }
-
-
- size_type l_intbuf = 0;
- size_type n_keys = adaptive_merge_n_keys_intbuf(l_block, len1, len2, xbuf, l_intbuf);
- size_type const to_collect = size_type(l_intbuf+n_keys);
-
- size_type const collected = collect_unique(first, first+len1, to_collect, comp, xbuf);
- BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1("\n A collect: ", len);
-
- if(collected != to_collect && collected < 4){
- merge_bufferless(first, first+collected, first+len1, comp);
- merge_bufferless(first, first + len1, first + len1 + len2, comp);
- return;
- }
-
- bool use_internal_buf = collected == to_collect;
- if (!use_internal_buf){
- l_intbuf = 0u;
- n_keys = collected;
- l_block = lblock_for_combine(l_intbuf, n_keys, len, use_internal_buf);
-
- l_intbuf = use_internal_buf ? l_block : 0u;
- }
- bool const xbuf_used = collected == to_collect && xbuf.capacity() >= l_block;
-
- adaptive_merge_combine_blocks(first, len1, len2, collected, n_keys, l_block, use_internal_buf, xbuf_used, comp, xbuf);
-
- adaptive_merge_final_merge (first, len1, len2, collected, l_intbuf, l_block, use_internal_buf, xbuf_used, comp, xbuf);
- }
- }
- }
- template<class RandIt, class Compare>
- void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
- , typename iterator_traits<RandIt>::value_type* uninitialized = 0
- , typename iter_size<RandIt>::type uninitialized_len = 0)
- {
- typedef typename iter_size<RandIt>::type size_type;
- typedef typename iterator_traits<RandIt>::value_type value_type;
- if (first == middle || middle == last){
- return;
- }
-
- do {
- if (comp(*middle, *first)){
- break;
- }
- ++first;
- if (first == middle)
- return;
- } while(1);
- RandIt first_high(middle);
- --first_high;
- do {
- --last;
- if (comp(*last, *first_high)){
- ++last;
- break;
- }
- if (last == middle)
- return;
- } while(1);
- ::boost::movelib::adaptive_xbuf<value_type, value_type*, size_type> xbuf(uninitialized, size_type(uninitialized_len));
- ::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf);
- }
- }
- }
- #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
- #pragma GCC diagnostic pop
- #endif
- #include <boost/move/detail/config_end.hpp>
- #endif
|