module Data.Sign
(
Sign (..)
, signNegate
, signMul
, signRecip
, signDiv
, signPow
, signOf
, showSign
) where
import Algebra.Enumerable (Enumerable (..))
import Control.DeepSeq
import Data.Typeable
import Data.Data
import qualified Numeric.Algebra as Alg
data Sign = Neg | Zero | Pos
deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data)
instance NFData Sign
instance Enumerable Sign where
universe = [Neg .. Pos]
instance Alg.Multiplicative Sign where
(*) = signMul
pow1p = signPow
instance Alg.Commutative Sign
instance Alg.Unital Sign where
one = Pos
pow = signPow
instance Alg.Division Sign where
recip = signRecip
(/) = signDiv
(\\) = flip signDiv
(^) = signPow
signNegate :: Sign -> Sign
signNegate Neg = Pos
signNegate Zero = Zero
signNegate Pos = Neg
signMul :: Sign -> Sign -> Sign
signMul Pos s = s
signMul s Pos = s
signMul Neg s = signNegate s
signMul s Neg = signNegate s
signMul _ _ = Zero
signRecip :: Sign -> Sign
signRecip Pos = Pos
signRecip Zero = error "signRecip: division by Zero"
signRecip Neg = Neg
signDiv :: Sign -> Sign -> Sign
signDiv s Pos = s
signDiv _ Zero = error "signDiv: division by Zero"
signDiv s Neg = signNegate s
signPow :: Integral x => Sign -> x -> Sign
signPow _ 0 = Pos
signPow Pos _ = Pos
signPow Zero _ = Zero
signPow Neg n = if even n then Pos else Neg
signOf :: Real a => a -> Sign
signOf r =
case r `compare` 0 of
LT -> Neg
EQ -> Zero
GT -> Pos
showSign :: Sign -> String
showSign Pos = "+"
showSign Neg = "-"
showSign Zero = "0"