should be it

This commit is contained in:
2025-10-24 19:21:19 -05:00
parent a4b23fc57c
commit f09560c7b1
14047 changed files with 3161551 additions and 1 deletions

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Morwenn <morwenn29@hotmail.fr>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,56 @@
/*
pdqsort.h - Pattern-defeating quicksort.
Copyright (c) 2015 Orson Peters
Modified by Morwenn in 2015-2016 to use in vergesort
This software is provided 'as-is', without any express or implied warranty. In no event will the
authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial
applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the
original software. If you use this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as
being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef VERGESORT_DETAIL_INSERTION_SORT_H_
#define VERGESORT_DETAIL_INSERTION_SORT_H_
#include <iterator>
#include "detail/prevnext.h"
namespace duckdb_vergesort
{
namespace detail
{
// Sorts [begin, end) using insertion sort with the given comparison function.
template<typename BidirectionalIterator, typename Compare>
void insertion_sort(BidirectionalIterator begin, BidirectionalIterator end, Compare comp) {
typedef typename std::iterator_traits<BidirectionalIterator>::value_type T;
if (begin == end) return;
for (BidirectionalIterator cur = detail::next(begin) ; cur != end ; ++cur) {
BidirectionalIterator sift = cur;
BidirectionalIterator sift_1 = detail::prev(cur);
// Compare first so we can avoid 2 moves for an element already positioned correctly.
if (comp(*sift, *sift_1)) {
T tmp = VERGESORT_PREFER_MOVE(*sift);
do {
*sift-- = VERGESORT_PREFER_MOVE(*sift_1);
} while (sift != begin && comp(tmp, *--sift_1));
*sift = VERGESORT_PREFER_MOVE(tmp);
}
}
}
}}
#endif // VERGESORT_DETAIL_INSERTION_SORT_H_

View File

@@ -0,0 +1,51 @@
/*
* vergesort.h - General-purpose hybrid sort
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2016 Morwenn <morwenn29@hotmail.fr>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef VERGESORT_DETAIL_IS_SORTED_UNTIL_H_
#define VERGESORT_DETAIL_IS_SORTED_UNTIL_H_
namespace duckdb_vergesort
{
namespace detail
{
// C++03 implementation of std::is_sorted_until
template<typename ForwardIterator, typename Compare>
ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last,
Compare compare)
{
if (first != last) {
ForwardIterator next = first;
while (++next != last) {
if (compare(*next, *first)) {
return next;
}
first = next;
}
}
return last;
}
}}
#endif // VERGESORT_DETAIL_IS_SORTED_UNTIL_H_

View File

@@ -0,0 +1,48 @@
/*
* vergesort.h - General-purpose hybrid sort
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2016 Morwenn <morwenn29@hotmail.fr>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef VERGESORT_DETAIL_ITER_SORT3_H_
#define VERGESORT_DETAIL_ITER_SORT3_H_
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <algorithm>
namespace duckdb_vergesort
{
namespace detail
{
template<typename Iterator, typename Compare>
void iter_sort3(Iterator a, Iterator b, Iterator c,
Compare compare)
{
if (compare(*b, *a)) { std::iter_swap(a, b); }
if (compare(*c, *b)) { std::iter_swap(b, c); }
if (compare(*b, *a)) { std::iter_swap(a, b); }
}
}}
#endif // VERGESORT_DETAIL_ITER_SORT3_H_

View File

@@ -0,0 +1,41 @@
/*
pdqsort.h - Pattern-defeating quicksort.
Copyright (c) 2015 Orson Peters
Modified by Morwenn in 2015-2016 to use in vergesort
This software is provided 'as-is', without any express or implied warranty. In no event will the
authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial
applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the
original software. If you use this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as
being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef VERGESORT_DETAIL_LOG2_H_
#define VERGESORT_DETAIL_LOG2_H_
namespace duckdb_vergesort
{
namespace detail
{
// Returns floor(log2(n)), assumes n > 0
template<typename Integer>
Integer log2(Integer n)
{
Integer log = 0;
while (n >>= 1) {
++log;
}
return log;
}
}}
#endif // VERGESORT_DETAIL_LOG2_H_

View File

@@ -0,0 +1,68 @@
/*
* vergesort.h - General-purpose hybrid sort
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2016 Morwenn <morwenn29@hotmail.fr>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef VERGESORT_DETAIL_PREVNEXT_H_
#define VERGESORT_DETAIL_PREVNEXT_H_
#include <iterator>
namespace duckdb_vergesort
{
namespace detail
{
template<typename BidirectionalIterator>
BidirectionalIterator
prev(BidirectionalIterator it)
{
return --it;
}
template<typename BidirectionalIterator>
BidirectionalIterator
prev(BidirectionalIterator it,
typename std::iterator_traits<BidirectionalIterator>::difference_type n)
{
std::advance(it, -n);
return it;
}
template<typename ForwardIterator>
ForwardIterator
next(ForwardIterator it)
{
return ++it;
}
template<typename ForwardIterator>
ForwardIterator
next(ForwardIterator it,
typename std::iterator_traits<ForwardIterator>::difference_type n)
{
std::advance(it, n);
return it;
}
}}
#endif // VERGESORT_DETAIL_PREVNEXT_H_

View File

@@ -0,0 +1,138 @@
/*
* vergesort.h - General-purpose hybrid sort
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2016 Morwenn <morwenn29@hotmail.fr>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef VERGESORT_DETAIL_QUICKSORT_H_
#define VERGESORT_DETAIL_QUICKSORT_H_
#include <algorithm>
#include <iterator>
#include "detail/insertion_sort.h"
#include "detail/iter_sort3.h"
#include "detail/prevnext.h"
namespace duckdb_vergesort
{
namespace detail
{
// partial application structs for partition
template<typename T, typename Compare>
struct partition_pivot_left
{
const T& pivot;
Compare compare;
partition_pivot_left(const T& pivot, const Compare& compare):
pivot(pivot),
compare(compare)
{}
bool operator()(const T& elem) const
{
return compare(elem, pivot);
}
};
template<typename T, typename Compare>
struct partition_pivot_right
{
const T& pivot;
Compare compare;
partition_pivot_right(const T& pivot, const Compare& compare):
pivot(pivot),
compare(compare)
{}
bool operator()(const T& elem) const
{
return not compare(pivot, elem);
}
};
template<typename ForwardIterator, typename Compare>
void quicksort(ForwardIterator first, ForwardIterator last,
typename std::iterator_traits<ForwardIterator>::difference_type size,
Compare compare)
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
typedef typename std::iterator_traits<ForwardIterator>::difference_type difference_type;
using std::swap;
// If the collection is small, fall back to insertion sort
if (size < 32) {
insertion_sort(first, last, compare);
return;
}
// Choose pivot as median of 9
ForwardIterator it1 = detail::next(first, size / 8);
ForwardIterator it2 = detail::next(it1, size / 8);
ForwardIterator it3 = detail::next(it2, size / 8);
ForwardIterator middle = detail::next(it3, size/2 - 3*(size/8));
ForwardIterator it4 = detail::next(middle, size / 8);
ForwardIterator it5 = detail::next(it4, size / 8);
ForwardIterator it6 = detail::next(it5, size / 8);
ForwardIterator last_1 = detail::next(it6, size - size/2 - 3*(size/8) - 1);
iter_sort3(first, it1, it2, compare);
iter_sort3(it3, middle, it4, compare);
iter_sort3(it5, it6, last_1, compare);
iter_sort3(it1, middle, it4, compare);
// Put the pivot at position prev(last) and partition
std::iter_swap(middle, last_1);
ForwardIterator middle1 = std::partition(
first, last_1,
partition_pivot_left<value_type, Compare>(*last_1, compare)
);
// Put the pivot in its final position and partition
std::iter_swap(middle1, last_1);
ForwardIterator middle2 = std::partition(
detail::next(middle1), last,
partition_pivot_right<value_type, Compare>(*middle1, compare)
);
// Recursive call: heuristic trick here: in real world cases,
// the middle partition is more likely to be smaller than the
// right one, so computing its size should generally be cheaper
difference_type size_left = std::distance(first, middle1);
difference_type size_middle = std::distance(middle1, middle2);
difference_type size_right = size - size_left - size_middle;
// Recurse in the smallest partition first to limit the call
// stack overhead
if (size_left > size_right) {
swap(first, middle2);
swap(middle1, last);
swap(size_left, size_right);
}
quicksort(first, middle1, size_left, compare);
quicksort(middle2, last, size_right,
VERGESORT_PREFER_MOVE(compare));
}
}}
#endif // VERGESORT_DETAIL_QUICKSORT_H_

View File

@@ -0,0 +1,352 @@
/*
* vergesort.h - General-purpose hybrid sort
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2020 Morwenn <morwenn29@hotmail.fr>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef VERGESORT_VERGESORT_H_
#define VERGESORT_VERGESORT_H_
// Used by several other internal headers, hence defined first
#if __cplusplus >= 201103L
#include <utility>
#define VERGESORT_PREFER_MOVE(x) std::move(x)
#else
#define VERGESORT_PREFER_MOVE(x) (x)
#endif
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iterator>
#include <list>
#include "detail/is_sorted_until.h"
#include "detail/log2.h"
// #include "detail/pdqsort.h"
#include "detail/prevnext.h"
#include "detail/quicksort.h"
namespace duckdb_vergesort
{
namespace detail
{
// In-place merge where [first, middle1), [middle1, middle2)
// and [middle2, last) are sorted. The two in-place merges are
// done in the order that should result in the smallest number
// of comparisons
template<typename BidirectionalIterator, typename Compare>
void inplace_merge3(BidirectionalIterator first, BidirectionalIterator middle1,
BidirectionalIterator middle2, BidirectionalIterator last,
Compare compare)
{
if (std::distance(first, middle1) < std::distance(middle2, last)) {
std::inplace_merge(first, middle1, middle2, compare);
std::inplace_merge(first, middle2, last, compare);
} else {
std::inplace_merge(middle1, middle2, last, compare);
std::inplace_merge(first, middle1, last, compare);
}
}
// vergesort for bidirectional iterators
template<typename BidirectionalIterator, typename Compare>
void vergesort(BidirectionalIterator first, BidirectionalIterator last,
Compare compare, std::bidirectional_iterator_tag)
{
typedef typename std::iterator_traits<BidirectionalIterator>::difference_type difference_type;
difference_type dist = std::distance(first, last);
if (dist < 80) {
// vergesort is inefficient for small collections
quicksort(first, last, dist, compare);
return;
}
// Limit under which quicksort is used
int unstable_limit = dist / log2(dist);
// Beginning of an unstable partition, last if the
// previous partition is stable
BidirectionalIterator begin_unstable = last;
// Size of the unstable partition
difference_type size_unstable = 0;
// Pair of iterators to iterate through the collection
BidirectionalIterator next = detail::is_sorted_until(first, last, compare);
if (next == last) return;
BidirectionalIterator current = detail::prev(next);
while (true) {
// Decreasing range
{
BidirectionalIterator begin_rng = current;
difference_type run_size = 1;
while (next != last) {
if (compare(*current, *next)) break;
++current;
++next;
++run_size;
}
// Reverse and merge
if (run_size > unstable_limit) {
if (begin_unstable != last) {
quicksort(begin_unstable, begin_rng, size_unstable, compare);
std::reverse(begin_rng, next);
std::inplace_merge(begin_unstable, begin_rng, next, compare);
std::inplace_merge(first, begin_unstable, next, compare);
begin_unstable = last;
size_unstable = 0;
} else {
std::reverse(begin_rng, next);
std::inplace_merge(first, begin_rng, next, compare);
}
} else {
size_unstable += run_size;
if (begin_unstable == last) {
begin_unstable = begin_rng;
}
}
if (next == last) break;
++current;
++next;
}
// Increasing range
{
BidirectionalIterator begin_rng = current;
difference_type run_size = 1;
while (next != last) {
if (compare(*next, *current)) break;
++current;
++next;
++run_size;
}
// Merge
if (run_size > unstable_limit) {
if (begin_unstable != last) {
quicksort(begin_unstable, begin_rng, size_unstable, compare);
std::inplace_merge(begin_unstable, begin_rng, next, compare);
std::inplace_merge(first, begin_unstable, next, compare);
begin_unstable = last;
size_unstable = 0;
} else {
std::inplace_merge(first, begin_rng, next, compare);
}
} else {
size_unstable += run_size;
if (begin_unstable == last) {
begin_unstable = begin_rng;
}
}
if (next == last) break;
++current;
++next;
}
}
if (begin_unstable != last) {
quicksort(begin_unstable, last, size_unstable, compare);
std::inplace_merge(first, begin_unstable, last, compare);
}
}
template<typename RandomAccessIterator, typename Compare, typename Fallback>
void vergesort(RandomAccessIterator first, RandomAccessIterator last,
Compare compare, std::random_access_iterator_tag, Fallback fallback)
{
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_type;
difference_type dist = last - first;
if (dist < 128) {
// Vergesort is inefficient for small collections
fallback(first, last);
return;
}
// Limit under which pdqsort is used to sort a sub-sequence
const difference_type unstable_limit = dist / detail::log2(dist);
// Vergesort detects big runs in ascending or descending order,
// and remember where each run ends by storing the end iterator
// of each run in this list, then it merges everything in the end
std::list<RandomAccessIterator> runs;
// Beginning of an unstable partition, or last if the previous
// partition is stable
RandomAccessIterator begin_unstable = last;
// Pair of iterators to iterate through the collection
RandomAccessIterator current = first;
RandomAccessIterator next = detail::next(first);
while (true) {
// Beginning of the current sequence
RandomAccessIterator begin_range = current;
// If the last part of the collection to sort isn't
// big enough, consider that it is an unstable sequence
if ((last - next) <= unstable_limit) {
if (begin_unstable == last) {
begin_unstable = begin_range;
}
break;
}
// Set backward iterators
current += unstable_limit;
next += unstable_limit;
// Set forward iterators
RandomAccessIterator current2 = current;
RandomAccessIterator next2 = next;
if (compare(*next, *current)) {
// Found a decreasing sequence, move iterators
// to the limits of the sequence
do {
--current;
--next;
if (compare(*current, *next)) break;
} while (current != begin_range);
if (compare(*current, *next)) ++current;
++current2;
++next2;
while (next2 != last) {
if (compare(*current2, *next2)) break;
++current2;
++next2;
}
// Check whether we found a big enough sorted sequence
if ((next2 - current) >= unstable_limit) {
std::reverse(current, next2);
if ((current - begin_range) && begin_unstable == last) {
begin_unstable = begin_range;
}
if (begin_unstable != last) {
fallback(begin_unstable, current);
runs.push_back(current);
begin_unstable = last;
}
runs.push_back(next2);
} else {
// Remember the beginning of the unsorted sequence
if (begin_unstable == last) {
begin_unstable = begin_range;
}
}
} else {
// Found an increasing sequence, move iterators
// to the limits of the sequence
do {
--current;
--next;
if (compare(*next, *current)) break;
} while (current != begin_range);
if (compare(*next, *current)) ++current;
++current2;
++next2;
while (next2 != last) {
if (compare(*next2, *current2)) break;
++current2;
++next2;
}
// Check whether we found a big enough sorted sequence
if ((next2 - current) >= unstable_limit) {
if ((current - begin_range) && begin_unstable == last) {
begin_unstable = begin_range;
}
if (begin_unstable != last) {
fallback(begin_unstable, current);
runs.push_back(current);
begin_unstable = last;
}
runs.push_back(next2);
} else {
// Remember the beginning of the unsorted sequence
if (begin_unstable == last) {
begin_unstable = begin_range;
}
}
}
if (next2 == last) break;
current = detail::next(current2);
next = detail::next(next2);
}
if (begin_unstable != last) {
// If there are unsorted elements left, sort them
runs.push_back(last);
fallback(begin_unstable, last);
}
if (runs.size() < 2) return;
// Merge runs pairwise until there aren't runs left
do {
RandomAccessIterator begin = first;
for (typename std::list<RandomAccessIterator>::iterator it = runs.begin() ;
it != runs.end() && it != detail::prev(runs.end()) ;
++it) {
std::inplace_merge(begin, *it, *detail::next(it), compare);
// Remove the middle iterator and advance
it = runs.erase(it);
begin = *it;
}
} while (runs.size() > 1);
}
}
template<typename BidirectionalIterator, typename Compare, typename Fallback>
void vergesort(BidirectionalIterator first, BidirectionalIterator last,
Compare compare, Fallback fallback)
{
typedef typename std::iterator_traits<BidirectionalIterator>::iterator_category category;
detail::vergesort(first, last, compare, category(), fallback);
}
template<typename BidirectionalIterator, typename Fallback>
void vergesort(BidirectionalIterator first, BidirectionalIterator last, Fallback fallback)
{
typedef typename std::iterator_traits<BidirectionalIterator>::value_type value_type;
vergesort(first, last, std::less<value_type>(), fallback);
}
}
#undef VERGESORT_PREFER_MOVE
#endif // VERGESORT_VERGESORT_H_