Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Bitvec reverse definition, getLsbD_reverse, getMsbD_reverse, reverse_append, reverse_replicate and Nat.mod_sub_eq_sub_mod #6476

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7acc914
prelim def
luisacicolini Dec 12, 2024
46a61c9
added relevant theorems
luisacicolini Dec 12, 2024
280ac8d
simpler def?
luisacicolini Dec 12, 2024
de0a2d6
reverse definition
luisacicolini Dec 28, 2024
e838c6a
Merge branch 'leanprover:master' into bitvec-reverse
luisacicolini Dec 28, 2024
01482af
chore: update reverse def
luisacicolini Dec 28, 2024
28fcb69
chore: better reverse definition
luisacicolini Dec 28, 2024
ee2a398
chore: close proof
luisacicolini Dec 30, 2024
77feac5
Merge branch 'leanprover:master' into bitvec-reverse
luisacicolini Dec 30, 2024
edf2a8c
chore: fix reverse
luisacicolini Dec 31, 2024
972f8cd
Merge branch 'bitvec-reverse' of github.com:opencompl/lean4 into bitv…
luisacicolini Dec 31, 2024
034bf23
chore: add docstring for reverse
luisacicolini Dec 31, 2024
cfdf9be
chore: add docstring for reverse
luisacicolini Dec 31, 2024
f51ba58
Update src/Init/Data/BitVec/Basic.lean
luisacicolini Jan 2, 2025
b47c36a
Update src/Init/Data/BitVec/Basic.lean
luisacicolini Jan 2, 2025
c20d086
feat: add msb_replicate
luisacicolini Jan 2, 2025
d62f75b
Merge branch 'leanprover:master' into bitvec-reverse
luisacicolini Jan 2, 2025
a8ff8e2
chore: fix build
luisacicolini Jan 2, 2025
42585f1
chore: remove useless hypotheses from proof
luisacicolini Jan 6, 2025
4ba0785
better proof strategy
kim-em Jan 8, 2025
052880f
chore: proof of reverse_cast
luisacicolini Jan 8, 2025
6fa32db
chore: temporary heavy proof
luisacicolini Jan 8, 2025
54a9697
chore: clean proof
luisacicolini Jan 8, 2025
38a1294
chore: remove nonterm simp
luisacicolini Jan 8, 2025
8efdadf
chore: fix simp only
luisacicolini Jan 8, 2025
37c1002
chore: move deprecateed theorems to fix build
luisacicolini Jan 8, 2025
b9049df
feat: replicate_append_self proof
luisacicolini Jan 10, 2025
38fb6eb
chore: an ugly and aggressive proof to start with, before induction
luisacicolini Jan 10, 2025
e696663
feat: cons append
luisacicolini Jan 10, 2025
63e1fb4
chore: fix cons_append for consistency with list behavior
luisacicolini Jan 11, 2025
7b39cc2
chore: induction proof done!
luisacicolini Jan 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Init/Data/BitVec/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -669,4 +669,11 @@ def ofBoolListLE : (bs : List Bool) → BitVec bs.length
| [] => 0#0
| b :: bs => concat (ofBoolListLE bs) b

/- ### reverse -/

/-- Reverse the bits in a bitvector. -/
def reverse : {w : Nat} → BitVec w → BitVec w
| 0, x => x
| w + 1, x => concat (reverse (x.truncate w)) (x.msb)

