{-# language Trustworthy #-}
module Integer.Signed
(
Signed (Zero, NonZero, Plus, Minus, NotPlus, NotMinus),
toInteger, fromInteger,
toNatural, fromNatural,
toPositive, fromPositive,
toInt, fromInt,
toWord, fromWord,
)
where
import Data.Function (($), (.))
import Data.Int (Int)
import Data.Maybe (Maybe (..))
import Data.Word (Word)
import Integer.Positive.Unsafe (Positive)
import Integer.Sign (Sign (..))
import Numeric.Natural (Natural)
import Prelude (Enum, Eq, Integer, Integral, Num, Ord, Real, Show, seq)
import qualified Control.DeepSeq as DeepSeq
import qualified Data.List as List
import qualified Data.Ord as Ord
import qualified Integer.Positive.Unsafe as Positive.Unsafe
import qualified Integer.Sign as Sign
import qualified Prelude as Bounded (Bounded (..))
import qualified Prelude as Enum (Enum (..))
import qualified Prelude as Num (Integral (..), Num (..), Real (..))
import qualified Text.Show as Show
data Signed = Zero | NonZero Sign Positive
deriving (Signed -> Signed -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Signed -> Signed -> Bool
$c/= :: Signed -> Signed -> Bool
== :: Signed -> Signed -> Bool
$c== :: Signed -> Signed -> Bool
Eq)
instance Ord Signed where
compare :: Signed -> Signed -> Ordering
compare Signed
Zero Signed
Zero = Ordering
Ord.EQ
compare Signed
Zero (Minus Positive
_) = Ordering
Ord.GT
compare Signed
Zero (Plus Positive
_ ) = Ordering
Ord.LT
compare (Minus Positive
_) Signed
Zero = Ordering
Ord.LT
compare (Plus Positive
_) Signed
Zero = Ordering
Ord.GT
compare (Plus Positive
_) (Minus Positive
_) = Ordering
Ord.GT
compare (Minus Positive
_) (Plus Positive
_) = Ordering
Ord.LT
compare (Plus Positive
a) (Plus Positive
b) = forall a. Ord a => a -> a -> Ordering
Ord.compare Positive
a Positive
b
compare (Minus Positive
a) (Minus Positive
b) = forall a. Ord a => a -> a -> Ordering
Ord.compare Positive
b Positive
a
instance DeepSeq.NFData Signed where
rnf :: Signed -> ()
rnf Signed
Zero = ()
rnf (NonZero Sign
a Positive
b) = Sign
a seq :: forall a b. a -> b -> b
`seq` Positive
b seq :: forall a b. a -> b -> b
`seq` ()
pattern Minus :: Positive -> Signed
pattern $bMinus :: Positive -> Signed
$mMinus :: forall {r}. Signed -> (Positive -> r) -> ((# #) -> r) -> r
Minus x = NonZero MinusSign x
pattern Plus :: Positive -> Signed
pattern $bPlus :: Positive -> Signed
$mPlus :: forall {r}. Signed -> (Positive -> r) -> ((# #) -> r) -> r
Plus x = NonZero PlusSign x
pattern NotMinus :: Natural -> Signed
pattern $bNotMinus :: Natural -> Signed
$mNotMinus :: forall {r}. Signed -> (Natural -> r) -> ((# #) -> r) -> r
NotMinus x <- (toNatural -> Just x)
where NotMinus = Natural -> Signed
fromNatural
pattern NotPlus :: Natural -> Signed
pattern $bNotPlus :: Natural -> Signed
$mNotPlus :: forall {r}. Signed -> (Natural -> r) -> ((# #) -> r) -> r
NotPlus x <- ((toNatural . negate) -> Just x)
where NotPlus = Signed -> Signed
negate forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Signed
fromNatural
{-# complete Zero, Minus, Plus #-}
{-# complete Plus, NotPlus #-}
{-# complete Minus, NotMinus #-}
fromPositive :: Positive -> Signed
fromPositive :: Positive -> Signed
fromPositive = Positive -> Signed
Plus
toPositive :: Signed -> Maybe Positive
toPositive :: Signed -> Maybe Positive
toPositive (Plus Positive
x) = forall a. a -> Maybe a
Just Positive
x
toPositive Signed
_ = forall a. Maybe a
Nothing
fromNatural :: Natural -> Signed
fromNatural :: Natural -> Signed
fromNatural Natural
0 = Signed
Zero
fromNatural Natural
x = Positive -> Signed
Plus forall a b. (a -> b) -> a -> b
$ Natural -> Positive
Positive.Unsafe.fromNatural Natural
x
toNatural :: Signed -> Maybe Natural
toNatural :: Signed -> Maybe Natural
toNatural (Minus Positive
_) = forall a. Maybe a
Nothing
toNatural Signed
Zero = forall a. a -> Maybe a
Just Natural
0
toNatural (Plus Positive
x) = forall a. a -> Maybe a
Just (Positive -> Natural
Positive.Unsafe.toNatural Positive
x)
add :: Signed -> Signed -> Signed
add :: Signed -> Signed -> Signed
add Signed
Zero Signed
x = Signed
x
add Signed
x Signed
Zero = Signed
x
add (NonZero Sign
sa Positive
a) (NonZero Sign
sb Positive
b) = case (Sign
sa, Sign
sb) of
(Sign
PlusSign, Sign
PlusSign) -> Positive -> Signed
Plus forall a b. (a -> b) -> a -> b
$ Positive
a forall a. Num a => a -> a -> a
Num.+ Positive
b
(Sign
MinusSign, Sign
MinusSign) -> Positive -> Signed
Minus forall a b. (a -> b) -> a -> b
$ Positive
a forall a. Num a => a -> a -> a
Num.+ Positive
b
(Sign
MinusSign, Sign
PlusSign) -> case forall a. Ord a => a -> a -> Ordering
Ord.compare Positive
a Positive
b of
Ordering
Ord.EQ -> Signed
Zero
Ordering
Ord.LT -> Positive -> Signed
Plus forall a b. (a -> b) -> a -> b
$ Positive -> Positive -> Positive
Positive.Unsafe.subtract Positive
b Positive
a
Ordering
Ord.GT -> Positive -> Signed
Minus forall a b. (a -> b) -> a -> b
$ Positive -> Positive -> Positive
Positive.Unsafe.subtract Positive
a Positive
b
(Sign
PlusSign, Sign
MinusSign) -> case forall a. Ord a => a -> a -> Ordering
Ord.compare Positive
a Positive
b of
Ordering
Ord.EQ -> Signed
Zero
Ordering
Ord.LT -> Positive -> Signed
Minus forall a b. (a -> b) -> a -> b
$ Positive -> Positive -> Positive
Positive.Unsafe.subtract Positive
b Positive
a
Ordering
Ord.GT -> Positive -> Signed
Plus forall a b. (a -> b) -> a -> b
$ Positive -> Positive -> Positive
Positive.Unsafe.subtract Positive
a Positive
b
negate :: Signed -> Signed
negate :: Signed -> Signed
negate Signed
Zero = Signed
Zero
negate (NonZero Sign
s Positive
x) = Sign -> Positive -> Signed
NonZero (Sign -> Sign
Sign.negate Sign
s) Positive
x
multiply :: Signed -> Signed -> Signed
multiply :: Signed -> Signed -> Signed
multiply Signed
Zero Signed
_ = Signed
Zero
multiply Signed
_ Signed
Zero = Signed
Zero
multiply (NonZero Sign
sa Positive
a) (NonZero Sign
sb Positive
b) =
Sign -> Positive -> Signed
NonZero (Sign -> Sign -> Sign
Sign.multiply Sign
sa Sign
sb) (Positive
a forall a. Num a => a -> a -> a
Num.* Positive
b)
abs :: Signed -> Signed
abs :: Signed -> Signed
abs Signed
Zero = Signed
Zero
abs x :: Signed
x@(NonZero Sign
s Positive
p) = case Sign
s of
Sign
PlusSign -> Signed
x
Sign
MinusSign -> Sign -> Positive -> Signed
NonZero Sign
PlusSign Positive
p
signum :: Signed -> Signed
signum :: Signed -> Signed
signum Signed
Zero = Signed
Zero
signum (NonZero Sign
s Positive
_) = Sign -> Positive -> Signed
NonZero Sign
s Positive
Positive.Unsafe.one
fromInteger :: Integer -> Signed
fromInteger :: Integer -> Signed
fromInteger Integer
x = case forall a. Ord a => a -> a -> Ordering
Ord.compare Integer
x Integer
0 of
Ordering
Ord.EQ -> Signed
Zero
Ordering
Ord.LT -> Positive -> Signed
Minus forall a b. (a -> b) -> a -> b
$ Integer -> Positive
Positive.Unsafe.fromInteger forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
Num.abs Integer
x
Ordering
Ord.GT -> Positive -> Signed
Plus forall a b. (a -> b) -> a -> b
$ Integer -> Positive
Positive.Unsafe.fromInteger Integer
x
toInteger :: Signed -> Integer
toInteger :: Signed -> Integer
toInteger Signed
Zero = Integer
0
toInteger (Plus Positive
x) = Positive -> Integer
Positive.Unsafe.toInteger Positive
x
toInteger (Minus Positive
x) = forall a. Num a => a -> a
Num.negate forall a b. (a -> b) -> a -> b
$ Positive -> Integer
Positive.Unsafe.toInteger Positive
x
toInt :: Signed -> Maybe Int
toInt :: Signed -> Maybe Int
toInt Signed
x = case Signed
x of
Signed
Zero -> forall a. a -> Maybe a
Just Int
0
Plus Positive
p -> if Bool
ok then forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
Num.fromInteger Integer
i) else forall a. Maybe a
Nothing
where
ok :: Bool
ok = Integer
i forall a. Ord a => a -> a -> Bool
Ord.<= forall a. Integral a => a -> Integer
Num.toInteger (forall a. Bounded a => a
Bounded.maxBound :: Int)
i :: Integer
i = Positive -> Integer
Positive.Unsafe.toInteger Positive
p
Minus Positive
p -> if Bool
ok then forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
Num.fromInteger Integer
i) else forall a. Maybe a
Nothing
where
ok :: Bool
ok = Integer
i forall a. Ord a => a -> a -> Bool
Ord.>= forall a. Integral a => a -> Integer
Num.toInteger (forall a. Bounded a => a
Bounded.minBound :: Int)
i :: Integer
i = forall a. Num a => a -> a
Num.negate (Positive -> Integer
Positive.Unsafe.toInteger Positive
p)
fromInt :: Int -> Signed
fromInt :: Int -> Signed
fromInt Int
x = case forall a. Ord a => a -> a -> Ordering
Ord.compare Int
x Int
0 of
Ordering
Ord.EQ -> Signed
Zero
Ordering
Ord.GT -> Positive -> Signed
Plus forall a b. (a -> b) -> a -> b
$ Int -> Positive
Positive.Unsafe.fromInt Int
x
Ordering
Ord.LT -> Positive -> Signed
Minus forall a b. (a -> b) -> a -> b
$ Integer -> Positive
Positive.Unsafe.fromInteger forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
Num.negate forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
Num.toInteger Int
x
toWord :: Signed -> Maybe Word
toWord :: Signed -> Maybe Word
toWord Signed
x = case Signed
x of
Signed
Zero -> forall a. a -> Maybe a
Just Word
0
Plus Positive
p -> if Bool
ok then forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
Num.fromInteger Integer
i) else forall a. Maybe a
Nothing
where
ok :: Bool
ok = Integer
i forall a. Ord a => a -> a -> Bool
Ord.<= forall a. Integral a => a -> Integer
Num.toInteger (forall a. Bounded a => a
Bounded.maxBound :: Word)
i :: Integer
i = Positive -> Integer
Positive.Unsafe.toInteger Positive
p
Minus Positive
_ -> forall a. Maybe a
Nothing
fromWord :: Word -> Signed
fromWord :: Word -> Signed
fromWord Word
x = case Word
x of
Word
0 -> Signed
Zero
Word
_ -> Positive -> Signed
Plus forall a b. (a -> b) -> a -> b
$ Integer -> Positive
Positive.Unsafe.fromInteger (forall a. Integral a => a -> Integer
Num.toInteger Word
x)
type Div a = a -> a -> (a, a)
divisionOp :: Div Integer -> Div Signed
divisionOp :: Div Integer -> Div Signed
divisionOp Div Integer
o Signed
a Signed
b =
let (Integer
q, Integer
r) = Div Integer
o (Signed -> Integer
toInteger Signed
a) (Signed -> Integer
toInteger Signed
b)
in (Integer -> Signed
fromInteger Integer
q, Integer -> Signed
fromInteger Integer
r)
instance Num Signed
where
+ :: Signed -> Signed -> Signed
(+) = Signed -> Signed -> Signed
add
* :: Signed -> Signed -> Signed
(*) = Signed -> Signed -> Signed
multiply
negate :: Signed -> Signed
negate = Signed -> Signed
negate
abs :: Signed -> Signed
abs = Signed -> Signed
abs
signum :: Signed -> Signed
signum = Signed -> Signed
signum
fromInteger :: Integer -> Signed
fromInteger = Integer -> Signed
fromInteger
instance Enum Signed
where
pred :: Signed -> Signed
pred = Integer -> Signed
fromInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => a -> a
Enum.pred forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signed -> Integer
toInteger
succ :: Signed -> Signed
succ = Integer -> Signed
fromInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => a -> a
Enum.succ forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signed -> Integer
toInteger
toEnum :: Int -> Signed
toEnum = Integer -> Signed
fromInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => Int -> a
Enum.toEnum
fromEnum :: Signed -> Int
fromEnum = forall a. Enum a => a -> Int
Enum.fromEnum forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signed -> Integer
toInteger
enumFrom :: Signed -> [Signed]
enumFrom Signed
a = forall a b. (a -> b) -> [a] -> [b]
List.map Integer -> Signed
fromInteger forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> [a]
Enum.enumFrom (Signed -> Integer
toInteger Signed
a)
enumFromTo :: Signed -> Signed -> [Signed]
enumFromTo Signed
a Signed
b = forall a b. (a -> b) -> [a] -> [b]
List.map Integer -> Signed
fromInteger forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> a -> [a]
Enum.enumFromTo (Signed -> Integer
toInteger Signed
a) (Signed -> Integer
toInteger Signed
b)
enumFromThen :: Signed -> Signed -> [Signed]
enumFromThen Signed
a Signed
b = forall a b. (a -> b) -> [a] -> [b]
List.map Integer -> Signed
fromInteger forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> a -> [a]
Enum.enumFromThen (Signed -> Integer
toInteger Signed
a) (Signed -> Integer
toInteger Signed
b)
enumFromThenTo :: Signed -> Signed -> Signed -> [Signed]
enumFromThenTo Signed
a Signed
b Signed
c = forall a b. (a -> b) -> [a] -> [b]
List.map Integer -> Signed
fromInteger forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> a -> a -> [a]
Enum.enumFromThenTo (Signed -> Integer
toInteger Signed
a) (Signed -> Integer
toInteger Signed
b) (Signed -> Integer
toInteger Signed
c)
instance Real Signed
where
toRational :: Signed -> Rational
toRational = forall a. Real a => a -> Rational
Num.toRational forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signed -> Integer
toInteger
instance Integral Signed
where
toInteger :: Signed -> Integer
toInteger = Signed -> Integer
toInteger
quotRem :: Div Signed
quotRem = Div Integer -> Div Signed
divisionOp forall a. Integral a => a -> a -> (a, a)
Num.quotRem
divMod :: Div Signed
divMod = Div Integer -> Div Signed
divisionOp forall a. Integral a => a -> a -> (a, a)
Num.divMod
instance Show Signed
where
show :: Signed -> String
show = forall a. Show a => a -> String
Show.show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Integral a => a -> Integer
Num.toInteger
showsPrec :: Int -> Signed -> ShowS
showsPrec Int
i = forall a. Show a => Int -> a -> ShowS
Show.showsPrec Int
i forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Integral a => a -> Integer
Num.toInteger