Skip to content

Commit 88124ab

Browse files
authored
Add an audit option to verify is_sorted (off by default) (#37)
1 parent 764c2d4 commit 88124ab

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ conan install timsort/2.0.2
127127

128128
A few configuration macros allow `gfx::timsort` and `gfx::timmerge` to emit diagnostic, which might be helpful to diagnose issues:
129129
* Defining `GFX_TIMSORT_ENABLE_ASSERT` inserts assertions in key locations in the algorithm to avoid logic errors.
130+
* Defining `GFX_TIMSORT_ENABLE_AUDIT` inserts assertions that verify pre- and postconditions. These verifications can slow the
131+
algorithm down significantly. Enable the audit only while testing or debugging.
130132
* Defining `GFX_TIMSORT_ENABLE_LOG` inserts logs in key locations, which allow to follow more closely the flow of the algorithm.
131133

132134
**cpp-TimSort** follows semantic versioning and provides the following macros to retrieve the current major, minor

include/gfx/timsort.hpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,22 @@
4545

4646
// Diagnostic selection macros
4747

48-
#ifdef GFX_TIMSORT_ENABLE_ASSERT
48+
#if defined(GFX_TIMSORT_ENABLE_ASSERT) || defined(GFX_TIMSORT_ENABLE_AUDIT)
4949
# include <cassert>
50+
#endif
51+
52+
#ifdef GFX_TIMSORT_ENABLE_ASSERT
5053
# define GFX_TIMSORT_ASSERT(expr) assert(expr)
5154
#else
5255
# define GFX_TIMSORT_ASSERT(expr) ((void)0)
5356
#endif
5457

58+
#ifdef GFX_TIMSORT_ENABLE_AUDIT
59+
# define GFX_TIMSORT_AUDIT(expr) assert(expr)
60+
#else
61+
# define GFX_TIMSORT_AUDIT(expr) ((void)0)
62+
#endif
63+
5564
#ifdef GFX_TIMSORT_ENABLE_LOG
5665
# include <iostream>
5766
# define GFX_TIMSORT_LOG(expr) (std::clog << "# " << __func__ << ": " << expr << std::endl)
@@ -712,7 +721,10 @@ void timmerge(RandomAccessIterator first, RandomAccessIterator middle,
712721
RandomAccessIterator last, Compare compare, Projection projection) {
713722
typedef detail::projection_compare<Compare, Projection> compare_t;
714723
compare_t comp(std::move(compare), std::move(projection));
715-
detail::TimSort<RandomAccessIterator, compare_t>::merge(first, middle, last, std::move(comp));
724+
GFX_TIMSORT_AUDIT(std::is_sorted(first, middle, comp) && "Precondition");
725+
GFX_TIMSORT_AUDIT(std::is_sorted(middle, last, comp) && "Precondition");
726+
detail::TimSort<RandomAccessIterator, compare_t>::merge(first, middle, last, comp);
727+
GFX_TIMSORT_AUDIT(std::is_sorted(first, last, comp) && "Postcondition");
716728
}
717729

718730
/**
@@ -742,7 +754,8 @@ void timsort(RandomAccessIterator const first, RandomAccessIterator const last,
742754
Compare compare, Projection projection) {
743755
typedef detail::projection_compare<Compare, Projection> compare_t;
744756
compare_t comp(std::move(compare), std::move(projection));
745-
detail::TimSort<RandomAccessIterator, compare_t>::sort(first, last, std::move(comp));
757+
detail::TimSort<RandomAccessIterator, compare_t>::sort(first, last, comp);
758+
GFX_TIMSORT_AUDIT(std::is_sorted(first, last, comp) && "Postcondition");
746759
}
747760

748761
/**
@@ -790,6 +803,8 @@ void timsort(RandomAccessRange &range) {
790803

791804
#undef GFX_TIMSORT_ENABLE_ASSERT
792805
#undef GFX_TIMSORT_ASSERT
806+
#undef GFX_TIMSORT_ENABLE_AUDIT
807+
#undef GFX_TIMSORT_AUDIT
793808
#undef GFX_TIMSORT_ENABLE_LOG
794809
#undef GFX_TIMSORT_LOG
795810

0 commit comments

Comments
 (0)