Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions Lib/test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -2765,12 +2765,6 @@ def test_fma_infinities(self):
self.assertEqual(math.fma(-b, -math.inf, c), math.inf)
self.assertEqual(math.fma(-b, math.inf, c), -math.inf)

# gh-73468: On some platforms, libc fma() doesn't implement IEE 754-2008
# properly: it doesn't use the right sign when the result is zero.
@unittest.skipIf(
sys.platform.startswith(("freebsd", "wasi", "netbsd", "emscripten"))
or (sys.platform == "android" and platform.machine() == "x86_64"),
f"this platform doesn't implement IEE 754-2008 properly")
def test_fma_zero_result(self):
nonnegative_finites = [0.0, 1e-300, 2.3, 1e300]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :func:`math.fma(x, y, z) <math.fma>` zero sign: fix the result sign when
*z* is zero. Patch by Victor Stinner and Sergey B Kirpichev.
17 changes: 16 additions & 1 deletion Modules/mathmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2344,7 +2344,22 @@ static PyObject *
math_fma_impl(PyObject *module, double x, double y, double z)
/*[clinic end generated code: output=4fc8626dbc278d17 input=e3ad1f4a4c89626e]*/
{
double r = fma(x, y, z);
double r;
if (z) {
r = fma(x, y, z);
}
else {
// gh-73468, gh-131032: On some platforms (ex: WASI, NetBSD,
// Emscripten, musl C library), libc fma() doesn't implement
// IEEE 754-2008 properly: it doesn't use the right sign when the
// result is zero.
if (x && y) {
r = x * y;
}
else {
r = copysign(1, z) == 1 ? x*y + z : x*y;
}
}

/* Fast path: if we got a finite result, we're done. */
if (isfinite(r)) {
Expand Down
Loading