Change float comparison operators to return false for NaN (bug 6107, r=ds).
--HG-- extra : rebase_source : a11c56fb23d6617545def3591ec6100dd143eb3e
This commit is contained in:
+25
-46
@@ -246,10 +246,25 @@ stock RoundFloat(Float:value)
|
||||
*/
|
||||
#pragma rational Float
|
||||
|
||||
native bool:__FLOAT_GT__(Float:a, Float:b);
|
||||
native bool:__FLOAT_GE__(Float:a, Float:b);
|
||||
native bool:__FLOAT_LT__(Float:a, Float:b);
|
||||
native bool:__FLOAT_LE__(Float:a, Float:b);
|
||||
native bool:__FLOAT_EQ__(Float:a, Float:b);
|
||||
native bool:__FLOAT_NE__(Float:a, Float:b);
|
||||
native bool:__FLOAT_NOT__(Float:a);
|
||||
|
||||
native Float:operator*(Float:oper1, Float:oper2) = FloatMul;
|
||||
native Float:operator/(Float:oper1, Float:oper2) = FloatDiv;
|
||||
native Float:operator+(Float:oper1, Float:oper2) = FloatAdd;
|
||||
native Float:operator-(Float:oper1, Float:oper2) = FloatSub;
|
||||
native bool:operator!(Float:oper1) = __FLOAT_NOT__;
|
||||
native bool:operator>(Float:oper1, Float:oper2) = __FLOAT_GT__;
|
||||
native bool:operator>=(Float:oper1, Float:oper2) = __FLOAT_GE__;
|
||||
native bool:operator<(Float:oper1, Float:oper2) = __FLOAT_LT__;
|
||||
native bool:operator<=(Float:oper1, Float:oper2) = __FLOAT_LE__;
|
||||
native bool:operator!=(Float:oper1, Float:oper2) = __FLOAT_NE__;
|
||||
native bool:operator==(Float:oper1, Float:oper2) = __FLOAT_EQ__;
|
||||
|
||||
stock Float:operator++(Float:oper)
|
||||
{
|
||||
@@ -296,90 +311,54 @@ stock Float:operator-(oper1, Float:oper2)
|
||||
return FloatSub(float(oper1), oper2);
|
||||
}
|
||||
|
||||
stock bool:operator==(Float:oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(oper1, oper2) == 0;
|
||||
}
|
||||
|
||||
stock bool:operator==(Float:oper1, oper2)
|
||||
{
|
||||
return FloatCompare(oper1, float(oper2)) == 0; /* "==" is commutative */
|
||||
}
|
||||
|
||||
stock bool:operator!=(Float:oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(oper1, oper2) != 0;
|
||||
return __FLOAT_EQ__(oper1, float(oper2));
|
||||
}
|
||||
|
||||
stock bool:operator!=(Float:oper1, oper2)
|
||||
{
|
||||
return FloatCompare(oper1, float(oper2)) != 0; /* "==" is commutative */
|
||||
}
|
||||
|
||||
stock bool:operator>(Float:oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(oper1, oper2) > 0;
|
||||
return __FLOAT_NE__(oper1, float(oper2));
|
||||
}
|
||||
|
||||
stock bool:operator>(Float:oper1, oper2)
|
||||
{
|
||||
return FloatCompare(oper1, float(oper2)) > 0;
|
||||
return __FLOAT_GT__(oper1, float(oper2));
|
||||
}
|
||||
|
||||
stock bool:operator>(oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(float(oper1), oper2) > 0;
|
||||
}
|
||||
|
||||
stock bool:operator>=(Float:oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(oper1, oper2) >= 0;
|
||||
return __FLOAT_GT__(float(oper1), oper2);
|
||||
}
|
||||
|
||||
stock bool:operator>=(Float:oper1, oper2)
|
||||
{
|
||||
return FloatCompare(oper1, float(oper2)) >= 0;
|
||||
return __FLOAT_GE__(oper1, float(oper2));
|
||||
}
|
||||
|
||||
stock bool:operator>=(oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(float(oper1), oper2) >= 0;
|
||||
}
|
||||
|
||||
stock bool:operator<(Float:oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(oper1, oper2) < 0;
|
||||
return __FLOAT_GE__(float(oper1), oper2);
|
||||
}
|
||||
|
||||
stock bool:operator<(Float:oper1, oper2)
|
||||
{
|
||||
return FloatCompare(oper1, float(oper2)) < 0;
|
||||
return __FLOAT_LT__(oper1, float(oper2));
|
||||
}
|
||||
|
||||
stock bool:operator<(oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(float(oper1), oper2) < 0;
|
||||
}
|
||||
|
||||
stock bool:operator<=(Float:oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(oper1, oper2) <= 0;
|
||||
return __FLOAT_LT__(float(oper1), oper2);
|
||||
}
|
||||
|
||||
stock bool:operator<=(Float:oper1, oper2)
|
||||
{
|
||||
return FloatCompare(oper1, float(oper2)) <= 0;
|
||||
return __FLOAT_LE__(oper1, float(oper2));
|
||||
}
|
||||
|
||||
stock bool:operator<=(oper1, Float:oper2)
|
||||
{
|
||||
return FloatCompare(float(oper1), oper2) <= 0;
|
||||
}
|
||||
|
||||
stock bool:operator!(Float:oper)
|
||||
{
|
||||
return (_:oper & ((-1)/2)) == 0; /* -1 = all bits to 1; /2 = remove most significant bit (sign)
|
||||
works on both 32bit and 64bit systems; no constant required */
|
||||
return __FLOAT_LE__(float(oper1), oper2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
public OnPluginStart()
|
||||
{
|
||||
RegServerCmd("test_floats", TestFloats)
|
||||
}
|
||||
|
||||
check(bool:got, bool:expect, const String:message[]="")
|
||||
{
|
||||
if (got != expect) {
|
||||
ThrowError("Check failed", message)
|
||||
}
|
||||
}
|
||||
|
||||
public Action:TestFloats(args)
|
||||
{
|
||||
new Float:x = 5.3
|
||||
new Float:y = 10.2
|
||||
|
||||
check(x < y, true)
|
||||
check(x <= y, true)
|
||||
check(x > y, false)
|
||||
check(x >= y, false)
|
||||
check(x == y, false)
|
||||
check(x != y, true)
|
||||
|
||||
x = 10.5
|
||||
y = 2.3
|
||||
|
||||
check(x < y, false)
|
||||
check(x <= y, false)
|
||||
check(x > y, true)
|
||||
check(x >= y, true)
|
||||
check(x == y, false)
|
||||
check(x != y, true)
|
||||
|
||||
x = 10.5
|
||||
y = x
|
||||
|
||||
check(x < y, false)
|
||||
check(x <= y, true)
|
||||
check(x > y, false)
|
||||
check(x >= y, true)
|
||||
check(x == y, true)
|
||||
check(x != y, false)
|
||||
|
||||
x = 0.0
|
||||
y = 0.0
|
||||
new Float:nan = x / y
|
||||
|
||||
check(x < nan, false)
|
||||
check(x <= nan, false)
|
||||
check(x > nan, false)
|
||||
check(x >= nan, false)
|
||||
check(x == nan, false)
|
||||
check(x != nan, true)
|
||||
check(nan < y, false)
|
||||
check(nan <= y, false)
|
||||
check(nan > y, false)
|
||||
check(nan >= y, false)
|
||||
check(nan == y, false)
|
||||
check(nan != y, true)
|
||||
check(nan == nan, false)
|
||||
check(nan != nan, true)
|
||||
|
||||
x = 10.5
|
||||
y = 0.0
|
||||
check(!x, false)
|
||||
check(!y, true)
|
||||
check(!nan, true)
|
||||
|
||||
y = -2.7
|
||||
check(-x == -10.5, true)
|
||||
check(-y == 2.7, true)
|
||||
|
||||
new String:buffer[32]
|
||||
Format(buffer, sizeof(buffer), "%f", nan)
|
||||
check(StrEqual(buffer, "NaN"), true)
|
||||
|
||||
PrintToServer("Tests finished.")
|
||||
|
||||
return Plugin_Stop
|
||||
}
|
||||
Reference in New Issue
Block a user