-- | An incomplete implementation of interval aritrhmetic.
module Data.Number.Interval(Interval, ival, getIval) where

data Interval a = I a a

ival :: (Ord a) => a -> a -> Interval a
ival :: forall a. Ord a => a -> a -> Interval a
ival a
l a
h | a
l forall a. Ord a => a -> a -> Bool
<= a
h = forall a. a -> a -> Interval a
I a
l a
h
         | Bool
otherwise = forall a. HasCallStack => [Char] -> a
error [Char]
"Interval.ival: low > high"

getIval :: Interval a -> (a, a)
getIval :: forall a. Interval a -> (a, a)
getIval (I a
l a
h) = (a
l, a
h)

instance (Ord a) => Eq (Interval a) where
    I a
l a
h == :: Interval a -> Interval a -> Bool
== I a
l' a
h'  =  a
l forall a. Eq a => a -> a -> Bool
== a
h' Bool -> Bool -> Bool
&& a
h forall a. Eq a => a -> a -> Bool
== a
l'
    I a
l a
h /= :: Interval a -> Interval a -> Bool
/= I a
l' a
h'  =  a
h forall a. Ord a => a -> a -> Bool
< a
l' Bool -> Bool -> Bool
|| a
h' forall a. Ord a => a -> a -> Bool
< a
l

instance (Ord a) => Ord (Interval a) where
    I a
l a
h < :: Interval a -> Interval a -> Bool
<  I a
l' a
h'  =  a
h forall a. Ord a => a -> a -> Bool
<  a
l'
    I a
l a
h <= :: Interval a -> Interval a -> Bool
<= I a
l' a
h'  =  a
h forall a. Ord a => a -> a -> Bool
<= a
l'
    I a
l a
h > :: Interval a -> Interval a -> Bool
>  I a
l' a
h'  =  a
l forall a. Ord a => a -> a -> Bool
>  a
h'
    I a
l a
h >= :: Interval a -> Interval a -> Bool
>= I a
l' a
h'  =  a
l forall a. Ord a => a -> a -> Bool
>= a
h'
    -- These funcions are partial, so we just leave them out.
    compare :: Interval a -> Interval a -> Ordering
compare Interval a
_ Interval a
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"Interval compare"
    max :: Interval a -> Interval a -> Interval a
max Interval a
_ Interval a
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"Interval max"
    min :: Interval a -> Interval a -> Interval a
min Interval a
_ Interval a
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"Interval min"

instance (Eq a, Show a) => Show (Interval a) where
    showsPrec :: Int -> Interval a -> ShowS
showsPrec Int
p (I a
l a
h) | a
l forall a. Eq a => a -> a -> Bool
== a
h = forall a. Show a => Int -> a -> ShowS
showsPrec Int
p a
l
                        | Bool
otherwise = forall a. Show a => Int -> a -> ShowS
showsPrec Int
p a
l forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
".." forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => Int -> a -> ShowS
showsPrec Int
p a
h

instance (Ord a, Num a) => Num (Interval a) where
    I a
l a
h + :: Interval a -> Interval a -> Interval a
+ I a
l' a
h'  =  forall a. a -> a -> Interval a
I (a
l forall a. Num a => a -> a -> a
+ a
l') (a
h forall a. Num a => a -> a -> a
+ a
h')
    I a
l a
h - :: Interval a -> Interval a -> Interval a
- I a
l' a
h'  =  forall a. a -> a -> Interval a
I (a
l forall a. Num a => a -> a -> a
- a
h') (a
h forall a. Num a => a -> a -> a
- a
l')
    I a
l a
h * :: Interval a -> Interval a -> Interval a
* I a
l' a
h'  =  forall a. a -> a -> Interval a
I (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a]
xs) (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a]
xs) where xs :: [a]
xs = [a
lforall a. Num a => a -> a -> a
*a
l', a
lforall a. Num a => a -> a -> a
*a
h', a
hforall a. Num a => a -> a -> a
*a
l', a
hforall a. Num a => a -> a -> a
*a
h']
    negate :: Interval a -> Interval a
negate (I a
l a
h)   =  forall a. a -> a -> Interval a
I (-a
h) (-a
l)
    -- leave out abs and signum
    abs :: Interval a -> Interval a
abs Interval a
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"Interval abs"
    signum :: Interval a -> Interval a
signum Interval a
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"Interval signum"
    fromInteger :: Integer -> Interval a
fromInteger Integer
i    =  forall a. a -> a -> Interval a
I a
l a
l where l :: a
l = forall a. Num a => Integer -> a
fromInteger Integer
i
 
instance (Ord a, Fractional a) => Fractional (Interval a) where
    I a
l a
h / :: Interval a -> Interval a -> Interval a
/ I a
l' a
h' | forall a. Num a => a -> a
signum a
l' forall a. Eq a => a -> a -> Bool
== forall a. Num a => a -> a
signum a
h' Bool -> Bool -> Bool
&& a
l' forall a. Eq a => a -> a -> Bool
/= a
0 =  forall a. a -> a -> Interval a
I (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a]
xs) (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a]
xs)
                    | Bool
otherwise = forall a. HasCallStack => [Char] -> a
error [Char]
"Interval: division by 0"
                    where xs :: [a]
xs = [a
lforall a. Fractional a => a -> a -> a
/a
l', a
lforall a. Fractional a => a -> a -> a
/a
h', a
hforall a. Fractional a => a -> a -> a
/a
l', a
hforall a. Fractional a => a -> a -> a
/a
h']
    fromRational :: Rational -> Interval a
fromRational Rational
r   =  forall a. a -> a -> Interval a
I a
l a
l where l :: a
l = forall a. Fractional a => Rational -> a
fromRational Rational
r