aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@gcc.gnu.org>2002-10-04 01:01:12 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-10-04 01:01:12 -0700
commitee6ff319272d415b5c36d7f45e6e08e8273d6b62 (patch)
tree5a48f88c6ae305fbba651fd2c77019b022c4e3ee /gcc
parent311b75739b289a6657e90317009db81d88a300de (diff)
downloadgcc-ee6ff319272d415b5c36d7f45e6e08e8273d6b62.zip
gcc-ee6ff319272d415b5c36d7f45e6e08e8273d6b62.tar.gz
gcc-ee6ff319272d415b5c36d7f45e6e08e8273d6b62.tar.bz2
real.h (SIGNIFICAND_BITS): Add one more word.
* 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. From-SVN: r57811
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/real.c87
-rw-r--r--gcc/real.h8
3 files changed, 68 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 573d75f..e081779 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/real.c b/gcc/real.c
index 4ce60d9..075da40 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -53,10 +53,17 @@
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
diff --git a/gcc/real.h b/gcc/real.h
index 9003170..fc84a10 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -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