diff --git a/doc/move.qbk b/doc/move.qbk index ec67b0c..52156e9 100644 --- a/doc/move.qbk +++ b/doc/move.qbk @@ -802,6 +802,13 @@ Special thanks to: [section:release_notes Release Notes] +[section:release_notes_boost_1_78 Boost 1.78 Release] + +* Fixed bugs: + * [@https://github.com/boostorg/move/issues/45 Git Issue #45: ['"Sort/merge bugs that affect boost::container::flat_map"]]. + +[endsect] + [section:release_notes_boost_1_77 Boost 1.77 Release] * Fixed bugs: diff --git a/include/boost/move/algo/adaptive_sort.hpp b/include/boost/move/algo/adaptive_sort.hpp index 48403bb..ab72d28 100644 --- a/include/boost/move/algo/adaptive_sort.hpp +++ b/include/boost/move/algo/adaptive_sort.hpp @@ -453,9 +453,9 @@ bool adaptive_sort_build_params l_build_buf = size_type(l_intbuf*2); n_keys = l_intbuf; } - else if(collected == (n_min_ideal_keys+l_intbuf)){ + else if(collected >= (n_min_ideal_keys+l_intbuf)){ l_build_buf = l_intbuf; - n_keys = n_min_ideal_keys; + n_keys = size_type(collected - l_intbuf); } //If collected keys are not enough, try to fix n_keys and l_intbuf. If no fix //is possible (due to very low unique keys), then go to a slow sort based on rotations. diff --git a/include/boost/move/algo/detail/merge.hpp b/include/boost/move/algo/detail/merge.hpp index 6520655..0491fa0 100644 --- a/include/boost/move/algo/detail/merge.hpp +++ b/include/boost/move/algo/detail/merge.hpp @@ -863,49 +863,48 @@ template::size_type size_type; //trivial cases if (!len2 || !len1) { - return; + // no-op } - else if (len1 <= buffer_size || len2 <= buffer_size) - { + else if (len1 <= buffer_size || len2 <= 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 = size_type(second_cut - middle); + else { + 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 = size_type(second_cut - middle); + } + else + { + len22 = len2 / 2; + second_cut += len22; + first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp); + len11 = size_type(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, + size_type(len1 - len11), size_type(len2 - len22), buffer, buffer_size, comp); } - else - { - len22 = len2 / 2; - second_cut += len22; - first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp); - len11 = size_type(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, - size_type(len1 - len11), size_type(len2 - len22), buffer, buffer_size, comp); } diff --git a/test/adaptive_sort_test.cpp b/test/adaptive_sort_test.cpp index 512138b..454c4fe 100644 --- a/test/adaptive_sort_test.cpp +++ b/test/adaptive_sort_test.cpp @@ -74,9 +74,15 @@ int main() instantiate_smalldiff_iterators(); const std::size_t NIter = 100; - test_random_shuffled(10001, 3, NIter); - test_random_shuffled(10001, 65, NIter); - test_random_shuffled(10001, 101, NIter); + //Below absolute minimal unique values + test_random_shuffled(10001, 3, NIter); + //Above absolute minimal unique values, below internal buffer + test_random_shuffled(10001, 65, NIter); + //Enough keys for internal buffer but below minimal keys + test_random_shuffled(10001, 101, NIter); + //Enough keys for internal buffer and above minimal keys + test_random_shuffled(10001, 200, NIter); + //Enough keys for internal buffer, and full keys test_random_shuffled(10001, 1023, NIter); test_random_shuffled(10001, 4095, NIter); test_random_shuffled(10001, 0, NIter);