Adds assert messages

review
This commit is contained in:
Robert Schadek 2019-06-25 15:55:31 +01:00
parent c256ecf65b
commit dbf9d93d95

View file

@ -464,7 +464,7 @@ if (ss != SwapStrategy.stable && isInputRange!Range && hasSwappableElements!Rang
++lo;
}
// found the left bound
assert(lo <= hi);
assert(lo <= hi, "lo must be <= hi");
for (;;)
{
if (lo == hi) return r[lo .. r.length];
@ -489,7 +489,7 @@ if (ss != SwapStrategy.stable && isInputRange!Range && hasSwappableElements!Rang
result.popFront();
}
// found the left bound
assert(!r.empty);
assert(!r.empty, "r must not be empty");
for (;;)
{
if (pred(r.back)) break;
@ -617,7 +617,8 @@ size_t pivotPartition(alias less = "a < b", Range)
(Range r, size_t pivot)
if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && hasAssignableElements!Range)
{
assert(pivot < r.length || r.length == 0 && pivot == 0);
assert(pivot < r.length || r.length == 0 && pivot == 0, "pivot must be"
~ " less than the length of r or r must be empty and pivot zero");
if (r.length <= 1) return 0;
import std.algorithm.mutation : swapAt, move;
alias lt = binaryFun!less;
@ -646,9 +647,9 @@ if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && hasAssig
// this used to import std.algorithm.all, but we want to save
// imports when unittests are enabled if possible.
foreach (x; r[0 .. lo])
assert(!lt(p, x));
assert(!lt(p, x), "p must not be less than x");
foreach (x; r[hi+1 .. r.length])
assert(!lt(x, p));
assert(!lt(x, p), "x must not be less than p");
}
do ++lo; while (lt(r[lo], p));
r[hi] = r[lo];
@ -659,17 +660,17 @@ if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && hasAssig
// Vacancy is not in r[hi]
}
// Fixup
assert(lo - hi <= 2);
assert(!lt(p, r[hi]));
assert(lo - hi <= 2, "Following compare not possible");
assert(!lt(p, r[hi]), "r[hi] must not be less than p");
if (lo == hi + 2)
{
assert(!lt(r[hi + 1], p));
assert(!lt(r[hi + 1], p), "r[hi + 1] must not be less than p");
r[lo] = r[hi + 1];
--lo;
}
r[lo] = save;
if (lt(p, save)) --lo;
assert(!lt(p, r[lo]));
assert(!lt(p, r[lo]), "r[lo] must not be less than p");
}
else
{
@ -682,14 +683,14 @@ if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && hasAssig
if (!lt(r[lo], r[0])) break;
}
// found the left bound: r[lo] >= r[0]
assert(lo <= hi);
assert(lo <= hi, "lo must be less or equal than hi");
for (;; --hi)
{
if (lo >= hi) break loop;
if (!lt(r[0], r[hi])) break;
}
// found the right bound: r[hi] <= r[0], swap & make progress
assert(!lt(r[lo], r[hi]));
assert(!lt(r[lo], r[hi]), "r[lo] must not be less than r[hi]");
r.swapAt(lo, hi);
}
--lo;
@ -847,15 +848,15 @@ if (ss == SwapStrategy.unstable && isRandomAccessRange!Range
for (;; ++j)
{
if (j == k) break bigloop;
assert(j < r.length);
assert(j < r.length, "j must be less than r.length");
if (lessFun(r[j], pivot)) continue;
if (lessFun(pivot, r[j])) break;
r.swapAt(i++, j);
}
assert(j < k);
assert(j < k, "j must be less than k");
for (;;)
{
assert(k > 0);
assert(k > 0, "k must be positive");
if (!lessFun(pivot, r[--k]))
{
if (lessFun(r[k], pivot)) break;
@ -1125,7 +1126,7 @@ if (Rs.length >= 2 &&
foreach (i, _; Rs)
{
case i:
assert(!source[i].empty);
assert(!source[i].empty, "Can not get front of empty Merge");
return source[i].front;
}
}
@ -1188,7 +1189,7 @@ if (Rs.length >= 2 &&
foreach (i, _; Rs)
{
case i:
assert(!source[i].empty);
assert(!source[i].empty, "Can not get back of empty Merge");
return source[i].back;
}
}
@ -1682,7 +1683,7 @@ private void shortSort(alias less, Range)(Range r)
break;
}
assert(r.length >= 6);
assert(r.length >= 6, "r must have more than 5 elements");
/* The last 5 elements of the range are sorted. Proceed with expanding the
sorted portion downward. */
immutable maxJ = r.length - 2;
@ -1740,7 +1741,7 @@ Sorts the first 5 elements exactly of range r.
*/
private void sort5(alias lt, Range)(Range r)
{
assert(r.length >= 5);
assert(r.length >= 5, "r must have more than 4 elements");
import std.algorithm.mutation : swapAt;
@ -1754,7 +1755,8 @@ private void sort5(alias lt, Range)(Range r)
r.swapAt(0, 2);
r.swapAt(1, 3);
}
assert(!lt(r[1], r[0]) && !lt(r[3], r[1]) && !lt(r[3], r[2]));
assert(!lt(r[1], r[0]) && !lt(r[3], r[1]) && !lt(r[3], r[2]), "unexpected"
~ " order");
// 3. Insert 4 into [0, 1, 3]
if (lt(r[4], r[1]))
@ -1770,10 +1772,11 @@ private void sort5(alias lt, Range)(Range r)
{
r.swapAt(3, 4);
}
assert(!lt(r[1], r[0]) && !lt(r[3], r[1]) && !lt(r[4], r[3]));
assert(!lt(r[1], r[0]) && !lt(r[3], r[1]) && !lt(r[4], r[3]), "unexpected"
~ " order");
// 4. Insert 2 into [0, 1, 3, 4] (note: we already know the last is greater)
assert(!lt(r[4], r[2]));
assert(!lt(r[4], r[2]), "unexpected order");
if (lt(r[2], r[1]))
{
r.swapAt(1, 2);
@ -2066,10 +2069,12 @@ private void quickSortImpl(alias less, Range)(Range r, size_t depth)
{
import std.algorithm.comparison : min, max;
import std.algorithm.mutation : swap, swapAt;
import std.conv : to;
alias Elem = ElementType!(Range);
enum size_t shortSortGetsBetter = max(32, 1024 / Elem.sizeof);
static assert(shortSortGetsBetter >= 1);
static assert(shortSortGetsBetter >= 1, Elem.stringof ~ " "
~ to!string(Elem.sizeof));
// partition
while (r.length > shortSortGetsBetter)
@ -2124,9 +2129,11 @@ package(std) template HeapOps(alias less, Range)
{
import std.algorithm.mutation : swapAt;
static assert(isRandomAccessRange!Range);
static assert(hasLength!Range);
static assert(hasSwappableElements!Range || hasAssignableElements!Range);
static assert(isRandomAccessRange!Range, Range.stringof ~ " must be a"
~ " RandomAccessRange");
static assert(hasLength!Range, Range.stringof ~ " must have length");
static assert(hasSwappableElements!Range || hasAssignableElements!Range,
Range.stringof ~ " must have swappable of assignable Elements");
alias lessFun = binaryFun!less;
@ -2153,7 +2160,7 @@ package(std) template HeapOps(alias less, Range)
{
siftDown(r, i, n);
}
assert(isHeap(r));
assert(isHeap(r), "r is not a heap");
}
bool isHeap()(Range r)
@ -2242,10 +2249,12 @@ private template TimSortImpl(alias pred, R)
import core.bitop : bsr;
import std.array : uninitializedArray;
static assert(isRandomAccessRange!R);
static assert(hasLength!R);
static assert(hasSlicing!R);
static assert(hasAssignableElements!R);
static assert(isRandomAccessRange!R, R.stringof ~ " must be a"
~ " RandomAccessRange");
static assert(hasLength!R, R.stringof ~ " must have a length");
static assert(hasSlicing!R, R.stringof ~ " must support slicing");
static assert(hasAssignableElements!R, R.stringof ~ " must support"
~ " assigning elements");
alias T = ElementType!R;
@ -2265,6 +2274,7 @@ private template TimSortImpl(alias pred, R)
void sort()(R range, T[] temp)
{
import std.algorithm.comparison : min;
import std.format : format;
// Do insertion sort on small range
if (range.length <= minimalMerge)
@ -2324,13 +2334,25 @@ private template TimSortImpl(alias pred, R)
// Assert that the code above established the invariant correctly
version (assert)
{
if (stackLen == 2) assert(stack[0].length > stack[1].length);
if (stackLen == 2)
{
assert(stack[0].length > stack[1].length, format!
"stack[0].length %s > stack[1].length %s"(
stack[0].length, stack[1].length
));
}
else if (stackLen > 2)
{
foreach (k; 2 .. stackLen)
{
assert(stack[k - 2].length > stack[k - 1].length + stack[k].length);
assert(stack[k - 1].length > stack[k].length);
assert(stack[k - 2].length > stack[k - 1].length + stack[k].length,
format!"stack[k - 2].length %s > stack[k - 1].length %s + stack[k].length %s"(
stack[k - 2].length, stack[k - 1].length, stack[k].length
));
assert(stack[k - 1].length > stack[k].length,
format!"stack[k - 1].length %s > stack[k].length %s"(
stack[k - 1].length, stack[k].length
));
}
}
}
@ -2362,7 +2384,8 @@ private template TimSortImpl(alias pred, R)
size_t firstRun()(R range)
out(ret)
{
assert(ret <= range.length);
assert(ret <= range.length, "ret must be less or equal than"
~ " range.length");
}
do
{
@ -2387,7 +2410,7 @@ private template TimSortImpl(alias pred, R)
void binaryInsertionSort()(R range, size_t sortedLen = 1)
out
{
if (!__ctfe) assert(isSorted!pred(range));
if (!__ctfe) assert(isSorted!pred(range), "range must be sorted");
}
do
{
@ -2419,8 +2442,10 @@ private template TimSortImpl(alias pred, R)
void mergeAt()(R range, Slice[] stack, immutable size_t at, ref size_t minGallop, ref T[] temp)
in
{
assert(stack.length >= 2);
assert(stack.length - at == 2 || stack.length - at == 3);
import std.format : format;
assert(stack.length >= 2, "stack be be greater than 1");
assert(stack.length - at == 2 || stack.length - at == 3,
format!"stack.length - at %s must be 2 or 3"(stack.length - at));
}
do
{
@ -2443,13 +2468,16 @@ private template TimSortImpl(alias pred, R)
{
if (!__ctfe)
{
assert(isSorted!pred(range[0 .. mid]));
assert(isSorted!pred(range[mid .. range.length]));
assert(isSorted!pred(range[0 .. mid]), "range[0 .. mid] must be"
~ " sorted");
assert(isSorted!pred(range[mid .. range.length]), "range[mid .."
~ " range.length] must be sorted");
}
}
do
{
assert(mid < range.length);
assert(mid < range.length, "mid must be less than the length of the"
~ " range");
// Reduce range of elements
immutable firstElement = gallopForwardUpper(range[0 .. mid], range[mid]);
@ -2476,7 +2504,7 @@ private template TimSortImpl(alias pred, R)
T[] ensureCapacity()(size_t minCapacity, T[] temp)
out(ret)
{
assert(ret.length >= minCapacity);
assert(ret.length >= minCapacity, "ensuring the capacity failed");
}
do
{
@ -2497,14 +2525,15 @@ private template TimSortImpl(alias pred, R)
size_t mergeLo()(R range, immutable size_t mid, size_t minGallop, T[] temp)
out
{
if (!__ctfe) assert(isSorted!pred(range));
if (!__ctfe) assert(isSorted!pred(range), "the range must be sorted");
}
do
{
import std.algorithm.mutation : copy;
assert(mid <= range.length);
assert(temp.length >= mid);
assert(mid <= range.length, "mid must be less than the length of the"
~ " range");
assert(temp.length >= mid, "temp.length must be greater or equal to mid");
// Copy run into temporary memory
temp = temp[0 .. mid];
@ -2580,14 +2609,17 @@ private template TimSortImpl(alias pred, R)
size_t mergeHi()(R range, immutable size_t mid, size_t minGallop, T[] temp)
out
{
if (!__ctfe) assert(isSorted!pred(range));
if (!__ctfe) assert(isSorted!pred(range), "the range must be sorted");
}
do
{
import std.algorithm.mutation : copy;
import std.format : format;
assert(mid <= range.length);
assert(temp.length >= range.length - mid);
assert(mid <= range.length, "mid must be less or equal to range.length");
assert(temp.length >= range.length - mid, format!
"temp.length %s >= range.length %s - mid %s"(temp.length,
range.length, mid));
// Copy run into temporary memory
temp = temp[0 .. range.length - mid];
@ -2686,7 +2718,8 @@ private template TimSortImpl(alias pred, R)
size_t gallopSearch(R)(R range, T value)
out(ret)
{
assert(ret <= range.length);
assert(ret <= range.length, "ret must be less or equal to"
~ " range.length");
}
do
{
@ -2807,6 +2840,7 @@ private template TimSortImpl(alias pred, R)
// Tests the Timsort function for correctness and stability
static bool testSort(uint seed)
{
import std.format : format;
auto arr = genSampleData(seed);
// Now sort the array!
@ -2818,12 +2852,15 @@ private template TimSortImpl(alias pred, R)
sort!(comp, SwapStrategy.stable)(arr);
// Test that the array was sorted correctly
assert(isSorted!comp(arr));
assert(isSorted!comp(arr), "arr must be sorted");
// Test that the array was sorted stably
foreach (i; 0 .. arr.length - 1)
{
if (arr[i].value == arr[i + 1].value) assert(arr[i].index < arr[i + 1].index);
if (arr[i].value == arr[i + 1].value)
assert(arr[i].index < arr[i + 1].index, format!
"arr[i %s].index %s < arr[i + 1].index %s"(
i, arr[i].index, arr[i + 1].index));
}
return true;
@ -2833,7 +2870,7 @@ private template TimSortImpl(alias pred, R)
testSort(seed);
enum result = testSort(seed);
assert(result == true);
assert(result == true, "invalid result");
}
@safe unittest
@ -2930,7 +2967,7 @@ if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R &&
import core.stdc.stdlib : malloc;
bool overflow;
const nbytes = mulu(len, T.sizeof, overflow);
if (overflow) assert(0);
if (overflow) assert(false, "multiplication overflowed");
return (cast(T*) malloc(nbytes))[0 .. len];
}
auto xform1 = trustedMalloc(r.length);
@ -3169,7 +3206,8 @@ if (isRandomAccessRange!(Range) && hasLength!Range &&
cast(void) binaryFun!less(r[0], r[r.length - 1]);
import std.algorithm.mutation : swapAt;
r.swapAt(size_t(0), size_t(0));
static assert(is(typeof(r.length) == size_t));
static assert(is(typeof(r.length) == size_t),
typeof(r.length).stringof ~ " must be of type size_t");
pivotPartition!less(r, 0);
}
bool useSampling = true;
@ -3281,7 +3319,7 @@ void topNImpl(alias less, R)(R r, size_t n, ref bool useSampling)
}
}
assert(pivot != size_t.max);
assert(pivot != size_t.max, "pivot must be not equal to size_t.max");
// See how the pivot fares
if (pivot == n)
{
@ -3301,7 +3339,9 @@ void topNImpl(alias less, R)(R r, size_t n, ref bool useSampling)
private size_t topNPartition(alias lp, R)(R r, size_t n, bool useSampling)
{
assert(r.length >= 9 && n < r.length);
import std.format : format;
assert(r.length >= 9 && n < r.length, "length must be longer than 9"
~ " and n must be less than r.length");
immutable ninth = r.length / 9;
auto pivot = ninth / 2;
// Position subrange r[lo .. hi] to have length equal to ninth and its upper
@ -3310,9 +3350,11 @@ private size_t topNPartition(alias lp, R)(R r, size_t n, bool useSampling)
// the median in already sorted ranges.
immutable lo = r.length / 2 - pivot, hi = lo + ninth;
// We have either one straggler on the left, one on the right, or none.
assert(lo - (r.length - hi) <= 1 || (r.length - hi) - lo <= 1);
assert(lo >= ninth * 4);
assert(r.length - hi >= ninth * 4);
assert(lo - (r.length - hi) <= 1 || (r.length - hi) - lo <= 1,
format!"straggler check failed lo %s, r.length %s, hi %s"(lo, r.length, hi));
assert(lo >= ninth * 4, format!"lo %s >= ninth * 4 %s"(lo, ninth * 4));
assert(r.length - hi >= ninth * 4,
format!"r.length %s - hi %s >= ninth * 4 %s"(r.length, hi, ninth * 4));
// Partition in groups of 3, and the mid tertile again in groups of 3
if (!useSampling)
@ -3328,12 +3370,15 @@ private size_t topNPartition(alias lp, R)(R r, size_t n, bool useSampling)
private void p3(alias less, Range)(Range r, size_t lo, immutable size_t hi)
{
assert(lo <= hi && hi < r.length);
import std.format : format;
assert(lo <= hi && hi < r.length,
format!"lo %s <= hi %s && hi < r.length %s"(lo, hi, r.length));
immutable ln = hi - lo;
for (; lo < hi; ++lo)
{
assert(lo >= ln);
assert(lo + ln < r.length);
assert(lo >= ln, format!"lo %s >= ln %s"(lo, ln));
assert(lo + ln < r.length, format!"lo %s + ln %s < r.length %s"(
lo, ln, r.length));
medianOf!less(r, lo - ln, lo, lo + ln);
}
}
@ -3341,12 +3386,15 @@ private void p3(alias less, Range)(Range r, size_t lo, immutable size_t hi)
private void p4(alias less, Flag!"leanRight" f, Range)
(Range r, size_t lo, immutable size_t hi)
{
assert(lo <= hi && hi < r.length);
import std.format : format;
assert(lo <= hi && hi < r.length, format!"lo %s <= hi %s && hi < r.length %s"(
lo, hi, r.length));
immutable ln = hi - lo, _2ln = ln * 2;
for (; lo < hi; ++lo)
{
assert(lo >= ln);
assert(lo + ln < r.length);
assert(lo >= ln, format!"lo %s >= ln %s"(lo, ln));
assert(lo + ln < r.length, format!"lo %s + ln %s < r.length %s"(
lo, ln, r.length));
static if (f == Yes.leanRight)
medianOf!(less, f)(r, lo - _2ln, lo - ln, lo, lo + ln);
else
@ -3357,8 +3405,8 @@ private void p4(alias less, Flag!"leanRight" f, Range)
private size_t topNPartitionOffMedian(alias lp, Flag!"leanRight" f, R)
(R r, size_t n, bool useSampling)
{
assert(r.length >= 12);
assert(n < r.length);
assert(r.length >= 12, "The length of r must be greater than 11");
assert(n < r.length, "n must be less than the length of r");
immutable _4 = r.length / 4;
static if (f == Yes.leanRight)
immutable leftLimit = 2 * _4;
@ -3395,17 +3443,21 @@ size_t expandPartition(alias lp, R)(R r, size_t lo, size_t pivot, size_t hi)
in
{
import std.algorithm.searching : all;
assert(lo <= pivot);
assert(pivot < hi);
assert(hi <= r.length);
assert(r[lo .. pivot + 1].all!(x => !lp(r[pivot], x)));
assert(r[pivot + 1 .. hi].all!(x => !lp(x, r[pivot])));
assert(lo <= pivot, "lo must be less than or equal pivot");
assert(pivot < hi, "pivot must be less than hi");
assert(hi <= r.length, "hi must be less than or equal to the length of r");
assert(r[lo .. pivot + 1].all!(x => !lp(r[pivot], x)),
"r[lo .. pivot + 1] failed less than test");
assert(r[pivot + 1 .. hi].all!(x => !lp(x, r[pivot])),
"r[pivot + 1 .. hi] failed less than test");
}
out
{
import std.algorithm.searching : all;
assert(r[0 .. pivot + 1].all!(x => !lp(r[pivot], x)));
assert(r[pivot + 1 .. r.length].all!(x => !lp(x, r[pivot])));
assert(r[0 .. pivot + 1].all!(x => !lp(r[pivot], x)),
"r[0 .. pivot + 1] failed less than test");
assert(r[pivot + 1 .. r.length].all!(x => !lp(x, r[pivot])),
"r[pivot + 1 .. r.length] failed less than test");
}
do
{
@ -3430,10 +3482,14 @@ do
r.swapAt(left, rite);
}
assert(r[lo .. pivot + 1].all!(x => !lp(r[pivot], x)));
assert(r[pivot + 1 .. hi + 1].all!(x => !lp(x, r[pivot])));
assert(r[0 .. left].all!(x => !lp(r[pivot], x)));
assert(r[rite + 1 .. r.length].all!(x => !lp(x, r[pivot])));
assert(r[lo .. pivot + 1].all!(x => !lp(r[pivot], x)),
"r[lo .. pivot + 1] failed less than test");
assert(r[pivot + 1 .. hi + 1].all!(x => !lp(x, r[pivot])),
"r[pivot + 1 .. hi + 1] failed less than test");
assert(r[0 .. left].all!(x => !lp(r[pivot], x)),
"r[0 .. left] failed less than test");
assert(r[rite + 1 .. r.length].all!(x => !lp(x, r[pivot])),
"r[rite + 1 .. r.length] failed less than test");
immutable oldPivot = pivot;
@ -3445,7 +3501,7 @@ do
if (left == lo) goto done;
if (!lp(r[oldPivot], r[left])) continue;
--pivot;
assert(!lp(r[oldPivot], r[pivot]));
assert(!lp(r[oldPivot], r[pivot]), "less check failed");
r.swapAt(left, pivot);
}
// Second loop: make left and pivot meet
@ -3472,7 +3528,7 @@ do
if (rite == hi) goto done;
if (!lp(r[rite], r[oldPivot])) continue;
++pivot;
assert(!lp(r[pivot], r[oldPivot]));
assert(!lp(r[pivot], r[oldPivot]), "less check failed");
r.swapAt(rite, pivot);
}
// Second loop: make left and pivot meet
@ -3932,37 +3988,45 @@ if (isRandomAccessRange!Range && hasLength!Range &&
Indexes.length >= 2 && Indexes.length <= 5 &&
allSatisfy!(isUnsigned, Indexes))
{
assert(r.length >= Indexes.length);
assert(r.length >= Indexes.length, "r.length must be greater equal to"
~ " Indexes.length");
import std.functional : binaryFun;
alias lt = binaryFun!less;
enum k = Indexes.length;
import std.algorithm.mutation : swapAt;
import std.format : format;
alias a = i[0];
static assert(is(typeof(a) == size_t));
static assert(is(typeof(a) == size_t), typeof(a).stringof ~ " must be"
~ " of type size_t");
static if (k >= 2)
{
alias b = i[1];
static assert(is(typeof(b) == size_t));
assert(a != b);
static assert(is(typeof(b) == size_t), typeof(b).stringof ~ " must be"
~ " of type size_t");
assert(a != b, "a != b ");
}
static if (k >= 3)
{
alias c = i[2];
static assert(is(typeof(c) == size_t));
assert(a != c && b != c);
static assert(is(typeof(c) == size_t), typeof(c).stringof ~ " must be"
~ " of type size_t");
assert(a != c && b != c, "a != c && b != c");
}
static if (k >= 4)
{
alias d = i[3];
static assert(is(typeof(d) == size_t));
assert(a != d && b != d && c != d);
static assert(is(typeof(d) == size_t), typeof(d).stringof ~ " must be"
~ " of type size_t");
assert(a != d && b != d && c != d, "a != d && b != d && c != d failed");
}
static if (k >= 5)
{
alias e = i[4];
static assert(is(typeof(e) == size_t));
assert(a != e && b != e && c != e && d != e);
static assert(is(typeof(e) == size_t), typeof(e).stringof ~ " must be"
~ " of type size_t");
assert(a != e && b != e && c != e && d != e,
"a != e && b != e && c != e && d != e failed");
}
static if (k == 2)
@ -3995,8 +4059,8 @@ if (isRandomAccessRange!Range && hasLength!Range &&
if (lt(r[c], r[b])) r.swapAt(b, c);
}
}
assert(!lt(r[b], r[a]));
assert(!lt(r[c], r[b]));
assert(!lt(r[b], r[a]), "less than check failed");
assert(!lt(r[c], r[b]), "less than check failed");
}
else static if (k == 4)
{
@ -4020,10 +4084,10 @@ if (isRandomAccessRange!Range && hasLength!Range &&
// Credit: Teppo Niinimäki
version (unittest) scope(success)
{
assert(!lt(r[c], r[a]));
assert(!lt(r[c], r[b]));
assert(!lt(r[d], r[c]));
assert(!lt(r[e], r[c]));
assert(!lt(r[c], r[a]), "less than check failed");
assert(!lt(r[c], r[b]), "less than check failed");
assert(!lt(r[d], r[c]), "less than check failed");
assert(!lt(r[e], r[c]), "less than check failed");
}
if (lt(r[c], r[a])) r.swapAt(a, c);
@ -4147,7 +4211,7 @@ if (isBidirectionalRange!BidirectionalRange &&
auto j = find!((a) => binaryFun!less(i.front, a))(
takeExactly(retro(range), n));
assert(!j.empty); // shouldn't happen since i.front < last.front
assert(!j.empty, "j must not be empty"); // shouldn't happen since i.front < last.front
swap(i.front, j.front);
reverse(takeExactly(retro(range), n));
@ -4404,7 +4468,7 @@ if (isBidirectionalRange!BidirectionalRange &&
takeExactly(retro(range), n));
// shouldn't happen since i.front < last.front
assert(!j.empty);
assert(!j.empty, "j must not be empty");
swap(i.front, j.front);
oddParity = !oddParity;