[PATCH] Enforce GMP/MPFR version requires and fix fortran/28276,27021
Paul Thomas
paulthomas2@wanadoo.fr
Wed Sep 13 04:24:00 GMT 2006
Steve,
OK for the fortran specific bits and the tests; as Mark says, you need
to get approval for the top level stuff from a build maintainer.
This patch applied cleanly and regtested fine on FC5/Athlon and
gmp-4.2/mpfr-2.2.0
Paul
>2006-09-12 Steven G. Kargl <kargl@gcc.gnu.org>
>
> * configure.in: Check for GMP 4.1 or newer. Check for MPFR 2.2.0
> or newer.
> * configure: Regenerated.
> * doc/install.texi: Document required versions of GMP and MPFR.
> * fortran/arith.c (arctangent2): Conditionally include code.
> (gfc_check_real_range): Use mpfr_subnormalize in preference to local
> hack.
> * fortran/simplify.c: Wrap Copyright to new line.
> (gfc_simplify_atan2): Use mpfr_atan2 in preference to arctangent2().
> (gfc_simplify_log): Ditto.
>
>
> PR fortran/28276
> * fortran/simplify.c (gfc_simplify_exponent): Use mpfr_get_exp in
> preference to broken local hack.
> * fortran/trans-intrinsic.c (gfc_get_intrinsic_lib_fndecl): Append
> l for long double functions.
>
> PR fortran/27021
> * fortran/simplify.c (gfc_simplify_nearest): Use mpfr_nexttoward and
> mpfr_subnormalize to handle numbers near zero in preference to broken
> local hack.
>
> PR fortran/28276
> * testsuite/gfortran.dg/exponent_1.f90: New test.
>
> PR fortran/27021
> * testsuite/gfortran.dg/nearest_1.f90: New test.
>
>
>
>------------------------------------------------------------------------
>
>Index: gcc/doc/install.texi
>===================================================================
>--- gcc/doc/install.texi (revision 116905)
>+++ gcc/doc/install.texi (working copy)
>@@ -290,17 +290,20 @@ Necessary (only on some platforms) to un
> systems' @command{tar} programs will also work, only try GNU
> @command{tar} if you have problems.
>
>-@item GNU Multiple Precision Library (GMP) version 4.0 (or later)
>+@item GNU Multiple Precision Library (GMP) version 4.1 (or later)
>
>-Necessary to build the Fortran frontend. If you don't have it
>+Necessary to build the Fortran frontend. If you do not have it
> installed in your library search path, you will have to configure with
> the @option{--with-gmp} or @option{--with-gmp-dir} configure option.
>
>-@item MPFR Library
>+@item MPFR Library version 2.2 (or later)
>
> Necessary to build the Fortran frontend. It can be downloaded from
>-@uref{http://www.mpfr.org/}. It is also included in the current GMP
>-release (4.1.3) when configured with @option{--enable-mpfr}.
>+@uref{http://www.mpfr.org/}. The version of MPFR that is bundled with
>+GMP 4.1.x contains numerous bugs. Although gfortran will appear
>+to function with the buggy verions of MPFR, there are few gfortran bugs
>+that will not be fixed to use this version. It is strongly
>+recommended to upgrade to at least MPFR version 2.2.
>
> The @option{--with-mpfr} or @option{--with-mpfr-dir} configure option should
> be used if your MPFR Library is not installed in your library search path.
>Index: gcc/fortran/arith.c
>===================================================================
>--- gcc/fortran/arith.c (revision 116905)
>+++ gcc/fortran/arith.c (working copy)
>@@ -75,6 +75,7 @@ gfc_set_model (mpfr_t x)
> mpfr_set_default_prec (mpfr_get_prec (x));
> }
>
>+#if !defined(MPFR_VERSION_MAJOR)
> /* Calculate atan2 (y, x)
>
> atan2(y, x) = atan(y/x) if x > 0,
>@@ -124,7 +125,7 @@ arctangent2 (mpfr_t y, mpfr_t x, mpfr_t
>
> mpfr_clear (t);
> }
>-
>+#endif
>
> /* Given an arithmetic error code, return a pointer to a string that
> explains the error. */
>@@ -407,6 +408,7 @@ gfc_check_real_range (mpfr_t p, int kind
> }
> else if (mpfr_cmp (q, gfc_real_kinds[i].tiny) < 0)
> {
>+#if !defined(MPFR_VERSION_MAJOR)
> /* MPFR operates on a number with a given precision and enormous
> exponential range. To represent subnormal numbers, the exponent is
> allowed to become smaller than emin, but always retains the full
>@@ -428,13 +430,30 @@ gfc_check_real_range (mpfr_t p, int kind
> sprintf (s, "0.%sE%d", bin, (int) e);
> mpfr_set_str (q, s, gfc_real_kinds[i].radix, GMP_RNDN);
>
>+ gfc_free (s);
>+ gfc_free (bin);
>+#else
>+ mp_exp_t emin, emax;
>+
>+ /* Save current values of emin and emax. */
>+ emin = mpfr_get_emin ();
>+ emax = mpfr_get_emax ();
>+
>+ /* Set emin and emax for the current model number. */
>+ mpfr_set_emin ((mp_exp_t) gfc_real_kinds[i].min_exponent - 1);
>+ mpfr_set_emax ((mp_exp_t) gfc_real_kinds[i].max_exponent - 1);
>+ mpfr_subnormalize (q, 0, GFC_RND_MODE);
>+
>+ /* Reset emin and emax. */
>+ mpfr_set_emin (emin);
>+ mpfr_set_emax (emax);
>+#endif
>+
>+ /* Copy sign if needed. */
> if (mpfr_sgn (p) < 0)
> mpfr_neg (p, q, GMP_RNDN);
> else
> mpfr_set (p, q, GMP_RNDN);
>-
>- gfc_free (s);
>- gfc_free (bin);
>
> retval = ARITH_OK;
> }
>Index: gcc/fortran/trans-intrinsic.c
>===================================================================
>--- gcc/fortran/trans-intrinsic.c (revision 116905)
>+++ gcc/fortran/trans-intrinsic.c (working copy)
>@@ -590,12 +590,18 @@ gfc_get_intrinsic_lib_fndecl (gfc_intrin
>
> if (m->libm_name)
> {
>- gcc_assert (ts->kind == 4 || ts->kind == 8 || ts->kind == 10
>- || ts->kind == 16);
>- snprintf (name, sizeof (name), "%s%s%s",
>- ts->type == BT_COMPLEX ? "c" : "",
>- m->name,
>- ts->kind == 4 ? "f" : "");
>+ if (ts->kind == 4)
>+ snprintf (name, sizeof (name), "%s%s%s",
>+ ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
>+ else if (ts->kind == 8)
>+ snprintf (name, sizeof (name), "%s%s",
>+ ts->type == BT_COMPLEX ? "c" : "", m->name);
>+ else
>+ {
>+ gcc_assert (ts->kind == 10 || ts->kind == 16);
>+ snprintf (name, sizeof (name), "%s%s%s",
>+ ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
>+ }
> }
> else
> {
>Index: gcc/fortran/simplify.c
>===================================================================
>--- gcc/fortran/simplify.c (revision 116905)
>+++ gcc/fortran/simplify.c (working copy)
>@@ -1,6 +1,6 @@
> /* Simplify intrinsic functions at compile-time.
>- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
>- Foundation, Inc.
>+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
>+ Free Software Foundation, Inc.
> Contributed by Andy Vaught & Katherine Holcomb
>
> This file is part of GCC.
>@@ -607,7 +607,11 @@ gfc_simplify_atan2 (gfc_expr * y, gfc_ex
> return &gfc_bad_expr;
> }
>
>+#if !defined(MPFR_VERSION_MAJOR)
> arctangent2 (y->value.real, x->value.real, result->value.real);
>+#else
>+ mpfr_atan2 (result->value.real, y->value.real, x->value.real, GFC_RND_MODE);
>+#endif
>
> return range_check (result, "ATAN2");
> }
>@@ -1054,9 +1058,12 @@ gfc_expr *
> gfc_simplify_exponent (gfc_expr * x)
> {
> int i;
>- mpfr_t tmp;
> gfc_expr *result;
>
>+#if !defined(MPFR_VERSION_MAJOR)
>+ mpfr_t tmp;
>+#endif
>+
> if (x->expr_type != EXPR_CONSTANT)
> return NULL;
>
>@@ -1071,6 +1078,9 @@ gfc_simplify_exponent (gfc_expr * x)
> return result;
> }
>
>+#if !defined(MPFR_VERSION_MAJOR)
>+ /* PR fortran/28276 suffers from a buggy MPFR, and this block of code
>+ does not function correctly. */
> mpfr_init (tmp);
>
> mpfr_abs (tmp, x->value.real, GFC_RND_MODE);
>@@ -1085,6 +1095,11 @@ gfc_simplify_exponent (gfc_expr * x)
> mpz_add_ui (result->value.integer,result->value.integer, 1);
>
> mpfr_clear (tmp);
>+#else
>+ /* Requires MPFR 2.2.0 or newer. */
>+ i = (int) mpfr_get_exp (x->value.real);
>+ mpz_set_si (result->value.integer, i);
>+#endif
>
> return range_check (result, "EXPONENT");
> }
>@@ -2146,8 +2161,13 @@ gfc_simplify_log (gfc_expr * x)
> mpfr_init (xr);
> mpfr_init (xi);
>
>- arctangent2 (x->value.complex.i, x->value.complex.r,
>- result->value.complex.i);
>+#if !defined(MPFR_VERSION_MAJOR)
>+ arctangent2 (x->value.complex.i, x->value.complex.r, result->value.complex.i);
>+#else
>+ mpfr_atan2 (result->value.complex.i, x->value.complex.i, x->value.complex.r,
>+ GFC_RND_MODE);
>+#endif
>+
>
> mpfr_mul (xr, x->value.complex.r, x->value.complex.r, GFC_RND_MODE);
> mpfr_mul (xi, x->value.complex.i, x->value.complex.i, GFC_RND_MODE);
>@@ -2474,27 +2494,28 @@ gfc_simplify_nearest (gfc_expr * x, gfc_
> {
> gfc_expr *result;
> mpfr_t tmp;
>- int direction, sgn;
>+ int sgn;
>+#if !defined(MPFR_VERSION_MAJOR)
>+ int direction;
>+#else
>+ mp_exp_t emin, emax;
>+#endif
>
> if (x->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT)
> return NULL;
>
>- gfc_set_model_kind (x->ts.kind);
>- result = gfc_copy_expr (x);
>-
>- direction = mpfr_sgn (s->value.real);
>-
>- if (direction == 0)
>+ if (mpfr_sgn (s->value.real) == 0)
> {
>- gfc_error ("Second argument of NEAREST at %L may not be zero",
>- &s->where);
>- gfc_free (result);
>+ gfc_error ("Second argument of NEAREST at %L shall not be zero", &s->where);
> return &gfc_bad_expr;
> }
>
>- /* TODO: Use mpfr_nextabove and mpfr_nextbelow once we move to a
>- newer version of mpfr. */
>+ gfc_set_model_kind (x->ts.kind);
>+ result = gfc_copy_expr (x);
>+
>+#if !defined(MPFR_VERSION_MAJOR)
>
>+ direction = mpfr_sgn (s->value.real);
> sgn = mpfr_sgn (x->value.real);
>
> if (sgn == 0)
>@@ -2539,6 +2560,28 @@ gfc_simplify_nearest (gfc_expr * x, gfc_
> if (sgn < 0)
> mpfr_neg (result->value.real, result->value.real, GFC_RND_MODE);
> }
>+#else
>+
>+ /* Save current values of emin and emax. */
>+ emin = mpfr_get_emin ();
>+ emax = mpfr_get_emax ();
>+
>+ /* Set emin and emax for the current model number. */
>+ sgn = gfc_validate_kind (BT_REAL, x->ts.kind, 0);
>+ mpfr_set_emin ((mp_exp_t) gfc_real_kinds[sgn].min_exponent - 1);
>+ mpfr_set_emax ((mp_exp_t) gfc_real_kinds[sgn].max_exponent - 1);
>+
>+ sgn = mpfr_sgn (s->value.real);
>+ mpfr_init (tmp);
>+ mpfr_set_inf (tmp, sgn);
>+ mpfr_nexttoward (result->value.real, tmp);
>+ mpfr_subnormalize (result->value.real, 0, GFC_RND_MODE);
>+
>+ mpfr_set_emin (emin);
>+ mpfr_set_emax (emax);
>+
>+ mpfr_clear(tmp);
>+#endif
>
> return range_check (result, "NEAREST");
> }
>Index: configure.in
>===================================================================
>--- configure.in (revision 116905)
>+++ configure.in (working copy)
>@@ -1103,17 +1103,23 @@ CFLAGS="$CFLAGS $gmpinc"
> # Check GMP actually works
> AC_MSG_CHECKING([for correct version of gmp.h])
> AC_TRY_COMPILE([#include "gmp.h"],[
>-#if __GNU_MP_VERSION < 3
>+#if __GNU_MP_VERSION < 4 || (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR < 1)
> choke me
> #endif
>-], [AC_MSG_RESULT([yes])],
>- [AC_MSG_RESULT([no]); have_gmp=no])
>+], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); have_gmp=no])
>
> if test x"$have_gmp" = xyes; then
>- AC_MSG_CHECKING([for MPFR])
>+ AC_MSG_CHECKING([for correct version of mpfr.h])
>+ AC_TRY_COMPILE([#include "gmp.h"
>+#include <mpfr.h>],[
>+#if MPFR_VERSION_MAJOR < 2 || (MPFR_VERSION_MAJOR == 2 && MPFR_VERSION_MINOR < 2)
>+ choke me
>+#endif
>+], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([buggy version of MPFR detected])])
>
> saved_LIBS="$LIBS"
> LIBS="$LIBS $gmplibs"
>+ AC_MSG_CHECKING([for any version of mpfr.h])
> AC_TRY_LINK([#include <gmp.h>
> #include <mpfr.h>], [mpfr_t n; mpfr_init(n);],
> [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); have_gmp=no])
>@@ -1258,7 +1264,7 @@ if test -d ${srcdir}/gcc; then
> case ,${enable_languages},:${have_gmp}:${need_gmp} in
> *,${language},*:no:yes)
> # Specifically requested language; tell them.
>- AC_MSG_ERROR([GMP with MPFR support is required to build $language])
>+ AC_MSG_ERROR([GMP 4.1 and MPFR 2.2 or newer versions required by $language])
> ;;
> *:no:yes)
> # Silently disable.
>
>
More information about the Fortran
mailing list