This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[patch, libgfortran] PR32611 Print sign of negative zero
- From: Jerry DeLisle <jvdelisle at verizon dot net>
- To: Fortran List <fortran at gcc dot gnu dot org>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 08 Jul 2007 22:34:14 -0700
- Subject: [patch, libgfortran] PR32611 Print sign of negative zero
The attached patch provides a solution to this PR.
The patch uses the signbit function to determine if a zero value is negative.
If so, the sign is emitted. If -std=legacy is specified at compile time, the
negative sign for zero values is not emitted.
This patch requires -std=legacy to be used to pass NIST. This is because F77
explicitly prohibits printing the negative sign for zero values.
No new test cases are required. The patch updates several to reflect the
change. One test, pr17706.f90, exercises the legacy behavior.
Regression tested on X86-64-Gnu/Linux.
OK for trunk?
Regards,
Jerry
2007-07-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/32611
* io/write.c (output_float): Use the sign bit of the value to determine
if a negative sign should be emitted for zero values. Do not emit the
negative sign for zero if -std=legacy was set during compile.
2007-07-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/32611
* gfortran.dg/large_real_kind_1.f90: Update test.
* gfortran.dg/pr17706.f90: Update test.
* gfortran.dg/fmt_zero_digits.f90: Update test.
* gfortran.dg/fmt_zero_precision.f90: Update test.
* gfortran.dg/real_const_3.f90: Update test.
Index: gcc/testsuite/gfortran.dg/large_real_kind_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/large_real_kind_1.f90 (revision 126472)
+++ gcc/testsuite/gfortran.dg/large_real_kind_1.f90 (working copy)
@@ -67,7 +67,7 @@ program test
x = tiny(x)
call outputstring (x,'(F20.15)',' 0.000000000000000')
- call outputstring (-x,'(F20.15)',' 0.000000000000000')
+ call outputstring (-x,'(F20.15)',' -0.000000000000000')
write (c1,'(G20.10E5)') x
write (c2,'(G20.10E5)') -x
Index: gcc/testsuite/gfortran.dg/pr17706.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pr17706.f90 (revision 126472)
+++ gcc/testsuite/gfortran.dg/pr17706.f90 (working copy)
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-options "-std=legacy" }
! PR17706
! this is a libgfortran test
! output value -0.00 is not standard compliant
Index: gcc/testsuite/gfortran.dg/fmt_zero_digits.f90
===================================================================
--- gcc/testsuite/gfortran.dg/fmt_zero_digits.f90 (revision 126472)
+++ gcc/testsuite/gfortran.dg/fmt_zero_digits.f90 (working copy)
@@ -6,5 +6,7 @@ program test
50 FORMAT (d20.0)
astr = ""
write(astr,50) -8.0D0
+ if (astr.ne." -0.D+01") call abort()
+ write(astr,50) 8.0D0
if (astr.ne." 0.D+01") call abort()
end program test
Index: gcc/testsuite/gfortran.dg/fmt_zero_precision.f90
===================================================================
--- gcc/testsuite/gfortran.dg/fmt_zero_precision.f90 (revision 126472)
+++ gcc/testsuite/gfortran.dg/fmt_zero_precision.f90 (working copy)
@@ -53,7 +53,7 @@
! { dg-output "-1\\.<(\n|\r\n|\r)" }
! { dg-output "-1\\.<(\n|\r\n|\r)" }
! { dg-output "-1\\.<(\n|\r\n|\r)" }
-! { dg-output " 0\\.<(\n|\r\n|\r)" }
+! { dg-output "-0\\.<(\n|\r\n|\r)" }
! { dg-output " 38\\.<(\n|\r\n|\r)" }
! { dg-output " 10345\\.<(\n|\r\n|\r)" }
! { dg-output " 334\\.<(\n|\r\n|\r)" }
Index: gcc/testsuite/gfortran.dg/real_const_3.f90
===================================================================
--- gcc/testsuite/gfortran.dg/real_const_3.f90 (revision 126472)
+++ gcc/testsuite/gfortran.dg/real_const_3.f90 (working copy)
@@ -38,4 +38,4 @@ end program main
!{ dg-output " \\( NaN, NaN\\)(\n|\r\n|\r)" }
!{ dg-output " \\( NaN, NaN\\)(\n|\r\n|\r)" }
!{ dg-output " \\( \\+Infinity, -Infinity\\)(\n|\r\n|\r)" }
-!{ dg-output " \\( 0.000000 , 0.000000 \\)(\n|\r\n|\r)" }
+!{ dg-output " \\( 0.000000 , -0.000000 \\)(\n|\r\n|\r)" }
Index: libgfortran/io/write.c
===================================================================
--- libgfortran/io/write.c (revision 126472)
+++ libgfortran/io/write.c (working copy)
@@ -465,6 +465,7 @@ output_float (st_parameter_dt *dtp, cons
int leadzero;
int nblanks;
int i;
+ int sign_bit;
sign_t sign;
ft = f->format;
@@ -482,6 +483,7 @@ output_float (st_parameter_dt *dtp, cons
For an N digit exponent, this gives us (MIN_FIELD_WIDTH-5)-N digits
after the decimal point, plus another one before the decimal point. */
sign = calculate_sign (dtp, value < 0.0);
+ sign_bit = signbit (value);
if (value < 0)
value = -value;
@@ -547,9 +549,15 @@ output_float (st_parameter_dt *dtp, cons
/* Read the exponent back in. */
e = atoi (&buffer[ndigits + 3]) + 1;
- /* Make sure zero comes out as 0.0e0. */
+ /* Make sure zero comes out as 0.0e0. */
if (value == 0.0)
- e = 0;
+ {
+ e = 0;
+ if (compile_options.warn_std != 0)
+ sign = calculate_sign(dtp, sign_bit);
+ else
+ sign = calculate_sign(dtp, 0);
+ }
/* Normalize the fractional component. */
buffer[2] = buffer[1];
@@ -751,7 +759,14 @@ output_float (st_parameter_dt *dtp, cons
break;
}
if (i == ndigits)
- sign = calculate_sign (dtp, 0);
+ {
+ /* The output is zero, so set the sign according to the sign bit unless
+ -std=legacy was specified. */
+ if (compile_options.warn_std != 0)
+ sign = calculate_sign(dtp, sign_bit);
+ else
+ sign = calculate_sign(dtp, 0);
+ }
/* Work out how much padding is needed. */
nblanks = w - (nbefore + nzero + nafter + edigits + 1);
@@ -776,7 +791,6 @@ output_float (st_parameter_dt *dtp, cons
/* Pad to full field width. */
-
if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
{
memset (out, ' ', nblanks);