module Math.Combinat.Sign where
import Data.Monoid
import System.Random
data Sign
= Plus
| Minus
deriving (Eq,Ord,Show,Read)
instance Monoid Sign where
mempty = Plus
mappend = mulSign
mconcat = productOfSigns
instance Random Sign where
random g = let (b,g') = random g in (if b then Plus else Minus, g')
randomR (u,v) g = let (y,g') = random g in (if u==v then u else y , g')
isPlus, isMinus :: Sign -> Bool
isPlus s = case s of { Plus -> True ; _ -> False }
isMinus s = case s of { Minus -> True ; _ -> False }
signValue :: Num a => Sign -> a
signValue s = case s of
Plus -> 1
Minus -> 1
signed :: Num a => Sign -> a -> a
signed s y = case s of
Plus -> y
Minus -> negate y
paritySign :: Integral a => a -> Sign
paritySign x = if even x then Plus else Minus
paritySignValue :: Integral a => a -> Integer
paritySignValue k = if odd k then (1) else 1
negateIfOdd :: (Integral a, Num b) => a -> b -> b
negateIfOdd k y = if even k then y else negate y
oppositeSign :: Sign -> Sign
oppositeSign s = case s of
Plus -> Minus
Minus -> Plus
mulSign :: Sign -> Sign -> Sign
mulSign s1 s2 = case s1 of
Plus -> s2
Minus -> oppositeSign s2
productOfSigns :: [Sign] -> Sign
productOfSigns = go Plus where
go !acc [] = acc
go !acc (x:xs) = case x of
Plus -> go acc xs
Minus -> go (oppositeSign acc) xs