diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-09-05 22:36:56 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-09-05 22:36:56 (GMT) |
commit | a40c793d06ee2b42a5013015352616b4ca6b288b (patch) | |
tree | 5e056aac66ded03b3a6cae9118c7e109c861bfc6 /Include | |
parent | 75ed167527e688ab6160af3b387532ea3e1c6a74 (diff) | |
download | cpython-a40c793d06ee2b42a5013015352616b4ca6b288b.zip cpython-a40c793d06ee2b42a5013015352616b4ca6b288b.tar.gz cpython-a40c793d06ee2b42a5013015352616b4ca6b288b.tar.bz2 |
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.
Diffstat (limited to 'Include')
-rw-r--r-- | Include/pyport.h | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/Include/pyport.h b/Include/pyport.h index 0363953..15a480a 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -230,6 +230,18 @@ extern "C" { */ #define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X)) +/* According to + * http://www.cray.com/swpubs/manuals/SN-2194_2.0/html-SN-2194_2.0/x3138.htm + * on some Cray systems HUGE_VAL is incorrectly (according to the C std) + * defined to be the largest positive finite rather than infinity. We need + * the std-conforming infinity meaning (provided the platform has one!). + */ +#ifdef INFINITY +#define Py_HUGE_VAL INFINITY +#else +#define Py_HUGE_VAL HUGE_VAL +#endif + /* 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 @@ -246,9 +258,24 @@ extern "C" { * 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)) +#define Py_OVERFLOWED(X) ((X) != 0.0 && (errno == ERANGE || \ + (X) == Py_HUGE_VAL || \ + (X) == -Py_HUGE_VAL)) + +/* Py_SET_ERANGE_ON_OVERFLOW(x) + * If a libm function did not set errno, but it looks like the result + * overflowed, set errno to ERANGE. Set errno to 0 before calling a libm + * function, and invoke this macro after, passing the function result. + * Caution: + * This isn't reliable. See Py_OVERFLOWED comments. + * X is evaluated more than once. + */ +#define Py_SET_ERANGE_IF_OVERFLOW(X) \ + do { \ + if (errno == 0 && ((X) == Py_HUGE_VAL || \ + (X) == -Py_HUGE_VAL)) \ + errno = ERANGE; \ + } while(0) /************************************************************************** Prototypes that are missing from the standard include files on some systems |