@node Floating-Point Environment, Floating-Point Exceptions, Flonum Operations, Fixnum and Flonum Operations
@subsection Floating-Point Environment
+@cindex floating-point environment
The @acronym{IEEE 754-2008} computation model includes a persistent
-rounding mode and exception flags.
-In MIT/GNU Scheme, every thread has its own floating-point
-environment, initialized to the default @acronym{IEEE 754-2008}
-environment, with no exceptions trapped, with no exceptions raised,
-and with round-to-nearest/ties-to-even.
+rounding mode, exception flags, and exception-handling modes.
+In MIT/GNU Scheme, the floating-point environment is per-thread.
+However, because saving and restoring the floating-point environment
+is expensive, it is maintained only for those threads that have
+touched the floating-point environment explicitly, either:
+
+@itemize @bullet
+@item
+during a procedure such as @code{flo:with-exceptions-trapped} that
+establishes a change to the floating-point environment for a dynamic
+extent, or
+
+@item
+after @code{flo:set-environment!} to a non-default environment (but
+not after @code{flo:set-environment!} to the default environment), or
+
+@item
+after various other procedures such as @code{flo:clear-exceptions!}
+that explicitly change the floating-point environment.
+@end itemize
+
+@noindent
+@cindex floating-point environment, default
+@cindex default environment, floating-point
+The default environment is as in @acronym{IEEE 754-2008}: no
+exceptions are trapped, and rounding is to nearest with ties broken to
+even.
+The set of exception flags in the default environment is indeterminate
+--- callers must enter a per-thread environment, e.g. by calling
+@code{flo:clear-exceptions!}, before acting on the exception flags.
+Like the default environment, a per-thread environment initially has
+no exceptions trapped and rounds to nearest with ties to even.
-@cindex floating-point environment
A @strong{floating-point environment} descriptor is a
machine-dependent object representing the @acronym{IEEE 754-2008}
-floating-point exception flags, exception-handling mode (trap or no
-trap), and rounding mode.
+floating-point rounding mode, exception flags, and exception-handling
+mode.
Users should not inspect a floating-point environment descriptor other
than to use it with the procedures here; its representation may vary
from system to system.
@deffn procedure flo:default-environment
-Returns a descriptor for the default floating-point environment, with
-no exceptions trapped, no exceptions raised, and
-round-to-nearest/ties-to-even.
+Returns a descriptor for the default environment, with no exceptions
+trapped and round-to-nearest/ties-to-even.
@end deffn
@deffn procedure flo:environment
@end deffn
@deffn procedure flo:preserving-environment thunk
-Saves the current floating-point environment and calls @var{thunk}.
+Saves the current floating-point environment if any and calls
+@var{thunk}.
On exit from @var{thunk}, including non-local exit, saves
@var{thunk}'s floating-point environment and restores the original
floating-point environment as if with @code{flo:set-environment!}.
On re-entry into @var{thunk}, restores @var{thunk}'s floating-point
environment.
+
+@strong{Note:} @code{Flo:preserving-environment} @emph{does not} enter
+a per-thread environment.
+If the current thread is in the default environment, the exception
+flags are indeterminate, and remain so inside
+@code{flo:preserving-environment}.
+Callers interested in using the exception flags should start inside
+@code{flo:preserving-environment} by clearing them with
+@code{flo:clear-exceptions!}.
@end deffn
@node Floating-Point Exceptions, Floating-Point Rounding Mode, Floating-Point Environment, Fixnum and Flonum Operations
@subsection Floating-Point Exceptions
-Floating-point computations such as arithmetic may raise exceptions.
+In @acronym{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, and, if the exception is trapped, signals a
-Scheme condition.
-Most machines support trapping exceptions, but not all --- for
-example, most ARM CPUs do not.
-In the default floating-point environment, no exceptions are trapped
-and no exceptions are raised.
+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.
+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.
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.
+The inexact-result exception is never trappable in MIT/GNU Scheme.
@item underflow
@cindex underflow exception
@item divide-by-zero
@cindex divide-by-zero exception
Raised on division of a nonzero finite real number by a zero real
-number, or logarithm of zero.
+number, or logarithm of zero, or other operation that has an unbounded
+limit at a point like division by a divisor approaching zero.
@item invalid-operation
@cindex invalid-operation exception
@deffn procedure flo:test-exceptions excepts
Returns the set of exceptions in @var{excepts} that are currently
raised.
+
+In the default environment, the result is indeterminate, and may
+be affected by floating-point operations in other threads.
@end deffn
@deffn procedure flo:clear-exceptions! excepts
@deffnx procedure flo:raise-exceptions! excepts
-Clears and raises the exceptions in @var{excepts}.
+Clears or raises the exceptions in @var{excepts}, entering a
+per-thread environment.
Other exceptions are unaffected.
@end deffn
@deffnx procedure flo:test-exception-flags exceptflags excepts
@code{Flo:save-exception-flags} returns a machine-dependent
representation of the currently trapped and raised exceptions.
-@code{Flo:restore-exception-flags!} restores it.
+@code{Flo:restore-exception-flags!} restores it, entering a per-thread
+environment.
@code{Flo:test-exception-flags} returns the set of exceptions in
@var{excepts} that are raised in @var{exceptflags}.
@var{excepts} not be trapped.
@code{Flo:set-trapped-exceptions!} replaces the set of trapped
exceptions altogether by @var{excepts}.
+All three procedures enter a per-thread environment.
@example
@group
Dynamic-extent analogues of @code{flo:trap-exceptions!},
@code{flo:untrap-exceptions!}, and @code{flo:set-trapped-exceptions!}.
These call @var{thunk} with their respective changes to the set of
-trapped exceptions, and restore it on return or non-local exit.
+trapped exceptions in a per-thread environment, and restore the
+environment on return or non-local exit.
@end deffn
@deffn procedure flo:defer-exception-traps!
exceptions, disables all exception traps, and returns a descriptor for
the saved floating-point environment.
-This is typically used together with @code{flo:update-environment!},
-to trap any exceptions that the caller had wanted trapped only after a
-long intermediate computation.
+@code{Flo:defer-exception-traps!} is typically used together with
+@code{flo:update-environment!}, to trap any exceptions that the caller
+had wanted trapped only after a long intermediate computation.
This pattern is captured in @code{flo:deferring-exception-traps}.
@end deffn
@deffn procedure flo:rounding-mode
@deffnx procedure flo:set-rounding-mode! mode
-Gets or sets the current rounding mode as a symbol.
+Gets or sets the current rounding mode as a symbol, entering a
+per-thread environment.
@end deffn
@deffn procedure flo:with-rounding-mode mode thunk
-Call @var{thunk} with the rounding mode set to @var{mode}.
-On return, the rounding mode is restored to what it was before.
+Call @var{thunk} in a per-thread environment with the rounding mode
+set to @var{mode}.
+On return, the floating-point environment, including rounding mode, is
+restored to what it was before.
Non-local exit from and re-entrance to @var{thunk} behaves as if the
call is surrounded by @code{flo:preserving-environment}