summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_cmath.py4
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_math.c23
-rw-r--r--Modules/_math.h8
4 files changed, 28 insertions, 10 deletions
diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py
index 4e93be4..692ea36 100644
--- a/Lib/test/test_cmath.py
+++ b/Lib/test/test_cmath.py
@@ -519,15 +519,11 @@ class CMathTests(unittest.TestCase):
# of zero, then atan and atanh will also have difficulties with
# the sign of complex zeros.
@requires_IEEE_754
- @unittest.skipIf(sysconfig.get_config_var('LOG1P_DROPS_ZERO_SIGN'),
- "system log1p() function doesn't preserve the sign")
def testAtanSign(self):
for z in complex_zeros:
self.assertComplexIdentical(cmath.atan(z), z)
@requires_IEEE_754
- @unittest.skipIf(sysconfig.get_config_var('LOG1P_DROPS_ZERO_SIGN'),
- "system log1p() function doesn't preserve the sign")
def testAtanhSign(self):
for z in complex_zeros:
self.assertComplexIdentical(cmath.atanh(z), z)
diff --git a/Misc/NEWS b/Misc/NEWS
index 4f3fc51..8fdd515 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -104,6 +104,9 @@ Core and Builtins
Library
-------
+- Issue #15477: In cmath and math modules, add workaround for platforms whose
+ system-supplied log1p function doesn't respect signs of zeros.
+
- Issue #11062: Fix adding a message from file to Babyl mailbox.
- Issue #15646: Prevent equivalent of a fork bomb when using
diff --git a/Modules/_math.c b/Modules/_math.c
index 2fef481..fe75a36 100644
--- a/Modules/_math.c
+++ b/Modules/_math.c
@@ -189,6 +189,27 @@ _Py_expm1(double x)
significant loss of precision that arises from direct evaluation when x is
small. */
+#ifdef HAVE_LOG1P
+
+double
+_Py_log1p(double x)
+{
+ /* Some platforms supply a log1p function but don't respect the sign of
+ zero: log1p(-0.0) gives 0.0 instead of the correct result of -0.0.
+
+ To save fiddling with configure tests and platform checks, we handle the
+ special case of zero input directly on all platforms.
+ */
+ if (x == 0.0) {
+ return x;
+ }
+ else {
+ return log1p(x);
+ }
+}
+
+#else
+
double
_Py_log1p(double x)
{
@@ -230,3 +251,5 @@ _Py_log1p(double x)
return log(1.+x);
}
}
+
+#endif /* ifdef HAVE_LOG1P */
diff --git a/Modules/_math.h b/Modules/_math.h
index c0ceece..cf079ad 100644
--- a/Modules/_math.h
+++ b/Modules/_math.h
@@ -36,10 +36,6 @@ double _Py_log1p(double x);
#define m_expm1 _Py_expm1
#endif
-#ifdef HAVE_LOG1P
-#define m_log1p log1p
-#else
-/* if the system doesn't have log1p, use the substitute
- function defined in Modules/_math.c. */
+/* Use the substitute from _math.c on all platforms:
+ it includes workarounds for buggy handling of zeros. */
#define m_log1p _Py_log1p
-#endif