OSDN Git Service

* real.h (SIGNIFICAND_BITS): Add one more word.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 4 Oct 2002 08:01:12 +0000 (08:01 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 4 Oct 2002 08:01:12 +0000 (08:01 +0000)
        (CONST_DOUBLE_FORMAT): Accomodate 6 words.
        * real.c (times_pten): New.
        (real_to_decimal, real_from_string): Use it.
        (sticky_rshift_significand): Use & to find modulus.
        (rshift_significand, lshift_significand): Likewise.
        (do_divide): Apply sticky bit after normalization.
        (real_to_decimal, real_to_hexadecimal): Fix sign of Inf and NaN.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@57811 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/real.c
gcc/real.h

index 573d75f..e081779 100644 (file)
@@ -1,3 +1,14 @@
+2002-10-04  Richard Henderson  <rth@redhat.com>
+
+       * real.h (SIGNIFICAND_BITS): Add one more word.
+       (CONST_DOUBLE_FORMAT): Accomodate 6 words.
+       * real.c (times_pten): New.
+       (real_to_decimal, real_from_string): Use it.
+       (sticky_rshift_significand): Use & to find modulus.
+       (rshift_significand, lshift_significand): Likewise.
+       (do_divide): Apply sticky bit after normalization.
+       (real_to_decimal, real_to_hexadecimal): Fix sign of Inf and NaN.
+
 2002-10-03  Andreas Jaeger  <aj@suse.de>
 
        * gengtype.c (adjust_field_rtx_def): Cast variables of type size_t
@@ -205,7 +216,7 @@ Wed Oct  2 17:01:36 CEST 2002  Jan Hubicka  <jh@suse.cz>
        for TLS debug info to !DECL_EXTERNAL.
 
 2002-10-01  Matt Thomas  <matt@3am-software.com>
-            Jason Thorpe  <thorpej@wasabisystems.com>
+           Jason Thorpe  <thorpej@wasabisystems.com>
 
        * config.gcc (vax-*-netbsdelf*): Enable configuration.
        * config/elfos.h (PCC_BITFIELD_TYPE_MATTERS): Define only
@@ -322,7 +333,7 @@ Wed Oct  2 17:01:36 CEST 2002  Jan Hubicka  <jh@suse.cz>
        * config/xtensa/xtensa.h (REG_CLASS_NAMES, REG_CLASS_CONTENTS):
        Add new RL_REGS register class.
        (PREFERRED_RELOAD_CLASS, PREFERRED_OUTPUT_RELOAD_CLASS):
-        Call xtensa_preferred_reload_class for both input and output reloads.
+       Call xtensa_preferred_reload_class for both input and output reloads.
        * config/xtensa/xtensa.c (xtensa_regno_to_class): Use new RL_REGS class.
        (xtensa_preferred_reload_class): Handle output reloads; use RL_REGS
        instead of either AR_REGS or GR_REGS classes.
index 4ce60d9..075da40 100644 (file)
    In addition, E must be large enough to hold the smallest supported
    denormal number in a normalized form.
 
-   Both of these requirements are easily satisfied.  The largest
-   target significand is 113 bits; we store 128.  The smallest
+   Both of these requirements are easily satisfied.  The largest target
+   significand is 113 bits; we store at least 160.  The smallest
    denormal number fits in 17 exponent bits; we store 29.
 
+   Note that the decimal string conversion routines are sensitive to 
+   rounding error.  Since the raw arithmetic routines do not themselves
+   have guard digits or rounding, the computation of 10**exp can
+   accumulate more than a few digits of error.  The previous incarnation
+   of real.c successfully used a 144 bit fraction; given the current
+   layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits.
+
    Target floating point models that use base 16 instead of base 2
    (i.e. IBM 370), are handled during round_for_format, in which we
    canonicalize the exponent to be a multiple of 4 (log2(16)), and
@@ -119,6 +126,7 @@ static void do_fix_trunc PARAMS ((REAL_VALUE_TYPE *,
 
 static const REAL_VALUE_TYPE * ten_to_ptwo PARAMS ((int));
 static const REAL_VALUE_TYPE * real_digit PARAMS ((int));
+static void times_pten PARAMS ((REAL_VALUE_TYPE *, int));
 
 static void round_for_format PARAMS ((const struct real_format *,
                                      REAL_VALUE_TYPE *));
@@ -186,7 +194,7 @@ sticky_rshift_significand (r, a, n)
     {
       for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i)
        sticky |= a->sig[i];
-      n -= ofs * HOST_BITS_PER_LONG;
+      n &= HOST_BITS_PER_LONG - 1;
     }
 
   if (n != 0)
@@ -222,7 +230,7 @@ rshift_significand (r, a, n)
 {
   unsigned int i, ofs = n / HOST_BITS_PER_LONG;
 
-  n -= ofs * HOST_BITS_PER_LONG;
+  n &= HOST_BITS_PER_LONG - 1;
   if (n != 0)
     {
       for (i = 0; i < SIGSZ; ++i)
@@ -253,7 +261,7 @@ lshift_significand (r, a, n)
 {
   unsigned int i, ofs = n / HOST_BITS_PER_LONG;
 
-  n -= ofs * HOST_BITS_PER_LONG;
+  n &= HOST_BITS_PER_LONG - 1;
   if (n == 0)
     {
       for (i = 0; ofs + i < SIGSZ; ++i)
@@ -888,10 +896,10 @@ do_divide (r, a, b)
   rr->exp = exp;
 
   inexact = div_significands (rr, a, b);
-  rr->sig[0] |= inexact;
 
   /* Re-normalize the result.  */
   normalize (rr);
+  rr->sig[0] |= inexact;
 
   if (rr != r)
     *r = t;
@@ -1416,11 +1424,11 @@ real_to_decimal (str, r_orig, digits)
     case rvc_normal:
       break;
     case rvc_inf:
-      strcpy (str, (r.sign ? "+Inf" : "-Inf"));
+      strcpy (str, (r.sign ? "-Inf" : "+Inf"));
       return;
     case rvc_nan:
       /* ??? Print the significand as well, if not canonical?  */
-      strcpy (str, (r.sign ? "+NaN" : "-NaN"));
+      strcpy (str, (r.sign ? "-NaN" : "+NaN"));
       return;
     default:
       abort ();
@@ -1441,21 +1449,7 @@ real_to_decimal (str, r_orig, digits)
   dec_exp = r.exp * M_LOG10_2;
   
   /* Scale the number such that it is in [1, 10).  */
-  if (dec_exp > 0)
-    {
-      int i;
-      for (i = EXP_BITS - 1; i >= 0; --i)
-       if (dec_exp & (1 << i))
-         do_divide (&r, &r, ten_to_ptwo (i));
-    }
-  else if (dec_exp < 0)
-    {
-      int i, pos_exp = -(--dec_exp);
-
-      for (i = EXP_BITS - 1; i >= 0; --i)
-       if (pos_exp & (1 << i))
-         do_multiply (&r, &r, ten_to_ptwo (i));
-    }
+  times_pten (&r, (dec_exp > 0 ? -dec_exp : -(--dec_exp)));
 
   /* Assert that the number is in the proper range.  Round-off can
      prevent the above from working exactly.  */
@@ -1545,11 +1539,11 @@ real_to_hexadecimal (str, r, digits)
     case rvc_normal:
       break;
     case rvc_inf:
-      strcpy (str, (r->sign ? "+Inf" : "-Inf"));
+      strcpy (str, (r->sign ? "-Inf" : "+Inf"));
       return;
     case rvc_nan:
       /* ??? Print the significand as well, if not canonical?  */
-      strcpy (str, (r->sign ? "+NaN" : "-NaN"));
+      strcpy (str, (r->sign ? "-NaN" : "+NaN"));
       return;
     default:
       abort ();
@@ -1755,19 +1749,8 @@ real_from_string (r, str)
          exp += d;
        }
 
-      if (exp < 0)
-       {
-         exp = -exp;
-         for (d = 0; d < EXP_BITS; ++d)
-           if (exp & (1 << d))
-             do_divide (r, r, ten_to_ptwo (d));
-       }
-      else if (exp > 0)
-       {
-         for (d = 0; d < EXP_BITS; ++d)
-           if (exp & (1 << d))
-             do_multiply (r, r, ten_to_ptwo (d));
-       }
+      if (exp)
+        times_pten (r, exp);
     }
 
   r->sign = sign;
@@ -1900,6 +1883,34 @@ real_digit (n)
   return &num[n];
 }
 
+/* Multiply R by 10**EXP.  */
+
+static void
+times_pten (r, exp)
+     REAL_VALUE_TYPE *r;
+     int exp;
+{
+  REAL_VALUE_TYPE pten, *rr;
+  bool negative = (exp < 0);
+  int i;
+
+  if (negative)
+    {
+      exp = -exp;
+      pten = *real_digit (1);
+      rr = &pten;
+    }
+  else
+    rr = r;
+
+  for (i = 0; exp > 0; ++i, exp >>= 1)
+    if (exp & 1)
+      do_multiply (rr, rr, ten_to_ptwo (i));
+
+  if (negative)
+    do_divide (r, r, &pten);
+}
+
 /* Fills R with +Inf.  */
 
 void
index 9003170..fc84a10 100644 (file)
@@ -34,7 +34,7 @@ enum real_value_class {
   rvc_nan
 };
 
-#define SIGNIFICAND_BITS       128
+#define SIGNIFICAND_BITS       (128 + HOST_BITS_PER_LONG)
 #define EXP_BITS               (32 - 3)
 #define MAX_EXP                        ((1 << (EXP_BITS - 1)) - 1)
 #define SIGSZ                  (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
@@ -88,7 +88,11 @@ extern char test_real_width
 #    if REAL_WIDTH == 5
 #     define CONST_DOUBLE_FORMAT "wwwww"
 #    else
-      #error "REAL_WIDTH > 5 not supported"
+#     if REAL_WIDTH == 6
+#      define CONST_DOUBLE_FORMAT "wwwwww"
+#     else
+       #error "REAL_WIDTH > 6 not supported"
+#     endif
 #    endif
 #   endif
 #  endif