]> granicus.if.org Git - python/commitdiff
Try to recover from that glibc's ldexp apparently doesn't set errno on
authorTim Peters <tim.peters@gmail.com>
Wed, 5 Sep 2001 05:38:10 +0000 (05:38 +0000)
committerTim Peters <tim.peters@gmail.com>
Wed, 5 Sep 2001 05:38:10 +0000 (05:38 +0000)
overflow.  Needs testing on Linux (test_long.py and test_long_future.py
especially).

Include/pyport.h
Objects/longobject.c

index aa9c1f71703bb79767c55aba470384aa41c92f78..96801539b5b1f4178b77c2eb9ae9c1a54e6becc2 100644 (file)
@@ -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.)
index 5da5113d2ef698ed9b9d8f08fcfff87ecb7e1573..91e0b66afb117f878aa38970c1bba8aa7544871b 100644 (file)
@@ -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);