Skip to content

Commit 4086c54

Browse files
committed
Remove verge_sorter
1 parent 456156e commit 4086c54

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+101
-231
lines changed

docs/Original-research.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Now, those observations/claims are there to be challenged: if you know a stable
1414

1515
### Vergesort
1616

17-
The vergesort is a new sorting algorithm which combines merge operations on almost sorted data, and falls back to another sorting algorithm when the data is not sorted enough. Somehow it can be considered as a cheap preprocessing step to take advantage of almost-sorted data when possible. Just like TimSort, it achieves linear time on some patterns, generally for almost sorted data, and should never be worse than O(n log n log log n) in the worst case - though no in-depth formal analysis has been performed.
17+
Vergesort is a sorting algorithm which combines merge operations on almost sorted data, and falls back to another sorting algorithm when the data is not sorted enough. Somehow it can be considered as a cheap preprocessing step to take advantage of almost-sorted data when possible. Just like TimSort, it achieves linear time on some patterns, generally for almost sorted data, and should never be worse than O(n log n log log n) in the worst case - though no in-depth formal analysis has been performed.
1818

1919
Best Average Worst Memory Stable
2020
n n log n n log n log log n n No
@@ -24,7 +24,7 @@ The two variations in space and time complexity depend on whether enough memory
2424

2525
While vergesort has been designed to work with random-access iterators, there also exists a version that works with bidirectional iterators. The algorithm is slightly different and a bit slower because it can't as easily jump through the collection. The complexity of that bidirectional iterators algorithm can get down to the same time as the random-access one when `quick_merge_sort` is used as the fallback algorithm.
2626

27-
The actual complexity of the algorithm is O(n log n log log n), but interestingly it is only reached in one of its paths that is among the fastest in practice. It is also possible to make vergesort stable but tweaking its reverse runs detection algorithm and making it fallback to a stable sorting algorithm.
27+
The actual complexity of the algorithm is O(n log n log log n), but interestingly it is only reached in one of its paths that is among the fastest in practice. It is also possible to make vergesort stable by tweaking its reverse runs detection algorithm and making it fallback to a stable sorting algorithm.
2828

2929
This sorting algorithm also exists as a [standalone repository][vergesort].
3030

docs/Sorter-adapters.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ struct stable_adapter;
283283
`stable_adapter` is the main customization point of those stable sorting facilities, and as such can be specialized to provide stable versions of your own unstable sorters or adapters. **cpp-sort** itself provides `stable_adapter` specializations for the following components:
284284

285285
* [`std_sorter`][std-sorter] (calls [`std::stable_sort`][std-stable-sort] instead of [`std::sort`][std-sort])
286-
* [`verge_sorter`][verge-sorter]
287286
* [`hybrid_adapter`][hybrid-adapter]
288287
* [`self_sort_adapter`][self-sort-adapter]
289288
* `stable_adapter` itself (automatic unnesting)
@@ -318,13 +317,19 @@ This little dance sometimes allows to reduce the nesting of function calls and t
318317
#include <cpp-sort/adapters/verge_adapter.h>
319318
```
320319

321-
The complexity analysis is a bit too complicated to be included in this documentation. Additionally, the space and time complexity changes depending on whether the merging algorithm has enough space to run in O(n) time or whether it needs to fall back to an O(n log n) algorithm. Assuming that the *adapted sorter* works in O(n log n) time and O(1) space, the complexity of the *resulting sorter* is as follows:
320+
Vergesort is a [*Mono*-adaptive][probe-mono] algorithm as long as the size of those runs is greater than *n / log n*; when the runs are smaller, it falls back to the *adapted sorted* to sort them.
321+
322+
The space and time complexities of this adapter change depending on whether the merging algorithm has enough space to run in O(n) time or whether it needs to fall back to an O(n log n) algorithm for merging. Assuming that the *adapted sorter* works in O(n log n) time and O(1) space, the complexity of the *resulting sorter* is as follows:
322323

323324
| Best | Average | Worst | Memory | Stable | Iterators |
324325
| ----------- | ----------- | ----------------- | ----------- | ----------- | ------------- |
325326
| n | n log n | n log n log log n | n | No | Bidirectional |
326327
| n | n log n | n log n | log n | No | Bidirectional |
327328

329+
We can understand that complexity as being bound by either the vergesort optimization layer or, by the *adapted sorter*'s complexity:
330+
* When vergesort doesn't find big enough runs, the complexity is bound by that of the *adapted sorter*.
331+
* When it does find big enough runs, the complexity is bound by the merging phase of the optimization layer. In such a case, `inplace_merge` is used to merge the runs: it uses additional memory if any is available, in which case vergesort is O(n log n). If there isn't much extra memory available, it may still require O(log n) extra memory (and thus raise an `std::bad_alloc` if there isn't that much memory available) in which case the complexity falls to O(n log n log log n).
332+
328333
The *resulting sorter* is always unstable, no matter the stability of the *adapted sorter*. It accepts bidirectional ranges.
329334

330335
```cpp
@@ -367,5 +372,4 @@ When wrapped into [`stable_adapter`][stable-adapter], it has a slightly differen
367372
[std-stable-sort]: https://en.cppreference.com/w/cpp/algorithm/stable_sort
368373
[std-true-type]: https://en.cppreference.com/w/cpp/types/integral_constant
369374
[verge-adapter]: Sorter-adapters.md#verge_adapter
370-
[verge-sorter]: Sorters.md#verge_sorter
371375
[vergesort-fallbacks]: https://github.com/Morwenn/vergesort/blob/trunk/fallbacks.md

docs/Sorters.md

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -380,33 +380,6 @@ While the sorting algorithm is stable and the complexity guarantees are good eno
380380

381381
*Changed in version 1.5.0:* `tim_sorter` now handles comparison and projection objects that aren't default-constructible.
382382

383-
### `verge_sorter`
384-
385-
```cpp
386-
#include <cpp-sort/sorters/verge_sorter.h>
387-
```
388-
389-
Implements a [vergesort][vergesort] algorithm backed by a quicksort derivative.
390-
391-
| Best | Average | Worst | Memory | Stable | Iterators |
392-
| ----------- | ----------- | ----------------- | ----------- | ----------- | ------------- |
393-
| n | n log n | n log n log log n | n | No | Random-access |
394-
| n | n log n | n log n | log n | No | Random-access |
395-
| n | n log n | n log n log log n | n | No | Bidirectional |
396-
| n | n log n | n log n | log² n | No | Bidirectional |
397-
398-
Vergesort is a [*Runs*-adaptive][probe-runs] algorithm (including descending runs) as long as the size of those runs is greater than *n / log n*; when the runs are smaller, it falls back to another sorting algorithm to sort them (pdqsort for random-access iterators, QuickMergesort otherwise).
399-
400-
Vergesort's complexity is bound either by its optimization layer or by the fallback sorter's complexity:
401-
* When it doesn't find big runs, the complexity is bound by the fallback sorter: depending on the category of iterators you can refer to the tables of either `pdq_sorter` or `quick_merge_sorter`.
402-
* When it does find big runs, vergesort's complexity is bound by the merging phase of its optimization layer. In such a case, `inplace_merge` is used to merge the runs: it will use additional memory if any is available, in which case vergesort is O(n log n). If there isn't much extra memory available, it may still require O(log n) extra memory (and thus raise an `std::bad_alloc` if there isn't that much memory available) in which case the complexity falls to O(n log n log log n). It should not happen that much, and the additional *log log n* factor is likely irrelevant for most real-world applications.
403-
404-
When wrapped into [`stable_adapter`][stable-adapter], it has a slightly different behaviour: it detects strictly descending runs instead of non-ascending ones, and wraps the fallback sorter with `stable_t`. This make the specialization stable, and faster than just using `make_stable`.
405-
406-
*Changed in version 1.6.0:* when sorting a collection made of bidirectional iterators, `verge_sorter` falls back to `quick_merge_sorter` instead of `quick_sorter`.
407-
408-
*New in version 1.9.0:* explicit specialization for `stable_adapter<verge_sorter>`.
409-
410383
### `wiki_sorter<>`
411384

412385
```cpp
@@ -537,7 +510,6 @@ struct spread_sorter:
537510
[merge-sort]: https://en.wikipedia.org/wiki/Merge_sort
538511
[pdq-sorter]: Sorters.md#pdq_sorter
539512
[pdqsort]: https://github.com/orlp/pdqsort
540-
[probe-runs]: Measures-of-presortedness.md#runs
541513
[quick-mergesort]: https://arxiv.org/abs/1307.3033
542514
[quicksort]: https://en.wikipedia.org/wiki/Quicksort
543515
[schwartz-adapter]: Sorter-adapters.md#schwartz_adapter
@@ -556,7 +528,6 @@ struct spread_sorter:
556528
[std-stable-sort]: https://en.cppreference.com/w/cpp/algorithm/stable_sort
557529
[std-vector-bool]: https://en.cppreference.com/w/cpp/container/vector_bool
558530
[timsort]: https://en.wikipedia.org/wiki/Timsort
559-
[vergesort]: https://github.com/Morwenn/vergesort
560531
[wiki-sort]: https://github.com/BonzaiThePenguin/WikiSort
561532
[wiki-sorter]: Sorters.md#wiki_sorter
562533
[writing-a-sorter]: Writing-a-sorter.md

include/cpp-sort/fwd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ namespace cppsort
5050
struct std_sorter;
5151
struct string_spread_sorter;
5252
struct tim_sorter;
53-
struct verge_sorter;
5453
template<typename BufferProvider>
5554
struct wiki_sorter;
5655

include/cpp-sort/sorters.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include <cpp-sort/sorters/spread_sorter.h>
3232
#include <cpp-sort/sorters/std_sorter.h>
3333
#include <cpp-sort/sorters/tim_sorter.h>
34-
#include <cpp-sort/sorters/verge_sorter.h>
3534
#include <cpp-sort/sorters/wiki_sorter.h>
3635

3736
#endif // CPPSORT_SORTERS_H_

include/cpp-sort/sorters/verge_sorter.h

Lines changed: 0 additions & 124 deletions
This file was deleted.

tests/adapters/every_adapter_internal_compare.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,4 @@ TEST_CASE( "test most adapters with a pointer to member function comparison",
132132
sorter{}(collection, &internal_compare<int>::compare_to);
133133
CHECK( std::is_sorted(collection.begin(), collection.end()) );
134134
}
135-
136-
SECTION( "verge_adapter" )
137-
{
138-
using sorter = cppsort::verge_adapter<
139-
cppsort::poplar_sorter
140-
>;
141-
142-
sorter{}(collection, &internal_compare<int>::compare_to);
143-
CHECK( std::is_sorted(collection.begin(), collection.end()) );
144-
}
145135
}

tests/adapters/every_adapter_non_const_compare.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,4 @@ TEST_CASE( "test adapters extended compatibility with LWG 3031", "[adapters]" )
139139
sorter{}(vec, non_const_compare);
140140
CHECK( std::is_sorted(vec.begin(), vec.end()) );
141141
}
142-
143-
SECTION( "verge_adapter" )
144-
{
145-
using sorter = cppsort::verge_adapter<
146-
cppsort::poplar_sorter
147-
>;
148-
149-
sorter{}(vec, non_const_compare);
150-
CHECK( std::is_sorted(vec.begin(), vec.end()) );
151-
}
152142
}

tests/adapters/indirect_adapter_every_sorter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ TEMPLATE_TEST_CASE( "every random-access sorter with indirect adapter", "[indire
4141
cppsort::std_sorter,
4242
cppsort::stable_adapter<cppsort::std_sorter>,
4343
cppsort::tim_sorter,
44-
cppsort::verge_sorter,
44+
old_verge_sorter,
4545
cppsort::wiki_sorter<> )
4646
{
4747
std::vector<double> collection; collection.reserve(412);
@@ -65,7 +65,7 @@ TEMPLATE_TEST_CASE( "every bidirectional sorter with indirect_adapter", "[indire
6565
cppsort::selection_sorter,
6666
cppsort::slab_sorter,
6767
cppsort::splay_sorter,
68-
cppsort::verge_sorter )
68+
old_verge_sorter )
6969
{
7070
std::list<double> collection;
7171
auto distribution = dist::shuffled{};

tests/adapters/schwartz_adapter_every_sorter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ TEMPLATE_TEST_CASE( "every random-access sorter with Schwartzian transform adapt
4747
cppsort::splay_sorter,
4848
old_split_sorter,
4949
cppsort::tim_sorter,
50-
cppsort::verge_sorter,
50+
old_verge_sorter,
5151
cppsort::wiki_sorter<cppsort::utility::fixed_buffer<0>> )
5252
{
5353
std::vector<wrapper<>> collection;
@@ -71,7 +71,7 @@ TEMPLATE_TEST_CASE( "every bidirectional sorter with Schwartzian transform adapt
7171
cppsort::selection_sorter,
7272
cppsort::slab_sorter,
7373
cppsort::splay_sorter,
74-
cppsort::verge_sorter )
74+
old_verge_sorter )
7575
{
7676
std::list<wrapper<>> collection;
7777
auto distribution = dist::shuffled{};

0 commit comments

Comments
 (0)