Commit 13fcd57f authored by Tim Peters's avatar Tim Peters

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).
parent 576d4f3d
...@@ -230,6 +230,26 @@ extern "C" { ...@@ -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.)
......
...@@ -545,7 +545,7 @@ PyLong_AsDouble(PyObject *vv) ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment