intervals 0.5.1.1 → 0.6
raw patch · 6 files changed
+69/−29 lines, 6 files
Files
- CHANGELOG.markdown +4/−0
- intervals.cabal +2/−1
- src/Numeric/Interval/Exception.hs +24/−0
- src/Numeric/Interval/Internal.hs +28/−21
- src/Numeric/Interval/Kaucher.hs +4/−2
- src/Numeric/Interval/NonEmpty/Internal.hs +7/−5
CHANGELOG.markdown view
@@ -1,3 +1,7 @@+0.6+---+* Added `Numeric.Interval.Exception`. For consistency, we tend to throw exceptions now instead of rely on `NaN` when working with empty intervals.+ 0.5.1.1 ------- * Misc `doctest` fixes.
intervals.cabal view
@@ -1,5 +1,5 @@ name: intervals-version: 0.5.1.1+version: 0.6 synopsis: Interval Arithmetic description: A 'Numeric.Interval.Interval' is a closed, convex set of floating point values.@@ -40,6 +40,7 @@ exposed-modules: Numeric.Interval+ Numeric.Interval.Exception Numeric.Interval.Internal Numeric.Interval.Kaucher Numeric.Interval.NonEmpty
+ src/Numeric/Interval/Exception.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE DeriveDataTypeable #-}+module Numeric.Interval.Exception+ ( EmptyInterval(..)+ , AmbiguousComparison(..)+ ) where++import Control.Exception+import Data.Data++data EmptyInterval = EmptyInterval+ deriving (Eq,Ord,Typeable,Data)++instance Show EmptyInterval where+ show EmptyInterval = "empty interval"++instance Exception EmptyInterval++data AmbiguousComparison = AmbiguousComparison+ deriving (Eq,Ord,Typeable,Data)++instance Show AmbiguousComparison where+ show AmbiguousComparison = "ambiguous comparison"++instance Exception AmbiguousComparison
src/Numeric/Interval/Internal.hs view
@@ -46,6 +46,7 @@ , ifloat ) where +import Control.Exception as Exception import Data.Data import Data.Foldable hiding (minimum, maximum, elem, notElem) import Data.Function (on)@@ -53,6 +54,7 @@ #if defined(__GLASGOW_HASKELL) && __GLASGOW_HASKELL__ >= 704 import GHC.Generics #endif+import Numeric.Interval.Exception import Prelude hiding (null, elem, notElem) -- $setup@@ -89,9 +91,6 @@ | otherwise = Nothing {-# INLINE interval #-} -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)@@ -119,7 +118,7 @@ empty = Empty {-# INLINE empty #-} --- | negation handles NaN properly+-- | Check if an interval is empty -- -- >>> null (1 ... 5) -- False@@ -142,22 +141,28 @@ singleton a = I a a {-# INLINE singleton #-} --- | The infinumum (lower bound) of an interval+-- | The infimum (lower bound) of an interval -- -- >>> inf (1.0 ... 20.0) -- 1.0-inf :: Fractional a => Interval a -> a+--+-- >>> inf empty+-- *** Exception: empty interval+inf :: Interval a -> a inf (I a _) = a-inf Empty = nan+inf Empty = Exception.throw EmptyInterval {-# INLINE inf #-} -- | The supremum (upper bound) of an interval -- -- >>> sup (1.0 ... 20.0) -- 20.0-sup :: Fractional a => Interval a -> a+--+-- >>> sup empty+-- *** Exception: empty interval+sup :: Interval a -> a sup (I _ b) = b-sup Empty = nan+sup Empty = Exception.throw EmptyInterval {-# INLINE sup #-} -- | Is the interval a singleton point?@@ -212,11 +217,12 @@ -- >>> magnitude (singleton 5) -- 5 --+-- throws 'EmptyInterval' if the interval is empty.+-- -- >>> magnitude empty--- 0+-- *** Exception: empty interval magnitude :: (Num a, Ord a) => Interval a -> a-magnitude (I a b) = on max abs a b-magnitude Empty = 0+magnitude = sup . abs {-# INLINE magnitude #-} -- | \"mignitude\"@@ -225,16 +231,17 @@ -- 1 -- -- >>> mignitude (-20 ... 10)--- 10+-- 0 -- -- >>> mignitude (singleton 5) -- 5 --+-- throws 'EmptyInterval' if the interval is empty.+-- -- >>> mignitude empty--- 0+-- *** Exception: empty interval mignitude :: (Num a, Ord a) => Interval a -> a-mignitude (I a b) = on min abs a b-mignitude Empty = 0+mignitude = inf . abs {-# INLINE mignitude #-} instance (Num a, Ord a) => Num (Interval a) where@@ -294,10 +301,10 @@ -- 5.0 -- -- >>> midpoint empty--- NaN+-- *** Exception: empty interval midpoint :: Fractional a => Interval a -> a midpoint (I a b) = a + (b - a) / 2-midpoint Empty = nan+midpoint Empty = Exception.throw EmptyInterval {-# INLINE midpoint #-} -- | Determine if a point is in the interval.@@ -340,7 +347,7 @@ -- | 'realToFrac' will use the midpoint instance Real a => Real (Interval a) where- toRational Empty = nan+ toRational Empty = Exception.throw EmptyInterval toRational (I ra rb) = a + (b - a) / 2 where a = toRational ra b = toRational rb@@ -354,7 +361,7 @@ | bx < ay = LT | ax > by = GT | bx == ay && ax == by = EQ- | otherwise = error "Numeric.Interval.compare: ambiguous comparison"+ | otherwise = Exception.throw AmbiguousComparison {-# INLINE compare #-} max (I a b) (I a' b') = max a a' ... max b b'@@ -409,7 +416,7 @@ _ / Empty = Empty x / y@(I a b) | 0 `notElem` y = divNonZero x y- | iz && sz = empty -- division by 0+ | iz && sz = Exception.throw DivideByZero | iz = divPositive x a | sz = divNegative x b | otherwise = divZero x
src/Numeric/Interval/Kaucher.hs view
@@ -47,6 +47,7 @@ ) where import Control.Applicative hiding (empty)+import Control.Exception as Exception import Data.Data import Data.Distributive import Data.Foldable hiding (minimum, maximum, elem, notElem)@@ -56,6 +57,7 @@ #if defined(__GLASGOW_HASKELL) && __GLASGOW_HASKELL__ >= 704 import GHC.Generics #endif+import Numeric.Interval.Exception import Prelude hiding (null, elem, notElem) -- $setup@@ -341,7 +343,7 @@ -- | 'realToFrac' will use the midpoint instance Real a => Real (Interval a) where toRational x- | null x = nan+ | null x = Exception.throw EmptyInterval | otherwise = a + (b - a) / 2 where a = toRational (inf x)@@ -353,7 +355,7 @@ | 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"+ | otherwise = Exception.throw AmbiguousComparison {-# INLINE compare #-} max (I a b) (I a' b') = max a a' ... max b b'
src/Numeric/Interval/NonEmpty/Internal.hs view
@@ -44,6 +44,7 @@ , ifloat ) where +import Control.Exception as Exception import Data.Data import Data.Foldable hiding (minimum, maximum, elem, notElem) import Data.Function (on)@@ -51,6 +52,7 @@ #if defined(__GLASGOW_HASKELL) && __GLASGOW_HASKELL__ >= 704 import GHC.Generics #endif+import Numeric.Interval.Exception import Prelude hiding (null, elem, notElem) -- $setup@@ -177,7 +179,7 @@ -- >>> magnitude (singleton 5) -- 5 magnitude :: (Num a, Ord a) => Interval a -> a-magnitude (I a b) = on max abs a b+magnitude = sup . abs {-# INLINE magnitude #-} -- | \"mignitude\"@@ -186,12 +188,12 @@ -- 1 -- -- >>> mignitude (-20 ... 10)--- 10+-- 0 -- -- >>> mignitude (singleton 5) -- 5 mignitude :: (Num a, Ord a) => Interval a -> a-mignitude (I a b) = on min abs a b+mignitude = inf . abs {-# INLINE mignitude #-} instance (Num a, Ord a) => Num (Interval a) where@@ -285,7 +287,7 @@ | bx < ay = LT | ax > by = GT | bx == ay && ax == by = EQ- | otherwise = error "Numeric.Interval.compare: ambiguous comparison"+ | otherwise = Exception.throw AmbiguousComparison {-# INLINE compare #-} max (I a b) (I a' b') = max a a' ... max b b'@@ -331,7 +333,7 @@ -- TODO: check isNegativeZero properly x / y@(I a b) | 0 `notElem` y = divNonZero x y- | iz && sz = error "division by zero"+ | iz && sz = Exception.throw DivideByZero | iz = divPositive x a | sz = divNegative x b | otherwise = divZero x