Fixes Issue #25

This commit is contained in:
Ion Gaztañaga
2019-04-08 00:32:28 +02:00
parent 2d00bc5d74
commit bfdfca0b88
9 changed files with 267 additions and 130 deletions

View File

@ -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<RandIt>::size_type != std::size_t"]].
[endsect]

View File

@ -309,7 +309,7 @@ void adaptive_merge_impl
template<class RandIt, class Compare>
void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
, typename iterator_traits<RandIt>::value_type* uninitialized = 0
, std::size_t uninitialized_len = 0)
, typename iterator_traits<RandIt>::size_type uninitialized_len = 0)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iterator_traits<RandIt>::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<value_type> xbuf(uninitialized, uninitialized_len);
::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);
}

View File

@ -148,7 +148,7 @@ typename iterator_traits<RandIt>::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<size_type>(elements_in_blocks, 2*l_build_buf);
}
template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class XBuf>
@ -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<RandIt, move_op> rbuf( (use_buf && xbuf_used) ? (combined_first-l_block) : combined_first, combined_first);
range_xbuf<RandIt, size_type, move_op> 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<RandIt, move_op> rbuf(combined_last, xbuf_used ? (combined_last+l_block) : combined_last);
range_xbuf<RandIt, size_type, move_op> 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<class RandIt, class RandRawIt, class Compare>
void adaptive_sort( RandIt first, RandIt last, Compare comp
, RandRawIt uninitialized
, std::size_t uninitialized_len)
, typename iterator_traits<RandIt>::size_type uninitialized_len)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
::boost::movelib::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
::boost::movelib::adaptive_xbuf<value_type, RandRawIt, size_type> xbuf(uninitialized, uninitialized_len);
::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf);
}

View File

@ -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<size_type>(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<size_type>(max_value<size_type>(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<RandIt>::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<size_type>(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<class RandIt, class Comp, class XBuf>
@ -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<size_type>(max_value<size_type>(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<size_type>(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<size_type>(max_value<size_type>(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<size_type>(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<size_type>(max_value<size_type>(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<Compare>(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<RandIt>::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;

View File

@ -19,11 +19,12 @@
#include <boost/move/algo/predicate.hpp>
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/assert.hpp>
#include <cstddef>
namespace boost {
namespace movelib {
template<class T, class RandRawIt = T*>
template<class T, class RandRawIt = T*, class SizeType = typename iterator_traits<RandRawIt>::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<class RandIt>
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<class RandIt>
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<class U>
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<class U>
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<class Iterator, class Op>
template<class Iterator, class SizeType, class Op>
class range_xbuf
{
range_xbuf(const range_xbuf &);
range_xbuf & operator=(const range_xbuf &);
public:
typedef typename iterator_traits<Iterator>::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<class RandIt>
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 <class RandIt, class SizeType, class Compare>
template <class RandIt, class Compare>
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<RandIt>::size_type len1
, typename iterator_traits<RandIt>::size_type len2
, Compare comp)
{
typedef SizeType size_type;
typedef typename iterator_traits<RandIt>::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<typename BidirectionalIterator1, typename BidirectionalIterator2,
typename SizeType>
template<typename BidirectionalIterator1, typename BidirectionalIterator2>
BidirectionalIterator1
rotate_adaptive(BidirectionalIterator1 first,
BidirectionalIterator1 middle,
BidirectionalIterator1 last,
SizeType len1, SizeType len2,
typename iterator_traits<BidirectionalIterator1>::size_type len1,
typename iterator_traits<BidirectionalIterator1>::size_type len2,
BidirectionalIterator2 buffer,
SizeType buffer_size)
typename iterator_traits<BidirectionalIterator1>::size_type buffer_size)
{
if (len1 > len2 && len2 <= buffer_size)
{
@ -878,70 +883,64 @@ template<typename BidirectionalIterator1, typename BidirectionalIterator2,
return rotate_gcd(first, middle, last);
}
template<typename BidirectionalIterator, typename SizeType,
template<typename BidirectionalIterator,
typename Pointer, typename Compare>
void merge_adaptive_ONlogN_recursive
(BidirectionalIterator first,
BidirectionalIterator middle,
BidirectionalIterator last,
SizeType len1, SizeType len2,
Pointer buffer, SizeType buffer_size,
typename iterator_traits<BidirectionalIterator>::size_type len1,
typename iterator_traits<BidirectionalIterator>::size_type len2,
Pointer buffer,
typename iterator_traits<BidirectionalIterator>::size_type buffer_size,
Compare comp)
{
typedef typename iterator_traits<BidirectionalIterator>::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<Pointer, move_op> rxbuf(buffer, buffer + buffer_size);
range_xbuf<Pointer, size_type, move_op> 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<BidirectionalIterator>::size_type uninitialized_len)
{
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
typedef typename iterator_traits<BidirectionalIterator>::size_type size_type;

View File

@ -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<class Comp>
Comp unantistable(Comp comp)
{ return comp; }
template<class Comp>
Comp unantistable(antistable<Comp> comp)
{ return comp.get(); }
template <class Comp>
class negate
{

View File

@ -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<int, short> short_rand_it_t;
boost::movelib::adaptive_merge(short_rand_it_t(), short_rand_it_t(), short_rand_it_t(), less_int());
typedef randit<int, signed char> 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<order_move_type>(10001, 3, NIter);
test_random_shuffled<order_move_type>(10001, 65, NIter);

View File

@ -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<int, short> short_rand_it_t;
boost::movelib::adaptive_sort(short_rand_it_t(), short_rand_it_t(), less_int());
typedef randit<int, signed char> 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<order_move_type>(10001, 3, NIter);
test_random_shuffled<order_move_type>(10001, 65, NIter);

View File

@ -14,6 +14,7 @@
#include <boost/config.hpp>
#include <boost/move/core.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <cstddef>
#include <cstdio>
@ -169,4 +170,106 @@ inline bool is_buffer(T *elements, std::size_t element_count)
}
//size_type iterator
template <class T, class D>
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