packages feed

aern2-mp-0.2.2.0: src/AERN2/MP/Ball/Comparisons.hs

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

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

    Comparisons of arbitrary precision dyadic balls
-}
module AERN2.MP.Ball.Comparisons
(
  -- * Auxiliary types
  module AERN2.Norm
  -- * Ball operations (see also instances)
  , reducePrecionIfInaccurate
  -- * Helpers for constructing ball functions
  , byEndpointsMP
  -- * intersection and hull
  , intersectCNMPBall
  , hullMPBall
)
where

import MixedTypesNumPrelude
-- import qualified Prelude as P

import qualified Control.CollectErrors as CE
import Control.CollectErrors
    ( CollectErrors(getMaybeValue), CanBeErrors )
import qualified Numeric.CollectErrors as CN

import AERN2.Kleenean
import AERN2.Norm
import AERN2.MP.Dyadic (Dyadic)
import AERN2.MP.Float (MPFloat)
-- import AERN2.MP.Float.Operators
import AERN2.MP.Precision

import AERN2.MP.Ball.Type
import AERN2.MP.Ball.Conversions ()

{- comparisons -}

instance HasEqAsymmetric MPBall MPBall where
  type EqCompareType MPBall MPBall = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2

instance HasEqAsymmetric MPBall Integer where
  type EqCompareType MPBall Integer = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2
instance HasEqAsymmetric Integer MPBall where
  type EqCompareType Integer MPBall = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2

instance HasEqAsymmetric MPBall Int where
  type EqCompareType MPBall Int = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2
instance HasEqAsymmetric Int MPBall where
  type EqCompareType Int MPBall = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2

instance HasEqAsymmetric MPBall Rational where
  type EqCompareType MPBall Rational = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2
instance HasEqAsymmetric Rational MPBall where
  type EqCompareType Rational MPBall = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2

instance HasEqAsymmetric MPBall Dyadic where
  type EqCompareType MPBall Dyadic = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2
instance HasEqAsymmetric Dyadic MPBall where
  type EqCompareType Dyadic MPBall = Kleenean
  b1 `equalTo` b2 =   b1 >= b2 && b1 <= b2

instance
  (HasEqAsymmetric MPBall b
  , IsBool (EqCompareType MPBall b)
  , CanBeErrors es)
  =>
  HasEqAsymmetric MPBall (CollectErrors es b)
  where
  type EqCompareType MPBall (CollectErrors es b) =
    CollectErrors es (EqCompareType MPBall b)
  equalTo = CE.liftT1 equalTo

instance
  (HasEqAsymmetric a MPBall
  , IsBool (EqCompareType a MPBall)
  , CanBeErrors es)
  =>
  HasEqAsymmetric (CollectErrors es a) MPBall
  where
  type EqCompareType (CollectErrors es a) MPBall =
    CollectErrors es (EqCompareType a MPBall)
  equalTo = CE.lift1T equalTo

instance HasOrderAsymmetric MPBall MPBall where
  type OrderCompareType MPBall MPBall = Kleenean
  lessThan b1 b2
    | r1 < l2 = CertainTrue
    | r2 <= l1 = CertainFalse
    | otherwise = TrueOrFalse
    where
    (l1, r1) = endpoints b1
    (l2, r2) = endpoints b2
  leq b1 b2
    | r1 <= l2 = CertainTrue
    | r2 < l1 = CertainFalse
    | otherwise = TrueOrFalse
    where
    (l1, r1) = endpoints b1
    (l2, r2) = endpoints b2

instance HasOrderAsymmetric Integer MPBall where
  type OrderCompareType Integer MPBall = Kleenean
  lessThan = convertFirst lessThan
  leq = convertFirst leq
instance HasOrderAsymmetric MPBall Integer where
  type OrderCompareType MPBall Integer = Kleenean
  lessThan = convertSecond lessThan
  leq = convertSecond leq

instance HasOrderAsymmetric Int MPBall where
  type OrderCompareType Int MPBall = Kleenean
  lessThan = convertFirst lessThan
  leq = convertFirst leq
instance HasOrderAsymmetric MPBall Int where
  type OrderCompareType MPBall Int = Kleenean
  lessThan = convertSecond lessThan
  leq = convertSecond leq

