{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Grisette.Core.Data.Class.SafeArith
(
ArithException (..),
SafeDivision (..),
SafeLinearArith (..),
SymIntegerOp,
)
where
import Control.Exception
import Control.Monad.Except
import Data.Int
import Data.Typeable
import Data.Word
import GHC.TypeNats
import Grisette.Core.Control.Monad.Union
import Grisette.Core.Data.BV
import Grisette.Core.Data.Class.Bool
import Grisette.Core.Data.Class.Error
import Grisette.Core.Data.Class.Mergeable
import Grisette.Core.Data.Class.SOrd
import Grisette.Core.Data.Class.SimpleMergeable
import Grisette.Core.Data.Class.Solvable
class (SOrd a, Num a, Mergeable a, Mergeable e) => SafeDivision e a | a -> e where
safeDiv :: (MonadError e uf, MonadUnion uf) => a -> a -> uf a
safeDiv a
l a
r = do
(a
d, a
_) <- forall e a (uf :: * -> *).
(SafeDivision e a, MonadError e uf, MonadUnion uf) =>
a -> a -> uf (a, a)
safeDivMod a
l a
r
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
d
safeMod :: (MonadError e uf, MonadUnion uf) => a -> a -> uf a
safeMod a
l a
r = do
(a
_, a
m) <- forall e a (uf :: * -> *).
(SafeDivision e a, MonadError e uf, MonadUnion uf) =>
a -> a -> uf (a, a)
safeDivMod a
l a
r
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
m
safeDivMod :: (MonadError e uf, MonadUnion uf) => a -> a -> uf (a, a)
safeDivMod a
l a
r = do
a
d <- forall e a (uf :: * -> *).
(SafeDivision e a, MonadError e uf, MonadUnion uf) =>
a -> a -> uf a
safeDiv a
l a
r
a
m <- forall e a (uf :: * -> *).
(SafeDivision e a, MonadError e uf, MonadUnion uf) =>
a -> a -> uf a
safeMod a
l a
r
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
d, a
m)
safeQuot :: (MonadError e uf, MonadUnion uf) => a -> a -> uf a
safeQuot a
l a
r = do
(a
d, a
m) <- forall e a (uf :: * -> *).
(SafeDivision e a, MonadError e uf, MonadUnion uf) =>
a -> a -> uf (a, a)
safeDivMod a
l a
r
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
((a
l forall a. SOrd a => a -> a -> SymBool
>=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
>~ a
0) forall b. LogicalOp b => b -> b -> b
||~ (a
l forall a. SOrd a => a -> a -> SymBool
<=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
<~ a
0) forall b. LogicalOp b => b -> b -> b
||~ a
m forall a. SEq a => a -> a -> SymBool
==~ a
0)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
d)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle forall a b. (a -> b) -> a -> b
$ a
d forall a. Num a => a -> a -> a
+ a
1)
safeRem :: (MonadError e uf, MonadUnion uf) => a -> a -> uf a
safeRem a
l a
r = do
(a
d, a
m) <- forall e a (uf :: * -> *).
(SafeDivision e a, MonadError e uf, MonadUnion uf) =>
a -> a -> uf (a, a)
safeDivMod a
l a
r
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
((a
l forall a. SOrd a => a -> a -> SymBool
>=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
>~ a
0) forall b. LogicalOp b => b -> b -> b
||~ (a
l forall a. SOrd a => a -> a -> SymBool
<=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
<~ a
0) forall b. LogicalOp b => b -> b -> b
||~ a
m forall a. SEq a => a -> a -> SymBool
==~ a
0)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
m)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle forall a b. (a -> b) -> a -> b
$ a
m forall a. Num a => a -> a -> a
- a
r)
safeQuotRem :: (MonadError e uf, MonadUnion uf) => a -> a -> uf (a, a)
safeQuotRem a
l a
r = do
(a
d, a
m) <- forall e a (uf :: * -> *).
(SafeDivision e a, MonadError e uf, MonadUnion uf) =>
a -> a -> uf (a, a)
safeDivMod a
l a
r
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
((a
l forall a. SOrd a => a -> a -> SymBool
>=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
>~ a
0) forall b. LogicalOp b => b -> b -> b
||~ (a
l forall a. SOrd a => a -> a -> SymBool
<=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
<~ a
0) forall b. LogicalOp b => b -> b -> b
||~ a
m forall a. SEq a => a -> a -> SymBool
==~ a
0)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
d, a
m))
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
d forall a. Num a => a -> a -> a
+ a
1, a
m forall a. Num a => a -> a -> a
- a
r))
safeDiv' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf a
safeDiv' e -> e'
t a
l a
r = do
(a
d, a
_) <- forall e a e' (uf :: * -> *).
(SafeDivision e a, MonadError e' uf, MonadUnion uf,
Mergeable e') =>
(e -> e') -> a -> a -> uf (a, a)
safeDivMod' e -> e'
t a
l a
r
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
d
safeMod' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf a
safeMod' e -> e'
t a
l a
r = do
(a
_, a
m) <- forall e a e' (uf :: * -> *).
(SafeDivision e a, MonadError e' uf, MonadUnion uf,
Mergeable e') =>
(e -> e') -> a -> a -> uf (a, a)
safeDivMod' e -> e'
t a
l a
r
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
m
safeDivMod' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf (a, a)
safeDivMod' e -> e'
t a
l a
r = do
a
d <- forall e a e' (uf :: * -> *).
(SafeDivision e a, MonadError e' uf, MonadUnion uf,
Mergeable e') =>
(e -> e') -> a -> a -> uf a
safeDiv' e -> e'
t a
l a
r
a
m <- forall e a e' (uf :: * -> *).
(SafeDivision e a, MonadError e' uf, MonadUnion uf,
Mergeable e') =>
(e -> e') -> a -> a -> uf a
safeMod' e -> e'
t a
l a
r
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
d, a
m)
safeQuot' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf a
safeQuot' e -> e'
t a
l a
r = do
(a
d, a
m) <- forall e a e' (uf :: * -> *).
(SafeDivision e a, MonadError e' uf, MonadUnion uf,
Mergeable e') =>
(e -> e') -> a -> a -> uf (a, a)
safeDivMod' e -> e'
t a
l a
r
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
((a
l forall a. SOrd a => a -> a -> SymBool
>=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
>~ a
0) forall b. LogicalOp b => b -> b -> b
||~ (a
l forall a. SOrd a => a -> a -> SymBool
<=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
<~ a
0) forall b. LogicalOp b => b -> b -> b
||~ a
m forall a. SEq a => a -> a -> SymBool
==~ a
0)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
d)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle forall a b. (a -> b) -> a -> b
$ a
d forall a. Num a => a -> a -> a
+ a
1)
safeRem' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf a
safeRem' e -> e'
t a
l a
r = do
(a
d, a
m) <- forall e a e' (uf :: * -> *).
(SafeDivision e a, MonadError e' uf, MonadUnion uf,
Mergeable e') =>
(e -> e') -> a -> a -> uf (a, a)
safeDivMod' e -> e'
t a
l a
r
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
((a
l forall a. SOrd a => a -> a -> SymBool
>=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
>~ a
0) forall b. LogicalOp b => b -> b -> b
||~ (a
l forall a. SOrd a => a -> a -> SymBool
<=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
<~ a
0) forall b. LogicalOp b => b -> b -> b
||~ a
m forall a. SEq a => a -> a -> SymBool
==~ a
0)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
m)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle forall a b. (a -> b) -> a -> b
$ a
m forall a. Num a => a -> a -> a
- a
r)
safeQuotRem' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf (a, a)
safeQuotRem' e -> e'
t a
l a
r = do
(a
d, a
m) <- forall e a e' (uf :: * -> *).
(SafeDivision e a, MonadError e' uf, MonadUnion uf,
Mergeable e') =>
(e -> e') -> a -> a -> uf (a, a)
safeDivMod' e -> e'
t a
l a
r
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
((a
l forall a. SOrd a => a -> a -> SymBool
>=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
>~ a
0) forall b. LogicalOp b => b -> b -> b
||~ (a
l forall a. SOrd a => a -> a -> SymBool
<=~ a
0 forall b. LogicalOp b => b -> b -> b
&&~ a
r forall a. SOrd a => a -> a -> SymBool
<~ a
0) forall b. LogicalOp b => b -> b -> b
||~ a
m forall a. SEq a => a -> a -> SymBool
==~ a
0)
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
d, a
m))
(forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
d forall a. Num a => a -> a -> a
+ a
1, a
m forall a. Num a => a -> a -> a
- a
r))
{-# MINIMAL (safeDivMod | (safeDiv, safeMod)), (safeDivMod' | (safeDiv', safeMod')) #-}
#define QUOTE() '
#define QID(a) a
#define QRIGHT(a) QID(a)'
#define QRIGHTT(a) QID(a)' t'
#define SAFE_DIVISION_FUNC(name, op) \
name _ r | r == 0 = merge $ throwError DivideByZero; \
name l r = mrgSingle $ l `op` r; \
QRIGHTT(name) _ r | r == 0 = let t1 = t' in merge $ throwError (t' DivideByZero); \
QRIGHTT(name) l r = mrgSingle $ l `op` r
#define SAFE_DIVISION_CONCRETE(type) \
instance SafeDivision ArithException type where \
SAFE_DIVISION_FUNC(safeDiv, div); \
SAFE_DIVISION_FUNC(safeMod, mod); \
SAFE_DIVISION_FUNC(safeDivMod, divMod); \
SAFE_DIVISION_FUNC(safeQuot, quot); \
SAFE_DIVISION_FUNC(safeRem, rem); \
SAFE_DIVISION_FUNC(safeQuotRem, quotRem)
#define SAFE_DIVISION_CONCRETE_BV(type) \
instance (KnownNat n, 1 <= n) => SafeDivision ArithException (type n) where \
SAFE_DIVISION_FUNC(safeDiv, div); \
SAFE_DIVISION_FUNC(safeMod, mod); \
SAFE_DIVISION_FUNC(safeDivMod, divMod); \
SAFE_DIVISION_FUNC(safeQuot, quot); \
SAFE_DIVISION_FUNC(safeRem, rem); \
SAFE_DIVISION_FUNC(safeQuotRem, quotRem)
#if 1
SAFE_DIVISION_CONCRETE(Integer)
SAFE_DIVISION_CONCRETE(Int8)
SAFE_DIVISION_CONCRETE(Int16)
SAFE_DIVISION_CONCRETE(Int32)
SAFE_DIVISION_CONCRETE(Int64)
SAFE_DIVISION_CONCRETE(Int)
SAFE_DIVISION_CONCRETE(Word8)
SAFE_DIVISION_CONCRETE(Word16)
SAFE_DIVISION_CONCRETE(Word32)
SAFE_DIVISION_CONCRETE(Word64)
SAFE_DIVISION_CONCRETE(Word)
#endif
#define SAFE_DIVISION_FUNC_SOME(stype, type, name, op) \
name (stype (l :: type l)) (stype (r :: type r)) = \
(case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> \
if r == 0 \
then merge $ throwError $ Right DivideByZero \
else mrgSingle $ stype $ l `op` r; \
Nothing -> merge $ throwError $ Left BitwidthMismatch); \
QRIGHT(name) t (stype (l :: type l)) (stype (r :: type r)) = \
(case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> \
if r == 0 \
then merge $ throwError $ t (Right DivideByZero) \
else mrgSingle $ stype $ l `op` r; \
Nothing -> merge $ throwError $ t (Left BitwidthMismatch))
#define SAFE_DIVISION_FUNC_SOME_DIVMOD(stype, type, name, op) \
name (stype (l :: type l)) (stype (r :: type r)) = \
(case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> \
if r == 0 \
then merge $ throwError $ Right DivideByZero \
else (case l `op` r of (d, m) -> mrgSingle (stype d, stype m)); \
Nothing -> merge $ throwError $ Left BitwidthMismatch); \
QRIGHT(name) t (stype (l :: type l)) (stype (r :: type r)) = \
(case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> \
if r == 0 \
then merge $ throwError $ t (Right DivideByZero) \
else (case l `op` r of (d, m) -> mrgSingle (stype d, stype m)); \
Nothing -> merge $ throwError $ t (Left BitwidthMismatch))
#if 1
SAFE_DIVISION_CONCRETE_BV(IntN)
SAFE_DIVISION_CONCRETE_BV(WordN)
instance SafeDivision (Either BitwidthMismatch ArithException) SomeIntN where
SAFE_DIVISION_FUNC_SOME(SomeIntN, IntN, safeDiv, div)
SAFE_DIVISION_FUNC_SOME(SomeIntN, IntN, safeMod, mod)
SAFE_DIVISION_FUNC_SOME_DIVMOD(SomeIntN, IntN, safeDivMod, divMod)
SAFE_DIVISION_FUNC_SOME(SomeIntN, IntN, safeQuot, quot)
SAFE_DIVISION_FUNC_SOME(SomeIntN, IntN, safeRem, rem)
SAFE_DIVISION_FUNC_SOME_DIVMOD(SomeIntN, IntN, safeQuotRem, quotRem)
instance SafeDivision (Either BitwidthMismatch ArithException) SomeWordN where
SAFE_DIVISION_FUNC_SOME(SomeWordN, WordN, safeDiv, div)
SAFE_DIVISION_FUNC_SOME(SomeWordN, WordN, safeMod, mod)
SAFE_DIVISION_FUNC_SOME_DIVMOD(SomeWordN, WordN, safeDivMod, divMod)
SAFE_DIVISION_FUNC_SOME(SomeWordN, WordN, safeQuot, quot)
SAFE_DIVISION_FUNC_SOME(SomeWordN, WordN, safeRem, rem)
SAFE_DIVISION_FUNC_SOME_DIVMOD(SomeWordN, WordN, safeQuotRem, quotRem)
#endif
class (SOrd a, Num a, Mergeable a, Mergeable e) => SafeLinearArith e a | a -> e where
safeAdd :: (MonadError e uf, MonadUnion uf) => a -> a -> uf a
safeNeg :: (MonadError e uf, MonadUnion uf) => a -> uf a
safeMinus :: (MonadError e uf, MonadUnion uf) => a -> a -> uf a
safeAdd' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf a
safeNeg' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> uf a
safeMinus' :: (MonadError e' uf, MonadUnion uf, Mergeable e') => (e -> e') -> a -> a -> uf a
instance SafeLinearArith ArithException Integer where
safeAdd :: forall (uf :: * -> *).
(MonadError ArithException uf, MonadUnion uf) =>
Integer -> Integer -> uf Integer
safeAdd Integer
l Integer
r = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (Integer
l forall a. Num a => a -> a -> a
+ Integer
r)
safeNeg :: forall (uf :: * -> *).
(MonadError ArithException uf, MonadUnion uf) =>
Integer -> uf Integer
safeNeg Integer
l = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (-Integer
l)
safeMinus :: forall (uf :: * -> *).
(MonadError ArithException uf, MonadUnion uf) =>
Integer -> Integer -> uf Integer
safeMinus Integer
l Integer
r = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (Integer
l forall a. Num a => a -> a -> a
- Integer
r)
safeAdd' :: forall e' (uf :: * -> *).
(MonadError e' uf, MonadUnion uf, Mergeable e') =>
(ArithException -> e') -> Integer -> Integer -> uf Integer
safeAdd' ArithException -> e'
_ Integer
l Integer
r = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (Integer
l forall a. Num a => a -> a -> a
+ Integer
r)
safeNeg' :: forall e' (uf :: * -> *).
(MonadError e' uf, MonadUnion uf, Mergeable e') =>
(ArithException -> e') -> Integer -> uf Integer
safeNeg' ArithException -> e'
_ Integer
l = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (-Integer
l)
safeMinus' :: forall e' (uf :: * -> *).
(MonadError e' uf, MonadUnion uf, Mergeable e') =>
(ArithException -> e') -> Integer -> Integer -> uf Integer
safeMinus' ArithException -> e'
_ Integer
l Integer
r = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (Integer
l forall a. Num a => a -> a -> a
- Integer
r)
#define SAFE_LINARITH_SIGNED_CONCRETE_BODY \
safeAdd l r = let res = l + r in \
mrgIf (con $ l > 0 && r > 0 && res < 0) \
(throwError Overflow) \
(mrgIf (con $ l < 0 && r < 0 && res >= 0) \
(throwError Underflow) \
(return res));\
safeAdd' t' l r = let res = l + r in \
mrgIf (con $ l > 0 && r > 0 && res < 0) \
(throwError (t' Overflow)) \
(mrgIf (con $ l < 0 && r < 0 && res >= 0) \
(throwError (t' Underflow)) \
(return res)); \
safeMinus l r = let res = l - r in \
mrgIf (con $ l >= 0 && r < 0 && res < 0) \
(throwError Overflow) \
(mrgIf (con $ l < 0 && r > 0 && res > 0) \
(throwError Underflow) \
(return res));\
safeMinus' t' l r = let res = l - r in \
mrgIf (con $ l >= 0 && r < 0 && res < 0) \
(throwError (t' Overflow)) \
(mrgIf (con $ l < 0 && r > 0 && res > 0) \
(throwError (t' Underflow)) \
(return res)); \
safeNeg v = mrgIf (con $ v == minBound) (throwError Overflow) (return $ -v);\
safeNeg' t' v = mrgIf (con $ v == minBound) (throwError (t' Overflow)) (return $ -v)
#define SAFE_LINARITH_SIGNED_CONCRETE(type) \
instance SafeLinearArith ArithException type where \
SAFE_LINARITH_SIGNED_CONCRETE_BODY
#define SAFE_LINARITH_SIGNED_BV_CONCRETE(type) \
instance (KnownNat n, 1 <= n) => SafeLinearArith ArithException (type n) where \
SAFE_LINARITH_SIGNED_CONCRETE_BODY
#define SAFE_LINARITH_UNSIGNED_CONCRETE_BODY \
safeAdd l r = let res = l + r in \
mrgIf (con $ l > res || r > res) \
(throwError Overflow) \
(return res);\
safeAdd' t' l r = let res = l + r in \
mrgIf (con $ l > res || r > res) \
(throwError (t' Overflow)) \
(return res); \
safeMinus l r = \
mrgIf (con $ r > l) \
(throwError Underflow) \
(return $ l - r);\
safeMinus' t' l r = \
mrgIf (con $ r > l) \
(throwError $ t' Underflow) \
(return $ l - r);\
safeNeg v = mrgIf (con $ v /= 0) (throwError Underflow) (return $ -v);\
safeNeg' t' v = mrgIf (con $ v /= 0) (throwError (t' Underflow)) (return $ -v)
#define SAFE_LINARITH_UNSIGNED_CONCRETE(type) \
instance SafeLinearArith ArithException type where \
SAFE_LINARITH_UNSIGNED_CONCRETE_BODY
#define SAFE_LINARITH_UNSIGNED_BV_CONCRETE(type) \
instance (KnownNat n, 1 <= n) => SafeLinearArith ArithException (type n) where \
SAFE_LINARITH_UNSIGNED_CONCRETE_BODY
#define SAFE_LINARITH_SOME_CONCRETE(type, ctype) \
instance SafeLinearArith (Either BitwidthMismatch ArithException) type where \
safeAdd (type (l :: ctype l)) (type (r :: ctype r)) = merge (\
case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> type <$> safeAdd' Right l r; \
_ -> throwError $ Left BitwidthMismatch); \
safeAdd' t (type (l :: ctype l)) (type (r :: ctype r)) = merge (\
case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> type <$> safeAdd' (t . Right) l r; \
_ -> let t' = t; t''' = t in throwError $ t' $ Left BitwidthMismatch); \
safeMinus (type (l :: ctype l)) (type (r :: ctype r)) = merge (\
case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> type <$> safeMinus' Right l r; \
_ -> throwError $ Left BitwidthMismatch); \
safeMinus' t (type (l :: ctype l)) (type (r :: ctype r)) = merge (\
case sameNat (Proxy @l) (Proxy @r) of \
Just Refl -> type <$> safeMinus' (t . Right) l r; \
_ -> let t' = t; t''' = t in throwError $ t' $ Left BitwidthMismatch); \
safeNeg (type l) = merge $ type <$> safeNeg' Right l; \
safeNeg' t (type l) = merge $ type <$> safeNeg' (t . Right) l
#if 1
SAFE_LINARITH_SIGNED_CONCRETE(Int8)
SAFE_LINARITH_SIGNED_CONCRETE(Int16)
SAFE_LINARITH_SIGNED_CONCRETE(Int32)
SAFE_LINARITH_SIGNED_CONCRETE(Int64)
SAFE_LINARITH_SIGNED_CONCRETE(Int)
SAFE_LINARITH_SIGNED_BV_CONCRETE(IntN)
SAFE_LINARITH_SOME_CONCRETE(SomeIntN, IntN)
SAFE_LINARITH_UNSIGNED_CONCRETE(Word8)
SAFE_LINARITH_UNSIGNED_CONCRETE(Word16)
SAFE_LINARITH_UNSIGNED_CONCRETE(Word32)
SAFE_LINARITH_UNSIGNED_CONCRETE(Word64)
SAFE_LINARITH_UNSIGNED_CONCRETE(Word)
SAFE_LINARITH_UNSIGNED_BV_CONCRETE(WordN)
SAFE_LINARITH_SOME_CONCRETE(SomeWordN, WordN)
#endif
class (Num a, SEq a, SOrd a, Solvable Integer a) => SymIntegerOp a