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."