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


PING.  PING.

If no one reviews the toplevel changes within the next few
days, I will commit the changes under the implicitly approved
rule.

steve

On Tue, Sep 12, 2006 at 02:20:27PM -0700, Steve Kargl wrote:
> The attached patch has been tested on amd64-*-freebsd, and it
> should only impact gfortran.  However, the patch does touch
> the toplevel configure.in, and hence, configure.
> 
> markm, I cc'd you because of the pending branching of 4.2 and
> the fact I touch configure.in.  If you prefer that I hold the
> patch until after the branching, I can do so.
> 
> The patch causes configure to check that the version of 
> GMP is 4.1 or newer and that MPFR is version 2.2.0 or
> newer.  For older versions of GMP, configure will die.
> For older versions of MPFR, configure simply checks that
> any version of MPFR is available.  If no version of
> MPFR is available, configure will die.  If an older version
> of MPFR is found, it will be used; however, several known
> problems with older MPFRs prevent the bug fixes for PR
> fortran/28276 and fortran/27021 from functioning (ie.,
> the old buggy gfortran code is still used).
> 
> This patch also removes the local hacks for handling subnormal
> numbers and the folding of atan2().  Again, if an older version
> of MPFR is found, the old buggy gfortran code is used.
> 
> 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.
> 
> -- 
> Steve

> 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.


-- 
Steve


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