Bit-Vectors

Basic Bit-Vector Term Builders

cvc5.pythonic.BitVec(name, bv, ctx=None)

Return a bit-vector constant named name. bv may be the number of bits of a bit-vector sort. If ctx=None, then the global context is used.

>>> x  = BitVec('x', 16)
>>> is_bv(x)
True
>>> x.size()
16
>>> x.sort()
BitVec(16)
>>> word = BitVecSort(16)
>>> x2 = BitVec('x', word)
>>> eq(x, x2)
True
cvc5.pythonic.BitVecVal(val, bv, ctx=None)

Return a bit-vector value with the given number of bits. If ctx=None, then the global context is used. The second argument can be a number of bits (integer) or a bit-vector sort.

>>> v = BitVecVal(10, 32)
>>> v
10
>>> print("0x%.8x" % v.as_long())
0x0000000a
>>> s = BitVecSort(3)
>>> u = BitVecVal(10, s)
>>> u
2
cvc5.pythonic.BitVecSort(sz, ctx=None)

Return an SMT bit-vector sort of the given size. If ctx=None, then the global context is used.

>>> Byte = BitVecSort(8)
>>> Word = BitVecSort(16)
>>> Byte
BitVec(8)
>>> x = Const('x', Byte)
>>> eq(x, BitVec('x', 8))
True
cvc5.pythonic.BitVecs(names, bv, ctx=None)

Return a tuple of bit-vector constants of size bv.

>>> x, y, z = BitVecs('x y z', 16)
>>> x.size()
16
>>> x.sort()
BitVec(16)
>>> Sum(x, y, z)
x + y + z
>>> Product(x, y, z)
x*y*z

Bit-Vector Overloads

See the following operator overloads for building bit-vector terms. Each kind of term can also be built with a builder function below.

Bit-Vector Term Builders

cvc5.pythonic.BV2Int(a, is_signed=False)

Return the SMT expression BV2Int(a).

>>> b = BitVec('b', 3)
>>> BV2Int(b).sort()
Int
>>> x = Int('x')
>>> x > BV2Int(b)
x > BV2Int(b)
>>> x > BV2Int(b, is_signed=False)
x > BV2Int(b)
>>> x > BV2Int(b, is_signed=True)
x > If(b < 0, BV2Int(b) - 8, BV2Int(b))
>>> solve(x > BV2Int(b), b == 1, x < 3)
[b = 1, x = 2]
cvc5.pythonic.Int2BV(a, num_bits)

Return the SMT expression Int2BV(a, num_bits). It is a bit-vector of width num_bits and represents the modulo of a by 2^num_bits

>>> x = Int('x')
>>> bv_x = Int2BV(x, 2)
>>> bv_x_plus_4 = Int2BV(x + 4, 2)
>>> solve([bv_x != bv_x_plus_4])
no solution
cvc5.pythonic.Concat(*args)

Create an SMT bit-vector, string, sequence or regular expression concatenation expression.

>>> v = BitVecVal(1, 4)
>>> Concat(v, v+1, v)
Concat(1, 1 + 1, 1)
>>> evaluate(Concat(v, v+1, v))
289
>>> print("%.3x" % simplify(Concat(v, v+1, v)).as_long())
121
cvc5.pythonic.Extract(high, low, a)

Create an SMT bit-vector extraction expression, or create a string extraction expression.

>>> x = BitVec('x', 8)
>>> Extract(6, 2, x)
Extract(6, 2, x)
>>> Extract(6, 2, x).sort()
BitVec(5)
cvc5.pythonic.ULE(a, b)

Create the SMT expression (unsigned) other <= self.

Use the operator <= for signed less than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> ULE(x, y)
ULE(x, y)
>>> (x <= y).sexpr()
'(bvsle x y)'
>>> ULE(x, y).sexpr()
'(bvule x y)'
cvc5.pythonic.ULT(a, b)

Create the SMT expression (unsigned) other < self.

Use the operator < for signed less than.

>>> x, y = BitVecs('x y', 32)
>>> ULT(x, y)
ULT(x, y)
>>> (x < y).sexpr()
'(bvslt x y)'
>>> ULT(x, y).sexpr()
'(bvult x y)'
cvc5.pythonic.UGE(a, b)

Create the SMT expression (unsigned) other >= self.

Use the operator >= for signed greater than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> UGE(x, y)
UGE(x, y)
>>> (x >= y).sexpr()
'(bvsge x y)'
>>> UGE(x, y).sexpr()
'(bvuge x y)'
cvc5.pythonic.UGT(a, b)

Create the SMT expression (unsigned) other > self.

Use the operator > for signed greater than.

>>> x, y = BitVecs('x y', 32)
>>> UGT(x, y)
UGT(x, y)
>>> (x > y).sexpr()
'(bvsgt x y)'
>>> UGT(x, y).sexpr()
'(bvugt x y)'
cvc5.pythonic.SLE(a, b)

Create the SMT expression (signed) other <= self.

See also the __le__ overload (<= operator) for BitVecRef

>>> x, y = BitVecs('x y', 32)
>>> SLE(x, y).sexpr()
'(bvsle x y)'
cvc5.pythonic.SLT(a, b)

Create the SMT expression (signed) other < self.

See also the __lt__ overload (< operator) for BitVecRef

>>> x, y = BitVecs('x y', 32)
>>> SLT(x, y).sexpr()
'(bvslt x y)'
cvc5.pythonic.SGE(a, b)

Create the SMT expression (signed) other >= self.

See also the __ge__ overload (>= operator) for BitVecRef

>>> x, y = BitVecs('x y', 32)
>>> SGE(x, y).sexpr()
'(bvsge x y)'
cvc5.pythonic.SGT(a, b)

Create the SMT expression (signed) other > self.

See also the __gt__ overload (> operator) for BitVecRef

>>> x, y = BitVecs('x y', 32)
>>> SGT(x, y).sexpr()
'(bvsgt x y)'
cvc5.pythonic.UDiv(a, b)

Create the SMT expression (unsigned) division self / other.

Use the operator / for signed division.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> UDiv(x, y)
UDiv(x, y)
>>> UDiv(x, y).sort()
BitVec(32)
>>> (x / y).sexpr()
'(bvsdiv x y)'
>>> UDiv(x, y).sexpr()
'(bvudiv x y)'
cvc5.pythonic.URem(a, b)

Create the SMT expression (unsigned) remainder self % other.

Use the operator % for signed modulus, and SRem() for signed remainder.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> URem(x, y)
URem(x, y)
>>> URem(x, y).sort()
BitVec(32)
>>> (x % y).sexpr()
'(bvsmod x y)'
>>> URem(x, y).sexpr()
'(bvurem x y)'
cvc5.pythonic.SDiv(a, b)

Create an SMT signed division expression.

See also the __div__ overload (/ operator) for BitVecRef.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> SDiv(x, y)
x/y
cvc5.pythonic.SMod(a, b)

Create an SMT expression for the signed modulus self % other.

See also the __mod__ overload (% operator) for BitVecRef.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> SMod(x, y)
x%y
cvc5.pythonic.SRem(a, b)

Create the SMT expression signed remainder.

Use the operator % for signed modulus, and URem() for unsigned remainder.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> SRem(x, y)
SRem(x, y)
>>> SRem(x, y).sort()
BitVec(32)
>>> (x % y).sexpr()
'(bvsmod x y)'
>>> SRem(x, y).sexpr()
'(bvsrem x y)'
cvc5.pythonic.LShR(a, b)

Create the SMT expression logical right shift.

Use the operator >> for the arithmetical right shift.

>>> x, y = BitVecs('x y', 32)
>>> LShR(x, y)
LShR(x, y)
>>> (x >> y).sexpr()
'(bvashr x y)'
>>> LShR(x, y).sexpr()
'(bvlshr x y)'
>>> BitVecVal(4, 3)
4
>>> BitVecVal(4, 3).as_signed_long()
-4
>>> simplify(BitVecVal(4, 3) >> 1).as_signed_long()
-2
>>> simplify(BitVecVal(4, 3) >> 1)
6
>>> simplify(LShR(BitVecVal(4, 3), 1))
2
>>> simplify(BitVecVal(2, 3) >> 1)
1
>>> simplify(LShR(BitVecVal(2, 3), 1))
1
cvc5.pythonic.RotateLeft(a, b)

Return an expression representing a rotated to the left b times.

>>> a, b = BitVecs('a b', 16)
>>> RotateLeft(a, 10)
RotateLeft(a, 10)
>>> simplify(RotateLeft(a, 0))
a
>>> simplify(RotateLeft(a, 16))
a
cvc5.pythonic.RotateRight(a, b)

Return an expression representing a rotated to the right b times.

>>> a, b = BitVecs('a b', 16)
>>> RotateRight(a, 10)
RotateRight(a, 10)
>>> simplify(RotateRight(a, 0))
a
>>> simplify(RotateRight(a, 16))
a
cvc5.pythonic.SignExt(n, a)

