From jwagener@amoco.com Fri Mar 10 02:50:41 1995
Received: from interlock.amoco.com by dkuug.dk with SMTP id AA27895
  (5.65c8/IDA-1.4.4j for <sc22wg5@dkuug.dk>); Fri, 10 Mar 1995 16:04:45 +0100
Received: by interlock.amoco.com id AA07036
  (InterLock SMTP Gateway 3.0 for sc22wg5@dkuug.dk);
  Fri, 10 Mar 1995 09:04:36 -0600
Message-Id: <199503101504.AA07036@interlock.amoco.com>
Received: by interlock.amoco.com (Protected-side Proxy Mail Agent-3);
  Fri, 10 Mar 1995 09:04:36 -0600
Received: by interlock.amoco.com (Protected-side Proxy Mail Agent-2);
  Fri, 10 Mar 1995 09:04:36 -0600
Received: by interlock.amoco.com (Protected-side Proxy Mail Agent-1);
  Fri, 10 Mar 1995 09:04:36 -0600
From: jwagener@amoco.com
X-Openmail-Hops: 1
Date: Fri, 10 Mar 95 08:50:41 -0600
Subject: Strategic Miscue ?
To: sc22wg5@dkuug.dk
X-Charset: ASCII
X-Char-Esc: 29

Item Subject: Message text
That is the new title of my ENABLE subset paper (attached), that has
been sent into the WG5 and X3J3 premeeting distributions.  (I would have
sent it out on the net last week, but got leveled by the flu before
making it.)

No doubt some will hold that that title most rightfully applies to my
sensibilities in persisting on presenting this topic.  (But see page one
of the paper for my reason for that title.)  It is a survivability
issue.  I don't disagree with the recent sentiments about the importance
of interoperability; indeed, a couple of weeks ago I distributed a
short, specific paper on this topic (which has also been sent into the
distributions).  (If you change the word "longreal" in that paper to
"unsigned int" I think it says exactly what Linda was getting at in her
recent note.  Though I would expect probably she will use a different
syntax, it will be interesting to see how her specific proposal differs
from X3J3/95-099 - sure sounds functionally identical to me so far.)  So
you see, I agree that interoperability is critical.

But not as critical as handling floating point exceptions.  Now I know
that that statement will raise a lot of hackles and be controversial. 
But it is correct in the application area in which I work - seismic and
reservoir models that are numerically computationally intensive.  This
is an area in which Fortran remains, for the moment, still king; 
Fortran dare lot lose ground in areas in which it is still king.  There
is need at Amoco for interoperability with C, but in the scientific area
the need is much greater for robust, high performance on numerical
computation.

Probably there's no "right" answer as to the most critical need, because
of the different application perspectives from which we all view the
problem.  For example, a persepctive surfacing at the last HPFF meeting
was the importance of C being able to call (numerical routines in)
Fortran.  How important is that compared with the reverse (Fortran
calling C)?  Maybe more than we have discussed so far, especially if
Fortran contiinues to be the leading language for numerical computation.

