[Cfp-interest] revised directives.txt

David Hough CFP pcfp at oakapple.net
Wed May 21 16:45:34 PDT 2014


I'll be talking about this at a research meeting tomorrow in Berkeley
to get some additional feedback.



Directives Pragmas


========== 754-2008 chapter 4 specifies attributes:

 4.1 Attribute specification

 An attribute is logically associated with a program block to modify
 its numerical and exception semantics.  A user can specify a constant
 value for an attribute parameter.

 Some attributes have the effect of an implicit parameter to most
 individual operations of this standard; language standards shall
 specify

 * rounding-direction attributes

 and should specify

 * alternate exception handling attributes

 Other attributes change the mapping of language expressions into
 operations of this standard; language standards that permit more than
 one such mapping should provide support for:

 * preferredWidth attributes

 * value-changing optimization attributes

 * reproducibility attributes

 For attribute specification, the implementation shall provide
 language-defined means, such as compiler directives, to specify a
 constant value for the attribute parameter for all standard operations
 in a block; the scope of the attribute value is the block with which
 it is associated. Language standards shall provide for constant
 specification of the default and each specific value of the
 attribute.
==========

========== 754-2008 chapter 8 recommends that languages require 
		various types of alternate exception handling:


 * default (raise flag)
Provide the default exception handling in the associated block 
despite alternate exception
handling that might be in effect in wider scope.

 * raiseNoFlag
Provide the default exception handling without raising the 
corresponding status flag.

 * mayRaiseFlag
Provide the default exception handling, except languages define 
whether a flag is raised.
Languages may defer to implementations for performance.

 * recordException
Provide the default exception handling and record the 
corresponding exception whenever
Clause 7 specifies raising a flag. 
Recording an exception means storing a description of the
exception, 
including language-standard-defined details which might include 
the current operation
and operands, and the location of the exception. 
Language standards define operations to convert
exception descriptions to and from character sequences, 
and to inspect, save, and restore exception descriptions.

 * substitute(x)
Specifiable for any exception: 
replace the default result of such an exceptional operation with a
variable or expression x. 
The timing and scope in which x is evaluated is language-defined.

 * substituteXor(x)
Specifiable for any exception arising from 
multiplication or division operations: like substitute(x),
but replace the default result of such an exceptional operation 
with |x| and, if |x| is not a NaN,
obtaining the sign bit from the XOR of the signs of the operands.

 * abruptUnderflow
When underflow is signaled because a tiny non-zero result is detected, 
replace the default result
with a zero of the same sign or 
a minimum normal rounded result of the same sign, raise the
underflow flag, and signal the inexact exception. 

 * Immediate alternate exception handler block associated with a block: 
if the indicated exception is
signaled, abandon execution of the associated block as soon as possible and 
execute the handler block, 
then continue execution where execution would have continued after 
normal termination of the associated block, 
according to the semantics of the language.

 * Delayed alternate exception handler block associated with a block: 
if the indicated exception is
signaled, handle it by default until the associated block terminates normally,
then execute the handler block, 
then continue execution where execution would have continued after normal
termination of the associated block, 
according to the semantics of the language.

Transfers:

 * Immediate transfer associated with a block: 
if the indicated exception is signaled, transfer control
as soon as possible; no return is possible.

 * Delayed transfer associated with a block: 
if the indicated exception is signaled, handle it by default
until the associated block terminates normally, then transfer control; 
no return is possible.

A transfer is a language-specific idiom for non-resumable control transfer. 
Language standards might require several transfer idioms such as:

 * break: Abandon the associated block and continue execution where execution 
would continue after normal termination of the associated block, 
according to the semantics of the language.

 * throw exceptionName: Causes an exceptionName not to be handled locally, 
but rather signaled to
the next handling in scope, 
perhaps the function that invoked the current subprogram, according to
the semantics of the language.

 * goto label:

==========

========== ANSI-C 7.6 specifies exception names

	FE_INEXACT
	FE_UNDERFLOW
	FE_OVERFLOW 
	FE_DIVBYZERO
	FE_INVALID
	FE_ALL_EXCEPT		shorthand for all five

========== ANSI-C specifies standard pragmas:

 6.10.6 Pragma directive

 Semantics A preprocessing directive of the form
  # pragma pp-tokensopt new-line where the preprocessing token STDC
 does not immediately follow pragma in the directive (prior to any
 macro replacement)174) causes the implementation to behave in an
 implementation-defined manner. The behavior might cause translation to
 fail or cause the translator or the resulting program to behave in a
 non-conforming manner. Any such pragma that is not recognized by the
 implementation is ignored.

 If the preprocessing token STDC does immediately follow pragma in the
 directive (prior to any macro replacement), then no macro replacement
 is performed on the directive, and the directive shall have one of the
 following forms175) whose meanings are described elsewhere:

  #pragma STDC FP_CONTRACT on-off-switch

  #pragma STDC FENV_ACCESS on-off-switch

  #pragma STDC CX_LIMITED_RANGE on-off-switch

 on-off-switch: one of

  ON OFF DEFAULT
