Compare commits

...

24 Commits

Author SHA1 Message Date
Kim Morrison
4b592234ba fix 2025-06-24 20:42:36 +10:00
Kim Morrison
4145232f68 merge master 2025-06-24 20:29:35 +10:00
Kim Morrison
13e146ad02 Merge remote-tracking branch 'origin/master' into grind_in_bitvec 2025-06-24 08:08:58 +02:00
Kim Morrison
b7da84a8ef . 2025-06-24 08:06:15 +02:00
Kim Morrison
a9a37ee156 finished 2025-06-24 08:05:46 +02:00
Kim Morrison
52ad449bbd Revert stdlib_flags 2025-06-24 07:05:54 +02:00
Kim Morrison
a74418eff5 merge master 2025-06-24 06:58:19 +02:00
Kim Morrison
7df51c0d74 need more @[expose] 2025-06-23 22:51:20 +10:00
Kim Morrison
aec05dbb2a tests 2025-06-23 09:21:06 +10:00
Kim Morrison
8cbfc5dc90 Merge remote-tracking branch 'origin/master' into grind_in_bitvec 2025-06-22 21:58:18 +10:00
Kim Morrison
e6209cb555 more grind 2025-06-22 21:58:01 +10:00
Kim Morrison
153d28cdce more 2025-06-21 21:35:13 +10:00
Kim Morrison
57cd7c8cf0 . 2025-06-21 16:09:17 +10:00
Kim Morrison
e5bf2efd59 merge master 2025-06-21 15:57:24 +10:00
Kim Morrison
137d8f650f merge 2025-06-21 15:54:47 +10:00
Kim Morrison
df2951c362 nice 2025-06-20 10:36:41 +10:00
Kim Morrison
18344f32f2 chore: @[expose] defs that appear in grind proof terms 2025-06-19 22:22:03 +10:00
Kim Morrison
582224d074 yay 2025-06-19 22:19:17 +10:00
Kim Morrison
25c6d3ab22 grinding BitVec 2025-06-19 14:00:22 +10:00
Kim Morrison
3dd3e69d4e failing to use grind in BitVec.Lemmas 2025-06-18 21:44:46 +10:00
Kim Morrison
be17de4e5c Merge branch 'push-zutxkzwzzkpo' into grind_in_bitvec 2025-06-18 15:28:23 +10:00
Sebastian Ullrich
a6df61d09a fix: set public aux decl prefix in init_grind_norm 2025-06-18 06:56:16 +02:00
Kim Morrison
3168726fcd Merge remote-tracking branch 'origin/master' into grind_in_bitvec 2025-06-18 08:51:29 +10:00
Kim Morrison
d70ff039cc failing to use grind in BitVec.Lemmas 2025-06-17 14:21:10 +10:00
6 changed files with 845 additions and 1672 deletions

View File