Anyway, the attached paper is in the spirit that handling floating point
exceptions is (one of the thing's that is most) critical to Fortran's
survivability, and that something should be done about it before F2K.

Jerry

(Sorry about the ascii-ization of the attached - it'll look better in
the distributions.)   -jlw

.......................................................................

Item Subject: ENABLE-7.TXT
To:      WG5 and X3J3                             X3J3/95-098 
From:    Jerry Wagener                            Page 1 of 10
Subject: Floating Point Subset of ENABLE

Introduction: Strategic Miscue?

That, I believe, could well be the consequence of the WG5 management committee
action in late 1994 in 
removing two Fortran 95 requirements firmly established at the 1994 WG5
meeting: exception handling 
and allocatable components.  Both of these requirements contribute to Fortran s
high performance 
capabilities.  In particular the exception handling requirement included -
indeed was motivated by - 
support for floating point exceptions; the absence of any support for handling
numeric exceptions in 
Fortran 95 will, I believe, compromise Fortran's leadership in high performance
numerical computation.

When the requirements for Fortran 95 were being assembled, input was supplied
by IFIP WG2.5, 
representing the numerical community.  They had exactly one request - standard
support for handling 
numeric exceptions. WG5 responded to this need by making exception handling a
Fortran 95 
requirement.  With the recent management committee action, however, the baby
(simple handling of 
floating point exceptions) was thrown out with the bath water.  Support for
floating point exceptions 
need not be extensive nor expensive, and we would be ill-advised to ignore this
need of Fortran s 
numerical constituency.  

Historically, Fortran has been practically synonymous with numerical
computation.  It is clearly Fortran's 
most important application domain.  While extending Fortran's role in other
application domains is 
important (e.g., interoperability with C, windows, etc.), maintaining its lead
in numerical computation is 
critical to Fortran s survival.  For example, one speaker at the Jan'95 HPFF
meeting mentioned writing 
applications in C++, with calls to Fortran for the numerical parts. 
Maintaining that numerical lead (e.g., 
in the mathematical library arena) means providing robustness, portability, and
high performance.  It is 
becoming increasingly clear that often the highest performance algorithms for a
given numerical 
computation are more susceptible to floating point exceptions (e.g., overflow,
underflow) than lower 
performance algorithms for that computation.  Thus (many) robust high
performance computations 
require handling these exceptions, and without floating point exception
handling in the standard, many 
high performance algorithms cannot be (portably) expressed in Fortran.

But with the advent of the Floating Point C Extensions (FPCE) these algorithms
can now be expressed in 
C and C++. This is not the time to be timid about floating point exception
handling.  Putting floating 
point exception handling off to Fortran 2000 (and perhaps 2004 for
implementations) would give C/C++ 
an unfettered decade to erode Fortran's leadership in the numerical arena.

A simple  80% solution  for floating point exception handling can be
implemented, I believe, within the 
established Fortran 95 schedule.  As an example, attached (and see
X3J3/95-026r1) is a subset of the 
original ENABLE proposal that deals only with floating point exceptions.  It is
extremely simple and is 
consistent with: (a) the earlier ENABLE proposal, (b) alternative suggestions
of a condition data type 
approach, and (c) recent numeric exception handling needs published (and to be
published) in the 
Transactions on Mathematical Software (see attached rationale); it suffers from
none of the problems 
described in papers X3J3/94-318 and X3J3/94-321; it should be inexpensive to
implement, especially on 
systems that provide hardware support for floating point exceptions.  

With some sort of solution such as this we can win the schedule battle as well
as increase immensely the 
odds of winning the survivability war.

Rationale for Floating Point Exception Handling
(with appreciation to Tom Hull)

There are many circumstances in computing which give rise to exceptional
situations that need to be handled. These 
range from cache misses (normally handled by the hardware) through I/O
interrupts (normally handled with a 
language feature, such as the IOSTAT= specifier) to floating-point exceptions.
A minimal ENABLE construct is 
included in Fortran 95 to facilitate the handling of floating point exceptions.

The most important use of a floating point exception handling facility is to
make possible the development of much 
more efficient software than is otherwise possible. The following "hypotenuse"
function, sqrt(x**2 + y**2), 
illustrates the use of a simple ENABLE ... HANDLE ... END ENABLE construct in
developing efficient software.

REAL FUNCTION HYPOT(X, Y)
REAL X, Y
REAL SCALED_X, SCALED_Y, SCALED_RESULT
INTRINSIC SQRT, ABS, EXPONENT, MAX, SCALE
ENABLE		! try a fast algorithm first
	HYPOT = SQRT( X**2 + Y**2 )
HANDLE		! if fast algorithm fails with an exception, try a slower safer one
	IF ( X=0.0 .OR. Y=0.0 ) THEN
		HYPOT = ABS(X) + ABS(Y)
	ELSE IF ( ( 2*ABS(EXPONENT(X) - EXPONENT(Y) ) > (DIGTS(X) + 1 ) ) THEN
		HYPOT = MAX( ABS(X), ABS(Y) )	!  one of X and Y can be ignored
	ELSE   			! scale so that ABS(X) is near 1
		SCALED_X = SCALE( X, -EXPONENT(X) )
		SCALED_Y = SCALE( Y, -EXPONENT(X) )
		SCALED_RESULT = SQRT( SCALED_X**2 + SCALED_Y**2 )
		ENABLE	! possibility of overflow in unscaling result
			HYPOT = SCALE( SCALED_RESULT, EXPONENT(X) )
		END ENABLE	! if overflow does occur here, it s propagated back to caller
	END IF
END ENABLE
END FUNCTION HYPOT

An attempt is made in the outer ENABLE block to evaluate this function directly
in the fastest possible way.   (Note 
that with hardware support, exception checking is very efficient; without the
enable construct reliable code would 
require programming checks that slow the computation significantly - see
below.)  The fast algorithm will work 
almost every time, but if an exception occur during this fast computation, the
handler takes over and in a safe but 
slower way evaluates the function. This slower evaluation may involve scaling
and unscaling, and in (very rare) 
extreme cases this unscaling can cause.  If underflow is handled as well as
overflow, the error bounds of slow 
computation are as good as in the fast computation.

A robust algorithm could always use just the code in the handle block, but then
it cannot be maximally efficient. 
Another possibility, in some cases, is code structured such as the following:

	if ( in the first exceptional region ) then
		handle this case
	else if ( in the second exceptional region ) then
		handle this case
	  :
	else
		do what you would have done in the ENABLE block
	end

But this is not only inefficient, it also "inverts" the logic of the
computation.  Other examples:TOMS 20, 2 (June 94) 
215-244 and "Faster Numerical Algorithms with Exception Handling" (Demmel, 1993
Symp. on Comp. Arith.). 

The HYPOT algorithm is used in example 2 of section 8.1.5.4.  The ENABLE
construct of the HYPOT function can 
be generalized in an obvious way to compute the Euclidean Norm, sqrt( x(1)**2 +
x(2)**2 + ... + x(n)**2 ), of an 
n-vector; the generalization of the HANDLE block is not so obvious (though
straightforward) and will be much 
slower relative to the ENABLE block than is the case with the HYPOT function.  
 
Generally speaking, a "floating-point" exception occurs if the result of a
floating-point arithmetic operation cannot 
be represented to good accuracy. For example, in IEEE single precision, "good
accuracy" roughly implies that the  
relative accuracy in the result is <= 2**(-24). There are a number of different
kinds of floating point exceptions: 
overflow, underflow, divide by zero (two flavors - numerator zero and nonzero),
inexact, etc. A complete floating 
point exception handling facility would encompass all of these and be able to
include/exclude any subset of them in 
a given context.  Exception handling in Fortran 95 is restricted to a very
simple ENABLE construct which handles 
floating point exceptions without distinction as to which specific exception is
checked or occurred; it has the form:

			ENABLE	
              				enable block	
         			[ HANDLE	
              				handle block ]	
         			END ENABLE	
 
and is carefully designed so as to be extendible to a more complete facility,
of either a global condition nature or a 
scoped condition (condion data type) nature.  Since in the vast majority of
cases the programmer knows which 
exception is likely to occur in a given situation, the  80% solution  does not
require explicitly identifying specific 
exceptions.  Exception checking is required only at HANDLE, END ENABLE and
nested ENABLE statements.

Unfortunately, some exceptions are not as important (to the 80% solution) to
handle as others, and some exceptions 
are expensive to check on architectures that do not provide full hardware
support for floating point exceptions.  
Therefore the Fortran 95 enable construct requires checking only for overflow
(absolute value of result > HUGE) 
and divide by zero; an implementation may include others (in particular,
underflow).  The IEEE INEXACT 
exception is not included in this ENABLE facility because INEXACT is almost
always signaling  and a more 
selective ENABLE construct is necessary to make the handling of INEXACT useful.

 
Handling underflow can be important for controling error bounds in floating
point computations. Underflow occurs 
when the absolute value of the computational result is larger than 0.0 and
smaller than TINY.  (Underflow is not 
always interpreted in exactly this way. For example, a result may be < TINY but
not signal underflow if stored in 
denormalized IEEE form. This distinction does not make any difference to the
final result in the case of HYPOT 
and probably not in most, if any, relevant situations. In any event, programs
can be written in such a way that the 
distinction does not matter.)  If underflow is flushed to zero without
signaling an exception, the program may still 
work, but the error bounds are likely to be a long way off - this is the case
with HYPOT, but if underflow is handled 
then HYPOT works perfectly in terms of uniform error bounds for both the fast
and slow algorithms.  Thus in some 
cases the most robust, reliable numerical algorithms must detect and handle
underflow.  Unfortunately, underflow is 
expensive to detect on some (important to Fortran) architectures that do not
provide hardware support for it, and 
therefore underflow was reluctantly omitted from the list of exceptions that
must be detected in a Fortran 95 enable 
construct.  The importance of error bound control suggests that a high priority
for Fortran 2000 should be extending 
the Fortran 95 ENABLE so that underflow handing can be accommodated in an
acceptable manner.  In the 
meantime, implementations should be encouraged to include underflow detection
within an enable construct, if it is 
reasonably efficient to do so.  Other implementations may, in effect, flush
underflow values to zero (or TINY), with 
acceptable results in most cases.

Finally, a floating point exception that is not handled in the procedure in
which it occurs should be propagated back 
to the calling procedure for handling. If a function fails with overflow
signaling, for example, it may mean that the 
correct function value is too large to be represented to reasonable accuracy.
But it may be the case that the overflow 
occurred at an intermediate stage in the calculation (in the caller) of a
result that can be represented to high 
accuracy; in other words, the exception may be "spurious" and can be handled in
the caller even if it cannot be 
handled in the callee. The simple ENABLE construct in Fortran 95 supports this
capability, without significant 
implementation cost.
EDITS TO X3J3/94-007r3
(with appreciation to John Reid)


Section 1.8 - at end of section, add new reference:  
     	IEC 559:1989, Binary floating-point arithmetic for microprocessor systems

	(also ANSI/IEEE 754-1985, IEEE standard for binary floating-point arithmetic).
.......................................................................
Section 2.1 - add to R215 (in alphabetical order) the line:  
  	or    enable-construct
.......................................................................
Section 2.1 - add to R216 (in alphabetic position) the line:
         	or    signal-stmt
.......................................................................
Section 2.3.4 - in list item(2), after 'CASE constructs,', add 'ENABLE
constructs,'
.......................................................................
Section 2.3.4 - add a fourth list item:
  	(4) Execution of a signal statement (8.1.5.4) may change the execution
sequence. 
.......................................................................
Section 2.5 - insert a new section just before 2.5:


2.4.8 Condition

Within an enable construct, a condition is signaled by the processor if a
floating point exception, such as overflow, 
occurs during program execution.  How the processor represents such exception
conditions is processor dependent.  
Outside enable constructs the meaning of exception conditions is processor
dependent.  The processor is required to 
support the exceptions floating point overflow (absolute value of result >
HUGE), floating point divide-by-zero 
(denominator is 0.0), and floating point underflow (0.0 < absolute value of
result < TINY); the processor may detect 
and signal other exceptions as well.

[Footnote: In a multitasking environment each virtual processor supports its
own exception conditions. If an enable 
construct contains statements that spawn tasks, enable, handle, and end-enable
statements act as barriers at which 
such exception condition values are merged.  Condition handling and the enable
construct are permitted in a pure 
procedure.]
.....................................................................
Section 3.3.1 - add to the Blanks Optional column (in alphabetical position):
            END ENABLE
.......................................................................
Section 7.1.7 - in fourth paragraph (which starts with 'Any'), after 'program',

		add ', except for real and complex operations in an enable block'
.......................................................................
Section 8.1 - add a fourth list item:
         (4) ENABLE construct
.......................................................................
Section 8.1 - in paragraph starting with 'Any', delete 'three'
........................................................................
Section 8.2 - insert a new section just before 8.2:

8.1.5 Condition handling

The processor is required to signal a condition if a floating point exception
occurs during execution of an intrinsic 
operation within an enable construct.   The processor is permitted, but not
required, to signal if an intrinsic function 
is not successful.  Within an enable construct, the user may signal with the
SIGNAL statement.  The processor may 
signal outside of an enable construct, but the meaning of such a signal is
processor dependent.

[Footnote: The intent of the intrinsic function provision is to allow an
intrinsic function to signal (to the caller) if a 
floating point exception occurs during evaluation of the function such that the
evaluation does not complete 
successfully.  It is not intended to allow signaling of calls defined as
illegal in Section 13; for example, calling SQRT 
with a negative real argument is nonstandard, whether or not the call to SQRT
is in an enable block.]

[Footnote:  Note that a SIGNAL statement may not appear outside of an enable
construct.]

[Footnote: On many processors, it is expected that some exception conditions
will cause no alteration to the flow of 
control when they are signaled and that they will be tested only when the
enable or handle block completes.  On 
other processors, this may be very expensive, and on them the handler may be
invoked at the time of signaling or 
soon thereafter.]

A signal must not occur if it could arise only during execution of a process
beyond those required or permitted by the 
standard.  For example, the division in the statement
           IF (X>1.) Y = Z/X
must not signal when X is less than 1.0, and for the statement
           WHERE(A>50.) A = EXP (A)
large elements of A must not cause signaling. On the other hand, when X has the
value 1.0 and Y has the value 0.0, 
the expression
           X>0.00001 .OR. X/Y>0.00001
is permitted to cause signaling.

[Footnote: In general, it is intended that implementations be free within
enable constructs to use the code motion 
techniques that they use outside enable constructs.]


8.1.5.1. The enable construct

The enable construct contains an enable block, and (optionally) a handle block.
 The handle block is executed only if 
execution of the enable block leads to signaling.

R835a    enable-construct 		is  	enable-stmt
                                     				enable-block
                                 			[ handle-stmt
                                     				handle-block ]
                                 			end-enable-stmt
 
R835b    enable-stmt   		is  	[ enable-construct-name : ]  ENABLE

R835c    enable-block   		is  	block
  
R835d    handle-stmt      		is  	HANDLE  [ enable-construct-name ]

R835e    handle-block   		is  	block

R835f    end-enable-stmt		is  	END ENABLE [ enable-construct-name ]
Constraint: If the enable-stmt of an enable-construct is identified by an
enable-construct-name, the corresponding 
end-enable-stmt must specify the same enable-construct-name. If the enable-stmt
of an enable-construct is not 
identified by an enable-construct-name, the corresponding end-enable-stmt must
not specify an enable-construct-
name. If the handle-stmt is identified by an enable-construct-name, the
corresponding enable-stmt must specify the 
same enable-construct-name.

Constraint: An enable-block must not contain a cycle-stmt, exit-stmt, or branch
statement that would cause branching 
outside of the enable-block. An alternate return specifier in an enable-block
must not specify the label of a statement 
outside the block.  An ERR=, END=, or EOR= specifier in a statement in an
enable-block must not be the label of a 
statement outside the block.

Constraint: A handle-block must not contain a cycle-stmt, exit-stmt, or branch
statement that would cause branching 
outside of the handle-block. An alternate return specifier in an handle-block
must not specify the label of a statement 
outside the block.  An ERR=, END=, or EOR= specifier in a statement in an
handle-block must not be the label of a 
statement outside the block.

An ENABLE statement may be a branch target statement (8.2). 

[Footnote: Neither a HANDLE statement nor an END ENABLE statement is permitted
to be a branch target.  A 
handle block is intended for execution only following signaling in its enable
block, and an END ENABLE statement 
is not a sensible target because it would permit skipping the handling of an
exception.]

[Footnote: Nesting of enable constructs is permitted.  An enable or handle
block may itself contain an enable 
construct.  Also, nesting with other constructs is permitted, subject to the
usual rules for proper nesting of 
constructs.]


8.1.5.2 Execution of an enable construct

Execution of an enable construct begins with the first executable construct of
the enable block and continues to the 
end of the block unless a condition is signaled.  The uncertainty scope of an
enable or handle block consists of the 
statements of the block that lie outside any enable construct nested within the
block. If a signal is associated with 
(occurs in) an uncertainty scope, there is a transfer of control sometime
during execution of the uncertainty scope 
subsequent to the signaling and prior to leaving the uncertainty scope.  Any
variable that might be defined or 
redefined by execution of a statement of the uncertainty scope or of a
procedure invoked in such a statement is 
undefined, any pointer whose pointer association might be altered has undefined
pointer association status, any 
allocatable array that might be allocated or deallocated may have been
allocated or become unallocated, and the file 
position of any file specified in an input/output statement that might be
executed is processor dependent.

[Footnote: The processor must check for signals at HANDLE statements, END
ENABLE statements, and nested 
ENABLE statements; it may also check at other points. The transfer to the
handle block is imprecise and processor 
dependent in order to allow for optimizations such as vectorization. As a
consequence, some variables become 
undefined. In Example 1 of 8.1.5.4, the matrix itself must not be altered by
the fast algorithm in order to be available 
for the slow algorithm.]

Although branching from within an enable construct to outside of the construct
is not allowed, a RETURN or STOP 
statement is permitted in an enable construct.

[Footnote: Note that although an enable construct may contain a RETURN or STOP
statement, there is no guarantee 
that such a statement will be executed in the event that an exception occurs
earlier in that uncertainty scope.]

If signaling occurs in an uncertainty scope that is nested in an enable block
that has a handler, a transfer is made to 
the handler of the innermost such enable block and the signaling ceases.  If
signaling occurs in an uncertainty scope 
that is not nested in an enable block that has a handler, a transfer is made
that is as for a return if in a subprogram, or 
stop in a main program, and the signaling continues (propagates to the caller).
In the event of signal propagation to 
the caller, the effect is as if the signal had been generated at the point of
return in the calling program.

If execution of the enable block completes without any signaling, the execution
of the enable construct is complete.

If the handler is invoked, the signal(s) triggering the handler are cleared by
the HANDLE statement and then 
execution proceeds with the first executable construct of the handle block.  If
execution of the handle block 
completes without signaling, the execution of the enable construct is complete.

[Footnote: Note that if a signal has occurred in an enable construct and not
cleared by a local HANDLE statement, it 
is propagated to the caller. Examples 2 and 3 in 8.1.5.4 both illustrate signal
propagation back to the caller. If the 
call is not in an enable construct, the effect is as if the exception had
occurred outside an enable construct. This could 
result in the program being nonstandard - for example if the exception is the
result of a divide-by-zero. In any event, 
the handling of a propagated signal is processor dependent if the call is not
in an enable construct.]



8.1.5.3 Signal statement

R835g     signal-stmt   is  SIGNAL 

Constraint: A signal-stmt may appear only in an enable-construct. 

The SIGNAL statement signals a processor-dependent floating point exception. 
The associated transfer of control 
takes place immediately; otherwise the effect of executing a SIGNAL statement
is the same as if the processor had 
signaled the condition.



8.1.5.4 Examples of ENABLE constructs


Example 1:

   ENABLE 
    		! First try the "fast" algorithm for inverting a matrix:
      MATRIX1 = FAST_INV (MATRIX) 
           	  	! MATRIX is not altered during execution of FAST_INV.
   HANDLE 
    		! "Fast" algorithm failed; try "slow" one:
        ENABLE 
           MATRIX1 = SLOW_INV (MATRIX)
        HANDLE 
           WRITE (*, *) 'Cannot invert matrix'
           STOP
        END ENABLE
   END ENABLE

In this example, the function FAST_INV may signal.  If it does, another try is
made with SLOW_INV.  If this still  
fails, a message is printed and the program stops.  Note the use of an  enable
construct within a handler.  Note also 
that the relevant code in both FAST_INV and SLOW_INV must enabled in order to
guarantee propagation of a 
signal.



Example 2

REAL FUNCTION HYPOT(X, Y)
! Calculation of the  hypotenuse  function:  sqrt(x**2+y**2)
! (See also the CABS example, page 225, ACM TOMS, June 1994.)
REAL X, Y
REAL SCALED_X, SCALED_Y, SCALED_RESULT
INTRINSIC SQRT, ABS, EXPONENT, MAX, SCALE
ENABLE		! try a fast algorithm first
	HYPOT = SQRT( X**2 + Y**2 )
HANDLE		! if fast algorithm fails with an exception, try a slower safer one
	IF ( X=0.0 .OR. Y=0.0 ) THEN
		HYPOT = ABS(X) + ABS(Y)
	ELSE IF ( ( 2*ABS(EXPONENT(X) - EXPONENT(Y) ) > (DIGTS(X) + 1 ) ) THEN
		HYPOT = MAX( ABS(X), ABS(Y) )	!  one of X and Y can be ignored
	ELSE   			! scale so that ABS(X) is near 1
		SCALED_X = SCALE( X, -EXPONENT(X) )
		SCALED_Y = SCALE( Y, -EXPONENT(X) )
		SCALED_RESULT = SQRT( SCALED_X**2 + SCALED_Y**2 )
		ENABLE	! possibility of overflow in unscaling result
			HYPOT = SCALE( SCALED_RESULT, EXPONENT(X) )
		END ENABLE	! if overflow does occur here, it s propagated back to caller
	END IF
END ENABLE
END FUNCTION HYPOT

Note that a signal propagates back to the caller if the slow algorithm fails
(but not if only the fast algorithm fails).




Example 3:

      MODULE LIBRARY
       :
      CONTAINS
         SUBROUTINE B
             :
            ENABLE
              	   X = Y*Z(I) 
	   IF (X>10.)  SIGNAL
            END ENABLE
             :
         END SUBROUTINE B
      END MODULE LIBRARY

      SUBROUTINE A
         USE LIBRARY
         ENABLE 
               CALL B
         HANDLE 
             :
         END ENABLE
      END SUBROUTINE A

In this case the user has defined what constitutes a numeric exception in the
event that processor overflow has not 
occurred.  In either case the handling takes place in subroutine A.




Example 4:

   SUBROUTINE LONG
      REAL, ALLOCATABLE A(:), B(:,:)
      : ! Other specifications
      ENABLE
          :
          ! Lots of code, including many procedure calls
          :
      HANDLE 
          ! Fix-up, including deallocation of any allocated arrays, in the
event of any 
          ! numeric exceptions that occur in enabled code in called procedures.
          IF(ALLOCATED(A)) DEALLOCATE (A)
          IF(ALLOCATED(B)) DEALLOCATE (B)
          :
      END ENABLE
   END SUBROUTINE LONG





......................................................................
Section 8.2 - in first paragraph, after 'end-do-stmt,' add 'an enable-stmt,'.
.......................................................................
Section 8.4 - add a new sentence to end of last paragraph:
	If the STOP statement is in an enable construct and a condition is signaling,
the 
	processor must issue a warning on the unit identified by * in a WRITE
statement, 
	indicating that an exception has occurred.
.......................................................................

	-   -


