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:
Tim Peters 2001-09-05 05:38:10 +00:00
parent e5ca6c71cd
commit 57f282a2a0
2 changed files with 22 additions and 2 deletions

View file

@ -230,6 +230,26 @@ extern "C" {
*/ */
#define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X)) #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 Prototypes that are missing from the standard include files on some systems
(and possibly only some versions of such systems.) (and possibly only some versions of such systems.)

View file

@ -545,7 +545,7 @@ PyLong_AsDouble(PyObject *vv)
goto overflow; goto overflow;
errno = 0; errno = 0;
x = ldexp(x, e * SHIFT); x = ldexp(x, e * SHIFT);
if (errno == ERANGE) if (Py_OVERFLOWED(x))
goto overflow; goto overflow;
return x; return x;
@ -1607,7 +1607,7 @@ long_true_divide(PyObject *v, PyObject *w)
goto overflow; goto overflow;
errno = 0; errno = 0;
ad = ldexp(ad, aexp * SHIFT); 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; goto overflow;
return PyFloat_FromDouble(ad); return PyFloat_FromDouble(ad);