summaryrefslogtreecommitdiff
path: root/libgfortran/io/write_float.def
diff options
context:
space:
mode:
authorjvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-29 14:56:02 +0000
committerjvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-29 14:56:02 +0000
commit20b8800c1193b72112bdb198d8afa1aaeed99dd5 (patch)
tree7c17b1373c610a14b69aea91b26798d2921a7d89 /libgfortran/io/write_float.def
parentf5ff0b2195783e33b0cf2e91f857882434f8f01f (diff)
downloadgcc-20b8800c1193b72112bdb198d8afa1aaeed99dd5.tar.gz
2011-04-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
Janne Blomqvist <jb@gcc.gnu.org> PR libgfortran/48488 PR libgfortran/48602 PR libgfortran/48615 PR libgfortran/48684 PR libgfortran/48787 * io/write.c (write_d, write_e, write_f, write_en, write_es): Add precision compemsation parameter to call. (set_fnode_default): Adjust default widths to assure round trip on write and read. (write_real): Adjust call to write_float. (write_real_g0): Calculate compensation for extra precision and adjust call to write_float. * io/write_float.def (output_float_FMT_G_): Use volatile rather than asm volatile to avoid optimization issue. Correctly calculate the number of blanks (nb) to be appended and simplify calculation logic. (write_float): Increase MIN_FIELD_WIDTH by one to accomodate the new default widths. Eliminate the code that attempted to reduce the the precision used in later sprintf functions. Add call parameter to compensate for extra precision. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@173166 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgfortran/io/write_float.def')
-rw-r--r--libgfortran/io/write_float.def62
1 files changed, 19 insertions, 43 deletions
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index 2bced6ffec4..2e2b4d87bf4 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -289,8 +289,9 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
}
else if (nbefore + nafter < ndigits)
{
- ndigits = nbefore + nafter;
- i = ndigits;
+ i = ndigits = nbefore + nafter;
+ if (d == 0 && digits[1] == '0')
+ goto skip;
if (digits[i] >= rchar)
{
/* Propagate the carry. */
@@ -812,7 +813,8 @@ CALCULATE_EXP(16)
static void \
output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
GFC_REAL_ ## x m, char *buffer, size_t size, \
- int sign_bit, bool zero_flag, int ndigits, int edigits) \
+ int sign_bit, bool zero_flag, int ndigits, \
+ int edigits, int comp_d) \
{ \
int e = f->u.real.e;\
int d = f->u.real.d;\
@@ -850,7 +852,7 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
{ \
newf->format = FMT_E;\
newf->u.real.w = w;\
- newf->u.real.d = d;\
+ newf->u.real.d = d - comp_d;\
newf->u.real.e = e;\
nb = 0;\
goto finish;\
@@ -864,11 +866,10 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
\
while (low <= high)\
{ \
- GFC_REAL_ ## x temp;\
+ volatile GFC_REAL_ ## x temp;\
mid = (low + high) / 2;\
\
temp = (calculate_exp_ ## x (mid - 1) * (1 - r * rexp_d));\
- asm volatile ("" : "+m" (temp));\
\
if (m < temp)\
{ \
@@ -894,22 +895,11 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
}\
}\
\
- if (e > 4)\
- e = 4;\
- if (e < 0)\
- nb = 4;\
- else\
- nb = e + 2;\
-\
- nb = nb >= w ? 0 : nb;\
+ nb = e <= 0 ? 4 : e + 2;\
+ nb = nb >= w ? w - 1 : nb;\
newf->format = FMT_F;\
- newf->u.real.w = f->u.real.w - nb;\
-\
- if (m == 0.0)\
- newf->u.real.d = d - 1;\
- else\
- newf->u.real.d = - (mid - d - 1);\
-\
+ newf->u.real.w = w - nb;\
+ newf->u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\
dtp->u.p.scale_factor = 0;\
\
finish:\
@@ -931,7 +921,7 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
gfc_char4_t *p4 = (gfc_char4_t *) p;\
memset4 (p4, pad, nb);\
}\
- else\
+ else \
memset (p, pad, nb);\
}\
}\
@@ -1010,19 +1000,20 @@ __qmath_(quadmath_snprintf) (buffer, sizeof buffer, \
edigits);\
else \
output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
- zero_flag, ndigits, edigits);\
+ zero_flag, ndigits, edigits, comp_d);\
}\
/* Output a real number according to its format. */
static void
-write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
+write_float (st_parameter_dt *dtp, const fnode *f, const char *source, \
+ int len, int comp_d)
{
#if defined(HAVE_GFC_REAL_16) || __LDBL_DIG__ > 18
-# define MIN_FIELD_WIDTH 48
+# define MIN_FIELD_WIDTH 49
#else
-# define MIN_FIELD_WIDTH 31
+# define MIN_FIELD_WIDTH 32
#endif
#define STR(x) STR1(x)
#define STR1(x) #x
@@ -1039,23 +1030,8 @@ write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
to handle the largest number of exponent digits expected. */
edigits=4;
- if (f->format == FMT_F || f->format == FMT_EN || f->format == FMT_G
- || ((f->format == FMT_D || f->format == FMT_E)
- && dtp->u.p.scale_factor != 0))
- {
- /* Always convert at full precision to avoid double rounding. */
- ndigits = MIN_FIELD_WIDTH - 4 - edigits;
- }
- else
- {
- /* The number of digits is known, so let printf do the rounding. */
- if (f->format == FMT_ES)
- ndigits = f->u.real.d + 1;
- else
- ndigits = f->u.real.d;
- if (ndigits > MIN_FIELD_WIDTH - 4 - edigits)
- ndigits = MIN_FIELD_WIDTH - 4 - edigits;
- }
+ /* Always convert at full precision to avoid double rounding. */
+ ndigits = MIN_FIELD_WIDTH - 4 - edigits;
switch (len)
{