aboutsummaryrefslogtreecommitdiff
path: root/gcc/real.c
diff options
context:
space:
mode:
authorJanis Johnson <janis187@us.ibm.com>2009-09-17 17:07:24 +0000
committerJanis Johnson <janis@gcc.gnu.org>2009-09-17 17:07:24 +0000
commitd2da4af2c7872e1d9892cc5b3792d10dd86782a4 (patch)
tree76332f90632195d93b999cee84b8426bd071c7d0 /gcc/real.c
parent51a0d6aa772829f49bc40564c92aa96e7a3cd910 (diff)
downloadgcc-d2da4af2c7872e1d9892cc5b3792d10dd86782a4.zip
gcc-d2da4af2c7872e1d9892cc5b3792d10dd86782a4.tar.gz
gcc-d2da4af2c7872e1d9892cc5b3792d10dd86782a4.tar.bz2
re PR c/41049 (conversion from integer to decimal float loses trailing zeros)
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. From-SVN: r151806
Diffstat (limited to 'gcc/real.c')
-rw-r--r--gcc/real.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/gcc/real.c b/gcc/real.c
index f4c493b..eb4e25b 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 *