{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE DeriveDataTypeable #-}
#if __GLASGOW_HASKELL__ >= 704
{-# LANGUAGE DeriveGeneric #-}
#endif
{-# OPTIONS_HADDOCK not-home #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Numeric.Interval.NonEmpty.Internal
-- Copyright   :  (c) Edward Kmett 2010-2014
-- License     :  BSD3
-- Maintainer  :  ekmett@gmail.com
-- Stability   :  experimental
-- Portability :  DeriveDataTypeable
--
-- Interval arithmetic
-----------------------------------------------------------------------------
module Numeric.Interval.NonEmpty.Internal
  ( Interval(..)
  , (...)
  , interval
  , whole
  , singleton
  , member
  , notMember
  , elem
  , notElem
  , inf
  , sup
  , singular
  , width
  , midpoint
  , distance
  , intersection
  , hull
  , bisect
  , bisectIntegral
  , magnitude
  , mignitude
  , contains
  , isSubsetOf
  , certainly, (<!), (<=!), (==!), (/=!), (>=!), (>!)
  , possibly, (<?), (<=?), (==?), (/=?), (>=?), (>?)
  , clamp
  , inflate, deflate
  , scale, symmetric
  , idouble
  , ifloat
  , iquot
  , irem
  , idiv
  , imod
  ) where

import Control.Exception as Exception
import Data.Data
#if __GLASGOW_HASKELL__ >= 704
import GHC.Generics
#endif
import Prelude hiding (null, elem, notElem)

import qualified Data.Semigroup

-- $setup
-- >>> import Test.QuickCheck.Arbitrary
-- >>> import Test.QuickCheck.Gen hiding (scale)
-- >>> import Test.QuickCheck.Property
-- >>> import Control.Applicative
-- >>> import Control.Exception
-- >>> :set -XNoMonomorphismRestriction
-- >>> :set -XExtendedDefaultRules
-- >>> default (Integer,Double)
-- >>> instance (Ord a, Arbitrary a) => Arbitrary (Interval a) where arbitrary = (...) <$> arbitrary <*> arbitrary
-- >>> let memberOf xs = sized $ \n -> case n of { 0 -> pure $ inf xs; 1 -> pure $ sup xs; _ -> choose (inf xs, sup xs); }
-- >>> let conservative sf f xs = forAll (choose (inf xs, sup xs)) $ \x -> (sf x) `member` (f xs)
-- >>> let conservative2 sf f xs ys = forAll ((,) <$> choose (inf xs, sup xs) <*> choose (inf ys, sup ys)) $ \(x,y) -> (sf x y) `member` (f xs ys)
-- >>> let conservativeExceptNaN sf f xs = forAll (choose (inf xs, sup xs)) $ \x -> isNaN (sf x) || (sf x) `member` (f xs)
-- >>> let compose2 = fmap . fmap
-- >>> let commutative op a b = (a `op` b) == (b `op` a)
--
-- -- Eta expansion needed for GHC-7.6
-- >>> :set -fno-warn-deprecations
-- >>> let elem x xs = Numeric.Interval.NonEmpty.Internal.elem x xs
-- >>> let notElem x xs = Numeric.Interval.NonEmpty.Internal.notElem x xs

data Interval a = I !a !a deriving
  ( Interval a -> Interval a -> Bool
(Interval a -> Interval a -> Bool)
-> (Interval a -> Interval a -> Bool) -> Eq (Interval a)
forall a. Eq a => Interval a -> Interval a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Interval a -> Interval a -> Bool
$c/= :: forall a. Eq a => Interval a -> Interval a -> Bool
== :: Interval a -> Interval a -> Bool
$c== :: forall a. Eq a => Interval a -> Interval a -> Bool
Eq, Eq (Interval a)
Eq (Interval a)
-> (Interval a -> Interval a -> Ordering)
-> (Interval a -> Interval a -> Bool)
-> (Interval a -> Interval a -> Bool)
-> (Interval a -> Interval a -> Bool)
-> (Interval a -> Interval a -> Bool)
-> (Interval a -> Interval a -> Interval a)
-> (Interval a -> Interval a -> Interval a)
-> Ord (Interval a)
Interval a -> Interval a -> Bool
Interval a -> Interval a -> Ordering
Interval a -> Interval a -> Interval a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Interval a)
forall a. Ord a => Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Ordering
forall a. Ord a => Interval a -> Interval a -> Interval a
min :: Interval a -> Interval a -> Interval a
$cmin :: forall a. Ord a => Interval a -> Interval a -> Interval a
max :: Interval a -> Interval a -> Interval a
$cmax :: forall a. Ord a => Interval a -> Interval a -> Interval a
>= :: Interval a -> Interval a -> Bool
$c>= :: forall a. Ord a => Interval a -> Interval a -> Bool
> :: Interval a -> Interval a -> Bool
$c> :: forall a. Ord a => Interval a -> Interval a -> Bool
<= :: Interval a -> Interval a -> Bool
$c<= :: forall a. Ord a => Interval a -> Interval a -> Bool
< :: Interval a -> Interval a -> Bool
$c< :: forall a. Ord a => Interval a -> Interval a -> Bool
compare :: Interval a -> Interval a -> Ordering
$ccompare :: forall a. Ord a => Interval a -> Interval a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Interval a)
Ord
  , Typeable (Interval a)
DataType
Constr
Typeable (Interval a)
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Interval a -> c (Interval a))
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Interval a))
-> (Interval a -> Constr)
-> (Interval a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (Interval a)))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (Interval a)))
-> ((forall b. Data b => b -> b) -> Interval a -> Interval a)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Interval a -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Interval a -> r)
-> (forall u. (forall d. Data d => d -> u) -> Interval a -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> Interval a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Interval a -> m (Interval a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Interval a -> m (Interval a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Interval a -> m (Interval a))
-> Data (Interval a)
Interval a -> DataType
Interval a -> Constr
(forall d. Data d => c (t d)) -> Maybe (c (Interval a))
(forall b. Data b => b -> b) -> Interval a -> Interval a
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Interval a -> c (Interval a)
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Interval a)
forall a. Data a => Typeable (Interval a)
forall a. Data a => Interval a -> DataType
forall a. Data a => Interval a -> Constr
forall a.
Data a =>
(forall b. Data b => b -> b) -> Interval a -> Interval a
forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Interval a -> u
forall a u.
Data a =>
(forall d. Data d => d -> u) -> Interval a -> [u]
forall a r r'.
Data a =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
forall a r r'.
Data a =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Interval a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Interval a -> c (Interval a)
forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Interval a))
forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Interval a))
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Interval a -> u
forall u. (forall d. Data d => d -> u) -> Interval a -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Interval a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Interval a -> c (Interval a)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Interval a))
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Interval a))
$cI :: Constr
$tInterval :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
$cgmapMo :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
gmapMp :: (forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
$cgmapMp :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
gmapM :: (forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
$cgmapM :: forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Interval a -> m (Interval a)
gmapQi :: Int -> (forall d. Data d => d -> u) -> Interval a -> u
$cgmapQi :: forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Interval a -> u
gmapQ :: (forall d. Data d => d -> u) -> Interval a -> [u]
$cgmapQ :: forall a u.
Data a =>
(forall d. Data d => d -> u) -> Interval a -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
$cgmapQr :: forall a r r'.
Data a =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
$cgmapQl :: forall a r r'.
Data a =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Interval a -> r
gmapT :: (forall b. Data b => b -> b) -> Interval a -> Interval a
$cgmapT :: forall a.
Data a =>
(forall b. Data b => b -> b) -> Interval a -> Interval a
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Interval a))
$cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Interval a))
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c (Interval a))
$cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Interval a))
dataTypeOf :: Interval a -> DataType
$cdataTypeOf :: forall a. Data a => Interval a -> DataType
toConstr :: Interval a -> Constr
$ctoConstr :: forall a. Data a => Interval a -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Interval a)
$cgunfold :: forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Interval a)
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Interval a -> c (Interval a)
$cgfoldl :: forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Interval a -> c (Interval a)
$cp1Data :: forall a. Data a => Typeable (Interval a)
Data
  , Typeable
#if __GLASGOW_HASKELL__ >= 704
  , (forall x. Interval a -> Rep (Interval a) x)
-> (forall x. Rep (Interval a) x -> Interval a)
-> Generic (Interval a)
forall x. Rep (Interval a) x -> Interval a
forall x. Interval a -> Rep (Interval a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Interval a) x -> Interval a
forall a x. Interval a -> Rep (Interval a) x
$cto :: forall a x. Rep (Interval a) x -> Interval a
$cfrom :: forall a x. Interval a -> Rep (Interval a) x
Generic
#if __GLASGOW_HASKELL__ >= 706
  , (forall a. Interval a -> Rep1 Interval a)
-> (forall a. Rep1 Interval a -> Interval a) -> Generic1 Interval
forall a. Rep1 Interval a -> Interval a
forall a. Interval a -> Rep1 Interval a
forall k (f :: k -> *).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
$cto1 :: forall a. Rep1 Interval a -> Interval a
$cfrom1 :: forall a. Interval a -> Rep1 Interval a
Generic1
#endif
#endif
  )

-- | 'Data.Semigroup.<>' is 'hull'
instance Ord a => Data.Semigroup.Semigroup (Interval a) where
  <> :: Interval a -> Interval a -> Interval a
(<>) = Interval a -> Interval a -> Interval a
forall a. Ord a => Interval a -> Interval a -> Interval a
hull

infix 3 ...

negInfinity :: Fractional a => a
negInfinity :: a
negInfinity = (-a
1)a -> a -> a
forall a. Fractional a => a -> a -> a
/a
0
{-# INLINE negInfinity #-}

posInfinity :: Fractional a => a
posInfinity :: a
posInfinity = a
1a -> a -> a
forall a. Fractional a => a -> a -> a
/a
0
{-# INLINE posInfinity #-}

-- the sign of a number, but as an Ordering so that we can pattern match over it.
-- GT means greater than zero, etc.
signum' :: (Ord a, Num a) => a -> Ordering
signum' :: a -> Ordering
signum' a
x = a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
x a
0

-- arguments are period, range, derivative, function, and interval
-- we require that each period of the function include precisely one local minimum and one local maximum
periodic :: (Num a, Ord a) => a -> Interval a -> (a -> Ordering) -> (a -> a) -> Interval a -> Interval a
periodic :: a
-> Interval a
-> (a -> Ordering)
-> (a -> a)
-> Interval a
-> Interval a
periodic a
p Interval a
r a -> Ordering
_ a -> a
_ Interval a
x | Interval a -> a
forall a. Num a => Interval a -> a
width Interval a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
p = Interval a
r
periodic a
_ Interval a
r a -> Ordering
d a -> a
f (I a
a a
b) = Interval a -> Ordering -> Ordering -> a -> a -> Interval a
forall a.
Ord a =>
Interval a -> Ordering -> Ordering -> a -> a -> Interval a
periodic' Interval a
r (a -> Ordering
d a
a) (a -> Ordering
d a
b) (a -> a
f a
a) (a -> a
f a
b)

-- arguments are global range, derivatives at endpoints, values at endpoints
periodic' :: (Ord a) => Interval a -> Ordering -> Ordering -> a -> a -> Interval a
periodic' :: Interval a -> Ordering -> Ordering -> a -> a -> Interval a
periodic' Interval a
r Ordering
GT Ordering
GT a
a a
b | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
b -- stays in increasing zone
                      | Bool
otherwise = Interval a
r  -- goes from increasing zone, all the way through decreasing zone, and back to increasing zone
periodic' Interval a
r Ordering
LT Ordering
LT a
a a
b | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
b = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
b a
a -- stays in decreasing zone
                      | Bool
otherwise = Interval a
r  -- goes from decreasing zone, all the way through increasing zone, and back to decreasing zone
periodic' Interval a
r Ordering
GT Ordering
_  a
a a
b = a -> a -> Interval a
forall a. a -> a -> Interval a
I (a -> a -> a
forall a. Ord a => a -> a -> a
min a
a a
b) (Interval a -> a
forall a. Interval a -> a
sup Interval a
r) -- was going up, started going down
periodic' Interval a
r Ordering
LT Ordering
_  a
a a
b = a -> a -> Interval a
forall a. a -> a -> Interval a
I (Interval a -> a
forall a. Interval a -> a
inf Interval a
r) (a -> a -> a
forall a. Ord a => a -> a -> a
max a
a a
b) -- was going down, started going up
periodic' Interval a
r Ordering
EQ Ordering
GT a
a a
b | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
b = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
b -- stays in increasing zone
                      | Bool
otherwise = Interval a
r -- goes from increasing zone, all the way through decreasing zone, and back to increasing zone
periodic' Interval a
r Ordering
EQ Ordering
LT a
a a
b | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
b = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
b a
a -- stays in decreasing zone
                      | Bool
otherwise = Interval a
r -- goes from decreasing zone, all the way through increasing zone, and back to decreasing zone
periodic' Interval a
_ Ordering
_  Ordering
_  a
a a
b = a
a a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... a
b -- precisely begins and ends at local extremes, so it's either a singleton or whole

-- | Create a non-empty interval, turning it around if necessary
(...) :: Ord a => a -> a -> Interval a
a
a ... :: a -> a -> Interval a
... a
b
  | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
b
  | Bool
otherwise = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
b a
a
{-# INLINE (...) #-}

-- | Try to create a non-empty interval.
interval :: Ord a => a -> a -> Maybe (Interval a)
interval :: a -> a -> Maybe (Interval a)
interval a
a a
b
  | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b = Interval a -> Maybe (Interval a)
forall a. a -> Maybe a
Just (Interval a -> Maybe (Interval a))
-> Interval a -> Maybe (Interval a)
forall a b. (a -> b) -> a -> b
$ a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
b
  | Bool
otherwise = Maybe (Interval a)
forall a. Maybe a
Nothing


-- | The whole real number line
--
-- >>> whole
-- -Infinity ... Infinity
--
-- prop> (x :: Double) `elem` whole
whole :: Fractional a => Interval a
whole :: Interval a
whole = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
forall a. Fractional a => a
negInfinity a
forall a. Fractional a => a
posInfinity
{-# INLINE whole #-}

-- | A singleton point
--
-- >>> singleton 1
-- 1 ... 1
--
-- prop> x `elem` (singleton x)
-- prop> x /= y ==> y `notElem` (singleton x)
singleton :: a -> Interval a
singleton :: a -> Interval a
singleton a
a = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
a
{-# INLINE singleton #-}

-- | The infinumum (lower bound) of an interval
--
-- >>> inf (1 ... 20)
-- 1
--
-- prop> min x y == inf (x ... y)
-- prop> inf x <= sup x
inf :: Interval a -> a
inf :: Interval a -> a
inf (I a
a a
_) = a
a
{-# INLINE inf #-}

-- | The supremum (upper bound) of an interval
--
-- >>> sup (1 ... 20)
-- 20
--
-- prop> sup x `elem` x
-- prop> max x y == sup (x ... y)
-- prop> inf x <= sup x
sup :: Interval a -> a
sup :: Interval a -> a
sup (I a
_ a
b) = a
b
{-# INLINE sup #-}

-- | Is the interval a singleton point?
-- N.B. This is fairly fragile and likely will not hold after
-- even a few operations that only involve singletons
--
-- >>> singular (singleton 1)
-- True
--
-- >>> singular (1.0 ... 20.0)
-- False
singular :: Ord a => Interval a -> Bool
singular :: Interval a -> Bool
singular (I a
a a
b) = a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b
{-# INLINE singular #-}

instance Show a => Show (Interval a) where
  showsPrec :: Int -> Interval a -> ShowS
showsPrec Int
n (I a
a a
b) =
    Bool -> ShowS -> ShowS
showParen (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
3) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
      Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
3 a
a ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
      String -> ShowS
showString String
" ... " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
      Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
3 a
b

-- | Calculate the width of an interval.
--
-- >>> width (1 ... 20)
-- 19
--
-- >>> width (singleton 1)
-- 0
--
-- prop> 0 <= width x
width :: Num a => Interval a -> a
width :: Interval a -> a
width (I a
a a
b) = a
b a -> a -> a
forall a. Num a => a -> a -> a
- a
a
{-# INLINE width #-}

-- | Magnitude
--
-- >>> magnitude (1 ... 20)
-- 20
--
-- >>> magnitude (-20 ... 10)
-- 20
--
-- >>> magnitude (singleton 5)
-- 5
--
-- prop> 0 <= magnitude x
magnitude :: (Num a, Ord a) => Interval a -> a
magnitude :: Interval a -> a
magnitude = Interval a -> a
forall a. Interval a -> a
sup (Interval a -> a) -> (Interval a -> Interval a) -> Interval a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval a -> Interval a
forall a. Num a => a -> a
abs
{-# INLINE magnitude #-}

-- | \"mignitude\"
--
-- >>> mignitude (1 ... 20)
-- 1
--
-- >>> mignitude (-20 ... 10)
-- 0
--
-- >>> mignitude (singleton 5)
-- 5
--
-- prop> 0 <= mignitude x
mignitude :: (Num a, Ord a) => Interval a -> a
mignitude :: Interval a -> a
mignitude = Interval a -> a
forall a. Interval a -> a
inf (Interval a -> a) -> (Interval a -> Interval a) -> Interval a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval a -> Interval a
forall a. Num a => a -> a
abs
{-# INLINE mignitude #-}

-- | Num instance for intervals.
--
-- prop> conservative2 ((+) :: Double -> Double -> Double) (+)
-- prop> conservative2 ((-) :: Double -> Double -> Double) (-)
-- prop> conservative2 ((*) :: Double -> Double -> Double) (*)
-- prop> conservative (abs :: Double -> Double) abs
instance (Num a, Ord a) => Num (Interval a) where
  I a
a a
b + :: Interval a -> Interval a -> Interval a
+ I a
a' a
b' = (a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
a') a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a
b')
  {-# INLINE (+) #-}
  I a
a a
b - :: Interval a -> Interval a -> Interval a
- I a
a' a
b' = (a
a a -> a -> a
forall a. Num a => a -> a -> a
- a
b') a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a
b a -> a -> a
forall a. Num a => a -> a -> a
- a
a')
  {-# INLINE (-) #-}
  I a
a a
b * :: Interval a -> Interval a -> Interval a
* I a
a' a
b' =
    [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
a', a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
b', a
b a -> a -> a
forall a. Num a => a -> a -> a
* a
a', a
b a -> a -> a
forall a. Num a => a -> a -> a
* a
b']
    a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
...
    [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
a', a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
b', a
b a -> a -> a
forall a. Num a => a -> a -> a
* a
a', a
b a -> a -> a
forall a. Num a => a -> a -> a
* a
b']
  {-# INLINE (*) #-}
  abs :: Interval a -> Interval a
abs x :: Interval a
x@(I a
a a
b)
    | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0    = Interval a
x
    | a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0    = Interval a -> Interval a
forall a. Num a => a -> a
negate Interval a
x
    | Bool
otherwise = a
0 a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... a -> a -> a
forall a. Ord a => a -> a -> a
max (- a
a) a
b
  {-# INLINE abs #-}

  signum :: Interval a -> Interval a
signum = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
increasing a -> a
forall a. Num a => a -> a
signum
  {-# INLINE signum #-}

  fromInteger :: Integer -> Interval a
fromInteger Integer
i = a -> Interval a
forall a. a -> Interval a
singleton (Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
i)
  {-# INLINE fromInteger #-}

-- | Bisect an interval at its midpoint.
--
-- >>> bisect (10.0 ... 20.0)
-- (10.0 ... 15.0,15.0 ... 20.0)
--
-- >>> bisect (singleton 5.0)
-- (5.0 ... 5.0,5.0 ... 5.0)
--
-- prop> let (a, b) = bisect (x :: Interval Double) in sup a == inf b
-- prop> let (a, b) = bisect (x :: Interval Double) in inf a == inf x
-- prop> let (a, b) = bisect (x :: Interval Double) in sup b == sup x
bisect :: Fractional a => Interval a -> (Interval a, Interval a)
bisect :: Interval a -> (Interval a, Interval a)
bisect (I a
a a
b) = (a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
m, a -> a -> Interval a
forall a. a -> a -> Interval a
I a
m a
b) where m :: a
m = a
a a -> a -> a
forall a. Num a => a -> a -> a
+ (a
b a -> a -> a
forall a. Num a => a -> a -> a
- a
a) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2
{-# INLINE bisect #-}

bisectIntegral :: Integral a => Interval a -> (Interval a, Interval a)
bisectIntegral :: Interval a -> (Interval a, Interval a)
bisectIntegral (I a
a a
b)
  | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
m Bool -> Bool -> Bool
|| a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
m = (a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
a, a -> a -> Interval a
forall a. a -> a -> Interval a
I a
b a
b)
  | Bool
otherwise        = (a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a a
m, a -> a -> Interval a
forall a. a -> a -> Interval a
I a
m a
b)
  where m :: a
m = a
a a -> a -> a
forall a. Num a => a -> a -> a
+ (a
b a -> a -> a
forall a. Num a => a -> a -> a
- a
a) a -> a -> a
forall a. Integral a => a -> a -> a
`div` a
2
{-# INLINE bisectIntegral #-}

-- | Nearest point to the midpoint of the interval.
--
-- >>> midpoint (10.0 ... 20.0)
-- 15.0
--
-- >>> midpoint (singleton 5.0)
-- 5.0
--
-- prop> midpoint x `elem` (x :: Interval Double)
midpoint :: Fractional a => Interval a -> a
midpoint :: Interval a -> a
midpoint (I a
a a
b) = a
a a -> a -> a
forall a. Num a => a -> a -> a
+ (a
b a -> a -> a
forall a. Num a => a -> a -> a
- a
a) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2
{-# INLINE midpoint #-}

-- | Hausdorff distance between intervals.
--
-- >>> distance (1 ... 7) (6 ... 10)
-- 0
--
-- >>> distance (1 ... 7) (15 ... 24)
-- 8
--
-- >>> distance (1 ... 7) (-10 ... -2)
-- 3
--
-- prop> commutative (distance :: Interval Double -> Interval Double -> Double)
-- prop> 0 <= distance x y
distance :: (Num a, Ord a) => Interval a -> Interval a -> a
distance :: Interval a -> Interval a -> a
distance Interval a
i1 Interval a
i2 = Interval a -> a
forall a. (Num a, Ord a) => Interval a -> a
mignitude (Interval a
i1 Interval a -> Interval a -> Interval a
forall a. Num a => a -> a -> a
- Interval a
i2)

-- | Determine if a point is in the interval.
--
-- >>> member 3.2 (1.0 ... 5.0)
-- True
--
-- >>> member 5 (1.0 ... 5.0)
-- True
--
-- >>> member 1 (1.0 ... 5.0)
-- True
--
-- >>> member 8 (1.0 ... 5.0)
-- False
member :: Ord a => a -> Interval a -> Bool
member :: a -> Interval a -> Bool
member a
x (I a
a a
b) = a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
a Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b
{-# INLINE member #-}

-- | Determine if a point is not included in the interval
--
-- >>> notMember 8 (1.0 ... 5.0)
-- True
--
-- >>> notMember 1.4 (1.0 ... 5.0)
-- False
notMember :: Ord a => a -> Interval a -> Bool
notMember :: a -> Interval a -> Bool
notMember a
x Interval a
xs = Bool -> Bool
not (a -> Interval a -> Bool
forall a. Ord a => a -> Interval a -> Bool
member a
x Interval a
xs)
{-# INLINE notMember #-}

-- | Determine if a point is in the interval.
--
-- >>> elem 3.2 (1.0 ... 5.0)
-- True
--
-- >>> elem 5 (1.0 ... 5.0)
-- True
--
-- >>> elem 1 (1.0 ... 5.0)
-- True
--
-- >>> elem 8 (1.0 ... 5.0)
-- False
elem :: Ord a => a -> Interval a -> Bool
elem :: a -> Interval a -> Bool
elem = a -> Interval a -> Bool
forall a. Ord a => a -> Interval a -> Bool
member
{-# INLINE elem #-}
{-# DEPRECATED elem "Use `member` instead." #-}

-- | Determine if a point is not included in the interval
--
-- >>> notElem 8 (1.0 ... 5.0)
-- True
--
-- >>> notElem 1.4 (1.0 ... 5.0)
-- False
notElem :: Ord a => a -> Interval a -> Bool
notElem :: a -> Interval a -> Bool
notElem = a -> Interval a -> Bool
forall a. Ord a => a -> Interval a -> Bool
notMember
{-# INLINE notElem #-}
{-# DEPRECATED notElem "Use `notMember` instead." #-}

-- | 'realToFrac' will use the midpoint
instance Real a => Real (Interval a) where
  toRational :: Interval a -> Rational
toRational (I a
ra a
rb) = Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ (Rational
b Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
a) Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
2 where
    a :: Rational
a = a -> Rational
forall a. Real a => a -> Rational
toRational a
ra
    b :: Rational
b = a -> Rational
forall a. Real a => a -> Rational
toRational a
rb
  {-# INLINE toRational #-}

-- @'divNonZero' X Y@ assumes @0 `'notElem'` Y@
divNonZero :: (Fractional a, Ord a) => Interval a -> Interval a -> Interval a
divNonZero :: Interval a -> Interval a -> Interval a
divNonZero (I a
a a
b) (I a
a' a
b') =
  [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a
a a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
a', a
a a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
b', a
b a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
a', a
b a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
b']
  a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
...
  [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a
a a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
a', a
a a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
b', a
b a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
a', a
b a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
b']

-- @'divPositive' X y@ assumes y > 0, and divides @X@ by [0 ... y]
divPositive :: (Fractional a, Ord a) => Interval a -> a -> Interval a
divPositive :: Interval a -> a -> Interval a
divPositive x :: Interval a
x@(I a
a a
b) a
y
  | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Interval a
x
  -- b < 0 || isNegativeZero b = negInfinity ... ( b / y)
  | a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = a
forall a. Fractional a => a
negInfinity a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a
b a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y)
  | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = Interval a
forall a. Fractional a => Interval a
whole
  | Bool
otherwise = (a
a a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y) a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... a
forall a. Fractional a => a
posInfinity
{-# INLINE divPositive #-}

-- divNegative assumes y < 0 and divides the interval @X@ by [y ... 0]
divNegative :: (Fractional a, Ord a) => Interval a -> a -> Interval a
divNegative :: Interval a -> a -> Interval a
divNegative x :: Interval a
x@(I a
a a
b) a
y
  | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = - Interval a
x -- flip negative zeros
  -- b < 0 || isNegativeZero b = (b / y) ... posInfinity
  | a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = (a
b a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y) a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... a
forall a. Fractional a => a
posInfinity
  | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = Interval a
forall a. Fractional a => Interval a
whole
  | Bool
otherwise = a
forall a. Fractional a => a
negInfinity a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a
a a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y)
{-# INLINE divNegative #-}

divZero :: (Fractional a, Ord a) => Interval a -> Interval a
divZero :: Interval a -> Interval a
divZero x :: Interval a
x@(I a
a a
b)
  | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Interval a
x
  | Bool
otherwise        = Interval a
forall a. Fractional a => Interval a
whole
{-# INLINE divZero #-}

-- | Fractional instance for intervals.
--
-- prop> ys /= singleton 0 ==> conservative2 ((/) :: Double -> Double -> Double) (/) xs ys
-- prop> xs /= singleton 0 ==> conservative (recip :: Double -> Double) recip xs
instance (Fractional a, Ord a) => Fractional (Interval a) where
  -- TODO: check isNegativeZero properly
  Interval a
x / :: Interval a -> Interval a -> Interval a
/ y :: Interval a
y@(I a
a a
b)
    | a
0 a -> Interval a -> Bool
forall a. Ord a => a -> Interval a -> Bool
`notElem` Interval a
y = Interval a -> Interval a -> Interval a
forall a.
(Fractional a, Ord a) =>
Interval a -> Interval a -> Interval a
divNonZero Interval a
x Interval a
y
    | Bool
iz Bool -> Bool -> Bool
&& Bool
sz  = ArithException -> Interval a
forall a e. Exception e => e -> a
Exception.throw ArithException
DivideByZero
    | Bool
iz        = Interval a -> a -> Interval a
forall a. (Fractional a, Ord a) => Interval a -> a -> Interval a
divPositive Interval a
x a
a
    |       Bool
sz  = Interval a -> a -> Interval a
forall a. (Fractional a, Ord a) => Interval a -> a -> Interval a
divNegative Interval a
x a
b
    | Bool
otherwise = Interval a -> Interval a
forall a. (Fractional a, Ord a) => Interval a -> Interval a
divZero Interval a
x
    where
      iz :: Bool
iz = a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0
      sz :: Bool
sz = a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0
  fromRational :: Rational -> Interval a
fromRational Rational
r  = let r' :: a
r' = Rational -> a
forall a. Fractional a => Rational -> a
fromRational Rational
r in a -> a -> Interval a
forall a. a -> a -> Interval a
I a
r' a
r'
  {-# INLINE fromRational #-}

instance RealFrac a => RealFrac (Interval a) where
  properFraction :: Interval a -> (b, Interval a)
properFraction Interval a
x = (b
b, Interval a
x Interval a -> Interval a -> Interval a
forall a. Num a => a -> a -> a
- b -> Interval a
forall a b. (Integral a, Num b) => a -> b
fromIntegral b
b)
    where
      b :: b
b = a -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint Interval a
x)
  {-# INLINE properFraction #-}
  ceiling :: Interval a -> b
ceiling Interval a
x = a -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Interval a -> a
forall a. Interval a -> a
sup Interval a
x)
  {-# INLINE ceiling #-}
  floor :: Interval a -> b
floor Interval a
x = a -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (Interval a -> a
forall a. Interval a -> a
inf Interval a
x)
  {-# INLINE floor #-}
  round :: Interval a -> b
round Interval a
x = a -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint Interval a
x)
  {-# INLINE round #-}
  truncate :: Interval a -> b
truncate Interval a
x = a -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint Interval a
x)
  {-# INLINE truncate #-}

-- | Transcendental functions for intervals.
--
-- prop> conservative (exp :: Double -> Double) exp
-- prop> conservativeExceptNaN (log :: Double -> Double) log
-- prop> conservative (sin :: Double -> Double) sin
-- prop> conservative (cos :: Double -> Double) cos
-- prop> conservative (tan :: Double -> Double) tan
-- prop> conservativeExceptNaN (asin :: Double -> Double) asin
-- prop> conservativeExceptNaN (acos :: Double -> Double) acos
-- prop> conservative (atan :: Double -> Double) atan
-- prop> conservative (sinh :: Double -> Double) sinh
-- prop> conservative (cosh :: Double -> Double) cosh
-- prop> conservative (tanh :: Double -> Double) tanh
-- prop> conservativeExceptNaN (asinh :: Double -> Double) asinh
-- prop> conservativeExceptNaN (acosh :: Double -> Double) acosh
-- prop> conservativeExceptNaN (atanh :: Double -> Double) atanh
--
-- >>> cos (0 ... (pi + 0.1))
-- -1.0 ... 1.0
instance (RealFloat a, Ord a) => Floating (Interval a) where
  pi :: Interval a
pi = a -> Interval a
forall a. a -> Interval a
singleton a
forall a. Floating a => a
pi
  {-# INLINE pi #-}
  exp :: Interval a -> Interval a
exp = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
increasing a -> a
forall a. Floating a => a -> a
exp
  {-# INLINE exp #-}
  log :: Interval a -> Interval a
log (I a
a a
b) = (if a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 then a -> a
forall a. Floating a => a -> a
log a
a else a
forall a. Fractional a => a
negInfinity) a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (if a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 then a -> a
forall a. Floating a => a -> a
log a
b else a
forall a. Fractional a => a
negInfinity)
  {-# INLINE log #-}
  sin :: Interval a -> Interval a
sin = a
-> Interval a
-> (a -> Ordering)
-> (a -> a)
-> Interval a
-> Interval a
forall a.
(Num a, Ord a) =>
a
-> Interval a
-> (a -> Ordering)
-> (a -> a)
-> Interval a
-> Interval a
periodic (a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi) (a -> Interval a
forall a. (Num a, Ord a) => a -> Interval a
symmetric a
1) (a -> Ordering
forall a. (Ord a, Num a) => a -> Ordering
signum' (a -> Ordering) -> (a -> a) -> a -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Floating a => a -> a
cos)          a -> a
forall a. Floating a => a -> a
sin
  cos :: Interval a -> Interval a
cos = a
-> Interval a
-> (a -> Ordering)
-> (a -> a)
-> Interval a
-> Interval a
forall a.
(Num a, Ord a) =>
a
-> Interval a
-> (a -> Ordering)
-> (a -> a)
-> Interval a
-> Interval a
periodic (a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi) (a -> Interval a
forall a. (Num a, Ord a) => a -> Interval a
symmetric a
1) (a -> Ordering
forall a. (Ord a, Num a) => a -> Ordering
signum' (a -> Ordering) -> (a -> a) -> a -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Num a => a -> a
negate (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Floating a => a -> a
sin) a -> a
forall a. Floating a => a -> a
cos
  tan :: Interval a -> Interval a
tan = a
-> Interval a
-> (a -> Ordering)
-> (a -> a)
-> Interval a
-> Interval a
forall a.
(Num a, Ord a) =>
a
-> Interval a
-> (a -> Ordering)
-> (a -> a)
-> Interval a
-> Interval a
periodic a
forall a. Floating a => a
pi       Interval a
forall a. Fractional a => Interval a
whole         (Ordering -> a -> Ordering
forall a b. a -> b -> a
const Ordering
GT)               a -> a
forall a. Floating a => a -> a
tan -- derivative only has to have correct sign
  asin :: Interval a -> Interval a
asin (I a
a a
b) = (a -> a
asin' a
a) a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a -> a
asin' a
b)
    where
      asin' :: a -> a
asin' a
x | a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
1 = a
halfPi
              | a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= -a
1 = -a
halfPi
              | Bool
otherwise = a -> a
forall a. Floating a => a -> a
asin a
x
      halfPi :: a
halfPi = a
forall a. Floating a => a
pi a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2
  {-# INLINE asin #-}
  acos :: Interval a -> Interval a
acos (I a
a a
b) = (a -> a
forall p. (Ord p, Floating p) => p -> p
acos' a
a) a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a -> a
forall p. (Ord p, Floating p) => p -> p
acos' a
b)
    where
      acos' :: p -> p
acos' p
x | p
x p -> p -> Bool
forall a. Ord a => a -> a -> Bool
>= p
1 = p
0
              | p
x p -> p -> Bool
forall a. Ord a => a -> a -> Bool
<= -p
1 = p
forall a. Floating a => a
pi
              | Bool
otherwise = p -> p
forall a. Floating a => a -> a
acos p
x
  {-# INLINE acos #-}
  atan :: Interval a -> Interval a
atan = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
increasing a -> a
forall a. Floating a => a -> a
atan
  {-# INLINE atan #-}
  sinh :: Interval a -> Interval a
sinh = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
increasing a -> a
forall a. Floating a => a -> a
sinh
  {-# INLINE sinh #-}
  cosh :: Interval a -> Interval a
cosh x :: Interval a
x@(I a
a a
b)
    | a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0  = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
decreasing a -> a
forall a. Floating a => a -> a
cosh Interval a
x
    | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0 = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
increasing a -> a
forall a. Floating a => a -> a
cosh Interval a
x
    | Bool
otherwise  = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
0 (a -> Interval a) -> a -> Interval a
forall a b. (a -> b) -> a -> b
$ a -> a
forall a. Floating a => a -> a
cosh (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ if - a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
b
                                then a
a
                                else a
b
  {-# INLINE cosh #-}
  tanh :: Interval a -> Interval a
tanh = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
increasing a -> a
forall a. Floating a => a -> a
tanh
  {-# INLINE tanh #-}
  asinh :: Interval a -> Interval a
asinh = (a -> a) -> Interval a -> Interval a
forall a b. (a -> b) -> Interval a -> Interval b
increasing a -> a
forall a. Floating a => a -> a
asinh
  {-# INLINE asinh #-}
  acosh :: Interval a -> Interval a
acosh (I a
a a
b) = (a -> a
forall p. (Ord p, Floating p) => p -> p
acosh' a
a) a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a -> a
forall p. (Ord p, Floating p) => p -> p
acosh' a
b)
    where
      acosh' :: p -> p
acosh' p
x | p
x p -> p -> Bool
forall a. Ord a => a -> a -> Bool
<= p
1 = p
0
               | Bool
otherwise = p -> p
forall a. Floating a => a -> a
acosh p
x
  {-# INLINE acosh #-}
  atanh :: Interval a -> Interval a
atanh (I a
a a
b) = (a -> a
forall p. (Ord p, Floating p) => p -> p
atanh' a
a) a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... (a -> a
forall p. (Ord p, Floating p) => p -> p
atanh' a
b)
    where
      atanh' :: p -> p
atanh' p
x | p
x p -> p -> Bool
forall a. Ord a => a -> a -> Bool
<= -p
1 = p
forall a. Fractional a => a
negInfinity
               | p
x p -> p -> Bool
forall a. Ord a => a -> a -> Bool
>= p
1 = p
forall a. Fractional a => a
posInfinity
               | Bool
otherwise = p -> p
forall a. Floating a => a -> a
atanh p
x
  {-# INLINE atanh #-}

-- | lift a monotone increasing function over a given interval
increasing :: (a -> b) -> Interval a -> Interval b
increasing :: (a -> b) -> Interval a -> Interval b
increasing a -> b
f (I a
a a
b) = b -> b -> Interval b
forall a. a -> a -> Interval a
I (a -> b
f a
a) (a -> b
f a
b)

-- | lift a monotone decreasing function over a given interval
decreasing :: (a -> b) -> Interval a -> Interval b
decreasing :: (a -> b) -> Interval a -> Interval b
decreasing a -> b
f (I a
a a
b) = b -> b -> Interval b
forall a. a -> a -> Interval a
I (a -> b
f a
b) (a -> b
f a
a)

-- | We have to play some semantic games to make these methods make sense.
-- Most compute with the midpoint of the interval.
instance RealFloat a => RealFloat (Interval a) where
  floatRadix :: Interval a -> Integer
floatRadix = a -> Integer
forall a. RealFloat a => a -> Integer
floatRadix (a -> Integer) -> (Interval a -> a) -> Interval a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint

  floatDigits :: Interval a -> Int
floatDigits = a -> Int
forall a. RealFloat a => a -> Int
floatDigits (a -> Int) -> (Interval a -> a) -> Interval a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint
  floatRange :: Interval a -> (Int, Int)
floatRange = a -> (Int, Int)
forall a. RealFloat a => a -> (Int, Int)
floatRange (a -> (Int, Int)) -> (Interval a -> a) -> Interval a -> (Int, Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint
  decodeFloat :: Interval a -> (Integer, Int)
decodeFloat = a -> (Integer, Int)
forall a. RealFloat a => a -> (Integer, Int)
decodeFloat (a -> (Integer, Int))
-> (Interval a -> a) -> Interval a -> (Integer, Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint
  encodeFloat :: Integer -> Int -> Interval a
encodeFloat Integer
m Int
e = a -> Interval a
forall a. a -> Interval a
singleton (Integer -> Int -> a
forall a. RealFloat a => Integer -> Int -> a
encodeFloat Integer
m Int
e)
  exponent :: Interval a -> Int
exponent = a -> Int
forall a. RealFloat a => a -> Int
exponent (a -> Int) -> (Interval a -> a) -> Interval a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint
  significand :: Interval a -> Interval a
significand Interval a
x = a -> a -> a
forall a. Ord a => a -> a -> a
min a
a a
b a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... a -> a -> a
forall a. Ord a => a -> a -> a
max a
a a
b
    where
      (Integer
_ ,Int
em) = a -> (Integer, Int)
forall a. RealFloat a => a -> (Integer, Int)
decodeFloat (Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint Interval a
x)
      (Integer
mi,Int
ei) = a -> (Integer, Int)
forall a. RealFloat a => a -> (Integer, Int)
decodeFloat (Interval a -> a
forall a. Interval a -> a
inf Interval a
x)
      (Integer
ms,Int
es) = a -> (Integer, Int)
forall a. RealFloat a => a -> (Integer, Int)
decodeFloat (Interval a -> a
forall a. Interval a -> a
sup Interval a
x)
      a :: a
a = Integer -> Int -> a
forall a. RealFloat a => Integer -> Int -> a
encodeFloat Integer
mi (Int
ei Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
em Int -> Int -> Int
forall a. Num a => a -> a -> a
- Interval a -> Int
forall a. RealFloat a => a -> Int
floatDigits Interval a
x)
      b :: a
b = Integer -> Int -> a
forall a. RealFloat a => Integer -> Int -> a
encodeFloat Integer
ms (Int
es Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
em Int -> Int -> Int
forall a. Num a => a -> a -> a
- Interval a -> Int
forall a. RealFloat a => a -> Int
floatDigits Interval a
x)
  scaleFloat :: Int -> Interval a -> Interval a
scaleFloat Int
n (I a
a a
b) = a -> a -> Interval a
forall a. a -> a -> Interval a
I (Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
n a
a) (Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
n a
b)
  isNaN :: Interval a -> Bool
isNaN (I a
a a
b) = a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
a Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
b
  isInfinite :: Interval a -> Bool
isInfinite (I a
a a
b) = a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
a Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
b
  isDenormalized :: Interval a -> Bool
isDenormalized (I a
a a
b) = a -> Bool
forall a. RealFloat a => a -> Bool
isDenormalized a
a Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isDenormalized a
b
  -- contains negative zero
  isNegativeZero :: Interval a -> Bool
isNegativeZero (I a
a a
b) = Bool -> Bool
not (a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0)
                  Bool -> Bool -> Bool
&& Bool -> Bool
not (a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0)
                  Bool -> Bool -> Bool
&& (  (a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& (a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
a))
                     Bool -> Bool -> Bool
|| (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
a)
                     Bool -> Bool -> Bool
|| (a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
&& a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0))
  isIEEE :: Interval a -> Bool
isIEEE Interval a
_ = Bool
False

  atan2 :: Interval a -> Interval a -> Interval a
atan2 = String -> Interval a -> Interval a -> Interval a
forall a. HasCallStack => String -> a
error String
"unimplemented"

-- TODO: (^), (^^) to give tighter bounds

-- | Calculate the intersection of two intervals.
--
-- >>> intersection (1 ... 10 :: Interval Double) (5 ... 15 :: Interval Double)
-- Just (5.0 ... 10.0)
intersection :: Ord a => Interval a -> Interval a -> Maybe (Interval a)
intersection :: Interval a -> Interval a -> Maybe (Interval a)
intersection x :: Interval a
x@(I a
a a
b) y :: Interval a
y@(I a
a' a
b')
  | Interval a
x Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
/=! Interval a
y   = Maybe (Interval a)
forall a. Maybe a
Nothing
  | Bool
otherwise = Interval a -> Maybe (Interval a)
forall a. a -> Maybe a
Just (Interval a -> Maybe (Interval a))
-> Interval a -> Maybe (Interval a)
forall a b. (a -> b) -> a -> b
$ a -> a -> Interval a
forall a. a -> a -> Interval a
I (a -> a -> a
forall a. Ord a => a -> a -> a
max a
a a
a') (a -> a -> a
forall a. Ord a => a -> a -> a
min a
b a
b')
{-# INLINE intersection #-}

-- | Calculate the convex hull of two intervals
--
-- >>> hull (0 ... 10 :: Interval Double) (5 ... 15 :: Interval Double)
-- 0.0 ... 15.0
--
-- >>> hull (15 ... 85 :: Interval Double) (0 ... 10 :: Interval Double)
-- 0.0 ... 85.0
--
-- prop> conservative2 const hull
-- prop> conservative2 (flip const) hull
hull :: Ord a => Interval a -> Interval a -> Interval a
hull :: Interval a -> Interval a -> Interval a
hull (I a
a a
b) (I a
a' a
b') = a -> a -> Interval a
forall a. a -> a -> Interval a
I (a -> a -> a
forall a. Ord a => a -> a -> a
min a
a a
a') (a -> a -> a
forall a. Ord a => a -> a -> a
max a
b a
b')
{-# INLINE hull #-}

-- | For all @x@ in @X@, @y@ in @Y@. @x '<' y@
--
-- >>> (5 ... 10 :: Interval Double) <! (20 ... 30 :: Interval Double)
-- True
--
-- >>> (5 ... 10 :: Interval Double) <! (10 ... 30 :: Interval Double)
-- False
--
-- >>> (20 ... 30 :: Interval Double) <! (5 ... 10 :: Interval Double)
-- False
(<!)  :: Ord a => Interval a -> Interval a -> Bool
I a
_ a
bx <! :: Interval a -> Interval a -> Bool
<! I a
ay a
_ = a
bx a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
ay
{-# INLINE (<!) #-}

-- | For all @x@ in @X@, @y@ in @Y@. @x '<=' y@
--
-- >>> (5 ... 10 :: Interval Double) <=! (20 ... 30 :: Interval Double)
-- True
--
-- >>> (5 ... 10 :: Interval Double) <=! (10 ... 30 :: Interval Double)
-- True
--
-- >>> (20 ... 30 :: Interval Double) <=! (5 ... 10 :: Interval Double)
-- False
(<=!) :: Ord a => Interval a -> Interval a -> Bool
I a
_ a
bx <=! :: Interval a -> Interval a -> Bool
<=! I a
ay a
_ = a
bx a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
ay
{-# INLINE (<=!) #-}

-- | For all @x@ in @X@, @y@ in @Y@. @x '==' y@
--
-- Only singleton intervals or empty intervals can return true
--
-- >>> (singleton 5 :: Interval Double) ==! (singleton 5 :: Interval Double)
-- True
--
-- >>> (5 ... 10 :: Interval Double) ==! (5 ... 10 :: Interval Double)
-- False
(==!) :: Eq a => Interval a -> Interval a -> Bool
I a
ax a
bx ==! :: Interval a -> Interval a -> Bool
==! I a
ay a
by = a
bx a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
ay Bool -> Bool -> Bool
&& a
ax a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
by
{-# INLINE (==!) #-}

-- | For all @x@ in @X@, @y@ in @Y@. @x '/=' y@
--
-- >>> (5 ... 15 :: Interval Double) /=! (20 ... 40 :: Interval Double)
-- True
--
-- >>> (5 ... 15 :: Interval Double) /=! (15 ... 40 :: Interval Double)
-- False
(/=!) :: Ord a => Interval a -> Interval a -> Bool
I a
ax a
bx /=! :: Interval a -> Interval a -> Bool
/=! I a
ay a
by = a
bx a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
ay Bool -> Bool -> Bool
|| a
ax a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
by
{-# INLINE (/=!) #-}

-- | For all @x@ in @X@, @y@ in @Y@. @x '>' y@
--
-- >>> (20 ... 40 :: Interval Double) >! (10 ... 19 :: Interval Double)
-- True
--
-- >>> (5 ... 20 :: Interval Double) >! (15 ... 40 :: Interval Double)
-- False
(>!)  :: Ord a => Interval a -> Interval a -> Bool
I a
ax a
_ >! :: Interval a -> Interval a -> Bool
>! I a
_ a
by = a
ax a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
by
{-# INLINE (>!) #-}

-- | For all @x@ in @X@, @y@ in @Y@. @x '>=' y@
--
-- >>> (20 ... 40 :: Interval Double) >=! (10 ... 20 :: Interval Double)
-- True
--
-- >>> (5 ... 20 :: Interval Double) >=! (15 ... 40 :: Interval Double)
-- False
(>=!) :: Ord a => Interval a -> Interval a -> Bool
I a
ax a
_ >=! :: Interval a -> Interval a -> Bool
>=! I a
_ a
by = a
ax a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
by
{-# INLINE (>=!) #-}

-- | For all @x@ in @X@, @y@ in @Y@. @x `op` y@
certainly :: Ord a => (forall b. Ord b => b -> b -> Bool) -> Interval a -> Interval a -> Bool
certainly :: (forall a. Ord a => a -> a -> Bool)
-> Interval a -> Interval a -> Bool
certainly forall a. Ord a => a -> a -> Bool
cmp Interval a
l Interval a
r
    | Bool
lt Bool -> Bool -> Bool
&& Bool
eq Bool -> Bool -> Bool
&& Bool
gt = Bool
True
    | Bool
lt Bool -> Bool -> Bool
&& Bool
eq       = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
<=! Interval a
r
    | Bool
lt Bool -> Bool -> Bool
&&       Bool
gt = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
/=! Interval a
r
    | Bool
lt             = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
<!  Interval a
r
    |       Bool
eq Bool -> Bool -> Bool
&& Bool
gt = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
>=! Interval a
r
    |       Bool
eq       = Interval a
l Interval a -> Interval a -> Bool
forall a. Eq a => Interval a -> Interval a -> Bool
==! Interval a
r
    |             Bool
gt = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
>!  Interval a
r
    | Bool
otherwise      = Bool
False
    where
        lt :: Bool
lt = Bool -> Bool -> Bool
forall a. Ord a => a -> a -> Bool
cmp Bool
False Bool
True
        eq :: Bool
eq = Bool -> Bool -> Bool
forall a. Ord a => a -> a -> Bool
cmp Bool
True Bool
True
        gt :: Bool
gt = Bool -> Bool -> Bool
forall a. Ord a => a -> a -> Bool
cmp Bool
True Bool
False
{-# INLINE certainly #-}

-- | Check if interval @X@ totally contains interval @Y@
--
-- >>> (20 ... 40 :: Interval Double) `contains` (25 ... 35 :: Interval Double)
-- True
--
-- >>> (20 ... 40 :: Interval Double) `contains` (15 ... 35 :: Interval Double)
-- False
contains :: Ord a => Interval a -> Interval a -> Bool
contains :: Interval a -> Interval a -> Bool
contains (I a
ax a
bx) (I a
ay a
by) = a
ax a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
ay Bool -> Bool -> Bool
&& a
by a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
bx
{-# INLINE contains #-}

-- | Flipped version of `contains`. Check if interval @X@ a subset of interval @Y@
--
-- >>> (25 ... 35 :: Interval Double) `isSubsetOf` (20 ... 40 :: Interval Double)
-- True
--
-- >>> (20 ... 40 :: Interval Double) `isSubsetOf` (15 ... 35 :: Interval Double)
-- False
isSubsetOf :: Ord a => Interval a -> Interval a -> Bool
isSubsetOf :: Interval a -> Interval a -> Bool
isSubsetOf = (Interval a -> Interval a -> Bool)
-> Interval a -> Interval a -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
contains
{-# INLINE isSubsetOf #-}

-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<' y@?
(<?) :: Ord a => Interval a -> Interval a -> Bool
I a
ax a
_ <? :: Interval a -> Interval a -> Bool
<? I a
_ a
by = a
ax a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
by
{-# INLINE (<?) #-}

-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<=' y@?
(<=?) :: Ord a => Interval a -> Interval a -> Bool
I a
ax a
_ <=? :: Interval a -> Interval a -> Bool
<=? I a
_ a
by = a
ax a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
by
{-# INLINE (<=?) #-}

-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '==' y@?
(==?) :: Ord a => Interval a -> Interval a -> Bool
I a
ax a
bx ==? :: Interval a -> Interval a -> Bool
==? I a
ay a
by = a
ax a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
by Bool -> Bool -> Bool
&& a
bx a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
ay
{-# INLINE (==?) #-}

-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '/=' y@?
(/=?) :: Eq a => Interval a -> Interval a -> Bool
I a
ax a
bx /=? :: Interval a -> Interval a -> Bool
/=? I a
ay a
by = a
ax a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
by Bool -> Bool -> Bool
|| a
bx a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
ay
{-# INLINE (/=?) #-}

-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>' y@?
(>?) :: Ord a => Interval a -> Interval a -> Bool
I a
_ a
bx >? :: Interval a -> Interval a -> Bool
>? I a
ay a
_ = a
bx a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
ay
{-# INLINE (>?) #-}

-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>=' y@?
(>=?) :: Ord a => Interval a -> Interval a -> Bool
I a
_ a
bx >=? :: Interval a -> Interval a -> Bool
>=? I a
ay a
_ = a
bx a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
ay
{-# INLINE (>=?) #-}

-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x `op` y@?
possibly :: Ord a => (forall b. Ord b => b -> b -> Bool) -> Interval a -> Interval a -> Bool
possibly :: (forall a. Ord a => a -> a -> Bool)
-> Interval a -> Interval a -> Bool
possibly forall a. Ord a => a -> a -> Bool
cmp Interval a
l Interval a
r
    | Bool
lt Bool -> Bool -> Bool
&& Bool
eq Bool -> Bool -> Bool
&& Bool
gt = Bool
True
    | Bool
lt Bool -> Bool -> Bool
&& Bool
eq       = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
<=? Interval a
r
    | Bool
lt Bool -> Bool -> Bool
&&       Bool
gt = Interval a
l Interval a -> Interval a -> Bool
forall a. Eq a => Interval a -> Interval a -> Bool
/=? Interval a
r
    | Bool
lt             = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
<? Interval a
r
    |       Bool
eq Bool -> Bool -> Bool
&& Bool
gt = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
>=? Interval a
r
    |       Bool
eq       = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
==? Interval a
r
    |             Bool
gt = Interval a
l Interval a -> Interval a -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
>? Interval a
r
    | Bool
otherwise      = Bool
False
    where
        lt :: Bool
lt = Ordering -> Ordering -> Bool
forall a. Ord a => a -> a -> Bool
cmp Ordering
LT Ordering
EQ
        eq :: Bool
eq = Ordering -> Ordering -> Bool
forall a. Ord a => a -> a -> Bool
cmp Ordering
EQ Ordering
EQ
        gt :: Bool
gt = Ordering -> Ordering -> Bool
forall a. Ord a => a -> a -> Bool
cmp Ordering
GT Ordering
EQ
{-# INLINE possibly #-}

-- | The nearest value to that supplied which is contained in the interval.
--
-- prop> (clamp xs y) `elem` xs
clamp :: Ord a => Interval a -> a -> a
clamp :: Interval a -> a -> a
clamp (I a
a a
b) a
x
  | a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
a     = a
a
  | a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
b     = a
b
  | Bool
otherwise = a
x

-- | Inflate an interval by enlarging it at both ends.
--
-- >>> inflate 3 (-1 ... 7)
-- -4 ... 10
--
-- >>> inflate (-2) (0 ... 4)
-- -2 ... 6
--
-- prop> inflate x i `contains` i
inflate :: (Num a, Ord a) => a -> Interval a -> Interval a
inflate :: a -> Interval a -> Interval a
inflate a
x Interval a
y = a -> Interval a
forall a. (Num a, Ord a) => a -> Interval a
symmetric a
x Interval a -> Interval a -> Interval a
forall a. Num a => a -> a -> a
+ Interval a
y

-- | Deflate an interval by shrinking it from both ends.
-- Note that in cases that would result in an empty interval, the result is a singleton interval at the midpoint.
--
-- >>> deflate 3.0 (-4.0 ... 10.0)
-- -1.0 ... 7.0
--
-- >>> deflate 2.0 (-1.0 ... 1.0)
-- 0.0 ... 0.0
deflate :: (Fractional a, Ord a) => a -> Interval a -> Interval a
deflate :: a -> Interval a -> Interval a
deflate a
x i :: Interval a
i@(I a
a a
b) | a
a' a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b'  = a -> a -> Interval a
forall a. a -> a -> Interval a
I a
a' a
b'
                    | Bool
otherwise = a -> Interval a
forall a. a -> Interval a
singleton a
m
  where
    a' :: a
a' = a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
x
    b' :: a
b' = a
b a -> a -> a
forall a. Num a => a -> a -> a
- a
x
    m :: a
m = Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint Interval a
i

-- | Scale an interval about its midpoint.
--
-- >>> scale 1.1 (-6.0 ... 4.0)
-- -6.5 ... 4.5
--
-- >>> scale (-2.0) (-1.0 ... 1.0)
-- -2.0 ... 2.0
--
-- prop> abs x >= 1 ==> (scale (x :: Double) i) `contains` i
-- prop> forAll (choose (0,1)) $ \x -> abs x <= 1 ==> i `contains` (scale (x :: Double) i)
scale :: (Fractional a, Ord a) => a -> Interval a -> Interval a
scale :: a -> Interval a -> Interval a
scale a
x Interval a
i = a
a a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... a
b where
  h :: a
h = a
x a -> a -> a
forall a. Num a => a -> a -> a
* Interval a -> a
forall a. Num a => Interval a -> a
width Interval a
i a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2
  mid :: a
mid = Interval a -> a
forall a. Fractional a => Interval a -> a
midpoint Interval a
i
  a :: a
a = a
mid a -> a -> a
forall a. Num a => a -> a -> a
- a
h
  b :: a
b = a
mid a -> a -> a
forall a. Num a => a -> a -> a
+ a
h

-- | Construct a symmetric interval.
--
-- >>> symmetric 3
-- -3 ... 3
--
-- >>> symmetric (-2)
-- -2 ... 2
--
-- prop> x `elem` symmetric x
-- prop> 0 `elem` symmetric x
symmetric :: (Num a, Ord a) => a -> Interval a
symmetric :: a -> Interval a
symmetric a
x = a -> a
forall a. Num a => a -> a
negate a
x a -> a -> Interval a
forall a. Ord a => a -> a -> Interval a
... a
x

-- | id function. Useful for type specification
--
-- >>> :t idouble (1 ... 3)
-- idouble (1 ... 3) :: Interval Double
idouble :: Interval Double -> Interval Double
idouble :: Interval Double -> Interval Double
idouble = Interval Double -> Interval Double
forall a. a -> a
id

-- | id function. Useful for type specification
--
-- >>> :t ifloat (1 ... 3)
-- ifloat (1 ... 3) :: Interval Float
ifloat :: Interval Float -> Interval Float
ifloat :: Interval Float -> Interval Float
ifloat = Interval Float -> Interval Float
forall a. a -> a
id

-- Bugs:
-- sin 1 :: Interval Double

default (Integer,Double)

-- | an interval containing all x `quot` y
-- prop> forAll (memberOf xs) $ \ x -> forAll (memberOf ys) $ \ y -> 0 `notMember` ys ==> (x `quot` y) `member` (xs `iquot` ys)
-- prop> 0 `member` ys ==> ioProperty $ do z <- try (evaluate (xs `iquot` ys)); return $ z === Left DivideByZero
iquot :: Integral a => Interval a -> Interval a -> Interval a
iquot :: Interval a -> Interval a -> Interval a
iquot (I a
l a
u) (I a
l' a
u') =
  if a
l' a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 Bool -> Bool -> Bool
&& a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u' then ArithException -> Interval a
forall a e. Exception e => e -> a
throw ArithException
DivideByZero else a -> a -> Interval a
forall a. a -> a -> Interval a
I
    ([a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a
a a -> a -> a
forall a. Integral a => a -> a -> a
`quot` a
b | a
a <- [a
l,a
u], a
b <- [a
l',a
u']])
    ([a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a
a a -> a -> a
forall a. Integral a => a -> a -> a
`quot` a
b | a
a <- [a
l,a
u], a
b <- [a
l',a
u']])

-- | an interval containing all x `rem` y
-- prop> forAll (memberOf xs) $ \ x -> forAll (memberOf ys) $ \ y -> 0 `notMember` ys ==> (x `rem` y) `member` (xs `irem` ys)
-- prop> 0 `member` ys ==> ioProperty $ do z <- try (evaluate (xs `irem` ys)); return $ z === Left DivideByZero
irem :: Integral a => Interval a -> Interval a -> Interval a
irem :: Interval a -> Interval a -> Interval a
irem (I a
l a
u) (I a
l' a
u') =
  if a
l' a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 Bool -> Bool -> Bool
&& a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u' then ArithException -> Interval a
forall a e. Exception e => e -> a
throw ArithException
DivideByZero else a -> a -> Interval a
forall a. a -> a -> Interval a
I
    ([a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a
0, a -> a
forall a. Num a => a -> a
signum a
l a -> a -> a
forall a. Num a => a -> a -> a
* (a -> a
forall a. Num a => a -> a
abs a
u' a -> a -> a
forall a. Num a => a -> a -> a
- a
1), a -> a
forall a. Num a => a -> a
signum a
l a -> a -> a
forall a. Num a => a -> a -> a
* (a -> a
forall a. Num a => a -> a
abs a
l' a -> a -> a
forall a. Num a => a -> a -> a
- a
1)])
    ([a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a
0, a -> a
forall a. Num a => a -> a
signum a
u a -> a -> a
forall a. Num a => a -> a -> a
* (a -> a
forall a. Num a => a -> a
abs a
u' a -> a -> a
forall a. Num a => a -> a -> a
- a
1), a -> a
forall a. Num a => a -> a
signum a
u a -> a -> a
forall a. Num a => a -> a -> a
* (a -> a
forall a. Num a => a -> a
abs a
l' a -> a -> a
forall a. Num a => a -> a -> a
- a
1)])

-- | an interval containing all x `div` y
-- prop> forAll (memberOf xs) $ \ x -> forAll (memberOf ys) $ \ y -> 0 `notMember` ys ==> (x `div` y) `member` (xs `idiv` ys)
-- prop> 0 `member` ys ==> ioProperty $ do z <- try (evaluate (xs `idiv` ys)); return $ z === Left DivideByZero
idiv :: Integral a => Interval a -> Interval a -> Interval a
idiv :: Interval a -> Interval a -> Interval a
idiv (I a
l a
u) (I a
l' a
u') =
  if a
l' a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 Bool -> Bool -> Bool
&& a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u' then ArithException -> Interval a
forall a e. Exception e => e -> a
throw ArithException
DivideByZero else a -> a -> Interval a
forall a. a -> a -> Interval a
I
    (a -> a -> a
forall a. Ord a => a -> a -> a
min (a
l a -> a -> a
forall a. Integral a => a -> a -> a
`Prelude.div` a -> a -> a
forall a. Ord a => a -> a -> a
max a
1 a
l') (a
u a -> a -> a
forall a. Integral a => a -> a -> a
`Prelude.div` a -> a -> a
forall a. Ord a => a -> a -> a
min (-a
1) a
u'))
    (a -> a -> a
forall a. Ord a => a -> a -> a
max (a
u a -> a -> a
forall a. Integral a => a -> a -> a
`Prelude.div` a -> a -> a
forall a. Ord a => a -> a -> a
max a
1 a
l') (a
l a -> a -> a
forall a. Integral a => a -> a -> a
`Prelude.div` a -> a -> a
forall a. Ord a => a -> a -> a
min (-a
1) a
u'))

-- | an interval containing all x `mod` y
-- prop> forAll (memberOf xs) $ \ x -> forAll (memberOf ys) $ \ y -> 0 `notMember` ys ==> (x `mod` y) `member` (xs `imod` ys)
-- prop> 0 `member` ys ==> ioProperty $ do z <- try (evaluate (xs `imod` ys)); return $ z === Left DivideByZero
imod :: Integral a => Interval a -> Interval a -> Interval a
imod :: Interval a -> Interval a -> Interval a
imod Interval a
_ (I a
l' a
u') =
  if a
l' a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 Bool -> Bool -> Bool
&& a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u' then ArithException -> Interval a
forall a e. Exception e => e -> a
throw ArithException
DivideByZero else
    a -> a -> Interval a
forall a. a -> a -> Interval a
I (a -> a -> a
forall a. Ord a => a -> a -> a
min (a
l'a -> a -> a
forall a. Num a => a -> a -> a
+a
1) a
0) (a -> a -> a
forall a. Ord a => a -> a -> a
max a
0 (a
u'a -> a -> a
forall a. Num a => a -> a -> a
-a
1))