From f4dd4402108cc005d45acd4ca83c8530c36a93ca Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 17 Sep 2024 20:16:15 +0300 Subject: [PATCH] gh-123836: workaround fmod(x, y) bug on Windows (#124171) Buildbot failure on Windows 10 with MSC v.1916 64 bit (AMD64): FAIL: testFmod (test.test_math.MathTests.testFmod) ---------------------------------------------------------------------- Traceback (most recent call last): File "D:\buildarea\3.x.bolen-windows10\build\Lib\test\test_math.py", line 605, in testFmod self.ftest('fmod(-10, 1)', math.fmod(-10, 1), -0.0) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\buildarea\3.x.bolen-windows10\build\Lib\test\test_math.py", line 258, in ftest self.fail("{}: {}".format(name, failure)) ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError: fmod(-10, 1): expected -0.0, got 0.0 (zero has wrong sign) Here Windows loose sign of the result; if y is nonzero, the result should have the same sign as x. This amends commit 28aea5d07d. --- .../2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst | 3 +++ Modules/mathmodule.c | 9 +++++++++ 2 files changed, 12 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst diff --git a/Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst b/Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst new file mode 100644 index 00000000000..c2f0bb14f55 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst @@ -0,0 +1,3 @@ +Add workaround for broken :c:func:`!fmod()` implementations on Windows, that +loose zero sign (e.g. ``fmod(-10, 1)`` returns ``0.0``). Patch by Sergey B +Kirpichev. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index b7eb745177f..baf2dc439b8 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2348,6 +2348,15 @@ math_fmod_impl(PyObject *module, double x, double y) return PyFloat_FromDouble(x); errno = 0; r = fmod(x, y); +#ifdef _MSC_VER + /* Windows (e.g. Windows 10 with MSC v.1916) loose sign + for zero result. But C99+ says: "if y is nonzero, the result + has the same sign as x". + */ + if (r == 0.0 && y != 0.0) { + r = copysign(r, x); + } +#endif if (isnan(r)) { if (!isnan(x) && !isnan(y)) errno = EDOM;