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]

Fix real.c handling of small paired-double values


This patch fixes the way encode_ibm_extended deals with numbers in the
range [2**-1022,2**(-1022+53)).  According to the real_format table,
such numbers are denormals:

  const struct real_format ibm_extended_format =
    {
      encode_ibm_extended,
      decode_ibm_extended,
      2,
      1,
      53 + 53,
      53,
>>>   -1021 + 53,
      1024,
      -1,
      true,
      true,
      true,
      true,
      true
    };

And this seems like an accurate description for this level of abstraction.
-1022+53 is the smallest exponent for which the full precision is available.
-1022+52 has a less bit of precision, etc.  Of course, numbers >= 2**-1022
will be represented with a normal high-part double, but that's just an
implementation detail.

The problem is that any number in the range [2**-1022,2**(-1022+53)) is
converted to denormal form before being passed to encode_ibm_extended.
It in turn rounds the number to double precision and passes it to
encode_ieee_double, which will interpret the value as a denormal double,
i.e. something < 2**-1022.  Thus we'll end up with a denormal high part
and a non-denormal low part.

The patch below fixes this by renormlising the input value before doing
any rounding or arithmetic on it.

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.

Patch bootstrapped & regression tested on mips-sgi-irix6.5.  It fixes
18_support/numeric_limits.cc and the attached test cases.  OK to install?

Richard


	* real.c (encode_ibm_extended): Normalize the input value before
	converting it to a double.  Handle the case where a normal value
	rounds to infinity.

Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.136
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.136 real.c
--- real.c	23 Jan 2004 16:16:32 -0000	1.136
+++ real.c	1 Feb 2004 13:53:20 -0000
@@ -3230,19 +3230,24 @@ static void
 encode_ibm_extended (const struct real_format *fmt, long *buf,
 		     const REAL_VALUE_TYPE *r)
 {
-  REAL_VALUE_TYPE u, v;
+  REAL_VALUE_TYPE u, normr, v;
   const struct real_format *base_fmt;
 
   base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
 
+  /* Renormlize R before doing any arithmetic on it.  */
+  normr = *r;
+  if (normr.class == rvc_normal)
+    normalize (&normr);
+
   /* u = IEEE double precision portion of significand.  */
-  u = *r;
+  u = normr;
   round_for_format (base_fmt, &u);
   encode_ieee_double (base_fmt, &buf[0], &u);
 
-  if (r->class == rvc_normal)
+  if (u.class == rvc_normal)
     {
-      do_add (&v, r, &u, 1);
+      do_add (&v, &normr, &u, 1);
       round_for_format (base_fmt, &v);
       encode_ieee_double (base_fmt, &buf[2], &v);
     }
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gcc.c-torture/execute/20040202-1.c	Mon Feb  2 13:47:58 2004
***************
*** 0 ****
--- 1,13 ----
+ int main ()
+ {
+   if (sizeof (long double) >= 8)
+     {
+       long double x;
+ 
+       x = 0x1.0p-500L;
+       x *= 0x1.0p-522L;
+       if (x != 0x1.0p-1022L || x == 0)
+ 	abort ();
+     }
+   exit (0);
+ }
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gcc.c-torture/execute/20040202-2.c	Mon Feb  2 13:48:02 2004
***************
*** 0 ****
--- 1,11 ----
+ int main ()
+ {
+   long double x, y;
+ 
+   x = 0x1.fffffffffffff8p1022L;
+   x *= 2;
+   y = 0x1.fffffffffffff8p1023L;
+   if (memcmp (&x, &y, sizeof (x)) != 0)
+     abort ();
+   exit (0);
+ }


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