NAG Fortran Compiler, Release 7.2: Updated IEEE arithmetic capabilities

Navigation: Previous Up Next

## 11.9 Updated IEEE arithmetic capabilities

These features were available in Release 7.0:

- The module `IEEE_ARITHMETIC` has new functions `IEEE_NEXT_DOWN` and `IEEE_NEXT_UP`. These are elemental with a single argument, which must be a `REAL` of an IEEE kind (that is, `IEEE_SUPPORT_DATATYPE` must return `.TRUE.` for that kind of `REAL`). They return the next IEEE value, that does not compare equal to the argument, in the downwards and upwards directions respectively, except that the next down from −∞ is −∞ itself, and the next up from +∞ is +∞ itself. These functions are superior to the old `IEEE_NEXT_AFTER` function in that they do not signal any exception unless the argument is a signalling NaN (in which case `IEEE_INVALID` is signalled).

  For example, `IEEE_NEXT_UP(-0.0)` and `IEEE_NEXT_UP(+0.0)` both return the smallest positive subnormal value (provided subnormal values are supported), without signalling `IEEE_UNDERFLOW` (which `IEEE_NEXT_AFTER` does).

  Similarly, `IEEE_NEXT_UP(HUGE(0.0))` returns +∞ without signalling overflow.

- The module `IEEE_ARITHMETIC` has new named constants `IEEE_NEGATIVE_SUBNORMAL`, `IEEE_POSITIVE_SUBNORMAL`, and the new function `IEEE_SUPPORT_SUBNORMAL`. These are from Fortran 2018, and reflect the change of terminology in the IEEE arithmetic standard in 2008. They are equivalent to the old functions `IEEE_NEGATIVE_DENORMAL`, `IEEE_POSITIVE_DENORMAL` and `IEEE_SUPPORT_DENORMAL`.

- The requirement that the `FLAG_VALUE` argument to `IEEE_GET_FLAG` and `IEEE_SET_FLAG`, the `HALTING` argument to `IEEE_GET_HALTING_MODE` and `IEEE_SET_HALTING_MODE`, and the `GRADUAL` argument to `IEEE_GET_UNDERFLOW_MODE` and `IEEE_SET_UNDERFLOW_MODE`, be default `LOGICAL` has been dropped; any kind of `LOGICAL` is now permitted.

  For example,

             USE F90_KIND
             USE IEEE_ARITHMETIC
             LOGICAL(byte) flags(SIZE(IEEE_ALL))
             CALL IEEE_GET_FLAG(IEEE_ALL,flags)

  will retrieve the current IEEE flags into an array of one-byte `LOGICAL`s.

These items are available in Release 7.2:

- The named constant `IEEE_AWAY` is of type `IEEE_ROUND_TYPE`, and represents a rounding mode that rounds to nearest, with ties away from zero. The IEEE standard only requires this rounding mode for decimal, and binary hardware does not support this, so it cannot be used.
- The elemental function `IEEE_FMA` performs a fused multiply-add operation. It has the syntax:

      IEEE_FMA (A, B, C)

  `A` : type Real (any IEEE kind);
  `B` : same type and kind as `A`;
  `C` : same type and kind as `A`.

  Result : Same type and kind as `A`.

  The result of the function is the value of (`A`×`B`)+`C` with only one rounding; that is, the whole operation is computed mathematically and only rounded to the format of `A` at the end. For example, `IEEE_OVERFLOW` is not signalled if `A`×`B` overflows, but only if the final result is out of range.

  Restriction: this function must not be invoked when the kind of `A` is not an IEEE format, i.e. if `IEEE_SUPPORT_DATATYPE (A)` returns false.

- The pure subroutine `IEEE_GET_MODES` retrieves the halting modes, rounding modes, and underflow mode in a single object. Its syntax is:

      IEEE_GET_MODES (MODES)

  `MODES` : scalar of type `IEEE_MODES_TYPE`, `Intent(Out)`.

  The retrieved modes can be used by `IEEE_SET_MODES` to restore the modes.
- The pure subroutine `IEEE_GET_ROUNDING_MODE`, which retrieves the current rounding mode, now has an optional argument to specify the radix. The syntax is thus now:

      IEEE_GET_ROUNDING_MODE (ROUND_VALUE [, RADIX ])

  `ROUND_VALUE` : type `IEEE_ROUND_TYPE`, Intent(Out);
  `RADIX` (optional) : Integer, Intent(In), must be equal to two or ten.

  The `ROUND_VALUE` argument is assigned the current rounding mode for the specified radix. If `RADIX` does not appear, the binary rounding mode is assigned.

- The elemental function `IEEE_INT` converts an IEEE Real value to Integer with a specific rounding mode. It has the syntax:

      IEEE_INT (A, ROUND [, KIND ])

  `A` : type Real;
  `ROUND` : type `IEEE_ROUND_TYPE`;
  `KIND` (optional) : scalar Integer constant expression;
  Result : type Integer, with kind `KIND` if `KIND` appears, otherwise default kind.

  The value of `A` is rounded to an integer using the rounding mode specified by `ROUND`. If that value is representable in the result kind, the result has that value; otherwise, the result is processor-dependent and `IEEE_INVALID` is signalled.

  This operation is either the `convertToInteger{round}` or the `convertToIntegerExact{round}` operation specified by the IEEE standard. If it is the latter, and `IEEE_INVALID` was not signalled, but `A` was not already an integer, `IEEE_INEXACT` is signalled.

  Restriction: this function must not be invoked when the kind of `A` is not an IEEE format, i.e. if `IEEE_SUPPORT_DATATYPE (A)` returns false.

- The elemental functions `IEEE_MAX_NUM`, `IEEE_MAX_NUM_MAG`, `IEEE_MIN_NUM`, `IEEE_MIN_NUM_MAG` perform maximum/minimum operations ignoring NaN values. If an argument is a signalling NaN, `IEEE_INVALID` is raised, if only one argument is a NaN, the result is the other argument; only if both arguments are NaNs is the result a NaN. The syntax for `IEEE_MAX_NUM` is:

      IEEE_MAX_NUM (X, Y)

  `X` : type Real;
  `Y` : same type and kind as `X`;
  Result : same type and kind as `X`.

  The value of the result is the maximum value of `X` and `Y`, ignoring NaN.

  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.

  The `IEEE_MAX_NUM_MAG` has the same syntax (apart from the name), and the result is whichever of `X` and `Y` has the greater magnitude. The same restriction applies.

  The `IEEE_MIN_NUM` has the same syntax (apart from the name), and the result is the minimum value of `X` and `Y`, ignoring NaN. The same restriction applies.

  The `IEEE_MIN_NUM_MAG` has the same syntax (apart from the name), and the result is whichever of `X` and `Y` has the smaller magnitude. The same restriction applies.

- The derived type `IEEE_MODES_TYPE` contains the all the floating-point modes: the halting modes, the rounding modes, and the underflow mode. It is used by the `IEEE_GET_MODES` and `IEEE_SET_MODES` subroutines.
- The elemental functions `IEEE_QUIET_`{`EQ`|`NE`|`LT`|`LE`|`GT`|`GE`} compare two IEEE format numbers, without raising any signal if an operand is a quiet NaN. If an operand is a signalling NaN, the `IEEE_INVALID` exception is raised. `IEEE_QUIET_EQ` and `IEEE_QUIET_NE` are exactly the same as `==` and `/=`, apart from only being usable on IEEE format numbers. The `IEEE_QUIET_EQ` function has the syntax:

      IEEE_QUIET_EQ (A, B)

  `A` : type Real (any IEEE kind);
  `B` : same type and kind as `A`;

  Result : Logical of default kind.

  The syntax of `IEEE_QUIET_NE` et al is the same, except for the name of the function.

  Restriction: these functions must not be invoked when the kind of X is not an IEEE format, i.e. if `IEEE_SUPPORT_DATATYPE (X)` returns false.

- The elemental function `IEEE_REAL` converts an Integer or IEEE format Real value to the specified IEEE format Real value. Its syntax is:

      IEEE_REAL (A, [, KIND ])

  `A` : type Real or Integer;
  `KIND` (optional) : scalar Integer constant expression;
  Result : type Real, with kind `KIND` if `KIND` appears, otherwise default kind.

  If the value of `A` is representable in the kind of the result, that value is the result. Otherwise, the value of `A` is rounded to the kind of the result using the current rounding mode.

  Restriction: this function must not be invoked when the kind of `A` or the result is not an IEEE format, i.e. if `IEEE_SUPPORT_DATATYPE (A)` or if `IEEE_SUPPORT_DATATYPE(REAL(0,KIND))` returns false.

- The elemental function `IEEE_RINT`, which rounds an IEEE number to an integer without changing its format, now has an optional argument `ROUND` which specifies the rounding required. The revised syntax is:

      IEEE_RINT (X [, ROUND ])

  `X` : type Real (any IEEE kind);
  `ROUND` (optional) : type `IEEE_ROUND_TYPE`.

  Result : Same type and kind as `X`.

  When `ROUND` is present, the result is the value of `X` rounded to an integer according to the mode specified by `ROUND`; this is the operation the IEEE standard calls `roundToIntegral{rounding}`. When `ROUND` is absent, the result is the value of `X` rounded to an integer according to the current rounding mode; this is the operation the IEEE standard calls `roundToIntegralExact`.

  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.

- The pure subroutine `IEEE_SET_MODES` sets the halting modes, rounding modes, and underflow mode to the state when a previous call to `IEEE_GET_MODES` was made. Its syntax is:

      IEEE_SET_MODES (MODES)

  `MODES` : scalar of type `IEEE_MODES_TYPE`, `Intent(In)`.

  The value of `MODES` must be one that was obtained via `IEEE_GET_MODES`.
- The pure subroutine `IEEE_SET_ROUNDING_MODE`, which sets the rounding mode, now has an optional argument to specify the radix. The syntax is thus now:

      IEEE_SET_ROUNDING_MODE (ROUND_VALUE [, RADIX ])

  `ROUND_VALUE` : type `IEEE_ROUND_TYPE`, Intent(In);
  `RADIX` (optional) : Integer, Intent(In), must be equal to two or ten.

  The rounding mode for the specified radix is set to `ROUND_VALUE`. If `RADIX` does not appear, the binary rounding mode is set.

  Restriction: This subroutine must not be invoked unless there is some `X` (with radix `RADIX` if it is present) for which both `IEEE_SUPPORT_DATATYPE(X)` and `IEEE_SUPPORT_ROUNDING(ROUND_VALUE,X)` are true.

- The elemental functions `IEEE_SIGNALING_`{`EQ`|`NE`|`LT`|`LE`|`GT`|`GE`} compare two IEEE format numbers, raising the `IEEE_INVALID` exception if an operand is a NaN (whether quiet or signalling). `IEEE_SIGNALING_LT`, `IEEE_SIGNALING_LE`, `IEEE_SIGNALING_GT` and `IEEE_SIGNALING_GE` are exactly the same as `<`, `<=`, `>` and `>=`, apart from only being usable on IEEE format numbers. The `IEEE_SIGNALING_EQ` function has the syntax:

      IEEE_SIGNALING_EQ (A, B)

  `A` : type Real (any IEEE kind);
  `B` : same type and kind as `A`;

  Result : Logical of default kind.

  The syntax of `IEEE_SIGNALING_NE` et al is the same, except for the name of the function.

  Restriction: these functions must not be invoked when the kind of X is not an IEEE format, i.e. if `IEEE_SUPPORT_DATATYPE (X)` returns false.

- The elemental function `IEEE_SIGNBIT` queries the sign bit of an IEEE format number. It has the syntax:

  `IEEE_SIGNBIT (X)`

  `X` : type Real (any kind);

  Result : Logical of default kind.

  The result is true if and only if the sign bit is set (indicating negative for any value that is not a NaN).

  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.