mirror of
https://github.com/python/cpython.git
synced 2024-11-28 04:15:11 +08:00
Try to recover from that glibc's ldexp apparently doesn't set errno on
overflow. Needs testing on Linux (test_long.py and test_long_future.py especially).
This commit is contained in:
parent
e5ca6c71cd
commit
57f282a2a0
@ -230,6 +230,26 @@ extern "C" {
|
||||
*/
|
||||
#define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X))
|
||||
|
||||
/* Py_OVERFLOWED(X)
|
||||
* Return 1 iff a libm function overflowed. Set errno to 0 before calling
|
||||
* a libm function, and invoke this macro after, passing the function
|
||||
* result.
|
||||
* Caution:
|
||||
* This isn't reliable. C99 no longer requires libm to set errno under
|
||||
* any exceptional condition, but does require +- HUGE_VAL return
|
||||
* values on overflow. A 754 box *probably* maps HUGE_VAL to a
|
||||
* double infinity, and we're cool if that's so, unless the input
|
||||
* was an infinity and an infinity is the expected result. A C89
|
||||
* system sets errno to ERANGE, so we check for that too. We're
|
||||
* out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or
|
||||
* if the returned result is a NaN, or if a C89 box returns HUGE_VAL
|
||||
* in non-overflow cases.
|
||||
* X is evaluated more than once.
|
||||
*/
|
||||
#define Py_OVERFLOWED(X) ((X) != 0.0 && (errno == ERANGE || \
|
||||
(X) == HUGE_VAL || \
|
||||
(X) == -HUGE_VAL))
|
||||
|
||||
/**************************************************************************
|
||||
Prototypes that are missing from the standard include files on some systems
|
||||
(and possibly only some versions of such systems.)
|
||||
|
@ -545,7 +545,7 @@ PyLong_AsDouble(PyObject *vv)
|
||||
goto overflow;
|
||||
errno = 0;
|
||||
x = ldexp(x, e * SHIFT);
|
||||
if (errno == ERANGE)
|
||||
if (Py_OVERFLOWED(x))
|
||||
goto overflow;
|
||||
return x;
|
||||
|
||||
@ -1607,7 +1607,7 @@ long_true_divide(PyObject *v, PyObject *w)
|
||||
goto overflow;
|
||||
errno = 0;
|
||||
ad = ldexp(ad, aexp * SHIFT);
|
||||
if (ad != 0 && errno == ERANGE) /* ignore underflow to 0.0 */
|
||||
if (Py_OVERFLOWED(ad)) /* ignore underflow to 0.0 */
|
||||
goto overflow;
|
||||
return PyFloat_FromDouble(ad);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user