Access to the floating point environment. Performing this access within a Haskell program turns out to be extremely problematic, because floating point operations are secretly impure. For example, the innocent-looking function
(+) :: Double -> Double -> Double
potentially both depends on and modifies the global floating point environment.
This module avoids the referential transparency problems that occur as a
result of accessing the floating point environment by restricting when
computations which access it are evaluated. There is some minor discipline
required of the programmer: she must arrange her code so that pure floating
point expressions are not forced during a call to
fenv-impure.hs in the
examples/ directory of the altfloat
distribution for why this discipline is necessary.
FEnv instances the numeric classes, so it should be possible to use natural syntax. Note that the operations done on FEnv are stored so that they can be performed later, thus one should be take care not to construct huge thunks when using this interface.
This interface has not been tested in multi-threaded programs. It might work: more info is needed about GHC's threading support.
- module Control.Applicative
- data RoundingMode
- data FloatException
- data FEnvState
- data FEnv a
- fenvEval :: FEnv a -> IO (a, [FloatException])
- withRoundingMode :: RoundingMode -> FEnv a -> FEnv a
- raiseExceptions :: [FloatException] -> FEnv a -> FEnv a
- fenvTrace :: String -> a -> FEnv a
- unsafeSaveEnvironment :: Bool -> IO FEnvState
- unsafeRestoreEnvironment :: FEnvState -> IO [FloatException]
- unsafeRaiseExceptions :: [FloatException] -> IO ()
- unsafeSetRoundingMode :: RoundingMode -> IO ()
- getRoundingMode :: IO RoundingMode
Opaque type which stores the complete floating point environment. It
corresponds to the C type
Container for computations which will be run in a modified floating point
environment. The FEnv container records all operations for later evaluation
fenvEval. Note that
pure is strict in order to force evaluation
of floating point values stored in the container.
Controlled access to the floating point environment
These functions can still break referential transparency, because it
is possible to arrange for a pure floating point expression to be forced
during the execution of
fenvEval. The easiest way to ensure that this
does not happen is to only use such expressions as the argument to
pure; never as the argument to
Runs all the computations which are recorded in an FEnv container. The floating point environment is preserved across this call, and any floating point exceptions which were raised during the computation are returned.
Evaluate an FEnv using a specific rounding mode. Rounding mode selections nest: subcomputations might use another mode. The default rounding mode is unspecified.
Raise floating point exceptions as part of an FEnv computation.
This function is to help with debugging the floating point environment
fenvTrace msg x constructs an FEnv value containing
trace) whenever the value is extracted.
Direct access to the floating point environment
Special care must be taken when using these functions. Modifying the floating point environment will affect all floating point computations that have not yet been evaluated.
Saves the current floating point environment and, optionally, clears all floating point exception flags and sets non-stop (continue on exceptions) mode.
Restores a previously-saved floating point environment and returns the list of floating point exceptions that occurred prior to restoring the environment.