ISO/IEC JTC1/SC22/WG5 N1137 To: WG5 From: Keith H. Bierman Subject: Individual comment on floating point and related topics. As it stands, I have to vote no on f95. This is a personal position; during the J3 meeting these issues were discussed, and J3 did not agree (nor did the US Tag). So while the issue(s) are arguably moot, for whatever it is worth, here are my thoughts. Perhaps some other national body or WG5 itself will choose to accept some or all of the ideas herein. Misc. bits of background: J3 membership is decreasing, and the amount of time many members can dedicate to committee work is often more limited than in the past. This necessitates making hard choices about what we can actually complete work on. As far as I am concerned (and as best I can tell my user community) apart from legacy code and coders, the primary reason to choose Fortran over other languages is a focus on numerical computing. Of course, every numerical program has a lot of non-numeric parts; but if I had to pick a single "strategic" direction it would be numerical computing. So what does that mean? Numerical computing is typically focused on: Performance (speed of code execution) Robustness (do I get the right answer?, do I know I got it? do I get good answers with bad data?? etc.) Portability (can I get the same answers in different places, different systems, etc.). Code reuse (has anyone done this before?, AKA legacy code) It does not seem to me that we have focused on the numerical aspects of computing as much as we might have. At the Tokyo meeting it was decided to not hold up f95 for ENABLE. As I recall, we have often voted (both J3 and WG5) that "condition handling" is important. We have, from time to time, even told people to go off and work on exception handling and other facilities. We have not, however, yet voted such facilities into the language. WG5 did recognize the urgency of the need and has established a TR group, ably headed by John Reid. I support their work, and if it is ready, I would be happy to change my vote on f95 from no to yes. During J3 discussion of ENABLE during the Breckenridge meeting, there appeared to be a lot of old issues resurfacing, and there seemed to be some sentiment for doing something simple that canonized existing practice. I tested J3's feelings with a paper (95-209) which was defeated as a requirement for f95. It also failed to amass sufficient interest as an ongoing work item. I had stated that I would not waste any more time on it. As it has turned out, I lied ;> (though I did mean the claim when it was made). I would very much like ENABLE in f95. I could, however, vote for an F95 which contained the functionality mostly described in 95-209. I have made some minor improvements and embellishments to it, and the revised proposal follows. It should be noted that this facility does not replace ENABLE nor does it preclude ENABLE. There is at least one spot of "intersection" that would have to be dealt with on a processor which supported both approaches (and ought to be dealt with if the Standards community chooses to have even the potential for both being part of a standard, or companion TRs, etc.) The specific point is clearing the "FSR" within an ENABLE block. The functions which can cause this are intended to be labeled where they occur in this writeup. There seems to be no chance of this being a US position, the US has voted against this many times. However, if someone else would like to take it over, they should at least have something more than a clean slate to work from. Last background note. It is my understanding of the Tokyo resolutions that WG5 requested a writeup of both the ENABLE and intrinsic approaches. If that is correct, I submit this as a possible response to that resolution. X3J3 95-209 plus evolution: From the tenor of the discussion at the 8/22 plenary session, I gather that there is some potential support for a simple canonization of existing practice. What follows is more than an outline, but somewhat less than a full proposal. Precise edits to the Standard are not provided. It is intended that as much of the IEEE 754 standard's facilities will be exposed to Fortran users via this proposal. Nearly all vendors of systems with IEEE floating point (IEEE 7|854) support provide three types of "access" to IEEE functionality: 1) Functions which can be used to test a specific variable for IEEE special values (e.g. ISNAN(X) which is used to determine if the variable X has a bit pattern corresponding to the IEEE NaN definition. Sometimes there are also functions which allow a user to set a variable to such a value, such as X=NAN(X) (NAN being a generic which takes its kind from the kind of its argument). The former are much more common than the latter. 2) Functions which allow the user to set, clear or test the IEEE flags AKA sticky bits. That is, a user can manually clear the hw, do a series of calculations, and then determine if the calculations suffered any of the "IEEE exceptions": INEXACT, UNDERFLOW, OVERFLOW, INVALID OPERAND, DIVIDE BY ZERO. 3) The ability to cause an exception to raise a SIGNAL (defined by the OS) and transfer control automatically. The first two can easily be added into the Standard without risk to implementors, performance or portability. The third is very hairy to define without nailing down the OS. Since there is a lot of functionality in the first two, that is what is proposed. It is noted that the facility outlined is less safe (that is easily misused and hard to debug) than a well constructed ENABLE approach. However, this approach does not preclude the other from being added to the Standard at some later date. It is similar to having both GOTO and DO constructs. It may be argued that this is a fine subject for a separate standard, or another portion of the multi-part standard 1539. I do not think that this is looking at the "big picture". Ultimately it would be most appropriate to "bind" Fortran strongly to the IEEE standard, "+" in Fortran when applied to two real numbers of appropriate KIND (see below) the arithmetic addition ought to behave (ought to be required to behave) as defined in the IEEE standard. Similarly for all other arithmetic operations defined in the IEEE standard. Read and WRITE should be augmented to handle the special IEEE values (+-Inf, NaN, -0.) precise control over optimization for critical regisions of cod, etc. Relegating this functionality to a standard outside of the "core" standard is inconsistent with the view that Fortran's main focus is numeric computation or even that numeric computation is within Fortran's main focus. The next revision of the C standard is currently slated to have such functionality. In order to begin to manage the namespace, I propose that we make this a standard module. However, this could just be a series of intrinsics. There is no "need" to manage the namespace specific to this proposal. For the sake of argument, let us call this module "IEEE_arithmetic". Since this is being cast as a standard module, no special attempt is made to have "unusual" names for these intrinsics. Users may employ USE/RENAME/ONLY to prevent conflicts with existing code, if desired. It is certainly possible to define fewer new functions with more elaborate argument lists. Many existing implementations have done so. For example, one implementation has ieee_flags(3M) Mathematical Library ieee_flags(3M) NAME ieee_flags - mode and status function for IEEE standard arithmetic ... integer function ieee_flags(character*(*) action, character*(*)mode, character*(*) in, out) DESCRIPTION This function provides easy access to the modes and status required to fully exploit ANSI/IEEE Std 754-1985 arithmetic in a C program. All arguments are pointers to strings. Results arising from invalid arguments and invalid combina- tions are undefined for efficiency. There are four types of action: ``get'', ``set'', ``clear'', and ``clearall''. There are three valid settings for mode, two corresponding to modes of IEEE arithmetic: ``direction'', ... current rounding direction mode ``precision'', ... current rounding precision mode and one corresponding to status of IEEE arithmetic: ... etc. Fewer functions, but a fairly complex calling sequence, and runtime processing (possibly in key loops) to make choices based on character strings .... To facilitate maximum performance, each of the proposed functions does very little processing of arguments. In many cases a processor may generate only a few inline machine code instructions rather than library calls. In order to allow for the maximum number of processors to provide the maximum value to users, we do NOT require complete IEEE conformance. What a vendor must do is to provide the module, and support the some basic inquiry functions. A user must utilize the inquiry functions to determine if they can count on specific features of the IEEE standard, before using any of the other inquiry or value setting procedures. Note that a processor ought not implement these as "macros", as IEEE conformance is often controlled by compiler switches. A processor which offers a switch to turn off a facility should adjust the values returned for these inquiries . For example, a processor which allows gradual underflow to be turned off (replaced with flush to zero) should return .FALSE. for IEEE_support_underflow() when a source file is processed with that option on. Naturally it should return .TRUE. when that option is not in effect. Basic Inquiry procedures logical function IEEE_support_all() Description. Inquire if processor supports all the IEEE facilities defined in this Standard. Class. IEEE Basic Inquiry Argument. None Result Characteristics. LOGICAL Result Value true if the processor claims complete IEEE conformance, to be more precise, if the processor would have returned true for all of the other inquiries. logical function IEEE_support_NAN() Description. Inquire if processor supports the IEEE Not A Number facility. Class. IEEE Basic Inquiry Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports IEEE NaN's. logical function IEEE_support_INF() Description. Inquire if processor supports the IEEE infinity facility. Class. IEEE Basic Inquiry Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports IEEE infinities (positive and negative). logical function IEEE_support_underflow() Description. Inquire if processor supports the IEEE gradual underflow. Class. IEEE Basic Inquiry Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports IEEE gradual underflow. logical function IEEE_support_inexact() Description. Inquire if processor supports the IEEE inexact exception. Class. IEEE Basic Inquiry Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports detection of IEEE inexact computation. logical function IEEE_support_sqrt(x) Description. Inquire if a processor supports IEEE sqrt for this datatype. Class IEEE Basic Inquiry Argument. X real Result characteristics. logical Result Value. True if Square root of X as defined in the IEEE standard is supported for the kind of X. real function IEEE_sqrt(x) Description. square-root of X as defined in the IEEE standard. Class IEEE value Argument. X REAL Result characteristics. REAL, same KIND as X. Result value. The Square-root of X as defined in the IEEE Standard. Constraint: X must be of type IEEE kind. Constraint: It is prohibited to invoke IS_sqrt when IEEE_support_sqrt is false. Note: IEEE_sqrt(-0.) is -0. On most IEEE processors the "native" Fortran sqrt is probably the same as IEEE_sqrt. However, processors without adequate hardware support may choose to "punt" hard cases, in which case a careful programmer may wish to use IEEE_sqrt for safety. logical function IEEE_support_invalid() Description. Inquire if processor supports the detection of IEEE invalid exception. Class. IEEE Basic Inquiry (BI) Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports detection of IEEE invalid computation. Note: While general signal handling is hard, the specific behavior of auto detection followed by program abortion is easily handled, and very popular. Therefore a processor must support: logical function IEEE_halting() Description. Inquire if processor supports the ability to abort or continue operation after IEEE exceptions. Class. IEEE Basic Inquiry (BI) Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports the ability to abort or continue operation after IEEE exceptions. logical function IEEE_support_rounding(x) Description. Inquire if processor supports a particular IEEE rounding mode. Class. IEEE Basic Inquiry (BI) Argument. x is one of NEAREST, TOZERO, TOINFINITY which are named parameters defined in this module. Result Characteristics. LOGICAL Result Value returns true if the processor supports a particular IEEE rounding mode. logical function IEEE_support_FSR() Description. Inquire if processor supports getting and setting the "fsr". Class. IEEE Basic Inquiry Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports getting and setting a floating point status "register". This is a combinition of the supported flags, rounding mode status and other processor dependent floating point context. A standard conforming program shall make no attempt to examine the bit pattern of the "FSR" nor to set it. A processor must also report on the IEEE datatypes supported logical function IEEE_datatype (x) Description. Inquire if this kind is an IEEE kind on this processor. Class. IEEE Basic Inquiry (BI) Argument. x REAL Result Characteristics. LOGICAL Result Value returns true if kind(x) is implemented as an IEEE data type. Note: An IEEE processor is required to support single precision, and an extended precision. This is usually REAL and DOUBLE PRECISION but it might not always be. In addition, some vendors support a "REAL*16" which does not follow the "logical extension" to the IEEE 754 standard (e.g. IBM's RS6K "doubled double" implementation of REAL*16). Users should be able to determine if a particular datatype is going to behave as "one would expect". But implementors should not be constrained to supply only datatypes which conform to IEEE 754 (for performance, or compatibility with older processors or eventual improvements in state of the art in floating point implementation). If a processor supports a particular IEEE exception, it must support the related support functions. If it does not support a particular IEEE exception, a program which uses any of the related functions is non-standard conformant. Assuming that a user has specified USE IEEE_arithmetic and not renamed the functions, and that x is an IEEE kind on that processor, we have following IEEE inquiry functions logical function IS_NAN(x) Description. Inquire if value is IEEE Not a Number. Class. IEEE Inquiry Argument. x REAL Result Characteristics. LOGICAL Result Value returns true if the value of X is an IEEE NaN. Constraint: X must be of type IEEE kind. Constraint: It is prohibited to invoke IS_NAN when IEEE_support_NAN is false. logical function IS_INF(x) Description. Inquire if value is IEEE Infinity. Class. IEEE Inquiry Argument. x REAL Result Characteristics. LOGICAL Result Value returns true if the value of X is IEEE Infinity (either positive or negative). Constraint: X must be of type IEEE kind. Constraint: It is prohibited to invoke IS_INF when IEEE_support_INF is false. Note: the sign of X can be determined directly via comparison (e.g. (X .GT. 0) is true for +Inf) or indirectly via SIGN or COPYSIGN. logical function IS_VALID(x) Description. Inquire if value is neither +Inf, -Inf or NaN. Class. IEEE Inquiry Argument. x REAL Result Characteristics. LOGICAL Result Value returns true if the value of X is a normal value. Constraint: X must be of type IEEE kind. Constriant: It is prohibited to invoke IS_VALID when IEEE_support_invalid is false. Comment: While one could code this via a combination of the primitives, it is often significantly more efficient to just test it once. It also makes for more readable code. logical function IS_SUBNORMAL(x) Description. Inquire if value is IEEE subnormal. Class. IEEE Inquiry Argument. x REAL Result Characteristics. LOGICAL Result Value returns true if the value of X is IEEE subnormal. This is only valid when gradual underflow is supported. Constraint: X must be of type IEEE kind. Constraint: It is prohibited to invoke IS_SUBNORMAL when IEEE_support_underflow is false. function COPYSIGN(x,y) Description. IEEE copysign Class. IEEE Value Argument. X,Y REAL Result Characteristics. LOGICAL Result Value returns X with the sign of Y. This is true even for IEEE special values, such as Nan and Inf (on processors supporting such values). Note: abs(x) = copysign(x,1.0) even when X is NaN. -x is x copied with its sign reversed, not 0-x; the distinction is germane when x is +-0 or NaN. real function IEEE_nextafter(x,y) Description. Returns the next representable neighbor of X in the direction of Y. Class IEEE Value Argument. X,Y REAL Result Characteristics. REAL Result Value. Aside from the obvious, some special cases exist. If x .eq. y, then the reuslt is X without any exception being signaled; otherwise if either X or Y is a quiet NaN, then the result is one or the other of the input NaNs. Overflow is signaled when X is finite but nextafter(x,y) is infinite; underflow is signaled when nextafter(x,y) is lies strictly between +-2**min. In both cases, inexact is signaled. real function LOGB(x) Description. When passed an argument of the form +-b*d.dddd where b is the machine radix and the ds are radix-b digits, returns the integer value of the exponent e in the floating point format of the argument. Class. IEEE Value Argument. x REAL Result Characteristics.REAL of the same kind as X. Result Value When X is +- 0, the result is -HUGE(x) When X is +- Inf, the result is +Inf When X is NaN, the result is X Constraint: X must be of type IEEE kind. Note: Processors which lack Inf and NaN don't have the possibility of being "handed" an exceptional value. real function SCALB(x,ifactor) Description. X*b**factor Class. IEEE value Argument X real ifactor integer b in the expression above is the base of the processor. When IEEE Inf is supported overflows result in +Inf. When IEEE Inf is not support +HUGE is returned. real function INF(x) Description. Generate IEEE infinity. Class. IEEE Value Argument. x REAL Result Characteristics.REAL of the same kind as X. Result Value IEEE + or - Inf based on the SIGN of x. Constraint: X must be of type IEEE kind. Constraint: It is prohibited to invoke INF when IEEE_support INF is false. real function NAN(x) Description. generate IEEE Not a Number. Class. IEEE Value Argument. x REAL Result Characteristics. REAL same kind as X Result Value returns IEEE signaling NAN. Constraint: X must be of type IEEE kind. Constraint: It is prohibited to invoke NAN when IEEE_support_NAN is false. Note: IEEE defines an entire family of values as NAN. A processor may choose to allow users to specify the bit pattern. If so, the value of X is appropriately transformed to be a signaling NaN with all the low order bits taken from the value of X. Comment: one can argue that NAN and INF are not needed, because users can code expressions to generate them. However, experience shows that optimizers often make it difficult to do this easily and portably. It is better to have these functions in the Standard to promote portability, without impacting optimization. subroutine IEEE_flag_set(flag, value) Description. Set an IEEE flag (AKA exception AKA sticky bit) Class. IEEE Value Argument. flag IEEE_flag type, which can have one of the values INVALID, UNDERFLOW, OVERFLOW, INEXACT, DIVZERO which are named PARAMETERS defined in the IEEE module. value LOGICAL Result Characteristics. None (the IEEE "status" register is modified). Result Value None that is directly accessible to the user. Constraint: It is prohibited to attempt to set any flag not supported on the processor. subroutine IEEE_flags_clear() Description. Set all the IEEE flags (AKA exception AKA sticky bit) Class. IEEE Value Argument. None Result Characteristics. None (the IEEE "status" register is modified). Result Value None that is directly accessible to the user. Constraint: It is prohibited to attempt to clear any flag not supported on the processor. Comment: this is precisely the same as calling IEEE_flag_set five times (with each of the flags, and the value .FALSE.). However on many systems, setting the "floating point status register" is an expensive operation. Providing a single function to clear the flags is a major optimization, and provides an easier abstraction for programmers. The act of clearing all the flags is common, the act of setting them all is rare, so there is no companion function to optimize the setting of flags. Note: IEEE_flag_set and IEEE_flags_clear potentially interact painfully with ENABLE. If a user has established an ENABLE block, and then (dynamically, perhaps far down the call chain) clears the IEEE flag(s) nominally handled by the ENABLE block, the ENABLE check will not necessarily catch all the exceptions the programmer intended. This circumvents the safety that ENABLE was intended to provide. logical function IEEE_flag_get(flag) Description. Get an IEEE flag (AKA exception AKA sticky bit) Class. IEEE Value Argument. flag IEEE_flag type, which can have one of the values INVALID, UNDERFLOW, OVERFLOW, INEXACT, DIVZERO or COMMON which are named PARAMETERS defined in the IEEE module. Result Characteristics. LOGICAL Result Value .TRUE. when the flag is set, .FALSE otherwise. Constraint: It is prohibited to attempt to get any flag not supported on the processor. IEEE_FSR_VALUE function IEEE_get_fsr() Description. Save the current value of all the IEEE hardware (flags, rounding mode, etc) Class. IEEE Value Argument. None. Result Characteristics IEEE_fsr which is module private. Result Value returns an implementation defined "cookie" which can only legally be used in an IEEE_set_fsr. The type is a private derived type called IEEE_FSR_VALUE Constraint: It is prohibited to attempt to get the FSR when IEEE_support_FSR is false. subroutine IEEE_set_fsr(x) Description. Restore the value of all the IEEE hardware (flags, rounding mode, etc) to x Class. IEEE Value Argument. x IEEE_FSR_VALUE. Constraint: It is prohibited to attempt to get the FSR when IEEE_support_FSR is false. takes an IEEE_FSR_VALUE stored in X from a previous get_fsr call and stuff it into appropriate hardware/system area(s). This is necessary for careful, friendly library code. Such code, on entry will do something like x=IEEE_get_fsr() do their own calculations, possibly changing rounding modes, etc. call IEEE_set_fsr(x) return Note: getting and setting may be expensive operations. It is the programmers responsibility to do it when necessary to assure correct results. Note: IEEE_set_fsr potentially interacts painfully with ENABLE. If a user has established an ENABLE block, and then (dynamically, perhaps far down the call chain) effectively clears the IEEE flag(s) nominally handled by the ENABLE block, the ENABLE check will not necessarily catch all the exceptions the programmer intended. This circumvents the safety that ENABLE is intended to provide. This effective clearing could be performed by storing the fsr before any exceptions have occurred, establishing an ENABLE block, calling some unsafe routine(s) which set the fsr to it's "original" value, and then returning to the ENABLE block. IEEE_RND_VALUE function IEEE_get_rounding_mode() Description. Save the current IEEE rounding mode. Class. IEEE Value Argument. None. Result Characteristics IEEE_RND_VALUE which is module private. Result Value returns an implementation defined "cookie" which can only legally be used in an IEEE_set_rounding_mode call. Constraint: It is prohibited to invoke IEEE_get_rounding_mode when IEEE_support_rounding is false. subroutine IEEE_set_rounding_mode(x) Description. Set the current IEEE rounding mode to X. Class. IEEE Value Argument. X type IEEE_RND_VALUE Constraint: It is prohibited to invoke IEEE_set_rounding_mode when IEEE_support_rounding is false. In a procedure which needs to toggle the rounding mode (such as an implementation of interval arithmetic) the rounding mode in effect on entry should be stored, the rounding mode set as required, computations performed and the rounding mode reset to what was in effect on entry. It is the programmers responsibility to do this as needed, the processor will not change the rounding mode automatically. subroutine IEEE_halt(flag,x) Description. Toggles continuation or halting on error. Class. IEEE Argument. flag type IEEE_flags which can have the values: INEXACT, UNDERFLOW, OVERFLOW, INVALID, DIVZERO and COMMON. X LOGICAL Constraint: it is prohibited to invoke IEEE_halt when IEEE_support_halting is false. Although the IEEE specified default is to continue on errors, this is inconsistent with much existing Fortran practice. So the Fortran default is to halt on error. INEXACT and UNDERFLOW are hardly ever errors. So the default is to continue execution on normal computations, computations which underflow and/or are INEXACT, to halt on DIVZERO, OVERFLOW or INVALID computations. When X is .FALSE. execution will continue when the specified exceptional conditions occur. When X is .TRUE. execution shall halt when the specified exceptional conditions occur. Such halting is not "precise" it occurs sometime after the particular computation has failed. An error message and retrospective are produced and computation ceases as if a STOP statement had been executed. The state of the IEEE flags shall be detailed. Note: the processor may provide other information (such as the approximate line number of the error, the name of the procedure being executed etc.). Things to worry about: As noted above, interactions with ENABLE. I believe that declaring such errors as programmer errors is acceptable, but is admittedly unfortunate. Triggering a halt, in a PURE procedure executing in parallel may be complicated. Again, I believe that doing so is a programmer error, and is prohibited is sufficient. Sensible systems will have (or will emulate having) separate hardware for different "threads" of execution. Can and should Fortran say anything in this area? If not, what does happen? I am inclined to view this facility as visibility into hw/OS local idiosyncrasies, and would prefer not to mandate what happens in the parallel cases. Admittedly this will hamper portability, but it seems premature to constrain systems in this area. Additional functionality: If a program generates IEEE special values, and attempts to print them, we have a bit of a problem. this can be solved by nailing down the "spelling" of the special values on output. It would simplify things to not allow them on input, but that complicates the life of users because they would no longer be able to rely upon reading a formatted file that had been written by a conforming program on a conforming processor. So it is worth adding logical function IEEE_support_IO() Description. Inquire if processor supports IEEE I/O. Class. IEEE Basic Inquiry Argument. None Result Characteristics. LOGICAL Result Value returns true if the processor supports printing and reading of IEEE special values. On such a processor, we'd have to modestly augment the description of the numeric format descriptors. On output, IEEE value result printed +Inf +Inf -Inf -Inf NaN NaN -0. -0. On input, the values will be allowed in numeric contexts on IEEE processors. On non- IEEE processors they shall result in a processor defined error condition. Careful programmers can use the IEEE_support_IO() function to trigger application specific logic to "vet" input before processing, if desired. Commentary: With such functionality, it is possible to write fast and robust code. It is also possible to write slow and/or possibly unsafe code. We are placing a significant burden on users (as opposed to the ENABLE proposal); however this provides much needed functionality in a way that is clearly implementable (since nearly all vendors already have a substantial fraction of it, albeit with a wide variety of "spellings" in their implementations). It would also be helpful to have other things (such as the C folks have in their J11.1 AKA NCEG material and more). Unordered comparisons, and optimization/constant folding control on a few lines at a time source code level, binding of Fortran arithmetic to IEEE arithmetic, well defined base conversion quality requirements (which is required if one wishes to get consistent results across platforms, moving computation across a network between different processors, etc.), mandatory maximum error bounds for intrinsics, appropriate handling of IEEE special values in I/O, etc. However, those are sufficiently more complex than can be dealt with this late in the game. This facility covers some functionality that is not currently planned for ENABLE, such as setting the IEEE rounding mode. It also provides the programmer with better control over potentially expensive (in terms of runtime) operations (at the cost of safety and programmer complexity). ;;;; note from a local lecture posting: Professor W. Kahan: ------------------ "The Baleful Effect of Computer Benchmarks upon Applied Mathematics, Physics and Chemistry" An unhealthy preoccupation with Speed, as if it were synonymous with Throughput, has distracted the computing industry and its marketplace from other important qualities that computer hardware and software should possess -- - Correctness, Accuracy, Dependability, Ease of Use, Flexibility, ... Worse, technical and political limitations peculiar to current benchmarking practices discourage innovations and accomodations of features necessary, as well as desirable, for robust and reliable technical computation. Particularly exasperating are computer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ languages that lack locutions to access advantageous features in ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ hardware that we have paid for but consequently cannot use. That lack prevents benchmarks from demonstrating the features' advantages, thus affording language implementors scant incentive to accommodate those features in their compilers. It is a vicious circle that the scientific and engineering community must help the computing industry break. ;;;;; an early version of this was sent to John Reid. He quickly replied with a proposed implementation. I haven't studied it carefully, and I'm sure he'd have polished it more before sending it onward. But the more eyes view such things, the more likely we are to get 'em right. I am, as always, indebited to John for his insights and hard work. It is, of course, up to John to weigh on either for or against the proposal .... that he was kind enough to make a sample implementation isn't proof that he supports it! ;> .... Here is how your module looks, for default real only, and with no guarantee of correctness. I will come up with comments soon. Best wishes, John. ................................................ module IEEE_arithmetic type IEEE_flag private integer i end type IEEE_flag type IEEE_FSR_VALUE private integer i(10) end type IEEE_FSR_VALUE type (IEEE_flag), parameter :: INVALID = IEEE_flag(1) type (IEEE_flag), parameter :: UNDERFLOW = IEEE_flag(2) type (IEEE_flag), parameter :: OVERFLOW = IEEE_flag(3) type (IEEE_flag), parameter :: INEXACT = IEEE_flag(4) type (IEEE_flag), parameter :: DIVZERO = IEEE_flag(5) type (IEEE_flag), parameter :: COMMON = IEEE_flag(6) type IEEE_RND_VALUE private integer i end type IEEE_RND_VALUE type (IEEE_RND_VALUE), parameter :: NEAREST = IEEE_RND_VALUE(1) type (IEEE_RND_VALUE), parameter :: TOZERO = IEEE_RND_VALUE(2) type (IEEE_RND_VALUE), parameter :: TOINFINITY = IEEE_RND_VALUE(3) end module IEEE_arithmetic module IEEE_support interface logical function IEEE_support_all() ! Inquire if processor supports all the IEEE facilities ! defined in this Standard. end function IEEE_support_all logical function IEEE_support_NAN() ! Inquire if processor supports the IEEE Not A Number facility. end function IEEE_support_NAN logical function IEEE_support_INF() ! Inquire if processor supports the IEEE infinity facility. end function IEEE_support_INF logical function IEEE_support_underflow() ! Inquire if processor supports the IEEE gradual underflow. end function IEEE_support_underflow logical function IEEE_support_inexact() ! Inquire if processor supports the IEEE inexact exception. end function IEEE_support_inexact logical function IEEE_support_sqrt(x) ! Inquire if processor supports the IEEE sqrt for this datatype. real, intent(in) :: x end function IEEE_support_sqrt real function IEEE_sqrt(x) ! Square-root of X as defined in the IEEE standard. real, intent(in) :: x end function IEEE_sqrt logical function IEEE_support_invalid() ! Inquire if processor supports the IEEE invalid exception. end function IEEE_support_invalid logical function IEEE_halting() ! Inquire if processor supports the ability to abort or ! continue operation after IEEE exceptions. end function IEEE_halting logical function IEEE_support_rounding(x) ! Inquire if processor supports a particular IEEE rounding. use IEEE_arithmetic type(IEEE_RND_VALUE), intent(in) :: x end function IEEE_support_rounding logical function IEEE_support_FSR() ! Inquire if processor supports getting and setting the "fsr". end function IEEE_support_FSR logical function IEEE_datatype(x) ! Inquire if this kind is an IEEE kind on this processor real, intent(in) :: x end function IEEE_datatype logical function IS_NAN(x) ! Test if value is IEEE Not a Number real, intent(in) :: x end function IS_NAN logical function IS_INF(x) ! Test if value is IEEE Infinity real, intent(in) :: x end function IS_INF logical function IS_SUBNORMAL(x) ! Test if value is IEEE subnormal real, intent(in) :: x end function IS_SUBNORMAL real function COPYSIGN(x,y) ! Returns X with the sign of Y. real, intent(in) :: x,y end function COPYSIGN real function IEEE_nextafter(x,y) ! Returns the next representable neighbor of X in the direction of Y real, intent(in) :: x,y end function IEEE_nextafter logical function LOGB(x) ! Returns the integer value of the exponent e in the ! IEEE floating point format of the argument real, intent(in) :: x end function LOGB real function SCALB(x,ifactor) ! X*b**factor real, intent(in) :: x integer, intent(in) :: ifactor end function SCALB real function INF(x) ! Generate IEEE infinity real, intent(in) :: x end function INF subroutine IEEE_flag_set(flag, value) ! Set an IEEE flag use IEEE_arithmetic type(IEEE_flag), intent(out) :: flag logical, intent(in) :: value end subroutine IEEE_flag_set subroutine IEEE_flags_clear() ! Clear all the IEEE flags end subroutine IEEE_flags_clear logical function IEEE_flag_get(flag) ! Get an IEEE flag use IEEE_arithmetic type(IEEE_flag), intent(in) :: flag end function IEEE_flag_get TYPE(IEEE_FSR_VALUE) function IEEE_get_fsr() ! returns an implementation defined value that can ! only legally be used in an IEEE_set_fsr call use IEEE_arithmetic end function IEEE_get_fsr subroutine IEEE_set_fsr(x) ! Restore the value of all the IEEE hardware (flags, ! rounding mode, etc) to x use IEEE_arithmetic TYPE(IEEE_FSR_VALUE), intent(in) :: x end subroutine IEEE_set_fsr TYPE(IEEE_RND_VALUE) function IEEE_get_rounding_mode() ! returns an implementation defined value that can ! only legally be used in an IEEE_set_rounding_mode call use IEEE_arithmetic end function IEEE_get_rounding_mode subroutine IEEE_set_rounding_mode(x) ! Set the current IEEE rounding mode to X use IEEE_arithmetic TYPE(IEEE_RND_VALUE), intent(in) :: x end subroutine IEEE_set_rounding_mode subroutine IEEE_halt(flag,x) ! Toggles continuation or halting on error use IEEE_arithmetic type(IEEE_flag), intent(in) :: flag logical, intent(in) :: x end subroutine IEEE_halt end interface end module IEEE_support