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.000001+j0.000001) / (-0.500000-j2.000000)) 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 <math.h> #include <complex.h> +#include <stdbool.h> #include <stdio.h> // 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 <math.h> #include <complex.h> +#include <stdbool.h> #include <stdio.h> // 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