[Python-checkins] CVS: python/dist/src/Modules mathmodule.c,2.56,2.57
Tim Peters
python-dev@python.org
Wed, 11 Oct 2000 23:10:28 -0700
Update of /cvsroot/python/python/dist/src/Modules
In directory slayer.i.sourceforge.net:/tmp/cvs-serv13972/python/dist/src/Modules
Modified Files:
mathmodule.c
Log Message:
Stop raising OverflowError on underflows reported by libm (errno==ERANGE and
libm result is 0). Cautiously add a few libm exception test cases:
1. That exp(-huge) returns 0 without exception.
2. That exp(+huge) triggers OverflowError.
3. That sqrt(-1) raises ValueError specifically (apparently under glibc linked
with -lieee, it was raising OverflowError due to an accident of the way
mathmodule.c's CHECK() macro happened to deal with Infs and NaNs under gcc).
Index: mathmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/mathmodule.c,v
retrieving revision 2.56
retrieving revision 2.57
diff -C2 -r2.56 -r2.57
*** mathmodule.c 2000/09/16 03:54:24 2.56
--- mathmodule.c 2000/10/12 06:10:25 2.57
***************
*** 1,3 ****
-
/* Math module -- standard C math library functions, pi and e */
--- 1,2 ----
***************
*** 19,22 ****
--- 18,26 ----
#endif
+ /* RED_FLAG 12-Oct-2000 Tim
+ * What CHECK does if errno != 0 and x is a NaN is a platform-dependent crap
+ * shoot. Most (but not all!) platforms will end up setting errno to ERANGE
+ * then, but EDOM is probably better.
+ */
#ifdef HUGE_VAL
#define CHECK(x) if (errno != 0) ; \
***************
*** 27,41 ****
#endif
! static PyObject *
! math_error(void)
{
if (errno == EDOM)
PyErr_SetString(PyExc_ValueError, "math domain error");
! else if (errno == ERANGE)
! PyErr_SetString(PyExc_OverflowError, "math range error");
else
/* Unexpected math error */
PyErr_SetFromErrno(PyExc_ValueError);
! return NULL;
}
--- 31,63 ----
#endif
! /* Call is_error when errno != 0, and where x is the result libm
! * returned. is_error will usually set up an exception and return
! * true (1), but may return false (0) without setting up an exception.
! */
! static int
! is_error(double x)
{
+ int result = 1; /* presumption of guilt */
if (errno == EDOM)
PyErr_SetString(PyExc_ValueError, "math domain error");
! else if (errno == ERANGE) {
! /* ANSI C generally requires libm functions to set ERANGE
! * on overflow, but also generally *allows* them to set
! * ERANGE on underflow too. There's no consistency about
! * the latter across platforms. Here we suppress the
! * underflow errors (libm functions should return a zero
! * on underflow, and +- HUGE_VAL on overflow, so testing
! * the result for zero suffices to distinguish the cases).
! */
! if (x)
! PyErr_SetString(PyExc_OverflowError,
! "math range error");
! else
! result = 0;
! }
else
/* Unexpected math error */
PyErr_SetFromErrno(PyExc_ValueError);
! return result;
}
***************
*** 51,56 ****
PyFPE_END_PROTECT(x)
CHECK(x);
! if (errno != 0)
! return math_error();
else
return PyFloat_FromDouble(x);
--- 73,78 ----
PyFPE_END_PROTECT(x)
CHECK(x);
! if (errno && is_error(x))
! return NULL;
else
return PyFloat_FromDouble(x);
***************
*** 68,73 ****
PyFPE_END_PROTECT(x)
CHECK(x);
! if (errno != 0)
! return math_error();
else
return PyFloat_FromDouble(x);
--- 90,95 ----
PyFPE_END_PROTECT(x)
CHECK(x);
! if (errno && is_error(x))
! return NULL;
else
return PyFloat_FromDouble(x);
***************
*** 144,150 ****
x = frexp(x, &i);
CHECK(x);
! if (errno != 0)
! return math_error();
! return Py_BuildValue("(di)", x, i);
}
--- 166,173 ----
x = frexp(x, &i);
CHECK(x);
! if (errno && is_error(x))
! return NULL;
! else
! return Py_BuildValue("(di)", x, i);
}
***************
*** 169,174 ****
PyFPE_END_PROTECT(x)
CHECK(x);
! if (errno != 0)
! return math_error();
else
return PyFloat_FromDouble(x);
--- 192,197 ----
PyFPE_END_PROTECT(x)
CHECK(x);
! if (errno && is_error(x))
! return NULL;
else
return PyFloat_FromDouble(x);
***************
*** 198,204 ****
#endif
CHECK(x);
! if (errno != 0)
! return math_error();
! return Py_BuildValue("(dd)", x, y);
}
--- 221,228 ----
#endif
CHECK(x);
! if (errno && is_error(x))
! return NULL;
! else
! return Py_BuildValue("(dd)", x, y);
}