Skip to content
Closed
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
129 changes: 65 additions & 64 deletions std/algorithm/comparison.d
Original file line number Diff line number Diff line change
Expand Up @@ -604,84 +604,85 @@ Returns:

*/
int cmp(alias pred = "a < b", R1, R2)(R1 r1, R2 r2)
if (isInputRange!R1 && isInputRange!R2 && !(isSomeString!R1 && isSomeString!R2))
if (isInputRange!R1 && isInputRange!R2 || isSomeString!R1 && isSomeString!R2)
{
for (;; r1.popFront(), r2.popFront())
static if (isInputRange!R1 && isInputRange!R2)
{
if (r1.empty) return -cast(int)!r2.empty;
if (r2.empty) return !r1.empty;
auto a = r1.front, b = r2.front;
if (binaryFun!pred(a, b)) return -1;
if (binaryFun!pred(b, a)) return 1;
for (;; r1.popFront(), r2.popFront())
{
if (r1.empty) return -cast(int)!r2.empty;
if (r2.empty) return !r1.empty;
auto a = r1.front, b = r2.front;
if (binaryFun!pred(a, b)) return -1;
if (binaryFun!pred(b, a)) return 1;
}
}
}

/// ditto
int cmp(alias pred = "a < b", R1, R2)(R1 r1, R2 r2) if (isSomeString!R1 && isSomeString!R2)
{
import core.stdc.string : memcmp;
import std.utf : decode;

static if (is(typeof(pred) : string))
enum isLessThan = pred == "a < b";
else
enum isLessThan = false;

// For speed only
static int threeWay(size_t a, size_t b)
{
static if (size_t.sizeof == int.sizeof && isLessThan)
return a - b;
else
return binaryFun!pred(b, a) ? 1 : binaryFun!pred(a, b) ? -1 : 0;
}
// For speed only
// @@@BUG@@@ overloading should be allowed for nested functions
static int threeWayInt(int a, int b)
{
static if (isLessThan)
return a - b;
import core.stdc.string : memcmp;
import std.utf : decode;

static if (is(typeof(pred) : string))
enum isLessThan = pred == "a < b";
else
return binaryFun!pred(b, a) ? 1 : binaryFun!pred(a, b) ? -1 : 0;
}
enum isLessThan = false;

static if (typeof(r1[0]).sizeof == typeof(r2[0]).sizeof && isLessThan)
{
static if (typeof(r1[0]).sizeof == 1)
// For speed only
static int threeWay(size_t a, size_t b)
{
immutable len = min(r1.length, r2.length);
immutable result = __ctfe ?
{
foreach (i; 0 .. len)
{
if (r1[i] != r2[i])
return threeWayInt(r1[i], r2[i]);
}
return 0;
}()
: () @trusted { return memcmp(r1.ptr, r2.ptr, len); }();
if (result) return result;
static if (size_t.sizeof == int.sizeof && isLessThan)
return a - b;
else
return binaryFun!pred(b, a) ? 1 : binaryFun!pred(a, b) ? -1 : 0;
}
else
// For speed only
// @@@BUG@@@ overloading should be allowed for nested functions
static int threeWayInt(int a, int b)
{
auto p1 = r1.ptr, p2 = r2.ptr,
pEnd = p1 + min(r1.length, r2.length);
for (; p1 != pEnd; ++p1, ++p2)
static if (isLessThan)
return a - b;
else
return binaryFun!pred(b, a) ? 1 : binaryFun!pred(a, b) ? -1 : 0;
}

static if (typeof(r1[0]).sizeof == typeof(r2[0]).sizeof && isLessThan)
{
static if (typeof(r1[0]).sizeof == 1)
{
immutable len = min(r1.length, r2.length);
immutable result = __ctfe ?
{
foreach (i; 0 .. len)
{
if (r1[i] != r2[i])
return threeWayInt(r1[i], r2[i]);
}
return 0;
}()
: () @trusted { return memcmp(r1.ptr, r2.ptr, len); }();
if (result) return result;
}
else
{
if (*p1 != *p2) return threeWayInt(cast(int) *p1, cast(int) *p2);
auto p1 = r1.ptr, p2 = r2.ptr,
pEnd = p1 + min(r1.length, r2.length);
for (; p1 != pEnd; ++p1, ++p2)
{
if (*p1 != *p2) return threeWayInt(cast(int) *p1, cast(int) *p2);
}
}
return threeWay(r1.length, r2.length);
}
return threeWay(r1.length, r2.length);
}
else
{
for (size_t i1, i2;;)
else
{
if (i1 == r1.length) return threeWay(i2, r2.length);
if (i2 == r2.length) return threeWay(r1.length, i1);
immutable c1 = decode(r1, i1),
c2 = decode(r2, i2);
if (c1 != c2) return threeWayInt(cast(int) c1, cast(int) c2);
for (size_t i1, i2;;)
{
if (i1 == r1.length) return threeWay(i2, r2.length);
if (i2 == r2.length) return threeWay(r1.length, i1);
immutable c1 = decode(r1, i1),
c2 = decode(r2, i2);
if (c1 != c2) return threeWayInt(cast(int) c1, cast(int) c2);
}
}
}
}
Expand Down
92 changes: 46 additions & 46 deletions std/algorithm/iteration.d
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,7 @@ template each(alias pred = "a")
import std.meta : AliasSeq;
import std.traits : Parameters;

