Bug 41867 - Translation time Floating Point precision is too small
Summary: Translation time Floating Point precision is too small
Status: RESOLVED DUPLICATE of bug 323
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.4.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-10-29 15:13 UTC by Fred J. Tydeman
Modified: 2009-10-31 18:37 UTC (History)
67 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fred J. Tydeman 2009-10-29 15:13:39 UTC
The following code fails on (at least) Intel x86/x87 systems running Linux:

/*
 * From C99:
 * 6.6 Constant expressions
 *
 * #5 An expression that evaluates to a constant is required in several
 * contexts. If a floating expression is evaluated in the translation
 * environment, the arithmetic precision and range shall be at least
 * as great as if the expression were being evaluated in the execution
 * environment.
 */

#include <float.h>	/* *_EPSILON */
#include <stdio.h>	/* printf() */

/*
 * Compute epsilon == Unit Last Place; may be + or - depends upon rounding.
 */
#define Q2  (((4.F /3.F  - 1.F ) - 1.F /4.F )*3.F  - 1.F /4.F )

/*
 * File scope is translation time
 */
static long double fs_ld2 = Q2;
static double      fs_d2  = Q2;
static float       fs_f2  = Q2;

int main(void){

  /*
   * Local scope is runtime
   */
  long double ls_ld2 = Q2;
  double      ls_d2  = Q2;
  float       ls_f2  = Q2;

  if( fs_ld2 != ls_ld2 ){
    (void)printf(" 1: BFP: translation time != runtime\n");
  }

  if( fs_d2 != ls_d2 ){
    (void)printf(" 2: BFP: translation time != runtime\n");
  }

  if( fs_f2 != ls_f2 ){
    (void)printf(" 3: BFP: translation time != runtime\n");
  }


  if( fs_ld2 != fs_d2 ){
    (void)printf(" 7: BFP: translation time: variable precision\n");
  }

  if( fs_d2 != fs_f2 ){
    (void)printf(" 8: BFP: translation time: variable precision\n");
  }


  if( ls_ld2 != ls_d2 ){
    (void)printf("11: BFP:runtime: variable precision\n");
  }

  if( ls_d2 != ls_f2 ){
    (void)printf("12: BFP:runtime: variable precision\n");
  }

  (void)printf("ls_ld2=%Lg\n", ls_ld2);
  (void)printf("ls_d2 =%g\n",  ls_d2);
  (void)printf("ls_f2 =%g\n",  ls_f2);
  (void)printf("LD_EPS=%Lg\n", LDBL_EPSILON);
  (void)printf(" D_EPS=%g\n", DBL_EPSILON);
  (void)printf(" F_EPS=%g\n", FLT_EPSILON);
  (void)printf("fs_ld2=%Lg\n", fs_ld2);
  (void)printf("fs_d2 =%g\n",  fs_d2);
  (void)printf("fs_f2 =%g\n",  fs_f2);

  return 0;
}
Comment 1 jsm-csl@polyomino.org.uk 2009-10-29 15:47:47 UTC
Subject: Re:   New: Translation time Floating Point precision
 is too small

On Thu, 29 Oct 2009, tydeman at tybor dot com wrote:

> The following code fails on (at least) Intel x86/x87 systems running Linux:

Please explain what you mean by "fails".  With what options did you 
compile it?  How was GCC configured?  What did it output?  What did you 
want it to output instead?  Why do you think what it output was wrong?

Comment 2 Fred J. Tydeman 2009-10-29 19:27:28 UTC
Compile options: -std=gnu99 -pedantic -H -fno-builtin -frounding-math
Since I take the gcc that comes with Fedora Core Linux 9 and 10, I have
no idea how GCC was configured.  
The output shows that all the file scope (translation time) precisions 
used were small (ULP is same magnitude as FLT_EPSILON), while all the 
local scope (runtime) precisions used were large (ULP same magnitude as 
LDBL_EPSILON).  All six should be the same magnitude as LDBL_EPSILON for 
this hardware.  
None of the messages with 1:, 2:, 3:, 7:, 8:, 11:, or 12: should be printed 
if things are done as per the C standard.  
A large precision implies a small magnitude ULP value (closer to zero).
Comment 3 Joseph S. Myers 2009-10-29 20:26:34 UTC
If you want C99-conforming excess precision, then use 4.5 or later (not 4.4)
with -fexcess-precision=standard or strict conformance options such as
-std=c99 that imply it (not -std=gnu99).  With that I get:

ls_ld2=1.0842e-19
ls_d2 =1.0842e-19
ls_f2 =1.0842e-19
LD_EPS=1.0842e-19
 D_EPS=2.22045e-16
 F_EPS=1.19209e-07
fs_ld2=1.0842e-19
fs_d2 =1.0842e-19
fs_f2 =1.0842e-19

which I think is what you want.


*** This bug has been marked as a duplicate of 323 ***
Comment 4 Fred J. Tydeman 2009-10-31 17:42:48 UTC
The requirement that translation time precision be at least as great as runtime
precision existed in C89, C90, C95, and C99 (so has been around for 20 years).

My code is a test of translation time precision versus runtime precision.

The first code I saw in bug 323 involved 3 auto variables (so is just runtime).
That is a different issue, so I believe that this bug is not a duplicate of 323.

I used gnu99 instead of c99 for the std because I also am testing Decimal FP
in addition to Binary FP.  Where should I find documentation on compiler
options to get as close to C99 conformance as possible?  Also, C99 + Decimal
FP conformance?

The output you show is what I expected.
Comment 5 Joseph S. Myers 2009-10-31 18:37:04 UTC
323 covers all excess precision issues.  Predictable results that do
not depend on when a computation is carried out require
-fexcess-precision=standard which requires 4.5.  It so happens that all
C conformance options, including -std=c89, enable -fexcess-precision=standard;
although C90 does not define any standard binding to excess precision such
as C99 does with FLT_EVAL_METHOD, enabling it for C90 conformance seemed the
best compromise.

Options are documented in the GCC manual (specifically, invoke.texi
in the GCC sources).  The closest conformance options are
-std={c89,iso9899:199409,c99} -pedantic (or -pedantic-errors if you want
errors for constraint violations).  There are no known target-independent
conformance bugs in -std=c89 -pedantic or -std=iso9899:199409 -pedantic
(excess precision issues are target-dependent) in 4.5 (there are various
such bugs in 4.4).

http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
is the online version of the documentation for conformance options;
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
includes the floating-point options and
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
describes -pedantic.

There are no options to enable C99 conformance except for allowing decimal
floating point.  If you want -fdecimal-fp or similar to enable decimal
floating point in a strict conformance mode, that would be a separate issue.


*** This bug has been marked as a duplicate of 323 ***