This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch, libgfortran] PR32611 Print sign of negative zero


Jerry DeLisle wrote:
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?

After due consideration. This is what I have decided.

I have provided a compile time flag, -fsign-zero that enables the negative sign on zero values. This is the default behavior.

-fno-sign-zero disables the negative sign. Though probably never used, it is there for anyone who comes upon an old application where it might matter.

I plan to commit the patch today or tomorrow. The patch will include fixes for test cases already submitted in the first patch I gave in this thread.

The flag has no effect on the behavior of the sign intrinsic like is done in ifort. If someone wants to do that, the flag will be there to use.

I will update the ChangeLog entries. Fully regression tested and NIST tested. NIST passes with -fno-sign-zero.

Regards,

Jerry

Index: runtime/compile_options.c
===================================================================
--- runtime/compile_options.c	(revision 126610)
+++ runtime/compile_options.c	(working copy)
@@ -1,5 +1,5 @@
 /* Handling of compile-time options that influence the library.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
 
 This file is part of the GNU Fortran 95 runtime library (libgfortran).
 
@@ -38,20 +38,21 @@ compile_options_t compile_options;
 
 /* Prototypes */
 extern void set_std (GFC_INTEGER_4, GFC_INTEGER_4, GFC_INTEGER_4,
-		     GFC_INTEGER_4, GFC_INTEGER_4);
+		     GFC_INTEGER_4, GFC_INTEGER_4, GFC_INTEGER_4);
 export_proto(set_std);
 
 
 void
 set_std (GFC_INTEGER_4 warn_std, GFC_INTEGER_4 allow_std,
 	 GFC_INTEGER_4 pedantic, GFC_INTEGER_4 dump_core,
-	 GFC_INTEGER_4 backtrace)
+	 GFC_INTEGER_4 backtrace, GFC_INTEGER_4 sign_zero)
 {
   compile_options.pedantic = pedantic;
   compile_options.warn_std = warn_std;
   compile_options.allow_std = allow_std;
   compile_options.dump_core = dump_core;
   compile_options.backtrace = backtrace;
+  compile_options.sign_zero = sign_zero;
 }
 
 
@@ -67,6 +68,7 @@ init_compile_options (void)
   compile_options.pedantic = 0;
   compile_options.dump_core = 0;
   compile_options.backtrace = 0;
+  compile_options.sign_zero = 1;
 }
 
 /* Function called by the front-end to tell us the
Index: libgfortran.h
===================================================================
--- libgfortran.h	(revision 126610)
+++ libgfortran.h	(working copy)
@@ -382,6 +382,7 @@ typedef struct
   int convert;
   int dump_core;
   int backtrace;
+  int sign_zero;
   size_t record_marker;
   int max_subrecord_length;
 }
Index: io/write.c
===================================================================
--- io/write.c	(revision 126610)
+++ 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.sign_zero == 1)
+        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.sign_zero == 1)
+        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);
Index: gfortran.h
===================================================================
--- gfortran.h	(revision 126610)
+++ gfortran.h	(working copy)
@@ -1861,6 +1861,7 @@ typedef struct
   int flag_cray_pointer;
   int flag_d_lines;
   int flag_openmp;
+  int flag_sign_zero;
 
   int fpe;
 
Index: lang.opt
===================================================================
--- lang.opt	(revision 126610)
+++ lang.opt	(working copy)
@@ -249,6 +249,10 @@ fshort-enums
 Fortran
 Use the narrowest integer type possible for enumeration types
 
+fsign-zero
+Fortran
+Apply negative sign to zero values
+
 funderscoring
 Fortran
 Append underscores to externally visible names
Index: trans-decl.c
===================================================================
--- trans-decl.c	(revision 126610)
+++ trans-decl.c	(working copy)
@@ -3158,7 +3158,7 @@ gfc_generate_function_code (gfc_namespac
   if (sym->attr.is_main_program)
     {
       tree gfc_int4_type_node = gfc_get_int_type (4);
-      tmp = build_call_expr (gfor_fndecl_set_std, 5,
+      tmp = build_call_expr (gfor_fndecl_set_std, 6,
 			     build_int_cst (gfc_int4_type_node,
 					    gfc_option.warn_std),
 			     build_int_cst (gfc_int4_type_node,
@@ -3168,7 +3168,9 @@ gfc_generate_function_code (gfc_namespac
 			     build_int_cst (gfc_int4_type_node,
 					    gfc_option.flag_dump_core),
 			     build_int_cst (gfc_int4_type_node,
-					    gfc_option.flag_backtrace));
+					    gfc_option.flag_backtrace),
+			     build_int_cst (gfc_int4_type_node,
+					    gfc_option.flag_sign_zero));
       gfc_add_expr_to_block (&body, tmp);
     }
 
Index: options.c
===================================================================
--- options.c	(revision 126610)
+++ options.c	(working copy)
@@ -102,6 +102,7 @@ gfc_init_options (unsigned int argc ATTR
   gfc_option.flag_cray_pointer = 0;
   gfc_option.flag_d_lines = -1;
   gfc_option.flag_openmp = 0;
+  gfc_option.flag_sign_zero = 1;
 
   gfc_option.fpe = 0;
 
@@ -619,6 +620,10 @@ gfc_handle_option (size_t scode, const c
       gfc_handle_module_path_options (arg);
       break;
     
+    case OPT_fsign_zero:
+      gfc_option.flag_sign_zero = value;
+      break;
+    
     case OPT_ffpe_trap_:
       gfc_handle_fpe_trap_option (arg);
       break;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]