* 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: <fenv.h> to <stdmath.h>, 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: <stdlia.h>, 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 <stdlia.h> (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, <TT>code sample</TT> are the conventions used to indicate text different from normal. * In <stdlia.h>,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) raiseSIGFPE. ** - The meaning of the TRAP state is changed to: a trap shall be turned into a raise ofSIGFPE. * 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 TrapsSIGFPEshall be sent to the executing program for each arithmetic exception. During program startup, the equivalent ofsignal(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) forSIGPFE. The default signal handler forSIGFPEshall 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. WhenSIGFPEis sent to the executing program, the user's signal handler forSIGFPEis invoked. Program execution is continued from the user's trap handler shall be supported by the use of thelongjmpfunction. Return from a signal handler for SIGFPE is still undefined; an implementation may supportreturnfrom a user'sSIGFPEtrap handler, but is not required to do so. * -- Add to <stdlia.h> 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 <stdlia.h> 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 <signal.h> is the means to test and alter the handlers. The signal function provides the capability to save and restore an existing signal handler.