diff options
author | Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2015-08-06 09:22:30 +0000 |
---|---|---|
committer | François-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2015-08-06 09:22:30 +0000 |
commit | cfe25557ad2ec48c264b3d9cb317cf4a88621e39 (patch) | |
tree | c2d720fe1a97f48b05867163e81668f2e448b7bf /gcc | |
parent | a3fe41f5c986c9557518bb9b4dc76269568a8af7 (diff) | |
download | gcc-cfe25557ad2ec48c264b3d9cb317cf4a88621e39.zip gcc-cfe25557ad2ec48c264b3d9cb317cf4a88621e39.tar.gz gcc-cfe25557ad2ec48c264b3d9cb317cf4a88621e39.tar.bz2 |
re PR fortran/64022 ([F2003][IEEE] ieee_support_flag does not handle kind=10 and kind=16 REAL variables)
PR fortran/64022
* gfortran.dg/ieee/large_2.f90: New test.
* gfortran.dg/ieee/large_3.F90: New test.
From-SVN: r226670
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/ieee/large_2.f90 | 145 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/ieee/large_3.F90 | 157 |
3 files changed, 308 insertions, 0 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1d7e6a6..dad3c51 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,12 @@ 2015-08-06 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> PR fortran/64022 + * gfortran.dg/ieee/large_2.f90: New test. + * gfortran.dg/ieee/large_3.F90: New test. + +2015-08-06 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/64022 * gfortran.dg/ieee/large_1.f90: Adjust test. 2015-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org> diff --git a/gcc/testsuite/gfortran.dg/ieee/large_2.f90 b/gcc/testsuite/gfortran.dg/ieee/large_2.f90 new file mode 100644 index 0000000..54e3397 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ieee/large_2.f90 @@ -0,0 +1,145 @@ +! { dg-do run } +! { dg-additional-options "-mfp-rounding-mode=d" { target alpha*-*-* } } + + use, intrinsic :: ieee_features + use, intrinsic :: ieee_arithmetic + implicit none + + ! k1 and k2 will be large real kinds, if supported, and single/double + ! otherwise + integer, parameter :: k1 = & + max(ieee_selected_real_kind(precision(0.d0) + 1), kind(0.)) + integer, parameter :: k2 = & + max(ieee_selected_real_kind(precision(0._k1) + 1), kind(0.d0)) + + interface check_equal + procedure check_equal1, check_equal2 + end interface + + interface check_not_equal + procedure check_not_equal1, check_not_equal2 + end interface + + interface divide + procedure divide1, divide2 + end interface + + real(kind=k1) :: x1, x2, x3 + real(kind=k2) :: y1, y2, y3 + type(ieee_round_type) :: mode + + if (ieee_support_rounding(ieee_up, x1) .and. & + ieee_support_rounding(ieee_down, x1) .and. & + ieee_support_rounding(ieee_nearest, x1) .and. & + ieee_support_rounding(ieee_to_zero, x1)) then + + x1 = 1 + x2 = 3 + x1 = divide(x1, x2, ieee_up) + + x3 = 1 + x2 = 3 + x3 = divide(x3, x2, ieee_down) + call check_not_equal(x1, x3) + call check_equal(x3, nearest(x1, -1._k1)) + call check_equal(x1, nearest(x3, 1._k1)) + + call check_equal(1._k1/3._k1, divide(1._k1, 3._k1, ieee_nearest)) + call check_equal(-1._k1/3._k1, divide(-1._k1, 3._k1, ieee_nearest)) + + call check_equal(divide(3._k1, 7._k1, ieee_to_zero), & + divide(3._k1, 7._k1, ieee_down)) + call check_equal(divide(-3._k1, 7._k1, ieee_to_zero), & + divide(-3._k1, 7._k1, ieee_up)) + + end if + + if (ieee_support_rounding(ieee_up, y1) .and. & + ieee_support_rounding(ieee_down, y1) .and. & + ieee_support_rounding(ieee_nearest, y1) .and. & + ieee_support_rounding(ieee_to_zero, y1)) then + + y1 = 1 + y2 = 3 + y1 = divide(y1, y2, ieee_up) + + y3 = 1 + y2 = 3 + y3 = divide(y3, y2, ieee_down) + call check_not_equal(y1, y3) + call check_equal(y3, nearest(y1, -1._k2)) + call check_equal(y1, nearest(y3, 1._k2)) + + call check_equal(1._k2/3._k2, divide(1._k2, 3._k2, ieee_nearest)) + call check_equal(-1._k2/3._k2, divide(-1._k2, 3._k2, ieee_nearest)) + + call check_equal(divide(3._k2, 7._k2, ieee_to_zero), & + divide(3._k2, 7._k2, ieee_down)) + call check_equal(divide(-3._k2, 7._k2, ieee_to_zero), & + divide(-3._k2, 7._k2, ieee_up)) + + end if + +contains + + real(kind=k1) function divide1 (x, y, rounding) result(res) + use, intrinsic :: ieee_arithmetic + real(kind=k1), intent(in) :: x, y + type(ieee_round_type), intent(in) :: rounding + type(ieee_round_type) :: old + + call ieee_get_rounding_mode (old) + call ieee_set_rounding_mode (rounding) + + res = x / y + + call ieee_set_rounding_mode (old) + end function + + real(kind=k2) function divide2 (x, y, rounding) result(res) + use, intrinsic :: ieee_arithmetic + real(kind=k2), intent(in) :: x, y + type(ieee_round_type), intent(in) :: rounding + type(ieee_round_type) :: old + + call ieee_get_rounding_mode (old) + call ieee_set_rounding_mode (rounding) + + res = x / y + + call ieee_set_rounding_mode (old) + end function + + subroutine check_equal1 (x, y) + real(kind=k1), intent(in) :: x, y + if (x /= y) then + print *, x, y + call abort + end if + end subroutine + + subroutine check_equal2 (x, y) + real(kind=k2), intent(in) :: x, y + if (x /= y) then + print *, x, y + call abort + end if + end subroutine + + subroutine check_not_equal1 (x, y) + real(kind=k1), intent(in) :: x, y + if (x == y) then + print *, x, y + call abort + end if + end subroutine + + subroutine check_not_equal2 (x, y) + real(kind=k2), intent(in) :: x, y + if (x == y) then + print *, x, y + call abort + end if + end subroutine + +end diff --git a/gcc/testsuite/gfortran.dg/ieee/large_3.F90 b/gcc/testsuite/gfortran.dg/ieee/large_3.F90 new file mode 100644 index 0000000..fbba091 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ieee/large_3.F90 @@ -0,0 +1,157 @@ +! { dg-do run } +! { dg-additional-options "-ffree-line-length-none" } +! { dg-additional-options "-mfp-trap-mode=sui" { target alpha*-*-* } } +! +! Use dg-additional-options rather than dg-options to avoid overwriting the +! default IEEE options which are passed by ieee.exp and necessary. + + use ieee_features + use ieee_exceptions + use ieee_arithmetic + + implicit none + + ! k1 and k2 will be large real kinds, if supported, and single/double + ! otherwise + integer, parameter :: k1 = & + max(ieee_selected_real_kind(precision(0.d0) + 1), kind(0.)) + integer, parameter :: k2 = & + max(ieee_selected_real_kind(precision(0._k1) + 1), kind(0.d0)) + + type(ieee_flag_type), parameter :: x(5) = & + [ IEEE_INVALID, IEEE_OVERFLOW, IEEE_DIVIDE_BY_ZERO, & + IEEE_UNDERFLOW, IEEE_INEXACT ] + logical :: l(5) = .false. + character(len=5) :: s + +#define FLAGS_STRING(S) \ + call ieee_get_flag(x, l) ; \ + write(S,"(5(A1))") merge(["I","O","Z","U","P"],[" "," "," "," "," "],l) + +#define CHECK_FLAGS(expected) \ + FLAGS_STRING(s) ; \ + if (s /= expected) then ; \ + write (*,"(A,I0,A,A)") "Flags at line ", __LINE__, ": ", s ; \ + call abort ; \ + end if ; \ + call check_flag_sub + + real(kind=k1), volatile :: sx + real(kind=k2), volatile :: dx + + ! This file tests IEEE_SET_FLAG and IEEE_GET_FLAG + + !!!! Large kind 1 + + ! Initial flags are all off + CHECK_FLAGS(" ") + + ! Check we can clear them + call ieee_set_flag(ieee_all, .false.) + CHECK_FLAGS(" ") + + ! Raise invalid, then clear + sx = -1 + sx = sqrt(sx) + CHECK_FLAGS("I ") + call ieee_set_flag(ieee_all, .false.) + CHECK_FLAGS(" ") + + ! Raise overflow and precision + sx = huge(sx) + CHECK_FLAGS(" ") + sx = sx*sx + CHECK_FLAGS(" O P") + + ! Also raise divide-by-zero + sx = 0 + sx = 1 / sx + CHECK_FLAGS(" OZ P") + + ! Clear them + call ieee_set_flag([ieee_overflow,ieee_inexact,& + ieee_divide_by_zero],[.false.,.false.,.true.]) + CHECK_FLAGS(" Z ") + call ieee_set_flag(ieee_divide_by_zero, .false.) + CHECK_FLAGS(" ") + + ! Raise underflow + sx = tiny(sx) + CHECK_FLAGS(" ") + sx = sx / 10 + CHECK_FLAGS(" UP") + + ! Raise everything + call ieee_set_flag(ieee_all, .true.) + CHECK_FLAGS("IOZUP") + + ! And clear + call ieee_set_flag(ieee_all, .false.) + CHECK_FLAGS(" ") + + + !!!! Large kind 2 + + ! Initial flags are all off + CHECK_FLAGS(" ") + + ! Check we can clear them + call ieee_set_flag(ieee_all, .false.) + CHECK_FLAGS(" ") + + ! Raise invalid, then clear + dx = -1 + dx = sqrt(dx) + CHECK_FLAGS("I ") + call ieee_set_flag(ieee_all, .false.) + CHECK_FLAGS(" ") + + ! Raise overflow and precision + dx = huge(dx) + CHECK_FLAGS(" ") + dx = dx*dx + CHECK_FLAGS(" O P") + + ! Also raise divide-by-zero + dx = 0 + dx = 1 / dx + CHECK_FLAGS(" OZ P") + + ! Clear them + call ieee_set_flag([ieee_overflow,ieee_inexact,& + ieee_divide_by_zero],[.false.,.false.,.true.]) + CHECK_FLAGS(" Z ") + call ieee_set_flag(ieee_divide_by_zero, .false.) + CHECK_FLAGS(" ") + + ! Raise underflow + dx = tiny(dx) + CHECK_FLAGS(" ") + dx = dx / 10 + CHECK_FLAGS(" UP") + + ! Raise everything + call ieee_set_flag(ieee_all, .true.) + CHECK_FLAGS("IOZUP") + + ! And clear + call ieee_set_flag(ieee_all, .false.) + CHECK_FLAGS(" ") + +contains + + subroutine check_flag_sub + use ieee_exceptions + logical :: l(5) = .false. + type(ieee_flag_type), parameter :: x(5) = & + [ IEEE_INVALID, IEEE_OVERFLOW, IEEE_DIVIDE_BY_ZERO, & + IEEE_UNDERFLOW, IEEE_INEXACT ] + call ieee_get_flag(x, l) + + if (any(l)) then + print *, "Flags not cleared in subroutine" + call abort + end if + end subroutine + +end |