From 91e1b815363299b9946130fb9264e93190f84c72 Mon Sep 17 00:00:00 2001 From: Ian Henriksen Date: Mon, 13 Nov 2023 09:47:55 -0800 Subject: [PATCH] Fix #172 by using relative error when checking expected floating point results. If a compiler is optimizing overly aggressively it may make assumptions about commutativity/associativity of floating point numbers that don't actually hold perfectly in practice. That's a likely cause of the current test failure with icx. The result in the test is just slightly off from the expected value. While this could arguably be a bug upstream, it's generally a bad idea to use exact float equality for tests. Relative error is a more reliable measure. This change makes the float-related tests check relative error rather than actual equality. The thresholds are very conservative, but checking this way should insulate our test suite from failures resulting in small differences in floating point handling at the compiler and/or hardware level. --- test/basics/qthread_fp.c | 8 ++++++-- test/basics/qthread_fp_double.c | 25 +++++++++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/test/basics/qthread_fp.c b/test/basics/qthread_fp.c index 1bfa7ae8c..37f4d78a0 100755 --- a/test/basics/qthread_fp.c +++ b/test/basics/qthread_fp.c @@ -2,6 +2,7 @@ #include #endif +#include #include #include #include @@ -56,11 +57,14 @@ static void checkFloat() int main(void) { float ans = taylor_exponential_core(250, 9.0); - assert(ans == 8103.083984f); + float expected = 8103.083984f; + float rel_error = fabsf(ans - expected) / fabsf(expected); + float threshold = 1E-7f; + assert(rel_error < threshold); int status = qthread_initialize(); assert(status == QTHREAD_SUCCESS); checkFloat(); return EXIT_SUCCESS; -} \ No newline at end of file +} diff --git a/test/basics/qthread_fp_double.c b/test/basics/qthread_fp_double.c index d151e65d0..8426343cf 100755 --- a/test/basics/qthread_fp_double.c +++ b/test/basics/qthread_fp_double.c @@ -2,6 +2,7 @@ #include #endif +#include #include #include #include @@ -67,11 +68,19 @@ static aligned_t checkDoubleAsQthreads() ret = qthread_readFF(NULL, &teParts3.cond); assert(ret == QTHREAD_SUCCESS); - assert(teParts1.ans == 8103.0839275753824); + double threshold = 1E-15; - assert(teParts2.ans == 20.085536923187668); + double expected_1 = 8103.0839275753824; + double rel_error_1 = fabs(expected_1 - teParts1.ans) / fabs(expected_1); + assert(rel_error_1 < threshold); - assert(teParts3.ans == 59874.141715197809); + double expected_2 = 20.085536923187668; + double rel_error_2 = fabs(expected_2 - teParts2.ans) / fabs(expected_2); + assert(rel_error_2 < threshold); + + double expected_3 = 59874.141715197809; + double rel_error_3 = fabs(expected_3 - teParts3.ans) / fabs(expected_3); + assert(rel_error_3 < threshold); return 0; } @@ -88,13 +97,17 @@ static void checkDoubleAsQthread() ret = qthread_readFF(NULL, &teParts.cond); assert(ret == QTHREAD_SUCCESS); - assert(teParts.ans == 8103.0839275753824); + double expected = 8103.0839275753824; + double rel_error = fabs(expected - teParts.ans) / fabs(expected); + assert(rel_error < 1E-15); } static void checkDouble() { double ans = taylor_exponential_core(250, 9.0); - assert(ans == 8103.0839275753824); + double expected = 8103.0839275753824; + double rel_error = fabs(expected - ans) / fabs(expected); + assert(rel_error < 1E-15); } int main(void) @@ -107,4 +120,4 @@ int main(void) checkDoubleAsQthread(); checkDoubleAsQthreads(); return EXIT_SUCCESS; -} \ No newline at end of file +}