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
This commit is contained in:
Richard Henderson 2002-10-04 01:01:12 -07:00
parent 311b75739b
commit ee6ff31927
3 changed files with 68 additions and 42 deletions

View 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.

View File

@ -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

View 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