Bitblasting of bitvectors #
This module provides theorems for showing the equivalence between BitVec operations using
the Fin 2^n
representation and Boolean vectors. It is still under development, but
intended to provide a path for converting SAT and SMT solver proofs about BitVectors
as vectors of bits into proofs about Lean BitVec
values.
The module is named for the bit-blasting operation in an SMT solver that converts bitvector expressions into expressions about individual bits in each vector.
Main results #
x + y : BitVec w
is(adc x y false).2
.
Future work #
All other operations are to be PR'ed later and are already proved in https://github.com/mhk119/lean-smt/blob/bitvec/Smt/Data/Bitwise.lean.
Preliminaries #
Addition #
If x &&& y = 0
, then the carry bit (x + y + 0)
is always false
for any index i
.
Intuitively, this is because a carry is only produced when at least two of x
, y
, and the
previous carry are true. However, since x &&& y = 0
, at most one of x, y
can be true,
and thus we never have a previous carry, which means that the sum cannot produce a carry.
Carry function for bitwise addition.
Equations
- BitVec.adcb x y c = (x.atLeastTwo y c, x.xor (y.xor c))
Instances For
Bitwise addition implemented via a ripple carry adder.
Equations
- x.adc y = BitVec.iunfoldr fun (i : Fin w) (c : Bool) => BitVec.adcb (x.getLsbD ↑i) (y.getLsbD ↑i) c
Instances For
add #
Adding a bitvector to its own complement yields the all ones bitpattern
Subtracting x
from the all ones bitvector is equivalent to taking its complement
Negation #
Inequalities (le / lt) #
mul recurrence for bitblasting #
A recurrence that describes multiplication as repeated addition. Is useful for bitblasting multiplication.
Equations
Instances For
Recurrence lemma: truncating to i+1
bits and then zero extending to w
equals truncating upto i
bits [0..i-1]
, and then adding the i
th bit of x
.
Recurrence lemma: multiplying x
with the first s
bits of y
is the
same as truncating y
to s
bits, then zero extending to the original length,
and performing the multplication.
shiftLeft recurrence for bitblasting #
shiftLeftRec x y n
shifts x
to the left by the first n
bits of y
.
The theorem shiftLeft_eq_shiftLeftRec
proves the equivalence of (x <<< y)
and shiftLeftRec
.
Together with equations shiftLeftRec_zero
, shiftLeftRec_succ
,
this allows us to unfold shiftLeft
into a circuit for bitblasting.
Equations
- x.shiftLeftRec y 0 = x <<< (y &&& BitVec.twoPow w₂ 0)
- x.shiftLeftRec y s_1.succ = x.shiftLeftRec y s_1 <<< (y &&& BitVec.twoPow w₂ s_1.succ)
Instances For
shiftLeftRec x y n
shifts x
to the left by the first n
bits of y
.
Show that x <<< y
can be written in terms of shiftLeftRec
.
This can be unfolded in terms of shiftLeftRec_zero
, shiftLeftRec_succ
for bitblasting.
sshiftRightRec x y n
shifts x
arithmetically/signed to the right by the first n
bits of y
.
The theorem sshiftRight_eq_sshiftRightRec
proves the equivalence of (x.sshiftRight y)
and sshiftRightRec
.
Together with equations sshiftRightRec_zero
, sshiftRightRec_succ
,
this allows us to unfold sshiftRight
into a circuit for bitblasting.
Equations
- x.sshiftRightRec y 0 = x.sshiftRight' (y &&& BitVec.twoPow w₂ 0)
- x.sshiftRightRec y s_1.succ = (x.sshiftRightRec y s_1).sshiftRight' (y &&& BitVec.twoPow w₂ s_1.succ)
Instances For
If y &&& z = 0
, x.sshiftRight (y ||| z) = (x.sshiftRight y).sshiftRight z
.
This follows as y &&& z = 0
implies y ||| z = y + z
,
and thus x.sshiftRight (y ||| z) = x.sshiftRight (y + z) = (x.sshiftRight y).sshiftRight z
.
Show that x.sshiftRight y
can be written in terms of sshiftRightRec
.
This can be unfolded in terms of sshiftRightRec_zero_eq
, sshiftRightRec_succ_eq
for bitblasting.
ushiftRightRec x y n
shifts x
logically to the right by the first n
bits of y
.
The theorem shiftRight_eq_ushiftRightRec
proves the equivalence
of (x >>> y)
and ushiftRightRec
.
Together with equations ushiftRightRec_zero
, ushiftRightRec_succ
,
this allows us to unfold ushiftRight
into a circuit for bitblasting.
Equations
- x.ushiftRightRec y 0 = x >>> (y &&& BitVec.twoPow w₂ 0)
- x.ushiftRightRec y s_1.succ = x.ushiftRightRec y s_1 >>> (y &&& BitVec.twoPow w₂ s_1.succ)
Instances For
Show that x >>> y
can be written in terms of ushiftRightRec
.
This can be unfolded in terms of ushiftRightRec_zero
, ushiftRightRec_succ
for bitblasting.