module Integer.AbsoluteDifference where

import Essentials
import Integer.Integer (Integer)
import Integer.Integer qualified as Integer
import Integer.Natural (Natural)
import Integer.Positive (Positive)
import Integer.Positive qualified as Positive
import Integer.Signed (Signed (Minus, NonZero, Plus, Zero))
import Integer.Signed qualified as Signed
import Prelude (fromInteger, (+), (-))
import Prelude qualified as Num (abs)

class AbsoluteDifference a b where
  absoluteDifference :: a -> b -> Natural

--

instance AbsoluteDifference Integer Integer where
  absoluteDifference :: Integer -> Integer -> Natural
absoluteDifference Integer
a Integer
b = forall a. Num a => Integer -> a
fromInteger forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
Num.abs forall a b. (a -> b) -> a -> b
$ Integer
a forall a. Num a => a -> a -> a
- Integer
b

instance AbsoluteDifference Natural Natural where
  absoluteDifference :: Natural -> Natural -> Natural
absoluteDifference Natural
a Natural
b = if Natural
a forall a. Ord a => a -> a -> Bool
>= Natural
b then Natural
a forall a. Num a => a -> a -> a
- Natural
b else Natural
b forall a. Num a => a -> a -> a
- Natural
a

instance AbsoluteDifference Positive Positive where
  absoluteDifference :: Positive -> Positive -> Natural
absoluteDifference Positive
a Positive
b =
    forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference
      (Positive -> Natural
Positive.toNatural Positive
a)
      (Positive -> Natural
Positive.toNatural Positive
b)

instance AbsoluteDifference Signed Signed where
  absoluteDifference :: Signed -> Signed -> Natural
absoluteDifference Signed
Zero Signed
Zero = Natural
0
  absoluteDifference Signed
Zero (NonZero Sign
_ Positive
x) = Positive -> Natural
Positive.toNatural Positive
x
  absoluteDifference (NonZero Sign
_ Positive
x) Signed
Zero = Positive -> Natural
Positive.toNatural Positive
x
  absoluteDifference (NonZero Sign
s1 Positive
x1) (NonZero Sign
s2 Positive
x2) =
    if Sign
s1 forall a. Eq a => a -> a -> Bool
== Sign
s2
      then forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Positive
x1 Positive
x2
      else Positive -> Natural
Positive.toNatural (Positive
x1 forall a. Num a => a -> a -> a
+ Positive
x2)

--

instance AbsoluteDifference Positive Natural where
  absoluteDifference :: Positive -> Natural -> Natural
absoluteDifference Positive
p Natural
n = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference (Positive -> Natural
Positive.toNatural Positive
p) Natural
n

instance AbsoluteDifference Natural Positive where
  absoluteDifference :: Natural -> Positive -> Natural
absoluteDifference Natural
n Positive
p = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Positive
p Natural
n

--

instance AbsoluteDifference Signed Natural where
  absoluteDifference :: Signed -> Natural -> Natural
absoluteDifference Signed
Zero Natural
n = Natural
n
  absoluteDifference (Plus Positive
a) Natural
b = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Positive
a Natural
b
  absoluteDifference (Minus Positive
a) Natural
b = Positive -> Natural
Positive.toNatural Positive
a forall a. Num a => a -> a -> a
+ Natural
b

instance AbsoluteDifference Natural Signed where
  absoluteDifference :: Natural -> Signed -> Natural
absoluteDifference Natural
n Signed
s = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Signed
s Natural
n

--

instance AbsoluteDifference Integer Natural where
  absoluteDifference :: Integer -> Natural -> Natural
absoluteDifference Integer
i Natural
n = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference (Integer -> Signed
Integer.toSigned Integer
i) Natural
n

instance AbsoluteDifference Natural Integer where
  absoluteDifference :: Natural -> Integer -> Natural
absoluteDifference Natural
n Integer
i = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Integer
i Natural
n

--

instance AbsoluteDifference Signed Positive where
  absoluteDifference :: Signed -> Positive -> Natural
absoluteDifference Signed
Zero Positive
p = Positive -> Natural
Positive.toNatural Positive
p
  absoluteDifference (Plus Positive
a) Positive
b = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Positive
a Positive
b
  absoluteDifference (Minus Positive
a) Positive
b = Positive -> Natural
Positive.toNatural (Positive
a forall a. Num a => a -> a -> a
+ Positive
b)

instance AbsoluteDifference Positive Signed where
  absoluteDifference :: Positive -> Signed -> Natural
absoluteDifference Positive
p Signed
s = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Signed
s Positive
p

--

instance AbsoluteDifference Signed Integer where
  absoluteDifference :: Signed -> Integer -> Natural
absoluteDifference Signed
s Integer
i = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference (Signed -> Integer
Signed.toInteger Signed
s) Integer
i

instance AbsoluteDifference Integer Signed where
  absoluteDifference :: Integer -> Signed -> Natural
absoluteDifference Integer
i Signed
s = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Signed
s Integer
i

--

instance AbsoluteDifference Positive Integer where
  absoluteDifference :: Positive -> Integer -> Natural
absoluteDifference Positive
p Integer
i = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference (Positive -> Integer
Positive.toInteger Positive
p) Integer
i

instance AbsoluteDifference Integer Positive where
  absoluteDifference :: Integer -> Positive -> Natural
absoluteDifference Integer
i Positive
p = forall a b. AbsoluteDifference a b => a -> b -> Natural
absoluteDifference Positive
p Integer
i