Next: , Previous: , Up: Fixnum and Flonum Operations   [Contents][Index]


4.8.4 Floating-Point Exceptions

In IEEE 754-2008, floating-point operations such as arithmetic may raise exceptions. This sets a flag in the floating-point environment that is maintained until it is cleared. Many machines can also be configured to trap on exceptions, which in Scheme leads to signalling a condition. (Not all CPUs support trapping exceptions — for example, most ARMv8 CPUs do not.) In the default environment, no exceptions are trapped.

Floating-point exceptions and sets of floating-point exceptions are represented by small integers, whose interpretation is machine-dependent — for example, the invalid-operation exception may be represented differently on PowerPC and AMD x86-64 CPUs. The number for a floating-point exception is the same as the number for a set of exceptions containing only that one; the bitwise-AND of two sets is their intersection, the bitwise-IOR is their union, etc. The procedures flo:exceptions->names and flo:names->exceptions convert between machine-dependent integer representations and machine-independent lists of human-readable symbols.

The following exceptions are recognized by MIT/GNU Scheme:

inexact-result

Raised when the result of a floating-point computation is not a floating-point number and therefore must be rounded.

The inexact-result exception is never trappable in MIT/GNU Scheme.

underflow

Raised when the result of a floating-point computation is too small in magnitude to be represented by a normal floating-point number, and is therefore rounded to a subnormal or zero.

overflow

Raised when the result of a floating-point computation is too large in magnitude to be represented by a floating-point number, and is therefore rounded to infinity.

divide-by-zero

Raised on division of a nonzero finite real number by a zero real number, or logarithm of zero, or other operation that has an unbounded limit at a point like division by a divisor approaching zero.

invalid-operation

Raised when the input to a floating-point computation is nonsensical, such as division of zero by zero, or real logarithm of a negative number. The result of an invalid-operation is a NaN. Also raised when the input to a floating-point operation is a signalling NaN, but not for a quiet NaN.

subnormal-operand

Raised when an operand in a floating-point operation is subnormal.

(This is not a standard IEEE 754-2008 exception. It is supported by Intel CPUs.)

procedure: flo:supported-exceptions

Returns the set of exceptions that are supported on the current machine.

procedure: flo:trappable-exceptions

Returns the set of exceptions that can be trapped on the current machine. This is usually the same as the supported exceptions, except for inexact-result, which is never trappable in MIT/GNU Scheme.

procedure: flo:exception:divide-by-zero
procedure: flo:exception:inexact-result
procedure: flo:exception:invalid-operation
procedure: flo:exception:overflow
procedure: flo:exception:subnormal-operand
procedure: flo:exception:underflow

Returns the specified floating-point exception number. On machines that do not support a particular exception, the corresponding procedure simply returns 0.

procedure: flo:exceptions->names excepts
procedure: flo:names->exceptions list

These procedures convert between a machine-dependent small integer representation of a set of exceptions, and a representation of a set of exceptions by a list of human-readable symbols naming them.

(flo:preserving-environment
 (lambda ()
   (flo:clear-exceptions! (flo:supported-exceptions))
   (flo:/ (identity-procedure 1.) 0.)
   (flo:exceptions->names
    (flo:test-exceptions (flo:supported-exceptions)))))
                               ⇒  (divide-by-zero)
procedure: flo:test-exceptions excepts

Returns the set of exceptions in excepts that are currently raised.

In the default environment, the result is indeterminate, and may be affected by floating-point operations in other threads.

procedure: flo:clear-exceptions! excepts
procedure: flo:raise-exceptions! excepts

Clears or raises the exceptions in excepts, entering a per-thread environment. Other exceptions are unaffected.

procedure: flo:save-exception-flags
procedure: flo:restore-exception-flags! exceptflags
procedure: flo:test-exception-flags exceptflags excepts

Flo:save-exception-flags returns a machine-dependent representation of the currently trapped and raised exceptions. Flo:restore-exception-flags! restores it, entering a per-thread environment. Flo:test-exception-flags returns the set of exceptions in excepts that are raised in exceptflags.

Exceptflags is not the same as a set of exceptions. It is opaque and machine-dependent and should not be used except with flo:restore-exception-flags! and flo:test-exception-flags.

Bug: Flo:test-exception-flags is unimplemented.

procedure: flo:have-trap-enable/disable?

Returns true if trapping floating-point exceptions is supported on this machine.

procedure: flo:default-trapped-exceptions

Returns the set of exceptions that are trapped in the default floating-point environment. Equivalent to (flo:names->exceptions '()), or simply 0, since by default, no exceptions are trapped.

procedure: flo:trapped-exceptions

Returns the set of exceptions that are currently trapped.

procedure: flo:trap-exceptions! excepts
procedure: flo:untrap-exceptions! excepts
procedure: flo:set-trapped-exceptions! excepts

Flo:trap-exceptions! requests that any exceptions in the set excepts be trapped, in addition to all of the ones that are currently trapped. Flo:untrap-exceptions! requests that any exceptions in the set excepts not be trapped. Flo:set-trapped-exceptions! replaces the set of trapped exceptions altogether by excepts. All three procedures enter a per-thread environment.

(define (flo:trap-exceptions! excepts)
  (flo:set-trapped-exceptions!
   (fix:or (flo:trapped-exceptions) excepts)))

(define (flo:untrap-exceptions! excepts)
  (flo:set-trapped-exceptions!
   (fix:andc (flo:trapped-exceptions) excepts)))

(define (flo:set-trapped-exceptions! excepts)
  (flo:trap-exceptions! excepts)
  (flo:untrap-exceptions!
   (fix:andc (flo:supported-exceptions) excepts)))
procedure: flo:with-exceptions-trapped excepts thunk
procedure: flo:with-exceptions-untrapped excepts thunk
procedure: flo:with-trapped-exceptions excepts thunk

Dynamic-extent analogues of flo:trap-exceptions!, flo:untrap-exceptions!, and flo:set-trapped-exceptions!. These call thunk with their respective changes to the set of trapped exceptions in a per-thread environment, and restore the environment on return or non-local exit.

procedure: flo:defer-exception-traps!

Saves the current floating-point environment, clears all raised exceptions, disables all exception traps, and returns a descriptor for the saved floating-point environment.

Flo:defer-exception-traps! is typically used together with flo:update-environment!, to trap any exceptions that the caller had wanted trapped only after a long intermediate computation. This pattern is captured in flo:deferring-exception-traps.

procedure: flo:deferring-exception-traps thunk

Calls thunk, but defers trapping on any exceptions it raises until it returns. Equivalent to:

(flo:preserving-environment
 (lambda ()
   (let ((environment (flo:defer-exception-traps!)))
     (begin0 (thunk)
       (flo:update-environment! environment)))))
procedure: flo:ignoring-exception-traps thunk

Calls thunk with all exceptions untrapped and unraised. Equivalent to:

(flo:preserving-environment
 (lambda ()
   (flo:defer-exception-traps!)
   (thunk)))

Next: Floating-Point Rounding Mode, Previous: Floating-Point Environment, Up: Fixnum and Flonum Operations   [Contents][Index]