mgorny created this revision.
Herald added a subscriber: dberris.
Use approximate comparison between the result of __divsc3()
and the canonical value calculated, to allow the possible difference of
1 representable value resulting from optimization.
For example, the value of (0.01+j0.01) / (-0.50-j2.00))
computed the canonical way without specific machine flags is:
z = -0x1.3bce70p-21 + j0x1.7af7bcp-22
However, if -march=i386 -mfpmath=387 is used, it becomes:
z = -0x1.3bce72p-21 + j0x1.7af7bcp-22
While this difference is insignificant, it may cause the exact
comparison used in tests to fail. Allowing the difference of one
representable value seems to be a reasonable compromise.
Repository:
rL LLVM
https://reviews.llvm.org/D28862
Files:
test/builtins/Unit/divsc3_test.c
Index: test/builtins/Unit/divsc3_test.c
===
--- test/builtins/Unit/divsc3_test.c
+++ test/builtins/Unit/divsc3_test.c
@@ -14,6 +14,7 @@
#include "int_lib.h"
#include
#include
+#include
#include
// Returns: the quotient of (a + ib) / (c + id)
@@ -47,6 +48,25 @@
return non_zero;
}
+// check for equality assuming that both real and imaginary parts
+// can differ by exactly 1 representable value, in order to handle
+// different levels of accuracy on 32-bit x86
+static bool approx_equal(float _Complex a, float _Complex b) {
+if (a != b) {
+float ra = __real__ a;
+float ia = __imag__ a;
+float rb = __real__ b;
+float ib = __imag__ b;
+
+if (ra != rb && nextafterf(ra, rb) != rb)
+return false;
+if (ia != ib && nextafterf(ia, ib) != ib)
+return false;
+}
+
+return true;
+}
+
int test__divsc3(float a, float b, float c, float d)
{
float _Complex r = __divsc3(a, b, c, d);
@@ -100,7 +120,7 @@
{
float _Complex z = (a * c + b * d) / (c * c + d * d)
+ (b * c - a * d) / (c * c + d * d) * _Complex_I;
-if (r != z)
+if (!approx_equal(r, z))
return 1;
}
break;
Index: test/builtins/Unit/divsc3_test.c
===
--- test/builtins/Unit/divsc3_test.c
+++ test/builtins/Unit/divsc3_test.c
@@ -14,6 +14,7 @@
#include "int_lib.h"
#include
#include
+#include
#include
// Returns: the quotient of (a + ib) / (c + id)
@@ -47,6 +48,25 @@
return non_zero;
}
+// check for equality assuming that both real and imaginary parts
+// can differ by exactly 1 representable value, in order to handle
+// different levels of accuracy on 32-bit x86
+static bool approx_equal(float _Complex a, float _Complex b) {
+if (a != b) {
+float ra = __real__ a;
+float ia = __imag__ a;
+float rb = __real__ b;
+float ib = __imag__ b;
+
+if (ra != rb && nextafterf(ra, rb) != rb)
+return false;
+if (ia != ib && nextafterf(ia, ib) != ib)
+return false;
+}
+
+return true;
+}
+
int test__divsc3(float a, float b, float c, float d)
{
float _Complex r = __divsc3(a, b, c, d);
@@ -100,7 +120,7 @@
{
float _Complex z = (a * c + b * d) / (c * c + d * d)
+ (b * c - a * d) / (c * c + d * d) * _Complex_I;
-if (r != z)
+if (!approx_equal(r, z))
return 1;
}
break;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits