diff options
author | janis <janis@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-17 17:07:24 +0000 |
---|---|---|
committer | janis <janis@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-17 17:07:24 +0000 |
commit | 3c9085936228ac479154971fc23f5fbf2e85af0c (patch) | |
tree | 76332f90632195d93b999cee84b8426bd071c7d0 /gcc/real.c | |
parent | c3ab1ea8f83f0dd64d0ad48aaad4b40ee7a4720f (diff) | |
download | gcc-3c9085936228ac479154971fc23f5fbf2e85af0c.tar.gz |
gcc/
PR c/41049
* real.c decimal_from_integer, decimal_integer_string): New.
(real_from_integer): Use them as special case for decimal float.
* config/dfp-bit.c (_si_to_sd, _usi_to_sd): Use default rounding.
(_di_to_sd, _di_to_dd, _di_to_td, _udi_to_sd, _udi_to_dd, _udi_to_td):
Do not append zero after the decimal point in string to convert.
gcc/testsuite/
PR c/41049
* dfp/pr41049.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151806 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/real.c')
-rw-r--r-- | gcc/real.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/gcc/real.c b/gcc/real.c index f4c493bd041..eb4e25bba83 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -110,6 +110,9 @@ static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int); static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *); +static void decimal_from_integer (REAL_VALUE_TYPE *); +static void decimal_integer_string (char *, const REAL_VALUE_TYPE *, + size_t); static const REAL_VALUE_TYPE * ten_to_ptwo (int); static const REAL_VALUE_TYPE * ten_to_mptwo (int); @@ -2168,10 +2171,70 @@ real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode, normalize (r); } - if (mode != VOIDmode) + if (DECIMAL_FLOAT_MODE_P (mode)) + decimal_from_integer (r); + else if (mode != VOIDmode) real_convert (r, mode, r); } +/* Render R, an integral value, as a floating point constant with no + specified exponent. */ + +static void +decimal_integer_string (char *str, const REAL_VALUE_TYPE *r_orig, + size_t buf_size) +{ + int dec_exp, digit, digits; + REAL_VALUE_TYPE r, pten; + char *p; + bool sign; + + r = *r_orig; + + if (r.cl == rvc_zero) + { + strcpy (str, "0."); + return; + } + + sign = r.sign; + r.sign = 0; + + dec_exp = REAL_EXP (&r) * M_LOG10_2; + digits = dec_exp + 1; + gcc_assert ((digits + 2) < (int)buf_size); + + pten = *real_digit (1); + times_pten (&pten, dec_exp); + + p = str; + if (sign) + *p++ = '-'; + + digit = rtd_divmod (&r, &pten); + gcc_assert (digit >= 0 && digit <= 9); + *p++ = digit + '0'; + while (--digits > 0) + { + times_pten (&r, 1); + digit = rtd_divmod (&r, &pten); + *p++ = digit + '0'; + } + *p++ = '.'; + *p++ = '\0'; +} + +/* Convert a real with an integral value to decimal float. */ + +static void +decimal_from_integer (REAL_VALUE_TYPE *r) +{ + char str[256]; + + decimal_integer_string (str, r, sizeof (str) - 1); + decimal_real_from_string (r, str); +} + /* Returns 10**2**N. */ static const REAL_VALUE_TYPE * |