ISSUE: IEEE Float Exception Trapping REVISION HISTORY: Version 1, 18 January 1994, Rob MacLachlan STATUS: open RELATED ISSUES: Allow IEEE Float Comparisons, IEEE Float Conformance This issue only concerns the Dylan language support for IEEE floating point exceptions. If LOWEST-COMMON-DENOMINATOR IEEE (non) conformance is chosen, then this issue would only arise in attempts to retrofit IEEE support to Dylan. CATEGORY: Clarification PROBLEM DESCRIPTION: The IEEE standard for floating point arithmetic defines several exceptions: Overflow Underflow Inexact Invalid Divide-By-Zero An IEEE exception is not considered to be "an error", and especially in the case of underflow, commonly useful semantics are associated with underflow (denormalized arithmetic, possible underflow to zero.) Although implementations are encouraged to conditionally trap (allowing run-time errors to be signalled), this must not be the default. The non-trapping default was chosen because it allows programmers to efficiently control exceptional conditions without requiring: -- Standardized trapping support which would be excessively expensive to implement in hardware, or -- Pervasive use of trap handing constructs in code that must operate near overflow/underflow boundaries. It would probably be most tasteful to always signal conditions on an IEEE exception, and then have a restart which allows execution to continue. However: -- IEEE implementations are not required to support any kind of trapping, -- Even when it is possible, execution with continuable trapping enabled can have a large performance and implementation complexity even when no traps occur, and -- Code with frequent exceptions can be greatly slowed by trapping into user mode, signalling a condition and proceeding. Even though it is not fully specified by the IEEE standards, some form of float exception trapping is generally supported, and is very useful for localizing bugs caused by unanticipated exceptions. Current practice: -- Lisp implementations have generally chosen to have trapping enabled by default. -- All the Unix environments I know of have a non-trapping default, and I assume that other IEEE environments also follow the non-trapping rule. -- The Dylan book does not seem to say whether floating point errors cause conditions to be signalled, making it unclear if and how Dylan programmers can write code that exploits non-error overflow or underflow. Float exception trapping is generally controlled on a per-process basis, which makes it difficult to mix trapping and non-trapping code: -- Much existing code assumes that trapping is off. Having trapping on by default makes it more difficult to use existing code not written in Dylan. At a minimum, it increases the cost of calling foreign code, since the trap status must be saved and restored. -- With Dylan-to-Dylan calls, different trapping policy could be used for different functions (or perhaps libraries) by shallow-binding the trap status in entry points (with unwind-protect) and around all calls out of the local trap state. However, this would make code that uses a local trapping policy less efficient, and would complicate implementation. PROPOSAL: [These proposals assume an option other than LOWEST-COMMON-DENOMINATOR has been chosen for "IEEE Float Conformance".] ASSUME-NON-TRAPPING: Dylan code may be written to assume non-trapping semantics. Conditions will be defined for the IEEE exception traps, but no portable way is defined to continue from these conditions. The environment is assumed to provide control of trapping for debugging support. ASSUME-TRAPPING: Dylan code may be written to assume that all exceptions will be signalled as conditions. Ideally, proceeding with an IEEE special value should be supported to emulate non-trapping semantics. RATIONALE: ASSUME-NON-TRAPPING: This is the model for which the IEEE float standard was developed, and is therefore the model best supported by hardware and operating systems. Trapping is considered to be a debugging feature under control of the programming environment. Since non-trapping is the default for nearly all programming environments, experienced programmers may be surprised by a trapping default. ASSUME-TRAPPING: This allows Dylan progammers to make use of the Dylan condition system for handling floating point exceptions. Using an error value to indicate an ill-defined operation is not done elsewhere in Dylan, and may be surprising to naive users. EXAMPLES: Some examples which cause exceptions, the result if not trapped, and the exception. 1e-38 - 1e-42 => 9.9990004e-39 Underflow 3e38 + 1e38 => +infinity Overflow 1.0 / 0.0 => +infinity Divide-By-Zero 0.0 / 0.0 => NaN Invalid-Operation 1.0 < NaN => #f Invalid-Operation COST TO IMPLEMENTORS: ASSUME-TRAPPING imposes a large burden on implementors. Continuation from a float trap with a different value can be complex to implement. COST TO USERS: ASSUME-NON-TRAPPING can perplex naive users. ASSUME-TRAPPING would sorely vex experienced numeric programmers. PERFORMANCE IMPACT: ASSUME-TRAPPING can cause substantial slowdown when running: -- programs with frequent exceptions, or -- any program on hardware that doesn't support trapping or that imposes a penalty on code that needs precise exceptions. BENEFITS: Either proposal would let programmers know what to expect when an exception happens. AESTHETICS: ASSUME-TRAPPING seems more Dylan-like. FUTURE FEATURES: