* Document Number: WG14 N756/J11 97-119
C9X Revision Proposal
=====================
* Title: LIA-1 Binding: Arithmetic exceptions => SIGFPE
Author: Fred J. Tydeman
Author Affiliation: Tydeman Consulting
Postal Address: 3711 Del Robles Dr., Austin, Texas, USA, 78727
E-mail Address: tydeman@tybor.com
Telephone Number: +1 (512) 255-8696
Fax Number: +1 (512) 255-8696
Sponsor: WG14
Date: 1997-09-21
Proposal Category:
__ Editorial change/non-normative contribution
__ Correction
Y_ New feature
__ Addition to obsolescent feature list
__ Addition to Future Directions
__ Other (please specify) ______________________________
Area of Standard Affected:
__ Environment
__ Language
__ Preprocessor
Y_ Library
Y_ Macro/typedef/tag name
Y_ Function
Y_ Header
__ Other (please specify) ______________________________
Prior Art: We believe that several implementations already do
this (for floating-point exceptions).
Target Audience: Programmers writing programs that perform a
significant amount of numeric processing.___________________
Related Documents (if any):
WG14/N758 C9X and LIA-1 informative annex,
WG14/N755 LIA-1 Binding: to ,
WG14/N753 LIA-1 Binding: Rationale,
WG14/N752 LIA-1 Binding: Optional parts annex,
WG14/N751 LIA-1 Binding: Combined LIA-1 + IEC-559 annex,
WG14/N750 LIA-1 Binding: LIA-1 annex,
WG14/N749 LIA-1 Binding: ,
WG14/N748 LIA-1 Binding: Adding 'pole' from LIA-2,
WG14/N747 IEC 559 Binding: Signaling NaNs,
WG14/N693 Type-Generic Math Functions,
WG14/N528 C Binding for LIA-1,
WG14/N488 LIA-2 (math library),
WG14/N487 LIA-1 (arithmetic),
WG14/N486 LIA Overview,
WG14/N463 Impact of adding LIA-1,
WG14/N461 C Binding of LIA-1,
NCEG 91-041 Floating-Point Modes and Status,
NCEG 90-015 NCEG Operators,
NCEG 89-007 Exception Handling,
NCEG 89-005 IEEE 754 Issues
Proposal Attached: _Y Yes __ No, but what's your interest?
Abstract: This proposal requires that arithmetic exceptions,
such as zero divide, get converted into raise of SIGFPE.
This then allows user signal handlers to be trap handlers of
arithmetic exceptions. Such signal handlers may longjmp,
abort, or exit.
This does not cover return from the SIGFPE signal handler
(replace exceptional value with value from signal handler)
nor presubstitution (replace exceptional value with
non-standard continuation value) as means to cope with
exceptions.
Proposal:
We have four choices with this part of the proposal:
1) Add the following text to (as normative).
2) Add the following text to the LIA-1 annex (so that it is
normative if and only if the implementation supports LIA-1).
This is the suggested choice.
3) Add the following text to the optional parts annex (so
if an implementation supports the optional feature, we
have standard syntax/semantics).
4) Forget it.
Note: The '*' characters in the lefthand column are not part
of the proposal (they are useful for emacs M-x outline mode)
In the following, **bold text**, *italic text*,
`code sample` are the conventions used to indicate
text different from normal.
* In , **7.x.4.1.1 The LIA_NOTIFY pragma**:
** - The meaning of the UNDEF state is extended to include: In
particular, there is no requirement that notifications
(arithmetic exceptions) raise **SIGFPE**.
** - The meaning of the TRAP state is changed to: a trap shall be
turned into a raise of **SIGFPE**.
* In LIA-1 annex, H.3.1.2 Traps:
Change the concept of 'trap first exception and terminate is
done via implementation defined means' to 'traps are
converted into raise of SIGFPE'.
There shall be a means to determine the non-numeric
exceptional value (in LIA-1 sense) that was produced for the
arithmetic exception. Here is the suggested way to do that.
(An alternative is to map each arithmetic exception into its
own SIG* value).
**** H.3.1.2 Traps
**SIGFPE** shall be sent to the executing program
for each arithmetic exception.
During program startup, the equivalent of
**signal(SIGFPE, SIG_DFL);**
**feenabletrap( FE_TRAP_INVALID | FE_TRAP_DIVBYZERO
| FE_TRAP_OVERFLOW | FE_TRAP_UNDERFLOW );**
**ieenabletrap( INT_TRAP_INVALID | INT_TRAP_DIVBYZERO
| INT_TRAP_OVERFLOW );**
shall be executed.
***** H.3.1.2.1 Trap and terminate
This shall be accomplished by using the implementation's
default signal handler (**SIG_DFL**) for **SIGPFE**.
The default signal handler for **SIGFPE** shall do the
same as the current implementation checking of LIA-1
indicators and "hard to ignore" message at termination.
***** H.3.1.2.2 Trap and resume
A user specifies code (a trap handler) to compensate for
exceptions by:
**signal(SIGFPE, user_trap_handler);**
where user_trap_handler is the user's trap handler.
When **SIGFPE** is sent to the executing program, the user's
signal handler for **SIGFPE** is invoked.
Program execution is continued from the user's trap handler
shall be supported by the use of the **longjmp**
function.
Return from a signal handler for SIGFPE is still undefined;
an implementation may support **return** from a user's
**SIGFPE** trap handler, but is not required to do so.
* -- Add to a type, several macros and a function
to get the details about the current arithmetic exception.
** The type declared is
liastat_t
which is a structure type that is the type of the value
returned by the liagetstatus function.
** The following macros, which expand to positive integral
constant expressions with distinct values, suitable for use
in #if preprocessing directives, some of which represent the
non-numeric exception values returned from mathematical
operations (see LIA-1 4.2 definitions), each corresponding
to the specified exceptional condition:
LIA_XV_RAISE raise(SIGFPE) in user's code
LIA_XV_INVALID invalid or undefined operation or
bad argument to operation (domain)
LIA_XV_POLE finite non-zero divided by zero or
pole of mathematical function, such as
log(0), or singularity
LIA_XV_OVERFLOW finite result so large in magnitude
that it cannot be represented without
extraordinary roundoff error
LIA_XV_UNDERFLOW finite result so small in magnitude
that it cannot be represented without
extraordinary roundoff error
LIA_XV_APPROX finite result can be represented, but
the error between the computed result
and the true result exceeds the
allowed error for the operation.
Large errors may result from arguments
too big to the trig functions.
LIA_XV_INEXACT non-zero error between computed result
and true result is within error bounds
of the operation; IEC-559 inexact by
itself
are defined if and only if the implementation supports the
exception by means of the functions in 7.x.4.2.
LIA_XV_RAISE, LIA_XV_APPROX, and LIA_XV_INEXACT are not
LIA-1 exception values.
[Note: LIA_XV_APPROX is from LIA-2 where it is called
arg_too_big.]
** The following macros, which expand to positive integral
constant expressions with distinct values, suitable for use
in #if preprocessing directives, that represent the
corresponding group of C types:
LIA_GRP_FLOATING float, double, long double,
float complex, double complex,
long double complex
LIA_GRP_INTEGRAL (signed, unsigned) x (char, short,
int, long, long long)
LIA_GRP_STRING char *, wchar_t *
are defined.
** The following macros, which expand to positive integral
constant expressions with distinct values, suitable for use
in #if preprocessing directives, that represent general or
specific mathematical operations, each corresponding to the
specified operation:
LIA_OP_ZERO_DIV_ZERO // zero / zero
LIA_OP_INF_DIV_INF // inf / inf
LIA_OP_INF_REM // inf REM y
LIA_OP_REM_ZERO // x REM zero
LIA_OP_INF_MOD // inf MOD y
LIA_OP_MOD_ZERO // x MOD zero
LIA_OP_CVT_FP_INF // inf -> fp or int
LIA_OP_CVT_FP_NAN // NaN -> fp or int
LIA_OP_CVT_STR_INF // "INF" -> fp or int
LIA_OP_CVT_STR_NAN // "NAN" -> fp or int
LIA_OP_CVT_STR_UNK // "unknown" -> fp or int
LIA_OP_NANS // signaling NaN operand
LIA_OP_SUBNORM // subnormal operand
LIA_OP_COMP // comparison
LIA_OP_ADD // +
LIA_OP_SUB // -
LIA_OP_MUL // *
LIA_OP_DIV // /
LIA_OP_SQRT // sqrt
LIA_OP_LOG // log
LIA_OP_EXP // exp
// and so on ...
are defined if and only if the implementation supports
exceptions by means of the functions in 7.x.4.2 for the
specific operation and operands or general operation.
Additional macro definitions, beginning with LIA_OP_ may
also be specified by the implementation.
[Note: The following details are not needed:
LIA_OP_INF_ADD_INF == undefined and add
== inf + (-inf) or (-inf) + inf
LIA_OP_INF_SUB_INF == undefined and sub
== inf - inf or (-inf) - (-inf)
LIA_OP_INF_MUL_ZERO == undefined and mul
== zero * inf or inf * zero
LIA_OP_DIV_ZERO == pole and div
== finite non-zero / zero
LIA_OP_LOG_ZERO == pole and log
== log(0)
LIA_OP_SQRT_NEG == undefined and sqrt
== sqrt(negative)
LIA_OP_UNORD_COMP == undefined and comp
== unordered compare
because those operations only have one failure, which can be
determined from the exception value and the operation]
** 7.x.4.3 The liagetstatus function
Synopsis
#include
liastat_t liagetstatus( void );
Description
The liagetstatus function obtains information about the
computational exception that caused the SIGFPE signal
handler to be called. liagetstatus shall be callable from a
signal handler for SIGFPE that results from a computational
exception. It is implementation defined what happens when
liagetstatus is called for signals other than SIGFPE. It is
implementation defined what happens when liagetstatus is
called from other than a signal handler.
Returns
The liagetstatus function returns a structure of type
liastat_t, comprising information about the current
exception. The structure shall contain at least the
following members, in any order:
int xcp_value; // exceptional value
int res_grp; // general type of result
double ulp_error; // how close is answer
int details; // operation & operand
The implementation may add more fields to give additional
information about the exception, such as the operand
specific types and values.
*** xcp_value shall contain either -1 (to indicate no
information available), or one of the macros starting with
LIA_XV_, and it indicates the non-numeric exceptional value,
in the LIA-1 sense, returned by the arithmetic operation or
library function that raised the exception.
*** res_grp shall contain either -1 (to indicate no information
available), or one of the macros starting with LIA_GRP_, and
it indicates the general type of result of the arithmetic
operation or library function that raised the exception.
[Note: An implementation may add a member to indicate the
specific type with these suggest names:
LIA_TYP_CMPLX_LONG_DOUBLE
LIA_TYP_CMPLX_DOUBLE
LIA_TYP_CMPLX_FLOAT
LIA_TYP_LONG_DOUBLE
LIA_TYP_DOUBLE
LIA_TYP_FLOAT
LIA_TYP_EXT_INT // signed extended integer type
LIA_TYP_LONG_LONG
LIA_TYP_LONG
LIA_TYP_INT
LIA_TYP_SHORT
LIA_TYP_CHAR
LIA_TYP_U_EXT_INT // unsigned extended integer type
LIA_TYP_U_LONG_LONG
LIA_TYP_U_LONG
LIA_TYP_U_INT
LIA_TYP_U_SHORT
LIA_TYP_U_CHAR
LIA_TYP_STR
LIA_TYP_WC_STR
LIA_TYP_PTR
LIA_TYP_BOOL // ???
]
*** The ulp_error field should give a rough indication of the
error between the computed result and the true result.
-1.0 shall indicate this field is meaningless and includes
undefined, overflow, underflow.
0.0 shall indicate an exact answer and includes IEC 559
divide by zero.
0.5 IEC 559 inexact (by itself) in round to nearest.
1.0 typical non IEC 559 rnd_error for arithmetic operation.
+x approximate ulp error in answer from math library
function.
DBL_MAX shall indicate total loss of precision or LIA-2
arg_to_big.
*** The details field shall contain either -1 (to indicate no
information available), or one of the macros starting with
LIA_OP_, and it gives a rough classification of the
operation and operand values. In some cases, the
combination of xcp_value and details jointly define the
exception (such as sqrt(negative) is LIA_XV_INVALID and
LIA_OP_SQRT). In other cases, the combination of xcp_value
and res_grp jointly define the exception (such as
FLT_MAX*FLT_MAX is LIA_XV_OVERFLOW and LIA_GRP_FLOATING).
* -- Add the following to the combined LIA-1 + IEC 559 annex:
** The SIGFPE signal handlers (the implementation's and the
user's default) are the handlers for the IEC 559 exceptions.
The signal function in is the means to test and
alter the handlers. The signal function provides the
capability to save and restore an existing signal handler.