Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions std/algorithm/comparison.d
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ Params:
handlers that accept one argument. There can also be a choice that
accepts zero arguments. That choice will be invoked if the $(D
switchObject) is null.
switchObject = the object against which the tests are being made.

Returns:
The value of the selected choice.
Expand Down Expand Up @@ -500,7 +501,7 @@ Params:

Returns:
Returns $(D val), if it is between $(D lower) and $(D upper).
Otherwise returns the nearest of the two.
Otherwise returns the nearest of the two.

*/
auto clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
Expand Down Expand Up @@ -708,14 +709,14 @@ template equal(alias pred = "a == b")
/++
This function compares to ranges for equality. The ranges may have
different element types, as long as $(D pred(a, b)) evaluates to $(D bool)
for $(D a) in $(D r1) and $(D b) in $(D r2).
for $(D a) in $(D r1) and $(D b) in $(D r2).
Performs $(BIGOH min(r1.length, r2.length)) evaluations of $(D pred).

Params:
r1 = The first range to be compared.
r1 = The first range to be compared.
r2 = The second range to be compared.

Returns:
Returns:
$(D true) if and only if the two ranges compare equal element
for element, according to binary predicate $(D pred).

Expand Down Expand Up @@ -799,7 +800,7 @@ range of range (of range...) comparisons.
{
import std.algorithm.iteration : map;
import std.math : approxEqual;
import std.internal.test.dummyrange : ReferenceForwardRange,
import std.internal.test.dummyrange : ReferenceForwardRange,
ReferenceInputRange, ReferenceInfiniteForwardRange;

debug(std_algorithm) scope(success)
Expand Down
82 changes: 78 additions & 4 deletions std/algorithm/sorting.d
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,80 @@ bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
assert(isSorted(s)); // bidirectional
}

/**
Like $(D isSorted), returns $(D true) if the given $(D values) are ordered
according to the comparison operation $(D less). Unlike $(D isSorted), takes values
directly instead of structured in a range.

$(D ordered) allows repeated values, e.g. $(D ordered(1, 1, 2)) is $(D true). To verify
that the values are ordered strictly monotonically, use $(D strictlyOrdered);
$(D strictlyOrdered(1, 1, 2)) is $(D false).

With either function, the predicate must be a strict ordering just like with $(D isSorted). For
example, using $(D "a <= b") instead of $(D "a < b") is incorrect and will cause failed
assertions.

Params:
values = The tested value
less = The comparison predicate

Returns:
$(D true) if the values are ordered; $(D ordered) allows for duplicates,
$(D strictlyOrdered) does not.
*/

bool ordered(alias less = "a < b", T...)(T values)
if ((T.length == 2 && is(typeof(binaryFun!less(values[1], values[0])) : bool))
||
(T.length > 2 && is(typeof(ordered!less(values[0 .. 1 + $ / 2])))
&& is(typeof(ordered!less(values[$ / 2 .. $]))))
)
{
foreach (i, _; T[0 .. $ - 1])
{
if (binaryFun!less(values[i + 1], values[i]))
{
assert(!binaryFun!less(values[i], values[i + 1]),
__FUNCTION__ ~ ": incorrect non-strict predicate.");
return false;
}
}
return true;
}

/// ditto
bool strictlyOrdered(alias less = "a < b", T...)(T values)
if (is(typeof(ordered!less(values))))
{
foreach (i, _; T[0 .. $ - 1])
{
if (!binaryFun!less(values[i], values[i + 1]))
{
return false;
}
assert(!binaryFun!less(values[i + 1], values[i]),
__FUNCTION__ ~ ": incorrect non-strict predicate.");
}
return true;
}

///
unittest
{
assert(ordered(42, 42, 43));
assert(!strictlyOrdered(43, 42, 45));
assert(ordered(42, 42, 43));
assert(!strictlyOrdered(42, 42, 43));
assert(!ordered(43, 42, 45));
// Ordered lexicographically
assert(ordered("Jane", "Jim", "Joe"));
assert(strictlyOrdered("Jane", "Jim", "Joe"));
// Incidentally also ordered by length decreasing
assert(ordered!((a, b) => a.length > b.length)("Jane", "Jim", "Joe"));
// ... but not strictly so: "Jim" and "Joe" have the same length
assert(!strictlyOrdered!((a, b) => a.length > b.length)("Jane", "Jim", "Joe"));
}

// partition
/**
Partitions a range in two using $(D pred) as a
Expand Down Expand Up @@ -1229,19 +1303,19 @@ private template TimSortImpl(alias pred, R)
immutable run3 = stackLen - 2;
immutable run2 = stackLen - 3;
immutable run1 = stackLen - 4;
if ( (stackLen > 2 && stack[run2].length <= stack[run3].length + stack[run4].length) ||

if ( (stackLen > 2 && stack[run2].length <= stack[run3].length + stack[run4].length) ||
(stackLen > 3 && stack[run1].length <= stack[run3].length + stack[run2].length) )
{
immutable at = stack[run2].length < stack[run4].length ? run2 : run3;
mergeAt(range, stack[0 .. stackLen], at, minGallop, temp);
}
else if (stack[run3].length > stack[run4].length) break;
else mergeAt(range, stack[0 .. stackLen], run3, minGallop, temp);

stackLen -= 1;
}

// Assert that the code above established the invariant correctly
version (assert)
{
Expand Down