should be it
This commit is contained in:
21
external/duckdb/third_party/vergesort/LICENSE
vendored
Normal file
21
external/duckdb/third_party/vergesort/LICENSE
vendored
Normal 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.
|
||||
56
external/duckdb/third_party/vergesort/detail/insertion_sort.h
vendored
Normal file
56
external/duckdb/third_party/vergesort/detail/insertion_sort.h
vendored
Normal 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_
|
||||
51
external/duckdb/third_party/vergesort/detail/is_sorted_until.h
vendored
Normal file
51
external/duckdb/third_party/vergesort/detail/is_sorted_until.h
vendored
Normal 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_
|
||||
48
external/duckdb/third_party/vergesort/detail/iter_sort3.h
vendored
Normal file
48
external/duckdb/third_party/vergesort/detail/iter_sort3.h
vendored
Normal 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_
|
||||
41
external/duckdb/third_party/vergesort/detail/log2.h
vendored
Normal file
41
external/duckdb/third_party/vergesort/detail/log2.h
vendored
Normal 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_
|
||||
68
external/duckdb/third_party/vergesort/detail/prevnext.h
vendored
Normal file
68
external/duckdb/third_party/vergesort/detail/prevnext.h
vendored
Normal 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_
|
||||
138
external/duckdb/third_party/vergesort/detail/quicksort.h
vendored
Normal file
138
external/duckdb/third_party/vergesort/detail/quicksort.h
vendored
Normal 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_
|
||||
352
external/duckdb/third_party/vergesort/vergesort.h
vendored
Normal file
352
external/duckdb/third_party/vergesort/vergesort.h
vendored
Normal 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_
|
||||
Reference in New Issue
Block a user