[Bug 277783] libc fma() doesn't not return the correct zero sign

2024-06-08 Thread bugzilla-noreply
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

2024-03-25 Thread bugzilla-noreply
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

2024-03-19 Thread bugzilla-noreply
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

2024-03-19 Thread bugzilla-noreply
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

2024-03-18 Thread bugzilla-noreply
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

2024-03-18 Thread bugzilla-noreply
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

2024-03-18 Thread bugzilla-noreply
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

2024-03-18 Thread bugzilla-noreply
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

2024-03-18 Thread bugzilla-noreply
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

2024-03-18 Thread bugzilla-noreply
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

2024-03-18 Thread bugzilla-noreply
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.