module Numeric.Natural.Internal ( Natural(..) , Whole(..) ) where import Data.Word import Data.Bits import Text.Read import Data.Ix newtype Natural = Natural { runNatural :: Integer } deriving (Eq,Ord,Ix) instance Show Natural where showsPrec d (Natural n) = showsPrec d n instance Read Natural where readPrec = fmap Natural $ step readPrec instance Num Natural where Natural n + Natural m = Natural (n + m) Natural n * Natural m = Natural (n * m) Natural n - Natural m | result < 0 = error "Natural.(-): negative result" | otherwise = Natural result where result = n - m abs (Natural n) = Natural n signum (Natural n) = Natural (signum n) fromInteger n | n >= 0 = Natural n | otherwise = error "Natural.fromInteger: negative" instance Bits Natural where Natural n .&. Natural m = Natural (n .&. m) Natural n .|. Natural m = Natural (n .|. m) xor (Natural n) (Natural m) = Natural (xor n m) complement _ = error "Bits.complement: Natural complement undefined" shift (Natural n) = Natural . shift n rotate (Natural n) = Natural . rotate n bit = Natural . bit setBit (Natural n) = Natural . setBit n clearBit (Natural n) = Natural . clearBit n complementBit (Natural n) = Natural . complementBit n testBit = testBit . runNatural bitSize = bitSize . runNatural isSigned _ = False shiftL (Natural n) = Natural . shiftL n shiftR (Natural n) = Natural . shiftR n rotateL (Natural n) = Natural . rotateL n rotateR (Natural n) = Natural . rotateR n instance Real Natural where toRational (Natural a) = toRational a instance Enum Natural where pred (Natural 0) = error "Natural.pred: 0" pred (Natural n) = Natural (pred n) succ (Natural n) = Natural (succ n) fromEnum (Natural n) = fromEnum n toEnum n | n < 0 = error "Natural.toEnum: negative" | otherwise = Natural (toEnum n) instance Integral Natural where quot (Natural a) (Natural b) = Natural (quot a b) rem (Natural a) (Natural b) = Natural (rem a b) div (Natural a) (Natural b) = Natural (div a b) mod (Natural a) (Natural b) = Natural (mod a b) divMod (Natural a) (Natural b) = (Natural q, Natural r) where (q,r) = divMod a b quotRem (Natural a) (Natural b) = (Natural q, Natural r) where (q,r) = quotRem a b toInteger = runNatural class Integral n => Whole n where toNatural :: n -> Natural unsafePred :: n -> n instance Whole Word where toNatural = Natural . toInteger unsafePred n = n - 1 instance Whole Word8 where toNatural = Natural . toInteger unsafePred n = n - 1 instance Whole Word16 where toNatural = Natural . toInteger unsafePred n = n - 1 instance Whole Word32 where toNatural = Natural . toInteger unsafePred n = n - 1 instance Whole Word64 where toNatural = Natural . toInteger unsafePred n = n - 1 instance Whole Natural where toNatural = id unsafePred (Natural n) = Natural (n - 1)