{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE Trustworthy #-} -- | -- Module : Grisette.Core.Data.Class.Integer -- Copyright : (c) Sirui Lu 2021-2023 -- License : BSD-3-Clause (see the LICENSE file) -- -- Maintainer : siruilu@cs.washington.edu -- Stability : Experimental -- Portability : GHC only module Grisette.Core.Data.Class.Integer ( -- * Symbolic integer operations ArithException (..), SignedDivMod (..), UnsignedDivMod (..), SignedQuotRem (..), SymIntegerOp, ) where import Control.Exception import Control.Monad.Except import Grisette.Core.Control.Monad.Union import Grisette.Core.Data.Class.Bool import Grisette.Core.Data.Class.Error import Grisette.Core.Data.Class.SOrd import Grisette.Core.Data.Class.Solvable -- $setup -- >>> import Grisette.Core -- >>> import Grisette.IR.SymPrim -- | Safe signed 'div' and 'mod' with monadic error handling in multi-path -- execution. These procedures show throw 'DivideByZero' exception when the -- divisor is zero. The result should be able to handle errors with -- `MonadError`, and the error type should be compatible with 'ArithException' -- (see 'TransformError' for more details). class SignedDivMod a where -- | Safe signed 'div' with monadic error handling in multi-path execution. -- -- >>> divs (ssym "a") (ssym "b") :: ExceptT AssertionError UnionM SymInteger -- ExceptT {If (= b 0) (Left AssertionError) (Right (div a b))} divs :: (MonadError e uf, MonadUnion uf, TransformError ArithException e) => a -> a -> uf a -- | Safe signed 'mod' with monadic error handling in multi-path execution. -- -- >>> mods (ssym "a") (ssym "b") :: ExceptT AssertionError UnionM SymInteger -- ExceptT {If (= b 0) (Left AssertionError) (Right (mod a b))} mods :: (MonadError e uf, MonadUnion uf, TransformError ArithException e) => a -> a -> uf a -- | Safe unsigned 'div' and 'mod' with monadic error handling in multi-path -- execution. These procedures show throw 'DivideByZero' exception when the -- divisor is zero. The result should be able to handle errors with -- `MonadError`, and the error type should be compatible with 'ArithException' -- (see 'TransformError' for more details). class UnsignedDivMod a where udivs :: (MonadError e uf, MonadUnion uf, TransformError ArithException e) => a -> a -> uf a umods :: (MonadError e uf, MonadUnion uf, TransformError ArithException e) => a -> a -> uf a -- | Safe signed 'quot' and 'rem' with monadic error handling in multi-path -- execution. These procedures show throw 'DivideByZero' exception when the -- divisor is zero. The result should be able to handle errors with -- `MonadError`, and the error type should be compatible with 'ArithException' -- (see 'TransformError' for more details). class SignedQuotRem a where quots :: (MonadError e uf, MonadUnion uf, TransformError ArithException e) => a -> a -> uf a rems :: (MonadError e uf, MonadUnion uf, TransformError ArithException e) => a -> a -> uf a -- | Aggregation for the operations on symbolic integer types class (Num a, SEq a, SOrd a, Solvable Integer a) => SymIntegerOp a