[Python-checkins] CVS: python/dist/src/Modules cmathmodule.c,2.25,2.26 mathmodule.c,2.64,2.65

Tim Peters tim_one@users.sourceforge.net
Wed, 05 Sep 2001 15:36:58 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv29981/python/Modules

Modified Files:
	cmathmodule.c mathmodule.c 
Log Message:
Rework the way we try to check for libm overflow, given that C99 no longer
requires that errno ever get set, and it looks like glibc is already
playing that game.  New rules:

+ Never use HUGE_VAL.  Use the new Py_HUGE_VAL instead.

+ Never believe errno.  If overflow is the only thing you're interested in,
  use the new Py_OVERFLOWED(x) macro.  If you're interested in any libm
  errors, use the new Py_SET_ERANGE_IF_OVERFLOW(x) macro, which attempts
  to set errno the way C89 said it worked.

Unfortunately, none of these are reliable, but they work on Windows and I
*expect* under glibc too.


Index: cmathmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/cmathmodule.c,v
retrieving revision 2.25
retrieving revision 2.26
diff -C2 -d -r2.25 -r2.26
*** cmathmodule.c	2001/09/05 14:45:54	2.25
--- cmathmodule.c	2001/09/05 22:36:56	2.26
***************
*** 5,21 ****
  #include "Python.h"
  
- #ifdef i860
- /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
- #undef HUGE_VAL
- #endif
- 
- #ifdef HUGE_VAL
- #define CHECK(x) if (errno != 0) ; \
- 	else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
- 	else errno = ERANGE
- #else
- #define CHECK(x) /* Don't know how to check */
- #endif
- 
  #ifndef M_PI
  #define M_PI (3.141592653589793239)
--- 5,8 ----
***************
*** 367,372 ****
  	x = (*func)(x);
  	PyFPE_END_PROTECT(x)
! 	CHECK(x.real);
! 	CHECK(x.imag);
  	if (errno != 0)
  		return math_error();
--- 354,359 ----
  	x = (*func)(x);
  	PyFPE_END_PROTECT(x)
! 	Py_SET_ERANGE_IF_OVERFLOW(x.real);
! 	Py_SET_ERANGE_IF_OVERFLOW(x.imag);
  	if (errno != 0)
  		return math_error();

Index: mathmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/mathmodule.c,v
retrieving revision 2.64
retrieving revision 2.65
diff -C2 -d -r2.64 -r2.65
*** mathmodule.c	2001/09/05 14:45:54	2.64
--- mathmodule.c	2001/09/05 22:36:56	2.65
***************
*** 13,35 ****
  #endif /* _MSC_VER */
  
- 
- #ifdef i860
- /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
- #undef HUGE_VAL
- #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) ; \
- 	else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
- 	else errno = ERANGE
- #else
- #define CHECK(x) /* Don't know how to check */
- #endif
- 
  #ifdef SCO_ATAN2_BUG
  /*
--- 13,16 ----
***************
*** 39,43 ****
  static double atan2_sco(double x, double y)
  {
! 	if (x == 0.0)
  		return (double)0.0;
  	return atan2(x, y);
--- 20,24 ----
  static double atan2_sco(double x, double y)
  {
!  	if (x == 0.0)
  		return (double)0.0;
  	return atan2(x, y);
***************
*** 59,70 ****
  	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)
--- 40,54 ----
  	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.
! 		 * Alas, C99 never requires that errno be set.
! 		 * 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)
***************
*** 90,94 ****
  	x = (*func)(x);
  	PyFPE_END_PROTECT(x)
! 	CHECK(x);
  	if (errno && is_error(x))
  		return NULL;
--- 74,78 ----
  	x = (*func)(x);
  	PyFPE_END_PROTECT(x)
! 	Py_SET_ERANGE_IF_OVERFLOW(x);
  	if (errno && is_error(x))
  		return NULL;
***************
*** 107,111 ****
  	x = (*func)(x, y);
  	PyFPE_END_PROTECT(x)
! 	CHECK(x);
  	if (errno && is_error(x))
  		return NULL;
--- 91,95 ----
  	x = (*func)(x, y);
  	PyFPE_END_PROTECT(x)
! 	Py_SET_ERANGE_IF_OVERFLOW(x);
  	if (errno && is_error(x))
  		return NULL;
***************
*** 181,185 ****
  	errno = 0;
  	x = frexp(x, &i);
! 	CHECK(x);
  	if (errno && is_error(x))
  		return NULL;
--- 165,169 ----
  	errno = 0;
  	x = frexp(x, &i);
! 	Py_SET_ERANGE_IF_OVERFLOW(x);
  	if (errno && is_error(x))
  		return NULL;
***************
*** 206,210 ****
  	x = ldexp(x, exp);
  	PyFPE_END_PROTECT(x)
! 	CHECK(x);
  	if (errno && is_error(x))
  		return NULL;
--- 190,194 ----
  	x = ldexp(x, exp);
  	PyFPE_END_PROTECT(x)
! 	Py_SET_ERANGE_IF_OVERFLOW(x);
  	if (errno && is_error(x))
  		return NULL;
***************
*** 232,236 ****
  	x = modf(x, &y);
  #endif
! 	CHECK(x);
  	if (errno && is_error(x))
  		return NULL;
--- 216,220 ----
  	x = modf(x, &y);
  #endif
! 	Py_SET_ERANGE_IF_OVERFLOW(x);
  	if (errno && is_error(x))
  		return NULL;