Bug 29383 - Fortran 2003/F95[TR15580:1999]: Floating point exception (IEEE) support
Summary: Fortran 2003/F95[TR15580:1999]: Floating point exception (IEEE) support
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.2.0
: P3 enhancement
Target Milestone: 5.0
Assignee: Francois-Xavier Coudert
Keywords: patch
: 54840 58020 (view as bug list)
Depends on: 58020 59023 59026
Blocks: F2003
  Show dependency treegraph
Reported: 2006-10-08 08:41 UTC by tobias.burnus
Modified: 2014-06-28 15:11 UTC (History)
13 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2006-10-22 07:19:52


Note You need to log in before you can comment on or make changes to this bug.
Description tobias.burnus 2006-10-08 08:41:37 UTC
See chapter 14 of the Fortran 2003 standard.

Example, cf.
 program ieee
  use,intrinsic :: ieee_arithmetic
  implicit none

  if(.not. IEEE_support_standard(1.0d0)               &
     .or. .not.IEEE_support_halting(IEEE_INVALID)         &
     .or. .not.IEEE_support_halting(IEEE_DIVIDE_BY_ZERO)) &
     stop 'No IEEE support available!'

  call ieee_set_halting_mode([IEEE_INVALID, IEEE_DIVIDE_BY_ZERO],&

  call printLog(1.0d0)
  call printLog(0.0d0)
  call printLog(-1.0d0)
  call printLog(2.0d0)


subroutine printLog(x)
  double precision, intent(in) :: x
  double precision :: y

  y = log(x)
  if(.not. ieee_is_finite(y)) then
    write(*,*) 'Ignoring calculation for x = ', x,'; result is: ',y
    print *, 'Result is: log(',x,') = ',y
  end if
end subroutine printLog
end program ieee

Expected result (NAG f95 gives the following):

 Result is: log(   1.0000000000000000 ) =    0.0000000000000000
 Ignoring calculation for x =    0.0000000000000000 ; result is:
 Ignoring calculation for x =   -1.0000000000000000 ; result is:  NaN
 Result is: log(   2.0000000000000000 ) =    0.6931471805599453
Warning: Floating invalid operand occurred
Warning: Floating divide by zero occurred
Comment 1 Francois-Xavier Coudert 2006-10-22 07:19:52 UTC

This one will probably be implemented after ISO_C_BINDING.
Comment 2 Tobias Burnus 2009-09-07 08:07:11 UTC
Add links to some discussions to make sure it won't get lost:


The thread which is here and maybe also some other fortran@gcc emails by Tim and Nick around this time:
Comment 3 Tobias Burnus 2010-04-14 06:33:21 UTC
Some underflow module for Fortran:
Comment 4 Tobias Burnus 2010-06-12 12:15:10 UTC
Malcolm Cohen wrote in "Implementing the Standards...",
http://www.fortran.bcs.org/2007/jubilee/f50.pdf, the following:

IEEE module implementation
• Only if IEEE_GET_FLAG is directly called in a routine: save then clear the flags on entry, merge the flags on exit.
• Only in a routine that uses a mode setting procedure: save mode on entry,
restore mode on exit.
• Parallelism and other optimisations are little impeded by the use of IEEE facilities (all IEEE semantics being local).
Comment 5 Thomas Henlich 2011-01-24 08:53:10 UTC
Even a partial, incomplete support of module IEEE_ARITHMETIC would be very useful and much appreciated:

From http://gcc.gnu.org/ml/gcc/2008-11/msg00372.html

a) To set an IEEE value (NaN, INF, etc.)
b) Check whether a value is NaN, etc.


So we wouldn't have to resort to non-standard functions like ISNAN() (http://gcc.gnu.org/onlinedocs/gfortran/ISNAN.html) anymore.
Comment 6 Bill Long 2011-07-22 17:53:49 UTC
Since most other compilers support ieee_arithmetic now, the lack of support in gfortran is becoming a portability issue.  Simple test case with 4.6.1:

> cat t1.f90
program test
   use,intrinsic :: ieee_arithmetic

   real :: x
   read *, x
   if (ieee_is_nan(x)) then
      print *, "Nan"
      print *, "Not NaN"
   end if
end program test
> gfortran t1.f90

   use,intrinsic :: ieee_arithmetic
