mirror of git://gcc.gnu.org/git/gcc.git
re PR libfortran/48787 (Invalid UP/DOWN rounding with F editing)
2011-05-01 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libgfortran/48787 * io/write_float.def (output_float): Gather up integer declarations and add new 'p' for scale factor. Use 'p' in place of the 'dtp' reference everywhere. For ROUND_UP scan the digit string and only perform rounding if something other than '0' is found. From-SVN: r173231
This commit is contained in:
parent
5a76c853a8
commit
7c4f44cd60
|
|
@ -1,3 +1,11 @@
|
||||||
|
2011-05-01 Jerry DeLisle <jvdelisle@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR libgfortran/48787
|
||||||
|
* io/write_float.def (output_float): Gather up integer declarations and
|
||||||
|
add new 'p' for scale factor. Use 'p' in place of the 'dtp' reference
|
||||||
|
everywhere. For ROUND_UP scan the digit string and only perform
|
||||||
|
rounding if something other than '0' is found.
|
||||||
|
|
||||||
2011-04-29 Janne Blomqvist <jb@gcc.gnu.org>
|
2011-04-29 Janne Blomqvist <jb@gcc.gnu.org>
|
||||||
|
|
||||||
* io/unix.c (min): New macro.
|
* io/unix.c (min): New macro.
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,9 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
||||||
{
|
{
|
||||||
char *out;
|
char *out;
|
||||||
char *digits;
|
char *digits;
|
||||||
int e;
|
int e, w, d, p, i;
|
||||||
char expchar, rchar;
|
char expchar, rchar;
|
||||||
format_token ft;
|
format_token ft;
|
||||||
int w;
|
|
||||||
int d;
|
|
||||||
/* Number of digits before the decimal point. */
|
/* Number of digits before the decimal point. */
|
||||||
int nbefore;
|
int nbefore;
|
||||||
/* Number of zeros after the decimal point. */
|
/* Number of zeros after the decimal point. */
|
||||||
|
|
@ -82,12 +80,12 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
||||||
int nzero_real;
|
int nzero_real;
|
||||||
int leadzero;
|
int leadzero;
|
||||||
int nblanks;
|
int nblanks;
|
||||||
int i;
|
|
||||||
sign_t sign;
|
sign_t sign;
|
||||||
|
|
||||||
ft = f->format;
|
ft = f->format;
|
||||||
w = f->u.real.w;
|
w = f->u.real.w;
|
||||||
d = f->u.real.d;
|
d = f->u.real.d;
|
||||||
|
p = dtp->u.p.scale_factor;
|
||||||
|
|
||||||
rchar = '5';
|
rchar = '5';
|
||||||
nzero_real = -1;
|
nzero_real = -1;
|
||||||
|
|
@ -119,14 +117,14 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
||||||
switch (ft)
|
switch (ft)
|
||||||
{
|
{
|
||||||
case FMT_F:
|
case FMT_F:
|
||||||
if (d == 0 && e <= 0 && dtp->u.p.scale_factor == 0)
|
if (d == 0 && e <= 0 && p == 0)
|
||||||
{
|
{
|
||||||
memmove (digits + 1, digits, ndigits - 1);
|
memmove (digits + 1, digits, ndigits - 1);
|
||||||
digits[0] = '0';
|
digits[0] = '0';
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbefore = e + dtp->u.p.scale_factor;
|
nbefore = e + p;
|
||||||
if (nbefore < 0)
|
if (nbefore < 0)
|
||||||
{
|
{
|
||||||
nzero = -nbefore;
|
nzero = -nbefore;
|
||||||
|
|
@ -147,13 +145,13 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
||||||
case FMT_E:
|
case FMT_E:
|
||||||
case FMT_D:
|
case FMT_D:
|
||||||
i = dtp->u.p.scale_factor;
|
i = dtp->u.p.scale_factor;
|
||||||
if (d <= 0 && i == 0)
|
if (d <= 0 && p == 0)
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
|
generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
|
||||||
"greater than zero in format specifier 'E' or 'D'");
|
"greater than zero in format specifier 'E' or 'D'");
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
if (i <= -d || i >= d + 2)
|
if (p <= -d || p >= d + 2)
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
|
generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
|
||||||
"out of range in format specifier 'E' or 'D'");
|
"out of range in format specifier 'E' or 'D'");
|
||||||
|
|
@ -161,20 +159,20 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!zero_flag)
|
if (!zero_flag)
|
||||||
e -= i;
|
e -= p;
|
||||||
if (i < 0)
|
if (p < 0)
|
||||||
{
|
{
|
||||||
nbefore = 0;
|
nbefore = 0;
|
||||||
nzero = -i;
|
nzero = -p;
|
||||||
nafter = d + i;
|
nafter = d + p;
|
||||||
}
|
}
|
||||||
else if (i > 0)
|
else if (p > 0)
|
||||||
{
|
{
|
||||||
nbefore = i;
|
nbefore = p;
|
||||||
nzero = 0;
|
nzero = 0;
|
||||||
nafter = (d - i) + 1;
|
nafter = (d - p) + 1;
|
||||||
}
|
}
|
||||||
else /* i == 0 */
|
else /* p == 0 */
|
||||||
{
|
{
|
||||||
nbefore = 0;
|
nbefore = 0;
|
||||||
nzero = 0;
|
nzero = 0;
|
||||||
|
|
@ -233,7 +231,13 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
||||||
if (sign_bit)
|
if (sign_bit)
|
||||||
goto skip;
|
goto skip;
|
||||||
rchar = '0';
|
rchar = '0';
|
||||||
break;
|
/* Scan for trailing zeros to see if we really need to round it. */
|
||||||
|
for(i = nbefore + nafter; i < ndigits; i++)
|
||||||
|
{
|
||||||
|
if (digits[i] != '0')
|
||||||
|
goto do_rnd;
|
||||||
|
}
|
||||||
|
goto skip;
|
||||||
case ROUND_DOWN:
|
case ROUND_DOWN:
|
||||||
if (!sign_bit)
|
if (!sign_bit)
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
@ -290,8 +294,6 @@ output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
|
||||||
else if (nbefore + nafter < ndigits)
|
else if (nbefore + nafter < ndigits)
|
||||||
{
|
{
|
||||||
i = ndigits = nbefore + nafter;
|
i = ndigits = nbefore + nafter;
|
||||||
if (d == 0 && digits[1] == '0')
|
|
||||||
goto skip;
|
|
||||||
if (digits[i] >= rchar)
|
if (digits[i] >= rchar)
|
||||||
{
|
{
|
||||||
/* Propagate the carry. */
|
/* Propagate the carry. */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue