sbv-11.4: SMT Based Verification: Symbolic Haskell theorem prover using SMT solving.
Copyright(c) Levent Erkok
LicenseBSD3
Maintainererkokl@gmail.com
Stabilityexperimental
Safe HaskellNone
LanguageHaskell2010

Data.SBV.Tools.Overflow

Description

Implementation of overflow detection functions. Based on: http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/z3prefix.pdf

Synopsis

Arithmetic overflows

class ArithOverflow a where Source #

Detecting overflow. Each function here will return sTrue if the result will not fit in the target type, i.e., if it overflows or underflows.

Methods

bvAddO :: a -> a -> SBool Source #

Bit-vector addition. Unsigned addition can only overflow. Signed addition can underflow and overflow.

A tell tale sign of unsigned addition overflow is when the sum is less than minimum of the arguments.

>>> prove $ \x y -> bvAddO x (y::SWord16) .<=> x + y .< x `smin` y
Q.E.D.

bvSubO :: a -> a -> SBool Source #

Bit-vector subtraction. Unsigned subtraction can only underflow. Signed subtraction can underflow and overflow.

bvMulO :: a -> a -> SBool Source #

Bit-vector multiplication. Unsigned multiplication can only overflow. Signed multiplication can underflow and overflow.

bvDivO :: a -> a -> SBool Source #

Bit-vector division. Unsigned division neither underflows nor overflows. Signed division can only overflow. In fact, for each signed bitvector type, there's precisely one pair that overflows, when x is minBound and y is -1:

>>> allSat $ \x y -> x `bvDivO` (y::SInt8)
Solution #1:
  s0 = -128 :: Int8
  s1 =   -1 :: Int8
This is the only solution.

bvNegO :: a -> SBool Source #

Bit-vector negation. Unsigned negation neither underflows nor overflows. Signed negation can only overflow, when the argument is minBound:

>>> prove $ \x -> x .== minBound .<=> bvNegO (x::SInt16)
Q.E.D.

Instances

Instances details
ArithOverflow SInt16 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SInt32 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SInt64 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SInt8 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SWord16 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SWord32 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SWord64 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SWord8 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

ArithOverflow SVal Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

(KnownNat n, BVIsNonZero n) => ArithOverflow (SInt n) Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

Methods

bvAddO :: SInt n -> SInt n -> SBool Source #

bvSubO :: SInt n -> SInt n -> SBool Source #

bvMulO :: SInt n -> SInt n -> SBool Source #

bvDivO :: SInt n -> SInt n -> SBool Source #

bvNegO :: SInt n -> SBool Source #

(KnownNat n, BVIsNonZero n) => ArithOverflow (SWord n) Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

Methods

bvAddO :: SWord n -> SWord n -> SBool Source #

bvSubO :: SWord n -> SWord n -> SBool Source #

bvMulO :: SWord n -> SWord n -> SBool Source #

bvDivO :: SWord n -> SWord n -> SBool Source #

bvNegO :: SWord n -> SBool Source #

class (ArithOverflow (SBV a), Num a, SymVal a) => CheckedArithmetic a where Source #

A class of checked-arithmetic operations. These follow the usual arithmetic, except make calls to sAssert to ensure no overflow/underflow can occur. Use them in conjunction with safe to ensure no overflow can happen.

Methods

(+!) :: SBV a -> SBV a -> SBV a infixl 6 Source #

(-!) :: SBV a -> SBV a -> SBV a infixl 6 Source #

(*!) :: SBV a -> SBV a -> SBV a infixl 7 Source #

(/!) :: SBV a -> SBV a -> SBV a infixl 7 Source #

negateChecked :: SBV a -> SBV a Source #

Instances

Instances details
CheckedArithmetic Int16 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

CheckedArithmetic Int32 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

CheckedArithmetic Int64 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

CheckedArithmetic Int8 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

CheckedArithmetic Word16 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

CheckedArithmetic Word32 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

CheckedArithmetic Word64 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

CheckedArithmetic Word8 Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

(KnownNat n, BVIsNonZero n) => CheckedArithmetic (IntN n) Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

Methods

(+!) :: SBV (IntN n) -> SBV (IntN n) -> SBV (IntN n) Source #

(-!) :: SBV (IntN n) -> SBV (IntN n) -> SBV (IntN n) Source #

(*!) :: SBV (IntN n) -> SBV (IntN n) -> SBV (IntN n) Source #

(/!) :: SBV (IntN n) -> SBV (IntN n) -> SBV (IntN n) Source #

negateChecked :: SBV (IntN n) -> SBV (IntN n) Source #

(KnownNat n, BVIsNonZero n) => CheckedArithmetic (WordN n) Source # 
Instance details

Defined in Data.SBV.Tools.Overflow

Methods

(+!) :: SBV (WordN n) -> SBV (WordN n) -> SBV (WordN n) Source #

(-!) :: SBV (WordN n) -> SBV (WordN n) -> SBV (WordN n) Source #

(*!) :: SBV (WordN n) -> SBV (WordN n) -> SBV (WordN n) Source #

(/!) :: SBV (WordN n) -> SBV (WordN n) -> SBV (WordN n) Source #

negateChecked :: SBV (WordN n) -> SBV (WordN n) Source #

Fast-checking of signed-multiplication overflow

signedMulOverflow :: forall (n :: Nat). (KnownNat n, BVIsNonZero n, KnownNat (n + 1), BVIsNonZero (n + 1), KnownNat (2 + Log2 n), BVIsNonZero (2 + Log2 n)) => SInt n -> SInt n -> SBool Source #

signedMulOverflow: Checking if a signed bitvector multiplication can overflow. In general you should simply use bvMulO for checking signed multiplication overflow for bit-vectors. This is a function supported by SMTLib. Unfortunately, individual implementations have different performance characteristics. For instance, bitwuzla has a fairly performant implementation of this, but z3 does not. (At least not as of August 2024.) In cases where you can't use bitwuzla, you can use this implementation which has better performance.

Cast overflows

sFromIntegralO :: (Integral a, HasKind a, Num a, SymVal a, HasKind b, Num b, SymVal b) => SBV a -> (SBV b, (SBool, SBool)) Source #

Detecting underflow/overflow conditions for casting between bit-vectors. The first output is the result, the second component itself is a pair with the first boolean indicating underflow and the second indicating overflow.

>>> sFromIntegralO (256 :: SInt16) :: (SWord8, (SBool, SBool))
(0 :: SWord8,(False,True))
>>> sFromIntegralO (-2 :: SInt16) :: (SWord8, (SBool, SBool))
(254 :: SWord8,(True,False))
>>> sFromIntegralO (2 :: SInt16) :: (SWord8, (SBool, SBool))
(2 :: SWord8,(False,False))
>>> prove $ \x -> sFromIntegralO (x::SInt32) .== (sFromIntegral x :: SInteger, (sFalse, sFalse))
Q.E.D.

As the last example shows, converting to sInteger never underflows or overflows for any value.

sFromIntegralChecked :: (?loc :: CallStack, Integral a, HasKind a, HasKind b, Num a, SymVal a, HasKind b, Num b, SymVal b) => SBV a -> SBV b Source #

Version of sFromIntegral that has calls to sAssert for checking no overflow/underflow can happen. Use it with a safe call.