@@ -37,7 +37,7 @@ instance natCastInst : NatCast (BitVec w) := ⟨BitVec.ofNat w⟩
/-- Theorem for normalizing the bitvector literal representation. -/
-- TODO: This needs more usage data to assess which direction the simp should go.
@[simp, bitvec_to_nat] theorem ofNat_eq_ofNat : @OfNat.ofNat (BitVec n) i _ = .ofNat n i := rfl
@[simp, bitvec_to_nat, grind =] theorem ofNat_eq_ofNat : @OfNat.ofNat (BitVec n) i _ = .ofNat n i := rfl
-- Note. Mathlib would like this to go the other direction.
@[simp] theorem natCast_eq_ofNat (w x : Nat) : @Nat.cast (BitVec w) _ x = .ofNat w x := rfl
@@ -115,17 +115,18 @@ instance : GetElem (BitVec w) Nat Bool fun _ i => i < w where
getElem xs i h := xs.getLsb i, h
/-- We prefer `x[i]` as the simp normal form for `getLsb'` -/
@[simp] theorem getLsb_eq_getElem (x : BitVec w) (i : Fin w) :
@[simp, grind =] theorem getLsb_eq_getElem (x : BitVec w) (i : Fin w) :
x.getLsb i = x[i] := rfl
/-- We prefer `x[i]?` as the simp normal form for `getLsb?` -/
@[simp] theorem getLsb?_eq_getElem? (x : BitVec w) (i : Nat) :
@[simp, grind =] theorem getLsb?_eq_getElem? (x : BitVec w) (i : Nat) :
x.getLsb? i = x[i]? := rfl
@[grind =_] -- Activate when we see `x.toNat.testBit i`.
theorem getElem_eq_testBit_toNat (x : BitVec w) (i : Nat) (h : i < w) :
x[i] = x.toNat.testBit i := rfl
@[simp]
@[simp, grind =]
theorem getLsbD_eq_getElem {x : BitVec w} {i : Nat} (h : i < w) :
x.getLsbD i = x[i] := rfl
@@ -356,8 +357,8 @@ section bool
@[expose]
def ofBool (b : Bool) : BitVec 1 := cond b 1 0
@[simp] theorem ofBool_false : ofBool false = 0 := by trivial
@[simp] theorem ofBool_true : ofBool true = 1 := by trivial
@[simp, grind =] theorem ofBool_false : ofBool false = 0 := by trivial
@[simp, grind =] theorem ofBool_true : ofBool true = 1 := by trivial
/-- Fills a bitvector with `w` copies of the bit `b`. -/
def fill (w : Nat) (b : Bool) : BitVec w := bif b then -1 else 0
@@ -415,15 +416,15 @@ that can more consistently simplify `BitVec.cast` away.
-/
@[inline, expose] protected def cast (eq : n = m) (x : BitVec n) : BitVec m := .ofNatLT x.toNat (eq x.isLt)
@[simp] theorem cast_ofNat {n m : Nat} (h : n = m) (x : Nat) :
@[simp, grind =] theorem cast_ofNat {n m : Nat} (h : n = m) (x : Nat) :
(BitVec.ofNat n x).cast h = BitVec.ofNat m x := by
subst h; rfl
@[simp] theorem cast_cast {n m k : Nat} (h₁ : n = m) (h₂ : m = k) (x : BitVec n) :
@[simp, grind =] theorem cast_cast {n m k : Nat} (h₁ : n = m) (h₂ : m = k) (x : BitVec n) :
(x.cast h₁).cast h₂ = x.cast (h₁ h₂) :=
rfl
@[simp] theorem cast_eq {n : Nat} (h : n = n) (x : BitVec n) : x.cast h = x := rfl
@[simp, grind =] theorem cast_eq {n : Nat} (h : n = n) (x : BitVec n) : x.cast h = x := rfl
/--
Extracts the bits `start` to `start + len - 1` from a bitvector of size `n` to yield a
@@ -707,10 +708,12 @@ The new bit is the most significant bit.
def cons {n} (msb : Bool) (lsbs : BitVec n) : BitVec (n+1) :=
((ofBool msb) ++ lsbs).cast (Nat.add_comm ..)
@[grind =]
theorem append_ofBool (msbs : BitVec w) (lsb : Bool) :
msbs ++ ofBool lsb = concat msbs lsb :=
rfl
@[grind =]
theorem ofBool_append (msb : Bool) (lsbs : BitVec w) :
ofBool msb ++ lsbs = (cons msb lsbs).cast (Nat.add_comm ..) :=
rfl
@@ -745,20 +748,20 @@ instance : Hashable (BitVec n) where
section normalization_eqs
/-! We add simp-lemmas that rewrite bitvector operations into the equivalent notation -/
@[simp] theorem append_eq (x : BitVec w) (y : BitVec v) : BitVec.append x y = x ++ y := rfl
@[simp] theorem shiftLeft_eq (x : BitVec w) (n : Nat) : BitVec.shiftLeft x n = x <<< n := rfl
@[simp] theorem ushiftRight_eq (x : BitVec w) (n : Nat) : BitVec.ushiftRight x n = x >>> n := rfl
@[simp] theorem not_eq (x : BitVec w) : BitVec.not x = ~~~x := rfl
@[simp] theorem and_eq (x y : BitVec w) : BitVec.and x y = x &&& y := rfl
@[simp] theorem or_eq (x y : BitVec w) : BitVec.or x y = x ||| y := rfl
@[simp] theorem xor_eq (x y : BitVec w) : BitVec.xor x y = x ^^^ y := rfl
@[simp] theorem neg_eq (x : BitVec w) : BitVec.neg x = -x := rfl
@[simp] theorem add_eq (x y : BitVec w) : BitVec.add x y = x + y := rfl
@[simp] theorem sub_eq (x y : BitVec w) : BitVec.sub x y = x - y := rfl
@[simp] theorem mul_eq (x y : BitVec w) : BitVec.mul x y = x * y := rfl
@[simp] theorem udiv_eq (x y : BitVec w) : BitVec.udiv x y = x / y := rfl
@[simp] theorem umod_eq (x y : BitVec w) : BitVec.umod x y = x % y := rfl
@[simp] theorem zero_eq : BitVec.zero n = 0#n := rfl
@[simp, grind =] theorem append_eq (x : BitVec w) (y : BitVec v) : BitVec.append x y = x ++ y := rfl
@[simp, grind =] theorem shiftLeft_eq (x : BitVec w) (n : Nat) : BitVec.shiftLeft x n = x <<< n := rfl
@[simp, grind =] theorem ushiftRight_eq (x : BitVec w) (n : Nat) : BitVec.ushiftRight x n = x >>> n := rfl
@[simp, grind =] theorem not_eq (x : BitVec w) : BitVec.not x = ~~~x := rfl
@[simp, grind =] theorem and_eq (x y : BitVec w) : BitVec.and x y = x &&& y := rfl
@[simp, grind =] theorem or_eq (x y : BitVec w) : BitVec.or x y = x ||| y := rfl
@[simp, grind =] theorem xor_eq (x y : BitVec w) : BitVec.xor x y = x ^^^ y := rfl
@[simp, grind =] theorem neg_eq (x : BitVec w) : BitVec.neg x = -x := rfl
@[simp, grind =] theorem add_eq (x y : BitVec w) : BitVec.add x y = x + y := rfl
@[simp, grind =] theorem sub_eq (x y : BitVec w) : BitVec.sub x y = x - y := rfl
@[simp, grind =] theorem mul_eq (x y : BitVec w) : BitVec.mul x y = x * y := rfl
@[simp, grind =] theorem udiv_eq (x y : BitVec w) : BitVec.udiv x y = x / y := rfl
@[simp, grind =] theorem umod_eq (x y : BitVec w) : BitVec.umod x y = x % y := rfl
@[simp, grind =] theorem zero_eq : BitVec.zero n = 0#n := rfl
end normalization_eqs
/-- Converts a list of `Bool`s into a big-endian `BitVec`. -/

