diff options
author | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-12 13:19:40 +0000 |
---|---|---|
committer | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-12 13:19:40 +0000 |
commit | e2eb2b7f42c984114a733ebf5b9b4fd48c77f52c (patch) | |
tree | 8520ed37f4f8d6016d590082a4aa6d51a73e1cdd /gcc/real.c | |
parent | 98bbec1e473511d08a36b0cf5796c7337c5d07f8 (diff) | |
download | gcc-e2eb2b7f42c984114a733ebf5b9b4fd48c77f52c.tar.gz |
ChangeLog:
* real.h (struct real_format): New member round_towards_zero.
* real.c (round_for_format): Respect fmt->round_towards_zero.
(ieee_single_format, mips_single_format, motorola_single_format,
spu_single_format, ieee_double_format, mips_double_format,
motorola_double_format, ieee_extended_motorola_format,
ieee_extended_intel_96_format, ieee_extended_intel_128_format,
ieee_extended_intel_96_round_53_format, ibm_extended_format,
mips_extended_format, ieee_quad_format, mips_quad_format,
vax_f_format, vax_d_format, vax_g_format): Initialize it.
* config/pdp11/pdp11.c (pdp11_f_format, pdp11_d_format): Likewise.
* builtins.s (do_mpfr_arg1): Consider round_towards_zero member of
real_format to choose rounding mode when calling MPFR functions.
(do_mpfr_arg2, do_mpfr_arg3, do_mpfr_sincos): Likewise.
(do_mpfr_bessel_n, do_mpfr_remquo, do_mpfr_lgamma_r): Likewise.
* real.h (real_to_decimal_for_mode): Add prototype.
* real.c (real_to_decimal_for_mode): Renames old real_to_decimal.
Respect target rounding mode when generating decimal representation.
(real_to_decimal): New stub for backwards compatibility.
* c-cppbuiltin.c (builtin_define_with_hex_fp_value): Use
real_to_decimal_for_mode instead of real_to_decimal.
* config/spu/spu.md ("floatdisf2", "floatunsdisf2"): New.
testsuite/ChangeLog:
* gcc.c-torture/execute/20031003-1.c (main): Update test to
accommodate SPU single-precision rounding mode.
* gcc.c-torture/execute/conversion.c (test_float_to_integer,
test_float_to_longlong_integer): Likewise.
* gcc.c-torture/execute/ieee/rbug.c (main): Likewise.
* gcc.dg/hex-round-1.c: Skip test on SPU.
* gcc.dg/hex-round-2.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139014 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/real.c')
-rw-r--r-- | gcc/real.c | 120 |
1 files changed, 96 insertions, 24 deletions
diff --git a/gcc/real.c b/gcc/real.c index 49eb97d740c..806e2f88f36 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -1443,20 +1443,30 @@ rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den) /* Render R as a decimal floating point constant. Emit DIGITS significant digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the maximum for the representation. If CROP_TRAILING_ZEROS, strip trailing - zeros. */ + zeros. If MODE is VOIDmode, round to nearest value. Otherwise, round + to a string that, when parsed back in mode MODE, yields the same value. */ #define M_LOG10_2 0.30102999566398119521 void -real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, - size_t digits, int crop_trailing_zeros) +real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig, + size_t buf_size, size_t digits, + int crop_trailing_zeros, enum machine_mode mode) { + const struct real_format *fmt = NULL; const REAL_VALUE_TYPE *one, *ten; REAL_VALUE_TYPE r, pten, u, v; int dec_exp, cmp_one, digit; size_t max_digits; char *p, *first, *last; bool sign; + bool round_up; + + if (mode != VOIDmode) + { + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); + } r = *r_orig; switch (r.cl) @@ -1672,17 +1682,31 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, digit = rtd_divmod (&r, &pten); /* Round the result. */ - if (digit == 5) + if (fmt && fmt->round_towards_zero) { - /* Round to nearest. If R is nonzero there are additional - nonzero digits to be extracted. */ + /* If the format uses round towards zero when parsing the string + back in, we need to always round away from zero here. */ if (cmp_significand_0 (&r)) digit++; - /* Round to even. */ - else if ((p[-1] - '0') & 1) - digit++; + round_up = digit > 0; } - if (digit > 5) + else + { + if (digit == 5) + { + /* Round to nearest. If R is nonzero there are additional + nonzero digits to be extracted. */ + if (cmp_significand_0 (&r)) + digit++; + /* Round to even. */ + else if ((p[-1] - '0') & 1) + digit++; + } + + round_up = digit > 5; + } + + if (round_up) { while (p > first) { @@ -1716,6 +1740,26 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, /* Append the exponent. */ sprintf (last, "e%+d", dec_exp); + +#ifdef ENABLE_CHECKING + /* Verify that we can read the original value back in. */ + if (mode != VOIDmode) + { + real_from_string (&r, str); + real_convert (&r, mode, &r); + gcc_assert (real_identical (&r, r_orig)); + } +#endif +} + +/* Likewise, except always uses round-to-nearest. */ + +void +real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, + size_t digits, int crop_trailing_zeros) +{ + real_to_decimal_for_mode (str, r_orig, buf_size, + digits, crop_trailing_zeros, VOIDmode); } /* Render R as a hexadecimal floating point constant. Emit DIGITS @@ -2389,9 +2433,8 @@ static void round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) { int p2, np2, i, w; - unsigned long sticky; - bool guard, lsb; int emin2m1, emax2; + bool round_up = false; if (r->decimal) { @@ -2463,21 +2506,28 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) } } - /* There are P2 true significand bits, followed by one guard bit, - followed by one sticky bit, followed by stuff. Fold nonzero - stuff into the sticky bit. */ + if (!fmt->round_towards_zero) + { + /* There are P2 true significand bits, followed by one guard bit, + followed by one sticky bit, followed by stuff. Fold nonzero + stuff into the sticky bit. */ + unsigned long sticky; + bool guard, lsb; - sticky = 0; - for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i) - sticky |= r->sig[i]; - sticky |= - r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1); + sticky = 0; + for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i) + sticky |= r->sig[i]; + sticky |= r->sig[w] + & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1); - guard = test_significand_bit (r, np2 - 1); - lsb = test_significand_bit (r, np2); + guard = test_significand_bit (r, np2 - 1); + lsb = test_significand_bit (r, np2); - /* Round to even. */ - if (guard && (sticky || lsb)) + /* Round to even. */ + round_up = guard && (sticky || lsb); + } + + if (round_up) { REAL_VALUE_TYPE u; get_zero (&u, 0); @@ -2817,6 +2867,7 @@ const struct real_format ieee_single_format = 128, 31, 31, + false, true, true, true, @@ -2836,6 +2887,7 @@ const struct real_format mips_single_format = 128, 31, 31, + false, true, true, true, @@ -2855,6 +2907,7 @@ const struct real_format motorola_single_format = 128, 31, 31, + false, true, true, true, @@ -2885,6 +2938,7 @@ const struct real_format spu_single_format = 129, 31, 31, + true, false, false, true, @@ -3092,6 +3146,7 @@ const struct real_format ieee_double_format = 1024, 63, 63, + false, true, true, true, @@ -3111,6 +3166,7 @@ const struct real_format mips_double_format = 1024, 63, 63, + false, true, true, true, @@ -3130,6 +3186,7 @@ const struct real_format motorola_double_format = 1024, 63, 63, + false, true, true, true, @@ -3467,6 +3524,7 @@ const struct real_format ieee_extended_motorola_format = 16384, 95, 95, + false, true, true, true, @@ -3486,6 +3544,7 @@ const struct real_format ieee_extended_intel_96_format = 16384, 79, 79, + false, true, true, true, @@ -3505,6 +3564,7 @@ const struct real_format ieee_extended_intel_128_format = 16384, 79, 79, + false, true, true, true, @@ -3526,6 +3586,7 @@ const struct real_format ieee_extended_intel_96_round_53_format = 16384, 79, 79, + false, true, true, true, @@ -3612,6 +3673,7 @@ const struct real_format ibm_extended_format = 1024, 127, -1, + false, true, true, true, @@ -3631,6 +3693,7 @@ const struct real_format mips_extended_format = 1024, 127, -1, + false, true, true, true, @@ -3892,6 +3955,7 @@ const struct real_format ieee_quad_format = 16384, 127, 127, + false, true, true, true, @@ -3911,6 +3975,7 @@ const struct real_format mips_quad_format = 16384, 127, 127, + false, true, true, true, @@ -4214,6 +4279,7 @@ const struct real_format vax_f_format = false, false, false, + false, false }; @@ -4233,6 +4299,7 @@ const struct real_format vax_d_format = false, false, false, + false, false }; @@ -4252,6 +4319,7 @@ const struct real_format vax_g_format = false, false, false, + false, false }; @@ -4321,6 +4389,7 @@ const struct real_format decimal_single_format = 96, 31, 31, + false, true, true, true, @@ -4341,6 +4410,7 @@ const struct real_format decimal_double_format = 384, 63, 63, + false, true, true, true, @@ -4361,6 +4431,7 @@ const struct real_format decimal_quad_format = 6144, 127, 127, + false, true, true, true, @@ -4404,6 +4475,7 @@ const struct real_format real_internal_format = MAX_EXP, -1, -1, + false, true, true, false, |