end BitVec
149 changes: 146 additions & 3 deletions src/Init/Data/BitVec/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2030,6 +2030,20 @@ theorem eq_msb_cons_setWidth (x : BitVec (w+1)) : x = (cons x.msb (x.setWidth w)
ext i
simp [cons]

theorem cons_append (x y : BitVec w) (a : Bool) :
cons a (x ++ y) = ((cons a x) ++ y).cast (by omega) := by
ext i
simp [cons, getLsbD_cast, getLsbD_append]
by_cases hi₀ : i < w
· simp only [hi₀, ↓reduceIte, show (i - (w + w) = 0) by omega, decide_true, Bool.true_and,
ite_eq_left_iff, Nat.not_lt]
omega
· simp only [hi₀, ↓reduceIte]
by_cases hi₁ : i < w + w
· simp [hi₁, show i - w < w by omega]
· simp [hi₁, show ¬ i - w < w by omega, Nat.sub_add_eq]

luisacicolini marked this conversation as resolved.
Show resolved Hide resolved

/-! ### concat -/

@[simp] theorem toNat_concat (x : BitVec w) (b : Bool) :
Expand Down Expand Up @@ -3184,11 +3198,11 @@ theorem and_one_eq_setWidth_ofBool_getLsbD {x : BitVec w} :
ext (_ | i) h <;> simp [Bool.and_comm]

@[simp]
theorem replicate_zero_eq {x : BitVec w} : x.replicate 0 = 0#0 := by
theorem replicate_zero {x : BitVec w} : x.replicate 0 = 0#0 := by
simp [replicate]
kim-em marked this conversation as resolved.
Show resolved Hide resolved

@[simp]
theorem replicate_succ_eq {x : BitVec w} :
theorem replicate_succ {x : BitVec w} :
x.replicate (n + 1) =
(x ++ replicate n x).cast (by rw [Nat.mul_succ]; omega) := by
simp [replicate]
Expand All @@ -3200,7 +3214,7 @@ theorem getLsbD_replicate {n w : Nat} (x : BitVec w) :
induction n generalizing x
case zero => simp
case succ n ih =>
simp only [replicate_succ_eq, getLsbD_cast, getLsbD_append]
simp only [replicate_succ, getLsbD_cast, getLsbD_append]
by_cases hi : i < w * (n + 1)
· simp only [hi, decide_true, Bool.true_and]
by_cases hi' : i < w * n
Expand All @@ -3217,6 +3231,78 @@ theorem getElem_replicate {n w : Nat} (x : BitVec w) (h : i < w * n) :
simp only [← getLsbD_eq_getElem, getLsbD_replicate]
by_cases h' : w = 0 <;> simp [h'] <;> omega

theorem append_assoc {x₁ : BitVec w₁} {x₂ : BitVec w₂} {x₃ : BitVec w₃} :
(x₁ ++ x₂)++ x₃ = (x₁ ++ (x₂ ++ x₃)).cast (by omega) := by
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(x₁ ++ x₂)++ x₃ = (x₁ ++ (x₂ ++ x₃)).cast (by omega) := by
(x₁ ++ x₂) ++ x₃ = (x₁ ++ (x₂ ++ x₃)).cast (by omega) := by

induction w₁ generalizing x₂ x₃
case zero => simp
case succ n ih =>
rw [← cons_msb_setWidth x₁]

