On 04/27/2011 12:57 PM, Janne Blomqvist wrote:
On Wed, Apr 27, 2011 at 08:53, Janne Blomqvist
<blomqvist.ja...@gmail.com>  wrote:
On Wed, Apr 27, 2011 at 07:09, Jerry DeLisle<jvdeli...@frontier.com>  wrote:
On 04/25/2011 07:36 AM, Janne Blomqvist wrote:

On Mon, Apr 25, 2011 at 14:44, Jerry DeLisle<jvdeli...@frontier.com>
  wrote:

On 04/25/2011 03:48 AM, Janne Blomqvist wrote:

Now, for one of the testcase changes:

--- gcc/testsuite/gfortran.dg/char4_iunit_1.f03 (revision 172909)
+++ gcc/testsuite/gfortran.dg/char4_iunit_1.f03 (working copy)
@@ -24,11 +24,11 @@ program char4_iunit_1
    write(string, *) .true., .false. , .true.
    if (string .ne. 4_" T F T                                    ") call
abort
    write(string, *) 1.2345e-06, 4.2846e+10_8
-  if (string .ne. 4_"  1.23450002E-06   42846000000.000000     ") call
abort
+  if (string .ne. 4_"  1.234500019E-06   42846000000.000000    ") call
abort

This looks wrong. For correctly rounded REAL(4) output, we need 9
significant digits, but here we print 10.


Well, I bumped it up for defaults based on pr48488 comment #2 shown
below.

Yes, that comment in the PR is correct; to guarantee that a
binary->ascii->binary roundtrip preserves the original binary value
(with the default "round to nearest, break on even" rounding mode),
one must output at least {9, 17, 21, 36} significant digits for real
kinds 4, 8, 10, and 16, respectively (yes, I double-checked IEEE
754-2008 that this is indeed correct).

Since for the G edit descriptor d is equivalent to the number of
significant digits, AFAICS the write.c patch below is correct and the
bug must be elsewhere, no?


No.

Look at this example:

program t4
  implicit none
  character(len=44) :: string
  write(*,*) 1.2345e-06, 4.2846e+10_8
  write(*,'(1x,1pG16.9e2,1x,1pG25.17e3)') 1.2345e-06, 4.2846e+10_8
  write(*,'(1x,1pG15.8e2,1x,1pG25.17e3)') 1.2345e-06, 4.2846e+10_8
end program t4

This gives with the patch:

  1.234500019E-06   42846000000.000000
  1.234500019E-06   42846000000.000000
  1.23450002E-06   42846000000.000000

And without the patch:

  1.23450002E-06   42846000000.000000
  1.234500019E-06   42846000000.000000
  1.23450002E-06   42846000000.000000

d is the number of digits after the decimal point, not the number of
significant digits.

I stand corrected. Or well, I still stand by my previous statement
that with the G edit descriptor d corresponds to the number of
significant digits. However, only when not using the scale factor.

Since we use a scale factor of 1, when the magnitude of the number is
such that the E edit descriptor is used, according to F2008 10.7.2.3.3
paragraph 6 for 0<  k<  d+2 we must print k significant digits to the
left of the decimal point and d-k+1 to the right. That is, with k=1 we
print one digit to the left of the decimal point and d-1+1=d to the
right which has the effect of increasing the number of significant
digits by one!

However, when the magnitude of the value is such that F editing is
used, the scale factor has no effect and we thus print d significant
digits.

So in order to guarantee an exact binary<->ascii roundtrip we must
accept an extra digit in some cases. Or then do something which would
make list formatted (and perhaps G0 as well?) write differ from 1PGw.d
(effectively, reduce d by one when the magnitude is such that E
editing is used)?

That is, what about something like the attached patch on top of your
patch. With the patch, the test program

program t4
  implicit none
  character(len=44) :: string
  write(*,*) 1.2345e-06, 4.2846e+10_8, 1.1
  write(*,'(1x,1pG16.9e2,1x,1pG25.17e3)') 1.2345e-06, 4.2846e+10_8
  write(*,'(1x,1pG15.8e2,1x,1pG25.17e3)') 1.2345e-06, 4.2846e+10_8
  write(*,'(1x,1pG0,1x,1pG0)') 1.2345e-06, 1.1
  write(*,'(1x,1pG0.9,1x,1pG0.9)') 1.2345e-06, 1.1