==========

========== ANSI-C 7.12.2 specifies scope for FP_CONTRACT 
           extendible to other standard pragmas:

 Each FP_CONTRACT pragma can occur either outside external declarations
 or preceding all explicit declarations and statements inside a
 compound statement. When outside external declarations, the pragma
 takes effect from its occurrence until another FP_CONTRACT pragma is
 encountered, or until the end of the translation unit. When inside a
 compound statement, the pragma takes effect from its occurrence until
 another FP_CONTRACT pragma is encountered (including within a nested
 compound statement), or until the end of the compound statement; at
 the end of a compound statement the state for the pragma is restored
 to its condition just before the compound statement. If this pragma is
 used in any other context, the behavior is undefined.

========== ANSI-C specifies scope with respect to invoked subfunctions:

Functions affected by constant rounding modes and alternate exception
handling modes

Within the scope of an FENV directive establishing a constant rounding mode
or an alternate exception handling mode,
all floating-point operators, 
implicit conversions (including the conversion of a value represented in a
format wider than its semantic types to its semantic type, 
as done by classification macros), and
invocations of functions indicated in the table below, 
for which macro replacement has not been
suppressed, 
shall be evaluated according to the specified mode. 
Invocations of functions for which macro replacement has
been suppressed and invocations of functions other than those indicated in the
table below shall not
be affected by constant rounding modes or alternate exception handling modes.

<Header> Function groups

<math.h> acos, asin, atan, atan2
<math.h> cos, sin, tan
<math.h> acosh, asinh, atanh
<math.h> cosh, sinh, tanh
<math.h> exp, exp2, expm1
<math.h> log, log10, log1p, log2
<math.h> scalbn, scalbln, ldexp
<math.h> cbrt, hypot, pow, sqrt
<math.h> erf, erfc
<math.h> lgamma, tgamma
<math.h> rint, nearbyint, lrint, llrint
<math.h> fdim
<math.h> fma
<math.h> fadd, daddl, fsub, dsubl, fmul, dmull, fdiv, ddivl, ffma, dfmal
<math.h> fsqrt, dsqrtl 
<stdlib.h> atof, strfromd, strfromf, strfroml, strtod, strtof, strtold
<wchar.h> wcstod, wcstof, wcstold
<stdio.h> printf and scanf families
<wchar.h> wprintf and wscanf families

Each <math.h> functon listed in the table above indicates 
the family of functions of all supported types 
(for example, acosf and acosl as well as acos).

========== Existing standard pragmas

(ANSI-C)
#pragma STDC FP_CONTRACT on-off-switch
#pragma STDC FENV_ACCESS on-off-switch
#pragma STDC CX_LIMITED_RANGE on-off-switch
 on-off-switch: one of
  	ON 
  	OFF 
	DEFAULT

(Floating-point extensions for C - Part 1)
#pragma STDC FENV_ROUND bdirection
 bdirection: 
	FE_DOWNWARD
	FE_TONEAREST 
	FE_TOWARDZERO
	FE_UPWARD
	FE_DYNAMIC

(Floating-point extensions for C - Part 2)
#pragma STDC FENV_DEC_ROUND ddirection
 ddirection:
	FE_DEC_DOWNWARD
	FE_DEC_TONEAREST
	FE_DEC_TONEARESTFROMZERO
	FE_DEC_TOWARDZERO
	FE_DEC_UPWARD
	FE_DEC_DYNAMIC
==========

========== Floating-point extensions for C - Part 3 
		expands the EVAL_METHOD macro definitions

(binary)

If FLT_RADIX is 2, the value of the macro FLT_EVAL_METHOD (5.2.4.2.2) 
characterizes the use of
evaluation formats for standard floating types and for binary interchange 
and extended floating types:

-1 indeterminable;

0 evaluate all operations and constants, whose semantic type has at most the range and
precision of float, to the range and precision of float; evaluate all other operations and
constants to the range and precision of the semantic type;

1 evaluate operations and constants, whose semantic type has at most the range and
precision of double, to the range and precision of double; evaluate all other operations
and constants to the range and precision of the semantic type;

2 evaluate operations and constants, whose semantic type has at most the range and
precision of long double, to the range and precision of long double; evaluate all other
operations and constants to the range and precision of the semantic type;

N, where _FloatN is a supported interchange floating type
evaluate operations and constants, whose semantic type has at most the range and
precision of the _FloatN type, to the range and precision of the _FloatN type; evaluate
all other operations and constants to the range and precision of the semantic type;

