Skip to content

Commit 2d48ebf

Browse files
committed
Sentinel support for timsort and timmerge
1 parent d3ab5e1 commit 2d48ebf

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ The list of available signatures is as follows (in namespace `gfx`):
3030

3131
template <
3232
std::random_access_iterator Iterator,
33+
std::sentinel_for<Iterator> Sentinel,
3334
typename Compare = std::ranges::less,
3435
typename Projection = std::identity
3536
>
3637
requires std::sortable<Iterator, Compare, Projection>
37-
void timsort(Iterator first, Iterator last,
38+
void timsort(Iterator first, Sentinel last,
3839
Compare compare={}, Projection projection={});
3940

4041
template <
@@ -49,11 +50,12 @@ void timsort(Range &range, Compare compare={}, Projection projection={});
4950

5051
template <
5152
std::random_access_iterator Iterator,
53+
std::sentinel_for<Iterator> Sentinel,
5254
typename Compare = std::ranges::less,
5355
typename Projection = std::identity
5456
>
5557
requires std::sortable<Iterator, Compare, Projection>
56-
void timmerge(Iterator first, Iterator middle, Iterator last,
58+
void timmerge(Iterator first, Iterator middle, Sentinel last,
5759
Compare compare={}, Projection projection={});
5860

5961
template <

include/gfx/timsort.hpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -695,16 +695,18 @@ template <typename RandomAccessIterator, typename Compare, typename Projection>
695695
*/
696696
template <
697697
std::random_access_iterator Iterator,
698+
std::sentinel_for<Iterator> Sentinel,
698699
typename Compare = std::ranges::less,
699700
typename Projection = std::identity
700701
>
701702
requires std::sortable<Iterator, Compare, Projection>
702-
void timmerge(Iterator first, Iterator middle, Iterator last,
703+
void timmerge(Iterator first, Iterator middle, Sentinel last,
703704
Compare comp={}, Projection proj={}) {
705+
auto last_it = std::ranges::next(first, last);
704706
GFX_TIMSORT_AUDIT(std::is_sorted(first, middle, comp, proj) && "Precondition");
705-
GFX_TIMSORT_AUDIT(std::is_sorted(middle, last, comp, proj) && "Precondition");
706-
detail::TimSort<Iterator, Compare, Projection>::merge(first, middle, last, comp, proj);
707-
GFX_TIMSORT_AUDIT(std::is_sorted(first, last, comp, proj) && "Postcondition");
707+
GFX_TIMSORT_AUDIT(std::is_sorted(middle, last_it, comp, proj) && "Precondition");
708+
detail::TimSort<Iterator, Compare, Projection>::merge(first, middle, last_it, comp, proj);
709+
GFX_TIMSORT_AUDIT(std::is_sorted(first, last_it, comp, proj) && "Postcondition");
708710
}
709711

710712
/**
@@ -728,14 +730,16 @@ void timmerge(Range &&range, std::ranges::iterator_t<Range> middle,
728730
*/
729731
template <
730732
std::random_access_iterator Iterator,
733+
std::sentinel_for<Iterator> Sentinel,
731734
typename Compare = std::ranges::less,
732735
typename Projection = std::identity
733736
>
734737
requires std::sortable<Iterator, Compare, Projection>
735-
void timsort(Iterator first, Iterator last,
738+
void timsort(Iterator first, Sentinel last,
736739
Compare comp={}, Projection proj={}) {
737-
detail::TimSort<Iterator, Compare, Projection>::sort(first, last, comp, proj);
738-
GFX_TIMSORT_AUDIT(std::is_sorted(first, last, comp, proj) && "Postcondition");
740+
auto last_it = std::ranges::next(first, last);
741+
detail::TimSort<Iterator, Compare, Projection>::sort(first, last_it, comp, proj);
742+
GFX_TIMSORT_AUDIT(std::is_sorted(first, last_it, comp, proj) && "Postcondition");
739743
}
740744

741745
/**

tests/cxx_20_tests.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SPDX-License-Identifier: MIT
44
*/
55
#include <algorithm>
6+
#include <iterator>
67
#include <numeric>
78
#include <random>
89
#include <span>
@@ -12,7 +13,7 @@
1213
#include "test_helpers.hpp"
1314

1415
TEST_CASE( "support for temporary types" ) {
15-
SECTION( "timsmerge over std::span" ) {
16+
SECTION( "timmerge over std::span" ) {
1617
std::vector<int> vec(100);
1718
std::iota(vec.begin(), vec.end(), -25);
1819
test_helpers::shuffle(vec);
@@ -35,3 +36,31 @@ TEST_CASE( "support for temporary types" ) {
3536
CHECK(std::ranges::is_sorted(vec));
3637
}
3738
}
39+
40+
TEST_CASE( "support for sentinels" )
41+
{
42+
SECTION( "timmerge with sentinel" ) {
43+
std::vector<int> vec(100);
44+
std::iota(vec.begin(), vec.end(), -25);
45+
test_helpers::shuffle(vec);
46+
47+
auto middle = vec.begin() + 38;
48+
gfx::timsort(vec.begin(), middle);
49+
gfx::timsort(middle, vec.end());
50+
51+
gfx::timmerge(std::counted_iterator(vec.begin(), 85),
52+
std::counted_iterator(middle, 85 - 38),
53+
std::default_sentinel);
54+
CHECK(std::is_sorted(vec.begin(), vec.begin() + 85));
55+
}
56+
57+
SECTION( "timsort with sentinel" ) {
58+
std::vector<int> vec(100);
59+
std::iota(vec.begin(), vec.end(), -25);
60+
test_helpers::shuffle(vec);
61+
62+
gfx::timsort(std::counted_iterator(vec.begin(), 85),
63+
std::default_sentinel);
64+
CHECK(std::is_sorted(vec.begin(), vec.begin() + 85));
65+
}
66+
}

0 commit comments

Comments
 (0)