end program t4

outputs

    1.23450002E-06   42846000000.000000        1.10000002
   1.234500019E-06   42846000000.000000
   1.23450002E-06   42846000000.000000
  1.23450002E-06 1.10000002
  1.234500019E-06 1.10000002

So the change is that now it prints the same number of significant
digits in E and F mode, both for list formatted output and kPG0 when
k>=0. For list formatted we can do pretty much what we want, and for
G0 the standard only says the processor can choose appropriate values
for w, d, and e. So far we have chosen d and e only based on the kind,
but AFAICS nothing prevents taking into account the magnitude as well.

I haven't modified any of the testcases so I expect some number of
regressions due to that, but I'm asking for opinions on the approach
itself before doing that.


Actually only saw one test case failure which I have adjusted. The attached patch applies Janne's patch to my patch and the fix for pr48787. Regression tested on x86-64.

OK for trunk?  I sure would like to get this in so I can move on to other 
things.

Jerry
Index: gcc/testsuite/gfortran.dg/fmt_g.f
===================================================================
--- gcc/testsuite/gfortran.dg/fmt_g.f	(revision 172909)
+++ gcc/testsuite/gfortran.dg/fmt_g.f	(working copy)
@@ -31,13 +31,13 @@
        WRITE(buffer,"(G12.5E5,'<')") -10000.
        if (buffer.ne."************<") call abort
        WRITE(buffer,"(G13.5E5,'<')") -10000.
-       if (buffer.ne."-10000.      <") call abort
+       if (buffer.ne."*************<") call abort
        WRITE(buffer,"(G14.5E5,'<')") -10000.
-       if (buffer.ne." -10000.      <") call abort
+       if (buffer.ne."-10000.       <") call abort
        WRITE(buffer,"(G15.5E5,'<')") -10000.
-       if (buffer.ne."  -10000.      <") call abort
+       if (buffer.ne." -10000.       <") call abort
        WRITE(buffer,"(G16.5E5,'<')") -10000.
-       if (buffer.ne."   -10000.      <") call abort
+       if (buffer.ne."  -10000.       <") call abort
 
        STOP
        END
Index: gcc/testsuite/gfortran.dg/fmt_g0_1.f08
===================================================================
--- gcc/testsuite/gfortran.dg/fmt_g0_1.f08	(revision 172909)
+++ gcc/testsuite/gfortran.dg/fmt_g0_1.f08	(working copy)
@@ -2,19 +2,19 @@
 ! PR36420 Fortran 2008: g0 edit descriptor 
 ! Test case provided by Jerry DeLisle <jvdeli...@gcc.gnu.org>
     character(25) :: string = "(g0,g0,g0)" 
-    character(33) :: buffer
+    character(50) :: buffer
     write(buffer, '(g0,g0,g0)') ':',12340,':'
     if (buffer.ne.":12340:") call abort
     write(buffer, string) ':',0,':'
     if (buffer.ne.":0:") call abort
-    write(buffer, string) ':',1.0/3.0,':'
-    if (buffer.ne.":.33333334:") call abort
-    write(buffer, '(1x,a,g0,a)') ':',1.0/3.0,':'
-    if (buffer.ne." :.33333334:") call abort
+    write(buffer, string) ':',1.0_8/3.0_8,':'
+    if (buffer.ne.":.33333333333333331:") call abort
+    write(buffer, '(1x,a,g0,a)') ':',1.0_8/3.0_8,':'
+    if (buffer.ne." :.33333333333333331:") call abort
     write(buffer, string) ':',"hello",':'
-    if (buffer.ne.":hello:") call abort
+    if (buffer.ne.":hello:") call abort 
     write(buffer, "(g0,g0,g0,g0)") ':',.true.,.false.,':'
     if (buffer.ne.":TF:") call abort
-    write(buffer, "(g0,g0,',',g0,g0)") '(',( 1.2345, 2.4567 ),')'
-    if (buffer.ne."(1.2345001,2.4567001)") call abort
+    write(buffer, "(g0,g0,',',g0,g0)") '(',( 1.2345_8, 2.4567_8 ),')'
+    if (buffer.ne."(1.2344999999999999,2.4567000000000001)") call abort
 end
