Patchwork [libgfortran] PR48787 Invalid UP/DOWN rounding with F editing

login
register
mail settings
Submitter Jerry DeLisle
Date May 4, 2011, 3:19 a.m.
Message ID <4DC0C5C5.6010006@frontier.com>
Download mbox | patch
Permalink /patch/93968/
State New
Headers show

Comments

Jerry DeLisle - May 4, 2011, 3:19 a.m.
Hi Folks,

This patch fixes the latest 'round' of test cases from Thomas.  The patch 
adjusts the count of digits before the decimal point by one where w>0 and d==0. 
  The patch also consolidates some of the code as a clean up.

Regression tested on x86-64.  Revised test case attached.

OK for trunk?

Jerry

2011-05-03  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/48787
	* io/write_float.def (output_float): Adjust up and down rounding for
	cases where 'd' = 0. Gather common code to one location.
! { 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")
    call checkfmt("(RU,1P,E17.0)", 2.5,  "           3.E+00")
    call checkfmt("(RU,ES17.0)", 2.5,    "           3.E+00")
    call checkfmt("(RU,EN17.0)", 2.5,    "           3.E+00")
    call checkfmt("(RU,F2.0)",      2.0,  "2.")
    call checkfmt("(RU,F6.4)",      2.0,  "2.0000")
    call checkfmt("(RU,1P,E6.0E2)", 2.0,  "2.E+00")
    call checkfmt("(RU,1P,E7.1E2)", 2.5,  "2.5E+00")
    call checkfmt("(RU,1P,E10.4E2)", 2.5,  "2.5000E+00")
    call checkfmt("(RU,1P,G6.0E2)", 2.0,  "2.E+00")
    call checkfmt("(RU,1P,G10.4E2)", 2.3456e5,  "2.3456E+05")

    call checkfmt("(RU,F2.0)",     0.09,  "1.")     ! 0.
    call checkfmt("(RD,F3.0)",     -0.09,  "-1.")     ! -0.
    call checkfmt("(RU,F2.0)",      2.0,  "2.")     ! 3.
    call checkfmt("(RD,F3.0)",     -2.0,  "-2.")     ! -3.
    call checkfmt("(RU,F6.4)",      2.0,  "2.0000")     ! 2.0001
    call checkfmt("(RD,F7.4)",     -2.0,  "-2.0000")     ! -2.0001
    call checkfmt("(RU,1P,E6.0E2)", 2.0,  "2.E+00") ! 3.E+00
    call checkfmt("(RD,1P,E7.0E2)", -2.0,  "-2.E+00") ! -3.E+00
    call checkfmt("(RU,1P,E7.1E2)", 2.5,  "2.5E+00") ! 2.6E+00
    call checkfmt("(RD,1P,E8.1E2)", -2.5,  "-2.5E+00") ! -2.6E+00
    call checkfmt("(RU,1P,E10.4E2)", 2.5,  "2.5000E+00") ! 2.5001E+00
    call checkfmt("(RD,1P,E11.4E2)", -2.5,  "-2.5000E+00") ! -2.5001E+00
    call checkfmt("(RU,1P,G6.0E2)", 2.0,  "2.E+00") ! 3.E+00
    call checkfmt("(RD,1P,G7.0E2)", -2.0,  "-2.E+00") ! -3.E+00
    call checkfmt("(RU,1P,G10.4E2)", 2.3456e5,  "2.3456E+05") ! 2.3457E+05
    call checkfmt("(RD,1P,G11.4E2)", -2.3456e5,  "-2.3456E+05") ! -2.3457E+05

    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")
    call checkfmt("(RC,1P,E17.0)", 2.5,  "           3.E+00")
    call checkfmt("(RC,ES17.0)", 2.5,    "           3.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")
    call checkfmt("(RC,1P,E17.0)", -2.5,  "          -3.E+00")
    call checkfmt("(RC,ES17.0)", -2.5,    "          -3.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")
    call checkfmt("(RD,E17.1)", nearest(3.0, -1.0),    "          0.2E+01")

contains
    subroutine checkfmt(fmt, x, cmp)
        character(len=*), intent(in) :: fmt
        real, intent(in) :: x
        character(len=*), intent(in) :: cmp
        character(len=20) :: 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
Janne Blomqvist - May 4, 2011, 7:22 p.m.
On Wed, May 4, 2011 at 06:19, Jerry DeLisle <jvdelisle@frontier.com> wrote:
> Hi Folks,
>
> This patch fixes the latest 'round' of test cases from Thomas.  The patch
> adjusts the count of digits before the decimal point by one where w>0 and
> d==0.  The patch also consolidates some of the code as a clean up.
>
> Regression tested on x86-64.  Revised test case attached.
>
> OK for trunk?

Ok.

Patch

Index: write_float.def
===================================================================
--- write_float.def	(revision 173234)
+++ write_float.def	(working copy)
@@ -221,6 +221,7 @@  output_float (st_parameter_dt *dtp, const fnode *f
 
   if (zero_flag)
     goto skip;
+
   /* 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)
@@ -230,19 +231,11 @@  output_float (st_parameter_dt *dtp, const fnode *f
       case ROUND_UP:
 	if (sign_bit)
 	  goto skip;
-	rchar = '0';
-	/* 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;
+	goto updown;
       case ROUND_DOWN:
 	if (!sign_bit)
 	  goto skip;
-	rchar = '0';
-	break;
+	goto updown;
       case ROUND_NEAREST:
 	/* Round compatible unless there is a tie. A tie is a 5 with
 	   all trailing zero's.  */
@@ -254,7 +247,7 @@  output_float (st_parameter_dt *dtp, const fnode *f
 		if (digits[i] != '0')
 		  goto do_rnd;
 	      }
-	    /* It is a  tie so round to even.  */
+	    /* It is a tie so round to even.  */
 	    switch (digits[nafter + nbefore - 1])
 	      {
 		case '1':
@@ -274,8 +267,21 @@  output_float (st_parameter_dt *dtp, const fnode *f
       case ROUND_UNSPECIFIED:
       case ROUND_COMPATIBLE:
 	rchar = '5';
-	/* Just fall through and do the actual rounding.  */
+	goto do_rnd;
     }
+
+  updown:
+
+  rchar = '0';
+  if (w > 0 && d == 0 && p == 0)
+    nbefore = 1;
+  /* 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;
     
   do_rnd: