From 57f282a2a06c01417abec74926e770fb12f95610 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Wed, 5 Sep 2001 05:38:10 +0000 Subject: 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). --- Include/pyport.h | 20 ++++++++++++++++++++ Objects/longobject.c | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h index aa9c1f7..9680153 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -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.) diff --git a/Objects/longobject.c b/Objects/longobject.c index 5da5113..91e0b66 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -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); -- cgit v0.12