aern2-fun-0.2.9.0: src/AERN2/Interval.hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}
{-|
Module : AERN2.Interval
Description : Intervals for use as function domains
Copyright : (c) Michal Konecny
License : BSD3
Maintainer : mikkonecny@gmail.com
Stability : experimental
Portability : portable
Intervals for use as function domains
-}
module AERN2.Interval
(
Interval(..), singleton
, width, split
, arbitraryNonEmptyInterval
, arbitraryNonEmptySmallInterval
, intersect, intersects
, DyadicInterval, CanBeDyadicInterval, dyadicInterval
, RealInterval, CanBeRealInterval, realInterval
)
where
import MixedTypesNumPrelude
-- import Numeric.CollectErrors (NumErrors, CanTakeErrors(..))
import qualified Numeric.CollectErrors as CN
import qualified Prelude as P
import Text.Printf
-- import Text.Regex.TDFA
-- import Data.Maybe
import GHC.Generics
import Data.Typeable
-- import qualified Data.List as List
-- import Test.Hspec
import Test.QuickCheck
import AERN2.MP.Enclosure
import AERN2.MP.Dyadic
import AERN2.MP.Ball hiding (intersect)
-- import qualified AERN2.MP.Ball as MPBall
import AERN2.Real
{- type -}
data Interval l r = Interval l r
deriving (P.Eq, Generic)
instance (Show l, Show r) => Show (Interval l r) where
show (Interval l r) =
printf "Interval (%s) (%s)" (show l) (show r)
-- printf "[%s,%s]" (show l) (show r)
instance (Read l, Read r) => Read (Interval l r) where
readsPrec _pr intervalS
| prefix1 == "Interval (" =
case reads afterP1 of
[(l,afterL)] ->
if prefix2 == ") ("
then
case reads afterP2 of
[(r,')':rest)] -> [(Interval l r, rest)]
_ -> []
else []
where
(prefix2, afterP2) = splitAt (length ") (") afterL
_ -> []
| otherwise = []
where
(prefix1, afterP1) = splitAt (length "Interval (") intervalS
singleton :: a -> Interval a a
singleton a = Interval a a
instance IsInterval (Interval e e) where
type IntervalEndpoint (Interval e e) = e
fromEndpoints l r = Interval l r
endpoints (Interval l r) = (l,r)
width :: (CanSub r l) => Interval l r -> SubType r l
width (Interval l r) = r - l
split ::
(CanAddSameType t, CanMulBy t Dyadic)
=>
(Interval t t) -> (Interval t t, Interval t t)
split (Interval l r) = (Interval l m, Interval m r)
where
m = (l + r)*(dyadic 0.5)
instance
(Arbitrary l, Arbitrary r, HasOrderCertainlyAsymmetric l r)
=>
Arbitrary (Interval l r)
where
arbitrary =
do
l <- arbitrary
r <- arbitrary
if l !<=! r then return (Interval l r) else arbitrary
arbitraryNonEmptyInterval ::
(Arbitrary l, Arbitrary r, HasOrderCertainlyAsymmetric l r)
=>
Gen (Interval l r)
arbitraryNonEmptyInterval =
do
l <- arbitrary
r <- arbitrary
if l !<! r then return (Interval l r) else arbitraryNonEmptyInterval
arbitraryNonEmptySmallInterval ::
(Arbitrary e, CanAddThis e Integer)
=>
Gen (Interval e e)
arbitraryNonEmptySmallInterval =
do
l <- arbitrary
w <- growingElements [1..10]
return (Interval l (l+w))
{- containment -}
instance
(HasOrderAsymmetric l l', OrderCompareType l l' ~ Bool,
HasOrderAsymmetric r' r, OrderCompareType r' r ~ Bool)
=>
CanTestContains (Interval l r) (Interval l' r')
where
contains (Interval l r) (Interval l' r') =
l <= l' && r' <= r
$(declForTypes
[[t| Integer |], [t| Int |], [t| Rational |], [t| Dyadic |]]
(\ t -> [d|
instance
(HasOrderAsymmetric l $t, OrderCompareType l $t ~ Bool,
HasOrderAsymmetric $t r, OrderCompareType $t r ~ Bool)
=>
CanTestContains (Interval l r) $t
where
contains (Interval l r) e = l <= e && e <= r
|]))
instance
(CanSubSameType e, CanAddSubMulBy t e
, HasIntegerBounds t, CanSubThis t Integer, CanDivBy t Integer)
=>
CanMapInside (Interval e e) t
where
mapInside (Interval l r) x =
l + xUnit * (r - l)
where
xUnit = (x - xL) / (max 1 $ xU - xL)
(xL,xU) = integerBounds x
{- intersection -}
instance
(CanMinMaxSameType l, CanMinMaxSameType r, HasOrderCertainly l r)
=>
CanIntersectAsymmetric (Interval l r) (Interval l r)
where
type IntersectionType (Interval l r) (Interval l r) = CN (Interval l r)
intersect (Interval l1 r1) (Interval l2 r2)
| l !<=! r = pure (Interval l r)
| l !>! r = CN.noValueNumErrorCertain err
| otherwise = CN.prependErrorPotential err $ cn (Interval l r)
where
l = l1 `max` l2
r = r1 `min` r2
err = CN.NumError "empty intersection"
intersects ::
(CanMinMaxSameType l, CanMinMaxSameType r, HasOrderCertainly l r)
=>
Interval l r -> Interval l r -> Bool
intersects i1 i2 = not . CN.hasError $ intersect i1 i2
{- comparison -}
instance
(HasEqAsymmetric l1 l2, HasEqAsymmetric r1 r2
, EqCompareType l1 l2 ~ EqCompareType r1 r2
, CanAndOrSameType (EqCompareType l1 l2))
=>
HasEqAsymmetric (Interval l1 r1) (Interval l2 r2)
where
type EqCompareType (Interval l1 r1) (Interval l2 r2) = EqCompareType l1 l2
equalTo (Interval l1 r1) (Interval l2 r2) =
(l1 == l2) && (r1 == r2)
{- Dyadic intervals -}
type DyadicInterval = Interval Dyadic Dyadic
type CanBeDyadicInterval t = ConvertibleExactly t DyadicInterval
dyadicInterval :: (CanBeDyadicInterval t) => t -> DyadicInterval
dyadicInterval = convertExactly
instance
(CanBeDyadic l, CanBeDyadic r, HasOrderCertainly l r, Show l, Show r,
Typeable l, Typeable r)
=>
ConvertibleExactly (l, r) DyadicInterval where
safeConvertExactly (l,r)
| l !<=! r = Right $ Interval (dyadic l) (dyadic r)
| otherwise = convError "endpoints are not in the correct order" (l,r)
instance ConvertibleExactly Dyadic DyadicInterval where
safeConvertExactly d =
Right $ Interval d d
instance ConvertibleExactly Integer DyadicInterval where
safeConvertExactly n =
do
nD <- safeConvertExactly n
Right $ Interval nD nD
instance ConvertibleExactly Rational DyadicInterval where
safeConvertExactly r =
do
rD <- safeConvertExactly r
Right $ Interval rD rD
instance ConvertibleExactly MPBall DyadicInterval where
safeConvertExactly ball =
Right $ Interval (centre l) (centre r)
where
(l,r) = endpointsAsIntervals ball
instance ConvertibleExactly DyadicInterval MPBall where
safeConvertExactly (Interval lD rD) =
Right $ fromEndpointsAsIntervals (mpBall lD) (mpBall rD)
{- CauchyReal intervals -}
type RealInterval = Interval CReal CReal
type CanBeRealInterval t = ConvertibleExactly t RealInterval
realInterval :: (CanBeRealInterval t) => t -> RealInterval
realInterval = convertExactly
instance
(CanBeCReal l, CanBeCReal r, HasOrderCertainly l r, Show l, Show r,
Typeable l, Typeable r)
=>
ConvertibleExactly (l, r) RealInterval where
safeConvertExactly (l,r)
| l !<=! r = Right $ Interval (creal l) (creal r)
| otherwise = convError "endpoints are not in the correct order" (l,r)