module Numeric.Decidable.Nilpotent (DecidableNilpotent(..)) where
import Data.Bits(Bits(..))
import Data.Int(Int8,Int16,Int32,Int64)
import Data.Word(Word8,Word16,Word32,Word64)
import Numeric.Algebra
import Numeric.Decidable.Zero
import Prelude hiding (Num(..), Ord(..))
class (Monoidal r, Multiplicative r) => DecidableNilpotent r where
isNilpotent :: r -> Bool
instance DecidableNilpotent () where
isNilpotent _ = True
instance DecidableNilpotent Bool where
isNilpotent = isZero
instance DecidableNilpotent Natural where
isNilpotent = isZero
instance DecidableNilpotent Integer where
isNilpotent = isZero
instance DecidableNilpotent Int where
isNilpotent = signedBitsNilpotent
instance DecidableNilpotent Int8 where
isNilpotent = signedBitsNilpotent
instance DecidableNilpotent Int16 where
isNilpotent = signedBitsNilpotent
instance DecidableNilpotent Int32 where
isNilpotent = signedBitsNilpotent
instance DecidableNilpotent Int64 where
isNilpotent = signedBitsNilpotent
instance DecidableNilpotent Word8 where
isNilpotent = unsignedBitsNilpotent
instance DecidableNilpotent Word16 where
isNilpotent = unsignedBitsNilpotent
instance DecidableNilpotent Word32 where
isNilpotent = unsignedBitsNilpotent
instance DecidableNilpotent Word64 where
isNilpotent = unsignedBitsNilpotent
instance (DecidableNilpotent a, DecidableNilpotent b) => DecidableNilpotent (a,b) where
isNilpotent (a,b) = isNilpotent a && isNilpotent b
instance (DecidableNilpotent a, DecidableNilpotent b, DecidableNilpotent c) => DecidableNilpotent (a,b,c) where
isNilpotent (a,b,c) = isNilpotent a && isNilpotent b && isNilpotent c
instance (DecidableNilpotent a, DecidableNilpotent b, DecidableNilpotent c, DecidableNilpotent d) => DecidableNilpotent (a,b,c,d) where
isNilpotent (a,b,c,d) = isNilpotent a && isNilpotent b && isNilpotent c && isNilpotent d
instance (DecidableNilpotent a, DecidableNilpotent b, DecidableNilpotent c, DecidableNilpotent d, DecidableNilpotent e) => DecidableNilpotent (a,b,c,d,e) where
isNilpotent (a,b,c,d,e) = isNilpotent a && isNilpotent b && isNilpotent c && isNilpotent d && isNilpotent e
unsignedBitsNilpotent :: (Bits r, Group r, Unital r) => r -> Bool
unsignedBitsNilpotent b = (b /= one) && b .&. (b one) == zero
signedBitsNilpotent :: (Bits r, Group r, Order r, Bounded r, Unital r) => r -> Bool
signedBitsNilpotent b | zero <~ b = unsignedBitsNilpotent b
| otherwise = b == minBound ||
unsignedBitsNilpotent (negate b)