aern2-mp-0.1.3.0: src/AERN2/MP/Float/UseRounded/Arithmetic.hs
{-|
Module : AERN2.MP.Float.UseRounded.Arithmetic
Description : Arbitrary precision floating point numbers
Copyright : (c) Michal Konecny
License : BSD3
Maintainer : mikkonecny@gmail.com
Stability : experimental
Portability : portable
Arbitrary precision floating-point numbers with up/down-rounded operations.
Currently, we use hmpfr when compiling with ghc 7.10 and higher
and haskell-mpfr when compiling with ghc 7.8.
-}
module AERN2.MP.Float.UseRounded.Arithmetic
(
-- * MPFloat basic arithmetic
addUp, addDown, subUp, subDown
, mulUp, mulDown, divUp, divDown, recipUp, recipDown
-- * MPFloat selected constants and operations
, piUp, piDown
, cosUp, cosDown, sinUp, sinDown
, sqrtUp, sqrtDown, expUp, expDown, logUp, logDown
)
where
import MixedTypesNumPrelude
import qualified Prelude as P
import AERN2.MP.Precision
import qualified AERN2.MP.Float.UseRounded.RoundedAdaptor as MPLow
import AERN2.MP.Float.UseRounded.Type
one :: MPFloat
one = MPLow.one
{- common functions -}
instance CanNeg MPFloat where
negate = unaryUp MPLow.neg
instance CanAbs MPFloat where
abs x
| x P.< MPLow.zero = negate x
| otherwise = x
addUp, addDown :: MPFloat -> MPFloat -> MPFloat
addUp = binaryUp True MPLow.add
addDown = binaryDown True MPLow.add
subUp, subDown :: MPFloat -> MPFloat -> MPFloat
subUp = binaryUp True MPLow.sub
subDown = binaryDown True MPLow.sub
mulUp, mulDown :: MPFloat -> MPFloat -> MPFloat
mulUp = binaryUp True MPLow.mul
mulDown = binaryDown True MPLow.mul
divUp,divDown :: MPFloat -> MPFloat -> MPFloat
divUp = binaryUp False MPLow.div
divDown = binaryDown False MPLow.div
recipUp :: MPFloat -> MPFloat
recipUp x = divUp one x
recipDown :: MPFloat -> MPFloat
recipDown x = divDown one x
{- special constants and functions -}
piUp :: Precision -> MPFloat
piUp p =
MPLow.pi MPLow.Up (p2mpfrPrec p)
piDown :: Precision -> MPFloat
piDown p =
MPLow.pi MPLow.Down (p2mpfrPrec p)
cosUp :: MPFloat -> MPFloat
cosUp = unaryUp MPLow.cos
cosDown :: MPFloat -> MPFloat
cosDown = unaryDown MPLow.cos
sinUp :: MPFloat -> MPFloat
sinUp = unaryUp MPLow.sin
sinDown :: MPFloat -> MPFloat
sinDown = unaryDown MPLow.sin
sqrtUp :: MPFloat -> MPFloat
sqrtUp = unaryUp MPLow.sqrt
sqrtDown :: MPFloat -> MPFloat
sqrtDown = unaryDown MPLow.sqrt
expUp :: MPFloat -> MPFloat
expUp = unaryUp MPLow.exp
expDown :: MPFloat -> MPFloat
expDown = unaryDown MPLow.exp
logUp :: MPFloat -> MPFloat
logUp = unaryUp MPLow.log
logDown :: MPFloat -> MPFloat
logDown = unaryDown MPLow.log
{- auxiliary functions to automatically determine result precision from operand precisions -}
unaryUp ::
(MPLow.RoundMode -> MPLow.Precision -> MPFloat -> MPFloat) ->
(MPFloat -> MPFloat)
unaryUp opRP x = opRP MPLow.Up p x
where
p = MPLow.getPrec x
unaryDown ::
(MPLow.RoundMode -> MPLow.Precision -> MPFloat -> MPFloat) ->
(MPFloat -> MPFloat)
unaryDown opRP x = opRP MPLow.Down p x
where
p = MPLow.getPrec x
binaryUp ::
Bool ->
(MPLow.RoundMode -> MPLow.Precision -> MPFloat -> MPFloat -> MPFloat) ->
(MPFloat -> MPFloat -> MPFloat)
binaryUp = binaryApprox True
binaryDown ::
Bool ->
(MPLow.RoundMode -> MPLow.Precision -> MPFloat -> MPFloat -> MPFloat) ->
(MPFloat -> MPFloat -> MPFloat)
binaryDown = binaryApprox False
binaryApprox ::
Bool -> Bool ->
(MPLow.RoundMode -> MPLow.Precision -> MPFloat -> MPFloat -> MPFloat) ->
(MPFloat -> MPFloat -> MPFloat)
binaryApprox isUp _canBeExact opRP x y =
withPrec pMax
where
pMax = (getPrecision x) `max` (getPrecision y)
withPrec p
| isUp = opRP MPLow.Up (p2mpfrPrec p) x y
| otherwise = opRP MPLow.Down (p2mpfrPrec p) x y