Index: gcc/testsuite/gfortran.dg/round_3.f08
===================================================================
--- gcc/testsuite/gfortran.dg/round_3.f08	(revision 0)
+++ gcc/testsuite/gfortran.dg/round_3.f08	(revision 0)
@@ -0,0 +1,75 @@
+! { dg-do run }
+! PR48615 Invalid UP/DOWN rounding with E and ES descriptors
+! Test case provided by Thomas Henlich.
+program pr48615
+    call checkfmt("(RU,F17.0)", 2.5,     "               3.")
+    call checkfmt("(RU,-1P,F17.1)", 2.5, "              0.3")
+    call checkfmt("(RU,E17.1)", 2.5,     "          0.3E+01") ! 0.2E+01
+    call checkfmt("(RU,1P,E17.0)", 2.5,  "           3.E+00")
+    call checkfmt("(RU,ES17.0)", 2.5,    "           3.E+00") ! 2.E+00
+    call checkfmt("(RU,EN17.0)", 2.5,    "           3.E+00")
+
+    call checkfmt("(RD,F17.0)", 2.5,     "               2.")
+    call checkfmt("(RD,-1P,F17.1)", 2.5, "              0.2")
+    call checkfmt("(RD,E17.1)", 2.5,     "          0.2E+01")
+    call checkfmt("(RD,1P,E17.0)", 2.5,  "           2.E+00")
+    call checkfmt("(RD,ES17.0)", 2.5,    "           2.E+00")
+    call checkfmt("(RD,EN17.0)", 2.5,    "           2.E+00")
+
+    call checkfmt("(RC,F17.0)", 2.5,     "               3.")
+    call checkfmt("(RC,-1P,F17.1)", 2.5, "              0.3")
+    call checkfmt("(RC,E17.1)", 2.5,     "          0.3E+01") ! 0.2E+01
+    call checkfmt("(RC,1P,E17.0)", 2.5,  "           3.E+00")
+    call checkfmt("(RC,ES17.0)", 2.5,    "           3.E+00") ! 2.E+00
+    call checkfmt("(RC,EN17.0)", 2.5,    "           3.E+00")
+
+    call checkfmt("(RN,F17.0)", 2.5,     "               2.")
+    call checkfmt("(RN,-1P,F17.1)", 2.5, "              0.2")
+    call checkfmt("(RN,E17.1)", 2.5,     "          0.2E+01")
+    call checkfmt("(RN,1P,E17.0)", 2.5,  "           2.E+00")
+    call checkfmt("(RN,ES17.0)", 2.5,    "           2.E+00")
+    call checkfmt("(RN,EN17.0)", 2.5,    "           2.E+00")
+
+    call checkfmt("(RZ,F17.0)", 2.5,     "               2.")
+    call checkfmt("(RZ,-1P,F17.1)", 2.5, "              0.2")
+    call checkfmt("(RZ,E17.1)", 2.5,     "          0.2E+01")
+    call checkfmt("(RZ,1P,E17.0)", 2.5,  "           2.E+00")
+    call checkfmt("(RZ,ES17.0)", 2.5,    "           2.E+00")
+    call checkfmt("(RZ,EN17.0)", 2.5,    "           2.E+00")
+
+    call checkfmt("(RZ,F17.0)", -2.5,     "              -2.")
+    call checkfmt("(RZ,-1P,F17.1)", -2.5, "             -0.2")
+    call checkfmt("(RZ,E17.1)", -2.5,     "         -0.2E+01")
+    call checkfmt("(RZ,1P,E17.0)", -2.5,  "          -2.E+00")
+    call checkfmt("(RZ,ES17.0)", -2.5,    "          -2.E+00")
+    call checkfmt("(RZ,EN17.0)", -2.5,    "          -2.E+00")
+
+    call checkfmt("(RN,F17.0)", -2.5,     "              -2.")
+    call checkfmt("(RN,-1P,F17.1)", -2.5, "             -0.2")
+    call checkfmt("(RN,E17.1)", -2.5,     "         -0.2E+01")
+    call checkfmt("(RN,1P,E17.0)", -2.5,  "          -2.E+00")
+    call checkfmt("(RN,ES17.0)", -2.5,    "          -2.E+00")
+    call checkfmt("(RN,EN17.0)", -2.5,    "          -2.E+00")
+
+    call checkfmt("(RC,F17.0)", -2.5,     "              -3.")
+    call checkfmt("(RC,-1P,F17.1)", -2.5, "             -0.3")
+    call checkfmt("(RC,E17.1)", -2.5,     "         -0.3E+01") ! -0.2E+01
+    call checkfmt("(RC,1P,E17.0)", -2.5,  "          -3.E+00")
+    call checkfmt("(RC,ES17.0)", -2.5,    "          -3.E+00") ! -2.E+00
+    call checkfmt("(RC,EN17.0)", -2.5,    "          -3.E+00")
+
+    call checkfmt("(RU,E17.1)", nearest(2.0, 1.0),     "          0.3E+01") ! 0.2E+01
+    call checkfmt("(RD,E17.1)", nearest(3.0, -1.0),    "          0.2E+01") ! 0.3E+01
+
+contains
+    subroutine checkfmt(fmt, x, cmp)
+        character(len=*), intent(in) :: fmt
+        real, intent(in) :: x
+        character(len=*), intent(in) :: cmp
+        character(len=40) :: s
+        
+        write(s, fmt) x
+        if (s /= cmp) call abort
+        !if (s /= cmp) print "(a,1x,a,' expected: ',1x)", fmt, s, cmp
+    end subroutine
+end program
Index: gcc/testsuite/gfortran.dg/namelist_print_1.f
===================================================================
--- gcc/testsuite/gfortran.dg/namelist_print_1.f	(revision 172909)
+++ gcc/testsuite/gfortran.dg/namelist_print_1.f	(working copy)
@@ -9,5 +9,5 @@
       namelist /mynml/ x
       x = 1
 ! ( dg-output "^" }
-      print mynml ! { dg-output "&MYNML(\n|\r\n|\r) X=  1.0000000    ,(\n|\r\n|\r) /(\n|\r\n|\r)" }
+      print mynml ! { dg-output "&MYNML(\n|\r\n|\r) X=  1.00000000    ,(\n|\r\n|\r) /(\n|\r\n|\r)" }
       end
Index: gcc/testsuite/gfortran.dg/char4_iunit_1.f03
===================================================================
--- gcc/testsuite/gfortran.dg/char4_iunit_1.f03	(revision 172909)
+++ gcc/testsuite/gfortran.dg/char4_iunit_1.f03	(working copy)
@@ -5,7 +5,7 @@
 ! Test case prepared by Jerry DeLisle  <jvdeli...@gcc.gnu.org>
 program char4_iunit_1
   implicit none
-  character(kind=4,len=42) :: string
+  character(kind=4,len=44) :: string
   integer(kind=4) :: i,j
   real(kind=4) :: inf, nan, large
 
@@ -24,11 +24,11 @@ program char4_iunit_1
   write(string, *) .true., .false. , .true.
   if (string .ne. 4_" T F T                                    ") call abort
   write(string, *) 1.2345e-06, 4.2846e+10_8
-  if (string .ne. 4_"  1.23450002E-06   42846000000.000000     ") call abort
+  if (string .ne. 4_"   1.23450002E-06   42846000000.000000      ") call abort
   write(string, *) nan, inf
-  if (string .ne. 4_"             NaN        Infinity          ") call abort
+  if (string .ne. 4_"              NaN         Infinity    ") call abort
   write(string, '(10x,f3.1,3x,f9.1)') nan, inf
-  if (string .ne. 4_"          NaN    Infinity                 ") call abort
+  if (string .ne. 4_"          NaN    Infinity             ") call abort
   write(string, *) (1.2, 3.4 )
-  if (string .ne. 4_" (  1.2000000    ,  3.4000001    )        ") call abort
+  if (string .ne. 4_" (  1.20000005    ,  3.40000010    )  ") call abort
 end program char4_iunit_1
Index: gcc/testsuite/gfortran.dg/f2003_io_5.f03
===================================================================
--- gcc/testsuite/gfortran.dg/f2003_io_5.f03	(revision 172909)
+++ gcc/testsuite/gfortran.dg/f2003_io_5.f03	(working copy)
@@ -5,7 +5,7 @@ integer :: i
 real :: a(10) = [ (i*1.3, i=1,10) ]
 real :: b(10)
 complex :: c
-character(34) :: complex
+character(36) :: complex
 namelist /nm/ a
 
 open(99,file="mynml",form="formatted",decimal="point",status="replace")
@@ -18,9 +18,9 @@ close(99, status="delete")
 
 c = (3.123,4.456)
 write(complex,*,decimal="comma") c