Fatal Error: Can't find an intrinsic module named 'ieee_arithmetic' at (1)
Comment 7 kargl 2012-10-07 00:08:49 UTC
*** Bug 54840 has been marked as a duplicate of this bug. ***
Comment 8 Andy Nelson 2012-10-09 15:19:36 UTC
Interesting. Didn't see this dup originally in my search.

In response to your other email (that it is very very hard), can you explain
a bit why if you've got the time/inclination? My first thought was that it 
would be a fairly simple pass through/reimplementation of the fpclassify 
functionality of c.


Andy Nelson

On Oct 6, 2012, at 6:08 PM, kargl at gcc dot gnu.org wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29383
> kargl at gcc dot gnu.org changed:
>           What    |Removed                     |Added
> ----------------------------------------------------------------------------
>                 CC|                            |andy.nelson at lanl dot gov
> --- Comment #7 from kargl at gcc dot gnu.org 2012-10-07 00:08:49 UTC ---
> *** Bug 54840 has been marked as a duplicate of this bug. ***
> -- 
> Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug.
Comment 9 kargl 2012-10-09 17:00:42 UTC
(In reply to comment #8)
> In response to your other email (that it is very very hard), can you explain
> a bit why if you've got the time/inclination? My first thought was that it 
> would be a fairly simple pass through/reimplementation of the fpclassify 
> functionality of c.

There are a few reason (and this is just my opinion).

1) gcc runs on numerous cpu architectures (i386, x86_64,
   arm, sparc, powerpc, etc).  Some (many? all?) do not
   have hardware support for IEEE754.  An implementation
   needs to be able to work on most (all?) of these cpus.

2) gcc runs on numerous operating systems.  The operating
   systems may or may not have sufficient support to allow
   an efficient IEEE754 implementation (a software
   implementation of IEEE754 will be slow).

3) Using C interoperability to access the fenv.h facility
   seems appealing, but gcc would need to deal with systems
   that do not have fenv.h.

4) gcc performs constant folding with mpfr, and in gfortran
   this constant folding is performed in round-to-nearest mode.
   gfortran would need to be update to delay constant folding
   until the rounding mode has been established.

   program foo
      use ieee_arithmetic
      real x
      call ieee_set_rounding_mode(ieee_down)
      x = 0.3 + 0.1999  ! Should be down in round-down?
      print '(Z0)', x
   end program foo

5) Finally, for some intrinsic functions, it is not possible
   to map to a libm routine without now putting a wrapper around
   the libm routine.  For example, consider FRACTION().  The standard

       Result Value.  The result has the value X*b**(-e), where b
       and e are as defined in 13.4 for the model representation of
       X.  If X has the value zero, the result has the value zero.
       If X is an IEEE infinity, the result is that infinity. If X
       is an IEEE NaN, the result is that NaN.

   The word "that" in "the result is that NaN" is problematic. 
   There are something like 2**p bit patterns that much NaN.
   Unfortunately, mapping FRACTION to libm's frexp gives the
   wrong NaN.  See PR 48979 for a longer explanation.

One can side step 1), 2), and 3) by unilaterally returning
false for ieee_support_standard(), which of course indicates
that the IEEE754 isn't standard.  4) and 5) are much harder
to fix.

Of course, I could be wrong.
Comment 10 Sean Santos 2012-12-04 19:28:19 UTC
Comment 9 seems a bit too pessimistic to me.

For one, returning ".false." for ieee_supports_* doesn't seem like a sidestep, but more like the correct behavior in an environment that lacks IEEE support (maybe even if the only reason is because the compiler has not implemented it).

For another, as noted above, one important use of the ieee_arithmetic module is to test for NaN/Inf in a standard-conforming way, rather than using compiler-specific extensions. (AFAIK, gfortran is the only F2003 compiler that forces you to use a non-portable extension to do this.)

For that functionality, the only likely problem I can see is in deciding when e.g. ieee_support_nan should return ".true.".

Of course this is only a fraction of what needs to be done (presumably the easiest part), but it's much better than nothing, particularly to address what I would expect to be one of the most common uses of this module.
Comment 11 Sean Santos 2013-04-14 20:08:59 UTC
I'm doing a bit of research because I'm considering trying to tackle part of this soon.

I believe that the Fortran standard does not require the rounding mode to apply to operations performed during constant folding, so point 4 above is moot.

Please see the collected interpretations of F2003:


