Added std.algorithm.safeLess for safe signed/unsigned comparison; rewrote min/max

This commit is contained in:
Lionello Lunesu 2014-05-23 08:15:11 -07:00
parent 1e9c457f14
commit 2815d548d3
2 changed files with 98 additions and 28 deletions

View file

@ -7117,17 +7117,9 @@ MinType!T min(T...)(T args)
algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof));
//Do the "min" proper with a and b //Do the "min" proper with a and b
static if (isIntegral!T0 && isIntegral!T1 && import std.functional : lessThan;
(mostNegative!T0 < 0) != (mostNegative!T1 < 0)) immutable chooseA = lessThan!(T0, T1)(a, b);
{ return cast(typeof(return)) (chooseA ? a : b);
static if (mostNegative!T0 < 0)
immutable chooseB = b < a && a > 0;
else
immutable chooseB = b < a || b < 0;
}
else
immutable chooseB = b < a;
return cast(typeof(return)) (chooseB ? b : a);
} }
unittest unittest
@ -7209,16 +7201,8 @@ MaxType!T max(T...)(T args)
algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof));
//Do the "max" proper with a and b //Do the "max" proper with a and b
static if (isIntegral!T0 && isIntegral!T1 && import std.functional : lessThan;
(mostNegative!T0 < 0) != (mostNegative!T1 < 0)) immutable chooseB = lessThan!(T0, T1)(a, b);
{
static if (mostNegative!T0 < 0)
immutable chooseB = b > a || a < 0;
else
immutable chooseB = b > a && b > 0;
}
else
immutable chooseB = b > a;
return cast(typeof(return)) (chooseB ? b : a); return cast(typeof(return)) (chooseB ? b : a);
} }

View file

@ -133,22 +133,108 @@ unittest
//assert(binaryFun!("return a + b;")(41, 1) == 42); //assert(binaryFun!("return a + b;")(41, 1) == 42);
} }
/* private template safeOp(string S)
if (is(typeof(mixin("0 "~S~" 0")) == bool))
{
private bool unsafeOp(ElementType1, ElementType2)(ElementType1 a, ElementType2 b) pure
if (isIntegral!ElementType1 && isIntegral!ElementType2)
{
alias T = CommonType!(ElementType1, ElementType2);
return mixin("cast(T)a "~S~" cast(T)b");
}
private bool safeOp(T0, T1)(T0 a, T1 b) pure
{
static if (isIntegral!T0 && isIntegral!T1 &&
(mostNegative!T0 < 0) != (mostNegative!T1 < 0))
{
static if (S == "<=" || S == "<")
{
static if (mostNegative!T0 < 0)
immutable result = a < 0 || unsafeOp(a, b);
else
immutable result = b >= 0 && unsafeOp(a, b);
}
else
{
static if (mostNegative!T0 < 0)
immutable result = a >= 0 && unsafeOp(a, b);
else
immutable result = b < 0 || unsafeOp(a, b);
}
}
else
{
static assert (is(typeof(mixin("a "~S~" b"))),
"Invalid arguments: Cannot compare types " ~ T0.stringof ~ " and " ~ T1.stringof ~ ".");
immutable result = mixin("a "~S~" b");
}
return result;
}
}
/**
Predicate that returns $(D_PARAM a < b). Predicate that returns $(D_PARAM a < b).
Correctly compares signed and unsigned integers, ie. -1 < 2U.
*/ */
//bool less(T)(T a, T b) { return a < b; } bool lessThan(T0, T1)(T0 a, T1 b)
//alias less = binaryFun!(q{a < b}); {
return safeOp!"<"(a, b);
}
/* unittest
{
assert(lessThan(2, 3));
assert(lessThan(2U, 3U));
assert(lessThan(2, 3.0));
assert(lessThan(-2, 3U));
assert(lessThan(2, 3U));
assert(!lessThan(3U, -2));
assert(!lessThan(3U, 2));
assert(!lessThan(0, 0));
assert(!lessThan(0U, 0));
assert(!lessThan(0, 0U));
}
/**
Predicate that returns $(D_PARAM a > b). Predicate that returns $(D_PARAM a > b).
Correctly compares signed and unsigned integers, ie. 2U > -1.
*/ */
//alias greater = binaryFun!(q{a > b}); bool greaterThan(T0, T1)(T0 a, T1 b)
{
return safeOp!">"(a, b);
}
/* unittest
{
assert(!greaterThan(2, 3));
assert(!greaterThan(2U, 3U));
assert(!greaterThan(2, 3.0));
assert(!greaterThan(-2, 3U));
assert(!greaterThan(2, 3U));
assert(greaterThan(3U, -2));
assert(greaterThan(3U, 2));
assert(!greaterThan(0, 0));
assert(!greaterThan(0U, 0));
assert(!greaterThan(0, 0U));
}
/**
Predicate that returns $(D_PARAM a == b). Predicate that returns $(D_PARAM a == b).
Correctly compares signed and unsigned integers, ie. !(-1 == ~0U).
*/ */
//alias equalTo = binaryFun!(q{a == b}); bool equalTo(T0, T1)(T0 a, T1 b)
{
return safeOp!"=="(a, b);
}
unittest
{
assert(equalTo(0U, 0));
assert(equalTo(0, 0U));
assert(!equalTo(-1, ~0U));
}
/** /**
N-ary predicate that reverses the order of arguments, e.g., given N-ary predicate that reverses the order of arguments, e.g., given
$(D pred(a, b, c)), returns $(D pred(c, b, a)). $(D pred(a, b, c)), returns $(D pred(c, b, a)).