-if (complex.ne." (  3,1229999    ;  4,4559999    )") call abort
+if (complex.ne." (  3,12299991    ;  4,45599985    )") call abort
 c = (0.0, 0.0)
 read(complex,*,decimal="comma") c
-if (complex.ne." (  3,1229999    ;  4,4559999    )") call abort
+if (complex.ne." (  3,12299991    ;  4,45599985    )") call abort
 
 end
Index: gcc/testsuite/gfortran.dg/coarray_15.f90
===================================================================
--- gcc/testsuite/gfortran.dg/coarray_15.f90	(revision 172909)
+++ gcc/testsuite/gfortran.dg/coarray_15.f90	(working copy)
@@ -9,7 +9,7 @@ program ex2
       implicit none
       real, allocatable :: z(:)[:]
       integer :: image
-      character(len=80) :: str
+      character(len=128) :: str
 
       allocate(z(3)[*])
       write(*,*) 'z allocated on image',this_image()
@@ -25,18 +25,18 @@ program ex2
 
       str = repeat('X', len(str))
       write(str,*) 'z=',z(:),' on image',this_image()
-      if (str /= " z=   1.2000000       1.2000000       1.2000000      on image           1") &
-        call abort ()
+      if (str /= " z=   1.20000005       1.20000005       1.20000005      on image           1") &
+        call abort
 
       str = repeat('X', len(str))
       write(str,*) 'z=',z,' on image',this_image()
-      if (str /= " z=   1.2000000       1.2000000       1.2000000      on image           1") &
-        call abort ()
+      if (str /= " z=   1.20000005       1.20000005       1.20000005      on image           1") &
+        call abort
 
       str = repeat('X', len(str))
       write(str,*) 'z=',z(1:3)[this_image()],' on image',this_image()
-      if (str /= " z=   1.2000000       1.2000000       1.2000000      on image           1") &
-        call abort ()
+      if (str /= " z=   1.20000005       1.20000005       1.20000005      on image           1") &
+        call abort
 
       call ex2a()
       call ex5()
@@ -46,7 +46,7 @@ subroutine ex2a()
       implicit none
       real, allocatable :: z(:,:)[:,:]
       integer :: image
-      character(len=100) :: str
+      character(len=128) :: str
 
       allocate(z(2,2)[1,*])
       write(*,*) 'z allocated on image',this_image()
@@ -62,38 +62,38 @@ subroutine ex2a()
 
       str = repeat('X', len(str))
       write(str,*) 'z=',z(:,:),' on image',this_image()
-      if (str /= " z=   1.2000000       1.2000000       1.2000000       1.2000000      on image           1") &
-        call abort ()
+      if (str /= " z=   1.20000005       1.20000005       1.20000005       1.20000005      on image           1") &
+        call abort
 
       str = repeat('X', len(str))
       write(str,*) 'z=',z,' on image',this_image()
-      if (str /= " z=   1.2000000       1.2000000       1.2000000       1.2000000      on image           1") &
-        call abort ()
+      if (str /= " z=   1.20000005       1.20000005       1.20000005       1.20000005      on image           1") &
+        call abort
 end subroutine ex2a
 
 subroutine ex5
    implicit none
    integer :: me
    real, save :: w(4)[*]
-   character(len=100) :: str
+   character(len=128) :: str
 
    me = this_image()
    w = me
 
    str = repeat('X', len(str))
    write(str,*) 'In main on image',this_image(), 'w= ',w 
-   if (str /= " In main on image           1 w=    1.0000000       1.0000000       1.0000000       1.0000000") &
-     call abort ()
+   if (str /= " In main on image           1 w=    1.00000000       1.00000000       1.00000000       1.00000000") &
+        call abort
 
    str = repeat('X', len(str))
    write(str,*) 'In main on image',this_image(), 'w= ',w(1:4) 
-   if (str /= " In main on image           1 w=    1.0000000       1.0000000       1.0000000       1.0000000") &
-     call abort ()
+   if (str /= " In main on image           1 w=    1.00000000       1.00000000       1.00000000       1.00000000") &
+        call abort
 
    str = repeat('X', len(str))
    write(str,*) 'In main on image',this_image(), 'w= ',w(:)[1]
