Bug 39036 - Decimal floating-point exception flags done wrong
Summary: Decimal floating-point exception flags done wrong
Status: RESOLVED DUPLICATE of bug 20785
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.3.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-01-30 02:00 UTC by Fred J. Tydeman
Modified: 2009-01-30 22:42 UTC (History)
5 users (show)

See Also:
Host: 4.3.2
Target: 4.3.2
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-01-30 02:00:15 UTC
Using gcc 4.3.2-7 on Intel Pentium 4 running Linux Fedora Core 10 and -std=gnu99

/* DFP TR 24732 == WG14 / N1176, N1312 */
#define __STDC_WANT_DEC_FP__ /* Tell implementation that we want Decimal FP */
#pragma STDC FENV_ACCESS ON	/* will be testing FP exception flags */

#include <stdio.h>	/* printf() */
#include <fenv.h>	/* fetestexcept(), FE_* */
#include <float.h>	/* DEC*_MIN, DEC*_MAX */


int main(void){
  _Decimal64 d10;
  int before;
  int after;

  before = feclearexcept( FE_ALL_EXCEPT );
  d10 = 1.0DD;
  d10 /= 3.0DD;
  after = fetestexcept( FE_ALL_EXCEPT );
  if( FE_INEXACT & after ){
    printf("Inexact raised as expected\n");
  }else{
    printf("Inexact wrong; after=%i\n", after);
  }

  before = feclearexcept( FE_ALL_EXCEPT );
  d10 = DEC64_MIN;
  d10 *= d10;
  after = fetestexcept( FE_ALL_EXCEPT );
  if( FE_UNDERFLOW & after ){
    printf("Underflow raised as expected\n");
  }else{
    printf("Underflow wrong; after=%i\n", after);
  }

  before = feclearexcept( FE_ALL_EXCEPT );
  d10 = DEC64_MAX;
  d10 *= d10;
  after = fetestexcept( FE_ALL_EXCEPT );
  if( FE_OVERFLOW & after ){
    printf("Overflow raised as expected\n");
  }else{
    printf("Overflow wrong; after=%i\n", after);
  }

  before = feclearexcept( FE_ALL_EXCEPT );
  d10 = DEC64_MIN;
  d10 /= (d10-d10);
  after = fetestexcept( FE_ALL_EXCEPT );
  if( FE_DIVBYZERO & after ){
    printf("Divbyzero raised as expected\n");
  }else{
    printf("Divbyzero wrong; after=%i\n", after);
  }

  before = feclearexcept( FE_ALL_EXCEPT );
  d10 = 0.0e-15DD;
  d10 /= d10;
  after = fetestexcept( FE_ALL_EXCEPT );
  if( FE_INVALID & after ){
    printf("Invalid raised as expected\n");
  }else{
    printf("Invalid wrong; after=%i\n", after);
  }

  printf("%2i = FE_INEXACT\n", FE_INEXACT);
  printf("%2i = FE_UNDERFLOW\n", FE_UNDERFLOW);
  printf("%2i = FE_OVERFLOW\n", FE_OVERFLOW);
  printf("%2i = FE_DIVBYZERO\n", FE_DIVBYZERO);
  printf("%2i = FE_INVALID\n", FE_INVALID);

  return 0;
}

gets:

Inexact wrong; after=0
Underflow wrong; after=0
Overflow wrong; after=32
Divbyzero wrong; after=0
Invalid wrong; after=0
32 = FE_INEXACT
16 = FE_UNDERFLOW
 8 = FE_OVERFLOW
 4 = FE_DIVBYZERO
 1 = FE_INVALID
Comment 1 pinskia@gmail.com 2009-01-30 02:41:15 UTC
Subject: Re:   New: Decimal floating-point exception flags done wrong



Sent from my iPhone

On Jan 29, 2009, at 6:00 PM, "tydeman at tybor dot com" <gcc-bugzilla@gcc.gnu.org 
 > wrote:

> Using gcc 4.3.2-7 on Intel Pentium 4 running Linux Fedora Core 10 and
> -std=gnu99

There were some dfp fixes on the trunk relating to fp exceptions so  
you should try the trunk before reporting any more bugs.

