This PR adds SMT-LIB operators to detect overflow
`BitVec.(umul_overflow, smul_overflow)`, according to the definitions
[here](https://github.com/SMT-LIB/SMT-LIB-2/blob/2.7/Theories/FixedSizeBitVectors.smt2),
and the theorems proving equivalence of such definitions with the
`BitVec` library functions (`umulOverflow_eq`, `smulOverflow_eq`).
Support theorems for these proofs are `BitVec.toInt_one_of_lt,
BitVec.toInt_mul_toInt_lt, BitVec.le_toInt_mul_toInt,
BitVec.toNat_mul_toNat_lt, BitVec.two_pow_le_toInt_mul_toInt_iff,
BitVec.toInt_mul_toInt_lt_neg_two_pow_iff` and `Int.neg_mul_le_mul,
Int.bmod_eq_self_of_le_mul_two, Int.mul_le_mul_of_natAbs_le,
Int.mul_le_mul_of_le_of_le_of_nonneg_of_nonpos, Int.pow_lt_pow`. The PR
also includes a set of tests.
Co-authored by @tobiasgrosser.
---------
Co-authored-by: Tobias Grosser <tobias@grosser.es>
Co-authored-by: Tobias Grosser <github@grosser.es>
Co-authored-by: Siddharth <siddu.druid@gmail.com>
This PR adds the Bitwuzla rewrite `NORM_BV_ADD_CONCAT` for symbolic
simplification of add-of-append.
---------
Co-authored-by: Tobias Grosser <github@grosser.es>
This PR makes the BitVec docstrings match each other and the rest of the
API in style.
---------
Co-authored-by: Markus Himmel <markus@himmel-villmar.de>
Co-authored-by: Siddharth <siddu.druid@gmail.com>
This PR implements the Bitwuzla rewrites
[BV_EXTRACT_ADD_MUL](e09c50818b/src/rewrite/rewrites_bv.cpp (L1495-L1510)),
which witness that the high bits at `i >= len` do not affect the bits of
the product upto `len`.
```lean
theorem extractLsb'_mul {w len} {x y : BitVec w} (hlen : len < w) :
(x * y).extractLsb' 0 len = x.extractLsb' 0 len * y.extractLsb' 0 len
```
---------
Co-authored-by: Alex Keizer <alex@keizer.dev>
This PR adds SMT-LIB operators to detect overflow `BitVec.(usubOverflow,
ssubOverflow)`, according to the [SMTLIB
standard](https://github.com/SMT-LIB/SMT-LIB-2/blob/2.7/Theories/FixedSizeBitVectors.smt2),
and the theorems proving equivalence of such definition with the
`BitVec` library functions `BittVec.(usubOverflow_eq, ssubOverflow_eq)`.
Co-authored by @bollu.
---------
Co-authored-by: Siddharth <siddu.druid@gmail.com>
Co-authored-by: Alex Keizer <alex@keizer.dev>
This PR implements the addition rewrite from the Bitwuzla rewrite
[BV_EXTRACT_ADD_MUL](e09c50818b/src/rewrite/rewrites_bv.cpp (L1495-L1510)),
which witness that the high bits at `i >= len` do not affect the bits of
the sum upto `len`:
```lean
theorem extractLsb'_add {w len} {x y : BitVec w} (hlen : len ≤ w) :
(x + y).extractLsb' 0 len = x.extractLsb' 0 len + y.extractLsb' 0 len
```
---------
Co-authored-by: Luisa Cicolini <48860705+luisacicolini@users.noreply.github.com>
This PR adds SMT-LIB operators to detect overflow `BitVec.negOverflow`,
according to the [SMTLIB
standard](https://github.com/SMT-LIB/SMT-LIB-2/blob/2.7/Theories/FixedSizeBitVectors.smt2),
and the theorem proving equivalence of such definition with the `BitVec`
library functions (`negOverflow_eq`).
Co-authored by @bollu and @alexkeizer
---------
Co-authored-by: Siddharth <siddu.druid@gmail.com>
This PR adds `BitVec.[toNat|toFin|toInt]_[sshiftRight|sshiftRight']`
plus variants with `of_msb_*`. While at it, we also add
`toInt_zero_length` and `toInt_of_zero_length`. In support of our main
theorem we add `toInt_shiftRight_lt` and `le_toInt_shiftRight`, which
make the main theorem automatically derivable via omega.
We also add four shift lemmas for `Int`: `le_shiftRight_of_nonpos`,
`shiftRight_le_of_nonneg`, `le_shiftRight_of_nonneg`,
`shiftRight_le_of_nonpos`, as well as `emod_eq_add_self_emod`,
`ediv_nonpos_of_nonpos_of_neg `, and`bmod_eq_emod_of_lt `. For `Nat` we
add `shiftRight_le`.
Beyond the lemmas directly needed in the proof, we added a couple more
to ensure the API is complete.
We also fix the casing of `toFin_ushiftRight` and rename `lt_toInt` to
`two_mul_lt_toInt` to avoid `'`-ed lemmas.
This PR adds lemmas for iterated conversions between finite types,
starting with something of type `Nat`/`Int`/`Fin`/`BitVec` and going
through `IntX`.
This PR does some stage0 cleanup after #7100, and enables a warning when
the old `structure S extends P : Type` syntax is used. It also updates
the library to put resulting types in the new correct place (`structure
S : Type extends P`).
The `structure` elaborator also has some additional docstrings, and
`StructFieldKind.fromParent` is renamed to
`StructFieldKind.fromSubobject`.
This PR makes `BitVec.getElem` the simp normal form in case a proof is
available and changes `ext` to return `x[i]` + a hypothesis that proves
that we are in-bounds. This aligns `BitVec` further with the API
conventions of the Lean standard datatypes.
We move our proofs to this new normal form, which results in slightly
smaller proofs. With the exception of `getElem_ofFin`, no new API
surface is added as the `getElem` API has already been completed over
the previous months. We also move `getElem_shiftConcat_*` a bit higher
as they are needed in earlier proofs. To keep the changeset small, we do
not update the API of `BVDecide` but insert `←
BitVec.getLsbD_eq_getElem` at the few locations where it is needed.
Finally, we add a simproc for getElem, mirroring the existing ones for
getLsbD/getMsdD.
---------
Co-authored-by: Alex Keizer <alex@keizer.dev>
This PR implements basic support for handling of enum inductives in
`bv_decide`. It now supports equality on enum inductive variables (or
other uninterpreted atoms) and constants.
This PR adds SMT-LIB operators to detect overflow
`BitVec.(uadd_overflow, sadd_overflow)`, according to the definitions
[here](https://github.com/SMT-LIB/SMT-LIB-2/blob/2.7/Theories/FixedSizeBitVectors.smt2),
and the theorems proving equivalence of such definitions with the
`BitVec` library functions (`uaddOverflow_eq`, `saddOverflow_eq`).
Support theorems for these proofs are `BitVec.toNat_mod_cancel_of_lt,
BitVec.toInt_lt, BitVec.le_toInt, Int.bmod_neg_iff`. The PR also
includes a set of tests.
---------
Co-authored-by: Tobias Grosser <github@grosser.es>
Co-authored-by: Alex Keizer <alex@keizer.dev>
Co-authored-by: Tobias Grosser <tobias@grosser.es>
Co-authored-by: Siddharth Bhat <siddu.druid@gmail.com>
This PR adds theorems `BitVec.(getElem_umod_of_lt, getElem_umod,
getLsbD_umod, getMsbD_umod)`. For the defiition of these theorems we
rely on `divRec`, excluding the case where `d=0#w`, which is treated
separately because there is no infrastructure to reason about this case
within `divRec`. In particular, our implementation follows the mathlib
standard [where division by 0 yields
0](c7c1e091c9/src/Init/Data/BitVec/Basic.lean (L217)),
while in [SMTLIB this yields
`allOnes`](c7c1e091c9/src/Init/Data/BitVec/Basic.lean (L237)).
Co-authored by @bollu.
---------
Co-authored-by: Siddharth <siddu.druid@gmail.com>
This PR adds lemmas for extracting a given bit of a `BitVec` obtained
via `sub`/`neg`/`sshiftRight'`/`abs`.
---------
Co-authored-by: Kim Morrison <scott@tqft.net>
This PR changes the signature of `Array.get` to take a Nat and a proof,
rather than a `Fin`, for consistency with the rest of the (planned)
Array API. Note that because of bootstrapping issues we can't provide
`get_elem_tactic` as an autoparameter for the proof. As users will
mostly use the `xs[i]` notation provided by `GetElem`, this hopefully
isn't a problem.
We may restore `Fin` based versions, either here or downstream, as
needed, but they won't be the "main" functions.
---------
Co-authored-by: David Thrane Christiansen <david@davidchristiansen.dk>
Since `getMsbD_add`, `getMsbD_sub`, `getLsbD_sub`, `msb_sub` , `msb_add`
depend on `getLsbD_add` (which lives in`BitBlast.lean`) and on each
other, I put all of these in `BitBlast.lean`.
This follows the norm for all other Bitvector operations, and makes the
symbols `/` and `%` the simp normal form.
I'd imagine that @hargonix would prefer that this be merged after
https://github.com/leanprover/lean4/pull/5628, so as to prevent churn
for his PR. I'm happy to rebase the PR once the other PR lands.
---------
Co-authored-by: Henrik Böving <hargonix@gmail.com>
…|twoPow|one|replicate]
... and mark `getElem_setWidth` as `@[simp]`.
`getElem_rotateLeft` and `getElem_rotateRight` have a non-trivial rhs
but we follow `getLsbD_[rotateLeft|rotateRight]`for consistency.
---------
Co-authored-by: Kim Morrison <scott@tqft.net>
@bollu, it would be good to have confirmation from you, but presumably
this was not meant to be `@[simp]`? It competes with `divRec_succ`, and
has a terrible RHS.
This PR adds the theorems
```
@[simp]
theorem divRec_zero (qr : DivModState w) :
divRec w w 0 n d qr = qr
@[simp]
theorem divRec_succ' (wn : Nat) (qr : DivModState w) :
divRec w wr (wn + 1) n d qr =
let r' := shiftConcat qr.r (n.getLsbD wn)
let input : DivModState w :=
if r' < d then ⟨qr.q.shiftConcat false, r'⟩ else ⟨qr.q.shiftConcat true, r' - d⟩
divRec w (wr + 1) wn n d input
```
The final statements may need some masasging to interoperate with
`bv_decide`. We prove the recurrence for unsigned division by building a
shift-subtract circuit, and then showing that this circuit obeys the
division algorithm's invariant.
---
A `DivModState` is lawful if the remainder width `wr` plus the dividend
width `wn` equals `w`,
and the bitvectors `r` and `n` have values in the bounds given by
bitwidths `wr`, resp. `wn`.
This is a proof engineering choice: An alternative world could have
`r : BitVec wr` and `n : BitVec wn`, but this required much more
dependent typing coercions.
Instead, we choose to declare all involved bitvectors as length `w`, and
then prove that
the values are within their respective bounds.
---------
Co-authored-by: Tobias Grosser <github@grosser.es>
Co-authored-by: Alex Keizer <alex@keizer.dev>
Co-authored-by: Kim Morrison <scott@tqft.net>
Co-authored-by: Tobias Grosser <tobias@grosser.es>
This renames `BitVec.getLsb` to `getLsbD` (`D` for "default" value, i.e.
false), and introduces `getLsb?` and `getLsb'` (which we can rename to
`getLsb` after a deprecation cycle).
(Similarly for `getMsb`.)
Also adds a `GetElem` class so we can use `x[i]` and `x[i]?` notation.
Later, we will turn
```
theorem getLsbD_eq_getElem?_getD (x : BitVec w) (i : Nat) (h : i < w) :
x.getLsbD i = x[i]?.getD false
```
on as a `@[simp]` lemma.
This PR doesn't attempt to demonstrate the benefits, but I think both
arguments are going to get easier, and this will bring the BitVec API
closer in line to List/Array, etc.
---------
Co-authored-by: Markus Himmel <markus@lean-fro.org>
This change canonicalizes the BitVec variable names to `x y z : BitVec`
instead of alternative namings such as `s t : BitVec` or `a b : BitVec`.
Variable names that carry semantic meaning such as `(msbs : BitVec w)
(lsb : Bool)` remain untouched.
This is purely a naming change to make our bitvector proofs more
consistent and polish the (auto-generated) documentation as a very small
step towards polishing the documentation of the BitVec library in Lean.
---------
Co-authored-by: AnotherAlexHere <153999274+AnotherAlexHere@users.noreply.github.com>