instance HasOrderAsymmetric Dyadic MPBall where
  type OrderCompareType Dyadic MPBall = Kleenean
  lessThan = convertFirst lessThan
  leq = convertFirst leq
instance HasOrderAsymmetric MPBall Dyadic where
  type OrderCompareType MPBall Dyadic = Kleenean
  lessThan = convertSecond lessThan
  leq = convertSecond leq

instance HasOrderAsymmetric MPBall Rational where
  type OrderCompareType MPBall Rational = Kleenean
  lessThan b1 q2
    | r1 < l2 = CertainTrue
    | r2 <= l1 = CertainFalse
    | otherwise = TrueOrFalse
    where
    (l1, r1) = endpoints b1
    l2 = q2
    r2 = q2
  leq b1 q2
    | r1 <= l2 = CertainTrue
    | r2 < l1 = CertainFalse
    | otherwise = TrueOrFalse
    where
    (l1, r1) = endpoints b1
    l2 = q2
    r2 = q2

instance HasOrderAsymmetric Rational MPBall where
  type OrderCompareType Rational MPBall = Kleenean
  lessThan q1 b2
    | r1 < l2 = CertainTrue
    | r2 <= l1 = CertainFalse
    | otherwise = TrueOrFalse
    where
    (l2, r2) = endpoints b2
    l1 = q1
    r1 = q1
  leq q1 b2
    | r1 <= l2 = CertainTrue
    | r2 < l1 = CertainFalse
    | otherwise = TrueOrFalse
    where
    (l2, r2) = endpoints b2
    l1 = q1
    r1 = q1

instance
  (HasOrderAsymmetric MPBall b
  , IsBool (OrderCompareType MPBall b)
  , CanBeErrors es)
  =>
  HasOrderAsymmetric MPBall (CollectErrors es  b)
  where
  type OrderCompareType MPBall (CollectErrors es  b) =
    CollectErrors es (OrderCompareType MPBall b)
  lessThan = CE.liftT1 lessThan
  leq = CE.liftT1 leq
  greaterThan = CE.liftT1 greaterThan
  geq = CE.liftT1 geq

instance
  (HasOrderAsymmetric a MPBall
  , IsBool (OrderCompareType a MPBall)
  , CanBeErrors es)
  =>
  HasOrderAsymmetric (CollectErrors es a) MPBall
  where
  type OrderCompareType (CollectErrors es  a) MPBall =
    CollectErrors es (OrderCompareType a MPBall)
  lessThan = CE.lift1T lessThan
  leq = CE.lift1T leq
  greaterThan = CE.lift1T greaterThan
  geq = CE.lift1T geq

instance CanTestZero MPBall
instance CanTestPosNeg MPBall

instance CanTestInteger MPBall where
  certainlyNotInteger b =
    (rN - lN) == 1 && lN !<! b && b !<! rN
    where
      (lN, rN) = integerBounds b
  certainlyIntegerGetIt b
    | rN == lN = Just lN
    | otherwise = Nothing
    where
      (lN, rN) = integerBounds b

instance CanMinMaxAsymmetric MPBall MPBall where
  min = byEndpointsMP min
  max = byEndpointsMP max

instance CanMinMaxAsymmetric MPBall Integer where
  type MinMaxType MPBall Integer = MPBall
  min = convertSecond min
  max = convertSecond max
instance CanMinMaxAsymmetric Integer MPBall where
  type MinMaxType Integer MPBall = MPBall
  min = convertFirst min
  max = convertFirst max

instance CanMinMaxAsymmetric MPBall Int where
  type MinMaxType MPBall Int = MPBall
  min = convertSecond min
  max = convertSecond max
instance CanMinMaxAsymmetric Int MPBall where
  type MinMaxType Int MPBall = MPBall
  min = convertFirst min
  max = convertFirst max

instance CanMinMaxAsymmetric MPBall Dyadic where
  type MinMaxType MPBall Dyadic = MPBall
  min = convertSecond min
  max = convertSecond max
instance CanMinMaxAsymmetric Dyadic MPBall where
  type MinMaxType Dyadic MPBall = MPBall
  min = convertFirst min
  max = convertFirst max

instance CanMinMaxAsymmetric MPBall Rational where
  type MinMaxType MPBall Rational = MPBall
  min = convertPSecond min
  max = convertPSecond max
instance CanMinMaxAsymmetric Rational MPBall where
  type MinMaxType Rational MPBall = MPBall
  min = convertPFirst min
  max = convertPFirst max

instance
  (CanMinMaxAsymmetric MPBall b
  , CanBeErrors es)
  =>
  CanMinMaxAsymmetric MPBall (CollectErrors es  b)
  where
  type MinMaxType MPBall (CollectErrors es  b) =
    CollectErrors es (MinMaxType MPBall b)
  min = CE.liftT1 min
  max = CE.liftT1 max

instance
  (CanMinMaxAsymmetric a MPBall
  , CanBeErrors es)
  =>
  CanMinMaxAsymmetric (CollectErrors es a) MPBall
  where
  type MinMaxType (CollectErrors es  a) MPBall =
    CollectErrors es (MinMaxType a MPBall)
  min = CE.lift1T min
  max = CE.lift1T max

{- intersection -}

instance CanIntersectAsymmetric MPBall MPBall where
  intersect a b
    | l > r =
        CN.noValueNumErrorCertain $ CN.NumError $ "intersect: empty intersection: " ++ show a ++ "; " ++ show b
    | otherwise = cn $ setPrecision p $ fromMPFloatEndpoints l r
    where
    p  = getPrecision a
    l = max aL bL
    r = min aR bR
    (aL,aR) = endpoints a
    (bL,bR) = endpoints b

intersectCNMPBall :: CN MPBall -> CN MPBall -> CN MPBall
intersectCNMPBall = intersect
  -- case (fst $ ensureNoCN x, fst $ ensureNoCN y) of 
  --   (Nothing, Nothing) -> x
  --   (Just _ , Nothing) -> x
  --   (Nothing, Just _ ) -> y
  --   (Just _ , Just _ ) -> lift2CE intersect x y

instance
  (CanIntersectAsymmetric MPBall b
  , CanBeErrors es)
  =>
  CanIntersectAsymmetric MPBall (CollectErrors es b)
  where
  type IntersectionType MPBall (CollectErrors es b) =
    CollectErrors es (IntersectionType MPBall b)
  intersect = CE.liftT1 intersect

instance
  (CanIntersectAsymmetric a MPBall
  , CanBeErrors es)
  =>
  CanIntersectAsymmetric (CollectErrors es a) MPBall
  where
  type IntersectionType (CollectErrors es  a) MPBall =
    CollectErrors es (IntersectionType a MPBall)
  intersect = CE.lift1T intersect

{- hull -}

hullMPBall :: MPBall -> MPBall -> MPBall
hullMPBall a b = 
  fromEndpoints rL rR
  where
  rL = min aL bL
  rR = max aR bR
  (aL,aR) = endpoints a
  (bL,bR) = endpoints b

{- union -}

instance CanUnionAsymmetric MPBall MPBall where
  union a b =
    case getMaybeValue (a `intersect` b) of
      Just _ -> r
      _ -> CN.prependErrorCertain err r
    where
    err = CN.NumError $ "union of enclosures: not enclosing the same value"
    r = cn $ hullMPBall a b

instance
  (CanUnionAsymmetric MPBall b
  , CanBeErrors es)
  =>
  CanUnionAsymmetric MPBall (CollectErrors es b)
  where
  type UnionType MPBall (CollectErrors es b) =
    CollectErrors es (UnionType MPBall b)
  union = CE.liftT1 union

instance
  (CanUnionAsymmetric a MPBall
  , CanBeErrors es)
  =>
  CanUnionAsymmetric (CollectErrors es a) MPBall
  where
  type UnionType (CollectErrors es  a) MPBall =
    CollectErrors es (UnionType a MPBall)
  union = CE.lift1T union

{-|
  Compute an MPBall function from *exact* MPFloat operations on interval endpoints.
  This works only for *non-decreasing* operations, eg addition, min, max.
-}
byEndpointsMP ::
    (MPFloat -> MPFloat -> MPFloat) ->
    (MPBall -> MPBall -> MPBall)
byEndpointsMP op b1 b2 =
    fromEndpoints (l1 `op` l2) (r1 `op` r2)
    where
    (l1,r1) = endpoints b1
    (l2,r2) = endpoints b2