| Index: gcc/libgfortran/io/write_float.def
|
| diff --git a/gcc/libgfortran/io/write_float.def b/gcc/libgfortran/io/write_float.def
|
| index 9804d7b9ab1caa226f7d705b5ac993e1440ab7d4..b945eb012db14c5e28cf56e8ded1489b1323eee4 100644
|
| --- a/gcc/libgfortran/io/write_float.def
|
| +++ b/gcc/libgfortran/io/write_float.def
|
| @@ -1,4 +1,4 @@
|
| -/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
| +/* Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
| Contributed by Andy Vaught
|
| Write float code factoring to this file by Jerry DeLisle
|
| F2003 I/O support contributed by Jerry DeLisle
|
| @@ -68,7 +68,7 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
| char *out;
|
| char *digits;
|
| int e;
|
| - char expchar;
|
| + char expchar, rchar;
|
| format_token ft;
|
| int w;
|
| int d;
|
| @@ -89,6 +89,7 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
| w = f->u.real.w;
|
| d = f->u.real.d;
|
|
|
| + rchar = '5';
|
| nzero_real = -1;
|
|
|
| /* We should always know the field width and precision. */
|
| @@ -140,6 +141,13 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
| switch (ft)
|
| {
|
| case FMT_F:
|
| + if (d == 0 && e <= 0 && dtp->u.p.scale_factor == 0)
|
| + {
|
| + memmove (digits + 1, digits, ndigits - 1);
|
| + digits[0] = '0';
|
| + e++;
|
| + }
|
| +
|
| nbefore = e + dtp->u.p.scale_factor;
|
| if (nbefore < 0)
|
| {
|
| @@ -235,24 +243,75 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
| internal_error (&dtp->common, "Unexpected format token");
|
| }
|
|
|
| - /* Round the value. */
|
| + /* Round the value. The value being rounded is an unsigned magnitude.
|
| + The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
|
| + switch (dtp->u.p.current_unit->round_status)
|
| + {
|
| + case ROUND_ZERO: /* Do nothing and truncation occurs. */
|
| + goto skip;
|
| + case ROUND_UP:
|
| + if (sign_bit)
|
| + goto skip;
|
| + rchar = '0';
|
| + break;
|
| + case ROUND_DOWN:
|
| + if (!sign_bit)
|
| + goto skip;
|
| + rchar = '0';
|
| + break;
|
| + case ROUND_NEAREST:
|
| + /* Round compatible unless there is a tie. A tie is a 5 with
|
| + all trailing zero's. */
|
| + i = nafter + nbefore;
|
| + if (digits[i] == '5')
|
| + {
|
| + for(i++ ; i < ndigits; i++)
|
| + {
|
| + if (digits[i] != '0')
|
| + goto do_rnd;
|
| + }
|
| + /* It is a tie so round to even. */
|
| + switch (digits[nafter + nbefore - 1])
|
| + {
|
| + case '1':
|
| + case '3':
|
| + case '5':
|
| + case '7':
|
| + case '9':
|
| + /* If odd, round away from zero to even. */
|
| + break;
|
| + default:
|
| + /* If even, skip rounding, truncate to even. */
|
| + goto skip;
|
| + }
|
| + }
|
| + /* Fall through. */
|
| + case ROUND_PROCDEFINED:
|
| + case ROUND_UNSPECIFIED:
|
| + case ROUND_COMPATIBLE:
|
| + rchar = '5';
|
| + /* Just fall through and do the actual rounding. */
|
| + }
|
| +
|
| + do_rnd:
|
| +
|
| if (nbefore + nafter == 0)
|
| {
|
| ndigits = 0;
|
| - if (nzero_real == d && digits[0] >= '5')
|
| - {
|
| - /* We rounded to zero but shouldn't have */
|
| - nzero--;
|
| - nafter = 1;
|
| - digits[0] = '1';
|
| - ndigits = 1;
|
| - }
|
| + if (nzero_real == d && digits[0] >= rchar)
|
| + {
|
| + /* We rounded to zero but shouldn't have */
|
| + nzero--;
|
| + nafter = 1;
|
| + digits[0] = '1';
|
| + ndigits = 1;
|
| + }
|
| }
|
| else if (nbefore + nafter < ndigits)
|
| {
|
| ndigits = nbefore + nafter;
|
| i = ndigits;
|
| - if (digits[i] >= '5')
|
| + if (digits[i] >= rchar)
|
| {
|
| /* Propagate the carry. */
|
| for (i--; i >= 0; i--)
|
| @@ -267,9 +326,10 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
|
|
| if (i < 0)
|
| {
|
| - /* The carry overflowed. Fortunately we have some spare space
|
| - at the start of the buffer. We may discard some digits, but
|
| - this is ok because we already know they are zero. */
|
| + /* The carry overflowed. Fortunately we have some spare
|
| + space at the start of the buffer. We may discard some
|
| + digits, but this is ok because we already know they are
|
| + zero. */
|
| digits--;
|
| digits[0] = '1';
|
| if (ft == FMT_F)
|
| @@ -297,6 +357,8 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
| }
|
| }
|
|
|
| + skip:
|
| +
|
| /* Calculate the format of the exponent field. */
|
| if (expchar)
|
| {
|
| @@ -756,21 +818,13 @@ sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
|
| {\
|
| GFC_REAL_ ## x tmp;\
|
| tmp = * (GFC_REAL_ ## x *)source;\
|
| - sign_bit = signbit (tmp);\
|
| + sign_bit = __builtin_signbit (tmp);\
|
| if (!isfinite (tmp))\
|
| { \
|
| write_infnan (dtp, f, isnan (tmp), sign_bit);\
|
| return;\
|
| }\
|
| tmp = sign_bit ? -tmp : tmp;\
|
| - if (f->u.real.d == 0 && f->format == FMT_F\
|
| - && dtp->u.p.scale_factor == 0)\
|
| - {\
|
| - if (tmp < 0.5)\
|
| - tmp = 0.0;\
|
| - else if (tmp < 1.0)\
|
| - tmp = 1.0;\
|
| - }\
|
| zero_flag = (tmp == 0.0);\
|
| \
|
| DTOA ## y\
|
|
|