This normalized a bitvec using ofFin
to ofNat
.
msb #
cast #
toInt/ofInt #
slt #
setWidth, zeroExtend and truncate #
zero extending a bitvector to width 1 equals the boolean of the lsb.
Zero extending 1#v
to 1#w
equals 1#w
when v > 0
.
Truncating to width 1 produces a bitvector equal to the least significant bit.
extractLsb #
allOnes #
or #
and #
xor #
not #
cast #
shiftLeft #
shiftLeft reductions from BitVec to Nat #
ushiftRight #
ushiftRight reductions from BitVec to Nat #
sshiftRight #
If the msb is true
, the arithmetic shift right equals negating,
then logical shifting right, then negating again.
The double negation preserves the lower bits that have been shifted,
and the outer negation ensures that the high bits are '1'.
The msb after arithmetic shifting right equals the original msb.
sshiftRight reductions from BitVec to Nat #
signExtend #
The sign extension is the same as zero extending when msb = false
.
The sign extension is a bitwise not, followed by a zero extend, followed by another bitwise not
when msb = true
. The double bitwise not ensures that the high bits are '1',
and the lower bits are preserved.
Sign extending to a width smaller than the starting width is a truncation.
Sign extending to the same bitwidth is a no op.
Sign extending to a larger bitwidth depends on the msb.
If the msb is false, then the result equals the original value.
If the msb is true, then we add a value of (2^v - 2^w)
, which arises from the sign extension.
append #
rev #
cons #
Variant of toNat_cons
using +
instead of |||
.
concat #
shiftConcat #
add #
sub/neg #
mul #
le and lt #
udiv #
umod #
smtUDiv #
sdiv #
smtSDiv #
srem #
smod #
Equation theorem for smod
in terms of umod
.
ofBoolList #
Rotate Left #
Accessing bits in x.rotateLeft r
the range [0, r)
is equal to
accessing bits x
in the range [w - r, w)
.
Proof by example: Let x := <6 5 4 3 2 1 0> : BitVec 7. x.rotateLeft 2 = (<6 5 | 4 3 2 1 0>).rotateLeft 2 = <3 2 1 0 | 6 5>
(x.rotateLeft 2).getLsbD ⟨i, i < 2⟩ = <3 2 1 0 | 6 5>.getLsbD ⟨i, i < 2⟩ = <6 5>[i] = <6 5 | 4 3 2 1 0>[i + len(<4 3 2 1 0>)] = <6 5 | 4 3 2 1 0>[i + 7 - 2]
Accessing bits in x.rotateLeft r
the range [r, w)
is equal to
accessing bits x
in the range [0, w - r)
.
Proof by example: Let x := <6 5 4 3 2 1 0> : BitVec 7. x.rotateLeft 2 = (<6 5 | 4 3 2 1 0>).rotateLeft 2 = <3 2 1 0 | 6 5>
(x.rotateLeft 2).getLsbD ⟨i, i ≥ 2⟩ = <3 2 1 0 | 6 5>.getLsbD ⟨i, i ≥ 2⟩ = <3 2 1 0>[i - 2] = <6 5 | 3 2 1 0>[i - 2]
Intuitively, grab the full width (7), then move the marker |
by r
to the right (-2)
Then, access the bit at i
from the right (+i)
.
Rotate Right #
Accessing bits in x.rotateRight r
the range [0, w-r)
is equal to
accessing bits x
in the range [r, w)
.
Proof by example: Let x := <6 5 4 3 2 1 0> : BitVec 7. x.rotateRight 2 = (<6 5 4 3 2 | 1 0>).rotateRight 2 = <1 0 | 6 5 4 3 2>
(x.rotateLeft 2).getLsbD ⟨i, i ≤ 7 - 2⟩ = <1 0 | 6 5 4 3 2>.getLsbD ⟨i, i ≤ 7 - 2⟩ = <6 5 4 3 2>.getLsbD i = <6 5 4 3 2 | 1 0>[i + 2]
Accessing bits in x.rotateRight r
the range [w-r, w)
is equal to
accessing bits x
in the range [0, r)
.
Proof by example: Let x := <6 5 4 3 2 1 0> : BitVec 7. x.rotateRight 2 = (<6 5 4 3 2 | 1 0>).rotateRight 2 = <1 0 | 6 5 4 3 2>
(x.rotateLeft 2).getLsbD ⟨i, i ≥ 7 - 2⟩ = <1 0 | 6 5 4 3 2>.getLsbD ⟨i, i ≤ 7 - 2⟩ = <1 0>.getLsbD (i - len(<6 5 4 3 2>) = <6 5 4 3 2 | 1 0> (i - len<6 4 4 3 2>)
The unsigned division of x
by 2^k
equals shifting x
right by k
,
when k
is less than the bitwidth w
.
When the (i+1)
th bit of x
is false,
keeping the lower (i + 1)
bits of x
equals keeping the lower i
bits.
When the (i+1)
th bit of x
is true,
keeping the lower (i + 1)
bits of x
equalsk eeping the lower i
bits
and then performing bitwise-or with twoPow i = (1 << i)
,
Bitwise and of (x : BitVec w)
with 1#w
equals zero extending x.lsb
to w
.
intMin #
The bitvector of width w
that has the smallest value when interpreted as an integer.
Equations
- BitVec.intMin w = BitVec.twoPow w (w - 1)
Instances For
The RHS is zero in case w = 0
which is modeled by wrapping the expression in ... % 2 ^ w
.
The RHS is zero in case w = 0
which is modeled by wrapping the expression in ... % 2 ^ w
.
intMax #
The bitvector of width w
that has the largest value when interpreted as an integer.
Equations
- BitVec.intMax w = BitVec.twoPow w (w - 1) - 1
Instances For
Non-overflow theorems #
neg #
abs #
The absolute value of x : BitVec w
, interpreted as an integer, is a case split:
- When
x = intMin w
, thenx.abs = intMin w
- Otherwise,
x.abs.toInt
equals the absolute value (x.toInt.natAbs
).
This is a simpler version of BitVec.toInt_abs_eq_ite
, which hides a case split on x.msb
.
Decidable quantifiers #
Equations
- BitVec.instDecidableForallBitVecSucc P = decidable_of_iff' (∀ (x : Bool) (v : BitVec n), P (BitVec.cons x v)) ⋯
Equations
- BitVec.instDecidableExistsBitVecZero P = decidable_of_iff (¬∀ (v : BitVec 0), ¬P v) ⋯
Equations
- BitVec.instDecidableExistsBitVecSucc P = decidable_of_iff (¬∀ (v : BitVec (n + 1)), ¬P v) ⋯
For small numerals this isn't necessary (as typeclass search can use the above two instances),
but for large numerals this provides a shortcut.
Note, however, that for large numerals the decision procedure may be very slow,
and you should use bv_decide
if possible.
Equations
- BitVec.instDecidableForallBitVec 0 x_3 = inferInstance
- BitVec.instDecidableForallBitVec n.succ x_3 = inferInstance
For small numerals this isn't necessary (as typeclass search can use the above two instances), but for large numerals this provides a shortcut. Note, however, that for large numerals the decision procedure may be very slow.
Equations
- BitVec.instDecidableExistsBitVec 0 x_3 = inferInstance
- BitVec.instDecidableExistsBitVec n.succ x_3 = inferInstance