Return a bit-vector expression with n extra sign-bits.

>>> x = BitVec('x', 16)
>>> n = SignExt(8, x)
>>> n.size()
24
>>> n
SignExt(8, x)
>>> n.sort()
BitVec(24)
>>> v0 = BitVecVal(2, 2)
>>> v0
2
>>> v0.size()
2
>>> v  = simplify(SignExt(6, v0))
>>> v
254
>>> v.size()
8
>>> print("%.x" % v.as_long())
fe
cvc5.pythonic.ZeroExt(n, a)

Return a bit-vector expression with n extra zero-bits.

>>> x = BitVec('x', 16)
>>> n = ZeroExt(8, x)
>>> n.size()
24
>>> n
ZeroExt(8, x)
>>> n.sort()
BitVec(24)
>>> v0 = BitVecVal(2, 2)
>>> v0
2
>>> v0.size()
2
>>> v  = simplify(ZeroExt(6, v0))
>>> v
2
>>> v.size()
8
cvc5.pythonic.RepeatBitVec(n, a)

Return an expression representing n copies of a.

>>> x = BitVec('x', 8)
>>> n = RepeatBitVec(4, x)
>>> n
RepeatBitVec(4, x)
>>> n.size()
32
>>> v0 = BitVecVal(10, 4)
>>> print("%.x" % v0.as_long())
a
>>> v = simplify(RepeatBitVec(4, v0))
>>> v.size()
16
>>> print("%.x" % v.as_long())
aaaa
cvc5.pythonic.BVRedAnd(a)

Return the reduction-and expression of a.

>>> x = BitVec('x', 4)
>>> solve([BVRedAnd(x), BVRedOr(~x)])
no solution
cvc5.pythonic.BVRedOr(a)

Return the reduction-or expression of a.

>>> x = BitVec('x', 4)
>>> solve([BVRedAnd(x), BVRedOr(~x)])
no solution
cvc5.pythonic.BVAdd(*args)

Create a sum of bit-vectors.

See also the __add__ overload (+ operator) for BitVecRef.

>>> x, y, z = BitVecs('x y z', 32)
>>> BVAdd(x, y, z)
x + y + z
cvc5.pythonic.BVMult(*args)

Create a product of bit-vectors.

See also the __mul__ overload (* operator) for BitVecRef.

>>> x, y, z = BitVecs('x y z', 32)
>>> BVMult(x, y, z)
x*y*z
cvc5.pythonic.BVSub(a, b)

Create a difference of bit-vectors.

See also the __sub__ overload (- operator) for BitVecRef.

>>> x, y = BitVecs('x y', 32)
>>> BVSub(x, y)
x - y
cvc5.pythonic.BVOr(*args)

Create a bit-wise disjunction of bit-vectors.

See also the __or__ overload (| operator) for BitVecRef.

>>> x, y, z = BitVecs('x y z', 32)
>>> BVOr(x, y, z)
x | y | z
cvc5.pythonic.BVAnd(*args)

Create a bit-wise conjunction of bit-vectors.

See also the __and__ overload (& operator) for BitVecRef.

>>> x, y, z = BitVecs('x y z', 32)
>>> BVAnd(x, y, z)
x & y & z
cvc5.pythonic.BVXor(*args)

Create a bit-wise exclusive disjunction of bit-vectors.

See also the __xor__ overload (^ operator) for BitVecRef.

>>> x, y, z = BitVecs('x y z', 32)
>>> BVXor(x, y, z)
x ^ y ^ z
cvc5.pythonic.BVNeg(a)

Create a negation (two’s complement) of a bit-vector

See also the __neg__ overload (unary - operator) for BitVecRef.

>>> x = BitVec('x', 32)
>>> BVNeg(x)
-x
cvc5.pythonic.BVNot(a)

Create a bitwise not of a bit-vector

See also the __invert__ overload (unary ~ operator) for BitVecRef.

>>> x = BitVec('x', 32)
>>> BVNot(x)
~x

Testers

cvc5.pythonic.is_bv_sort(s)

Return True if s is an SMT bit-vector sort.

>>> is_bv_sort(BitVecSort(32))
True
>>> is_bv_sort(IntSort())
False
cvc5.pythonic.is_bv(a)

Return True if a is an SMT bit-vector expression.

>>> b = BitVec('b', 32)
>>> is_bv(b)
True
>>> is_bv(b + 10)
True
>>> is_bv(Int('x'))
False
cvc5.pythonic.is_bv_value(a)