-   if (str /= " In main on image           1 w=    1.0000000       1.0000000       1.0000000       1.0000000") &
-     call abort ()
+   if (str /= " In main on image           1 w=    1.00000000       1.00000000       1.00000000       1.00000000") &
+        call abort
 
    sync all
    call ex5_sub(me,w)
@@ -103,10 +103,10 @@ subroutine ex5_sub(n,w)
    implicit none
    integer :: n
    real :: w(n)
-   character(len=50) :: str
+   character(len=75) :: str
 
    str = repeat('X', len(str))
    write(str,*) 'In sub on image',this_image(), 'w= ',w 
-   if (str /= " In sub on image           1 w=    1.0000000") &
-     call abort ()
+   if (str /= " In sub on image           1 w=    1.00000000") &
+        call abort
 end subroutine ex5_sub
Index: gcc/testsuite/gfortran.dg/namelist_65.f90
===================================================================
--- gcc/testsuite/gfortran.dg/namelist_65.f90	(revision 172909)
+++ gcc/testsuite/gfortran.dg/namelist_65.f90	(working copy)
@@ -14,9 +14,9 @@ enddo
 
 write(out,nl1)
 if (out(1).ne."&NL1") call abort
-if (out(2).ne." A=  1.0000000    ,") call abort
-if (out(3).ne." B=  2.0000000    ,") call abort
-if (out(4).ne." C=  3.0000000    ,") call abort
+if (out(2).ne." A=  1.00000000    ,") call abort
+if (out(3).ne." B=  2.00000000    ,") call abort
+if (out(4).ne." C=  3.00000000    ,") call abort
 if (out(5).ne." /") call abort
 
 end program oneline
Index: gcc/testsuite/gfortran.dg/fmt_cache_1.f
===================================================================
--- gcc/testsuite/gfortran.dg/fmt_cache_1.f	(revision 172909)
+++ gcc/testsuite/gfortran.dg/fmt_cache_1.f	(working copy)
@@ -3,9 +3,10 @@
 ! pr40330  incorrect io.
 ! test case derived from pr40662, <jvdeli...@gcc.gnu.org>
       program astap
-      character(40) teststring
-      arlxca = 0.0
-      open(10, status="scratch")
+      implicit none
+      character(34) :: teststring
+      real(4) :: arlxca = 0.0
+      open(10)
       write(10,40) arlxca
       write(10,40) arlxca
 40    format(t4,"arlxca = ",1pg13.6,t27,"arlxcc = ",g13.6,t53,
@@ -21,13 +22,12 @@
      .            "ebalnc = ",g13.6,t79,"ebalsa = ",g13.6,t105,
      .            "ebalsc = ",g13.6)
       rewind 10
-      rewind 10
       teststring = ""
       read(10,'(a)') teststring
-      if (teststring.ne."   arlxca =   0.00000     arlxcc = ")call abort
+      if (teststring.ne."   arlxca =   0.00000     arlxcc =")call abort
       teststring = ""
       read(10,'(a)') teststring
-      if (teststring.ne."   arlxca =   0.00000     arlxcc = ")call abort
+      if (teststring.ne."   arlxca =   0.00000     arlxcc =")call abort
       end program astap
 
 
Index: gcc/testsuite/gfortran.dg/char4_iunit_2.f03
===================================================================
--- gcc/testsuite/gfortran.dg/char4_iunit_2.f03	(revision 172909)
+++ gcc/testsuite/gfortran.dg/char4_iunit_2.f03	(working copy)
@@ -43,5 +43,5 @@ program char4_iunit_2
   write(widestring,*)"test",i, x, str_default,&
    trim(str_char4)
   if (widestring .ne. &
-    k_" test         345   52.542999     0 hijklmnp qwertyuiopasd") call abort
+    k_" test         345   52.5429993     0 hijklmnp qwertyuiopasd") call abort
 end program char4_iunit_2
Index: gcc/testsuite/gfortran.dg/real_const_3.f90
===================================================================
--- gcc/testsuite/gfortran.dg/real_const_3.f90	(revision 172909)
+++ gcc/testsuite/gfortran.dg/real_const_3.f90	(working copy)
@@ -42,15 +42,15 @@ program main
   if (trim(adjustl(str)) .ne. 'NaN') call abort
 
   write(str,*) z
-  if (trim(adjustl(str)) .ne. '(            NaN,            NaN)') call abort
+  if (trim(adjustl(str)) .ne. '(             NaN,             NaN)') call abort
 
   write(str,*) z2
