diff options
author | Steven G. Kargl <kargl@gcc.gnu.org> | 2006-09-27 20:15:22 +0000 |
---|---|---|
committer | Steven G. Kargl <kargl@gcc.gnu.org> | 2006-09-27 20:15:22 +0000 |
commit | e48d66a949a0ea367bb3df15df5f345f46184d9f (patch) | |
tree | 3792a732440b9bb02382ecb8b58e6ed8d955c8f9 /gcc | |
parent | c394e8918d7d752d9f8a6aba037ab6c7647ab483 (diff) | |
download | gcc-e48d66a949a0ea367bb3df15df5f345f46184d9f.zip gcc-e48d66a949a0ea367bb3df15df5f345f46184d9f.tar.gz gcc-e48d66a949a0ea367bb3df15df5f345f46184d9f.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/doc/install.texi | 13 | ||||
-rw-r--r-- | gcc/fortran/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/fortran/arith.c | 27 | ||||
-rw-r--r-- | gcc/fortran/simplify.c | 77 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/exponent_1.f90 | 23 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/nearest_1.f90 | 14 |
9 files changed, 173 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 856bcb2..0e16018 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +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 diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index fa15835..66ec7ca 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -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. diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e6860a6..08de524 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,24 @@ +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 diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c index 766169f..53f1262 100644 --- a/gcc/fortran/arith.c +++ b/gcc/fortran/arith.c @@ -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 diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index 48d8e6b..c448db6 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -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_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"); } diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index cef767d..facc15a 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -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 { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 836f236..715e252 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +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 diff --git a/gcc/testsuite/gfortran.dg/exponent_1.f90 b/gcc/testsuite/gfortran.dg/exponent_1.f90 new file mode 100644 index 0000000..9f701e8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/exponent_1.f90 @@ -0,0 +1,23 @@ +! { 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 diff --git a/gcc/testsuite/gfortran.dg/nearest_1.f90 b/gcc/testsuite/gfortran.dg/nearest_1.f90 new file mode 100644 index 0000000..a5ece0f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nearest_1.f90 @@ -0,0 +1,14 @@ +! { 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 + |