! { dg-do run } ! { dg-additional-options "-mfp-rounding-mode=d" { target alpha*-*-* } } use, intrinsic :: ieee_features, only : ieee_rounding use, intrinsic :: ieee_arithmetic implicit none interface check_equal procedure check_equal_float, check_equal_double end interface interface check_not_equal procedure check_not_equal_float, check_not_equal_double end interface interface divide procedure divide_float, divide_double end interface real :: sx1, sx2, sx3 double precision :: dx1, dx2, dx3 type(ieee_round_type) :: mode ! We should support at least C float and C double types if (ieee_support_rounding(ieee_nearest)) then if (.not. ieee_support_rounding(ieee_nearest, 0.)) STOP 1 if (.not. ieee_support_rounding(ieee_nearest, 0.d0)) STOP 2 end if ! The initial rounding mode should probably be NEAREST ! (at least on the platforms we currently support) if (ieee_support_rounding(ieee_nearest, 0.)) then call ieee_get_rounding_mode (mode) if (mode /= ieee_nearest) STOP 3 end if if (ieee_support_rounding(ieee_up, sx1) .and. & ieee_support_rounding(ieee_down, sx1) .and. & ieee_support_rounding(ieee_nearest, sx1) .and. & ieee_support_rounding(ieee_to_zero, sx1)) then sx1 = 1 sx2 = 3 sx1 = divide(sx1, sx2, ieee_up) sx3 = 1 sx2 = 3 sx3 = divide(sx3, sx2, ieee_down) call check_not_equal(sx1, sx3) call check_equal(sx3, nearest(sx1, -1.)) call check_equal(sx1, nearest(sx3, 1.)) call check_equal(1./3., divide(1., 3., ieee_nearest)) call check_equal(-1./3., divide(-1., 3., ieee_nearest)) call check_equal(divide(3., 7., ieee_to_zero), & divide(3., 7., ieee_down)) call check_equal(divide(-3., 7., ieee_to_zero), & divide(-3., 7., ieee_up)) end if if (ieee_support_rounding(ieee_up, dx1) .and. & ieee_support_rounding(ieee_down, dx1) .and. & ieee_support_rounding(ieee_nearest, dx1) .and. & ieee_support_rounding(ieee_to_zero, dx1)) then dx1 = 1 dx2 = 3 dx1 = divide(dx1, dx2, ieee_up) dx3 = 1 dx2 = 3 dx3 = divide(dx3, dx2, ieee_down) call check_not_equal(dx1, dx3) call check_equal(dx3, nearest(dx1, -1.d0)) call check_equal(dx1, nearest(dx3, 1.d0)) call check_equal(1.d0/3.d0, divide(1.d0, 3.d0, ieee_nearest)) call check_equal(-1.d0/3.d0, divide(-1.d0, 3.d0, ieee_nearest)) call check_equal(divide(3.d0, 7.d0, ieee_to_zero), & divide(3.d0, 7.d0, ieee_down)) call check_equal(divide(-3.d0, 7.d0, ieee_to_zero), & divide(-3.d0, 7.d0, ieee_up)) end if contains real function divide_float (x, y, rounding) result(res) use, intrinsic :: ieee_arithmetic real, 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 double precision function divide_double (x, y, rounding) result(res) use, intrinsic :: ieee_arithmetic double precision, 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_equal_float (x, y) real, intent(in) :: x, y if (x /= y) then print *, x, y STOP 4 end if end subroutine subroutine check_equal_double (x, y) double precision, intent(in) :: x, y if (x /= y) then print *, x, y STOP 5 end if end subroutine subroutine check_not_equal_float (x, y) real, intent(in) :: x, y if (x == y) then print *, x, y STOP 6 end if end subroutine subroutine check_not_equal_double (x, y) double precision, intent(in) :: x, y if (x == y) then print *, x, y STOP 7 end if end subroutine end