summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2015-06-23 12:38:13 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2015-06-23 12:38:13 (GMT)
commita72f0cdaea847228aceb5b56fbd28b77ef4809c4 (patch)
treeae80fc12096a3e2dd5989b74a2916e7c856ede58
parent5376ba9630e45ad177150ae68c9712640330a2fc (diff)
parent6bc217dd3d43763e62b413e75ddaeb7d30e1b451 (diff)
downloadcpython-a72f0cdaea847228aceb5b56fbd28b77ef4809c4.zip
cpython-a72f0cdaea847228aceb5b56fbd28b77ef4809c4.tar.gz
cpython-a72f0cdaea847228aceb5b56fbd28b77ef4809c4.tar.bz2
Issue #24489: ensure a previously set C errno doesn't disturb cmath.polar().
-rw-r--r--Lib/test/test_cmath.py51
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/_testcapimodule.c13
-rw-r--r--Modules/cmathmodule.c3
4 files changed, 58 insertions, 11 deletions
diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py
index 25ab7c1..1f884e5 100644
--- a/Lib/test/test_cmath.py
+++ b/Lib/test/test_cmath.py
@@ -1,4 +1,4 @@
-from test.support import requires_IEEE_754
+from test.support import requires_IEEE_754, cpython_only
from test.test_math import parse_testfile, test_file
import test.test_math as test_math
import unittest
@@ -382,17 +382,48 @@ class CMathTests(unittest.TestCase):
self.rAssertAlmostEqual(expected.imag, actual.imag,
msg=error_message)
- def assertCISEqual(self, a, b):
- eps = 1E-7
- if abs(a[0] - b[0]) > eps or abs(a[1] - b[1]) > eps:
- self.fail((a ,b))
+ def check_polar(self, func):
+ def check(arg, expected):
+ got = func(arg)
+ for e, g in zip(expected, got):
+ self.rAssertAlmostEqual(e, g)
+ check(0, (0., 0.))
+ check(1, (1., 0.))
+ check(-1, (1., pi))
+ check(1j, (1., pi / 2))
+ check(-3j, (3., -pi / 2))
+ inf = float('inf')
+ check(complex(inf, 0), (inf, 0.))
+ check(complex(-inf, 0), (inf, pi))
+ check(complex(3, inf), (inf, pi / 2))
+ check(complex(5, -inf), (inf, -pi / 2))
+ check(complex(inf, inf), (inf, pi / 4))
+ check(complex(inf, -inf), (inf, -pi / 4))
+ check(complex(-inf, inf), (inf, 3 * pi / 4))
+ check(complex(-inf, -inf), (inf, -3 * pi / 4))
+ nan = float('nan')
+ check(complex(nan, 0), (nan, nan))
+ check(complex(0, nan), (nan, nan))
+ check(complex(nan, nan), (nan, nan))
+ check(complex(inf, nan), (inf, nan))
+ check(complex(-inf, nan), (inf, nan))
+ check(complex(nan, inf), (inf, nan))
+ check(complex(nan, -inf), (inf, nan))
def test_polar(self):
- self.assertCISEqual(polar(0), (0., 0.))
- self.assertCISEqual(polar(1.), (1., 0.))
- self.assertCISEqual(polar(-1.), (1., pi))
- self.assertCISEqual(polar(1j), (1., pi/2))
- self.assertCISEqual(polar(-1j), (1., -pi/2))
+ self.check_polar(polar)
+
+ @cpython_only
+ def test_polar_errno(self):
+ # Issue #24489: check a previously set C errno doesn't disturb polar()
+ from _testcapi import set_errno
+ def polar_with_errno_set(z):
+ set_errno(11)
+ try:
+ return polar(z)
+ finally:
+ set_errno(0)
+ self.check_polar(polar_with_errno_set)
def test_phase(self):
self.assertAlmostEqual(phase(0), 0.)
diff --git a/Misc/NEWS b/Misc/NEWS
index cc3f4d4..8d25325 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,8 @@ Core and Builtins
Library
-------
+- Issue #24489: ensure a previously set C errno doesn't disturb cmath.polar().
+
- Issue #24408: Fixed AttributeError in measure() and metrics() methods of
tkinter.Font.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 2697ac2..ba0a24b 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1796,6 +1796,18 @@ raise_exception(PyObject *self, PyObject *args)
}
static PyObject *
+set_errno(PyObject *self, PyObject *args)
+{
+ int new_errno;
+
+ if (!PyArg_ParseTuple(args, "i:set_errno", &new_errno))
+ return NULL;
+
+ errno = new_errno;
+ Py_RETURN_NONE;
+}
+
+static PyObject *
test_set_exc_info(PyObject *self, PyObject *args)
{
PyObject *orig_exc;
@@ -3510,6 +3522,7 @@ test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
+ {"set_errno", set_errno, METH_VARARGS},
{"test_config", (PyCFunction)test_config, METH_NOARGS},
{"test_sizeof_c_types", (PyCFunction)test_sizeof_c_types, METH_NOARGS},
{"test_datetime_capi", test_datetime_capi, METH_NOARGS},
diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c
index d12e4c5..7f6c2c9 100644
--- a/Modules/cmathmodule.c
+++ b/Modules/cmathmodule.c
@@ -986,9 +986,10 @@ cmath_polar_impl(PyModuleDef *module, Py_complex z)
{
double r, phi;
+ errno = 0;
PyFPE_START_PROTECT("polar function", return 0)
phi = c_atan2(z); /* should not cause any exception */
- r = _Py_c_abs(z); /* sets errno to ERANGE on overflow; otherwise 0 */
+ r = _Py_c_abs(z); /* sets errno to ERANGE on overflow */
PyFPE_END_PROTECT(r)
if (errno != 0)
return math_error();