-  if (trim(adjustl(str)) .ne. '(            NaN,            NaN)') call abort
+  if (trim(adjustl(str)) .ne. '(             NaN,             NaN)') call abort
 
   write(str,*) z3
-  if (trim(adjustl(str)) .ne. '(       Infinity,      -Infinity)') call abort
+  if (trim(adjustl(str)) .ne. '(        Infinity,       -Infinity)') call abort
 
   write(str,*) z4
-  if (trim(adjustl(str)) .ne. '(  0.0000000    , -0.0000000    )') call abort
+  if (trim(adjustl(str)) .ne. '(  0.00000000    , -0.00000000    )') call abort
 
 end program main
Index: libgfortran/io/write.c
===================================================================
--- libgfortran/io/write.c	(revision 172909)
+++ libgfortran/io/write.c	(working copy)
@@ -1155,35 +1155,35 @@ write_z (st_parameter_dt *dtp, const fnode *f, con
 void
 write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
 {
-  write_float (dtp, f, p, len);
+  write_float (dtp, f, p, len, 0);
 }
 
 
 void
 write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
 {
-  write_float (dtp, f, p, len);
+  write_float (dtp, f, p, len, 0);
 }
 
 
 void
 write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
 {
-  write_float (dtp, f, p, len);
+  write_float (dtp, f, p, len, 0);
 }
 
 
 void
 write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
 {
-  write_float (dtp, f, p, len);
+  write_float (dtp, f, p, len, 0);
 }
 
 
 void
 write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
 {
-  write_float (dtp, f, p, len);
+  write_float (dtp, f, p, len, 0);
 }
 
 
@@ -1432,8 +1432,8 @@ set_fnode_default (st_parameter_dt *dtp, fnode *f,
   switch (length)
     {
     case 4:
-      f->u.real.w = 15;
-      f->u.real.d = 8;
+      f->u.real.w = 16;
+      f->u.real.d = 9;
       f->u.real.e = 2;
       break;
     case 8:
@@ -1442,13 +1442,13 @@ set_fnode_default (st_parameter_dt *dtp, fnode *f,
       f->u.real.e = 3;
       break;
     case 10:
-      f->u.real.w = 29;
-      f->u.real.d = 20;
+      f->u.real.w = 30;
+      f->u.real.d = 21;
       f->u.real.e = 4;
       break;
     case 16:
-      f->u.real.w = 44;
-      f->u.real.d = 35;
+      f->u.real.w = 45;
+      f->u.real.d = 36;
       f->u.real.e = 4;
       break;
     default:
@@ -1468,7 +1468,7 @@ write_real (st_parameter_dt *dtp, const char *sour
   int org_scale = dtp->u.p.scale_factor;
   dtp->u.p.scale_factor = 1;
   set_fnode_default (dtp, &f, length);
-  write_float (dtp, &f, source , length);
+  write_float (dtp, &f, source , length, 1);
   dtp->u.p.scale_factor = org_scale;
 }
 
@@ -1476,12 +1476,20 @@ write_real (st_parameter_dt *dtp, const char *sour
 void
 write_real_g0 (st_parameter_dt *dtp, const char *source, int length, int d)
 {
-  fnode f ;
+  fnode f;
+  int comp_d; 
   set_fnode_default (dtp, &f, length);
   if (d > 0)
     f.u.real.d = d;
+
+  /* Compensate for extra digits when using scale factor, d is not
+     specified, and the magnitude is such that E editing is used.  */
+  if (dtp->u.p.scale_factor > 0 && d == 0)
+    comp_d = 1;
+  else
+    comp_d = 0;
   dtp->u.p.g0_no_blanks = 1;
-  write_float (dtp, &f, source , length);
+  write_float (dtp, &f, source , length, comp_d);
   dtp->u.p.g0_no_blanks = 0;
 }
 
Index: libgfortran/io/write_float.def
===================================================================
--- libgfortran/io/write_float.def	(revision 172909)
+++ libgfortran/io/write_float.def	(working copy)
@@ -289,8 +289,9 @@ output_float (st_parameter_dt *dtp, const fnode *f
     }
   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, co
     { \
       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, co
 \
   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, co
 	}\
     }\
 \
-  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, co
 	  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 @@ static void
      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)
     {

Reply via email to