N + 1, where _FloatNx is a supported extended floating type
evaluate operations and constants, whose semantic type has at most the range and
precision of the _FloatNx type, to the range and precision of the _FloatNx type;
evaluate all other operations and constants to the range and precision of the semantic type.


(decimal)

The implementation-defined value of the macro DEC_EVAL_METHOD characterizes the use of
evaluation formats (see analogous FLT_EVAL_METHOD in 5.2.4.2.2) for decimal interchange and
extended floating types:

-1 indeterminable;

0 evaluate all operations and constants just to the range and precision of the type;

1 evaluate operations and constants, whose semantic type has at most the range and
precision of the _Decimal64 type, to the range and precision of the _Decimal64 type;
evaluate all other operations and constants to the range and precision of the semantic type;

2 evaluate operations and constants, whose semantic type has at most the range and
precision of the _Decimal128 type, to the range and precision of the _Decimal128 type;
evaluate all other operations and constants to the range and precision of the semantic type;

N, where _DecimalN is a supported interchange floating type
evaluate operations and constants, whose semantic type has at most the range and
precision of the _DecimalN type, to the range and precision of the _DecimalN type;
evaluate all other operations and constants to the range and precision of the semantic type;

N + 1, where _DecimalNx is a supported extended floating type
evaluate operations and constants, whose semantic type has at most the range and
precision of the _DecimalNx type, to the range and precision of the _DecimalNx type;
evaluate all other operations and constants to the range and precision of the semantic type;

==========================================================================

The foregoing pragma STDC syntax and scope will be extended to
encompass the attributes required by 754-2008.
Implementations are allowed to generate warnings for standard pragmas 
that they don't implement; they are not allowed to silently ignore them.

==========================================================================

----- ALTERNATE EXCEPTION HANDLING proposals -----

A standard pragma FENV_EXCEPT will provide some alternate exception
handling capabilities mentioned by 
754-2008.
To obtain maximum flexibility, standard macros will be specified as well:
FP_EXCEPTIONAL_FLAGS,
FP_EXCEPTIONAL_DETERMINISTIC,
and FP_EXCEPTIONAL_NONDETERMINISTIC.



Add the following subexceptions of invalid and divbyzero:
 subexception:
	FE_INVALID_SNAN		7.2a
	FE_INVALID_MUL		7.2b
	FE_INVALID_FMA		7.2c
	FE_INVALID_ADD		7.2d
	FE_INVALID_DIV		7.2e
	FE_INVALID_REM		7.2f
	FE_INVALID_SQRT		7.2g
	FE_INVALID_QUANTIZE	7.2h
	FE_INVALID_INT		7.2i
	FE_INVALID_UNORDERED	7.2j
	FE_INVALID_LOGB		7.2k
	FE_INVALID_OTHER	especially for 754 chapter 9 functions
	FE_DIVBYZERO_DIVISOR	7.3 divisor zero
	FE_DIVBYZERO_LOGB	7.3 logb(0)
	FE_DIVBYZERO_OTHER	especially for 754 chapter 9 functions
	

#pragma STDC FENV_EXCEPT exception-list action 
 exception list is a list of exceptions and subexceptions
 separated by commas

 This pragma's actions don't change control flow:
	DEFAULT				754 default
 	NO_FLAG				default result, but no flag raised
	MAY_FLAG			implementation may raise flag or not
	ABRUPT 				underflow only, mandatory
	RECORD				record the exception in a "debugger"
					and continue; same as default if
					no debugger active

What about functions invoked within compound statements controlled by
an alternate exception handling pragma?    To follow the lead of
FENV_ROUND, a list of functions corresponding to 754 operations
specifies those affected by rounding and alternate exception handling pragmas.
Inlining does not affect whether an operation is affected.

Exceptional Macros

 FE_EXCEPTIONAL_FLAGS( 
	compound-statement)
 FE_EXCEPTIONAL_DETERMINISTIC( 
	compound-statement, exception1, exception2, ...)
 FE_EXCEPTIONAL_NONDETERMINISTIC( 
	compound-statement, exception1, exception2, ...)

are special macros, almost varargs functions.   

FE_EXCEPTIONAL_FLAGS evaluates the compound-statement and returns an int
which is a mask of all the exception flags that would have been raised
during the execution of the compound-statement.     It's equivalent to

	s1 = save flags
	clear flags
	compound-statement
	s2 = save flags
	restore s1 flags
	compound-statement value is s2 flags

The saving is in verbiage so the compound-statement isn't lost in a sea of
flag mechanism.	   A typical usage might be

if ( FE_EXCEPTIONAL_FLAGS( d=b*b-a*c ;) & (FE_OVERFLOW | FE_UNDERFLOW) ) {
	/* normal case */
	d = sqrt(d);
} else {
	/* exceptional case - scale to avoid intermediate spill */
	...
}

Execution of compound-statement continues to its end, even if exceptions
are detected early.    Because it is based on 754 flags, detecting 
subexceptions is not possible.     Underflow detection is based upon
whether the underflow flag was raised, not whether the underflow exception
occurred.

FE_EXCEPTIONAL_DETERMINISTIC and FE_EXCEPTIONAL_NONDETERMINISTIC
evaluate the compound-statement,
and return a non-zero int if any of the listed exceptions arose in the
course of the computation, and a zero int otherwise.
The non-zero int might be an implementation-dependent encoding of the listed
exceptions that arose, taking into account sub-exceptions.
Flags and traps for the listed exceptions
are the same after execution as before.
Other side effects, including flags and traps for unlisted exceptions,
occur the same as if compound-statement were executed alone.
Subexceptions can be specified though that might imply a performance
penalty relative to specifying exceptions.
Underflow detection is based upon whether the underflow exception occurred,
not whether the underflow flag was raised.

FE_EXCEPTIONAL_DETERMINISTIC
finishes the compound-statement and then
sets the result value and continues execution.
Intermediate and final results are in a deterministic state.

FE_EXCEPTIONAL_NONDETERMINISTIC
is allowed to quit work on the compound-statement 
as soon as it determines that a listed exception has occurred.
Intermediate results might not be in a deterministic state.
Listed exceptions that might have been encountered later might not be reported.
An example of an application is computing the sum of squares for a 2-norm:
one might have the fast obvious loop as the compound-statement,
with underflow and overflow as the exceptions to be tested for;
if either arise, the fast computation is discarded and a slower scaled
one undertaken.

Using the notation FE_EXCEPTIONAL to refer to either,
they are intended to be used like any other conditional expression,

 if FE_EXCEPTIONAL(compound-statement, exception) {
  exceptional-case-code
 } else {
  nonexceptional-case-code
 }
 
 FE_EXCEPTIONAL(compound-statement, exception) 
	? exceptional-case-code 
	: nonexceptional-case-code
 
 switch FE_EXCEPTIONAL(compound-statement, exception1, exception2) {
 case exception1: exceptional-case1-code
 case exception2: exceptional-case2-code
 case exception1|exception2: exceptional-case12-code
 default: nonexceptional-case-code
 }

The code in compound-statement and nonexceptional-case-code might well
overlap.
Optimizing compilers would be expected to handle these cases
without unnecessary recomputation. 

FE_EXCEPTIONAL is intended to impart the flexibility of C++ try/catch without
damaging C syntax or supporting the full generality of C++ try/catch.
FE_EXCEPTIONAL is not a function; its arguments include a 
compound-statement, and the compound-statement is not to be 
evaluated outside the macro.
It seems much better to avoid scope issues by having
expressions and labels exist within normal
C syntax rather than somehow grafted onto pragmas. 

We could note than a corresponding construct

 FE_SIGNALING( compound-statement, signal1, signal2, ...)

could have commensurate benefits for non-numeric programs: hiding all
the complication of setting up, using, and tearing down local signal handlers
by making the compiler and operating system figure it out.
But that's not our case. 

(By considering signals I came up with the name FE_SIGNALING and then
the name FE_EXCEPTIONAL, rather than FE_TRYCATCH,
but maybe somebody else has a better idea.)









----- OTHER DIRECTIVES under consideration -----

FENV_FLT_EVAL_METHOD and FENV_DEC_EVAL_METHOD
specify the minimum evaluation width for expressions involving
standard, or binary, or decimal floating-point types.

#pragma STDC FENV_FLT_EVAL_METHOD eval
	eval is one of the integer constants available from FLT_EVAL_METHOD,
	but not -1
This affects standard and binary floating-point types.

#pragma STDC FENV_DEC_EVAL_METHOD eval
	eval is one of the integer constants available from DEC_EVAL_METHOD,
	but not -1
This affects decimal floating-point types.


#pragma STDC FENV_VALUE_CHANGING_OPTIMIZATIONS switch
 switch:
  ON
  OFF
  DEFAULT

enables compilers to make value changing optimizations but doesn't require
them.
There will be specific optimizations under this umbrella, such as

#pragma STDC FENV_FAST_SUBNORMAL switch
 enables but does not require abrupt underflow and 
 zero treatment of subnormal operands if faster, implementation defined
 Compare to the ABRUPT alternate exception handling mode for underflow:
 it is compulsory, even if slower, and is defined in 754.

#pragma STDC FENV_REPRODUCIBLE switch
  ON
  OFF
  DEFAULT

requires compilers to generate code that avoids certain specified
sources of irreproducible results.
Implies FENV_FLT_EVAL_METHOD and FENV_DEC_EVAL_METHOD values 0.
There will be additional specific features under this umbrella...





More information about the Cfp-interest mailing list