@@ -22,6 +22,56 @@ This implementation of timsort notably avoids using the postfix `++` or `--` ope
2222are used, which means that timsort will work even if the postfix operators are not present or return an incompatible
2323type such as ` void ` .
2424
25+ Merging sorted ranges efficiently is an important part of the TimSort algorithm. This library exposes its merge
26+ algorithm in the public API. According to the benchmarks, ` gfx::timmerge ` is slower than ` std::inplace_merge ` on
27+ heavily/randomly overlapping subranges of simple elements, but it is faster for complex elements such as ` std::string `
28+ and on sparsely overlapping subranges. ` gfx::timmerge ` should be usable as a drop-in replacement for
29+ ` std::inplace_merge ` , with the difference that it can't fallback to a O(n log n) algorithm when there isn't enough
30+ extra heap memory available. Like ` gfx::timsort ` , ` gfx::timmerge ` can take a projection function and avoids using the
31+ postfix ` ++ ` or ` -- ` operators.
32+
33+ The full list of available signatures is as follows (in namespace ` gfx ` ):
34+
35+ ``` cpp
36+ // timsort overloads taking a pair of iterators
37+
38+ template <typename RandomAccessIterator>
39+ void timsort (RandomAccessIterator const first, RandomAccessIterator const last);
40+
41+ template <typename RandomAccessIterator, typename Compare>
42+ void timsort(RandomAccessIterator const first, RandomAccessIterator const last,
43+ Compare compare);
44+
45+ template <typename RandomAccessIterator, typename Compare, typename Projection>
46+ void timsort(RandomAccessIterator const first, RandomAccessIterator const last,
47+ Compare compare, Projection projection);
48+
49+ // timsort overloads taking a range
50+
51+ template <typename RandomAccessRange >
52+ void timsort(RandomAccessRange &range);
53+
54+ template <typename RandomAccessRange, typename Compare>
55+ void timsort(RandomAccessRange &range, Compare compare);
56+
57+ template <typename RandomAccessRange, typename Compare, typename Projection>
58+ void timsort(RandomAccessRange &range, Compare compare, Projection projection);
59+
60+ // timmerge overloads
61+
62+ template <typename RandomAccessIterator >
63+ void timmerge(RandomAccessIterator first, RandomAccessIterator middle,
64+ RandomAccessIterator last);
65+
66+ template <typename RandomAccessIterator, typename Compare>
67+ void timmerge(RandomAccessIterator first, RandomAccessIterator middle,
68+ RandomAccessIterator last, Compare compare);
69+
70+ template <typename RandomAccessIterator, typename Compare, typename Projection>
71+ void timmerge(RandomAccessIterator first, RandomAccessIterator middle,
72+ RandomAccessIterator last, Compare compare, Projection projection);
73+ ```
74+
2575## EXAMPLE
2676
2777Example of using timsort with a comparison function and a projection function to sort a vector of strings by length:
@@ -78,7 +128,7 @@ conan install timsort/1.2.2
78128
79129## DIAGNOSTICS & INFORMATION
80130
81- A few configuration macros allow gfx::timsort to emit diagnostic, which might be helpful to diagnose issues:
131+ A few configuration macros allow ` gfx::timsort ` and ` gfx::timmerge ` to emit diagnostic, which might be helpful to diagnose issues:
82132* Defining ` GFX_TIMSORT_ENABLE_ASSERT ` inserts assertions in key locations in the algorithm to avoid logic errors.
83133* Defining ` GFX_TIMSORT_ENABLE_LOG ` inserts logs in key locations, which allow to follow more closely the flow of the algorithm.
84134
@@ -106,7 +156,7 @@ built with CMake:
106156Benchmarks are available in the ` benchmarks ` subdirectory, and can be constructed directly by passing ` BUILD_BENCHMARKS=ON `
107157variable to CMake during the configuration step.
108158
109- Example output (timing scale: sec.):
159+ Example bench_sort output (timing scale: sec.):
110160
111161 c++ -v
112162 Apple LLVM version 7.0.0 (clang-700.0.72)
@@ -147,3 +197,29 @@ Example output (timing scale: sec.):
147197 std::sort 0.402458
148198 std::stable_sort 2.436326
149199 timsort 0.298639
200+
201+ Example bench_merge output (timing scale: milliseconds; omitted detailed results for different
202+ middle iterator positions, reformatted to improve readability):
203+
204+ c++ -v
205+ Using built-in specs.
206+ ...
207+ Target: x86_64-pc-linux-gnu
208+ ...
209+ gcc version 10.2.0 (GCC)
210+ c++ -I ../include -Wall -Wextra -g -DNDEBUG -O2 -std=c++11 bench_merge.cpp -o bench_merge
211+ ./bench_merge
212+ size 100000
213+ element type\algorithm: std::inplace_merge timmerge
214+ RANDOMIZED SEQUENCE
215+ [int] approx. average 33.404430 37.047990
216+ [std::string] approx. average 324.964249 210.297207
217+ REVERSED SEQUENCE
218+ [int] approx. average 11.441404 4.017482
219+ [std::string] approx. average 305.649503 114.773898
220+ SORTED SEQUENCE
221+ [int] approx. average 4.291098 0.105571
222+ [std::string] approx. average 158.238114 0.273858
223+
224+ Detailed bench_merge results for different middle iterator positions can be found at
225+ https://github.com/timsort/cpp-TimSort/wiki/Benchmark-results
0 commit comments