This is the mail archive of the 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]

rs6000 LDBL_MAX converts to infinity

This patch corrects a problem with -mlong-double-128 on powerpc*-linux,
where converting numbers some delta larger than DBL_MAX but smaller
than LDBL_MAX results in infinity. touched this
area, with Richard noting

> While there, I noticed that the code didn't deal correctly with normal
> values of the form 0x1.FFFFFFFFFFFFFx....P1023, where the high bit of "x"
> is set.  The high part double will round to infinity, and so the extended
> precision number will also be infinite.  However, at the moment, the low
> part of this number will have a nonzero (negative) lowpart.

LDBL_MAX is a number of the above form, in fact x.... is a bunch of
F's.  It's obvious that gcc's own value for LDBL_MAX ought to convert to
a finite number!  So either LDBL_MAX needs adjusting or
encode_ibm_extended needs to convert these numbers to finite values.
I think the latter is the correct course.

	* real.c (encode_ibm_extended): Handle LDBL_MAX and other large
	numbers.  Don't round before converting low double.

While looking at this code, I noticed that the value is rounded to
double after the high double has been subtracted.  I think this is
unnecessary since real_to_target_fmt rounds before calling the
encode function.  No other encode_* function does this rounding.
Digging through the history, I see that Alexandre Oliva added the
round_for_format call in version 1.109,
I couldn't see any explanation in the thread on the mailing list.

Bootstrap and regression test powerpc64-linux in progress.  A better
test would be on some mips target with 128-bit long doubles enabled,
since powerpc64-linux doesn't yet have 128-bit long double in glibc.
Would one of the mips crowd please run a bootstrap with this patch?

Assuming testing shows no regressions, OK mainline and 3.4?  

Index: gcc/real.c
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.138
diff -u -p -r1.138 real.c
--- gcc/real.c	10 Feb 2004 23:05:58 -0000	1.138
+++ gcc/real.c	3 Mar 2004 00:13:35 -0000
@@ -3245,10 +3245,16 @@ encode_ibm_extended (const struct real_f
   round_for_format (base_fmt, &u);
   encode_ieee_double (base_fmt, &buf[0], &u);
-  if (u.class == rvc_normal)
+  if (normr.class == rvc_normal)
+      if (u.class == rvc_inf)
+	{
+	  /* Rounding caused an overflow.  Convert without rounding so
+	     we can handle LDBL_MAX.  */
+	  encode_ieee_double (base_fmt, &buf[0], &normr);
+	  decode_ieee_double (base_fmt, &u, &buf[0]);
+	}
       do_add (&v, &normr, &u, 1);
-      round_for_format (base_fmt, &v);
       encode_ieee_double (base_fmt, &buf[2], &v);

Alan Modra
IBM OzLabs - Linux Technology Centre

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