The propagation rule for the exception flags is that the information “flows upwards”. Thus each procedure starts with the flags clear, and when it returns any flag that is set will cause the corresponding flag in the caller to become set. This ensures that procedures that can be executed in parallel will not interfere with each other via the IEEE exception flags. When the computer hardware only supports a single global set of flags, this model needs enforcement on in procedures that themselves examine the flags (by IEEE_GET_FLAG or IEEE_GET_STATUS).
The propagation rule for modes, is that the mode settings “flow downwards”. This enables code motion optimisations within all routines, and the only cost is that procedures which modify the modes must restore them (to the state on entry) when they return.
The modes that are available are:
In the descriptions of the procedures, where it says REAL(*) it means any kind of REAL (this is not standard Fortran syntax). Conversely, where it says LOGICAL it means default LOGICAL only, not any other kind of LOGICAL.
The functions whose names begin ‘IEEE_SUPPORT_’ are all enquiry functions. Many of these take a REAL(*) argument X; only the kind of X is used by the enquiry function, so X is permitted to be undefined, unallocated, disassociated, or an undefined pointer.
Note that a procedure must not be invoked on a data type that does not support the feature the procedure uses; the “support” enquiry functions can be used to detect this.
IEEE_DATATYPE | whether any IEEE datatypes are available |
IEEE_DENORMAL | whether IEEE denormal values are available* |
IEEE_DIVIDE | whether division has the accuracy required by IEEE* |
IEEE_HALTING | whether control of halting is supported |
IEEE_INEXACT_FLAG | whether the inexact exception is supported* |
IEEE_INF | whether IEEE positive and negative infinities are available* |
IEEE_INVALID_FLAG | whether the invalid exception is supported* |
IEEE_NAN | whether IEEE NaNs are available* |
IEEE_ROUNDING | whether all IEEE rounding modes are available* |
IEEE_SQRT | whether SQRT conforms to the IEEE standard* |
IEEE_UNDERFLOW_FLAG | whether the underflow flag is supported* |
(*) for at least one kind of REAL.
Those feature types which are required by the user procedure should be explicitly referenced by the USE statement with an ONLY clause, e.g.
USE,INTRINSIC :: IEEE_FEATURES,ONLY:IEEE_SQRT
This ensures that if the feature specified is not available the compilation will fail.
The type IEEE_FEATURES_TYPE is not in itself useful.
TYPE IEEE_STATUS_TYPEVariables of this type can hold a floating-point status value; it combines all the mode settings and flags.
TYPE IEEE_FLAG_TYPEValues of this type specify individual IEEE exception flags; constants for these are available as follows.
IEEE_DIVIDE_BY_ZERO | division by zero flag |
IEEE_INEXACT | inexact result flag |
IEEE_INVALID | invalid operation flag |
IEEE_OVERFLOW | overflow flag |
IEEE_UNDERFLOW | underflow flag |
In addition, two array constants are available for indicating common combinations of flags:
TYPE(IEEE_FLAG_TYPE),PARAMETER :: & IEEE_USUAL(3) = (/ IEEE_DIVIDE_BY_ZERO,IEEE_INVALID,IEEE_OVERFLOW /), & IEEE_ALL(5) = (/ IEEE_DIVIDE_BY_ZERO,IEEE_INVALID,IEEE_OVERFLOW, & IEEE_UNDERFLOW,IEEE_INEXACT /)
ELEMENTAL SUBROUTINE IEEE_GET_FLAG(FLAG,FLAG_VALUE) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(OUT) :: FLAG_VALUESets FLAG_VALUE to .TRUE. if the exception flag indicated by FLAG is currently set, and to .FALSE. otherwise.
ELEMENTAL SUBROUTINE IEEE_GET_HALTING_MODE(FLAG,HALTING) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(OUT) :: HALTINGSets HALTING to .TRUE. if the program will be terminated on the occurrence of the floating-point exception designated by FLAG, and to .FALSE. otherwise.
PURE SUBROUTINE IEEE_GET_STATUS(STATUS_VALUE) TYPE(IEEE_STATUS_TYPE),INTENT(OUT) :: STATUS_VALUESets STATUS_VALUE to the current floating-point status; this contains all the current exception flag and mode settings.
PURE SUBROUTINE IEEE_SET_FLAG(FLAG,FLAG_VALUE) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(IN) :: FLAG_VALUESets the exception flag designated by FLAG to FLAG_VALUE. FLAG may be an array of any rank, as long as it has no duplicate values, in which case FLAG_VALUE may be scalar or an array with the same shape.
PURE SUBROUTINE IEEE_SET_HALTING_MODE(FLAG,HALTING) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(IN) :: HALTINGSets the halting mode for the exception designated by FLAG to HALTING. FLAG may be an array of any rank, as long as it has no duplicate values, in which case HALTING may be scalar or an array with the same shape.
PURE SUBROUTINE IEEE_SET_STATUS(STATUS_VALUE) TYPE(IEEE_STATUS_TYPE),INTENT(IN) :: STATUS_VALUESets the floating-point status to that stored in STATUS_VALUE. This must have been previously obtained by calling IEEE_GET_STATUS.
PURE LOGICAL FUNCTION IEEE_SUPPORT_FLAG(FLAG) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAGReturns whether the exception flag designated by FLAG is supported for all kinds of REAL.
PURE LOGICAL FUNCTION IEEE_SUPPORT_FLAG(FLAG,X) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG REAL(*),INTENT(IN) :: XReturns whether the exception flag designated by FLAG is supported for REAL with the kind of X.
PURE LOGICAL FUNCTION IEEE_SUPPORT_HALTING(FLAG) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAGReturns whether control of the “halting mode” for the exception designated by FLAG is supported.
PURE LOGICAL FUNCTION IEEE_SUPPORT_DATATYPE()Returns whether all real variables X satisfy the conditions for IEEE_SUPPORT_DATATYPE(X).
PURE LOGICAL FUNCTION IEEE_SUPPORT_DATATYPE(X) REAL(*),INTENT(IN) :: XReturns whether variables with the kind of X satisfy the following conditions:
PURE LOGICAL FUNCTION IEEE_SUPPORT_DENORMAL() PURE LOGICAL FUNCTION IEEE_SUPPORT_DENORMAL(X) REAL(*),INTENT(IN) :: XReturns whether for all real kinds, or variables with the kind of X, subnormal values (with absolute value between zero and TINY) exist as required by IEEE and operations on them conform to IEEE.
PURE LOGICAL FUNCTION IEEE_SUPPORT_DIVIDE() PURE LOGICAL FUNCTION IEEE_SUPPORT_DIVIDE(X) REAL(*),INTENT(IN) :: XReturns whether intrinsic division (/) conforms to IEEE, for all real kinds or variables with the kind of X respectively.
PURE LOGICAL FUNCTION IEEE_SUPPORT_INF() PURE LOGICAL FUNCTION IEEE_SUPPORT_INF(X) REAL(*),INTENT(IN) :: XReturns whether for all real kinds, or variables with the kind of X, positive and negative infinity values exist and behave in conformance with IEEE.
PURE LOGICAL FUNCTION IEEE_SUPPORT_IO() PURE LOGICAL FUNCTION IEEE_SUPPORT_IO(X) REAL(*),INTENT(IN) :: X[5.2] Returns whether for all real kinds, or variables with the kind of X, conversion to and from text during formatted input/output conforms to IEEE, for the input/output rounding modes ROUND='DOWN', 'NEAREST', 'UP' and 'ZERO' (and the corresponding edit descriptors RD, RN, RU and RZ).
PURE LOGICAL FUNCTION IEEE_SUPPORT_NAN() PURE LOGICAL FUNCTION IEEE_SUPPORT_NAN(X) REAL(*),INTENT(IN) :: XReturns whether for all real kinds, or variables with the kind of X, positive and negative “Not-a-Number” values exist and behave in conformance with IEEE.
PURE LOGICAL FUNCTION IEEE_SUPPORT_ROUNDING(ROUND_VALUE) TYPE(IEEE_ROUND_TYPE),INTENT(IN) :: ROUND_VALUE PURE LOGICAL FUNCTION IEEE_SUPPORT_ROUNDING(ROUND_VALUE,X) TYPE(IEEE_ROUND_TYPE),INTENT(IN) :: ROUND_VALUE REAL(*),INTENT(IN) :: XReturns whether for all real kinds, or variables with the kind of X, the rounding mode designated by ROUND_VALUE may be set using IEEE_SET_ROUNDING_MODE and conforms to IEEE.
PURE LOGICAL FUNCTION IEEE_SUPPORT_SQRT() PURE LOGICAL FUNCTION IEEE_SUPPORT_SQRT(X) REAL(*),INTENT(IN) :: XReturns whether the intrinsic function SQRT conforms to IEEE, for all real kinds or variables with the kind of X respectively.
PURE LOGICAL FUNCTION IEEE_SUPPORT_STANDARD() PURE LOGICAL FUNCTION IEEE_SUPPORT_STANDARD(X) REAL(*),INTENT(IN) :: XReturns whether for all real kinds, or variables with the kind of X, all the facilities described by the IEEE modules except for input/output conversions (see IEEE_SUPPORT_IO) are supported and conform to IEEE.
PURE LOGICAL FUNCTION IEEE_SUPPORT_UNDERFLOW_CONTROL() PURE LOGICAL FUNCTION IEEE_SUPPORT_UNDERFLOW_CONTROL(X) REAL(*),INTENT(IN) :: X[5.2] Returns whether for all real kinds, or variables with the kind of X, the underflow mode can be controlled with IEEE_SET_UNDERFLOW_MODE.
TYPE IEEE_ROUND_TYPEValues of this type specify the IEEE rounding mode. The following predefined constants are provided.
IEEE_DOWN | round down (towards minus infinity) |
IEEE_NEAREST | round to nearest (ties to even) |
IEEE_TO_ZERO | round positive numbers down, negative numbers up |
IEEE_UP | round up (towards positive infinity) |
IEEE_OTHER | any other rounding mode |
PURE SUBROUTINE IEEE_GET_ROUNDING_MODE(ROUND_VALUE) TYPE(IEEE_ROUND_TYPE),INTENT(OUT) :: ROUND_VALUESet ROUND_VALUE to the current rounding mode.
PURE SUBROUTINE IEEE_SET_ROUNDING_MODE(ROUND_VALUE) TYPE(IEEE_ROUND_TYPE),INTENT(IN) :: ROUND_VALUESet the rounding mode to that designated by ROUND_VALUE.
With gradual underflow, the space between -TINY(X) and TINY(X) is filled with equally-spaced “subnormal” numbers; the spacing of these numbers is equal to the spacing of model numbers above TINY(X) (and equal to the smallest subnormal number). This gradually reduces the precision of the numbers as they get closer to zero: the smallest number has only one bit of precision, so any calculation with such a number will have a very large relative error.
With abrupt underflow, the only value between -TINY(X) and TINY(X) is zero. This kind of underflow is nearly universal in non-IEEE arithmetics and is widely provided by hardware even for IEEE arithmetic. Its main advantage is that it can be much faster.
SUBROUTINE IEEE_GET_UNDERFLOW_MODE(GRADUAL) LOGICAL,INTENT(OUT) :: GRADUALSets GRADUAL to .TRUE. if the current underflow mode is gradual underflow, and to .FALSE. if it is abrupt underflow.
SUBROUTINE IEEE_SET_UNDERFLOW_MODE(GRADUAL) LOGICAL,INTENT(IN) :: GRADUALSets the underflow mode to gradual underflow if GRADUAL is .TRUE., and to abrupt underflow if it is .FALSE..
TYPE IEEE_CLASS_TYPEValues of this type indicate the IEEE class of a number; this is equal to one of the provided constants:
IEEE_NEGATIVE_DENORMAL | negative subnormal number x, in the range −TINY(x)<x<0 |
IEEE_NEGATIVE_INF | −∞ (negative infinity) |
IEEE_NEGATIVE_NORMAL | negative normal number x, in the range −HUGE(x)≤x≤−TINY(x) |
IEEE_NEGATIVE_ZERO | −0 (zero with the sign bit set) |
IEEE_POSITIVE_DENORMAL | positive subnormal number x, in the range 0<x<TINY(x) |
IEEE_POSITIVE_INF | +∞ (positive infinity) |
IEEE_POSITIVE_NORMAL | positive normal number x, in the range TINY(x)≤x≤HUGE(x) |
IEEE_POSITIVE_ZERO | +0 (zero with the sign bit clear) |
IEEE_QUIET_NAN | Not-a-Number (usually the result of an invalid operation) |
IEEE_SIGNALING_NAN | Not-a-Number which raises the invalid signal on reference |
[5.2] IEEE_OTHER_VALUE | any value that does not fit one of the above categories |
The comparison operators .EQ. (=) and .NE. (/=) are provided for comparing values of this type.
ELEMENTAL TYPE(IEEE_CLASS_TYPE) FUNCTION IEEE_CLASS(X) REAL(*),INTENT(IN) :: Xreturns the classification of the value of X.
ELEMENTAL REAL(*) FUNCTION IEEE_VALUE(X,CLASS) REAL(*),INTENT(IN) :: X TYPE(IEEE_CLASS_TYPE),INTENT(IN) :: CLASSReturns a “sample” value with the kind of X and the classification designated by CLASS.
ELEMENTAL LOGICAL FUNCTION IEEE_IS_FINITE(X) REAL(*),INTENT(IN) :: XReturns whether X is “finite”, i.e. not an infinity, NaN, or IEEE_OTHER_VALUE.
ELEMENTAL LOGICAL FUNCTION IEEE_IS_NAN(X) REAL(*),INTENT(IN) :: XReturns whether X is a NaN.
ELEMENTAL LOGICAL FUNCTION IEEE_IS_NEGATIVE(X) REAL(*),INTENT(IN) :: XReturns whether X is negative; it differs the comparison X<0 only in the case of negative zero, where it returns .TRUE..
ELEMENTAL LOGICAL FUNCTION IEEE_UNORDERED(X,Y) REAL(*),INTENT(IN) :: X,YReturns the value of ‘IEEE_IS_NAN(X) .OR. IEEE_IS_NAN(Y)’.
ELEMENTAL REAL(*) FUNCTION IEEE_COPY_SIGN(X,Y) REAL(*),INTENT(IN) :: X,YReturns X with the sign bit of Y.
ELEMENTAL REAL(*) FUNCTION IEEE_LOGB(X) REAL(*),INTENT(IN) :: XIf X is zero, returns −∞ if infinity is supported and -HUGE(X) otherwise. For nonzero X, returns EXPONENT(X)-1
ELEMENTAL REAL(*) FUNCTION IEEE_NEXT_AFTER(X,Y) REAL(*),INTENT(IN) :: X,YReturns the nearest number to X that is closer to Y, or X if X and Y are equal.
ELEMENTAL REAL(*) FUNCTION IEEE_REM(X,Y) REAL(*),INTENT(IN) :: X,YReturns the exact remainder resulting from the division of X by Y.
ELEMENTAL REAL(*) FUNCTION IEEE_RINT(X) REAL(*),INTENT(IN) :: XReturns X rounded to an integer according to the current rounding mode.
ELEMENTAL REAL(*) FUNCTION IEEE_SCALB(X,I) REAL(*),INTENT(IN) :: X INTEGER(*),INTENT(IN) :: IReturns SCALE(X,I), i.e. X*2I, without computing 2I separately.