aern2-mp-0.1.4: src-rounded/AERN2/MP/Float/Conversions.hs
{-|
Module : AERN2.MP.Float.Conversions
Description : Conversions and comparisons of arbitrary precision floats
Copyright : (c) Michal Konecny
License : BSD3
Maintainer : mikkonecny@gmail.com
Stability : experimental
Portability : portable
Conversions and comparisons of arbitrary precision floating point numbers
-}
module AERN2.MP.Float.Conversions
(
-- * MPFloat to other types (see also instances)
toDouble
-- * MPFloat constructors (see also instances)
, CanBeMPFloat, mpFloat
, fromIntegerCEDU
, fromRationalCEDU
-- * comparisons and constants (see also instances)
, zero, one, two
, nan, infinity
)
where
import MixedTypesNumPrelude
import qualified Prelude as P
import Data.Ratio
import Data.Convertible
import AERN2.Norm
import AERN2.MP.Precision
import AERN2.MP.Float.Auxi
import AERN2.MP.Float.Type
import AERN2.MP.Float.Arithmetic
import qualified AERN2.MP.Float.RoundedAdaptor as MPLow
mpToDouble :: MPLow.RoundMode -> MPFloat -> Double
mpToDouble = MPLow.toDoubleA
mpToRational :: MPFloat -> Rational
mpToRational x
| x == 0 = 0.0
| otherwise = MPLow.toRationalA x
mpFromRationalA :: MPLow.RoundMode -> MPLow.Precision -> Rational -> MPFloat
mpFromRationalA = MPLow.fromRationalA
{- conversions to MPFloat -}
type CanBeMPFloat t = ConvertibleExactly t MPFloat
mpFloat :: (CanBeMPFloat t) => t -> MPFloat
mpFloat = convertExactly
instance ConvertibleExactly Integer MPFloat where
safeConvertExactly n =
findExact $ map (flip fromIntegerCEDU n) $ standardPrecisions initPrec
where
initPrec =
case getNormLog n of
NormBits b -> prec (b + 8)
_ -> prec 8
findExact [] =
convError "integer too high to represent exactly" n
findExact (cedu : rest)
| ceduErr cedu P.> zero = findExact rest
| otherwise = Right (ceduCentre cedu)
instance ConvertibleExactly Int MPFloat where
safeConvertExactly = safeConvertExactly . integer
fromIntegerCEDU :: Precision -> Integer -> BoundsCEDU MPFloat
fromIntegerCEDU pp n =
constCEDU (\r p -> MPLow.fromIntegerA r p n) (p2mpfrPrec pp)
fromRationalCEDU :: Precision -> Rational -> BoundsCEDU MPFloat
fromRationalCEDU pp q =
constCEDU (\r p -> mpFromRationalA r p q) (p2mpfrPrec pp)
{- conversions from MPFloat -}
instance ConvertibleExactly MPFloat Rational where
safeConvertExactly = Right . mpToRational
toDouble :: MPFloat -> Double
toDouble = mpToDouble MPLow.Up
instance Convertible MPFloat Double where
safeConvert x
| isFinite dbl = Right dbl
| otherwise = convError "conversion to double: out of bounds" x
where
dbl = toDouble x
instance CanRound MPFloat where
properFraction x = (n,f)
where
r = rational x
n = (numerator r) `P.quot` (denominator r)
f = ceduCentre $ x `subCEDU` (mpFloat n)
{- comparisons -}
instance HasEqAsymmetric MPFloat MPFloat
instance HasEqAsymmetric MPFloat Integer where
equalTo = convertSecond equalTo
instance HasEqAsymmetric Integer MPFloat where
equalTo = convertFirst equalTo
instance HasEqAsymmetric MPFloat Int where
equalTo = convertSecond equalTo
instance HasEqAsymmetric Int MPFloat where
equalTo = convertFirst equalTo
instance HasEqAsymmetric MPFloat Rational where
equalTo = convertFirst equalTo
instance HasEqAsymmetric Rational MPFloat where
equalTo = convertSecond equalTo
instance CanTestZero MPFloat
instance HasOrderAsymmetric MPFloat MPFloat
instance HasOrderAsymmetric MPFloat Integer where
lessThan = convertSecond lessThan
leq = convertSecond leq
instance HasOrderAsymmetric Integer MPFloat where
lessThan = convertFirst lessThan
leq = convertFirst leq
instance HasOrderAsymmetric MPFloat Int where
lessThan = convertSecond lessThan
leq = convertSecond leq
instance HasOrderAsymmetric Int MPFloat where
lessThan = convertFirst lessThan
leq = convertFirst leq
instance HasOrderAsymmetric Rational MPFloat where
lessThan = convertSecond lessThan
leq = convertSecond leq
instance HasOrderAsymmetric MPFloat Rational where
lessThan = convertFirst lessThan
leq = convertFirst leq
instance CanTestPosNeg MPFloat
{- min, max -}
instance CanMinMaxAsymmetric MPFloat MPFloat
{- constants -}
zero, one, two :: MPFloat
zero = MPLow.zero
one = MPLow.one
two = MPLow.add MPLow.Up (MPLow.getPrec one) one one
nan, infinity :: MPFloat
nan = ceduCentre $ divCEDU zero zero
infinity = ceduCentre $ divCEDU one zero
itisNaN :: MPFloat -> Bool
itisNaN x = not $ x P.== x
itisInfinite :: MPFloat -> Bool
itisInfinite x =
ceduCentre (mulCEDU x two) P.== x
&&
x P./= zero
instance CanTestFinite MPFloat where
isInfinite = itisInfinite
isFinite x = not (itisInfinite x || itisNaN x)
instance CanTestNaN MPFloat where
isNaN = itisNaN