C++: Fix range analysis rounding for negative zero

This commit is contained in:
Jonas Jensen
2018-10-26 12:02:00 +02:00
parent cbe16e56d7
commit a3505e008b
3 changed files with 17 additions and 6 deletions

View File

@@ -293,13 +293,24 @@ predicate analyzableDef(RangeSsaDefinition def, LocalScopeVariable v) {
assignmentDef(def, v, _) or defDependsOnDef(def, v, _, _)
}
/**
* Computes a normal form of `x` where -0.0 has changed to +0.0. This can be
* needed on the lesser side of a floating-point comparison or on both sides of
* a floating point equality because QL does not follow IEEE in floating-point
* comparisons but instead defines -0.0 to be less than and distinct from 0.0.
*/
bindingset[x]
private float normalizeFloatUp(float x) {
result = x + 0.0
}
/**
* Computes `x + y`, rounded towards +Inf. This is the general case where both
* `x` and `y` may be large numbers.
*/
bindingset[x, y]
private float addRoundingUp(float x, float y) {
if (x + y) - x < y or (x + y) - y < x
if normalizeFloatUp((x + y) - x) < y or normalizeFloatUp((x + y) - y) < x
then result = (x + y).nextUp()
else result = (x + y)
}
@@ -310,7 +321,7 @@ private float addRoundingUp(float x, float y) {
*/
bindingset[x, y]
private float addRoundingDown(float x, float y) {
if (x + y) - x > y or (x + y) - y > x
if (x + y) - x > normalizeFloatUp(y) or (x + y) - y > normalizeFloatUp(x)
then result = (x + y).nextDown()
else result = (x + y)
}

View File

@@ -141,10 +141,10 @@
| test.c:186:18:186:18 | a | -7.0 |
| test.c:187:14:187:14 | a | -7.0 |
| test.c:188:14:188:14 | a | -7.0 |
| test.c:189:5:189:9 | total | -52.00000000000001 |
| test.c:189:5:189:9 | total | -52.0 |
| test.c:189:14:189:14 | b | -7.0 |
| test.c:189:16:189:16 | c | 2.0 |
| test.c:192:10:192:14 | total | -57.00000000000001 |
| test.c:192:10:192:14 | total | -57.0 |
| test.c:200:12:200:12 | a | -2.147483648E9 |
| test.c:200:17:200:17 | a | 3.0 |
| test.c:200:33:200:33 | b | -2.147483648E9 |

View File

@@ -186,10 +186,10 @@ int test_unary(int a) {
if (-7 <= a && a <= -2) {
int b = +a;
int c = -a;
total += b+c; // BUG: lower bound should be exact, not approximate
total += b+c;
}
return total; // BUG: lower bound should be exact, not approximate
return total;
}