-- This differs from intervals package: even an empty interval has offset (but not inf)

module Data.Interval
    ( Interval(..)
    , member
    , empty
    , contains
    ) where

data Interval a = I { forall a. Interval a -> a
offset :: !a, forall a. Interval a -> a
size :: !a }

instance (Ord a, Num a) => Eq (Interval a) where
    == :: Interval a -> Interval a -> Bool
(==) (I a
o1 a
s1) (I a
o2 a
s2) | a
s1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>  a
0 Bool -> Bool -> Bool
&& a
s2 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>  a
0 = a
o1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
o2 Bool -> Bool -> Bool
&& a
s1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
s2
                             | a
s1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 Bool -> Bool -> Bool
&& a
s2 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 = a
o1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
o2
                             | Bool
otherwise          = Bool
False

instance (Ord a, Num a, Show a) => Show (Interval a) where
    show :: Interval a -> String
show (I a
o a
s) | a
s a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0    = String
"empty @" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
o
                 | Bool
otherwise = a -> String
forall a. Show a => a -> String
show a
o String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" ... " String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show (a
o a -> a -> a
forall a. Num a => a -> a -> a
+ a
s a -> a -> a
forall a. Num a => a -> a -> a
- a
1)

empty :: (Ord a, Num a) => Interval a -> Bool
empty :: forall a. (Ord a, Num a) => Interval a -> Bool
empty (I a
_ a
s) | a
s a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0    = Bool
True
              | Bool
otherwise = Bool
False
{-# INLINE empty #-}

member :: (Ord a, Num a) => a -> Interval a -> Bool
member :: forall a. (Ord a, Num a) => a -> Interval a -> Bool
member a
x i :: Interval a
i@(I a
o a
s) | Interval a -> Bool
forall a. (Ord a, Num a) => Interval a -> Bool
empty Interval a
i   = Bool
False
                   | Bool
otherwise = a
o a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
x Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= (a
o a -> a -> a
forall a. Num a => a -> a -> a
+ a
s a -> a -> a
forall a. Num a => a -> a -> a
- a
1)
{-# INLINE member #-}

contains :: (Ord a, Num a) => Interval a -> Interval a -> Bool
contains :: forall a. (Ord a, Num a) => Interval a -> Interval a -> Bool
contains Interval a
b a :: Interval a
a@(I a
ao a
as) | Interval a -> Bool
forall a. (Ord a, Num a) => Interval a -> Bool
empty Interval a
b   = Bool
False
                       | Interval a -> Bool
forall a. (Ord a, Num a) => Interval a -> Bool
empty Interval a
a   = a
ao a -> Interval a -> Bool
forall a. (Ord a, Num a) => a -> Interval a -> Bool
`member` Interval a
b
                       | Bool
otherwise = a
ao a -> Interval a -> Bool
forall a. (Ord a, Num a) => a -> Interval a -> Bool
`member` Interval a
b Bool -> Bool -> Bool
&& (a
ao a -> a -> a
forall a. Num a => a -> a -> a
+ a
as a -> a -> a
forall a. Num a => a -> a -> a
- a
1) a -> Interval a -> Bool
forall a. (Ord a, Num a) => a -> Interval a -> Bool
`member` Interval a
b
{-# INLINE contains #-}