This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Require GMP 4.2 and MPFR 2.2
On Sun, May 14, 2006 at 07:37:35PM -0600, Roger Sayle wrote:
>
> Hi Steve,
>
> On Sun, 14 May 2006, Steve Kargl wrote:
> > I withdraw the patch. It and my patches that require MPFR 2.2.0
> > will be carried forward in my local tree. gfortran can't afford
> > alienating middle and back end developers, who will simply stop
> > testing their changes with gfortran.
>
> Is there any chance you could post your local patches that require
> MPFR 2.2 to the fortran and/or gcc-patches list? I'm curious to
> see how you propose to use the new subnormal functionality, atan2
> implementation, etc... I think these are all good reasons to upgrade
> MPFR (and pre-requisites should the middle-end decide to use
> MPFR itself), but it might be possible to utilize autoconf's HAVE_
> macros to reach a compromise whereby we make use of the fixed
> and extended functionality where available, without completely
> sacrificing the existing gfortran 4.1/4.2 functionality on systems
> that haven't yet upgraded.
>
> Perhaps such a compromise is impossible, as your intended changes
> are significantly invasive, but without learning more about your
> plans its difficult for folks to appreciate the costs vs. benefits.
The compromise would require "#ifdef MPFR_VERSION >= 2" type
preprocessing directives in the code. This would mean that
the configure.in patch probably isn't needed. However, the
inertia of several linux distributions lack of upgrading
gmp and mpfr would continue because there will be no reason
to upgrade.
Here's the patch. It may not apply cleanly because I removed
some cosmetic changes (ie., whitespace fixes).
Index: arith.c
===================================================================
--- arith.c (revision 113737)
+++ arith.c (working copy)
@@ -1,6 +1,6 @@
/* Compiler arithmetic
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation,
- Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Andy Vaught
This file is part of GCC.
@@ -20,9 +20,9 @@ along with GCC; see the file COPYING. I
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
-/* Since target arithmetic must be done on the host, there has to
- be some way of evaluating arithmetic expressions as the host
- would evaluate them. We use the GNU MP library to do arithmetic,
+/* Since target arithmetic must be done on the host, there has to be
+ some way of evaluating arithmetic expressions as the host would
+ evaluate them. We use GMP and MPFR libraries to do arithmetic,
and this file provides the interface. */
#include "config.h"
@@ -75,57 +75,6 @@ gfc_set_model (mpfr_t x)
mpfr_set_default_prec (mpfr_get_prec (x));
}
-/* Calculate atan2 (y, x)
-
-atan2(y, x) = atan(y/x) if x > 0,
- sign(y)*(pi - atan(|y/x|)) if x < 0,
- 0 if x = 0 && y == 0,
- sign(y)*pi/2 if x = 0 && y != 0.
-*/
-
-void
-arctangent2 (mpfr_t y, mpfr_t x, mpfr_t result)
-{
- int i;
- mpfr_t t;
-
- gfc_set_model (y);
- mpfr_init (t);
-
- i = mpfr_sgn (x);
-
- if (i > 0)
- {
- mpfr_div (t, y, x, GFC_RND_MODE);
- mpfr_atan (result, t, GFC_RND_MODE);
- }
- else if (i < 0)
- {
- mpfr_const_pi (result, GFC_RND_MODE);
- mpfr_div (t, y, x, GFC_RND_MODE);
- mpfr_abs (t, t, GFC_RND_MODE);
- mpfr_atan (t, t, GFC_RND_MODE);
- mpfr_sub (result, result, t, GFC_RND_MODE);
- if (mpfr_sgn (y) < 0)
- mpfr_neg (result, result, GFC_RND_MODE);
- }
- else
- {
- if (mpfr_sgn (y) == 0)
- mpfr_set_ui (result, 0, GFC_RND_MODE);
- else
- {
- mpfr_const_pi (result, GFC_RND_MODE);
- mpfr_div_ui (result, result, 2, GFC_RND_MODE);
- if (mpfr_sgn (y) < 0)
- mpfr_neg (result, result, GFC_RND_MODE);
- }
- }
-
- mpfr_clear (t);
-
-}
-
@@ -330,6 +278,7 @@ gfc_arith_done_1 (void)
{
mpfr_clear (rp->epsilon);
mpfr_clear (rp->huge);
+ mpfr_clear (rp->subnormal);
mpfr_clear (rp->tiny);
}
}
@@ -362,16 +311,16 @@ gfc_check_integer_range (mpz_t p, int ki
}
-/* Given a real and a kind, make sure that the real lies within the
- range of the kind. Returns ARITH_OK, ARITH_OVERFLOW or
- ARITH_UNDERFLOW. */
+/* Given a real and a kind, make sure that the real lies within the range
+ of the kind. Returns ARITH_OK, ARITH_OVERFLOW or ARITH_UNDERFLOW. */
static arith
gfc_check_real_range (mpfr_t p, int kind)
{
+ int i;
arith retval;
mpfr_t q;
- int i;
+ mp_exp_t emin, emax;
i = gfc_validate_kind (BT_REAL, kind, false);
@@ -387,34 +336,19 @@ gfc_check_real_range (mpfr_t p, int kind
retval = ARITH_UNDERFLOW;
else if (mpfr_cmp (q, gfc_real_kinds[i].tiny) < 0)
{
- /* MPFR operates on a numbers 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
- precision. This function resets unused bits to 0 to alleviate
- rounding problems. Note, a future version of MPFR will have a
- mpfr_subnormalize() function, which handles this truncation in a
- more efficient and robust way. */
-
- int j, k;
- char *bin, *s;
- mp_exp_t e;
-
- bin = mpfr_get_str (NULL, &e, gfc_real_kinds[i].radix, 0, q, GMP_RNDN);
- k = gfc_real_kinds[i].digits - (gfc_real_kinds[i].min_exponent - e);
- for (j = k; j < gfc_real_kinds[i].digits; j++)
- bin[j] = '0';
- /* Need space for '0.', bin, 'E', and e */
- s = (char *) gfc_getmem (strlen(bin)+10);
- sprintf (s, "0.%sE%d", bin, (int) e);
- mpfr_set_str (q, s, gfc_real_kinds[i].radix, GMP_RNDN);
-
- if (mpfr_sgn (p) < 0)
- mpfr_neg (p, q, GMP_RNDN);
- else
- mpfr_set (p, q, GMP_RNDN);
-
- gfc_free (s);
- gfc_free (bin);
+ /* 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 (p, 0, GFC_RND_MODE);
+
+ /* Reset emin and emax. */
+ mpfr_set_emin (emin);
+ mpfr_set_emax (emax);
retval = ARITH_OK;
}
Index: arith.h
===================================================================
--- arith.h (revision 113737)
+++ arith.h (working copy)
@@ -1,5 +1,5 @@
/* Compiler arithmetic header.
- Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2004, 2006 Free Software Foundation, Inc.
Contributed by Steven Bosscher
This file is part of GCC.
@@ -24,11 +24,9 @@ Software Foundation, 51 Franklin Street,
#include "gfortran.h"
-/* MPFR does not have mpfr_atan2(), which needs to return the principle
- value of atan2(). MPFR also does not have the conversion of a mpfr_t
- to a mpz_t, so declare a function for this as well. */
+/* MPFR does not have the conversion of a mpfr_t to a mpz_t, so declare
+ a function for this as well. */
-void arctangent2 (mpfr_t, mpfr_t, mpfr_t);
void gfc_mpfr_to_mpz(mpz_t, mpfr_t);
void gfc_set_model_kind (int);
void gfc_set_model (mpfr_t);
Index: simplify.c
===================================================================
--- simplify.c (revision 113737)
+++ 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.
@@ -588,7 +588,7 @@ gfc_simplify_atan2 (gfc_expr * y, gfc_ex
return &gfc_bad_expr;
}
- arctangent2 (y->value.real, x->value.real, result->value.real);
+ mpfr_atan2 (result->value.real, y->value.real, x->value.real, GFC_RND_MODE);
return range_check (result, "ATAN2");
}
@@ -2067,8 +2067,8 @@ 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);
+ mpfr_atan2 (result->value.complex.i, x->value.complex.i,
+ x->value.complex.r, GFC_RND_MODE);
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);
@@ -2395,71 +2395,42 @@ gfc_simplify_nearest (gfc_expr * x, gfc_
{
gfc_expr *result;
mpfr_t tmp;
- int direction, sgn;
+ int sgn;
+ mp_exp_t emin, emax;
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. */
-
- sgn = mpfr_sgn (x->value.real);
-
- if (sgn == 0)
- {
- int k = gfc_validate_kind (BT_REAL, x->ts.kind, 0);
-
- if (direction > 0)
- mpfr_add (result->value.real,
- x->value.real, gfc_real_kinds[k].subnormal, GFC_RND_MODE);
- else
- mpfr_sub (result->value.real,
- x->value.real, gfc_real_kinds[k].subnormal, GFC_RND_MODE);
- }
- else
- {
- if (sgn < 0)
- {
- direction = -direction;
- mpfr_neg (result->value.real, result->value.real, GFC_RND_MODE);
- }
+ gfc_set_model_kind (x->ts.kind);
- if (direction > 0)
- mpfr_add_one_ulp (result->value.real, GFC_RND_MODE);
- else
- {
- /* In this case the exponent can shrink, which makes us skip
- over one number because we subtract one ulp with the
- larger exponent. Thus we need to compensate for this. */
- mpfr_init_set (tmp, result->value.real, GFC_RND_MODE);
+ sgn = gfc_validate_kind (BT_REAL, x->ts.kind, 0);
- mpfr_sub_one_ulp (result->value.real, GFC_RND_MODE);
- mpfr_add_one_ulp (result->value.real, GFC_RND_MODE);
+ result = gfc_copy_expr (x);
+
+ /* 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[sgn].min_exponent - 1);
+ mpfr_set_emax ((mp_exp_t) gfc_real_kinds[sgn].max_exponent - 1);
- /* If we're back to where we started, the spacing is one
- ulp, and we get the correct result by subtracting. */
- if (mpfr_cmp (tmp, result->value.real) == 0)
- mpfr_sub_one_ulp (result->value.real, GFC_RND_MODE);
+ 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_clear (tmp);
- }
+ mpfr_set_emin (emin);
+ mpfr_set_emax (emax);
- if (sgn < 0)
- mpfr_neg (result->value.real, result->value.real, GFC_RND_MODE);
- }
+ mpfr_clear(tmp);
return range_check (result, "NEAREST");
}
--
Steve