module Data.Number.Int ( Int(..), pos ) where
import Prelude hiding ( Int )
import Data.Number.Nat
import Data.Number.NatO
import Data.Ratio ( (%) )
data Int
= Neg Nat
| NatO NatO
deriving Eq
pos :: Nat -> Int
pos = NatO . Nat
instance Show Int where
show (Neg n) = "-" ++ show n
show (NatO n) = show n
instance Read Int where
readsPrec n = map (\(x,str) -> (toEnum x,str)) . readsPrec n
instance Ord Int where
compare (Neg _) (NatO _) = LT
compare (NatO _) (Neg _) = GT
compare (NatO m) (NatO n) = compare m n
compare (Neg m) (Neg n) = compare n m
x < y = cmpIntLT y x == GT
x > y = cmpIntLT x y == GT
x <= y = cmpIntLT x y == LT
x >= y = cmpIntLT y x == LT
cmpIntLT :: Int -> Int -> Ordering
cmpIntLT (Neg _) (NatO _) = LT
cmpIntLT (NatO _) (Neg _) = GT
cmpIntLT (NatO m) (NatO n) = cmpNatOLT m n
cmpIntLT (Neg m) (Neg n) = invOrd (cmpNatLT m n)
instance Enum Int where
succ (NatO n) = NatO (succ n)
succ (Neg IHi) = NatO Zero
succ (Neg n) = Neg (succ n)
pred (Neg n) = Neg (pred n)
pred (NatO Zero) = Neg IHi
pred (NatO n) = NatO (pred n)
toEnum = toInt
fromEnum = fromInt
instance Num Int where
n + NatO Zero = n
Neg m + NatO (Nat n) = n -^ m
NatO Zero + n = n
NatO (Nat m) + Neg n = m -^ n
NatO m + NatO n = NatO (m+n)
Neg m + Neg n = Neg (m+n)
m Neg n = m + pos n
m NatO Zero = m
m NatO (Nat n) = m + Neg n
_ * NatO Zero = NatO Zero
NatO Zero * _ = NatO Zero
Neg m * NatO (Nat n) = Neg (m*n)
NatO (Nat m) * Neg n = Neg (m*n)
Neg m * Neg n = pos (m*n)
NatO m * NatO n = NatO (m*n)
negate (Neg n) = pos n
negate n@(NatO Zero) = n
negate (NatO (Nat n)) = Neg n
signum (Neg _) = Neg IHi
signum n@(NatO Zero) = n
signum (NatO _) = pos IHi
abs (Neg n) = pos n
abs n = n
fromInteger = toInt
(-^) :: Nat -> Nat -> Int
x -^ y =
case minus x y of
NatO n -> NatO n
Neg IHi -> NatO Zero
Neg n -> Neg (pred n)
minus :: Nat -> Nat -> Int
minus IHi y = Neg y
minus x@(O _) IHi = pos (pred x)
minus (I x) IHi = pos (O x)
minus (O x) (O y) = incNeg (mult2 (minus x y))
minus (I x) (I y) = incNeg (mult2 (minus x y))
minus (O x) (I y) = decNeg (mult2 (minus x y))
minus (I x) (O y) = decNeg (mult2 (negate (minus y x)))
mult2 :: Int -> Int
mult2 (Neg n) = Neg (O n)
mult2 (NatO n) =
NatO (case n of
Zero -> Zero
Nat m -> Nat (O m))
incNeg :: Int -> Int
incNeg (Neg n) = Neg (pred n)
incNeg (NatO n) = NatO n
decNeg :: Int -> Int
decNeg (Neg n) = Neg n
decNeg (NatO n) = NatO (pred n)
instance Integral Int where
quotRem (Neg m) (Neg n) = (NatO q,neg r)
where
(q,r) = quotRem (Nat m) (Nat n)
quotRem (Neg m) (NatO n) = (neg q,neg r)
where
(q,r) = quotRem (Nat m) n
quotRem (NatO m) (Neg n) = (neg q,NatO r)
where
(q,r) = quotRem m (Nat n)
quotRem (NatO m) (NatO n) = (NatO q,NatO r)
where
(q,r) = quotRem m n
toInteger = fromInt
fromInt :: Num n => Int -> n
fromInt (Neg n) = fromNat n
fromInt (NatO n) = fromNatO n
toInt :: (Integral n,Num n) => n -> Int
toInt n
| n<0 = Neg (toNat (n))
| otherwise = NatO (toNatO n)
neg :: NatO -> Int
neg Zero = NatO Zero
neg (Nat n) = Neg n
instance Real Int where
toRational n = toInteger n % 1