diff options
-rw-r--r-- | libgfortran/ChangeLog | 19 | ||||
-rw-r--r-- | libgfortran/acinclude.m4 | 119 | ||||
-rw-r--r-- | libgfortran/config.h.in | 9 | ||||
-rwxr-xr-x | libgfortran/configure | 247 | ||||
-rw-r--r-- | libgfortran/configure.ac | 9 | ||||
-rw-r--r-- | libgfortran/intrinsics/c99_functions.c | 13 | ||||
-rw-r--r-- | libgfortran/io/write.c | 3 | ||||
-rw-r--r-- | libgfortran/libgfortran.h | 28 |
8 files changed, 428 insertions, 19 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index b94c9f510ca..3f75f617151 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,22 @@ +2005-09-27 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. + * configure: Regenerate. + * config.h.in: Regenerate. + * 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. + 2005-09-24 Janne Blomqvist <jblomqvi@cc.hut.fi> * io.h: Changed prototypes of list_formatted_{read|write}. diff --git a/libgfortran/acinclude.m4 b/libgfortran/acinclude.m4 index f9fcca66659..dbf25f3c636 100644 --- a/libgfortran/acinclude.m4 +++ b/libgfortran/acinclude.m4 @@ -230,3 +230,122 @@ esac])]) 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]) diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in index 47f7c2f76c8..44c45c7767b 100644 --- a/libgfortran/config.h.in +++ b/libgfortran/config.h.in @@ -75,6 +75,15 @@ /* Define to 1 if the target supports __attribute__((visibility(...))). */ #undef HAVE_ATTRIBUTE_VISIBILITY +/* Define if fpclassify is broken. */ +#undef HAVE_BROKEN_FPCLASSIFY + +/* Define if isfinite is broken. */ +#undef HAVE_BROKEN_ISFINITE + +/* Define if isnan is broken. */ +#undef HAVE_BROKEN_ISNAN + /* libm includes cabs */ #undef HAVE_CABS diff --git a/libgfortran/configure b/libgfortran/configure index 6ace2fb76b1..5b31d51a647 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -19028,7 +19028,7 @@ _ACEOF fi -# Hack for AIX +# On AIX, clog is present in libm as __clog echo "$as_me:$LINENO: checking for __clog in -lm" >&5 echo $ECHO_N "checking for __clog in -lm... $ECHO_C" >&6 if test "${ac_cv_lib_m___clog+set}" = set; then @@ -19107,6 +19107,251 @@ _ACEOF fi +# Check for a isfinite macro that works on long doubles. + + echo "$as_me:$LINENO: checking whether isfinite is broken" >&5 +echo $ECHO_N "checking whether isfinite is broken... $ECHO_C" >&6 +if test "${have_broken_isfinite+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + libgfor_check_for_broken_isfinite_save_LIBS=$LIBS + LIBS="$LIBS -lm" + if test "$cross_compiling" = yes; then + +case "${target}" in + hppa*-*-hpux*) have_broken_isfinite=yes ;; + *) have_broken_isfinite=no ;; +esac +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#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; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + have_broken_isfinite=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +have_broken_isfinite=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + LIBS=$libgfor_check_for_broken_isfinite_save_LIBS +fi +echo "$as_me:$LINENO: result: $have_broken_isfinite" >&5 +echo "${ECHO_T}$have_broken_isfinite" >&6 +if test x"$have_broken_isfinite" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BROKEN_ISFINITE 1 +_ACEOF + +fi + +# Check for a isnan macro that works on long doubles. + + echo "$as_me:$LINENO: checking whether isnan is broken" >&5 +echo $ECHO_N "checking whether isnan is broken... $ECHO_C" >&6 +if test "${have_broken_isnan+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + libgfor_check_for_broken_isnan_save_LIBS=$LIBS + LIBS="$LIBS -lm" + if test "$cross_compiling" = yes; then + +case "${target}" in + hppa*-*-hpux*) have_broken_isnan=yes ;; + *) have_broken_isnan=no ;; +esac +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#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; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + have_broken_isnan=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +have_broken_isnan=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + LIBS=$libgfor_check_for_broken_isnan_save_LIBS +fi +echo "$as_me:$LINENO: result: $have_broken_isnan" >&5 +echo "${ECHO_T}$have_broken_isnan" >&6 +if test x"$have_broken_isnan" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BROKEN_ISNAN 1 +_ACEOF + +fi + +# Check for a fpclassify macro that works on long doubles. + + echo "$as_me:$LINENO: checking whether fpclassify is broken" >&5 +echo $ECHO_N "checking whether fpclassify is broken... $ECHO_C" >&6 +if test "${have_broken_fpclassify+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + libgfor_check_for_broken_fpclassify_save_LIBS=$LIBS + LIBS="$LIBS -lm" + if test "$cross_compiling" = yes; then + +case "${target}" in + hppa*-*-hpux*) have_broken_fpclassify=yes ;; + *) have_broken_fpclassify=no ;; +esac +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#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; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + have_broken_fpclassify=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +have_broken_fpclassify=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + LIBS=$libgfor_check_for_broken_fpclassify_save_LIBS +fi +echo "$as_me:$LINENO: result: $have_broken_fpclassify" >&5 +echo "${ECHO_T}$have_broken_fpclassify" >&6 +if test x"$have_broken_fpclassify" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BROKEN_FPCLASSIFY 1 +_ACEOF + +fi + # Fallback in case isfinite is not available. echo "$as_me:$LINENO: checking for finite in -lm" >&5 echo $ECHO_N "checking for finite in -lm... $ECHO_C" >&6 diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index ebd17b193b1..65f62416374 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -328,6 +328,15 @@ AC_CHECK_LIB([m],[ynl],[AC_DEFINE([HAVE_YNL],[1],[libm includes ynl])]) # On AIX, clog is present in libm as __clog AC_CHECK_LIB([m],[__clog],[AC_DEFINE([HAVE_CLOG],[1],[libm includes clog])]) +# 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])]) diff --git a/libgfortran/intrinsics/c99_functions.c b/libgfortran/intrinsics/c99_functions.c index 8083f776df5..2417e69cbed 100644 --- a/libgfortran/intrinsics/c99_functions.c +++ b/libgfortran/intrinsics/c99_functions.c @@ -344,12 +344,8 @@ double round(double x) { double t; -#if defined(fpclassify) - int i; - i = fpclassify(x); - if (i == FP_INFINITE || i == FP_NAN) + if (!isfinite (x)) return (x); -#endif if (x >= 0.0) { @@ -377,13 +373,8 @@ float roundf(float x) { float t; -#if defined(fpclassify) - int i; - - i = fpclassify(x); - if (i == FP_INFINITE || i == FP_NAN) + if (!isfinite (x)) return (x); -#endif if (x >= 0.0) { diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c index 04361345ffb..c1bf78eca3e 100644 --- a/libgfortran/io/write.c +++ b/libgfortran/io/write.c @@ -821,9 +821,6 @@ write_float (fnode *f, const char *source, int len) 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) { diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h index 54aca7e66bc..191d8d48070 100644 --- a/libgfortran/libgfortran.h +++ b/libgfortran/libgfortran.h @@ -177,13 +177,33 @@ typedef off_t gfc_offset; When isfinite is not available, try to use one of the alternatives, or bail out. */ -#if (!defined(isfinite) || defined(__CYGWIN__)) + +#if defined(HAVE_BROKEN_ISFINITE) || defined(__CYGWIN__) #undef isfinite -#if defined(fpclassify) +#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 isfinite(x) ((x) - (x) == 0) -#endif +#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. */ |