! Implementation of the IEEE_ARITHMETIC standard intrinsic module ! Copyright (C) 2013-2017 Free Software Foundation, Inc. ! Contributed by Francois-Xavier Coudert ! ! This file is part of the GNU Fortran runtime library (libgfortran). ! ! Libgfortran is free software; you can redistribute it and/or ! modify it under the terms of the GNU General Public ! License as published by the Free Software Foundation; either ! version 3 of the License, or (at your option) any later version. ! ! Libgfortran is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! ! Under Section 7 of GPL version 3, you are granted additional ! permissions described in the GCC Runtime Library Exception, version ! 3.1, as published by the Free Software Foundation. ! ! You should have received a copy of the GNU General Public License and ! a copy of the GCC Runtime Library Exception along with this program; ! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ! . */ #include "config.h" #include "kinds.inc" #include "c99_protos.inc" #include "fpu-target.inc" module IEEE_ARITHMETIC use IEEE_EXCEPTIONS implicit none private ! Every public symbol from IEEE_EXCEPTIONS must be made public here public :: IEEE_FLAG_TYPE, IEEE_INVALID, IEEE_OVERFLOW, & IEEE_DIVIDE_BY_ZERO, IEEE_UNDERFLOW, IEEE_INEXACT, IEEE_USUAL, & IEEE_ALL, IEEE_STATUS_TYPE, IEEE_GET_FLAG, IEEE_GET_HALTING_MODE, & IEEE_GET_STATUS, IEEE_SET_FLAG, IEEE_SET_HALTING_MODE, & IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING ! Derived types and named constants type, public :: IEEE_CLASS_TYPE private integer :: hidden end type type(IEEE_CLASS_TYPE), parameter, public :: & IEEE_OTHER_VALUE = IEEE_CLASS_TYPE(0), & IEEE_SIGNALING_NAN = IEEE_CLASS_TYPE(1), & IEEE_QUIET_NAN = IEEE_CLASS_TYPE(2), & IEEE_NEGATIVE_INF = IEEE_CLASS_TYPE(3), & IEEE_NEGATIVE_NORMAL = IEEE_CLASS_TYPE(4), & IEEE_NEGATIVE_DENORMAL = IEEE_CLASS_TYPE(5), & IEEE_NEGATIVE_ZERO = IEEE_CLASS_TYPE(6), & IEEE_POSITIVE_ZERO = IEEE_CLASS_TYPE(7), & IEEE_POSITIVE_DENORMAL = IEEE_CLASS_TYPE(8), & IEEE_POSITIVE_NORMAL = IEEE_CLASS_TYPE(9), & IEEE_POSITIVE_INF = IEEE_CLASS_TYPE(10) type, public :: IEEE_ROUND_TYPE private integer :: hidden end type type(IEEE_ROUND_TYPE), parameter, public :: & IEEE_NEAREST = IEEE_ROUND_TYPE(GFC_FPE_TONEAREST), & IEEE_TO_ZERO = IEEE_ROUND_TYPE(GFC_FPE_TOWARDZERO), & IEEE_UP = IEEE_ROUND_TYPE(GFC_FPE_UPWARD), & IEEE_DOWN = IEEE_ROUND_TYPE(GFC_FPE_DOWNWARD), & IEEE_OTHER = IEEE_ROUND_TYPE(0) ! Equality operators on the derived types interface operator (==) module procedure IEEE_CLASS_TYPE_EQ, IEEE_ROUND_TYPE_EQ end interface public :: operator(==) interface operator (/=) module procedure IEEE_CLASS_TYPE_NE, IEEE_ROUND_TYPE_NE end interface public :: operator (/=) ! IEEE_IS_FINITE interface elemental logical function _gfortran_ieee_is_finite_4(X) real(kind=4), intent(in) :: X end function elemental logical function _gfortran_ieee_is_finite_8(X) real(kind=8), intent(in) :: X end function #ifdef HAVE_GFC_REAL_10 elemental logical function _gfortran_ieee_is_finite_10(X) real(kind=10), intent(in) :: X end function #endif #ifdef HAVE_GFC_REAL_16 elemental logical function _gfortran_ieee_is_finite_16(X) real(kind=16), intent(in) :: X end function #endif end interface interface IEEE_IS_FINITE procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_is_finite_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_is_finite_10, & #endif _gfortran_ieee_is_finite_8, _gfortran_ieee_is_finite_4 end interface public :: IEEE_IS_FINITE ! IEEE_IS_NAN interface elemental logical function _gfortran_ieee_is_nan_4(X) real(kind=4), intent(in) :: X end function elemental logical function _gfortran_ieee_is_nan_8(X) real(kind=8), intent(in) :: X end function #ifdef HAVE_GFC_REAL_10 elemental logical function _gfortran_ieee_is_nan_10(X) real(kind=10), intent(in) :: X end function #endif #ifdef HAVE_GFC_REAL_16 elemental logical function _gfortran_ieee_is_nan_16(X) real(kind=16), intent(in) :: X end function #endif end interface interface IEEE_IS_NAN procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_is_nan_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_is_nan_10, & #endif _gfortran_ieee_is_nan_8, _gfortran_ieee_is_nan_4 end interface public :: IEEE_IS_NAN ! IEEE_IS_NEGATIVE interface elemental logical function _gfortran_ieee_is_negative_4(X) real(kind=4), intent(in) :: X end function elemental logical function _gfortran_ieee_is_negative_8(X) real(kind=8), intent(in) :: X end function #ifdef HAVE_GFC_REAL_10 elemental logical function _gfortran_ieee_is_negative_10(X) real(kind=10), intent(in) :: X end function #endif #ifdef HAVE_GFC_REAL_16 elemental logical function _gfortran_ieee_is_negative_16(X) real(kind=16), intent(in) :: X end function #endif end interface interface IEEE_IS_NEGATIVE procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_is_negative_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_is_negative_10, & #endif _gfortran_ieee_is_negative_8, _gfortran_ieee_is_negative_4 end interface public :: IEEE_IS_NEGATIVE ! IEEE_IS_NORMAL interface elemental logical function _gfortran_ieee_is_normal_4(X) real(kind=4), intent(in) :: X end function elemental logical function _gfortran_ieee_is_normal_8(X) real(kind=8), intent(in) :: X end function #ifdef HAVE_GFC_REAL_10 elemental logical function _gfortran_ieee_is_normal_10(X) real(kind=10), intent(in) :: X end function #endif #ifdef HAVE_GFC_REAL_16 elemental logical function _gfortran_ieee_is_normal_16(X) real(kind=16), intent(in) :: X end function #endif end interface interface IEEE_IS_NORMAL procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_is_normal_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_is_normal_10, & #endif _gfortran_ieee_is_normal_8, _gfortran_ieee_is_normal_4 end interface public :: IEEE_IS_NORMAL ! IEEE_COPY_SIGN #define COPYSIGN_MACRO(A,B) \ elemental real(kind = A) function \ _gfortran_ieee_copy_sign_/**/A/**/_/**/B (X,Y) ; \ real(kind = A), intent(in) :: X ; \ real(kind = B), intent(in) :: Y ; \ end function interface COPYSIGN_MACRO(4,4) COPYSIGN_MACRO(4,8) #ifdef HAVE_GFC_REAL_10 COPYSIGN_MACRO(4,10) #endif #ifdef HAVE_GFC_REAL_16 COPYSIGN_MACRO(4,16) #endif COPYSIGN_MACRO(8,4) COPYSIGN_MACRO(8,8) #ifdef HAVE_GFC_REAL_10 COPYSIGN_MACRO(8,10) #endif #ifdef HAVE_GFC_REAL_16 COPYSIGN_MACRO(8,16) #endif #ifdef HAVE_GFC_REAL_10 COPYSIGN_MACRO(10,4) COPYSIGN_MACRO(10,8) COPYSIGN_MACRO(10,10) #ifdef HAVE_GFC_REAL_16 COPYSIGN_MACRO(10,16) #endif #endif #ifdef HAVE_GFC_REAL_16 COPYSIGN_MACRO(16,4) COPYSIGN_MACRO(16,8) #ifdef HAVE_GFC_REAL_10 COPYSIGN_MACRO(16,10) #endif COPYSIGN_MACRO(16,16) #endif end interface interface IEEE_COPY_SIGN procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_copy_sign_16_16, & #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_copy_sign_16_10, & #endif _gfortran_ieee_copy_sign_16_8, & _gfortran_ieee_copy_sign_16_4, & #endif #ifdef HAVE_GFC_REAL_10 #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_copy_sign_10_16, & #endif _gfortran_ieee_copy_sign_10_10, & _gfortran_ieee_copy_sign_10_8, & _gfortran_ieee_copy_sign_10_4, & #endif #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_copy_sign_8_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_copy_sign_8_10, & #endif _gfortran_ieee_copy_sign_8_8, & _gfortran_ieee_copy_sign_8_4, & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_copy_sign_4_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_copy_sign_4_10, & #endif _gfortran_ieee_copy_sign_4_8, & _gfortran_ieee_copy_sign_4_4 end interface public :: IEEE_COPY_SIGN ! IEEE_UNORDERED #define UNORDERED_MACRO(A,B) \ elemental logical function \ _gfortran_ieee_unordered_/**/A/**/_/**/B (X,Y) ; \ real(kind = A), intent(in) :: X ; \ real(kind = B), intent(in) :: Y ; \ end function interface UNORDERED_MACRO(4,4) UNORDERED_MACRO(4,8) #ifdef HAVE_GFC_REAL_10 UNORDERED_MACRO(4,10) #endif #ifdef HAVE_GFC_REAL_16 UNORDERED_MACRO(4,16) #endif UNORDERED_MACRO(8,4) UNORDERED_MACRO(8,8) #ifdef HAVE_GFC_REAL_10 UNORDERED_MACRO(8,10) #endif #ifdef HAVE_GFC_REAL_16 UNORDERED_MACRO(8,16) #endif #ifdef HAVE_GFC_REAL_10 UNORDERED_MACRO(10,4) UNORDERED_MACRO(10,8) UNORDERED_MACRO(10,10) #ifdef HAVE_GFC_REAL_16 UNORDERED_MACRO(10,16) #endif #endif #ifdef HAVE_GFC_REAL_16 UNORDERED_MACRO(16,4) UNORDERED_MACRO(16,8) #ifdef HAVE_GFC_REAL_10 UNORDERED_MACRO(16,10) #endif UNORDERED_MACRO(16,16) #endif end interface interface IEEE_UNORDERED procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_unordered_16_16, & #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_unordered_16_10, & #endif _gfortran_ieee_unordered_16_8, & _gfortran_ieee_unordered_16_4, & #endif #ifdef HAVE_GFC_REAL_10 #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_unordered_10_16, & #endif _gfortran_ieee_unordered_10_10, & _gfortran_ieee_unordered_10_8, & _gfortran_ieee_unordered_10_4, & #endif #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_unordered_8_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_unordered_8_10, & #endif _gfortran_ieee_unordered_8_8, & _gfortran_ieee_unordered_8_4, & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_unordered_4_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_unordered_4_10, & #endif _gfortran_ieee_unordered_4_8, & _gfortran_ieee_unordered_4_4 end interface public :: IEEE_UNORDERED ! IEEE_LOGB interface elemental real(kind=4) function _gfortran_ieee_logb_4 (X) real(kind=4), intent(in) :: X end function elemental real(kind=8) function _gfortran_ieee_logb_8 (X) real(kind=8), intent(in) :: X end function #ifdef HAVE_GFC_REAL_10 elemental real(kind=10) function _gfortran_ieee_logb_10 (X) real(kind=10), intent(in) :: X end function #endif #ifdef HAVE_GFC_REAL_16 elemental real(kind=16) function _gfortran_ieee_logb_16 (X) real(kind=16), intent(in) :: X end function #endif end interface interface IEEE_LOGB procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_logb_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_logb_10, & #endif _gfortran_ieee_logb_8, & _gfortran_ieee_logb_4 end interface public :: IEEE_LOGB ! IEEE_NEXT_AFTER #define NEXT_AFTER_MACRO(A,B) \ elemental real(kind = A) function \ _gfortran_ieee_next_after_/**/A/**/_/**/B (X,Y) ; \ real(kind = A), intent(in) :: X ; \ real(kind = B), intent(in) :: Y ; \ end function interface NEXT_AFTER_MACRO(4,4) NEXT_AFTER_MACRO(4,8) #ifdef HAVE_GFC_REAL_10 NEXT_AFTER_MACRO(4,10) #endif #ifdef HAVE_GFC_REAL_16 NEXT_AFTER_MACRO(4,16) #endif NEXT_AFTER_MACRO(8,4) NEXT_AFTER_MACRO(8,8) #ifdef HAVE_GFC_REAL_10 NEXT_AFTER_MACRO(8,10) #endif #ifdef HAVE_GFC_REAL_16 NEXT_AFTER_MACRO(8,16) #endif #ifdef HAVE_GFC_REAL_10 NEXT_AFTER_MACRO(10,4) NEXT_AFTER_MACRO(10,8) NEXT_AFTER_MACRO(10,10) #ifdef HAVE_GFC_REAL_16 NEXT_AFTER_MACRO(10,16) #endif #endif #ifdef HAVE_GFC_REAL_16 NEXT_AFTER_MACRO(16,4) NEXT_AFTER_MACRO(16,8) #ifdef HAVE_GFC_REAL_10 NEXT_AFTER_MACRO(16,10) #endif NEXT_AFTER_MACRO(16,16) #endif end interface interface IEEE_NEXT_AFTER procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_next_after_16_16, & #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_next_after_16_10, & #endif _gfortran_ieee_next_after_16_8, & _gfortran_ieee_next_after_16_4, & #endif #ifdef HAVE_GFC_REAL_10 #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_next_after_10_16, & #endif _gfortran_ieee_next_after_10_10, & _gfortran_ieee_next_after_10_8, & _gfortran_ieee_next_after_10_4, & #endif #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_next_after_8_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_next_after_8_10, & #endif _gfortran_ieee_next_after_8_8, & _gfortran_ieee_next_after_8_4, & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_next_after_4_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_next_after_4_10, & #endif _gfortran_ieee_next_after_4_8, & _gfortran_ieee_next_after_4_4 end interface public :: IEEE_NEXT_AFTER ! IEEE_REM #define REM_MACRO(RES,A,B) \ elemental real(kind = RES) function \ _gfortran_ieee_rem_/**/A/**/_/**/B (X,Y) ; \ real(kind = A), intent(in) :: X ; \ real(kind = B), intent(in) :: Y ; \ end function interface REM_MACRO(4,4,4) REM_MACRO(8,4,8) #ifdef HAVE_GFC_REAL_10 REM_MACRO(10,4,10) #endif #ifdef HAVE_GFC_REAL_16 REM_MACRO(16,4,16) #endif REM_MACRO(8,8,4) REM_MACRO(8,8,8) #ifdef HAVE_GFC_REAL_10 REM_MACRO(10,8,10) #endif #ifdef HAVE_GFC_REAL_16 REM_MACRO(16,8,16) #endif #ifdef HAVE_GFC_REAL_10 REM_MACRO(10,10,4) REM_MACRO(10,10,8) REM_MACRO(10,10,10) #ifdef HAVE_GFC_REAL_16 REM_MACRO(16,10,16) #endif #endif #ifdef HAVE_GFC_REAL_16 REM_MACRO(16,16,4) REM_MACRO(16,16,8) #ifdef HAVE_GFC_REAL_10 REM_MACRO(16,16,10) #endif REM_MACRO(16,16,16) #endif end interface interface IEEE_REM procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_rem_16_16, & #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_rem_16_10, & #endif _gfortran_ieee_rem_16_8, & _gfortran_ieee_rem_16_4, & #endif #ifdef HAVE_GFC_REAL_10 #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_rem_10_16, & #endif _gfortran_ieee_rem_10_10, & _gfortran_ieee_rem_10_8, & _gfortran_ieee_rem_10_4, & #endif #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_rem_8_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_rem_8_10, & #endif _gfortran_ieee_rem_8_8, & _gfortran_ieee_rem_8_4, & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_rem_4_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_rem_4_10, & #endif _gfortran_ieee_rem_4_8, & _gfortran_ieee_rem_4_4 end interface public :: IEEE_REM ! IEEE_RINT interface elemental real(kind=4) function _gfortran_ieee_rint_4 (X) real(kind=4), intent(in) :: X end function elemental real(kind=8) function _gfortran_ieee_rint_8 (X) real(kind=8), intent(in) :: X end function #ifdef HAVE_GFC_REAL_10 elemental real(kind=10) function _gfortran_ieee_rint_10 (X) real(kind=10), intent(in) :: X end function #endif #ifdef HAVE_GFC_REAL_16 elemental real(kind=16) function _gfortran_ieee_rint_16 (X) real(kind=16), intent(in) :: X end function #endif end interface interface IEEE_RINT procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_rint_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_rint_10, & #endif _gfortran_ieee_rint_8, _gfortran_ieee_rint_4 end interface public :: IEEE_RINT ! IEEE_SCALB interface elemental real(kind=4) function _gfortran_ieee_scalb_4 (X, I) real(kind=4), intent(in) :: X integer, intent(in) :: I end function elemental real(kind=8) function _gfortran_ieee_scalb_8 (X, I) real(kind=8), intent(in) :: X integer, intent(in) :: I end function #ifdef HAVE_GFC_REAL_10 elemental real(kind=10) function _gfortran_ieee_scalb_10 (X, I) real(kind=10), intent(in) :: X integer, intent(in) :: I end function #endif #ifdef HAVE_GFC_REAL_16 elemental real(kind=16) function _gfortran_ieee_scalb_16 (X, I) real(kind=16), intent(in) :: X integer, intent(in) :: I end function #endif end interface interface IEEE_SCALB procedure & #ifdef HAVE_GFC_REAL_16 _gfortran_ieee_scalb_16, & #endif #ifdef HAVE_GFC_REAL_10 _gfortran_ieee_scalb_10, & #endif _gfortran_ieee_scalb_8, _gfortran_ieee_scalb_4 end interface public :: IEEE_SCALB ! IEEE_VALUE interface IEEE_VALUE module procedure & #ifdef HAVE_GFC_REAL_16 IEEE_VALUE_16, & #endif #ifdef HAVE_GFC_REAL_10 IEEE_VALUE_10, & #endif IEEE_VALUE_8, IEEE_VALUE_4 end interface public :: IEEE_VALUE ! IEEE_CLASS interface IEEE_CLASS module procedure & #ifdef HAVE_GFC_REAL_16 IEEE_CLASS_16, & #endif #ifdef HAVE_GFC_REAL_10 IEEE_CLASS_10, & #endif IEEE_CLASS_8, IEEE_CLASS_4 end interface public :: IEEE_CLASS ! Public declarations for contained procedures public :: IEEE_GET_ROUNDING_MODE, IEEE_SET_ROUNDING_MODE public :: IEEE_GET_UNDERFLOW_MODE, IEEE_SET_UNDERFLOW_MODE public :: IEEE_SELECTED_REAL_KIND ! IEEE_SUPPORT_ROUNDING interface IEEE_SUPPORT_ROUNDING module procedure IEEE_SUPPORT_ROUNDING_4, IEEE_SUPPORT_ROUNDING_8, & #ifdef HAVE_GFC_REAL_10 IEEE_SUPPORT_ROUNDING_10, & #endif #ifdef HAVE_GFC_REAL_16 IEEE_SUPPORT_ROUNDING_16, & #endif IEEE_SUPPORT_ROUNDING_NOARG end interface public :: IEEE_SUPPORT_ROUNDING ! Interface to the FPU-specific function interface pure integer function support_rounding_helper(flag) & bind(c, name="_gfortrani_support_fpu_rounding_mode") integer, intent(in), value :: flag end function end interface ! IEEE_SUPPORT_UNDERFLOW_CONTROL interface IEEE_SUPPORT_UNDERFLOW_CONTROL module procedure IEEE_SUPPORT_UNDERFLOW_CONTROL_4, & IEEE_SUPPORT_UNDERFLOW_CONTROL_8, & #ifdef HAVE_GFC_REAL_10 IEEE_SUPPORT_UNDERFLOW_CONTROL_10, & #endif #ifdef HAVE_GFC_REAL_16 IEEE_SUPPORT_UNDERFLOW_CONTROL_16, & #endif IEEE_SUPPORT_UNDERFLOW_CONTROL_NOARG end interface public :: IEEE_SUPPORT_UNDERFLOW_CONTROL ! Interface to the FPU-specific function interface pure integer function support_underflow_control_helper(kind) & bind(c, name="_gfortrani_support_fpu_underflow_control") integer, intent(in), value :: kind end function end interface ! IEEE_SUPPORT_* generic functions #if defined(HAVE_GFC_REAL_10) && defined(HAVE_GFC_REAL_16) # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_10, NAME/**/_16, NAME/**/_NOARG #elif defined(HAVE_GFC_REAL_10) # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_10, NAME/**/_NOARG #elif defined(HAVE_GFC_REAL_16) # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_16, NAME/**/_NOARG #else # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_NOARG #endif #define SUPPORTGENERIC(NAME) \ interface NAME ; module procedure MACRO1(NAME) ; end interface ; \ public :: NAME SUPPORTGENERIC(IEEE_SUPPORT_DATATYPE) SUPPORTGENERIC(IEEE_SUPPORT_DENORMAL) SUPPORTGENERIC(IEEE_SUPPORT_DIVIDE) SUPPORTGENERIC(IEEE_SUPPORT_INF) SUPPORTGENERIC(IEEE_SUPPORT_IO) SUPPORTGENERIC(IEEE_SUPPORT_NAN) SUPPORTGENERIC(IEEE_SUPPORT_SQRT) SUPPORTGENERIC(IEEE_SUPPORT_STANDARD) contains ! Equality operators for IEEE_CLASS_TYPE and IEEE_ROUNDING_MODE elemental logical function IEEE_CLASS_TYPE_EQ (X, Y) result(res) implicit none type(IEEE_CLASS_TYPE), intent(in) :: X, Y res = (X%hidden == Y%hidden) end function elemental logical function IEEE_CLASS_TYPE_NE (X, Y) result(res) implicit none type(IEEE_CLASS_TYPE), intent(in) :: X, Y res = (X%hidden /= Y%hidden) end function elemental logical function IEEE_ROUND_TYPE_EQ (X, Y) result(res) implicit none type(IEEE_ROUND_TYPE), intent(in) :: X, Y res = (X%hidden == Y%hidden) end function elemental logical function IEEE_ROUND_TYPE_NE (X, Y) result(res) implicit none type(IEEE_ROUND_TYPE), intent(in) :: X, Y res = (X%hidden /= Y%hidden) end function ! IEEE_SELECTED_REAL_KIND integer function IEEE_SELECTED_REAL_KIND (P, R, RADIX) result(res) implicit none integer, intent(in), optional :: P, R, RADIX ! Currently, if IEEE is supported and this module is built, it means ! all our floating-point types conform to IEEE. Hence, we simply call ! SELECTED_REAL_KIND. res = SELECTED_REAL_KIND (P, R, RADIX) end function ! IEEE_CLASS elemental function IEEE_CLASS_4 (X) result(res) implicit none real(kind=4), intent(in) :: X type(IEEE_CLASS_TYPE) :: res interface pure integer function _gfortrani_ieee_class_helper_4(val) real(kind=4), intent(in) :: val end function end interface res = IEEE_CLASS_TYPE(_gfortrani_ieee_class_helper_4(X)) end function elemental function IEEE_CLASS_8 (X) result(res) implicit none real(kind=8), intent(in) :: X type(IEEE_CLASS_TYPE) :: res interface pure integer function _gfortrani_ieee_class_helper_8(val) real(kind=8), intent(in) :: val end function end interface res = IEEE_CLASS_TYPE(_gfortrani_ieee_class_helper_8(X)) end function #ifdef HAVE_GFC_REAL_10 elemental function IEEE_CLASS_10 (X) result(res) implicit none real(kind=10), intent(in) :: X type(IEEE_CLASS_TYPE) :: res interface pure integer function _gfortrani_ieee_class_helper_10(val) real(kind=10), intent(in) :: val end function end interface res = IEEE_CLASS_TYPE(_gfortrani_ieee_class_helper_10(X)) end function #endif #ifdef HAVE_GFC_REAL_16 elemental function IEEE_CLASS_16 (X) result(res) implicit none real(kind=16), intent(in) :: X type(IEEE_CLASS_TYPE) :: res interface pure integer function _gfortrani_ieee_class_helper_16(val) real(kind=16), intent(in) :: val end function end interface res = IEEE_CLASS_TYPE(_gfortrani_ieee_class_helper_16(X)) end function #endif ! IEEE_VALUE elemental real(kind=4) function IEEE_VALUE_4(X, CLASS) result(res) real(kind=4), intent(in) :: X type(IEEE_CLASS_TYPE), intent(in) :: CLASS select case (CLASS%hidden) case (1) ! IEEE_SIGNALING_NAN res = -1 res = sqrt(res) case (2) ! IEEE_QUIET_NAN res = -1 res = sqrt(res) case (3) ! IEEE_NEGATIVE_INF res = huge(res) res = (-res) * res case (4) ! IEEE_NEGATIVE_NORMAL res = -42 case (5) ! IEEE_NEGATIVE_DENORMAL res = -tiny(res) res = res / 2 case (6) ! IEEE_NEGATIVE_ZERO res = 0 res = -res case (7) ! IEEE_POSITIVE_ZERO res = 0 case (8) ! IEEE_POSITIVE_DENORMAL res = tiny(res) res = res / 2 case (9) ! IEEE_POSITIVE_NORMAL res = 42 case (10) ! IEEE_POSITIVE_INF res = huge(res) res = res * res case default ! IEEE_OTHER_VALUE, should not happen res = 0 end select end function elemental real(kind=8) function IEEE_VALUE_8(X, CLASS) result(res) real(kind=8), intent(in) :: X type(IEEE_CLASS_TYPE), intent(in) :: CLASS select case (CLASS%hidden) case (1) ! IEEE_SIGNALING_NAN res = -1 res = sqrt(res) case (2) ! IEEE_QUIET_NAN res = -1 res = sqrt(res) case (3) ! IEEE_NEGATIVE_INF res = huge(res) res = (-res) * res case (4) ! IEEE_NEGATIVE_NORMAL res = -42 case (5) ! IEEE_NEGATIVE_DENORMAL res = -tiny(res) res = res / 2 case (6) ! IEEE_NEGATIVE_ZERO res = 0 res = -res case (7) ! IEEE_POSITIVE_ZERO res = 0 case (8) ! IEEE_POSITIVE_DENORMAL res = tiny(res) res = res / 2 case (9) ! IEEE_POSITIVE_NORMAL res = 42 case (10) ! IEEE_POSITIVE_INF res = huge(res) res = res * res case default ! IEEE_OTHER_VALUE, should not happen res = 0 end select end function #ifdef HAVE_GFC_REAL_10 elemental real(kind=10) function IEEE_VALUE_10(X, CLASS) result(res) real(kind=10), intent(in) :: X type(IEEE_CLASS_TYPE), intent(in) :: CLASS select case (CLASS%hidden) case (1) ! IEEE_SIGNALING_NAN res = -1 res = sqrt(res) case (2) ! IEEE_QUIET_NAN res = -1 res = sqrt(res) case (3) ! IEEE_NEGATIVE_INF res = huge(res) res = (-res) * res case (4) ! IEEE_NEGATIVE_NORMAL res = -42 case (5) ! IEEE_NEGATIVE_DENORMAL res = -tiny(res) res = res / 2 case (6) ! IEEE_NEGATIVE_ZERO res = 0 res = -res case (7) ! IEEE_POSITIVE_ZERO res = 0 case (8) ! IEEE_POSITIVE_DENORMAL res = tiny(res) res = res / 2 case (9) ! IEEE_POSITIVE_NORMAL res = 42 case (10) ! IEEE_POSITIVE_INF res = huge(res) res = res * res case default ! IEEE_OTHER_VALUE, should not happen res = 0 end select end function #endif #ifdef HAVE_GFC_REAL_16 elemental real(kind=16) function IEEE_VALUE_16(X, CLASS) result(res) real(kind=16), intent(in) :: X type(IEEE_CLASS_TYPE), intent(in) :: CLASS select case (CLASS%hidden) case (1) ! IEEE_SIGNALING_NAN res = -1 res = sqrt(res) case (2) ! IEEE_QUIET_NAN res = -1 res = sqrt(res) case (3) ! IEEE_NEGATIVE_INF res = huge(res) res = (-res) * res case (4) ! IEEE_NEGATIVE_NORMAL res = -42 case (5) ! IEEE_NEGATIVE_DENORMAL res = -tiny(res) res = res / 2 case (6) ! IEEE_NEGATIVE_ZERO res = 0 res = -res case (7) ! IEEE_POSITIVE_ZERO res = 0 case (8) ! IEEE_POSITIVE_DENORMAL res = tiny(res) res = res / 2 case (9) ! IEEE_POSITIVE_NORMAL res = 42 case (10) ! IEEE_POSITIVE_INF res = huge(res) res = res * res case default ! IEEE_OTHER_VALUE, should not happen res = 0 end select end function #endif ! IEEE_GET_ROUNDING_MODE subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE) implicit none type(IEEE_ROUND_TYPE), intent(out) :: ROUND_VALUE interface integer function helper() & bind(c, name="_gfortrani_get_fpu_rounding_mode") end function end interface ROUND_VALUE = IEEE_ROUND_TYPE(helper()) end subroutine ! IEEE_SET_ROUNDING_MODE subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE) implicit none type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE interface subroutine helper(val) & bind(c, name="_gfortrani_set_fpu_rounding_mode") integer, value :: val end subroutine end interface call helper(ROUND_VALUE%hidden) end subroutine ! IEEE_GET_UNDERFLOW_MODE subroutine IEEE_GET_UNDERFLOW_MODE (GRADUAL) implicit none logical, intent(out) :: GRADUAL interface integer function helper() & bind(c, name="_gfortrani_get_fpu_underflow_mode") end function end interface GRADUAL = (helper() /= 0) end subroutine ! IEEE_SET_UNDERFLOW_MODE subroutine IEEE_SET_UNDERFLOW_MODE (GRADUAL) implicit none logical, intent(in) :: GRADUAL interface subroutine helper(val) & bind(c, name="_gfortrani_set_fpu_underflow_mode") integer, value :: val end subroutine end interface call helper(merge(1, 0, GRADUAL)) end subroutine ! IEEE_SUPPORT_ROUNDING pure logical function IEEE_SUPPORT_ROUNDING_4 (ROUND_VALUE, X) result(res) implicit none real(kind=4), intent(in) :: X type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0) end function pure logical function IEEE_SUPPORT_ROUNDING_8 (ROUND_VALUE, X) result(res) implicit none real(kind=8), intent(in) :: X type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0) end function #ifdef HAVE_GFC_REAL_10 pure logical function IEEE_SUPPORT_ROUNDING_10 (ROUND_VALUE, X) result(res) implicit none real(kind=10), intent(in) :: X type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0) end function #endif #ifdef HAVE_GFC_REAL_16 pure logical function IEEE_SUPPORT_ROUNDING_16 (ROUND_VALUE, X) result(res) implicit none real(kind=16), intent(in) :: X type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0) end function #endif pure logical function IEEE_SUPPORT_ROUNDING_NOARG (ROUND_VALUE) result(res) implicit none type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0) end function ! IEEE_SUPPORT_UNDERFLOW_CONTROL pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_4 (X) result(res) implicit none real(kind=4), intent(in) :: X res = (support_underflow_control_helper(4) /= 0) end function pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_8 (X) result(res) implicit none real(kind=8), intent(in) :: X res = (support_underflow_control_helper(8) /= 0) end function #ifdef HAVE_GFC_REAL_10 pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_10 (X) result(res) implicit none real(kind=10), intent(in) :: X res = (support_underflow_control_helper(10) /= 0) end function #endif #ifdef HAVE_GFC_REAL_16 pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_16 (X) result(res) implicit none real(kind=16), intent(in) :: X res = (support_underflow_control_helper(16) /= 0) end function #endif pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_NOARG () result(res) implicit none res = (support_underflow_control_helper(4) /= 0 & .and. support_underflow_control_helper(8) /= 0 & #ifdef HAVE_GFC_REAL_10 .and. support_underflow_control_helper(10) /= 0 & #endif #ifdef HAVE_GFC_REAL_16 .and. support_underflow_control_helper(16) /= 0 & #endif ) end function ! IEEE_SUPPORT_* functions #define SUPPORTMACRO(NAME, INTKIND, VALUE) \ pure logical function NAME/**/_/**/INTKIND (X) result(res) ; \ implicit none ; \ real(INTKIND), intent(in) :: X(..) ; \ res = VALUE ; \ end function #define SUPPORTMACRO_NOARG(NAME, VALUE) \ pure logical function NAME/**/_NOARG () result(res) ; \ implicit none ; \ res = VALUE ; \ end function ! IEEE_SUPPORT_DATATYPE SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_DATATYPE,.true.) ! IEEE_SUPPORT_DENORMAL SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_DENORMAL,.true.) ! IEEE_SUPPORT_DIVIDE SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_DIVIDE,.true.) ! IEEE_SUPPORT_INF SUPPORTMACRO(IEEE_SUPPORT_INF,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_INF,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_INF,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_INF,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_INF,.true.) ! IEEE_SUPPORT_IO SUPPORTMACRO(IEEE_SUPPORT_IO,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_IO,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_IO,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_IO,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_IO,.true.) ! IEEE_SUPPORT_NAN SUPPORTMACRO(IEEE_SUPPORT_NAN,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_NAN,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_NAN,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_NAN,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_NAN,.true.) ! IEEE_SUPPORT_SQRT SUPPORTMACRO(IEEE_SUPPORT_SQRT,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_SQRT,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_SQRT,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_SQRT,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_SQRT,.true.) ! IEEE_SUPPORT_STANDARD SUPPORTMACRO(IEEE_SUPPORT_STANDARD,4,.true.) SUPPORTMACRO(IEEE_SUPPORT_STANDARD,8,.true.) #ifdef HAVE_GFC_REAL_10 SUPPORTMACRO(IEEE_SUPPORT_STANDARD,10,.true.) #endif #ifdef HAVE_GFC_REAL_16 SUPPORTMACRO(IEEE_SUPPORT_STANDARD,16,.true.) #endif SUPPORTMACRO_NOARG(IEEE_SUPPORT_STANDARD,.true.) end module IEEE_ARITHMETIC