Commit e48d66a9 by Steven G. Kargl

re PR fortran/28276 (EXPONENT() broken for real constants)

	* 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: Conditionally include arctangent2().
	(gfc_check_real_range): Use mpfr_subnormalize in preference to local
	hack.
	* fortran/trans-intrinsic.c (gfc_get_intrinsic_lib_fndecl): Append
	l for long double functions.
	* 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.

	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.

From-SVN: r117257
parent c394e891
2006-09-27 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.
2006-09-27 Dave Brolley <brolley@redhat.com>
* configure.in (RUNTEST): Look for 'runtest' in the source tree by using
......
......@@ -1097,17 +1097,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])
......@@ -1252,7 +1258,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.
......
2006-09-27 Steven G. Kargl <kargl@gcc.gnu.org>
* doc/install.texi: Document required versions of GMP and MPFR.
2006-09-27 Paul Brook <paul@codesourcery.com>
PR target/29230
......
......@@ -290,17 +290,20 @@ Necessary (only on some platforms) to untar the source code. Many
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.
......
2006-09-27 Steven G. Kargl <kargl@gcc.gnu.org>
* arith.c: Conditionally include arctangent2().
(gfc_check_real_range): Use mpfr_subnormalize in preference to local
hack.
* trans-intrinsic.c (gfc_get_intrinsic_lib_fndecl): Append
l for long double functions.
* simplify.c: Wrap Copyright to new line.
(gfc_simplify_atan2): Use mpfr_atan2 in preference to arctangent2().
(gfc_simplify_log): Ditto.
PR fortran/28276
* simplify.c (gfc_simplify_exponent): Use mpfr_get_exp in
preference to broken local hack.
PR fortran/27021
* simplify.c (gfc_simplify_nearest): Use mpfr_nexttoward and
mpfr_subnormalize to handle numbers near zero in preference to broken
local hack.
2006-09-26 Jakub Jelinek <jakub@redhat.com>
PR fortran/29097
......
......@@ -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 result)
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,14 +430,31 @@ 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;
}
else
......
/* 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_expr * x)
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_expr * s)
{
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_expr * s)
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");
}
......
......@@ -590,12 +590,18 @@ gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
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
{
......
2006-09-27 Steven G. Kargl <kargls@gcc.gnu.org>
PR fortran/28276
* gfortran.dg/exponent_1.f90: New test.
PR fortran/27021
* gfortran.dg/nearest_1.f90: New test.
2006-09-26 Jakub Jelinek <jakub@redhat.com>
PR middle-end/25261
! { dg-do run }
! PR fortran/28276
! Original code submitted by Harald Anlauf
! Converted to Dejagnu for the testsuite by Steven G. Kargl
!
program gfcbug36
implicit none
real, parameter :: one = 1.0
real :: a = one
if (fraction(a) /= 0.5) call abort
if (fraction(one) /= 0.5) call abort
if (fraction(1.0) /= 0.5) call abort
if (exponent(a) /= 1.0) call abort
if (exponent(one) /= 1.0) call abort
if (exponent (1.0) /= 1.0) call abort
if (scale(fraction(a), exponent(a)) / a /= 1.) call abort
if (scale(fraction(one), exponent(one)) / one /= 1.) call abort
if (scale(fraction(1.0), exponent(1.0)) / 1.0 /= 1.) call abort
end program gfcbug36
! { dg-do run }
! PR fortran/27021
! Original code submitted by Dominique d'Humieres
! Converted to Dejagnu for the testsuite by Steven G. Kargl
program chop
real o, t, td, tu, x, y
o = 1.
t = tiny(o)
td = nearest(t,-1.0)
x = td/2.0
y = nearest(tiny(o),-1.0)/2.0
if (abs(x - y) /= 0.) call abort
end program chop
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment