packages feed

intervals 0.2.2.1 → 0.3

raw patch · 7 files changed

+603/−505 lines, 7 filesdep +ghc-primdep −numeric-extrasdep ~base

Dependencies added: ghc-prim

Dependencies removed: numeric-extras

Dependency ranges changed: base

Files

+ CHANGELOG.markdown view
@@ -0,0 +1,4 @@+0.3+---+* Removed dependency on `numeric-extras`+
+ HLint.hs view
@@ -0,0 +1,12 @@+import "hint" HLint.HLint++-- not viable+ignore "Reduce duplication"++-- don't want to!+ignore "Use infix"++-- these don't consider the corner cases when using doubles+ignore "Use >"+ignore "Use <="+ignore "Use >="
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2010, Edward Kmett+Copyright (c) 2010-2013, Edward Kmett  All rights reserved. @@ -13,10 +13,6 @@       copyright notice, this list of conditions and the following       disclaimer in the documentation and/or other materials provided       with the distribution.--    * Neither the name of Edward Kmett nor the names of other-      contributors may be used to endorse or promote products derived-      from this software without specific prior written permission.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
− Numeric/Interval.hs
@@ -1,484 +0,0 @@-{-# LANGUAGE Rank2Types, TypeFamilies #-}--------------------------------------------------------------------------------- |--- Module      :  Numeric.Interval--- Copyright   :  (c) Edward Kmett 2010--- License     :  BSD3--- Maintainer  :  ekmett@gmail.com--- Stability   :  experimental--- Portability :  GHC only------ Interval arithmetic-----------------------------------------------------------------------------------module Numeric.Interval -    ( Interval(..)-    , (...)-    , whole-    , empty-    , null-    , singleton-    , elem-    , notElem-    , inf-    , sup-    , singular-    , width-    , midpoint-    , intersection-    , hull-    , bisection-    , magnitude-    , mignitude-    , contains-    , isSubsetOf-    , certainly, (<!), (<=!), (==!), (>=!), (>!)-    , possibly, (<?), (<=?), (==?), (>=?), (>?)-    , idouble -    , ifloat -    ) where--import Prelude hiding (null, elem, notElem)-import Numeric.Extras-import Data.Function (on)--data Interval a = I !a !a--infix 3 ...--negInfinity :: Fractional a => a-negInfinity = (-1)/0 -{-# INLINE negInfinity #-}--posInfinity :: Fractional a => a-posInfinity = 1/0-{-# INLINE posInfinity #-}--nan :: Fractional a => a -nan = 0/0---- | The rule of thumb is you should only use this to construct using values--- that you took out of the interval. Otherwise, use I, to force rounding-(...) :: a -> a -> Interval a -a ... b = I a b-{-# INLINE (...) #-}---- | The whole real number line-whole :: Fractional a => Interval a -whole = negInfinity ... posInfinity-{-# INLINE whole #-}---- | An empty interval-empty :: Fractional a => Interval a -empty = nan ... nan-{-# INLINE empty #-}---- | negation handles NaN properly-null :: Ord a => Interval a -> Bool-null x = not (inf x <= sup x)-{-# INLINE null #-}---- | A singleton point-singleton :: a -> Interval a -singleton a = a ... a-{-# INLINE singleton #-}---- | The infinumum (lower bound) of an interval-inf :: Interval a -> a-inf (I a _) = a-{-# INLINE inf #-}---- | The supremum (upper bound) of an interval-sup :: Interval a -> a-sup (I _ b) = 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 :: Ord a => Interval a -> Bool-singular x = not (null x) && inf x == sup x-{-# INLINE singular #-}--instance Eq a => Eq (Interval a) where-    (==) = (==!) --instance Show a => Show (Interval a) where-    showsPrec n (I a b) =   -        showParen (n > 3) $-            showsPrec 3 a .-            showString " ... " . -            showsPrec 3 b---- | Calculate the width of an interval.-width :: Num a => Interval a -> a-width (I a b) = b - a-{-# INLINE width #-}---- | magnitude -magnitude :: (Num a, Ord a) => Interval a -> a -magnitude x = (max `on` abs) (inf x) (sup x)-{-# INLINE magnitude #-}---- | "mignitude"-mignitude :: (Num a, Ord a) => Interval a -> a -mignitude x = (min `on` abs) (inf x) (sup x)-{-# INLINE mignitude #-}--instance (Num a, Ord a) => Num (Interval a) where-    I a b + I a' b' = (a + a') ... (b + b')-    I a b - I a' b' = (a - b') ... (b - a')-    I a b * I a' b' = minimum [a * a', a * b', b * a', b * b'] -                      ...-                      maximum [a * a', a * b', b * a', b * b']-    abs x@(I a b) -        | a >= 0    = x -        | b <= 0    = negate x-        | otherwise = max (- a) b ... b--    signum = increasing signum--    fromInteger i = singleton (fromInteger i)---- | Bisect an interval at its midpoint.-bisection :: Fractional a => Interval a -> (Interval a, Interval a)-bisection x = (inf x ... m, m ... sup x)-    where m = midpoint x-{-# INLINE bisection #-}---- | Nearest point to the midpoint of the interval.-midpoint :: Fractional a => Interval a -> a-midpoint x = inf x + (sup x - inf x) / 2-{-# INLINE midpoint #-}--elem :: Ord a => a -> Interval a -> Bool-elem x xs = x >= inf xs && x <= sup xs-{-# INLINE elem #-}--notElem :: Ord a => a -> Interval a -> Bool-notElem x xs = not (elem x xs)-{-# INLINE notElem #-}---- | This means that realToFrac will use the midpoint---- | What moron put an Ord instance requirement on Real!-instance Real a => Real (Interval a) where-    toRational x -        | null x   = nan-        | otherwise = a + (b - a) / 2-        where-            a = toRational (inf x)-            b = toRational (sup x)--instance Ord a => Ord (Interval a) where-    compare x y -        | sup x < inf y = LT-        | inf x > sup y = GT-        | sup x == inf y && inf x == sup y = EQ-        | otherwise = error "Numeric.Interval.compare: ambiguous comparison"-    min = minInterval-    max = maxInterval---- @'divNonZero' X Y@ assumes @0 `'notElem'` Y@-divNonZero :: (Fractional a, Ord a) => Interval a -> Interval a -> Interval a -divNonZero (I a b) (I a' b') = -    minimum [a / a', a / b', b / a', b / b'] -    `I`-    maximum [a / a', a / b', b / a', b / b']---- @'divPositive' X y@ assumes y > 0, and divides @X@ by [0 ... y]-divPositive :: (Fractional a, Ord a) => Interval a -> a -> Interval a -divPositive x@(I a b) y-    | a == 0 && b == 0 = x-    -- b < 0 || isNegativeZero b = negInfinity `I` ( b / y)-    | b < 0 = negInfinity `I` ( b / y)-    | a < 0 = whole -    | otherwise = (a / y) `I` posInfinity---- divNegative assumes y < 0 and divides the interval @X@ by [y ... 0]-divNegative :: (Fractional a, Ord a) => Interval a -> a -> Interval a-divNegative x@(I a b) y-    | a == 0 && b == 0 = - x -- flip negative zeros-    -- b < 0 || isNegativeZero b = (b / y) `I` posInfinity-    | b < 0 = (b / y) `I` posInfinity-    | a < 0 = whole-    | otherwise = negInfinity `I` (a / y)--divZero :: (Fractional a, Ord a) => Interval a -> Interval a-divZero x | inf x == 0 && sup x == 0 = x-          | otherwise = whole--instance (Fractional a, Ord a) => Fractional (Interval a) where-    -- TODO: check isNegativeZero properly-    x / y-        | 0 `notElem` y = divNonZero x y -        | iz && sz  = empty -- division by 0-        | iz        = divPositive x (inf y)-        |       sz  = divNegative x (sup y)-        | otherwise = divZero x-        where -            iz = inf y == 0-            sz = sup y == 0-    recip (I a b)   = on min recip a b ... on max recip a b-    fromRational r  = fromRational r ... fromRational r--instance RealFloat a => RealFrac (Interval a) where-    properFraction x = (b, x - fromIntegral b)-        where -            b = truncate (midpoint x)-    ceiling x = ceiling (sup x)-    floor x = floor (inf x)-    round x = round (midpoint x)-    truncate x = truncate (midpoint x)--instance (RealExtras a, Ord a) => Floating (Interval a) where-    pi = singleton pi-    exp = increasing exp-    log (I a b) = (if a > 0 then log a else negInfinity) ... log b-    cos x -        | null x = empty-        | width t >= pi = (-1) ... 1-        | inf t >= pi = - cos (t - pi)-        | sup t <= pi = decreasing cos t-        | sup t <= 2 * pi = (-1) ... cos ((pi * 2 - sup t) `min` inf t)-        | otherwise = (-1) ... 1-        where -            t = fmod x (pi * 2)-    sin x -        | null x = empty-        | otherwise = cos (x - pi / 2)-    tan x -        | null x = empty-        | inf t' <= - pi / 2 || sup t' >= pi / 2 = whole-        | otherwise = increasing tan x-        where-            t = x `fmod` pi -            t' | t >= pi / 2 = t - pi-               | otherwise    = t-    asin x@(I a b)-        | null x || b < -1 || a > 1 = empty-        | otherwise = -            (if a <= -1 then -halfPi else asin a)-            `I`-            (if b >= 1 then halfPi else asin b)-        where-            halfPi = pi / 2-    acos x@(I a b)-        | null x || b < -1 || a > 1 = empty-        | otherwise = -            (if b >= 1 then 0 else acos b)-            `I`-            (if a < -1 then pi else acos a)-    atan = increasing atan-    sinh = increasing sinh-    cosh x@(I a b)-        | null x = empty-        | b < 0  = decreasing cosh x-        | a >= 0 = increasing cosh x-        | otherwise  = I 0 $ cosh $ if - a > b-                                    then a -                                    else b-    tanh = increasing tanh-    asinh = increasing asinh-    acosh x@(I a b)-        | null x || b < 1 = empty-        | otherwise = I lo $ acosh b-        where lo | a <= 1 = 0 -                 | otherwise = acosh a-    atanh x@(I a b)-        | null x || b < -1 || a > 1 = empty-        | otherwise =-                (if a <= - 1 then negInfinity else atanh a)-                `I`-                (if b >= 1 then posInfinity else atanh b)-    --- | lift a monotone increasing function over a given interval -increasing :: (a -> a) -> Interval a -> Interval a-increasing f (I a b) = I (f a) (f b)---- | lift a monotone increasing function over a given interval -decreasing :: (a -> a) -> Interval a -> Interval a-decreasing f (I a b) = I (f b) (f a)---- | We have to play some semantic games to make these methods make sense.--- Most compute with the midpoint of the interval.-instance RealExtras a => RealFloat (Interval a) where-    floatRadix = floatRadix . midpoint-    floatDigits = floatDigits . midpoint-    floatRange = floatRange . midpoint-    decodeFloat = decodeFloat . midpoint-    encodeFloat m e = singleton (encodeFloat m e)-    exponent = exponent . midpoint-    significand x = min a b ... max a b-        where-            (_ ,em) = decodeFloat (midpoint x)-            (mi,ei) = decodeFloat (inf x)-            (ms,es) = decodeFloat (sup x)-            a = encodeFloat mi (ei - em - floatDigits x) -            b = encodeFloat ms (es - em - floatDigits x)-    scaleFloat n x = scaleFloat n (inf x) ... scaleFloat n (sup x)-    isNaN x = isNaN (inf x) || isNaN (sup x)-    isInfinite x = isInfinite (inf x) || isInfinite (sup x)-    isDenormalized x = isDenormalized (inf x) || isDenormalized (sup x)-    -- contains negative zero-    isNegativeZero x = not (inf x > 0) -                    && not (sup x < 0)-                    && (  (sup x == 0 && (inf x < 0 || isNegativeZero (inf x)))-                       || (inf x == 0 && isNegativeZero (inf x)) -                       || (inf x < 0 && sup x >= 0))-    isIEEE x = isIEEE (inf x) && isIEEE (sup x)-    atan2 = error "unimplemented"---- TODO: (^), (^^) to give tighter bounds-        --- | Calculate the intersection of two intervals.-intersection :: (Fractional a, Ord a) => Interval a -> Interval a -> Interval a-intersection x@(I a b) y@(I a' b')-    | x /=! y = empty-    | otherwise = I (max a a') (min b b')-{-# INLINE intersection #-}---- | Calculate the convex hull of two intervals-hull :: Ord a => Interval a -> Interval a -> Interval a-hull x@(I a b) y@(I a' b') -    | null x = y-    | null y = x-    | otherwise = I (min a a') (max b b')-{-# INLINE hull #-}-    -instance RealExtras a => RealExtras (Interval a) where-    type C (Interval a) = C a-    fmod x y | null y = empty -             | otherwise = r -- `intersection` bounds-        where -            n :: Integer-            n = floor (inf x / if inf x < 0 then inf y else sup y)-            r = x - fromIntegral n * y -            -- bounds | inf y >= 0 = y-            --        | otherwise = y `hull` negate y-    expm1 = increasing expm1-    log1p (I a b) = (if a > (-1) then log1p a else negInfinity) `I` log1p b-    hypot x y = hypot a a' `I` hypot b b'-        where-            I a b = abs x-            I a' b' = abs y-    cbrt = increasing cbrt-    erf = increasing erf---- | For all @x@ in @X@, @y@ in @Y@. @x '<' y@-(<!)  :: Ord a => Interval a -> Interval a -> Bool-x <! y = sup x < inf y-{-# INLINE (<!) #-}---- | For all @x@ in @X@, @y@ in @Y@. @x '<=' y@-(<=!) :: Ord a => Interval a -> Interval a -> Bool-x <=! y = sup x <= inf y-{-# INLINE (<=!) #-}---- | For all @x@ in @X@, @y@ in @Y@. @x '==' y@-(==!) :: Eq a => Interval a -> Interval a -> Bool-x ==! y = sup x == inf y && inf x == sup y-{-# INLINE (==!) #-}---- | For all @x@ in @X@, @y@ in @Y@. @x '/=' y@-(/=!) :: Ord a => Interval a -> Interval a -> Bool-x /=! y = sup x < inf y || inf x > sup y-{-# INLINE (/=!) #-}---- | For all @x@ in @X@, @y@ in @Y@. @x '>' y@-(>!)  :: Ord a => Interval a -> Interval a -> Bool-x >! y = inf x > sup y-{-# INLINE (>!) #-}---- | For all @x@ in @X@, @y@ in @Y@. @x '>=' y@-(>=!) :: Ord a => Interval a -> Interval a -> Bool-x >=! y = inf x >= sup y-{-# 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 cmp l r -    | lt && eq && gt = True-    | lt && eq       = l <=! r-    | lt &&       gt = l /=! r-    | lt             = l <! r -    |       eq && gt = l >=! r -    |       eq       = l ==! r-    |             gt = l >! r-    | otherwise      = False-    where -        lt = cmp LT EQ-        eq = cmp EQ EQ-        gt = cmp GT EQ-{-# INLINE certainly #-}--contains :: Ord a => Interval a -> Interval a -> Bool-contains x y = null y -            || (not (null x) && inf x <= inf y && sup y <= sup x)-{-# INLINE contains #-}--isSubsetOf :: Ord a => Interval a -> Interval a -> Bool-isSubsetOf = flip contains--maxInterval :: Ord a => Interval a -> Interval a -> Interval a-maxInterval  (I a b) (I a' b') = I (max a a') (max b b')--minInterval :: Ord a => Interval a -> Interval a -> Interval a-minInterval  (I a b) (I a' b') = I (min a a') (min b b')---- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<' y@?-(<?) :: Ord a => Interval a -> Interval a -> Bool-x <? y = inf x < sup y-{-# INLINE (<?) #-}---- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<=' y@?-(<=?) :: Ord a => Interval a -> Interval a -> Bool-x <=? y = inf x <= sup y-{-# INLINE (<=?) #-}---- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '==' y@?-(==?) :: Ord a => Interval a -> Interval a -> Bool-x ==? y = inf x <= sup y && sup x >= inf y-{-# INLINE (==?) #-}---- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '/=' y@?-(/=?) :: Eq a => Interval a -> Interval a -> Bool-x /=? y = inf x /= sup y || sup x /= inf y-{-# INLINE (/=?) #-}---- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>' y@?-(>?) :: Ord a => Interval a -> Interval a -> Bool-x >? y = sup x > inf y-{-# INLINE (>?) #-}---- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>=' y@?-(>=?) :: Ord a => Interval a -> Interval a -> Bool-x >=? y = sup x >= inf y-{-# 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 cmp l r -    | lt && eq && gt = True-    | lt && eq       = l <=? r-    | lt &&       gt = l /=? r-    | lt             = l <? r -    |       eq && gt = l >=? r -    |       eq       = l ==? r-    |             gt = l >? r-    | otherwise      = False-    where -        lt = cmp LT EQ-        eq = cmp EQ EQ-        gt = cmp GT EQ-{-# INLINE possibly #-}--idouble :: Interval Double -> Interval Double-idouble = id--ifloat :: Interval Float -> Interval Float-ifloat = id---- Bugs:--- sin 1 :: Interval Double
+ README.markdown view
@@ -0,0 +1,15 @@+intervals+==========++[![Build Status](https://secure.travis-ci.org/ekmett/intervals.png?branch=master)](http://travis-ci.org/ekmett/intervals)++Basic interval arithmetic++Contact Information+-------------------++Contributions and bug reports are welcome!++Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.++-Edward Kmett
intervals.cabal view
@@ -1,14 +1,13 @@ name:              intervals-version:           0.2.2.1+version:           0.3 synopsis:          Interval Arithmetic description:-    A 'Numeric.Interval.Interval' is a closed, convex set of floating point values.-    .-    We do not control the rounding mode of the end points of the interval when-    using floating point arithmetic, so be aware that in order to get precise-    containment of the result, you will need to use an underlying type with-    both lower and upper bounds like 'CReal'-+  A 'Numeric.Interval.Interval' is a closed, convex set of floating point values.+  .+  We do not control the rounding mode of the end points of the interval when+  using floating point arithmetic, so be aware that in order to get precise+  containment of the result, you will need to use an underlying type with+  both lower and upper bounds like 'CReal' homepage:           http://github.com/ekmett/intervals bug-reports:        http://github.com/ekmett/intervals/issues license:            BSD3@@ -18,20 +17,23 @@ category:           Math build-type:         Simple cabal-version:      >=1.6-extra-source-files: .travis.yml-tested-with:        GHC == 7.4.2, GHC == 7.6.1+extra-source-files: .travis.yml CHANGELOG.markdown README.markdown HLint.hs+tested-with:        GHC == 7.4.2, GHC == 7.6.1, GHC == 7.6.3  source-repository head   type: git   location: git://github.com/ekmett/intervals.git  library-  other-extensions:-    Rank2Types-    TypeFamilies+  hs-source-dirs: src+   exposed-modules: Numeric.Interval+   build-depends:-    base           >= 4     && < 5,     array          >= 0.3   && < 0.6,-    numeric-extras >= 0.0.1 && < 0.1-  ghc-options:     -Wall+    base           >= 4     && < 5++  if impl(ghc >=7.4)+    build-depends: ghc-prim++  ghc-options:     -Wall -O2
+ src/Numeric/Interval.hs view
@@ -0,0 +1,553 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE DeriveDataTypeable #-}+#if defined(__GLASGOW_HASKELL) && __GLASGOW_HASKELL__ >= 704+{-# LANGUAGE DeriveGeneric #-}+#endif+-----------------------------------------------------------------------------+-- |+-- Module      :  Numeric.Interval+-- Copyright   :  (c) Edward Kmett 2010-2013+-- License     :  BSD3+-- Maintainer  :  ekmett@gmail.com+-- Stability   :  experimental+-- Portability :  DeriveDataTypeable+--+-- Interval arithmetic+--+-----------------------------------------------------------------------------++module Numeric.Interval+  ( Interval(..)+  , (...)+  , whole+  , empty+  , null+  , singleton+  , elem+  , notElem+  , inf+  , sup+  , singular+  , width+  , midpoint+  , intersection+  , hull+  , bisection+  , magnitude+  , mignitude+  , contains+  , isSubsetOf+  , certainly, (<!), (<=!), (==!), (>=!), (>!)+  , possibly, (<?), (<=?), (==?), (>=?), (>?)+  , idouble+  , ifloat+  ) where++import Control.Applicative hiding (empty)+import Data.Data+import Data.Foldable hiding (minimum, maximum, elem, notElem)+import Data.Function (on)+import Data.Monoid+import Data.Traversable+#if defined(__GLASGOW_HASKELL) && __GLASGOW_HASKELL__ >= 704+import GHC.Generics+#endif+import Prelude hiding (null, elem, notElem)++data Interval a = I !a !a deriving+  ( Data+  , Typeable+#if defined(__GLASGOW_HASKELL) && __GLASGOW_HASKELL__ >= 704+  , Generic+#if __GLASGOW_HASKELL__ >= 706+  , Generic1+#endif+#endif+  )++instance Functor Interval where+  fmap f (I a b) = I (f a) (f b)+  {-# INLINE fmap #-}++instance Foldable Interval where+  foldMap f (I a b) = f a `mappend` f b+  {-# INLINE foldMap #-}++instance Traversable Interval where+  traverse f (I a b) = I <$> f a <*> f b+  {-# INLINE traverse #-}++instance Applicative Interval where+  pure a = I a a+  {-# INLINE pure #-}+  I f g <*> I a b = I (f a) (g b)+  {-# INLINE (<*>) #-}++instance Monad Interval where+  return a = I a a+  {-# INLINE return #-}+  I a b >>= f = I a' b' where+    I a' _ = f a+    I _ b' = f b+  {-# INLINE (>>=) #-}++infix 3 ...++negInfinity :: Fractional a => a+negInfinity = (-1)/0+{-# INLINE negInfinity #-}++posInfinity :: Fractional a => a+posInfinity = 1/0+{-# INLINE posInfinity #-}++nan :: Fractional a => a+nan = 0/0++fmod :: RealFrac a => a -> a -> a+fmod a b = a - q*b where+  q = realToFrac (truncate $ a / b :: Integer)+{-# INLINE fmod #-}++-- | The rule of thumb is you should only use this to construct using values+-- that you took out of the interval. Otherwise, use I, to force rounding+(...) :: a -> a -> Interval a+(...) = I+{-# INLINE (...) #-}++-- | The whole real number line+whole :: Fractional a => Interval a+whole = negInfinity ... posInfinity+{-# INLINE whole #-}++-- | An empty interval+empty :: Fractional a => Interval a+empty = nan ... nan+{-# INLINE empty #-}++-- | negation handles NaN properly+null :: Ord a => Interval a -> Bool+null x = not (inf x <= sup x)+{-# INLINE null #-}++-- | A singleton point+singleton :: a -> Interval a+singleton a = a ... a+{-# INLINE singleton #-}++-- | The infinumum (lower bound) of an interval+inf :: Interval a -> a+inf (I a _) = a+{-# INLINE inf #-}++-- | The supremum (upper bound) of an interval+sup :: Interval a -> a+sup (I _ b) = 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 :: Ord a => Interval a -> Bool+singular x = not (null x) && inf x == sup x+{-# INLINE singular #-}++instance Eq a => Eq (Interval a) where+  (==) = (==!)+  {-# INLINE (==) #-}++instance Show a => Show (Interval a) where+  showsPrec n (I a b) =+    showParen (n > 3) $+      showsPrec 3 a .+      showString " ... " .+      showsPrec 3 b++-- | Calculate the width of an interval.+width :: Num a => Interval a -> a+width (I a b) = b - a+{-# INLINE width #-}++-- | Magnitude+magnitude :: (Num a, Ord a) => Interval a -> a+magnitude x = (max `on` abs) (inf x) (sup x)+{-# INLINE magnitude #-}++-- | \"mignitude\"+mignitude :: (Num a, Ord a) => Interval a -> a+mignitude x = (min `on` abs) (inf x) (sup x)+{-# INLINE mignitude #-}++instance (Num a, Ord a) => Num (Interval a) where+  I a b + I a' b' = (a + a') ... (b + b')+  {-# INLINE (+) #-}+  I a b - I a' b' = (a - b') ... (b - a')+  {-# INLINE (-) #-}+  I a b * I a' b' =+    minimum [a * a', a * b', b * a', b * b']+    ...+    maximum [a * a', a * b', b * a', b * b']+  {-# INLINE (*) #-}+  abs x@(I a b)+    | a >= 0    = x+    | b <= 0    = negate x+    | otherwise = 0 ... max (- a) b+  {-# INLINE abs #-}++  signum = increasing signum+  {-# INLINE signum #-}++  fromInteger i = singleton (fromInteger i)+  {-# INLINE fromInteger #-}++-- | Bisect an interval at its midpoint.+bisection :: Fractional a => Interval a -> (Interval a, Interval a)+bisection x = (inf x ... m, m ... sup x)+  where m = midpoint x+{-# INLINE bisection #-}++-- | Nearest point to the midpoint of the interval.+midpoint :: Fractional a => Interval a -> a+midpoint x = inf x + (sup x - inf x) / 2+{-# INLINE midpoint #-}++elem :: Ord a => a -> Interval a -> Bool+elem x xs = x >= inf xs && x <= sup xs+{-# INLINE elem #-}++notElem :: Ord a => a -> Interval a -> Bool+notElem x xs = not (elem x xs)+{-# INLINE notElem #-}++-- | This means that realToFrac will use the midpoint++-- | What moron put an Ord instance requirement on Real!+instance Real a => Real (Interval a) where+  toRational x+    | null x   = nan+    | otherwise = a + (b - a) / 2+    where+      a = toRational (inf x)+      b = toRational (sup x)+  {-# INLINE toRational #-}++instance Ord a => Ord (Interval a) where+  compare x y+    | sup x < inf y = LT+    | inf x > sup y = GT+    | sup x == inf y && inf x == sup y = EQ+    | otherwise = error "Numeric.Interval.compare: ambiguous comparison"+  {-# INLINE compare #-}++  max (I a b) (I a' b') = max a a' ... max b b'+  {-# INLINE max #-}++  min (I a b) (I a' b') = min a a' ... min b b'+  {-# INLINE min #-}++-- @'divNonZero' X Y@ assumes @0 `'notElem'` Y@+divNonZero :: (Fractional a, Ord a) => Interval a -> Interval a -> Interval a+divNonZero (I a b) (I a' b') =+  minimum [a / a', a / b', b / a', b / b']+  ...+  maximum [a / a', a / b', b / a', b / b']++-- @'divPositive' X y@ assumes y > 0, and divides @X@ by [0 ... y]+divPositive :: (Fractional a, Ord a) => Interval a -> a -> Interval a+divPositive x@(I a b) y+  | a == 0 && b == 0 = x+  -- b < 0 || isNegativeZero b = negInfinity ... ( b / y)+  | b < 0 = negInfinity ... ( b / y)+  | a < 0 = whole+  | otherwise = (a / y) ... 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 x@(I a b) y+  | a == 0 && b == 0 = - x -- flip negative zeros+  -- b < 0 || isNegativeZero b = (b / y) ... posInfinity+  | b < 0 = (b / y) ... posInfinity+  | a < 0 = whole+  | otherwise = negInfinity ... (a / y)+{-# INLINE divNegative #-}++divZero :: (Fractional a, Ord a) => Interval a -> Interval a+divZero x+  | inf x == 0 && sup x == 0 = x+  | otherwise = whole+{-# INLINE divZero #-}++instance (Fractional a, Ord a) => Fractional (Interval a) where+  -- TODO: check isNegativeZero properly+  x / y+    | 0 `notElem` y = divNonZero x y+    | iz && sz  = empty -- division by 0+    | iz        = divPositive x (inf y)+    |       sz  = divNegative x (sup y)+    | otherwise = divZero x+    where+      iz = inf y == 0+      sz = sup y == 0+  recip (I a b)   = on min recip a b ... on max recip a b+  {-# INLINE recip #-}+  fromRational r  = let r' = fromRational r in r' ... r'+  {-# INLINE fromRational #-}++instance RealFrac a => RealFrac (Interval a) where+  properFraction x = (b, x - fromIntegral b)+    where+      b = truncate (midpoint x)+  {-# INLINE properFraction #-}+  ceiling x = ceiling (sup x)+  {-# INLINE ceiling #-}+  floor x = floor (inf x)+  {-# INLINE floor #-}+  round x = round (midpoint x)+  {-# INLINE round #-}+  truncate x = truncate (midpoint x)+  {-# INLINE truncate #-}++instance (RealFloat a, Ord a) => Floating (Interval a) where+  pi = singleton pi+  {-# INLINE pi #-}+  exp = increasing exp+  {-# INLINE exp #-}+  log (I a b) = (if a > 0 then log a else negInfinity) ... log b+  {-# INLINE log #-}+  cos x+    | null x = empty+    | width t >= pi = (-1) ... 1+    | inf t >= pi = - cos (t - pi)+    | sup t <= pi = decreasing cos t+    | sup t <= 2 * pi = (-1) ... cos ((pi * 2 - sup t) `min` inf t)+    | otherwise = (-1) ... 1+    where+      t = fmod x (pi * 2)+  {-# INLINE cos #-}+  sin x+    | null x = empty+    | otherwise = cos (x - pi / 2)+  {-# INLINE sin #-}+  tan x+    | null x = empty+    | inf t' <= - pi / 2 || sup t' >= pi / 2 = whole+    | otherwise = increasing tan x+    where+      t = x `fmod` pi+      t' | t >= pi / 2 = t - pi+         | otherwise    = t+  {-# INLINE tan #-}+  asin x@(I a b)+    | null x || b < -1 || a > 1 = empty+    | otherwise =+      (if a <= -1 then -halfPi else asin a)+      ...+      (if b >= 1 then halfPi else asin b)+    where+      halfPi = pi / 2+  {-# INLINE asin #-}+  acos x@(I a b)+    | null x || b < -1 || a > 1 = empty+    | otherwise =+      (if b >= 1 then 0 else acos b)+      ...+      (if a < -1 then pi else acos a)+  {-# INLINE acos #-}+  atan = increasing atan+  {-# INLINE atan #-}+  sinh = increasing sinh+  {-# INLINE sinh #-}+  cosh x@(I a b)+    | null x = empty+    | b < 0  = decreasing cosh x+    | a >= 0 = increasing cosh x+    | otherwise  = I 0 $ cosh $ if - a > b+                                then a+                                else b+  {-# INLINE cosh #-}+  tanh = increasing tanh+  {-# INLINE tanh #-}+  asinh = increasing asinh+  {-# INLINE asinh #-}+  acosh x@(I a b)+    | null x || b < 1 = empty+    | otherwise = I lo $ acosh b+    where lo | a <= 1 = 0+             | otherwise = acosh a+  {-# INLINE acosh #-}+  atanh x@(I a b)+    | null x || b < -1 || a > 1 = empty+    | otherwise =+      (if a <= - 1 then negInfinity else atanh a)+      ...+      (if b >= 1 then posInfinity else atanh b)+  {-# INLINE atanh #-}++-- | lift a monotone increasing function over a given interval+increasing :: (a -> b) -> Interval a -> Interval b+increasing f (I a b) = f a ... f b++-- | lift a monotone increasing function over a given interval+decreasing :: (a -> b) -> Interval a -> Interval b+decreasing f (I a b) = f b ... f 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 = floatRadix . midpoint++  floatDigits = floatDigits . midpoint+  floatRange = floatRange . midpoint+  decodeFloat = decodeFloat . midpoint+  encodeFloat m e = singleton (encodeFloat m e)+  exponent = exponent . midpoint+  significand x = min a b ... max a b+    where+      (_ ,em) = decodeFloat (midpoint x)+      (mi,ei) = decodeFloat (inf x)+      (ms,es) = decodeFloat (sup x)+      a = encodeFloat mi (ei - em - floatDigits x)+      b = encodeFloat ms (es - em - floatDigits x)+  scaleFloat n x = scaleFloat n (inf x) ... scaleFloat n (sup x)+  isNaN x = isNaN (inf x) || isNaN (sup x)+  isInfinite x = isInfinite (inf x) || isInfinite (sup x)+  isDenormalized x = isDenormalized (inf x) || isDenormalized (sup x)+  -- contains negative zero+  isNegativeZero x = not (inf x > 0)+                  && not (sup x < 0)+                  && (  (sup x == 0 && (inf x < 0 || isNegativeZero (inf x)))+                     || (inf x == 0 && isNegativeZero (inf x))+                     || (inf x < 0 && sup x >= 0))+  isIEEE x = isIEEE (inf x) && isIEEE (sup x)+  atan2 = error "unimplemented"++-- TODO: (^), (^^) to give tighter bounds++-- | Calculate the intersection of two intervals.+intersection :: (Fractional a, Ord a) => Interval a -> Interval a -> Interval a+intersection x@(I a b) y@(I a' b')+  | x /=! y = empty+  | otherwise = max a a' ... min b b'+{-# INLINE intersection #-}++-- | Calculate the convex hull of two intervals+hull :: Ord a => Interval a -> Interval a -> Interval a+hull x@(I a b) y@(I a' b')+  | null x = y+  | null y = x+  | otherwise = min a a' ... max b b'+{-# INLINE hull #-}++-- | For all @x@ in @X@, @y@ in @Y@. @x '<' y@+(<!)  :: Ord a => Interval a -> Interval a -> Bool+x <! y = sup x < inf y+{-# INLINE (<!) #-}++-- | For all @x@ in @X@, @y@ in @Y@. @x '<=' y@+(<=!) :: Ord a => Interval a -> Interval a -> Bool+x <=! y = sup x <= inf y+{-# INLINE (<=!) #-}++-- | For all @x@ in @X@, @y@ in @Y@. @x '==' y@+(==!) :: Eq a => Interval a -> Interval a -> Bool+x ==! y = sup x == inf y && inf x == sup y+{-# INLINE (==!) #-}++-- | For all @x@ in @X@, @y@ in @Y@. @x '/=' y@+(/=!) :: Ord a => Interval a -> Interval a -> Bool+x /=! y = sup x < inf y || inf x > sup y+{-# INLINE (/=!) #-}++-- | For all @x@ in @X@, @y@ in @Y@. @x '>' y@+(>!)  :: Ord a => Interval a -> Interval a -> Bool+x >! y = inf x > sup y+{-# INLINE (>!) #-}++-- | For all @x@ in @X@, @y@ in @Y@. @x '>=' y@+(>=!) :: Ord a => Interval a -> Interval a -> Bool+x >=! y = inf x >= sup y+{-# 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 cmp l r+    | lt && eq && gt = True+    | lt && eq       = l <=! r+    | lt &&       gt = l /=! r+    | lt             = l <!  r+    |       eq && gt = l >=! r+    |       eq       = l ==! r+    |             gt = l >!  r+    | otherwise      = False+    where+        lt = cmp LT EQ+        eq = cmp EQ EQ+        gt = cmp GT EQ+{-# INLINE certainly #-}++contains :: Ord a => Interval a -> Interval a -> Bool+contains x y = null y+            || (not (null x) && inf x <= inf y && sup y <= sup x)+{-# INLINE contains #-}++isSubsetOf :: Ord a => Interval a -> Interval a -> Bool+isSubsetOf = flip contains+{-# INLINE isSubsetOf #-}++-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<' y@?+(<?) :: Ord a => Interval a -> Interval a -> Bool+x <? y = inf x < sup y+{-# INLINE (<?) #-}++-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<=' y@?+(<=?) :: Ord a => Interval a -> Interval a -> Bool+x <=? y = inf x <= sup y+{-# INLINE (<=?) #-}++-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '==' y@?+(==?) :: Ord a => Interval a -> Interval a -> Bool+x ==? y = inf x <= sup y && sup x >= inf y+{-# INLINE (==?) #-}++-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '/=' y@?+(/=?) :: Eq a => Interval a -> Interval a -> Bool+x /=? y = inf x /= sup y || sup x /= inf y+{-# INLINE (/=?) #-}++-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>' y@?+(>?) :: Ord a => Interval a -> Interval a -> Bool+x >? y = sup x > inf y+{-# INLINE (>?) #-}++-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>=' y@?+(>=?) :: Ord a => Interval a -> Interval a -> Bool+x >=? y = sup x >= inf y+{-# 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 cmp l r+    | lt && eq && gt = True+    | lt && eq       = l <=? r+    | lt &&       gt = l /=? r+    | lt             = l <? r+    |       eq && gt = l >=? r+    |       eq       = l ==? r+    |             gt = l >? r+    | otherwise      = False+    where+        lt = cmp LT EQ+        eq = cmp EQ EQ+        gt = cmp GT EQ+{-# INLINE possibly #-}++idouble :: Interval Double -> Interval Double+idouble = id++ifloat :: Interval Float -> Interval Float+ifloat = id++-- Bugs:+-- sin 1 :: Interval Double