diff options
author | Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2022-01-10 17:04:34 +0100 |
---|---|---|
committer | Francois-Xavier Coudert <fxcoudert@gmail.com> | 2022-01-16 22:57:45 +0100 |
commit | 90045c5df5b3c8853e7740fb72a11aead1c489bb (patch) | |
tree | 5a59d689ecb0d21bb9aa1cb3e3a1d2e479a5f07b /gcc | |
parent | bca1c431affee41ecadb7f29d8d65142a73e0ebf (diff) | |
download | gcc-90045c5df5b3c8853e7740fb72a11aead1c489bb.zip gcc-90045c5df5b3c8853e7740fb72a11aead1c489bb.tar.gz gcc-90045c5df5b3c8853e7740fb72a11aead1c489bb.tar.bz2 |
Fortran: allow IEEE_VALUE to correctly return signaling NaNs
I moved the library implementation of IEEE_VALUE in libgfortran from
Fortran to C code, which gives us access to GCC's built-ins for NaN generation
(both quiet and signalling). It will be perform better than the current
Fortran implementation.
libgfortran/ChangeLog:
PR fortran/82207
* mk-kinds-h.sh: Add values for TINY.
* ieee/ieee_arithmetic.F90: Call C helper functions for
IEEE_VALUE.
* ieee/ieee_helper.c: New functions ieee_value_helper_N for each
floating-point type.
gcc/testsuite/ChangeLog:
PR fortran/82207
* gfortran.dg/ieee/ieee_10.f90: Do not create signaling NaNs.
* gfortran.dg/ieee/signaling_2.f90: New test.
* gfortran.dg/ieee/signaling_2_c.c: New file.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gfortran.dg/ieee/ieee_10.f90 | 12 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 | 70 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c | 8 |
3 files changed, 86 insertions, 4 deletions
diff --git a/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90 b/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90 index c3ffffc..a596504 100644 --- a/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90 +++ b/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90 @@ -12,8 +12,10 @@ program foo real x real(8) y - x = ieee_value(x, ieee_signaling_nan) - if (.not. ieee_is_nan(x)) stop 1 + ! At this point it is unclear what the behavior should be + ! for -ffpe-trap=invalid with a signaling NaN + !x = ieee_value(x, ieee_signaling_nan) + !if (.not. ieee_is_nan(x)) stop 1 x = ieee_value(x, ieee_quiet_nan) if (.not. ieee_is_nan(x)) stop 2 @@ -22,8 +24,10 @@ program foo x = ieee_value(x, ieee_negative_inf) if (ieee_is_finite(x)) stop 4 - y = ieee_value(y, ieee_signaling_nan) - if (.not. ieee_is_nan(y)) stop 5 + ! At this point it is unclear what the behavior should be + ! for -ffpe-trap=invalid with a signaling NaN + !y = ieee_value(y, ieee_signaling_nan) + !if (.not. ieee_is_nan(y)) stop 5 y = ieee_value(y, ieee_quiet_nan) if (.not. ieee_is_nan(y)) stop 6 diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 b/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 new file mode 100644 index 0000000..e7e7a4a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 @@ -0,0 +1,70 @@ +! { dg-do run } +! { dg-require-effective-target issignaling } */ +! { dg-additional-sources signaling_2_c.c } +! { dg-additional-options "-w" } +! the -w option is needed to make cc1 not report a warning for +! the -fintrinsic-modules-path option passed by ieee.exp +! +program test + use, intrinsic :: iso_c_binding + use, intrinsic :: ieee_arithmetic + implicit none + + interface + integer(kind=c_int) function isnansf (x) bind(c) + import :: c_float, c_int + real(kind=c_float), value :: x + end function + + integer(kind=c_int) function isnans (x) bind(c) + import :: c_double, c_int + real(kind=c_double), value :: x + end function + + integer(kind=c_int) function isnansl (x) bind(c) + import :: c_long_double, c_int + real(kind=c_long_double), value :: x + end function + end interface + + real(kind=c_float) :: x + real(kind=c_double) :: y + real(kind=c_long_double) :: z + + if (ieee_support_nan(x)) then + x = ieee_value(x, ieee_signaling_nan) + if (ieee_class(x) /= ieee_signaling_nan) stop 100 + if (.not. ieee_is_nan(x)) stop 101 + if (isnansf(x) /= 1) stop 102 + + x = ieee_value(x, ieee_quiet_nan) + if (ieee_class(x) /= ieee_quiet_nan) stop 103 + if (.not. ieee_is_nan(x)) stop 104 + if (isnansf(x) /= 0) stop 105 + end if + + if (ieee_support_nan(y)) then + y = ieee_value(y, ieee_signaling_nan) + if (ieee_class(y) /= ieee_signaling_nan) stop 100 + if (.not. ieee_is_nan(y)) stop 101 + if (isnans(y) /= 1) stop 102 + + y = ieee_value(y, ieee_quiet_nan) + if (ieee_class(y) /= ieee_quiet_nan) stop 103 + if (.not. ieee_is_nan(y)) stop 104 + if (isnans(y) /= 0) stop 105 + end if + + if (ieee_support_nan(z)) then + z = ieee_value(z, ieee_signaling_nan) + if (ieee_class(z) /= ieee_signaling_nan) stop 100 + if (.not. ieee_is_nan(z)) stop 101 + if (isnansl(z) /= 1) stop 102 + + z = ieee_value(z, ieee_quiet_nan) + if (ieee_class(z) /= ieee_quiet_nan) stop 103 + if (.not. ieee_is_nan(z)) stop 104 + if (isnansl(z) /= 0) stop 105 + end if + +end program test diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c new file mode 100644 index 0000000..ea7fc04 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c @@ -0,0 +1,8 @@ +#define _GNU_SOURCE +#include <math.h> +#include <float.h> + +int isnansf (float x) { return issignaling (x) ? 1 : 0; } +int isnans (double x) { return issignaling (x) ? 1 : 0; } +int isnansl (long double x) { return issignaling (x) ? 1 : 0; } + |