This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Enforce GMP/MPFR version requires and fix fortran/28276,27021


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.




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]