Skip to content

Commit 28ba074

Browse files
committed
restore errno on success
1 parent 23d948e commit 28ba074

3 files changed

Lines changed: 37 additions & 20 deletions

File tree

Lib/test/test_capi/test_complex.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -281,18 +281,33 @@ def test_py_c_abs(self):
281281
# Test _Py_c_abs()
282282
_py_c_abs = _testcapi._py_c_abs
283283

284-
self.assertEqual(_py_c_abs(-1), (1.0, 0))
285-
self.assertEqual(_py_c_abs(1j), (1.0, 0))
286-
287-
self.assertEqual(_py_c_abs(complex('+inf+1j')), (INF, 0))
288-
self.assertEqual(_py_c_abs(complex('-inf+1j')), (INF, 0))
289-
self.assertEqual(_py_c_abs(complex('1.25+infj')), (INF, 0))
290-
self.assertEqual(_py_c_abs(complex('1.25-infj')), (INF, 0))
291-
292-
self.assertTrue(isnan(_py_c_abs(complex('1.25+nanj'))[0]))
293-
self.assertTrue(isnan(_py_c_abs(complex('nan-1j'))[0]))
294-
295-
self.assertEqual(_py_c_abs(complex(*[DBL_MAX]*2))[1], errno.ERANGE)
284+
try:
285+
_testcapi.set_errno(0)
286+
self.assertEqual(_py_c_abs(-1), (1.0, 0))
287+
_testcapi.set_errno(0)
288+
self.assertEqual(_py_c_abs(1j), (1.0, 0))
289+
290+
_testcapi.set_errno(0)
291+
self.assertEqual(_py_c_abs(complex('+inf+1j')), (INF, 0))
292+
_testcapi.set_errno(0)
293+
self.assertEqual(_py_c_abs(complex('-inf+1j')), (INF, 0))
294+
_testcapi.set_errno(0)
295+
self.assertEqual(_py_c_abs(complex('1.25+infj')), (INF, 0))
296+
_testcapi.set_errno(0)
297+
self.assertEqual(_py_c_abs(complex('1.25-infj')), (INF, 0))
298+
299+
_testcapi.set_errno(0)
300+
self.assertTrue(isnan(_py_c_abs(complex('1.25+nanj'))[0]))
301+
_testcapi.set_errno(0)
302+
self.assertTrue(isnan(_py_c_abs(complex('nan-1j'))[0]))
303+
304+
_testcapi.set_errno(0)
305+
self.assertEqual(_py_c_abs(complex(*[DBL_MAX]*2))[1], errno.ERANGE)
306+
307+
_testcapi.set_errno(errno.EACCES) # preserve errno
308+
self.assertEqual(_py_c_abs(1j), (1, errno.EACCES))
309+
finally:
310+
_testcapi.set_errno(0)
296311

297312

298313
if __name__ == "__main__":

Modules/_testcapi/complex.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ _py_c_abs(PyObject *Py_UNUSED(module), PyObject* obj)
7676
return NULL;
7777
}
7878

79-
errno = 0;
8079
res = _Py_c_abs(complex);
8180
return Py_BuildValue("di", res, errno);
8281
}

Objects/complexobject.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -381,27 +381,32 @@ _Py_c_abs(Py_complex z)
381381
{
382382
/* sets errno = ERANGE on overflow */
383383
double result;
384+
int saved_errno = errno;
384385

385386
if (!isfinite(z.real) || !isfinite(z.imag)) {
386387
/* C99 rules: if either the real or the imaginary part is an
387388
infinity, return infinity, even if the other part is a
388389
NaN. */
389390
if (isinf(z.real)) {
390391
result = fabs(z.real);
392+
errno = saved_errno;
391393
return result;
392394
}
393395
if (isinf(z.imag)) {
394396
result = fabs(z.imag);
397+
errno = saved_errno;
395398
return result;
396399
}
397400
/* either the real or imaginary part is a NaN,
398401
and neither is infinite. Result should be NaN. */
402+
errno = saved_errno;
399403
return Py_NAN;
400404
}
401405
result = hypot(z.real, z.imag);
402-
if (!isfinite(result)) {
406+
if (!isfinite(result))
403407
errno = ERANGE;
404-
}
408+
else
409+
errno = saved_errno;
405410
return result;
406411
}
407412

@@ -811,11 +816,9 @@ complex_abs(PyObject *op)
811816
PyComplexObject *v = _PyComplexObject_CAST(op);
812817
double result;
813818

814-
result = hypot(v->cval.real, v->cval.imag);
815-
/* Testing FE_OVERFLOW floating-point exception is slow. */
816-
if (isfinite(v->cval.real) && isfinite(v->cval.imag)
817-
&& !isfinite(result))
818-
{
819+
errno = 0;
820+
result = _Py_c_abs(v->cval);
821+
if (errno == ERANGE) {
819822
PyErr_SetString(PyExc_OverflowError,
820823
"absolute value too large");
821824
return NULL;

0 commit comments

Comments
 (0)