From Keith.Bierman@Eng.Sun.COM  Thu Sep  7 23:28:26 1995
Received: from mercury.Sun.COM (mercury.Sun.COM [192.9.25.1]) by dkuug.dk (8.6.12/8.6.12) with ESMTP id XAA23369 for <sc22wg5@dkuug.dk>; Thu, 7 Sep 1995 23:27:22 +0200
Received: from Eng.Sun.COM by mercury.Sun.COM (Sun.COM)
	id OAA05092; Thu, 7 Sep 1995 14:26:41 -0700
Received: from chiba.eng.sun.com by Eng.Sun.COM (5.x/SMI-5.3)
	id AA01207; Thu, 7 Sep 1995 14:26:34 -0700
Received: by chiba.eng.sun.com (4.1/SMI-4.1)
	id AA03639; Thu, 7 Sep 95 14:26:29 PDT
Date: Thu, 7 Sep 95 14:26:29 PDT
From: Keith.Bierman@Eng.Sun.COM (Keith Bierman-khb@chiba.eng.sun.com::SunPro)
Message-Id: <9509072126.AA03639@chiba.eng.sun.com>
To: sc22wg5 <sc22wg5@dkuug.dk>
Subject: paper for the wg5 nov premeeting


Please include this paper in the premeeting. Thanks in advance.

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

