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]

[2/4] [patch, middle-end] Consolidate GCC, GFortran MPFR-to-tree functions.


Both GFortran and GCC have functions to convert a MPFR float to a REAL_VALUE_TYPE representation. This patch adjusts the GCC version to have all the functionality needed by GFortran (specifically, a caller-specified rounding mode, and handling for Inf and NaN values copied in from the GFortran implementation in fortran/trans-const.c), so that the GFortran version can be replaced by a call to the GCC version in part 4. Doing this adds some additional arguments to the function calls, and so the prototypes and existing uses of the functions also need to be updated.

---------------------------------------------------------------------
2007-04-06  Brooks Moses  <brooks.moses@codesourcery.com>

	real.c (mpfr_from_real): Handle Inf and NaN, and allow the
	rounding mode to be specified by the caller.
	(real_to_mpfr) Likewise.
	real.h: Update mpfr_from_real, mpfr_to_real prototypes to
	include new arguments.
	builtins.c: Update mpfr_from_real, mpfr_to_real calls.

---------------------------------------------------------------------

Tested with a bootstrap and "make check-gcc" on i686-pc-linux-gnu. Ok for trunk?

- Brooks
Index: real.c
===================================================================
--- real.c	(revision 123513)
+++ real.c	(working copy)
@@ -4991,30 +4991,59 @@
    for initializing and clearing the MPFR parameter.  */
 
 void
-mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r)
+mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode)
 {
   /* We use a string as an intermediate type.  */
   char buf[128];
   int ret;
 
+  /* Take care of Infinity and NaN.  */
+  if (r->cl == rvc_inf)
+    {
+      mpfr_set_inf(m, r->sign);
+      return;
+    }
+  
+  if (r->cl == rvc_nan)
+    {
+      mpfr_set_nan(m);
+      return;
+    }
+  
   real_to_hexadecimal (buf, r, sizeof (buf), 0, 1);
   /* mpfr_set_str() parses hexadecimal floats from strings in the same
      format that GCC will output them.  Nothing extra is needed.  */
-  ret = mpfr_set_str (m, buf, 16, GMP_RNDN);
+  ret = mpfr_set_str (m, buf, 16, rndmode);
   gcc_assert (ret == 0);
 }
 
-/* Convert from MPFR to REAL_VALUE_TYPE.  */
+/* Convert from MPFR to REAL_VALUE_TYPE, for a given type TYPE and rounding
+   mode RNDMODE.  TYPE is only relevant if M is a NaN.  */
 
 void
-real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m)
+real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type, mp_rnd_t rndmode)
 {
   /* We use a string as an intermediate type.  */
   char buf[128], *rstr;
   mp_exp_t exp;
 
-  rstr = mpfr_get_str (NULL, &exp, 16, 0, m, GMP_RNDN);
+  /* Take care of Infinity and NaN.  */
+  if (mpfr_inf_p (m))
+    {
+      real_inf (r);
+      if (mpfr_sgn (m) < 0)
+	*r = REAL_VALUE_NEGATE(*r);
+      return;
+    }
 
+  if (mpfr_nan_p (m))
+    {
+      real_nan (r, "", 0, TYPE_MODE (type));
+      return;
+    }
+
+  rstr = mpfr_get_str (NULL, &exp, 16, 0, m, rndmode);
+
   /* The additional 12 chars add space for the sprintf below.  This
      leaves 6 digits for the exponent which is supposedly enough.  */
   gcc_assert (rstr != NULL && strlen (rstr) < sizeof (buf) - 12);
Index: real.h
===================================================================
--- real.h	(revision 123513)
+++ real.h	(working copy)
@@ -434,8 +434,8 @@
 /* Convert between MPFR and REAL_VALUE_TYPE.  The caller is
    responsible for initializing and clearing the MPFR parameter.  */
 
-extern void real_from_mpfr (REAL_VALUE_TYPE *, mpfr_srcptr);
-extern void mpfr_from_real (mpfr_ptr, const REAL_VALUE_TYPE *);
+extern void real_from_mpfr (REAL_VALUE_TYPE *, mpfr_srcptr, tree, mp_rnd_t);
+extern void mpfr_from_real (mpfr_ptr, const REAL_VALUE_TYPE *, mp_rnd_t);
 
 /* Check whether the real constant value given is an integer.  */
 extern bool real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode);
Index: builtins.c
===================================================================
--- builtins.c	(revision 123513)
+++ builtins.c	(working copy)
@@ -12201,7 +12201,7 @@
     {
       REAL_VALUE_TYPE rr;
 
-      real_from_mpfr (&rr, m);
+      real_from_mpfr (&rr, m, type, GMP_RNDN);
       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
 	 check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
 	 but the mpft_t is not, then we underflowed in the
@@ -12254,7 +12254,7 @@
 	  mpfr_t m;
 
 	  mpfr_init2 (m, prec);
-	  mpfr_from_real (m, ra);
+	  mpfr_from_real (m, ra, GMP_RNDN);
 	  mpfr_clear_flags ();
 	  inexact = func (m, m, GMP_RNDN);
 	  result = do_mpfr_ckconv (m, type, inexact);
@@ -12297,8 +12297,8 @@
 	  mpfr_t m1, m2;
 
 	  mpfr_inits2 (prec, m1, m2, NULL);
-	  mpfr_from_real (m1, ra1);
-	  mpfr_from_real (m2, ra2);
+	  mpfr_from_real (m1, ra1, GMP_RNDN);
+	  mpfr_from_real (m2, ra2, GMP_RNDN);
 	  mpfr_clear_flags ();
 	  inexact = func (m1, m1, m2, GMP_RNDN);
 	  result = do_mpfr_ckconv (m1, type, inexact);
@@ -12345,9 +12345,9 @@
 	  mpfr_t m1, m2, m3;
 
 	  mpfr_inits2 (prec, m1, m2, m3, NULL);
-	  mpfr_from_real (m1, ra1);
-	  mpfr_from_real (m2, ra2);
-	  mpfr_from_real (m3, ra3);
+	  mpfr_from_real (m1, ra1, GMP_RNDN);
+	  mpfr_from_real (m2, ra2, GMP_RNDN);
+	  mpfr_from_real (m3, ra3, GMP_RNDN);
 	  mpfr_clear_flags ();
 	  inexact = func (m1, m1, m2, m3, GMP_RNDN);
 	  result = do_mpfr_ckconv (m1, type, inexact);
@@ -12389,7 +12389,7 @@
 	  mpfr_t m, ms, mc;
 
 	  mpfr_inits2 (prec, m, ms, mc, NULL);
-	  mpfr_from_real (m, ra);
+	  mpfr_from_real (m, ra, GMP_RNDN);
 	  mpfr_clear_flags ();
 	  inexact = mpfr_sin_cos (ms, mc, m, GMP_RNDN);
 	  result_s = do_mpfr_ckconv (ms, type, inexact);

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