This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: Patch for libgfortran; broken isnan/isfinite/fpclassify
- From: Steve Ellcey <sje at cup dot hp dot com>
- To: fxcoudert at gmail dot com
- Cc: fortran at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Tue, 27 Sep 2005 09:47:39 -0700 (PDT)
- Subject: Re: Patch for libgfortran; broken isnan/isfinite/fpclassify
> I'm just saying that:
>
> #if (defined(fpclassify) && defined(HAVE_BROKEN_FPCLASSIFY))
> #undef fpclassify
> #endif
>
> could be written as:
>
> #if defined(HAVE_BROKEN_FPCLASSIFY)
> #undef fpclassify
> #endif
Ah, that makes sense now. Here is the new patch with all the
issues addressed. I will check it in later today after I finish
retesting.
Steve Ellcey
sje@cup.hp.com
2005-09-24 Steve Ellcey <sje@cup.hp.com>
PR target/23552
* acinclude.m4 (LIBGFOR_CHECK_FOR_BROKEN_ISFINITE): New.
(LIBGFOR_CHECK_FOR_BROKEN_ISNAN): New.
(LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY): New.
* configure.ac (LIBGFOR_CHECK_FOR_BROKEN_ISFINITE): Add use.
(LIBGFOR_CHECK_FOR_BROKEN_ISNAN): Add use.
(LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY): Add use.
* libgfortan.h (isfinite): undef if broken, set if needed.
(isnan): undef if broken, set if needed.
(fpclassify): undef if broken, set if needed.
* io/write.c: Remove TODO comment about working isfinite.
* intrinsics/c99_functions.c (round): Use isfinite instead
of fpclassify.
* intrinsics/c99_functions.c (roundf): Ditto.
*** gcc.orig/libgfortran/acinclude.m4 Fri Sep 23 13:40:12 2005
--- gcc/libgfortran/acinclude.m4 Tue Sep 27 09:28:56 2005
*************** esac])])
*** 230,232 ****
--- 230,351 ----
if test x"$have_crlf" = xyes; then
AC_DEFINE(HAVE_CRLF, 1, [Define if CRLF is line terminator.])
fi])
+
+ dnl Check whether isfinite is broken.
+ dnl The most common problem is that it does not work on long doubles.
+ AC_DEFUN([LIBGFOR_CHECK_FOR_BROKEN_ISFINITE], [
+ AC_CACHE_CHECK([whether isfinite is broken],
+ have_broken_isfinite, [
+ libgfor_check_for_broken_isfinite_save_LIBS=$LIBS
+ LIBS="$LIBS -lm"
+ AC_TRY_RUN([
+ #ifdef HAVE_MATH_H
+ #include <math.h>
+ #endif
+ #include <float.h>
+ int main ()
+ {
+ #ifdef isfinite
+ #ifdef LDBL_MAX
+ if (!isfinite(LDBL_MAX)) return 1;
+ #endif
+ #ifdef DBL_MAX
+ if (!isfinite(DBL_MAX)) return 1;
+ #endif
+ #endif
+ return 0;
+ }], have_broken_isfinite=no, have_broken_isfinite=yes, [
+ case "${target}" in
+ hppa*-*-hpux*) have_broken_isfinite=yes ;;
+ *) have_broken_isfinite=no ;;
+ esac])]
+ LIBS=$libgfor_check_for_broken_isfinite_save_LIBS)
+ if test x"$have_broken_isfinite" = xyes; then
+ AC_DEFINE(HAVE_BROKEN_ISFINITE, 1, [Define if isfinite is broken.])
+ fi])
+
+ dnl Check whether isnan is broken.
+ dnl The most common problem is that it does not work on long doubles.
+ AC_DEFUN([LIBGFOR_CHECK_FOR_BROKEN_ISNAN], [
+ AC_CACHE_CHECK([whether isnan is broken],
+ have_broken_isnan, [
+ libgfor_check_for_broken_isnan_save_LIBS=$LIBS
+ LIBS="$LIBS -lm"
+ AC_TRY_RUN([
+ #ifdef HAVE_MATH_H
+ #include <math.h>
+ #endif
+ #include <float.h>
+ int main ()
+ {
+ #ifdef isnan
+ #ifdef LDBL_MAX
+ {
+ long double x;
+ x = __builtin_nanl ("");
+ if (!isnan(x)) return 1;
+ if (isnan(LDBL_MAX)) return 1;
+ #ifdef NAN
+ x = (long double) NAN;
+ if (!isnan(x)) return 1;
+ #endif
+ }
+ #endif
+ #ifdef DBL_MAX
+ {
+ double y;
+ y = __builtin_nan ("");
+ if (!isnan(y)) return 1;
+ if (isnan(DBL_MAX)) return 1;
+ #ifdef NAN
+ y = (double) NAN;
+ if (!isnan(y)) return 1;
+ #endif
+ }
+ #endif
+ #endif
+ return 0;
+ }], have_broken_isnan=no, have_broken_isnan=yes, [
+ case "${target}" in
+ hppa*-*-hpux*) have_broken_isnan=yes ;;
+ *) have_broken_isnan=no ;;
+ esac])]
+ LIBS=$libgfor_check_for_broken_isnan_save_LIBS)
+ if test x"$have_broken_isnan" = xyes; then
+ AC_DEFINE(HAVE_BROKEN_ISNAN, 1, [Define if isnan is broken.])
+ fi])
+
+ dnl Check whether fpclassify is broken.
+ dnl The most common problem is that it does not work on long doubles.
+ AC_DEFUN([LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY], [
+ AC_CACHE_CHECK([whether fpclassify is broken],
+ have_broken_fpclassify, [
+ libgfor_check_for_broken_fpclassify_save_LIBS=$LIBS
+ LIBS="$LIBS -lm"
+ AC_TRY_RUN([
+ #ifdef HAVE_MATH_H
+ #include <math.h>
+ #endif
+ #include <float.h>
+ int main ()
+ {
+ #ifdef fpclassify
+ #ifdef LDBL_MAX
+ if (fpclassify(LDBL_MAX) == FP_NAN
+ || fpclassify(LDBL_MAX) == FP_INFINITE) return 1;
+ #endif
+ #ifdef DBL_MAX
+ if (fpclassify(DBL_MAX) == FP_NAN
+ || fpclassify(DBL_MAX) == FP_INFINITE) return 1;
+ #endif
+ #endif
+ return 0;
+ }], have_broken_fpclassify=no, have_broken_fpclassify=yes, [
+ case "${target}" in
+ hppa*-*-hpux*) have_broken_fpclassify=yes ;;
+ *) have_broken_fpclassify=no ;;
+ esac])]
+ LIBS=$libgfor_check_for_broken_fpclassify_save_LIBS)
+ if test x"$have_broken_fpclassify" = xyes; then
+ AC_DEFINE(HAVE_BROKEN_FPCLASSIFY, 1, [Define if fpclassify is broken.])
+ fi])
*** gcc.orig/libgfortran/configure.ac Fri Sep 23 13:40:12 2005
--- gcc/libgfortran/configure.ac Fri Sep 23 13:39:24 2005
*************** AC_CHECK_LIB([m],[y1f],[AC_DEFINE([HAVE_
*** 230,235 ****
--- 230,244 ----
AC_CHECK_LIB([m],[yn],[AC_DEFINE([HAVE_YN],[1],[libm includes yn])])
AC_CHECK_LIB([m],[ynf],[AC_DEFINE([HAVE_YNF],[1],[libm includes ynf])])
+ # Check for a isfinite macro that works on long doubles.
+ LIBGFOR_CHECK_FOR_BROKEN_ISFINITE
+
+ # Check for a isnan macro that works on long doubles.
+ LIBGFOR_CHECK_FOR_BROKEN_ISNAN
+
+ # Check for a fpclassify macro that works on long doubles.
+ LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY
+
# Fallback in case isfinite is not available.
AC_CHECK_LIB([m],[finite],[AC_DEFINE([HAVE_FINITE],[1],[libm includes finite])])
*** gcc.orig/libgfortran/libgfortran.h Fri Sep 23 13:40:12 2005
--- gcc/libgfortran/libgfortran.h Tue Sep 27 09:30:00 2005
*************** typedef off_t gfc_offset;
*** 177,189 ****
When isfinite is not available, try to use one of the
alternatives, or bail out. */
! #if (!defined(isfinite) || defined(__CYGWIN__))
#undef isfinite
! #if defined(fpclassify)
#define isfinite(x) (fpclassify(x) != FP_NAN && fpclassify(x) != FP_INFINITE)
#else
! #define isfinite(x) ((x) - (x) == 0)
! #endif
#endif /* !defined(isfinite) */
/* TODO: find the C99 version of these an move into above ifdef. */
--- 177,209 ----
When isfinite is not available, try to use one of the
alternatives, or bail out. */
!
! #if defined(HAVE_BROKEN_ISFINITE) || defined(__CYGWIN__)
#undef isfinite
! #endif
!
! #if defined(HAVE_BROKEN_ISNAN)
! #undef isnan
! #endif
!
! #if defined(HAVE_BROKEN_FPCLASSIFY)
! #undef fpclassify
! #endif
!
! #if !defined(isfinite)
! #if !defined(fpclassify)
! #define isfinite(x) ((x) - (x) == 0)
! #else
#define isfinite(x) (fpclassify(x) != FP_NAN && fpclassify(x) != FP_INFINITE)
+ #endif /* !defined(fpclassify) */
+ #endif /* !defined(isfinite) */
+
+ #if !defined(isnan)
+ #if !defined(fpclassify)
+ #define isnan(x) ((x) != (x))
#else
! #define isnan(x) (fpclassify(x) == FP_NAN)
! #endif /* !defined(fpclassify) */
#endif /* !defined(isfinite) */
/* TODO: find the C99 version of these an move into above ifdef. */
*** gcc.orig/libgfortran/io/write.c Fri Sep 23 13:40:24 2005
--- gcc/libgfortran/io/write.c Fri Sep 23 13:39:35 2005
*************** write_float (fnode *f, const char *sourc
*** 821,829 ****
if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
{
- /* TODO: there are some systems where isfinite is not able to work
- with long double variables. We should detect this case and
- provide our own version for isfinite. */
res = isfinite (n);
if (res == 0)
{
--- 821,826 ----
*** gcc.orig/libgfortran/intrinsics/c99_functions.c Fri Sep 23 13:40:32 2005
--- gcc/libgfortran/intrinsics/c99_functions.c Fri Sep 23 13:39:49 2005
*************** double
*** 315,326 ****
round(double x)
{
double t;
! #if defined(fpclassify)
! int i;
! i = fpclassify(x);
! if (i == FP_INFINITE || i == FP_NAN)
return (x);
- #endif
if (x >= 0.0)
{
--- 315,322 ----
round(double x)
{
double t;
! if (!isfinite (x))
return (x);
if (x >= 0.0)
{
*************** float
*** 347,359 ****
roundf(float x)
{
float t;
! #if defined(fpclassify)
! int i;
!
! i = fpclassify(x);
! if (i == FP_INFINITE || i == FP_NAN)
return (x);
- #endif
if (x >= 0.0)
{
--- 343,350 ----
roundf(float x)
{
float t;
! if (!isfinite (x))
return (x);
if (x >= 0.0)
{