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