J3/16-276r2
To: J3
From: Robert Corbett
Subject: IEEE comparisons
Date: 2016 October 13
1. Introduction
This paper proposes edits to improve conformance of Fortran
relational intrinsic operations and IEEE comparison functions with
the requirements and recommendations specified for comparisons in
ISO/IEC/IEEE 60559:2011(E).
2. Discussion
ISO/IEC/IEEE 60559:2011(E) requires implementations to provide
twenty-two comparison predicates for all supported floating-point
formats. Each of the comparison predicates is either unordered,
signaling or unordered quiet. An unordered-signaling comparison
signals an invalid operation exception if one or both of the values
being compared is a NaN. An unordered-quiet comparison signals an
invalid operation exception if one or both of the values being
compared is a signaling NaN. The comparison predicates do not
signal any other exceptions.
The Fortran 2015 draft designated 16-007r2 requires relational
intrinsic operations for IEEE values to be implemented using
unordered-signaling comparisons. ISO/IEC/IEEE 60559:2011(E)
recommends a different binding. Order relational operations are
to be implemented using unordered-signaling comparisons, but
equality operations are to be implemented using unordered-quiet
comparisons. The 1989 edition of ISO/IEC 60559 explicitly required
FORTRAN processors to implement x .EQ. y and x .NE. y using
unordered-quiet comparisons.
If a Fortran processor supports NaNs for a given real kind type
parameter value, comparisons of real values that have that kind
type parameter value in a scoping unit that accesses IEEE_EXCEPTIONS
or IEEE_ARITHMETIC shall provide the functionality of the comparison
predicates for the corresponding floating-point format. The
following table gives examples of ways the comparison predicates
can be expressed in Fortran.
Comparison Predicate Fortran Equivalents
---------- --------- ------- -----------
compareQuietEqual(x, y) x .EQ. y
x == y
IEEE_QUIET_EQ(x, y)
.NOT. (x .NE. y)
.NOT. (x /= y)
.NOT. IEEE_QUIET_NE(x, y)
compareQuietNotEqual(x, y) x .NE. y
x /= y
IEEE_QUIET_NE(x, y)
.NOT. (x .EQ. y)
.NOT. (x == y)
.NOT. IEEE_QUIET_EQ(x, y)
compareSignalingEqual(x, y) IEEE_SIGNALING_EQ(x, y)
.NOT. IEEE_SIGNALING_NE(x, y)
compareSignalingGreater(x, y) x .GT. y
x > y
IEEE_SIGNALING_GT(x, y)
compareSignalingGreaterEqual(x, y) x .GE. y
x >= y
IEEE_SIGNALING_GE(x, y)
compareSignalingLess(x, y) x .LT. y
x < y
IEEE_SIGNALING_LT(x, y)
compareSignalingLessEqual(x, y) x .LE. y
x <= y
IEEE_SIGNALING_LE(x, y)
compareSignalingNotEqual(x, y) IEEE_SIGNALING_NE(x, y)
.NOT. IEEE_SIGNALING_EQ(x, y)
compareSignalingNotGreater(x, y) .NOT. (x .GT. y)
.NOT. (x > y)
.NOT. IEEE_SIGNALING_GT(x, y)
compareSignalingLessUnordered(x, y) .NOT. (x .GE. y)
.NOT. (x >= y)
.NOT. IEEE_SIGNALING_GE(x, y)
compareSignalingNotLess(x, y) .NOT. (x .LT. y)
.NOT. (x < y)
.NOT. IEEE_SIGNALING_LT(x, y)
compareSignalingGreaterUnordered(x, y) .NOT. (x .LE. y)
.NOT. (x <= y)
.NOT. IEEE_SIGNALING_LE(x, Y)
compareQuietGreater(x, y) IEEE_QUIET_GT(x, y)
compareQuietGreaterEqual(x, y) IEEE_QUIET_GE(x, y)
compareQuietLess(x, y) IEEE_QUIET_LT(x, y)
compareQuietLessEqual(x, y) IEEE_QUIET_LE(x, y)
compareQuietUnordered(x, y) IEEE_UNORDERED(x, y)
compareQuietNotGreater(x, y) .NOT. IEEE_QUIET_GT(x, y)
compareQuietLessUnordered(x, y) .NOT. IEEE_QUIET_GE(x, y)
compareQuietNotLess(x, y) .NOT. IEEE_QUIET_LT(x, y)
compareQuietGreaterUnordered(x, y) .NOT. IEEE_QUIET_LE(x, y)
compareQuietOrdered(x, y) .NOT. IEEE_UNORDERED(x, y)
The relational intrinsic operations for real operands with the same
kind type parameter value consist solely of the comparison operation.
If the operands have different kind type parameter values, the
operands are converted to real values with the kind type parameter
value before the comparison is done (paragraph 7 of
Subclause 10.1.5.5.1 of 16-007r2). Those conversions might signal
exceptions in addition to exceptions signaled by the comparison.
Other than IEEE_UNORDERED, the comparison functions defined in
IEEE_ARITHMETIC require their arguments to have the same kind type
parameter value. The arguments of IEEE_UNORDERED can have any
combination of real kind type parameter values.
The note proposed for Subclause 10.1.5.4.2 is a restatement of part
of the note that appears as the final paragraph of Subclause 5.11 of
ISO/IEC/IEEE 60559:2011(E). The note could have been added to
Subclause 10.1.5.5.2p2+ [160, 6+] instead. The proposed location
seems a little better. The note is unnecessary, but it adds
certainty that NaNs must be considered as possible values.
The note proposed for Subclause 17.3 is intended to help the reader
understand the relevant portion of the semantics of the conditional
predicates defined in ISO/IEC/IEEE 60559:2011(E) without requiring
him or her to read ISO/IEC/IEEE 60559:2011(E).
The correspondence between the relational operators and the IEEE
conditional predicates is expressed using Table 17.0a because I was
told to use a table at meeting 210. I use the notation 17.0a, because
the table will be the first table in the clause.
The text that states that complex comparisons may signal IEEE_INVALID
could be strengthened to require IEEE_INVALID to be signaled in some
cases, but care must be taken to avoid prohibiting desirable
optimizations.
The examples given for the signaling IEEE comparison functions are
slightly flawed. Because the values of the expressions are known in
advance, a processor is not required to evaluate those expressions
(see 10.1.7p1, 161:11-12). If the expressions are not evaluated,
they will not signal IEEE_INVALID.
The function IEEE_UNORDERED does not require IEEE_SUPPORT_NAN(X)
and IEEE_SUPPORT_NAN(Y) to be true. I think it should, but I did
not include an edit for that.
ISO/IEC/IEEE 60559:2011(E) requires the comparison predicate
compareQuietUnordered to signal an invalid operation exception
if at least one of its operands is a signaling NaN. That
requirement is reasonable if X and Y are of the same format, but
it might be unreasonable if they have different formats. One
way to implement IEEE_UNORDERED for operands of different
formats is as
(X .NE. X) .OR. (Y .NE. Y)
If the .OR. operation is short-circuited and X is a NaN, the
implementation might not check if Y is a signaling NaN.
3. Edits to 16-007r2
[xix, Introduction]
Between "IEEE_QUIET_NE perform quiet comparisons." and
"The decimal rounding mode", insert
"The new functions IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE,
IEEE_SIGNALING_GT, IEEE_SIGNALING_GE, IEEE_SIGNALING_LE,
IEEE_SIGNALING_LT, and IEEE_SIGNALING_NE perform signaling
comparisons."
[160:6+, 10.1.5.5.2 "Evaluation of relational intrinsic operations" p2+]
Insert the note
"NOTE 10.25a
Whether an operand of a relational intrinsic operation could be an
IEEE NaN affects whether expressions are equivalent. For example,
if x or y could be a NaN, the expressions
.NOT. (x .LT. y) and x .GE. y
are not equivalent."
[449:14-16, 17.3 "The exceptions" p1]
Replace the sentence
"In a numeric relational operation ... are unordered."
with
"IEEE_INVALID occurs for numeric relational intrinsic operations as
specified below."
[449:38+, 17.3 "The exceptions" p5+]
Insert the note
"NOTE 17.2a
The comparison predicates defined by ISO/IEC/IEEE 60559:2011
are either unordered signaling or unordered quiet. An unordered
signaling predicate signals an invalid operation exception if and
only if at least one of the values being compared is a NaN. An
unordered quiet predicate signals an invalid operation exception
if and only if at least one of the values being compared is a
signaling NaN. The comparison predicates do not signal any other
exceptions."
[449:38++, 17.3 "The exceptions" p5++]
Following the note added by the previous edit, insert
"In a scoping unit that has access to IEEE_EXCEPTIONS or
IEEE_ARITHMETIC, if /x_1/ and /x_2/ are numeric entities, the type
of /x_1 + x_2/ is real, and /IEEE_SUPPORT_NAN(x_1 + x_2)/ is true,
then the relational intrinsic operation /x_1 rel-op x_2/ shall
signal IEEE_INVALID as specified for the conditional predicate of
ISO/IEC/IEEE 60559:2011 corresponding to /rel-op/ indicated by
Table 17.0a. If the types or kind type parameters of /x_1/
and /x_2/ differ, the
conversions (\ref interpretation of relational operations)
might signal exceptions instead of or in addition to
an IEEE_INVALID exception signaled by the comparison."
[449:38+++, 17.3 "The exceptions" p5+++]
Following the text added by the previous edit, insert the
table
" Table 17.0a IEEE Relational Operator Correspondence
Operators IEEE Comparison Predicate
========= ==== ========== =========
.LT. or < compareSignalingLess
.LE. or <= compareSignalingLessEqual
.GT. or > compareSignalingGreater
.GE. or >= compareSignalingGreaterEqual
.EQ. or == compareQuietEqual
.NE. or /= compareQuietNotEqual
[449:38++++, 17.3 "The exceptions" p5++++]
Following the table added by the previous edit, insert
"In a scoping unit that has access to IEEE_EXCEPTIONS or
IEEE_ARITHMETIC, if /x_1/ or /x_2/ are numeric entities, the type
of /x_1 + x_2/ is complex, and IEEE_SUPPORT_NAN(REAL(x_1 + x_2)) is
true, then the relational operation may signal IEEE_INVALID if at
least one of the values of the real and imaginary parts of the
values being compared is a signaling NaN. If any conversions are
done before the values are compared, those conversions might signal
exceptions instead of or in addition to an IEEE_INVALID exception
signaled by the comparison."
[454, 17.10 "Summary of the procedures" Table 17.1]
Between IEEE_SET_UNDERFLOW_MODE and IEEE_SIGNBIT, insert
"IEEE_SIGNALING_EQ (A,B) E Signaling compares equal
IEEE_SIGNALING_GE (A,B) E Signaling compares greater than or equal
IEEE_SIGNALING_GT (A,B) E Signaling compares greater than
IEEE_SIGNALING_LE (A,B) E Signaling compares less than or equal
IEEE_SIGNALING_LT (A,B) E Signaling compares less than
IEEE_SIGNALING_NE (A,B) E Signaling compares not equal"
[464:14, 17.11.24 "IEEE_QUIET_EQ" p3]
Replace "same type and type parameters as A" with
"same type and kind type parameter as A."
[464:15, 17.11.24 "IEEE_QUIET_EQ" p4]
Replace "IEEE_QUIET_EQ (A)" with "IEEE_QUIET_EQ (A, B)".
[464:19-20, 17.11.24 "IEEE_QUIET_EQ" p6]
Replace "60559:2011; ... signaled." with
"60559:2011; that is, it is true if and only if A compares equal to B.
If A or B is a NaN, the result will be false. If A or B is a
signaling NaN, IEEE_INVALID signals; otherwise, no exception is
signaled."
[464:28, 17.11.25 "IEEE_QUIET_GE" p3]
Replace "same type and type parameters as A" with
"same type and kind type parameter as A."
[464:29, 17.11.25 "IEEE_QUIET_GE" p4]
Replace "IEEE_QUIET_GE (A)" with "IEEE_QUIET_GE (A, B)".
[464:33-34, 17.11.25 "IEEE_QUIET_GE" p6]
Replace "60559:2011; ... signaled." with
"60559:2011; that is, it is true if and only if A compares greater
than or equal to B. If A or B is a NaN, the result will be false.
If A or B is a signaling NaN, IEEE_INVALID signals; otherwise, no
exception is signaled."
[465:6, 17.11.26 "IEEE_QUIET_GT" p3]
Replace "same type and type parameters as A" with
"same type and kind type parameter as A."
[465:7, 17.11.26 "IEEE_QUIET_GT" p4]
Replace "IEEE_QUIET_GT (A)" with "IEEE_QUIET_GT (A, B)".
[465:11-12, 17.11.26 "IEEE_QUIET_GT" p6]
Replace "60559:2011; ... signaled." with
"60559:2011; that is, it is true if and only if A compares greater
than B. If A or B is a NaN, the result will be false. If A or B
is a signaling NaN, IEEE_INVALID signals; otherwise, no exception
is signaled."
[465:20, 17.11.27 "IEEE_QUIET_LE" p3]
Replace "same type and type parameters as A" with
"same type and kind type parameter as A."
[465:21, 17.11.27 "IEEE_QUIET_LE" p4]
Replace "IEEE_QUIET_LE (A)" with "IEEE_QUIET_LE (A, B)".
[465:25-26, 17.11.27 "IEEE_QUIET_LE" p6]
Replace "60559:2011; ... signaled." with
"60559:2011; that is, it is true if and only if A compares less than
or equal to B. If A or B is a NaN, the result will be false. If
A or B is a signaling NaN, IEEE_INVALID signals; otherwise, no
exception is signaled."
[465:34, 17.11.28 "IEEE_QUIET_LT" p3]
Replace "same type and type parameters as A" with
"same type and kind type parameter as A."
[465:35, 17.11.28 "IEEE_QUIET_LT" p4]
Replace "IEEE_QUIET_LT (A)" with "IEEE_QUIET_LT (A, B)".
[466:2-3, 17.11.28 "IEEE_QUIET_LT" p6]
Replace "60559:2011; ... signaled." with
"60559:2011; that is, it is true if and only if A compares less than B.
If A or B is a NaN, the result will be false. If A or B is a
signaling NaN, IEEE_INVALID signals; otherwise, no exception is
signaled."
[466:11, 17.11.29 "IEEE_QUIET_NE" p3]
Replace "same type and type parameters as A" with
"same type and kind type parameter as A."
[466:12, 17.11.29 "IEEE_QUIET_NE" p4]
Replace "IEEE_QUIET_NE (A)" with "IEEE_QUIET_NE (A, B)".
[466:16-17, 17.11.29 "IEEE_QUIET_NE" p6]
Replace "60559:2011; ... signaled." with
"60559:2011; that is, it is true if and only if A compares not equal
to B. If A or B is a NaN, the result will be true. If A or B is a
signaling NaN, IEEE_INVALID signals; otherwise, no exception is
signaled."
[471:4+, 17.11.40p5+]
Insert
"17.11.40a IEEE_SIGNALING_EQ (A, B)
Description. Signaling compares equal.
Class. Elemental function.
Arguments.
A shall be of type real
B shall be of the same type and kind type parameter as A.
Restrictions. IEEE_SIGNALING_EQ (A, B) shall not be invoked if
IEEE_SUPPORT_DATATYPE(A) has the value false.
Result Characteristics. Default logical.
Result Value. The result has the value specified for the
compareSignalingEqual operation in ISO/IEC/IEEE 60559:2011; that is,
it is true if and only if A compares equal to B. If A or B is a
NaN, the result will be false and IEEE_INVALID signals; otherwise,
no exception is signaled.
Example. IEEE_SIGNALING_EQ(1.0, IEEE_VALUE(IEEE_QUIET_NAN)) has the
value false and signals IEEE_INVALID."
17.11.40b IEEE_SIGNALING_GE (A, B)
Description. Signaling compares greater than or equal.
Class. Elemental function.
Arguments.
A shall be of type real
B shall be of the same type and kind type parameter as A.
Restrictions. IEEE_SIGNALING_GE (A, B) shall not be invoked if
IEEE_SUPPORT_DATATYPE(A) has the value false.
Result Characteristics. Default logical.
Result Value. The result has the value specified for the
compareSignalingGreaterEqual operation in ISO/IEC/IEEE 60559:2011;
that is, it is true if and only if A compares greater than or equal
to B. If A or B is a NaN, the result will be false and IEEE_INVALID
signals; otherwise, no exception is signaled.
Example. IEEE_SIGNALING_GE(1.0, IEEE_VALUE(IEEE_QUIET_NAN)) has the
value false and signals IEEE_INVALID."
17.11.40c IEEE_SIGNALING_GT (A, B)
Description. Signaling compares greater than.
Class. Elemental function.
Arguments.
A shall be of type real
B shall be of the same type and kind type parameter as A.
Restrictions. IEEE_SIGNALING_GT (A, B) shall not be invoked if
IEEE_SUPPORT_DATATYPE(A) has the value false.
Result Characteristics. Default logical.
Result Value. The result has the value specified for the
compareSignalingGreater operation in ISO/IEC/IEEE 60559:2011; that
is, it is true if and only if A compares greater than B. If A or B
is a NaN, the result will be false and IEEE_INVALID signals;
otherwise, no exception is signaled.
Example. IEEE_SIGNALING_GT(1.0, IEEE_VALUE(IEEE_QUIET_NAN)) has the
value false and signals IEEE_INVALID."
17.11.40d IEEE_SIGNALING_LE (A, B)
Description. Signaling compares less than or equal.
Class. Elemental function.
Arguments.
A shall be of type real
B shall be of the same type and kind type parameter as A.
Restrictions. IEEE_SIGNALING_LE (A, B) shall not be invoked if
IEEE_SUPPORT_DATATYPE(A) has the value false.
Result Characteristics. Default logical.
Result Value. The result has the value specified for the
compareSignalingLessEqual operation in ISO/IEC/IEEE 60559:2011;
that is, it is true if and only if A compares less than or equal
to B. If A or B is a NaN, the result will be false and IEEE_INVALID
signals; otherwise, no exception is signaled.
Example. IEEE_SIGNALING_LE(1.0, IEEE_VALUE(IEEE_QUIET_NAN)) has the
value false and signals IEEE_INVALID."
17.11.40e IEEE_SIGNALING_LT (A, B)
Description. Signaling compares less than.
Class. Elemental function.
Arguments.
A shall be of type real
B shall be of the same type and kind type parameter as A.
Restrictions. IEEE_SIGNALING_LT (A, B) shall not be invoked if
IEEE_SUPPORT_DATATYPE(A) has the value false.
Result Characteristics. Default logical.
Result Value. The result has the value specified for the
compareSignalingLess operation in ISO/IEC/IEEE 60559:2011; that
is, it is true if and only if A compares less than B. If A or B
is a NaN, the result will be false and IEEE_INVALID signals;
otherwise, no exception is signaled.
Example. IEEE_SIGNALING_LT(1.0, IEEE_VALUE(IEEE_QUIET_NAN)) has the
value false and signals IEEE_INVALID.
17.11.40f IEEE_SIGNALING_NE (A, B)
Description. Signaling compares not equal.
Class. Elemental function.
Arguments.
A shall be of type real
B shall be of the same type and kind type parameter as A.
Restrictions. IEEE_SIGNALING_NE (A, B) shall not be invoked if
IEEE_SUPPORT_DATATYPE(A) has the value false.
Result Characteristics. Default logical.
Result Value. The result has the value specified for the
compareSignalingNotEqual operation in ISO/IEC/IEEE 60559:2011; that
is, it is true if and only if A compares not equal to B. If A or B
is a NaN, the result will be true and IEEE_INVALID signals;
otherwise, no exception is signaled.
Example. IEEE_SIGNALING_NE(1.0, IEEE_VALUE(IEEE_QUIET_NAN)) has the
value true and signals IEEE_INVALID."
[476:22, 17.11.55 "IEEE_UNORDERED" p6]
After "false." insert
"If X or Y is a signaling NaN, IEEE_INVALID may signal."