View File

@@ -31,6 +31,8 @@ instance instOfNat : OfNat (BitVec n) i where ofNat := .ofNat n i
/-- Return the bound in terms of toNat. -/
theorem isLt (x : BitVec w) : x.toNat < 2^w := x.toFin.isLt
grind_pattern isLt => x.toNat, 2^w
end Nat
section arithmetic

View File

@@ -12,10 +12,10 @@ namespace BitVec
theorem testBit_toNat (x : BitVec w) : x.toNat.testBit i = x.getLsbD i := rfl
@[simp] theorem getLsbD_ofFin (x : Fin (2^n)) (i : Nat) :
@[simp, grind =] theorem getLsbD_ofFin (x : Fin (2^n)) (i : Nat) :
getLsbD (BitVec.ofFin x) i = x.val.testBit i := rfl
@[simp] theorem getLsbD_of_ge (x : BitVec w) (i : Nat) (ge : w i) : getLsbD x i = false := by
@[simp, grind] theorem getLsbD_of_ge (x : BitVec w) (i : Nat) (ge : w i) : getLsbD x i = false := by
let x, x_lt := x
simp only [getLsbD_ofFin]
apply Nat.testBit_lt_two_pow
@@ -37,31 +37,35 @@ theorem eq_of_getLsbD_eq {x y : BitVec w}
have p : i w := Nat.le_of_not_gt i_lt
simp [testBit_toNat, getLsbD_of_ge _ _ p]
@[simp, bitvec_to_nat] theorem toNat_ofNat (x w : Nat) : (BitVec.ofNat w x).toNat = x % 2^w := by
@[simp, bitvec_to_nat, grind =]
theorem toNat_ofNat (x w : Nat) : (BitVec.ofNat w x).toNat = x % 2^w := by
simp [BitVec.toNat, BitVec.ofNat, Fin.ofNat]
@[ext] theorem eq_of_getElem_eq {x y : BitVec n} :
@[ext, grind ext] theorem eq_of_getElem_eq {x y : BitVec n} :
( i (hi : i < n), x[i] = y[i]) x = y :=
fun h => BitVec.eq_of_getLsbD_eq (h ·)
@[simp] theorem toNat_append (x : BitVec m) (y : BitVec n) :
@[simp, grind =] theorem toNat_append (x : BitVec m) (y : BitVec n) :
(x ++ y).toNat = x.toNat <<< n ||| y.toNat :=
rfl
@[simp] theorem toNat_ofBool (b : Bool) : (ofBool b).toNat = b.toNat := by
@[simp, grind =] theorem toNat_ofBool (b : Bool) : (ofBool b).toNat = b.toNat := by
cases b <;> rfl
@[simp, bitvec_to_nat] theorem toNat_cast (h : w = v) (x : BitVec w) : (x.cast h).toNat = x.toNat := rfl
@[simp, bitvec_to_nat, grind =]
theorem toNat_cast (h : w = v) (x : BitVec w) : (x.cast h).toNat = x.toNat := rfl
@[simp, bitvec_to_nat] theorem toNat_ofFin (x : Fin (2^n)) : (BitVec.ofFin x).toNat = x.val := rfl
@[simp, bitvec_to_nat, grind =]
theorem toNat_ofFin (x : Fin (2^n)) : (BitVec.ofFin x).toNat = x.val := rfl
@[simp] theorem toNat_ofNatLT (x : Nat) (p : x < 2^w) : (x#'p).toNat = x := rfl
@[simp, grind =] theorem toNat_ofNatLT (x : Nat) (p : x < 2^w) : (x#'p).toNat = x := rfl
@[simp] theorem toNat_cons (b : Bool) (x : BitVec w) :
@[simp, grind =] theorem toNat_cons (b : Bool) (x : BitVec w) :
(cons b x).toNat = (b.toNat <<< w) ||| x.toNat := by
let x, _ := x
simp only [cons, toNat_cast, toNat_append, toNat_ofBool, toNat_ofFin]
@[grind =]
theorem getElem_cons {b : Bool} {n} {x : BitVec n} {i : Nat} (h : i < n + 1) :
(cons b x)[i] = if h : i = n then b else x[i] := by
simp only [getElem_eq_testBit_toNat, toNat_cons, Nat.testBit_or]
@@ -80,12 +84,14 @@ theorem getElem_cons {b : Bool} {n} {x : BitVec n} {i : Nat} (h : i < n + 1) :
private theorem lt_two_pow_of_le {x m n : Nat} (lt : x < 2 ^ m) (le : m n) : x < 2 ^ n :=
Nat.lt_of_lt_of_le lt (Nat.pow_le_pow_right (by trivial : 0 < 2) le)
@[simp, bitvec_to_nat] theorem toNat_setWidth' {m n : Nat} (p : m n) (x : BitVec m) :
@[simp, bitvec_to_nat, grind =]
theorem toNat_setWidth' {m n : Nat} (p : m n) (x : BitVec m) :
(setWidth' p x).toNat = x.toNat := by
simp only [setWidth', toNat_ofNatLT]
@[simp, bitvec_to_nat] theorem toNat_setWidth (i : Nat) (x : BitVec n) :
BitVec.toNat (setWidth i x) = x.toNat % 2^i := by
@[simp, bitvec_to_nat, grind =]
theorem toNat_setWidth (i : Nat) (x : BitVec n) :
(setWidth i x).toNat = x.toNat % 2^i := by
let x, lt_n := x
simp only [setWidth]
if n_le_i : n i then
@@ -94,15 +100,17 @@ private theorem lt_two_pow_of_le {x m n : Nat} (lt : x < 2 ^ m) (le : m ≤ n) :
else
simp [n_le_i, toNat_ofNat]
@[simp] theorem ofNat_toNat (m : Nat) (x : BitVec n) : BitVec.ofNat m x.toNat = setWidth m x := by
@[simp, grind =]
theorem ofNat_toNat (m : Nat) (x : BitVec n) : BitVec.ofNat m x.toNat = setWidth m x := by
apply eq_of_toNat_eq
simp only [toNat_ofNat, toNat_setWidth]
@[grind =]
theorem getElem_setWidth' (x : BitVec w) (i : Nat) (h : w v) (hi : i < v) :
(setWidth' h x)[i] = x.getLsbD i := by
rw [getElem_eq_testBit_toNat, toNat_setWidth', getLsbD]
@[simp]
@[simp, grind =]
theorem getElem_setWidth (m : Nat) (x : BitVec n) (i : Nat) (h : i < m) :
(setWidth m x)[i] = x.getLsbD i := by
rw [setWidth]
@@ -112,6 +120,7 @@ theorem getElem_setWidth (m : Nat) (x : BitVec n) (i : Nat) (h : i < m) :
getLsbD, Bool.and_eq_right_iff_imp, decide_eq_true_eq]
omega
-- Later this is provable by `grind`, so doesn't need an annotation.
@[simp] theorem cons_msb_setWidth (x : BitVec (w+1)) : (cons x.msb (x.setWidth w)) = x := by
ext i
simp only [getElem_cons]
@@ -121,10 +130,12 @@ theorem getElem_setWidth (m : Nat) (x : BitVec n) (i : Nat) (h : i < m) :
· simp_all only [getElem_setWidth, getLsbD_eq_getElem]
· omega
@[simp, bitvec_to_nat] theorem toNat_neg (x : BitVec n) : (- x).toNat = (2^n - x.toNat) % 2^n := by
@[simp, bitvec_to_nat, grind =]
theorem toNat_neg (x : BitVec n) : (- x).toNat = (2^n - x.toNat) % 2^n := by
simp [Neg.neg, BitVec.neg]
@[simp] theorem setWidth_neg_of_le {x : BitVec v} (h : w v) : BitVec.setWidth w (-x) = -BitVec.setWidth w x := by
@[simp, grind =]
theorem setWidth_neg_of_le {x : BitVec v} (h : w v) : BitVec.setWidth w (-x) = -BitVec.setWidth w x := by
apply BitVec.eq_of_toNat_eq
simp only [toNat_setWidth, toNat_neg]
rw [Nat.mod_mod_of_dvd _ (Nat.pow_dvd_pow 2 h)]

File diff suppressed because it is too large Load Diff

View File

@@ -63,7 +63,7 @@ theorem mk_val (i : Fin n) : (⟨i, i.isLt⟩ : Fin n) = i := Fin.eta ..
0 = (a, ha : Fin n) a = 0 := by
simp [eq_comm]
@[simp] theorem val_ofNat (n : Nat) [NeZero n] (a : Nat) :
@[simp, grind =] theorem val_ofNat (n : Nat) [NeZero n] (a : Nat) :
(Fin.ofNat n a).val = a % n := rfl
@[deprecated val_ofNat (since := "2025-05-28")] abbrev val_ofNat' := @val_ofNat
@@ -249,7 +249,7 @@ protected theorem le_antisymm_iff {x y : Fin n} : x = y ↔ x ≤ y ∧ y ≤ x
protected theorem le_antisymm {x y : Fin n} (h1 : x y) (h2 : y x) : x = y :=
Fin.le_antisymm_iff.2 h1, h2
@[simp] theorem val_rev (i : Fin n) : rev i = n - (i + 1) := rfl
@[simp, grind =] theorem val_rev (i : Fin n) : rev i = n - (i + 1) := rfl
@[simp] theorem rev_rev (i : Fin n) : rev (rev i) = i := Fin.ext <| by
rw [val_rev, val_rev, Nat.sub_sub, Nat.sub_sub_self (by exact i.2), Nat.add_sub_cancel]
@@ -445,7 +445,7 @@ theorem succ_succ_ne_one (a : Fin n) : Fin.succ (Fin.succ a) ≠ 1 :=
@[simp] theorem castLT_mk (i n m : Nat) (hn : i < n) (hm : i < m) : castLT i, hn hm = i, hm :=
rfl
@[simp] theorem coe_castLE (h : n m) (i : Fin n) : (castLE h i : Nat) = i := rfl
@[simp, grind =] theorem coe_castLE (h : n m) (i : Fin n) : (castLE h i : Nat) = i := rfl
@[simp] theorem castLE_mk (i n m : Nat) (hn : i < n) (h : n m) :
castLE h i, hn = i, Nat.lt_of_lt_of_le hn h := rfl

View File

@@ -0,0 +1,7 @@
open BitVec
example (x : BitVec (w+1)) : (cons x.msb (x.setWidth w)) = x := by
grind
example {x : BitVec v} (h : w v) : BitVec.setWidth w (-x) = -BitVec.setWidth w x := by
grind