```{-|
Copyright  :  (C) 2013-2016, University of Twente
License    :  BSD2 (see the file LICENSE)
Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
-}

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}

{-# LANGUAGE Safe #-}

{-# OPTIONS_HADDOCK show-extensions #-}

module Clash.Class.Num
( -- * Arithmetic functions for arguments and results of different precision
ExtendingNum (..)
-- * Saturating arithmetic functions
, SaturationMode (..)
, SaturatingNum (..)
, boundedAdd
, boundedSub
, boundedMul
)
where

-- * Arithmetic functions for arguments and results of different precision

-- | Adding, subtracting, and multiplying values of two different (sub-)types.
class ExtendingNum a b where
-- | Type of the result of the addition or subtraction
type AResult a b
-- | Add values of different (sub-)types, return a value of a (sub-)type
-- that is potentially different from either argument.
add  :: a -> b -> AResult a b
-- | Subtract values of different (sub-)types, return a value of a (sub-)type
-- that is potentially different from either argument.
sub :: a -> b -> AResult a b
-- | Type of the result of the multiplication
type MResult a b
-- | Multiply values of different (sub-)types, return a value of a (sub-)type
-- that is potentially different from either argument.
mul :: a -> b -> MResult a b

-- * Saturating arithmetic functions

-- | Determine how overflow and underflow are handled by the functions in
-- 'SaturatingNum'
data SaturationMode
= SatWrap  -- ^ Wrap around on overflow and underflow
| SatBound -- ^ Become 'maxBound' on overflow, and 'minBound' on underflow
| SatZero  -- ^ Become @0@ on overflow and underflow
| SatSymmetric -- ^ Become 'maxBound' on overflow, and (@'minBound' + 1@) on
-- underflow for signed numbers, and 'minBound' for unsigned
-- numbers.
deriving (Int -> SaturationMode -> ShowS
[SaturationMode] -> ShowS
SaturationMode -> String
(Int -> SaturationMode -> ShowS)
-> (SaturationMode -> String)
-> ([SaturationMode] -> ShowS)
-> Show SaturationMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SaturationMode] -> ShowS
\$cshowList :: [SaturationMode] -> ShowS
show :: SaturationMode -> String
\$cshow :: SaturationMode -> String
showsPrec :: Int -> SaturationMode -> ShowS
\$cshowsPrec :: Int -> SaturationMode -> ShowS
Show, SaturationMode -> SaturationMode -> Bool
(SaturationMode -> SaturationMode -> Bool)
-> (SaturationMode -> SaturationMode -> Bool) -> Eq SaturationMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SaturationMode -> SaturationMode -> Bool
\$c/= :: SaturationMode -> SaturationMode -> Bool
== :: SaturationMode -> SaturationMode -> Bool
\$c== :: SaturationMode -> SaturationMode -> Bool
Eq, Int -> SaturationMode
SaturationMode -> Int
SaturationMode -> [SaturationMode]
SaturationMode -> SaturationMode
SaturationMode -> SaturationMode -> [SaturationMode]
SaturationMode
-> SaturationMode -> SaturationMode -> [SaturationMode]
(SaturationMode -> SaturationMode)
-> (SaturationMode -> SaturationMode)
-> (Int -> SaturationMode)
-> (SaturationMode -> Int)
-> (SaturationMode -> [SaturationMode])
-> (SaturationMode -> SaturationMode -> [SaturationMode])
-> (SaturationMode -> SaturationMode -> [SaturationMode])
-> (SaturationMode
-> SaturationMode -> SaturationMode -> [SaturationMode])
-> Enum SaturationMode
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: SaturationMode
-> SaturationMode -> SaturationMode -> [SaturationMode]
\$cenumFromThenTo :: SaturationMode
-> SaturationMode -> SaturationMode -> [SaturationMode]
enumFromTo :: SaturationMode -> SaturationMode -> [SaturationMode]
\$cenumFromTo :: SaturationMode -> SaturationMode -> [SaturationMode]
enumFromThen :: SaturationMode -> SaturationMode -> [SaturationMode]
\$cenumFromThen :: SaturationMode -> SaturationMode -> [SaturationMode]
enumFrom :: SaturationMode -> [SaturationMode]
\$cenumFrom :: SaturationMode -> [SaturationMode]
fromEnum :: SaturationMode -> Int
\$cfromEnum :: SaturationMode -> Int
toEnum :: Int -> SaturationMode
\$ctoEnum :: Int -> SaturationMode
pred :: SaturationMode -> SaturationMode
\$cpred :: SaturationMode -> SaturationMode
succ :: SaturationMode -> SaturationMode
\$csucc :: SaturationMode -> SaturationMode
Enum, SaturationMode
SaturationMode -> SaturationMode -> Bounded SaturationMode
forall a. a -> a -> Bounded a
maxBound :: SaturationMode
\$cmaxBound :: SaturationMode
minBound :: SaturationMode
\$cminBound :: SaturationMode
Bounded)

-- | 'Num' operators in which overflow and underflow behavior can be specified
-- using 'SaturationMode'.
class (Bounded a, Num a) => SaturatingNum a where
-- | Addition with parameterizable over- and underflow behavior
satAdd :: SaturationMode -> a -> a -> a
-- | Subtraction with parameterizable over- and underflow behavior
satSub  :: SaturationMode -> a -> a -> a
-- | Multiplication with parameterizable over- and underflow behavior
satMul :: SaturationMode -> a -> a -> a
-- | Get successor of (or in other words, add 1 to) given number
satSucc :: SaturationMode -> a -> a
-- Default method suitable for types that can represent the number 1
satSucc SaturationMode
s a
n = SaturationMode -> a -> a -> a
forall a. SaturatingNum a => SaturationMode -> a -> a -> a
satAdd SaturationMode
s a
n a
1
{-# INLINE satSucc #-}
-- | Get predecessor of (or in other words, subtract 1 from) given number
satPred :: SaturationMode -> a -> a
-- Default method suitable for types that can represent the number 1
satPred SaturationMode
s a
n = SaturationMode -> a -> a -> a
forall a. SaturatingNum a => SaturationMode -> a -> a -> a
satSub SaturationMode
s a
n a
1
{-# INLINE satPred #-}

-- | Addition that clips to 'maxBound' on overflow, and 'minBound' on underflow
boundedAdd :: SaturatingNum a => a -> a -> a
boundedAdd :: a -> a -> a
boundedAdd = SaturationMode -> a -> a -> a
forall a. SaturatingNum a => SaturationMode -> a -> a -> a
satAdd SaturationMode
SatBound
{-# INLINE boundedAdd #-}

-- | Subtraction that clips to 'maxBound' on overflow, and 'minBound' on
-- underflow
boundedSub  :: SaturatingNum a => a -> a -> a
boundedSub :: a -> a -> a
boundedSub = SaturationMode -> a -> a -> a
forall a. SaturatingNum a => SaturationMode -> a -> a -> a
satSub SaturationMode
SatBound
{-# INLINE boundedSub #-}

-- | Multiplication that clips to 'maxBound' on overflow, and 'minBound' on
-- underflow
boundedMul :: SaturatingNum a => a -> a -> a
boundedMul :: a -> a -> a
boundedMul = SaturationMode -> a -> a -> a
forall a. SaturatingNum a => SaturationMode -> a -> a -> a
satMul SaturationMode
SatBound
{-# INLINE boundedMul #-}
```