Particularly see F03/0040 and F03/0078. In combination they guarantee that the compiler is allowed to transform expressions at compile time according to the "mathematical equivalence" rule regardless of the rounding mode. In any case, the rounding mode cannot always be established at compile time; if the committee had not decided upon this behavior, then constant folding would often be impossible, period.

The Fortran 2003 and 2008 standards also give examples where constant folding and propagation are allowed to influence whether or not an IEEE exception is signaled.
Comment 12 Walter Spector 2014-06-03 18:15:42 UTC
Adding myself to the CC list, sympathizing with comment #5. Just IEEE_ARITHMETIC intrinsic functions for basic setting (e.g., IEEE_VALUE) and testing (e.g., IEEE_IS_NAN) with the default rounding mode, roughly equivalent to what g95 supports, would be very useful.  I don't need fancy rounding modes.
Comment 13 Francois-Xavier Coudert 2014-06-07 10:19:17 UTC
*** Bug 58020 has been marked as a duplicate of this bug. ***
Comment 14 Francois-Xavier Coudert 2014-06-07 10:25:28 UTC
I posted a patch adding a rather complete IEEE support here: https://gcc.gnu.org/ml/fortran/2014-06/msg00038.html
Comment 15 Francois-Xavier Coudert 2014-06-28 14:18:13 UTC
Author: fxcoudert
Date: Sat Jun 28 14:17:41 2014
New Revision: 212102

URL: https://gcc.gnu.org/viewcvs?rev=212102&root=gcc&view=rev
	PR fortran/29383

	* gfortran.h (gfc_simplify_ieee_selected_real_kind): New prototype.
	* libgfortran.h (GFC_FPE_*): Use simple integer values, valid in
	both C and Fortran.
	* expr.c (gfc_check_init_expr): Simplify IEEE_SELECTED_REAL_KIND.
	* simplify.c (gfc_simplify_ieee_selected_real_kind): New function.
	* module.c (mio_symbol): Keep track of symbols which came from
	intrinsic modules.
	(gfc_use_module): Keep track of the IEEE modules.
	* trans-decl.c (gfc_get_symbol_decl): Adjust code since
	we have new intrinsic modules.
	(gfc_build_builtin_function_decls): Build decls for
	ieee_procedure_entry and ieee_procedure_exit.
	(is_from_ieee_module, is_ieee_module_used, save_fp_state,
	restore_fp_state): New functions.
	(gfc_generate_function_code): Save and restore floating-point
	state on procedure entry/exit, when IEEE modules are used.
	* intrinsic.texi: Document the IEEE modules.

	* configure.host: Add checks for IEEE support, rework priorities.
	* configure.ac: Define IEEE_SUPPORT, check for fpsetsticky and
	* configure: Regenerate.
	* Makefile.am: Build new ieee files, install IEEE_* modules.
	* Makefile.in: Regenerate.
	* gfortran.map (GFORTRAN_1.6): Add new symbols.
	* libgfortran.h (get_fpu_trap_exceptions, set_fpu_trap_exceptions,
	support_fpu_trap, set_fpu_except_flags, support_fpu_flag,
	support_fpu_rounding_mode, get_fpu_state, set_fpu_state): New
	* config/fpu-*.h (get_fpu_trap_exceptions,
	set_fpu_trap_exceptions, support_fpu_trap, set_fpu_except_flags,
	support_fpu_flag, support_fpu_rounding_mode, get_fpu_state,
	set_fpu_state): New functions.
	* ieee/ieee_features.F90: New file.
	* ieee/ieee_exceptions.F90: New file.
	* ieee/ieee_arithmetic.F90: New file.
	* ieee/ieee_helper.c: New file.

	* lib/target-supports.exp (check_effective_target_fortran_ieee): 
	New function.
	* gfortran.dg/ieee/ieee.exp: New file.
	* gfortran.dg/ieee/ieee_1.F90: New file.
	* gfortran.dg/ieee/ieee_2.f90: New file.
	* gfortran.dg/ieee/ieee_3.f90: New file.
	* gfortran.dg/ieee/ieee_4.f90: New file.
	* gfortran.dg/ieee/ieee_5.f90: New file.
	* gfortran.dg/ieee/ieee_6.f90: New file.
	* gfortran.dg/ieee/ieee_7.f90: New file.
	* gfortran.dg/ieee/ieee_rounding_1.f90: New file.

Comment 16 Francois-Xavier Coudert 2014-06-28 15:11:25 UTC
This has now been fixed on trunk (4.10). Hurray!