|
| 1 | +# Algorithm |
| 2 | +`algorithm` is a small module providing a few iterator based algorithms: |
| 3 | + |
| 4 | +- `seq::merge`: similar to `std::merge` but providing a better handling of consecutive ordered values, and has a special case for unbalanced merging (one range is way smaller than the other) |
| 5 | + |
| 6 | +- `seq::inplace_merge`: similar to `std::inplace_merge` but relying on `seq::merge` and using a user-provided buffer. `seq::inplace_merge` never allocates memory unless one of the following constant buffer is provided: |
| 7 | + - `seq::default_buffer`: uses as much memory as `std::inplace_merge` |
| 8 | + - `seq::medium_buffer`: uses 8 times less memory than with `seq::default_buffer` |
| 9 | + - `small_buffer` : uses 32 times less memory than with `seq::default_buffer` |
| 10 | + - `tiny_buffer`: uses 128 times less memory than with `seq::default_buffer` |
| 11 | + |
| 12 | + Note that a buffer of size 0 is supported, the algorithm will just be way slower. The inplace merging is based on the following [article](https://www.jmeiners.com/efficient-programming-with-components/15_merge_inplace.html) and was first published in 1981. |
| 13 | + |
| 14 | +- `seq::reverse_descending`: reverse a range sorted in descending order in a stable way: consecutive equal values are not reversed. |
| 15 | + |
| 16 | +- `seq::unique`: removed duplicates from a range in a stable way. This is very similar to `std::unique` except that the range does not need to be sorted. It uses a hash table under the hood to find duplicate values. A custom hash function and comparison function can be passed for custom types. |
| 17 | + |
| 18 | +- `seq::net_sort` and `seq::net_sort_size`: "new" generic stable sorting algorithm that is used everywhere within the seq library. `seq::net_sort` is a merge sort algorithm with the following specificities: |
| 19 | + - Bottom-up merging instead of the more traditional top-down approach, |
| 20 | + - Small blocks of 8 elements are sorted using a sorting network, |
| 21 | + - Bidirectional merging is used for relocatable types, |
| 22 | + - Ping-pong merge is used to merge 4 sorted ranges, |
| 23 | + - Can work without allocating memory through a (potentially null) user provided buffer, |
| 24 | + - Also works on bidirectional iterators. |
| 25 | + |
| 26 | + If provided buffer is one of `seq::default_buffer`, `seq::medium_buffer`, `seq::small_buffer` or `seq::tiny_buffer`, this function will try to allocate memory. |
| 27 | + |
| 28 | + From my tests on multiple input types, net_sort() is always faster than std::stable_sort(). |
| 29 | + |
| 30 | + net_sort_size() and net_sort() work on bidirectional iterators. Using net_sort_size() instead of net_sort() is faster when the range size is already known. |
| 31 | + |
| 32 | + Full credits to scandum (https://github.com/scandum) for its quadsort algorithm from which I took several ideas (bidirectional merge and ping-pong merge). |
0 commit comments