rw [cons_]
sorry
ext i
simp only [getLsbD_append, getLsbD_cast]
by_cases hi₁ : i < w₁ <;> by_cases hi₂ : i < w₂ <;> by_cases hi₃ : i < w₃
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']
· omega
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']; intro; omega
· omega
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']
· omega
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']; intro; omega
· simp [hi']
by_cases hi'' : i - w₃ < w₂
· simp [hi'']; omega
· simp [hi'', Nat.sub_add_eq, show i - w₃ - w₂ = i - w₂ - w₃ by omega]
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']
· simp [hi']; omega
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']; intro; omega
· simp [hi']
by_cases hi'' : i - w₃ < w₂
· simp [hi'']; omega
· simp [hi'', Nat.sub_add_eq, show i - w₃ - w₂ = i - w₂ - w₃ by omega]
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']
· simp [hi']; omega
· simp [hi₁, hi₂, hi₃]
by_cases hi' : i < w₂ + w₃
· simp [hi']; intro; omega
· simp [hi']
by_cases hi'' : i - w₃ < w₂
· simp [hi'']; omega
· simp [hi'', Nat.sub_add_eq, show i - w₃ - w₂ = i - w₂ - w₃ by omega]


theorem replicate_append_self {x : BitVec w} :
x ++ x.replicate n = (x.replicate n ++ x).cast (by omega) := by
induction n with
| zero => simp
| succ n ih =>
rw [replicate_succ]
conv => lhs; rw [ih]
simp [cast_cast, cast_eq]
rw [← cast_append_left]
· rw [append_assoc]; congr
· rw [Nat.add_comm, Nat.mul_add, Nat.mul_one]; omega

theorem replicate_succ' {x : BitVec w} :
x.replicate (n + 1) =
(replicate n x ++ x).cast (by rw [Nat.mul_succ]) := by
simp [replicate_append_self]

/-! ### intMin -/

/-- The bitvector of width `w` that has the smallest value when interpreted as an integer. -/
Expand Down Expand Up @@ -3502,6 +3588,57 @@ theorem toInt_abs_eq_natAbs_of_ne_intMin {x : BitVec w} (hx : x ≠ intMin w) :
x.abs.toInt = x.toInt.natAbs := by
simp [toInt_abs_eq_natAbs, hx]

/-! ### Reverse -/

theorem getLsbD_reverse {i : Nat} {x : BitVec w} :
(x.reverse).getLsbD i = x.getMsbD i := by
induction w generalizing i
case zero => simp
case succ n ih =>
simp only [reverse, truncate_eq_setWidth, getLsbD_concat]
rcases i with rfl | i
· rfl
· simp only [Nat.add_one_ne_zero, ↓reduceIte, Nat.add_one_sub_one, ih]
rw [getMsbD_setWidth]
simp only [show n - (n + 1) = 0 by omega, Nat.zero_le, decide_true, Bool.true_and]
congr; omega

theorem getMsbD_reverse {i : Nat} {x : BitVec w} :
(x.reverse).getMsbD i = x.getLsbD i := by
simp only [getMsbD_eq_getLsbD, getLsbD_reverse]
by_cases hi : i < w
· simp only [hi, decide_true, show w - 1 - i < w by omega, Bool.true_and]
congr; omega
· simp [hi, show i ≥ w by omega]

luisacicolini marked this conversation as resolved.
Show resolved Hide resolved
theorem msb_reverse {x : BitVec w} :
(x.reverse).msb = x.getLsbD 0 :=
by rw [BitVec.msb, getMsbD_reverse]

theorem reverse_append {x : BitVec w} {y : BitVec v} :
(x ++ y).reverse = (y.reverse ++ x.reverse).cast (by omega) := by
ext i h
simp only [getLsbD_append, getLsbD_reverse]
by_cases hi : i < v
· by_cases hw : w ≤ i
· simp [getMsbD_append, getLsbD_cast, getLsbD_append, getLsbD_reverse, hw]
· simp [getMsbD_append, getLsbD_cast, getLsbD_append, getLsbD_reverse, hw, show i < w by omega]
· by_cases hw : w ≤ i
· simp [getMsbD_append, getLsbD_cast, getLsbD_append, hw, show ¬ i < w by omega, getLsbD_reverse]
· simp [getMsbD_append, getLsbD_cast, getLsbD_append, hw, show i < w by omega, getLsbD_reverse]

@[simp]
theorem reverse_cast {w v : Nat} (h : w = v) (x : BitVec w) :
(x.cast h).reverse = x.reverse.cast h := by
subst h; simp

theorem reverse_replicate {n : Nat} {x : BitVec w} :
(x.replicate n).reverse = (x.reverse).replicate n := by
induction n with
| zero => rfl
| succ n ih =>
conv => lhs; simp only [replicate_succ']
simp [reverse_append, ih]

/-! ### Decidable quantifiers -/

Expand Down Expand Up @@ -3717,4 +3854,10 @@ abbrev shiftLeft_zero_eq := @shiftLeft_zero
@[deprecated ushiftRight_zero (since := "2024-10-27")]
abbrev ushiftRight_zero_eq := @ushiftRight_zero

@[deprecated replicate_zero (since := "2025-01-08")]
abbrev replicate_zero_eq := @replicate_zero

@[deprecated replicate_succ (since := "2025-01-08")]
abbrev replicate_succ_eq := @replicate_succ

end BitVec
Loading