diff --git a/doc/move.qbk b/doc/move.qbk index eaa3c22..e70baef 100644 --- a/doc/move.qbk +++ b/doc/move.qbk @@ -806,7 +806,8 @@ Special thanks to: * Removed support for deprecated GCC compilers. * Fixed bugs: - * [@https://github.com/boostorg/move/pull/23 Git Pull #23: ['"Add minimal cmake file "]]. + * [@https://github.com/boostorg/move/pull/23 Git Pull #23: ['"Add minimal cmake file"]]. + * [@https://github.com/boostorg/move/issues/25 Git Pull #25: ['"daptive_merge is broken for iterator_traits::size_type != std::size_t"]]. [endsect] diff --git a/include/boost/move/algo/adaptive_merge.hpp b/include/boost/move/algo/adaptive_merge.hpp index f907b5c..2169843 100644 --- a/include/boost/move/algo/adaptive_merge.hpp +++ b/include/boost/move/algo/adaptive_merge.hpp @@ -309,7 +309,7 @@ void adaptive_merge_impl template void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp , typename iterator_traits::value_type* uninitialized = 0 - , std::size_t uninitialized_len = 0) + , typename iterator_traits::size_type uninitialized_len = 0) { typedef typename iterator_traits::size_type size_type; typedef typename iterator_traits::value_type value_type; @@ -340,7 +340,7 @@ void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp return; } while(1); - ::boost::movelib::adaptive_xbuf xbuf(uninitialized, uninitialized_len); + ::boost::movelib::adaptive_xbuf xbuf(uninitialized, size_type(uninitialized_len)); ::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf); } diff --git a/include/boost/move/algo/adaptive_sort.hpp b/include/boost/move/algo/adaptive_sort.hpp index b32cdc0..5819399 100644 --- a/include/boost/move/algo/adaptive_sort.hpp +++ b/include/boost/move/algo/adaptive_sort.hpp @@ -148,7 +148,7 @@ typename iterator_traits::size_type } xbuf.clear(); //2*l_build_buf or total already merged - return min_value(elements_in_blocks, 2*l_build_buf); + return min_value(elements_in_blocks, 2*l_build_buf); } template @@ -185,14 +185,14 @@ void adaptive_sort_combine_blocks bool const is_last = combined_i==n_reg_combined; size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined; - range_xbuf rbuf( (use_buf && xbuf_used) ? (combined_first-l_block) : combined_first, combined_first); + range_xbuf rbuf( (use_buf && xbuf_used) ? (combined_first-l_block) : combined_first, combined_first); size_type n_block_a, n_block_b, l_irreg1, l_irreg2; combine_params( keys, key_comp, l_cur_combined , l_prev_merged, l_block, rbuf , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combpar: ", len + l_block); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp)); if(!use_buf){ merge_blocks_bufferless (keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp); @@ -211,14 +211,14 @@ void adaptive_sort_combine_blocks size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined; RandIt const combined_last(combined_first+l_cur_combined); - range_xbuf rbuf(combined_last, xbuf_used ? (combined_last+l_block) : combined_last); + range_xbuf rbuf(combined_last, xbuf_used ? (combined_last+l_block) : combined_last); size_type n_block_a, n_block_b, l_irreg1, l_irreg2; combine_params( keys, key_comp, l_cur_combined , l_prev_merged, l_block, rbuf , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combpar: ", len + l_block); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp)); merge_blocks_right (keys, key_comp, combined_first, l_block, n_block_a, n_block_b, l_irreg2, comp, xbuf_used); BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After merge_blocks_R: ", len + l_block); @@ -263,7 +263,7 @@ bool adaptive_sort_combine_all_blocks // Implies l_block == n_keys/2 && use_internal_buf == true //Otherwise, just give up and and use all keys to merge using rotations (use_internal_buf = false) bool use_internal_buf = false; - size_type const l_block = lblock_for_combine(l_intbuf, n_keys, 2*l_merged, use_internal_buf); + size_type const l_block = lblock_for_combine(l_intbuf, n_keys, size_type(2*l_merged), use_internal_buf); BOOST_ASSERT(!l_intbuf || (l_block == l_intbuf)); BOOST_ASSERT(n == 0 || (!use_internal_buf || prev_use_internal_buf) ); BOOST_ASSERT(n == 0 || (!use_internal_buf || l_prev_block == l_block) ); @@ -607,12 +607,12 @@ void adaptive_sort_impl template void adaptive_sort( RandIt first, RandIt last, Compare comp , RandRawIt uninitialized - , std::size_t uninitialized_len) + , typename iterator_traits::size_type uninitialized_len) { typedef typename iterator_traits::size_type size_type; typedef typename iterator_traits::value_type value_type; - ::boost::movelib::adaptive_xbuf xbuf(uninitialized, uninitialized_len); + ::boost::movelib::adaptive_xbuf xbuf(uninitialized, uninitialized_len); ::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf); } diff --git a/include/boost/move/algo/detail/adaptive_sort_merge.hpp b/include/boost/move/algo/detail/adaptive_sort_merge.hpp index 6b2aa8f..60ef24a 100644 --- a/include/boost/move/algo/detail/adaptive_sort_merge.hpp +++ b/include/boost/move/algo/detail/adaptive_sort_merge.hpp @@ -328,11 +328,11 @@ void merge_blocks_bufferless RandItKeys key_range2(key_first); size_type min_check = n_block_a == n_block_left ? 0u : n_block_a; - size_type max_check = min_value(min_check+1, n_block_left); + size_type max_check = min_value(min_check+1, n_block_left); for (RandIt f = first+l_irreg1; n_block_left; --n_block_left, ++key_range2, f += l_block, min_check -= min_check != 0, max_check -= max_check != 0) { size_type const next_key_idx = find_next_block(key_range2, key_comp, f, l_block, min_check, max_check, comp); RandItKeys const key_next(key_range2 + next_key_idx); - max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left); + max_check = min_value(max_value(max_check, next_key_idx+size_type(2)), n_block_left); RandIt const first_min = f + next_key_idx*l_block; @@ -344,12 +344,12 @@ void merge_blocks_bufferless n_bef_irreg2 += l_irreg_pos_count; swap_and_update_key(key_next, key_range2, key_mid, f, f + l_block, first_min); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(f, f+l_block, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, first_min + l_block, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(f, f+l_block, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first_min, first_min + l_block, comp)); BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((f == (first+l_irreg1)) || !comp(*f, *(f-l_block))); } } - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first+l_irreg1+n_bef_irreg2*l_block, first_irr2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first+l_irreg1+n_bef_irreg2*l_block, first_irr2, comp)); RandIt first1 = first; RandIt last1 = first+l_irreg1; @@ -361,11 +361,11 @@ void merge_blocks_bufferless first1 = is_range1_A == is_range2_A ? last1 : partial_merge_bufferless(first1, last1, last1 + l_block, &is_range1_A, comp); last1 += l_block; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, first1, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, first1, comp)); } merge_bufferless(is_range1_A ? first1 : last1, first_irr2, last_irr2, comp); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, last_irr2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, last_irr2, comp)); } // Complexity: 2*distance(first, last)+max_collected^2/2 @@ -615,7 +615,7 @@ void stable_merge typedef typename iterator_traits::size_type size_type; size_type const len1 = size_type(middle-first); size_type const len2 = size_type(last-middle); - size_type const l_min = min_value(len1, len2); + size_type const l_min = min_value(len1, len2); if(xbuf.capacity() >= l_min){ buffered_merge(first, middle, last, comp, xbuf); xbuf.clear(); @@ -624,6 +624,7 @@ void stable_merge //merge_bufferless(first, middle, last, comp); merge_adaptive_ONlogN(first, middle, last, comp, xbuf.begin(), xbuf.capacity()); } + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, last, boost::movelib::unantistable(comp))); } template @@ -939,19 +940,19 @@ OutputIt op_merge_blocks_with_irreg for(; n_block_left; --n_block_left, ++key_first, min_check -= min_check != 0, max_check -= max_check != 0){ size_type next_key_idx = find_next_block(key_first, key_comp, first_reg, l_block, min_check, max_check, comp); - max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left); + max_check = min_value(max_value(max_check, next_key_idx+size_type(2)), n_block_left); RandIt const last_reg = first_reg + l_block; RandIt first_min = first_reg + next_key_idx*l_block; RandIt const last_min = first_min + l_block; (void)last_min; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_reg, last_reg, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!next_key_idx || is_sorted(first_min, last_min, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first_reg, last_reg, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!next_key_idx || boost::movelib::is_sorted(first_min, last_min, comp)); BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((!next_key_idx || !comp(*first_reg, *first_min ))); OutputIt orig_dest = dest; (void)orig_dest; dest = next_key_idx ? op_partial_merge_and_swap(first_irr, last_irr, first_reg, last_reg, first_min, dest, comp, op, is_stable) : op_partial_merge (first_irr, last_irr, first_reg, last_reg, dest, comp, op, is_stable); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(orig_dest, dest, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(orig_dest, dest, comp)); if(first_reg == dest){ dest = next_key_idx ? ::boost::adl_move_swap_ranges(first_min, last_min, first_reg) @@ -965,7 +966,7 @@ OutputIt op_merge_blocks_with_irreg RandItKeys const key_next(key_first + next_key_idx); swap_and_update_key(key_next, key_first, key_mid, last_reg, last_reg, first_min); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(orig_dest, dest, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(orig_dest, dest, comp)); first_reg = last_reg; } return dest; @@ -1017,17 +1018,17 @@ void op_merge_blocks_left //Process all regular blocks before the irregular B block //////////////////////////////////////////////////////////////////////////// size_type min_check = n_block_a == n_block_left ? 0u : n_block_a; - size_type max_check = min_value(min_check+1, n_block_left); + size_type max_check = min_value(min_check+size_type(1), n_block_left); for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) { size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp); - max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left); + max_check = min_value(max_value(max_check, next_key_idx+size_type(2)), n_block_left); RandIt const first_min = first2 + next_key_idx*l_block; RandIt const last_min = first_min + l_block; (void)last_min; RandIt const last2 = first2 + l_block; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first1, last1, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || is_sorted(first_min, last_min, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first1, last1, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first2, last2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || boost::movelib::is_sorted(first_min, last_min, comp)); //Check if irregular b block should go here. //If so, break to the special code handling the irregular block @@ -1068,7 +1069,7 @@ void op_merge_blocks_left (buffer, buffer+(last1-first1), first2, last2, first_min, buf_beg, buf_end, comp, op, is_range1_A); } (void)unmerged; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, unmerged, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first-l_block, unmerged, comp)); swap_and_update_key( key_next, key_range2, key_mid, first2, last2 , last_min - size_type(last2 - first2)); @@ -1117,7 +1118,7 @@ void op_merge_blocks_left else if(!is_buffer_middle){ buffer = op(forward_t(), first1, last1, buffer); } - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, buffer, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first-l_block, buffer, comp)); //////////////////////////////////////////////////////////////////////////// //Process irregular B block and remaining A blocks @@ -1126,7 +1127,7 @@ void op_merge_blocks_left ( key_range2, key_mid, key_comp, first2, first_irr2, last_irr2 , buffer, l_block, n_block_left, min_check, max_check, comp, false, op); buffer = op(forward_t(), first_irr2, last_irr2, buffer);(void)buffer; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, buffer, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first-l_block, buffer, comp)); } // first - first element to merge. @@ -1240,18 +1241,18 @@ void op_merge_blocks_with_buf //Process all regular blocks before the irregular B block //////////////////////////////////////////////////////////////////////////// size_type min_check = n_block_a == n_block_left ? 0u : n_block_a; - size_type max_check = min_value(min_check+1, n_block_left); + size_type max_check = min_value(min_check+size_type(1), n_block_left); for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) { size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp); - max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left); + max_check = min_value(max_value(max_check, next_key_idx+size_type(2)), n_block_left); RandIt first_min = first2 + next_key_idx*l_block; RandIt const last_min = first_min + l_block; (void)last_min; RandIt const last2 = first2 + l_block; bool const buffer_empty = buffer == buffer_end; (void)buffer_empty; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(buffer_empty ? is_sorted(first1, last1, comp) : is_sorted(buffer, buffer_end, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || is_sorted(first_min, last_min, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(buffer_empty ? boost::movelib::is_sorted(first1, last1, comp) : boost::movelib::is_sorted(buffer, buffer_end, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first2, last2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || boost::movelib::is_sorted(first_min, last_min, comp)); //Check if irregular b block should go here. //If so, break to the special code handling the irregular block @@ -1273,10 +1274,10 @@ void op_merge_blocks_with_buf //swap_and_update_key(key_next, key_range2, key_mid, first2, last2, first_min); buffer_end = buffer_and_update_key(key_next, key_range2, key_mid, first2, last2, first_min, buffer = buf_first, op); BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_swp: ", len); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp)); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, last_min, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first2, last2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first_min, last_min, comp)); first1 = first2; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, first1, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, first1, comp)); } else { RandIt const unmerged = op_partial_merge_and_save(first1, last1, first2, last2, first_min, buffer, buffer_end, comp, op, is_range1_A); @@ -1296,10 +1297,10 @@ void op_merge_blocks_with_buf } BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!is_range_1_empty || (last_min-first_min) == (last2-unmerged)); BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_swp: ", len); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, last_min, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first_min, last_min, comp)); is_range1_A ^= is_range_1_empty; first1 = unmerged; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, unmerged, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, unmerged, comp)); } BOOST_ASSERT( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left)); is_range2_A ? --n_block_a_left : --n_block_b_left; @@ -1307,7 +1308,7 @@ void op_merge_blocks_with_buf first2 = last2; } RandIt res = op(forward_t(), buffer, buffer_end, first1); (void)res; - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, res, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, res, comp)); BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_fwd: ", len); //////////////////////////////////////////////////////////////////////////// @@ -1325,14 +1326,14 @@ void op_merge_blocks_with_buf , (make_reverse_iterator)(first_irr2), rbuf_beg, (make_reverse_iterator)(buffer), (make_reverse_iterator)(last_irr2) , l_block, n_block_left, 0, n_block_left , inverse(comp), true, op).base(); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(dest, last_irr2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(dest, last_irr2, comp)); BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_irg: ", len); buffer_end = rbuf_beg.base(); BOOST_ASSERT((dest-last1) == (buffer_end-buffer)); op_merge_with_left_placed(is_range1_A ? first1 : last1, last1, dest, buffer, buffer_end, comp, op); BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_with_left_plc:", len); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, last_irr2, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, last_irr2, comp)); } ////////////////////////////////// @@ -1446,17 +1447,17 @@ typename iterator_traits::size_type RandIt pos = first_block; while((elements_in_blocks - p0) > 2*l_merged) { op_merge_left(pos-l_merged, pos, pos+l_merged, pos+2*l_merged, comp, op); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, pos+l_merged, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(pos-l_merged, pos+l_merged, comp)); p0 += 2*l_merged; pos = first_block+p0; } if((elements_in_blocks-p0) > l_merged) { op_merge_left(pos-l_merged, pos, pos+l_merged, first_block+elements_in_blocks, comp, op); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, pos-l_merged+(first_block+elements_in_blocks-pos), comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(pos-l_merged, pos-l_merged+(first_block+elements_in_blocks-pos), comp)); } else { op(forward_t(), pos, first_block+elements_in_blocks, pos-l_merged); - BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, first_block+elements_in_blocks-l_merged, comp)); + BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(pos-l_merged, first_block+elements_in_blocks-l_merged, comp)); } first_block -= l_merged; l_left_space -= l_merged; diff --git a/include/boost/move/algo/detail/merge.hpp b/include/boost/move/algo/detail/merge.hpp index 427f6f3..58df061 100644 --- a/include/boost/move/algo/detail/merge.hpp +++ b/include/boost/move/algo/detail/merge.hpp @@ -19,11 +19,12 @@ #include #include #include +#include namespace boost { namespace movelib { -template +template::size_type> class adaptive_xbuf { adaptive_xbuf(const adaptive_xbuf &); @@ -35,21 +36,22 @@ class adaptive_xbuf public: typedef RandRawIt iterator; + typedef SizeType size_type; adaptive_xbuf() : m_ptr(), m_size(0), m_capacity(0) {} - adaptive_xbuf(RandRawIt raw_memory, std::size_t capacity) + adaptive_xbuf(RandRawIt raw_memory, size_type capacity) : m_ptr(raw_memory), m_size(0), m_capacity(capacity) {} template - void move_assign(RandIt first, std::size_t n) + void move_assign(RandIt first, size_type n) { if(n <= m_size){ boost::move(first, first+n, m_ptr); - std::size_t size = m_size; + size_type size = m_size; while(size-- != n){ m_ptr[size].~T(); } @@ -63,7 +65,7 @@ class adaptive_xbuf } template - void push_back(RandIt first, std::size_t n) + void push_back(RandIt first, size_type n) { BOOST_ASSERT(m_capacity - m_size >= n); boost::uninitialized_move(first, first+n, m_ptr+m_size); @@ -94,22 +96,22 @@ class adaptive_xbuf } } - void set_size(std::size_t size) + void set_size(size_type size) { m_size = size; } - void shrink_to_fit(std::size_t const size) + void shrink_to_fit(size_type const size) { if(m_size > size){ - for(std::size_t szt_i = size; szt_i != m_size; ++szt_i){ + for(size_type szt_i = size; szt_i != m_size; ++szt_i){ m_ptr[szt_i].~T(); } m_size = size; } } - void initialize_until(std::size_t const size, T &t) + void initialize_until(size_type const size, T &t) { BOOST_ASSERT(m_size < m_capacity); if(m_size < size){ @@ -148,7 +150,7 @@ class adaptive_xbuf public: template - bool supports_aligned_trailing(std::size_t size, std::size_t trail_count) const + bool supports_aligned_trailing(size_type size, size_type trail_count) const { if(this->is_raw_ptr(this->data()) && m_capacity){ uintptr_t u_addr_sz = uintptr_t(&*(this->data()+size)); @@ -166,7 +168,7 @@ class adaptive_xbuf } template - U *aligned_trailing(std::size_t pos) const + U *aligned_trailing(size_type pos) const { uintptr_t u_addr = uintptr_t(&*(this->data()+pos)); u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U); @@ -178,7 +180,7 @@ class adaptive_xbuf this->clear(); } - std::size_t capacity() const + size_type capacity() const { return m_capacity; } iterator data() const @@ -190,7 +192,7 @@ class adaptive_xbuf iterator end() const { return m_ptr+m_size; } - std::size_t size() const + size_type size() const { return m_size; } bool empty() const @@ -203,18 +205,18 @@ class adaptive_xbuf private: RandRawIt m_ptr; - std::size_t m_size; - std::size_t m_capacity; + size_type m_size; + size_type m_capacity; }; -template +template class range_xbuf { range_xbuf(const range_xbuf &); range_xbuf & operator=(const range_xbuf &); public: - typedef typename iterator_traits::size_type size_type; + typedef SizeType size_type; typedef Iterator iterator; range_xbuf(Iterator first, Iterator last) @@ -222,7 +224,7 @@ class range_xbuf {} template - void move_assign(RandIt first, std::size_t n) + void move_assign(RandIt first, size_type n) { BOOST_ASSERT(size_type(n) <= size_type(m_cap-m_first)); m_last = Op()(forward_t(), first, first+n, m_first); @@ -231,7 +233,7 @@ class range_xbuf ~range_xbuf() {} - std::size_t capacity() const + size_type capacity() const { return m_cap-m_first; } Iterator data() const @@ -240,7 +242,7 @@ class range_xbuf Iterator end() const { return m_last; } - std::size_t size() const + size_type size() const { return m_last-m_first; } bool empty() const @@ -260,7 +262,7 @@ class range_xbuf return pos; } - void set_size(std::size_t size) + void set_size(size_type size) { m_last = m_first; m_last += size; @@ -581,11 +583,14 @@ void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp static const std::size_t MergeBufferlessONLogNRotationThreshold = 16u; -template +template void merge_bufferless_ONlogN_recursive - (RandIt first, RandIt middle, RandIt last, SizeType len1, SizeType len2, Compare comp) + ( RandIt first, RandIt middle, RandIt last + , typename iterator_traits::size_type len1 + , typename iterator_traits::size_type len2 + , Compare comp) { - typedef SizeType size_type; + typedef typename iterator_traits::size_type size_type; while(1) { //trivial cases @@ -841,15 +846,15 @@ void uninitialized_merge_with_left_placed /// This is a helper function for the merge routines. -template +template BidirectionalIterator1 rotate_adaptive(BidirectionalIterator1 first, BidirectionalIterator1 middle, BidirectionalIterator1 last, - SizeType len1, SizeType len2, + typename iterator_traits::size_type len1, + typename iterator_traits::size_type len2, BidirectionalIterator2 buffer, - SizeType buffer_size) + typename iterator_traits::size_type buffer_size) { if (len1 > len2 && len2 <= buffer_size) { @@ -878,70 +883,64 @@ template void merge_adaptive_ONlogN_recursive (BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, - SizeType len1, SizeType len2, - Pointer buffer, SizeType buffer_size, + typename iterator_traits::size_type len1, + typename iterator_traits::size_type len2, + Pointer buffer, + typename iterator_traits::size_type buffer_size, Compare comp) { typedef typename iterator_traits::size_type size_type; - if (len1 <= buffer_size || len2 <= buffer_size) + //trivial cases + if (!len2 || !len1) { + return; + } + else if (len1 <= buffer_size || len2 <= buffer_size) { - range_xbuf rxbuf(buffer, buffer + buffer_size); + range_xbuf rxbuf(buffer, buffer + buffer_size); buffered_merge(first, middle, last, comp, rxbuf); } + else if (size_type(len1 + len2) == 2u) { + if (comp(*middle, *first)) + adl_move_swap(*first, *middle); + return; + } + else if (size_type(len1 + len2) < MergeBufferlessONLogNRotationThreshold) { + merge_bufferless_ON2(first, middle, last, comp); + return; + } + BidirectionalIterator first_cut = first; + BidirectionalIterator second_cut = middle; + size_type len11 = 0; + size_type len22 = 0; + if (len1 > len2) //(len1 < len2) + { + len11 = len1 / 2; + first_cut += len11; + second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp); + len22 = second_cut - middle; + } else { - //trivial cases - if (!len2) { - return; - } - else if (!len1) { - return; - } - else if (size_type(len1 | len2) == 1u) { - if (comp(*middle, *first)) - adl_move_swap(*first, *middle); - return; - } - else if (size_type(len1 + len2) < MergeBufferlessONLogNRotationThreshold) { - merge_bufferless_ON2(first, middle, last, comp); - return; - } - BidirectionalIterator first_cut = first; - BidirectionalIterator second_cut = middle; - size_type len11 = 0; - size_type len22 = 0; - if (len1 > len2) //(len1 < len2) - { - len11 = len1 / 2; - //len11 = buffer_size; - first_cut += len11; - second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp); - len22 = second_cut - middle; - } - else - { - //len22 = len2 / 2; - len22 = buffer_size; - second_cut += len22; - first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp); - len11 = first_cut - first; - } - - BidirectionalIterator new_middle - = rotate_adaptive(first_cut, middle, second_cut, - len1 - len11, len22, buffer, - buffer_size); - merge_adaptive_ONlogN_recursive(first, first_cut, new_middle, len11, - len22, buffer, buffer_size, comp); - merge_adaptive_ONlogN_recursive(new_middle, second_cut, last, - len1 - len11, len2 - len22, buffer, buffer_size, comp); + len22 = len2 / 2; + second_cut += len22; + first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp); + len11 = first_cut - first; } + + BidirectionalIterator new_middle + = rotate_adaptive(first_cut, middle, second_cut, + size_type(len1 - len11), len22, buffer, + buffer_size); + merge_adaptive_ONlogN_recursive(first, first_cut, new_middle, len11, + len22, buffer, buffer_size, comp); + merge_adaptive_ONlogN_recursive(new_middle, second_cut, last, + len1 - len11, len2 - len22, buffer, buffer_size, comp); } @@ -951,7 +950,7 @@ void merge_adaptive_ONlogN(BidirectionalIterator first, BidirectionalIterator last, Compare comp, RandRawIt uninitialized, - std::size_t uninitialized_len) + typename iterator_traits::size_type uninitialized_len) { typedef typename iterator_traits::value_type value_type; typedef typename iterator_traits::size_type size_type; diff --git a/include/boost/move/algo/predicate.hpp b/include/boost/move/algo/predicate.hpp index 01f9586..ca76b75 100644 --- a/include/boost/move/algo/predicate.hpp +++ b/include/boost/move/algo/predicate.hpp @@ -36,11 +36,22 @@ struct antistable bool operator()(const U &u, const V & v) { return !m_comp(v, u); } + const Comp &get() const + { return m_comp; } + private: antistable & operator=(const antistable &); Comp &m_comp; }; +template +Comp unantistable(Comp comp) +{ return comp; } + +template +Comp unantistable(antistable comp) +{ return comp.get(); } + template class negate { diff --git a/test/adaptive_merge_test.cpp b/test/adaptive_merge_test.cpp index 7a55e1f..1a64707 100644 --- a/test/adaptive_merge_test.cpp +++ b/test/adaptive_merge_test.cpp @@ -66,8 +66,19 @@ bool test_random_shuffled(std::size_t const element_count, std::size_t const num return true; } +void instantiate_smalldiff_iterators() +{ + typedef randit short_rand_it_t; + boost::movelib::adaptive_merge(short_rand_it_t(), short_rand_it_t(), short_rand_it_t(), less_int()); + + typedef randit schar_rand_it_t; + boost::movelib::adaptive_merge(schar_rand_it_t(), schar_rand_it_t(), schar_rand_it_t(), less_int()); +} + int main() { + instantiate_smalldiff_iterators(); + const std::size_t NIter = 100; test_random_shuffled(10001, 3, NIter); test_random_shuffled(10001, 65, NIter); diff --git a/test/adaptive_sort_test.cpp b/test/adaptive_sort_test.cpp index 686b4bd..973dd4c 100644 --- a/test/adaptive_sort_test.cpp +++ b/test/adaptive_sort_test.cpp @@ -38,7 +38,7 @@ bool test_random_shuffled(std::size_t const element_count, std::size_t const num std::srand(0); - for (std::size_t i = 0; i != num_iter; ++i) + for (std::size_t it = 0; it != num_iter; ++it) { ::random_shuffle(elements.get(), elements.get() + element_count); for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){ @@ -59,8 +59,19 @@ bool test_random_shuffled(std::size_t const element_count, std::size_t const num return true; } +void instantiate_smalldiff_iterators() +{ + typedef randit short_rand_it_t; + boost::movelib::adaptive_sort(short_rand_it_t(), short_rand_it_t(), less_int()); + + typedef randit schar_rand_it_t; + boost::movelib::adaptive_sort(schar_rand_it_t(), schar_rand_it_t(), less_int()); +} + int main() { + instantiate_smalldiff_iterators(); + const std::size_t NIter = 100; test_random_shuffled(10001, 3, NIter); test_random_shuffled(10001, 65, NIter); diff --git a/test/order_type.hpp b/test/order_type.hpp index da4a90a..de398ab 100644 --- a/test/order_type.hpp +++ b/test/order_type.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -169,4 +170,106 @@ inline bool is_buffer(T *elements, std::size_t element_count) } +//size_type iterator +template +class randit +{ + public: + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef D difference_type; + typedef T* pointer; + typedef T& reference; + + private: + T* m_ptr; + + public: + explicit randit(T* ptr) + : m_ptr(ptr) + {} + + public: + + //Constructors + randit() + : m_ptr() //Value initialization to achieve "null iterators" (N3644) + {} + + randit(const randit& other) + : m_ptr(other.m_ptr) + {} + + randit & operator=(const randit& other) + { m_ptr = other.m_ptr; return *this; } + + //T* like operators + reference operator*() const + { return *m_ptr; } + + pointer operator->() const + { return m_ptr; } + + reference operator[](difference_type off) const + { return m_ptr[off]; } + + //Increment / Decrement + randit& operator++() + { ++m_ptr; return *this; } + + randit operator++(int) + { return randit(m_ptr++); } + + randit& operator--() + { --m_ptr; return *this; } + + randit operator--(int) + { return randit(m_ptr--); } + + //Arithmetic + randit& operator+=(difference_type off) + { m_ptr += off; return *this; } + + randit& operator-=(difference_type off) + { m_ptr -= off; return *this; } + + friend randit operator+(const randit &x, difference_type off) + { return randit(x.m_ptr+off); } + + friend randit operator+(difference_type off, randit right) + { right.m_ptr += off; return right; } + + friend randit operator-(randit left, difference_type off) + { left.m_ptr -= off; return left; } + + friend difference_type operator-(const randit &left, const randit& right) + { return difference_type(left.m_ptr - right.m_ptr); } + + //Comparison operators + friend bool operator== (const randit& l, const randit& r) + { return l.m_ptr == r.m_ptr; } + + friend bool operator!= (const randit& l, const randit& r) + { return l.m_ptr != r.m_ptr; } + + friend bool operator< (const randit& l, const randit& r) + { return l.m_ptr < r.m_ptr; } + + friend bool operator<= (const randit& l, const randit& r) + { return l.m_ptr <= r.m_ptr; } + + friend bool operator> (const randit& l, const randit& r) + { return l.m_ptr > r.m_ptr; } + + friend bool operator>= (const randit& l, const randit& r) + { return l.m_ptr >= r.m_ptr; } +}; + +struct less_int +{ + bool operator()(int l, int r) + { return l < r; } +}; + + #endif //BOOST_MOVE_TEST_ORDER_TYPE_HPP