Return True if a is an SMT bit-vector numeral value.

>>> b = BitVec('b', 32)
>>> is_bv_value(b)
False
>>> b = BitVecVal(10, 32)
>>> b
10
>>> is_bv_value(b)
True

Classes (with overloads)

class cvc5.pythonic.BitVecSortRef(ast, ctx=None)

Bit-vector sort.

cast(val)

Try to cast val as a Bit-Vector.

>>> b = BitVecSort(32)
>>> b.cast(10)
10
>>> b.cast(10).sexpr()
'#b00000000000000000000000000001010'
size()

Return the size (number of bits) of the bit-vector sort self.

>>> b = BitVecSort(32)
>>> b.size()
32
subsort(other)

Return True if self is a subsort of other.

>>> IntSort().subsort(RealSort())
True
>>> BoolSort().subsort(RealSort())
True
>>> SetSort(BitVecSort(2)).subsort(SetSort(IntSort()))
False
class cvc5.pythonic.BitVecRef(ast, ctx=None, reverse_children=False)

Bit-vector expressions.

__add__(other)

Create the SMT expression self + other.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x + y
x + y
>>> (x + y).sort()
BitVec(32)
__and__(other)

Create the SMT expression bitwise-and self & other.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x & y
x & y
>>> (x & y).sort()
BitVec(32)
__div__(other)

Create the SMT expression (signed) division self / other.

Use the function UDiv() for unsigned division.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x / y
x/y
>>> (x / y).sort()
BitVec(32)
>>> (x / y).sexpr()
'(bvsdiv x y)'
>>> UDiv(x, y).sexpr()
'(bvudiv x y)'
__ge__(other)

Create the SMT expression (signed) other >= self.

Use the function UGE() for unsigned greater than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> x >= y
x >= y
>>> (x >= y).sexpr()
'(bvsge x y)'
>>> UGE(x, y).sexpr()
'(bvuge x y)'
__gt__(other)

Create the SMT expression (signed) other > self.

Use the function UGT() for unsigned greater than.

>>> x, y = BitVecs('x y', 32)
>>> x > y
x > y
>>> (x > y).sexpr()
'(bvsgt x y)'
>>> UGT(x, y).sexpr()
'(bvugt x y)'
__invert__()

Create the SMT expression bitwise-not ~self.

>>> x = BitVec('x', 32)
>>> ~x
~x
>>> solve([~(~x) != x])
no solution
__le__(other)

Create the SMT expression (signed) other <= self.

Use the function ULE() for unsigned less than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> x <= y
x <= y
>>> (x <= y).sexpr()
'(bvsle x y)'
>>> ULE(x, y).sexpr()
'(bvule x y)'
__lshift__(other)

Create the SMT expression left shift self << other

>>> x, y = BitVecs('x y', 32)
>>> x << y
x << y
>>> (x << y).sexpr()
'(bvshl x y)'
>>> evaluate(BitVecVal(2, 3) << 1)
4
__lt__(other)

Create the SMT expression (signed) other < self.

Use the function ULT() for unsigned less than.

>>> x, y = BitVecs('x y', 32)
>>> x < y
x < y
>>> (x < y).sexpr()
'(bvslt x y)'
>>> ULT(x, y).sexpr()
'(bvult x y)'
__mod__(other)

Create the SMT expression (signed) mod self % other.

Use the function URem() for unsigned remainder, and SRem() for signed remainder.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x % y
x%y
>>> (x % y).sort()
BitVec(32)
>>> (x % y).sexpr()
'(bvsmod x y)'
>>> URem(x, y).sexpr()
'(bvurem x y)'
>>> SRem(x, y).sexpr()
'(bvsrem x y)'
__mul__(other)

Create the SMT expression self * other.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x * y
x*y
>>> (x * y).sort()
BitVec(32)
__neg__()

Return an expression representing -self.

>>> x = BitVec('x', 32)
>>> -x
-x
>>> solve([-(-x) != x])
no solution
__or__(other)

Create the SMT expression bitwise-or self | other.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x | y
x | y
>>> (x | y).sort()
BitVec(32)
__pos__()

Return self.

>>> x = BitVec('x', 32)
>>> +x
x
__radd__(other)

Create the SMT expression other + self.

>>> x = BitVec('x', 32)
>>> 10 + x
10 + x
__rand__(other)

Create the SMT expression bitwise-or other & self.

>>> x = BitVec('x', 32)
>>> 10 & x
10 & x
__rdiv__(other)

Create the SMT expression (signed) division other / self.

Use the function UDiv() for unsigned division.

>>> x = BitVec('x', 32)
>>> 10 / x
10/x
>>> (10 / x).sexpr()
'(bvsdiv #b00000000000000000000000000001010 x)'
>>> UDiv(10, x).sexpr()
'(bvudiv #b00000000000000000000000000001010 x)'
__rlshift__(other)

Create the SMT expression left shift other << self.

Use the function LShR() for the right logical shift

>>> x = BitVec('x', 32)
>>> 10 << x
10 << x
>>> (10 << x).sexpr()
'(bvshl #b00000000000000000000000000001010 x)'
__rmod__(other)

Create the SMT expression (signed) mod other % self.

Use the function URem() for unsigned remainder, and SRem() for signed remainder.

>>> x = BitVec('x', 32)
>>> 10 % x
10%x
>>> (10 % x).sexpr()
'(bvsmod #b00000000000000000000000000001010 x)'
>>> URem(10, x).sexpr()
'(bvurem #b00000000000000000000000000001010 x)'
>>> SRem(10, x).sexpr()
'(bvsrem #b00000000000000000000000000001010 x)'
__rmul__(other)

Create the SMT expression other * self.

>>> x = BitVec('x', 32)
>>> 10 * x
10*x
__ror__(other)

Create the SMT expression bitwise-or other | self.

>>> x = BitVec('x', 32)
>>> 10 | x
10 | x
__rrshift__(other)

Create the SMT expression (arithmetical) right shift other >> self.

Use the function LShR() for the right logical shift

>>> x = BitVec('x', 32)
>>> 10 >> x
10 >> x
>>> (10 >> x).sexpr()
'(bvashr #b00000000000000000000000000001010 x)'
__rshift__(other)

Create the SMT expression (arithmetical) right shift self >> other

Use the function LShR() for the right logical shift

>>> x, y = BitVecs('x y', 32)
>>> x >> y
x >> y
>>> (x >> y).sexpr()
'(bvashr x y)'
>>> LShR(x, y).sexpr()
'(bvlshr x y)'
>>> BitVecVal(4, 3)
4
>>> BitVecVal(4, 3).as_signed_long()
-4
>>> evaluate(BitVecVal(4, 3) >> 1).as_signed_long()
-2
>>> evaluate(BitVecVal(4, 3) >> 1)
6
>>> evaluate(LShR(BitVecVal(4, 3), 1))
2
>>> evaluate(BitVecVal(2, 3) >> 1)
1
>>> evaluate(LShR(BitVecVal(2, 3), 1))
1
__rsub__(other)

Create the SMT expression other - self.

>>> x = BitVec('x', 32)
>>> 10 - x
10 - x
__rtruediv__(other)

Create the SMT expression (signed) division other / self.

__rxor__(other)

Create the SMT expression bitwise-xor other ^ self.

>>> x = BitVec('x', 32)
>>> 10 ^ x
10 ^ x
__sub__(other)

Create the SMT expression self - other.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x - y
x - y
>>> (x - y).sort()
BitVec(32)
__truediv__(other)

Create the SMT expression (signed) division self / other.

__xor__(other)

Create the SMT expression bitwise-xor self ^ other.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x ^ y
x ^ y
>>> (x ^ y).sort()
BitVec(32)
size()

Return the number of bits of the bit-vector expression self.

>>> x = BitVec('x', 32)
>>> (x + 1).size()
32
>>> Concat(x, x).size()
64
sort()

Return the sort of the bit-vector expression self.

>>> x = BitVec('x', 32)
>>> x.sort()
BitVec(32)
>>> x.sort() == BitVecSort(32)
True
class cvc5.pythonic.BitVecNumRef(ast, ctx=None, reverse_children=False)

Bit-vector values.

as_long()

Return an SMT bit-vector numeral as a Python long (bignum) numeral.

>>> v = BitVecVal(0xbadc0de, 32)
>>> v
195936478
>>> print("0x%.8x" % v.as_long())
0x0badc0de
as_signed_long()

Return an SMT bit-vector numeral as a Python long (bignum) numeral. The most significant bit is assumed to be the sign.

>>> BitVecVal(4, 3).as_signed_long()
-4
>>> BitVecVal(7, 3).as_signed_long()
-1
>>> BitVecVal(3, 3).as_signed_long()
3
>>> BitVecVal(2**32 - 1, 32).as_signed_long()
-1
>>> BitVecVal(2**64 - 1, 64).as_signed_long()
-1