exp-pairs-0.1.1.0: Math/ExpPairs/RatioInf.hs
{-|
Module : Math.ExpPairs.RatioInf
Description : Rational numbers with infinities
Copyright : (c) Andrew Lelechenko, 2014-2015
License : GPL-3
Maintainer : andrew.lelechenko@gmail.com
Stability : experimental
Portability : POSIX
Provides types and necessary instances for rational numbers, extended with infinite values. Just use 'RationalInf' instead of 'Rational' from "Data.Ratio".
-}
module Math.ExpPairs.RatioInf (RatioInf (..), RationalInf) where
import Data.Ratio
-- |Extends a rational type with positive and negative
-- infinities.
data RatioInf t
-- |Negative infinity
= InfMinus
-- |Finite value
| Finite (Ratio t)
-- |Positive infinity
| InfPlus
deriving (Ord, Eq)
-- |Arbitrary-precision rational numbers with positive and negative
-- infinities.
type RationalInf = RatioInf Integer
instance (Integral t, Show t) => Show (RatioInf t) where
show InfMinus = "-Inf"
show (Finite x) = show x
show InfPlus = "+Inf"
instance (Integral t) => Num (RatioInf t) where
InfMinus + InfPlus = error "Cannot add up negative and positive infinities"
InfPlus + InfMinus = error "Cannot add up negative and positive infinities"
InfMinus + _ = InfMinus
InfPlus + _ = InfPlus
_ + InfMinus = InfMinus
_ + InfPlus = InfPlus
(Finite a) + (Finite b) = Finite (a+b)
fromInteger n = Finite (fromInteger n)
signum InfMinus = Finite (-1)
signum InfPlus = Finite 1
signum (Finite r) = Finite (signum r)
abs InfMinus = InfPlus
abs InfPlus = InfPlus
abs (Finite r) = Finite (abs r)
negate InfMinus = InfPlus
negate InfPlus = InfMinus
negate (Finite r) = Finite (negate r)
InfMinus * a
| signum a == Finite 0 = error "Cannot multiply infinity by zero"
| signum a == Finite 1 = InfMinus
| signum a == Finite (-1) = InfPlus
InfPlus * a
| signum a == Finite 0 = error "Cannot multiply infinity by zero"
| signum a == Finite 1 = InfPlus
| signum a == Finite (-1) = InfMinus
a * InfMinus
| signum a == Finite 0 = error "Cannot multiply infinity by zero"
| signum a == Finite 1 = InfMinus
| signum a == Finite (-1) = InfPlus
a * InfPlus
| signum a == Finite 0 = error "Cannot multiply infinity by zero"
| signum a == Finite 1 = InfPlus
| signum a == Finite (-1) = InfMinus
(Finite a) * (Finite b) = Finite (a*b)
instance (Integral t) => Fractional (RatioInf t) where
fromRational = Finite . fromRational
InfMinus / InfMinus = error "Cannot divide infinity by infinity"
InfMinus / InfPlus = error "Cannot divide infinity by infinity"
InfMinus / (Finite a)
| signum a == 0 = error "Cannot divide infinity by zero"
| signum a == 1 = InfMinus
| signum a == -1 = InfPlus
InfPlus / InfMinus = error "Cannot divide infinity by infinity"
InfPlus / InfPlus = error "Cannot divide infinity by infinity"
InfPlus / (Finite a)
| signum a == 0 = error "Cannot divide infinity by zero"
| signum a == 1 = InfPlus
| signum a == -1 = InfMinus
(Finite _) / InfPlus = Finite 0
(Finite _) / InfMinus = Finite 0
(Finite _) / (Finite 0) = error "Cannot divide finite value by zero"
(Finite a) / (Finite b) = Finite (a/b)
instance (Integral t) => Real (RatioInf t) where
toRational (Finite r) = toRational r
toRational InfPlus = error "Cannot map infinity into Rational"
toRational InfMinus = error "Cannot map infinity into Rational"