>
>
> /* DFP TR 24732 == WG14 / N1176, N1312 */
> #define __STDC_WANT_DEC_FP__ /* Tell implementation that we want  
> Decimal FP */
> #pragma STDC FENV_ACCESS ON     /* will be testing FP exception  
> flags */
>
> #include <stdio.h>      /* printf() */
> #include <fenv.h>       /* fetestexcept(), FE_* */
> #include <float.h>      /* DEC*_MIN, DEC*_MAX */
>
>
> int main(void){
>  _Decimal64 d10;
>  int before;
>  int after;
>
>  before = feclearexcept( FE_ALL_EXCEPT );
>  d10 = 1.0DD;
>  d10 /= 3.0DD;
>  after = fetestexcept( FE_ALL_EXCEPT );
>  if( FE_INEXACT & after ){
>    printf("Inexact raised as expected\n");
>  }else{
>    printf("Inexact wrong; after=%i\n", after);
>  }
>
>  before = feclearexcept( FE_ALL_EXCEPT );
>  d10 = DEC64_MIN;
>  d10 *= d10;
>  after = fetestexcept( FE_ALL_EXCEPT );
>  if( FE_UNDERFLOW & after ){
>    printf("Underflow raised as expected\n");
>  }else{
>    printf("Underflow wrong; after=%i\n", after);
>  }
>
>  before = feclearexcept( FE_ALL_EXCEPT );
>  d10 = DEC64_MAX;
>  d10 *= d10;
>  after = fetestexcept( FE_ALL_EXCEPT );
>  if( FE_OVERFLOW & after ){
>    printf("Overflow raised as expected\n");
>  }else{
>    printf("Overflow wrong; after=%i\n", after);
>  }
>
>  before = feclearexcept( FE_ALL_EXCEPT );
>  d10 = DEC64_MIN;
>  d10 /= (d10-d10);
>  after = fetestexcept( FE_ALL_EXCEPT );
>  if( FE_DIVBYZERO & after ){
>    printf("Divbyzero raised as expected\n");
>  }else{
>    printf("Divbyzero wrong; after=%i\n", after);
>  }
>
>  before = feclearexcept( FE_ALL_EXCEPT );
>  d10 = 0.0e-15DD;
>  d10 /= d10;
>  after = fetestexcept( FE_ALL_EXCEPT );
>  if( FE_INVALID & after ){
>    printf("Invalid raised as expected\n");
>  }else{
>    printf("Invalid wrong; after=%i\n", after);
>  }
>
>  printf("%2i = FE_INEXACT\n", FE_INEXACT);
>  printf("%2i = FE_UNDERFLOW\n", FE_UNDERFLOW);
>  printf("%2i = FE_OVERFLOW\n", FE_OVERFLOW);
>  printf("%2i = FE_DIVBYZERO\n", FE_DIVBYZERO);
>  printf("%2i = FE_INVALID\n", FE_INVALID);
>
>  return 0;
> }
>
> gets:
>
> Inexact wrong; after=0
> Underflow wrong; after=0
> Overflow wrong; after=32
> Divbyzero wrong; after=0
> Invalid wrong; after=0
> 32 = FE_INEXACT
> 16 = FE_UNDERFLOW
> 8 = FE_OVERFLOW
> 4 = FE_DIVBYZERO
> 1 = FE_INVALID
>
>
> -- 
>           Summary: Decimal floating-point exception flags done wrong
>           Product: gcc
>           Version: 4.3.2
>            Status: UNCONFIRMED
>          Severity: normal
>          Priority: P3
>         Component: c
>        AssignedTo: unassigned at gcc dot gnu dot org
>        ReportedBy: tydeman at tybor dot com
>  GCC host triplet: 4.3.2
> GCC target triplet: 4.3.2
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39036
>
Comment 2 Richard Biener 2009-01-30 07:19:40 UTC
STDC FENV_ACCESS is not implemented.

*** This bug has been marked as a duplicate of 20785 ***
Comment 3 Janis Johnson 2009-01-30 21:31:05 UTC
The bug is a duplicate of 20785 because the pragma is not implemented.

From the point of view of GCC it is invalid because <fenv.h> and the functions it declares are not provided by GCC, but by the C library.
Comment 4 Richard B. Kreckel 2009-01-30 22:37:22 UTC
(In reply to comment #3)
> From the point of view of GCC it is invalid because <fenv.h> and the functions
> it declares are not provided by GCC, but by the C library.

On the other hand, one can argue that if GCC cannot guarantee that these C library functions get executed in the proper order, it should provide replacements of these functions for which it can make this guarantee.
Comment 5 Fred J. Tydeman 2009-01-30 22:42:22 UTC
I consider emulation of decimal FP to be part of the compiler's job.  Part of
that emulation is setting the FP execption flags as per IEEE-754-2008.

There is one set of FP exception flags (used for both binary FP and decimal FP).

Given that the <fenv.h> functions work correctly for binary FP exceptions
(and they mostly do on Intel x86/x87), then they should work correctly for
decimal FP exceptions.

The full set of command line options I give gcc is:
  -std=gnu99 -pedantic -H -fno-builtin -frounding-math
My understanding is -frounding-math is supposed to act like a global
#pragma STDC FENV_ACCESS ON
Comment 6 jsm-csl@polyomino.org.uk 2009-01-30 23:14:09 UTC
Subject: Re:  Decimal floating-point exception flags done wrong

On Fri, 30 Jan 2009, tydeman at tybor dot com wrote:

> I consider emulation of decimal FP to be part of the compiler's job.  Part of
> that emulation is setting the FP execption flags as per IEEE-754-2008.

The implementation of decimal FP for the GNU system is partly in GCC and 
partly in (E)GLIBC (available as patches or an EGLIBC branch).  The 
implementation approach chosen is that the versions of the 
arithmetic/conversion functions that handle exceptions and rounding modes 
are included only in the libdfp included with (E)GLIBC, not in libgcc.  
(Depending on the target, copies of libm functions to handle exceptions 
and rounding modes may need including in libdfp to avoid a dependency on 
libm, and this can only be done as part of the libc/libm/libdfp 
implementation.)

So, if you want exceptions and rounding modes support for decimal FP, use 
an appropriate libc version and link against the associated libdfp.