IEEE_ARITHMETIC
, IEEE_EXCEPTIONS
and IEEE_FEATURES
.
This extension is small superset of the one described by the ISO Technical
Report ISO/IEC TR 15580:1999.
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:
The function IEEE_SELECTED_REAL_KIND
, and all the functions whose names
begin with IEEE_SUPPORT_
, are permitted to appear in specification and
constant expressions (as long as the arguments are appropriate for the context).
The elemental functions are also permitted to appear in specification
expressions, but not constant expressions.
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_FEATURES_TYPE
, and up to 11
constants of that type representing IEEE features: these are as follows.
IEEE_DATATYPE | whether any IEEE datatypes are available |
IEEE_DENORMAL | whether IEEE subnormal 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 /)
IEEE_EXCEPTIONS
are as follows.
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.
IEEE_EXCEPTIONS
.
IEEE_SELECTED_REAL_KIND
function is similar to the
SELECTED_REAL_KIND
intrinsic function, but selects among IEEE-compliant
REAL
types ignoring any that are not compliant.
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:
TINY(X)
and HUGE(X)
are
exactly those of an IEEE floating-point format;
+
, -
and *
operations conform to IEEE for at least one
rounding mode;
IEEE_COPY_SIGN
, IEEE_LOGB
, IEEE_NEXT_AFTER
,
IEEE_NEXT_DOWN
, IEEE_NEXT_UP
,
IEEE_REM
, IEEE_SCALB
and IEEE_UNORDERED
may be used.
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_SUBNORMAL() PURE LOGICAL FUNCTION IEEE_SUPPORT_SUBNORMAL(X) REAL(*),INTENT(IN) :: X[7.0] Returns 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.
This function is from Fortran 2018.
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_AWAY * | round to nearest (ties away from zero) |
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 |
* The constant IEEE_AWAY
is a Fortran 2018 addition.
The IEEE standard only requires this rounding mode for decimal,
and binary hardware does not support this, so it cannot be used.
PURE SUBROUTINE IEEE_GET_ROUNDING_MODE(ROUND_VALUE) TYPE(IEEE_ROUND_TYPE),INTENT(OUT) :: ROUND_VALUESet
ROUND_VALUE
to the current rounding mode.
(Note: Fortran 2018 has added an optional RADIX
argument to this function.)
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
.
(Note: Fortran 2018 has added an optional RADIX
argument to this function.)
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 |
[7.0]
The constants IEEE_POSITIVE_SUBNORMAL
and IEEE_NEGATIVE_SUBNORMAL
, from Fortran 2018,
are also provided; they have the same values as IEEE_POSITIVE_DENORMAL
and IEEE_NEGATIVE_DENORMAL
respectively.
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
.
Restriction: this function must not be invoked when the kind of X
or Y
is not an IEEE format, i.e.
if IEEE_SUPPORT_DATATYPE (X)
or IEEE_SUPPORT_DATATYPE (Y)
returns false.
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
Restriction: this function must not be invoked when the kind of X
is not an IEEE format, i.e.
if IEEE_SUPPORT_DATATYPE (X)
returns false.
ELEMENTAL REAL(KIND(X)) 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.
If the result is subnormal, IEEE_UNDERFLOW
is signalled.
If the result is infinite but X
was finite, IEEE_OVERFLOW
is signalled.
Restriction: this function must not be invoked when the kind of X
or Y
is not an IEEE format, i.e.
if IEEE_SUPPORT_DATATYPE (X)
or IEEE_SUPPORT_DATATYPE (Y)
returns false.
ELEMENTAL REAL(*) FUNCTION IEEE_NEXT_DOWN(X) REAL(*),INTENT(IN) :: X[7.0] Returns the nearest number to
X
that is less than it, unless
X
is −∞ or NaN, in which case if X is a signalling NaN
a quiet NaN is returned, otherwise X is returned.
No exception is signalled unless X is a signalling NaN.
ELEMENTAL REAL(*) FUNCTION IEEE_NEXT_UP(X) REAL(*),INTENT(IN) :: X[7.0] Returns the nearest number to
X
that is greater than it, unless
X
is +∞ or NaN, in which case if X is a signalling NaN
a quiet NaN is returned, otherwise X is returned.
No exception is signalled unless X is a signalling NaN.
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.
(Note: Fortran 2018 has added an optional ROUND argument to this function.)
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.