5.5.3. Exceptions

Floating-point arithmetic operations can run into various problems. For example, the result computed might be either too big or too small to fit into the format, or there might be no way to calculate the result (as in trying to take the square root of a negative number, or trying to divide zero by zero). These are known as exceptions, because they indicate unusual or exceptional situations.

The ARM floating-point environment can handle exceptions in more than one way.

Ignoring exceptions

The system invents a plausible result for the operation and returns that. For example, the square root of a negative number can produce a NaN, and trying to compute a value too big to fit in the format can produce infinity. If an exception occurs and is ignored, a flag is set in the floating-point status word to tell you that something went wrong at some point in the past.

Trapping exceptions

This means that when an exception occurs, a piece of code called a trap handler is run. The system provides a default trap handler, that prints an error message and terminates the application. However, you can supply your own trap handlers, that can clean up the exceptional condition in whatever way you choose. Trap handlers can even supply a result to be returned from the operation.

For example, if you had an algorithm where it was convenient to assume that 0 divided by 0 was 1, you could supply a custom trap handler for the Invalid Operation exception, that spotted that particular case and substituted the answer you wanted.

Types of exception

The ARM floating-point environment recognizes five different types of exception:

  • The Invalid Operation exception happens when there is no sensible result for an operation. This can happen for any of the following reasons:

    • performing any operation on a signalling NaN, except the simplest operations (copying and changing the sign)

    • adding plus infinity to minus infinity, or subtracting an infinity from itself

    • multiplying infinity by zero

    • dividing 0 by 0, or dividing infinity by infinity

    • taking the remainder from dividing anything by 0, or infinity by anything

    • taking the square root of a negative number (not including minus zero)

    • converting a floating-point number to an integer if the result does not fit

    • comparing two numbers if one of them is a NaN.

  • If the Invalid Operation exception is not trapped, all the above operations return a quiet NaN, except for conversion to an integer, which returns zero (as there are no quiet NaNs in integers).

  • The Divide by Zero exception happens if you divide a finite nonzero number by zero. (Dividing zero by zero gives an Invalid Operation exception. Dividing infinity by zero is valid and returns infinity.) If Divide by Zero is not trapped, the operation returns infinity.

  • The Overflow exception happens when the result of an operation is too big to fit into the format. This happens, for example, if you add the largest representable number (marked d in Table 5.12) to itself. If Overflow is not trapped, the operation returns infinity, or the largest finite number, depending on the rounding mode.

  • The Underflow exception can happen when the result of an operation is too small to be represented as a normalized number (with Exp at least 1). The situations that cause

    Underflow depends on whether it is trapped or not:

    • If Underflow is trapped, it occurs whenever a result is too small to be represented as a normalized number.

    • If Underflow is not trapped, it only occurs if the result actually loses accuracy because it is so small. So, for example, dividing the float number 0x00800000 by 2 does not signal Underflow, because the result (0x00400000) is still as accurate as it would be if Exp had a greater range. However, trying to multiply the float number 0x00000001 by 1.5 does signal Underflow.

      (For readers familiar with the IEEE 754 specification, the ARM choice of implementation options are to detect tininess after rounding, and to detect loss of accuracy as a denormalization loss.)

      If Underflow is not trapped, the result is rounded to one of the two nearest representable denormal numbers, according to the current rounding mode. The loss of precision is ignored and the system returns the best result it can.

    • The Inexact Result exception happens whenever the result of an operation requires rounding. This would cause significant loss of speed if it had to be detected on every operation in software, so the ordinary floating-point libraries do not support the Inexact Result exception. The enhanced floating-point libraries, and hardware floating-point systems, all support Inexact Result.

      If Inexact Result is not trapped, the system rounds the result in the usual way.

      The flag for Inexact Result is also set by Overflow and Underflow if either one of those is not trapped.

All exceptions are untrapped by default.

Copyright © 1999-2001 ARM Limited. All rights reserved.ARM DUI 0067D