Skip to content

Commit a72f0cd

Browse files
committed
Issue python#24489: ensure a previously set C errno doesn't disturb cmath.polar().
2 parents 5376ba9 + 6bc217d commit a72f0cd

File tree

4 files changed

+58
-11
lines changed

4 files changed

+58
-11
lines changed

Lib/test/test_cmath.py

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from test.support import requires_IEEE_754
1+
from test.support import requires_IEEE_754, cpython_only
22
from test.test_math import parse_testfile, test_file
33
import test.test_math as test_math
44
import unittest
@@ -382,17 +382,48 @@ def polar_complex(z):
382382
self.rAssertAlmostEqual(expected.imag, actual.imag,
383383
msg=error_message)
384384

385-
def assertCISEqual(self, a, b):
386-
eps = 1E-7
387-
if abs(a[0] - b[0]) > eps or abs(a[1] - b[1]) > eps:
388-
self.fail((a ,b))
385+
def check_polar(self, func):
386+
def check(arg, expected):
387+
got = func(arg)
388+
for e, g in zip(expected, got):
389+
self.rAssertAlmostEqual(e, g)
390+
check(0, (0., 0.))
391+
check(1, (1., 0.))
392+
check(-1, (1., pi))
393+
check(1j, (1., pi / 2))
394+
check(-3j, (3., -pi / 2))
395+
inf = float('inf')
396+
check(complex(inf, 0), (inf, 0.))
397+
check(complex(-inf, 0), (inf, pi))
398+
check(complex(3, inf), (inf, pi / 2))
399+
check(complex(5, -inf), (inf, -pi / 2))
400+
check(complex(inf, inf), (inf, pi / 4))
401+
check(complex(inf, -inf), (inf, -pi / 4))
402+
check(complex(-inf, inf), (inf, 3 * pi / 4))
403+
check(complex(-inf, -inf), (inf, -3 * pi / 4))
404+
nan = float('nan')
405+
check(complex(nan, 0), (nan, nan))
406+
check(complex(0, nan), (nan, nan))
407+
check(complex(nan, nan), (nan, nan))
408+
check(complex(inf, nan), (inf, nan))
409+
check(complex(-inf, nan), (inf, nan))
410+
check(complex(nan, inf), (inf, nan))
411+
check(complex(nan, -inf), (inf, nan))
389412

390413
def test_polar(self):
391-
self.assertCISEqual(polar(0), (0., 0.))
392-
self.assertCISEqual(polar(1.), (1., 0.))
393-
self.assertCISEqual(polar(-1.), (1., pi))
394-
self.assertCISEqual(polar(1j), (1., pi/2))
395-
self.assertCISEqual(polar(-1j), (1., -pi/2))
414+
self.check_polar(polar)
415+
416+
@cpython_only
417+
def test_polar_errno(self):
418+
# Issue #24489: check a previously set C errno doesn't disturb polar()
419+
from _testcapi import set_errno
420+
def polar_with_errno_set(z):
421+
set_errno(11)
422+
try:
423+
return polar(z)
424+
finally:
425+
set_errno(0)
426+
self.check_polar(polar_with_errno_set)
396427

397428
def test_phase(self):
398429
self.assertAlmostEqual(phase(0), 0.)

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Core and Builtins
2424
Library
2525
-------
2626

27+
- Issue #24489: ensure a previously set C errno doesn't disturb cmath.polar().
28+
2729
- Issue #24408: Fixed AttributeError in measure() and metrics() methods of
2830
tkinter.Font.
2931

Modules/_testcapimodule.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,18 @@ raise_exception(PyObject *self, PyObject *args)
17951795
return NULL;
17961796
}
17971797

1798+
static PyObject *
1799+
set_errno(PyObject *self, PyObject *args)
1800+
{
1801+
int new_errno;
1802+
1803+
if (!PyArg_ParseTuple(args, "i:set_errno", &new_errno))
1804+
return NULL;
1805+
1806+
errno = new_errno;
1807+
Py_RETURN_NONE;
1808+
}
1809+
17981810
static PyObject *
17991811
test_set_exc_info(PyObject *self, PyObject *args)
18001812
{
@@ -3510,6 +3522,7 @@ test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
35103522
static PyMethodDef TestMethods[] = {
35113523
{"raise_exception", raise_exception, METH_VARARGS},
35123524
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
3525+
{"set_errno", set_errno, METH_VARARGS},
35133526
{"test_config", (PyCFunction)test_config, METH_NOARGS},
35143527
{"test_sizeof_c_types", (PyCFunction)test_sizeof_c_types, METH_NOARGS},
35153528
{"test_datetime_capi", test_datetime_capi, METH_NOARGS},

Modules/cmathmodule.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,9 +986,10 @@ cmath_polar_impl(PyModuleDef *module, Py_complex z)
986986
{
987987
double r, phi;
988988

989+
errno = 0;
989990
PyFPE_START_PROTECT("polar function", return 0)
990991
phi = c_atan2(z); /* should not cause any exception */
991-
r = _Py_c_abs(z); /* sets errno to ERANGE on overflow; otherwise 0 */
992+
r = _Py_c_abs(z); /* sets errno to ERANGE on overflow */
992993
PyFPE_END_PROTECT(r)
993994
if (errno != 0)
994995
return math_error();

0 commit comments

Comments
 (0)