altfloat-0.3: Alternative floating point support for GHC.




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 fenvEval. See 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.



Data types

data FEnvState Source

Opaque type which stores the complete floating point environment. It corresponds to the C type fenv_t.


data FEnv a Source

Container for computations which will be run in a modified floating point environment. The FEnv container records all operations for later evaluation by fenvEval. Note that pure is strict in order to force evaluation of floating point values stored in the container.

Do not use the Eq or Show instances, they are provided only because Num requires them.


Functor FEnv 
Applicative FEnv 
Eq a => Eq (FEnv a) 
Fractional a => Fractional (FEnv a) 
Num a => Num (FEnv a) 
Show a => Show (FEnv a) 
RealFloat a => RealFloat (FEnv a) 
Floating a => Floating (FEnv a) 

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 fmap.

fenvEval :: FEnv a -> IO (a, [FloatException])Source

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.

withRoundingMode :: RoundingMode -> FEnv a -> FEnv aSource

Evaluate an FEnv using a specific rounding mode. Rounding mode selections nest: subcomputations might use another mode. The default rounding mode is unspecified.

raiseExceptions :: [FloatException] -> FEnv a -> FEnv aSource

Raise floating point exceptions as part of an FEnv computation.

fenvTrace :: String -> a -> FEnv aSource

This function is to help with debugging the floating point environment handling. fenvTrace msg x constructs an FEnv value containing x that prints msg (using 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.

unsafeSaveEnvironment :: Bool -> IO FEnvStateSource

Saves the current floating point environment and, optionally, clears all floating point exception flags and sets non-stop (continue on exceptions) mode.

unsafeRestoreEnvironment :: FEnvState -> IO [FloatException]Source

Restores a previously-saved floating point environment and returns the list of floating point exceptions that occurred prior to restoring the environment.

unsafeRaiseExceptions :: [FloatException] -> IO ()Source

Raises the given floating point exceptions.