{-# OPTIONS_GHC -Wno-orphans #-}
{-|
    Module      :  AERN2.MP.Ball.Conversions
    Description :  Conversions of arbitrary precision dyadic balls
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable

    Conversions of arbitrary precision dyadic balls
-}
module AERN2.MP.Ball.Conversions
(
  integerBounds
)
where

import MixedTypesNumPrelude
-- import qualified Prelude as P

-- import qualified Numeric.CollectErrors as CN

import Data.Typeable
-- import Data.Convertible

import AERN2.MP.Dyadic (Dyadic, dyadic)
import qualified AERN2.MP.Float as MPFloat
import AERN2.MP.Float (MPFloat, mpFloat)
-- import AERN2.MP.Float.Operators
import AERN2.MP.Precision
-- import qualified AERN2.MP.ErrorBound as EB
-- import qualified AERN2.MP.ErrorBound as EB
import AERN2.MP.ErrorBound (ErrorBound, errorBound, CanBeErrorBound)

import AERN2.MP.Ball.Type

{--- extracting from a ball ---}

instance HasIntegerBounds MPBall where
  integerBounds :: MPBall -> (Integer, Integer)
integerBounds MPBall
b =
    (MPFloat -> RoundType MPFloat
forall t. CanRound t => t -> RoundType t
floor MPFloat
l, MPFloat -> RoundType MPFloat
forall t. CanRound t => t -> RoundType t
ceiling MPFloat
r)
    where
      (MPFloat
l,MPFloat
r) = MPBall -> (IntervalEndpoint MPBall, IntervalEndpoint MPBall)
forall i.
IsInterval i =>
i -> (IntervalEndpoint i, IntervalEndpoint i)
endpoints MPBall
b

instance Convertible MPBall ErrorBound where
  safeConvert :: MPBall -> ConvertResult ErrorBound
safeConvert MPBall
b =
    ErrorBound -> ConvertResult ErrorBound
forall a b. b -> Either a b
Right (MPFloat -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound (MPFloat -> MPFloat -> MinMaxType MPFloat MPFloat
forall t1 t2.
CanMinMaxAsymmetric t1 t2 =>
t1 -> t2 -> MinMaxType t1 t2
max (MPFloat -> AbsType MPFloat
forall t. CanAbs t => t -> AbsType t
abs MPFloat
l) (MPFloat -> AbsType MPFloat
forall t. CanAbs t => t -> AbsType t
abs MPFloat
r)))
    where
    (MPFloat
l,MPFloat
r) = MPBall -> (IntervalEndpoint MPBall, IntervalEndpoint MPBall)
forall i.
IsInterval i =>
i -> (IntervalEndpoint i, IntervalEndpoint i)
endpoints MPBall
b

{--- constructing an exact ball ---}

instance ConvertibleExactly MPBall MPBall where
  safeConvertExactly :: MPBall -> ConvertResult MPBall
safeConvertExactly = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right

instance ConvertibleExactly Dyadic MPBall where
  safeConvertExactly :: Dyadic -> ConvertResult MPBall
safeConvertExactly Dyadic
x = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right (MPBall -> ConvertResult MPBall) -> MPBall -> ConvertResult MPBall
forall a b. (a -> b) -> a -> b
$ MPFloat -> ErrorBound -> MPBall
MPBall (Dyadic -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat Dyadic
x) (Integer -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound Integer
0)

instance ConvertibleExactly ErrorBound MPBall where
  safeConvertExactly :: ErrorBound -> ConvertResult MPBall
safeConvertExactly ErrorBound
eb = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right (MPBall -> ConvertResult MPBall) -> MPBall -> ConvertResult MPBall
forall a b. (a -> b) -> a -> b
$ MPFloat -> ErrorBound -> MPBall
MPBall (ErrorBound -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat ErrorBound
eb) (Integer -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound Integer
0)

instance
  (ConvertibleExactly c Dyadic, ConvertibleExactly e Dyadic
  , Show c, Show e, Typeable c, Typeable e)
  =>
  ConvertibleExactly (c, e) MPBall
  where
  safeConvertExactly :: (c, e) -> ConvertResult MPBall
safeConvertExactly (c
c,e
e)
    | MPBall -> Bool
forall t. CanTestFinite t => t -> Bool
isFinite MPBall
b = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right MPBall
b
    | Bool
otherwise = String -> (c, e) -> ConvertResult MPBall
forall a b.
(Show a, Typeable a, Typeable b) =>
String -> a -> ConvertResult b
convError String
"too large to convert to MPBall" (c
c,e
e)
    where
    b :: MPBall
b = MPFloat -> ErrorBound -> MPBall
MPBall (Dyadic -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat (Dyadic -> MPFloat) -> Dyadic -> MPFloat
forall a b. (a -> b) -> a -> b
$ c -> Dyadic
forall t. CanBeDyadic t => t -> Dyadic
dyadic c
c) (MPFloat -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound (MPFloat -> ErrorBound) -> MPFloat -> ErrorBound
forall a b. (a -> b) -> a -> b
$ Dyadic -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat (Dyadic -> MPFloat) -> Dyadic -> MPFloat
forall a b. (a -> b) -> a -> b
$ e -> Dyadic
forall t. CanBeDyadic t => t -> Dyadic
dyadic e
e)

instance ConvertibleExactly Integer MPBall where
  safeConvertExactly :: Integer -> ConvertResult MPBall
safeConvertExactly Integer
x
    | MPBall -> Bool
forall t. CanTestFinite t => t -> Bool
isFinite MPBall
b = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right MPBall
b
    | Bool
otherwise = String -> Integer -> ConvertResult MPBall
forall a b.
(Show a, Typeable a, Typeable b) =>
String -> a -> ConvertResult b
convError String
"too large to convert to MPBall" Integer
x
    where
      b :: MPBall
b = MPFloat -> ErrorBound -> MPBall
MPBall (Integer -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat Integer
x) (Integer -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound Integer
0)

instance ConvertibleExactly Int MPBall where
  safeConvertExactly :: Int -> ConvertResult MPBall
safeConvertExactly Int
x = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right (MPBall -> ConvertResult MPBall) -> MPBall -> ConvertResult MPBall
forall a b. (a -> b) -> a -> b
$ MPFloat -> ErrorBound -> MPBall
MPBall (Int -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat Int
x) (Integer -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound Integer
0)

{--- constructing a ball with a given precision ---}

instance ConvertibleWithPrecision Integer MPBall where
  safeConvertP :: Precision -> Integer -> ConvertResult MPBall
safeConvertP Precision
p Integer
x
    | MPBall -> Bool
forall t. CanTestFinite t => t -> Bool
isFinite MPBall
b = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right MPBall
b
    | Bool
otherwise = String -> Integer -> ConvertResult MPBall
forall a b.
(Show a, Typeable a, Typeable b) =>
String -> a -> ConvertResult b
convError (String
"too large to convert to MPBall with precision " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Precision -> String
forall a. Show a => a -> String
show Precision
p) Integer
x
    where
    b :: MPBall
b = MPFloat -> ErrorBound -> MPBall
MPBall MPFloat
xC (MPFloat -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound MPFloat
xErr)
    (MPFloat
xC, MPFloat
xErr) = BoundsCEDU MPFloat -> (MPFloat, MPFloat)
forall a. BoundsCEDU a -> (a, a)
MPFloat.ceduCentreErr (BoundsCEDU MPFloat -> (MPFloat, MPFloat))
-> BoundsCEDU MPFloat -> (MPFloat, MPFloat)
forall a b. (a -> b) -> a -> b
$ Precision -> Integer -> BoundsCEDU MPFloat
MPFloat.fromIntegerCEDU Precision
p Integer
x

instance ConvertibleWithPrecision Int MPBall where
  safeConvertP :: Precision -> Int -> ConvertResult MPBall
safeConvertP Precision
p = Precision -> Integer -> ConvertResult MPBall
forall t1 t2.
ConvertibleWithPrecision t1 t2 =>
Precision -> t1 -> ConvertResult t2
safeConvertP Precision
p (Integer -> ConvertResult MPBall)
-> (Int -> Integer) -> Int -> ConvertResult MPBall
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer
forall t. CanBeInteger t => t -> Integer
integer

instance ConvertibleWithPrecision Dyadic MPBall where
  safeConvertP :: Precision -> Dyadic -> ConvertResult MPBall
safeConvertP Precision
p Dyadic
x
    | MPBall -> Bool
forall t. CanTestFinite t => t -> Bool
isFinite MPBall
b = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right MPBall
b
    | Bool
otherwise = String -> Dyadic -> ConvertResult MPBall
forall a b.
(Show a, Typeable a, Typeable b) =>
String -> a -> ConvertResult b
convError (String
"too large to convert to MPBall with precision " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Precision -> String
forall a. Show a => a -> String
show Precision
p) Dyadic
x
    where
    b :: MPBall
b = Dyadic -> MPBall
forall t. CanBeMPBall t => t -> MPBall
mpBall Dyadic
x

instance ConvertibleWithPrecision Rational MPBall where
  safeConvertP :: Precision -> Rational -> ConvertResult MPBall
safeConvertP Precision
p Rational
x
    | MPBall -> Bool
forall t. CanTestFinite t => t -> Bool
isFinite MPBall
b = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right MPBall
b
    | Bool
otherwise = String -> Rational -> ConvertResult MPBall
forall a b.
(Show a, Typeable a, Typeable b) =>
String -> a -> ConvertResult b
convError (String
"too large to convert to MPBall with precision " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Precision -> String
forall a. Show a => a -> String
show Precision
p) Rational
x
    where
    b :: MPBall
b = MPFloat -> ErrorBound -> MPBall
MPBall MPFloat
xC (MPFloat -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound MPFloat
xErr)
    (MPFloat
xC, MPFloat
xErr) = BoundsCEDU MPFloat -> (MPFloat, MPFloat)
forall a. BoundsCEDU a -> (a, a)
MPFloat.ceduCentreErr (BoundsCEDU MPFloat -> (MPFloat, MPFloat))
-> BoundsCEDU MPFloat -> (MPFloat, MPFloat)
forall a b. (a -> b) -> a -> b
$ Precision -> Rational -> BoundsCEDU MPFloat
MPFloat.fromRationalCEDU Precision
p Rational
x

instance ConvertibleWithPrecision (Rational, Rational) MPBall where
  safeConvertP :: Precision -> (Rational, Rational) -> ConvertResult MPBall
safeConvertP Precision
p (Rational
x,Rational
e)
    | MPBall -> Bool
forall t. CanTestFinite t => t -> Bool
isFinite MPBall
b = MPBall -> ConvertResult MPBall
forall a b. b -> Either a b
Right MPBall
b
    | Bool
otherwise = String -> Rational -> ConvertResult MPBall
forall a b.
(Show a, Typeable a, Typeable b) =>
String -> a -> ConvertResult b
convError (String
"too large to convert to MPBall with precision " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Precision -> String
forall a. Show a => a -> String
show Precision
p) Rational
x
    where
    b :: MPBall
b = MPFloat -> ErrorBound -> MPBall
MPBall MPFloat
xFlt (ErrorBound
xe ErrorBound -> ErrorBound -> AddType ErrorBound ErrorBound
forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ ErrorBound
eUp) -- beware, precision may be too high relative to accuracy
    (MPBall MPFloat
xFlt ErrorBound
xe) = Precision -> Rational -> MPBall
forall t. CanBeMPBallP t => Precision -> t -> MPBall
mpBallP Precision
p Rational
x
    eUp :: ErrorBound
eUp = Rational -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound Rational
e

{--- constructing a fat ball ---}

instance (CanBeErrorBound t) => CanPlusMinus MPBall t where
  plusMinus :: MPBall -> t -> PlusMinusType MPBall t
plusMinus MPBall
b t
e = (ErrorBound -> ErrorBound) -> MPBall -> MPBall
forall t. IsBall t => (ErrorBound -> ErrorBound) -> t -> t
updateRadius (ErrorBound -> ErrorBound -> AddType ErrorBound ErrorBound
forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ (t -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound t
e)) MPBall
b

instance (CanBeErrorBound t) => CanPlusMinus (CN MPBall) t where
  plusMinus :: CN MPBall -> t -> PlusMinusType (CN MPBall) t
plusMinus CN MPBall
b t
e = (ErrorBound -> ErrorBound) -> CN MPBall -> CN MPBall
forall t. IsBall t => (ErrorBound -> ErrorBound) -> t -> t
updateRadius (ErrorBound -> ErrorBound -> AddType ErrorBound ErrorBound
forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ (t -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound t
e)) CN MPBall
b

instance (CanBeErrorBound t) => CanPlusMinus MPFloat t where
  type PlusMinusType MPFloat t = MPBall
  plusMinus :: MPFloat -> t -> PlusMinusType MPFloat t
plusMinus MPFloat
b t
e = MPFloat -> ErrorBound -> MPBall
MPBall MPFloat
b (t -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound t
e)

instance (CanBeErrorBound t) => CanPlusMinus Dyadic t where
  type PlusMinusType Dyadic t = MPBall
  plusMinus :: Dyadic -> t -> PlusMinusType Dyadic t
plusMinus Dyadic
b t
e = MPFloat -> ErrorBound -> MPBall
MPBall (Dyadic -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat Dyadic
b) (t -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound t
e)

instance (CanBeErrorBound t) => CanPlusMinus Integer t where
  type PlusMinusType Integer t = MPBall
  plusMinus :: Integer -> t -> PlusMinusType Integer t
plusMinus Integer
b t
e = MPFloat -> ErrorBound -> MPBall
MPBall (Integer -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat Integer
b) (t -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound t
e)

instance (CanBeErrorBound t) => CanPlusMinus Int t where
  type PlusMinusType Int t = MPBall
  plusMinus :: Int -> t -> PlusMinusType Int t
plusMinus Int
b t
e = MPFloat -> ErrorBound -> MPBall
MPBall (Int -> MPFloat
forall t. CanBeMPFloat t => t -> MPFloat
mpFloat Int
b) (t -> ErrorBound
forall t. CanBeErrorBound t => t -> ErrorBound
errorBound t
e)

instance (CanBeErrorBound t) => CanPlusMinus Rational t where
  type PlusMinusType Rational t = MPBall
  plusMinus :: Rational -> t -> PlusMinusType Rational t
plusMinus Rational
b t
e = (Precision -> Rational -> MPBall
forall t. CanBeMPBallP t => Precision -> t -> MPBall
mpBallP Precision
p Rational
b) MPBall -> t -> PlusMinusType MPBall t
forall t1 t2. CanPlusMinus t1 t2 => t1 -> t2 -> PlusMinusType t1 t2
+- t
e
    where
    p :: Precision
p = Integer -> Precision
prec Integer
100