module Integer.Positive
  (
    {- * Type -} Positive,
    {- * Subtraction -} subtract,
    {- * Conversion -}
    {- ** Natural -} toNatural, fromNatural,
    {- ** Integer -} toInteger, fromInteger,
    {- ** Signed -} toSigned, fromSigned,
    {- ** Int -} toInt, fromInt,
    {- ** Word -} toWord, fromWord,
    {- * One (1) -} one, addOne, subtractOne,
  )
  where

import Essentials

import Data.Int (Int)
import Data.Word (Word)
import Integer.Positive.Unsafe (Positive, addOne, one, toInteger, toNatural)
import Integer.Signed (Signed (..))
import Numeric.Natural (Natural)
import Prelude (Integer)

import qualified Data.Ord as Ord
import qualified Integer.Positive.Unsafe as Unsafe
import qualified Prelude as Bounded (Bounded (..))
import qualified Prelude as Num (Integral (..), Num (..))

fromInteger :: Integer -> Maybe Positive
fromInteger :: Integer -> Maybe Positive
fromInteger Integer
x = if Integer
x forall a. Ord a => a -> a -> Bool
Ord.> Integer
0 then forall a. a -> Maybe a
Just (Integer -> Positive
Unsafe.fromInteger Integer
x) else forall a. Maybe a
Nothing

fromNatural :: Natural -> Maybe Positive
fromNatural :: Natural -> Maybe Positive
fromNatural Natural
x = case Natural
x of Natural
0 -> forall a. Maybe a
Nothing; Natural
_ -> forall a. a -> Maybe a
Just (Natural -> Positive
Unsafe.fromNatural Natural
x)

toInt :: Positive -> Maybe Int
toInt :: Positive -> Maybe Int
toInt Positive
x = if Bool
ok then forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
Num.fromInteger Integer
x') else forall a. Maybe a
Nothing
  where
    ok :: Bool
ok = Integer
x' forall a. Ord a => a -> a -> Bool
Ord.<= forall a. Integral a => a -> Integer
Num.toInteger (forall a. Bounded a => a
Bounded.maxBound :: Int)
    x' :: Integer
x' = forall a. Integral a => a -> Integer
Num.toInteger Positive
x

fromInt :: Int -> Maybe Positive
fromInt :: Int -> Maybe Positive
fromInt Int
x = if Bool
ok then forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
Num.fromInteger Integer
x') else forall a. Maybe a
Nothing
  where
    ok :: Bool
ok = Integer
x' forall a. Ord a => a -> a -> Bool
Ord.>= Integer
1
    x' :: Integer
x' = forall a. Integral a => a -> Integer
Num.toInteger Int
x

toWord :: Positive -> Maybe Word
toWord :: Positive -> Maybe Word
toWord Positive
x = if Bool
ok then forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
Num.fromInteger Integer
x') else forall a. Maybe a
Nothing
  where
    ok :: Bool
ok = Integer
x' forall a. Ord a => a -> a -> Bool
Ord.<= forall a. Integral a => a -> Integer
Num.toInteger (forall a. Bounded a => a
Bounded.maxBound :: Word)
    x' :: Integer
x' = forall a. Integral a => a -> Integer
Num.toInteger Positive
x

fromWord :: Word -> Maybe Positive
fromWord :: Word -> Maybe Positive
fromWord Word
x = if Bool
ok then forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
Num.fromInteger Integer
x') else forall a. Maybe a
Nothing
  where
    ok :: Bool
ok = Integer
x' forall a. Ord a => a -> a -> Bool
Ord.>= Integer
1
    x' :: Integer
x' = forall a. Integral a => a -> Integer
Num.toInteger Word
x

subtract :: Positive -> Positive -> Signed
subtract :: Positive -> Positive -> Signed
subtract Positive
a Positive
b = case forall a. Ord a => a -> a -> Ordering
Ord.compare Positive
a Positive
b of
    Ordering
Ord.EQ -> Signed
Zero
    Ordering
Ord.GT -> Positive -> Signed
Plus  forall a b. (a -> b) -> a -> b
$ Positive -> Positive -> Positive
Unsafe.subtract Positive
a Positive
b
    Ordering
Ord.LT -> Positive -> Signed
Minus forall a b. (a -> b) -> a -> b
$ Positive -> Positive -> Positive
Unsafe.subtract Positive
b Positive
a

subtractOne :: Positive -> Natural
subtractOne :: Positive -> Natural
subtractOne Positive
x = Positive -> Natural
toNatural Positive
x forall a. Num a => a -> a -> a
Num.- Natural
1

toSigned :: Positive -> Signed
toSigned :: Positive -> Signed
toSigned = Positive -> Signed
Plus

fromSigned :: Signed -> Maybe Positive
fromSigned :: Signed -> Maybe Positive
fromSigned (Plus Positive
x) = forall a. a -> Maybe a
Just Positive
x
fromSigned Signed
_        = forall a. Maybe a
Nothing