private:
alias BinaryArgs = AliasSeq!(pred, "i", "a");

enum isRangeUnaryIterable(R) =
Expand Down Expand Up @@ -886,67 +887,66 @@ template each(alias pred = "a")
(!isForwardRange!R || isDynamicArray!R) &&
(isForeachUnaryIterable!R || isForeachBinaryIterable!R);

public:
void each(Range)(Range r)
if (isRangeIterable!Range && !isForeachIterable!Range)
if (isRangeIterable!Range ||
isForeachIterable!Range ||
__traits(compiles, Parameters!(Parameters!(r.opApply))) ||
__traits(compiles, typeof(range.front).length))
{
debug(each) pragma(msg, "Using while for ", Range.stringof);
static if (isRangeUnaryIterable!Range)
static if (isRangeIterable!Range)
{
while (!r.empty)
debug(each) pragma(msg, "Using while for ", Range.stringof);
static if (isRangeUnaryIterable!Range)
{
cast(void)unaryFun!pred(r.front);
r.popFront();
while (!r.empty)
{
cast(void)unaryFun!pred(r.front);
r.popFront();
}
}
else // if (isRangeBinaryIterable!Range)
{
size_t i = 0;
while (!r.empty)
{
cast(void)binaryFun!BinaryArgs(i, r.front);
r.popFront();
i++;
}
}
}
else // if (isRangeBinaryIterable!Range)
else if (isForeachIterable!Iterable)
{
size_t i = 0;
while (!r.empty)
debug(each) pragma(msg, "Using foreach for ", Iterable.stringof);
static if (isForeachUnaryIterable!Iterable)
{
foreach (ref e; r)
cast(void)unaryFun!pred(e);
}
else // if (isForeachBinaryIterable!Iterable)
{
cast(void)binaryFun!BinaryArgs(i, r.front);
r.popFront();
i++;
foreach (ref i, ref e; r)
cast(void)binaryFun!BinaryArgs(i, e);
}
}
}

void each(Iterable)(auto ref Iterable r)
if (isForeachIterable!Iterable)
{
debug(each) pragma(msg, "Using foreach for ", Iterable.stringof);
static if (isForeachUnaryIterable!Iterable)
else static if (__traits(compiles, Parameters!(Parameters!(r.opApply))))
{
foreach (ref e; r)
cast(void)unaryFun!pred(e);
// opApply with >2 parameters. count the delegate args.
// only works if it is not templated (otherwise we cannot count the args)
auto dg(Parameters!(Parameters!(r.opApply)) params) {
pred(params);
return 0; // tells opApply to continue iteration
}
r.opApply(&dg);
}
else // if (isForeachBinaryIterable!Iterable)
else static if (__traits(compiles, typeof(range.front).length))
{
foreach (ref i, ref e; r)
cast(void)binaryFun!BinaryArgs(i, e);
// range interface with >2 parameters.
for (auto r = range; !r.empty; r.popFront())
pred(r.front.expand);
}
}

// opApply with >2 parameters. count the delegate args.
// only works if it is not templated (otherwise we cannot count the args)
void each(Iterable)(auto ref Iterable r)
if (!isRangeIterable!Iterable && !isForeachIterable!Iterable &&
__traits(compiles, Parameters!(Parameters!(r.opApply))))
{
auto dg(Parameters!(Parameters!(r.opApply)) params) {
pred(params);
return 0; // tells opApply to continue iteration
}
r.opApply(&dg);
}

// range interface with >2 parameters.
void each(Range)(Range range)
if (!isRangeIterable!Range && !isForeachIterable!Range &&
__traits(compiles, typeof(range.front).length))
{
for (auto r = range; !r.empty; r.popFront())
pred(r.front.expand);
}
}

///
Expand Down
Loading