[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 --- Comment #9 from commit-h...@freebsd.org --- A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=888796ade2842486d3167067e8034254c38aadd3 commit 888796ade2842486d3167067e8034254c38aadd3 Author: Ed Maste AuthorDate: 2024-03-19 14:31:39 + Commit: Ed Maste CommitDate: 2024-06-08 15:55:36 + libm: fma: correct zero sign with small inputs PR: 277783 Reported by:Victor Stinner Submitted by: kargl MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D44433 lib/msun/src/s_fma.c | 4 +++- lib/msun/src/s_fmal.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 Malcolm Smith changed: What|Removed |Added CC||sm...@chaquo.com --- Comment #8 from Malcolm Smith --- > Python does not officially support Android yet, see: > https://peps.python.org/pep-0738/ I'm working on adding Android support to Python, and I've found that this issue exists on Android x86_64, but ARM64 is OK. -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 --- Comment #7 from Ed Maste --- Proposed patch for fma and fmal in https://reviews.freebsd.org/D44433 We can switch to BUILTIN_FMA in a later change -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 Kyle Evans changed: What|Removed |Added CC||kev...@freebsd.org Component|kern|bin -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 --- Comment #6 from Steve Kargl --- (In reply to Steve Kargl from comment #4) A similar issue is present in src/s_fmal.c. The patch in comment #4 can be adapted for fmal. -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 --- Comment #5 from Victor Stinner --- Ed: > Thank you for the report and C reproduction case. Do you know which other > implementations are being tested? (macOS, musl, bionic?) Python test_math checks fma() on Windows, Linux, macOS, WASI, FreeBSD, etc. The tests pass on all platforms but FreeBSD and WASI. Apparently, the WASI libc is based musl, but I failed to reproduce the issue using musl-gcc on Linux. bionic: Python does not officially support Android yet, see: https://peps.python.org/pep-0738/ -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 --- Comment #4 from Steve Kargl --- Ok, with the given input to fma, one arrives at line 271 return (xy.hi + vzs + ldexp(xy.lo, spread)); (gdb) p vzs $12 = -0.5 (gdb) p xy.hi $13 = 0.5 (gdb) p xy.lo $14 = -3.944304526105059e-31 (gdb) p spread $15 = -999 Turns out that ldexp(3.944304526105059e-31, -999) = -0x0p+0. So, you have 0.5 - 0.5 - 0. = 0. - 0. = +0 So, a pessimestic patch is Index: src/s_fma.c === --- src/s_fma.c (revision 2834) +++ src/s_fma.c (working copy) @@ -267,7 +267,9 @@ */ fesetround(oround); volatile double vzs = zs; /* XXX gcc CSE bug workaround */ - return (xy.hi + vzs + ldexp(xy.lo, spread)); + xs = ldexp(xy.lo, spread); + xy.hi += vzs; + return (xy.hi == 0 ? xs : xy.hi + xs); } if (oround != FE_TONEAREST) { -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 --- Comment #3 from Steve Kargl --- If one looks in src/s_fma.c, one sees #ifdef USE_BUILTIN_FMA double fma(double x, double y, double z) { return (__builtin_fma(x, y, z)); } #else If libm is built with -DUSE_BUILTIN_FMA, then one get -0. -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 --- Comment #2 from Steve Kargl --- So, I don't loose a reduced version of the code: #include #include int main(void) { volatile double x = 0x1p-500, y = 0x1p-550, z = 0x1p-1000; double a, b, c, r; a = x-y; b = x+y; c = -z; r = fma(a, b, c); /* * Should print -0 instead of +0. */ printf("fma(%+a, %+a, %+a) = %+g\n", a, b, c, r); return 0; } % cc -o z -O3 a.c -lm && ./z fma(+0x1.8p-501, +0x1.4p-500, -0x1p-1000) = +0 % cc -o z -O3 a.c -mfma -lm && ./z fma(+0x1.8p-501, +0x1.4p-500, -0x1p-1000) = -0 -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 Ed Maste changed: What|Removed |Added CC||ema...@freebsd.org, ||ka...@freebsd.org --- Comment #1 from Ed Maste --- Thank you for the report and C reproduction case. Do you know which other implementations are being tested? (macOS, musl, bionic?) Steve would you be able to take an initial look at this? -- You are receiving this mail because: You are the assignee for the bug.
[Bug 277783] libc fma() doesn't not return the correct zero sign
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277783 Bug ID: 277783 Summary: libc fma() doesn't not return the correct zero sign Product: Base System Version: 14.0-RELEASE Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: kern Assignee: b...@freebsd.org Reporter: victor.stin...@gmail.com Attachment #249266 text/plain mime type: Created attachment 249266 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=249266=edit Example reproducing the fma() zero sign issue Hi, I exposed the libc fma() function in Python: * https://github.com/python/cpython/commit/8e3c953b3acd7c656f66696806c9ae917e816492 * https://github.com/python/cpython/pull/116667 * https://github.com/python/cpython/issues/73468 The problem is that the Python test suite fails on FreeBSD x86-64 on tests on the zero sign: test_fma_zero_result() https://github.com/python/cpython/blob/cd2ed917801b93fb46d1dcf19dd480e5146932d8/Lib/test/test_math.py#L2694-L2748 Example: --- #include #include #include void set_double(double *x, const char *bytes) { memcpy(x, bytes, sizeof(*x)); } int main(int argc, char **argv) { double x = 0; //float.fromhex('0x1p-500') double y = 0; //float.fromhex('0x1p-550') double z = 0; //float.fromhex('0x1p-1000') #if 1 // condition always true, but trick the compiler, otherwise it will not // call fma() at runtime, but just compute the result at build time. if (argc) { set_double(, "\x00\x00\x00\x00\x00\x00\xb0\x20"); } else { x = 123; } #else set_double(, "\x00\x00\x00\x00\x00\x00\xb0\x20"); #endif set_double(, "\x00\x00\x00\x00\x00\x00\x90\x1d"); set_double(, "\x00\x00\x00\x00\x00\x00p\x01"); printf("x %g\n", x); printf("y %g\n", y); printf("z %g\n", z); double a, b, c, r; a = x-y; b = x+y; c = -z; r = fma(a, b, c); printf("fma(x-y, x+y, -z):\n"); printf("fma(%+g, %+g, %+g) = %+g\n", a, b, c, r); return 0; } --- Output on x86-64: --- $ clang x.c -Og -o x -lm && ./x x 3.05494e-151 y 2.71333e-166 z 9.33264e-302 fma(x-y, x+y, -z): fma(+3.05494e-151, +3.05494e-151, -9.33264e-302) = +0 --- fma() result is "+0" which is wrong. For example, if you replace "#if 1" with "#if 0", you get: --- (...) fma(+3.05494e-151, +3.05494e-151, -9.33264e-302) = -0 --- fma() result is now "-0" which is correct. This time, the result was computed at build time. Extract of the Python tests which fail on FreeBSD: --- # Corner case where rounding the multiplication would # give the wrong result. x = float.fromhex('0x1p-500') y = float.fromhex('0x1p-550') z = float.fromhex('0x1p-1000') self.assertIsNegativeZero(math.fma(x-y, x+y, -z)) self.assertIsPositiveZero(math.fma(y-x, x+y, z)) self.assertIsNegativeZero(math.fma(y-x, -(x+y), -z)) self.assertIsPositiveZero(math.fma(x-y, -(x+y), z)) --- For example, on Linux x86-64, the example works as expected with GCC and clang: --- vstinner@mona$ gcc x.c -o x -O2 -lm && ./x x 3.05494e-151 y 2.71333e-166 z 9.33264e-302 fma(x-y, x+y, -z): fma(+3.05494e-151, +3.05494e-151, -9.33264e-302) = -0 vstinner@mona$ clang x.c -o x -O2 -lm && ./x x 3.05494e-151 y 2.71333e-166 z 9.33264e-302 fma(x-y, x+y, -z): fma(+3.05494e-151, +3.05494e-151, -9.33264e-302) = -0 --- fma() returns -0 which is correct. On the bug, I selected "kern" component. I expect that the bug is more in the libc, but I cannot see "libc" choice. -- You are receiving this mail because: You are the assignee for the bug.