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 nonnumeric 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 (95209) 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 95209. 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 95209 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 7854) 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 multipart 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 7541985 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. squareroot of X as defined in the IEEE standard.
Class IEEE value
Argument. X REAL
Result characteristics. REAL, same KIND as X.
Result value. The Squareroot 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 nonstandard 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 0x; 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 radixb 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)
! Squareroot 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