From 459c6e2a46eb02a380eb7e7ae14b45692aac188a Mon Sep 17 00:00:00 2001 From: Tobias Grosser Date: Thu, 21 Nov 2024 02:01:11 -0500 Subject: [PATCH] feat: BitVec.getElem_[sub|neg|sshiftRight'|abs] (#6126) This PR adds lemmas for extracting a given bit of a `BitVec` obtained via `sub`/`neg`/`sshiftRight'`/`abs`. --------- Co-authored-by: Kim Morrison --- src/Init/Data/BitVec/Bitblast.lean | 8 ++++++++ src/Init/Data/BitVec/Lemmas.lean | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Init/Data/BitVec/Bitblast.lean b/src/Init/Data/BitVec/Bitblast.lean index 1fa7a3166d1a..3ef86361b628 100644 --- a/src/Init/Data/BitVec/Bitblast.lean +++ b/src/Init/Data/BitVec/Bitblast.lean @@ -346,6 +346,10 @@ theorem getMsbD_sub {i : Nat} {i_lt : i < w} {x y : BitVec w} : · rfl · omega +theorem getElem_sub {i : Nat} {x y : BitVec w} (h : i < w) : + (x - y)[i] = (x[i] ^^ ((~~~y + 1#w)[i] ^^ carry i x (~~~y + 1#w) false)) := by + simp [← getLsbD_eq_getElem, getLsbD_sub, h] + theorem msb_sub {x y: BitVec w} : (x - y).msb = (x.msb ^^ ((~~~y + 1#w).msb ^^ carry (w - 1 - 0) x (~~~y + 1#w) false)) := by @@ -410,6 +414,10 @@ theorem getLsbD_neg {i : Nat} {x : BitVec w} : · have h_ge : w ≤ i := by omega simp [getLsbD_ge _ _ h_ge, h_ge, hi] +theorem getElem_neg {i : Nat} {x : BitVec w} (h : i < w) : + (-x)[i] = (x[i] ^^ decide (∃ j < i, x.getLsbD j = true)) := by + simp [← getLsbD_eq_getElem, getLsbD_neg, h] + theorem getMsbD_neg {i : Nat} {x : BitVec w} : getMsbD (-x) i = (getMsbD x i ^^ decide (∃ j < w, i < j ∧ getMsbD x j = true)) := by diff --git a/src/Init/Data/BitVec/Lemmas.lean b/src/Init/Data/BitVec/Lemmas.lean index 9cf09579bc98..1ecbdde3419c 100644 --- a/src/Init/Data/BitVec/Lemmas.lean +++ b/src/Init/Data/BitVec/Lemmas.lean @@ -1480,6 +1480,12 @@ theorem getLsbD_sshiftRight' {x y: BitVec w} {i : Nat} : (!decide (w ≤ i) && if y.toNat + i < w then x.getLsbD (y.toNat + i) else x.msb) := by simp only [BitVec.sshiftRight', BitVec.getLsbD_sshiftRight] +@[simp] +theorem getElem_sshiftRight' {x y : BitVec w} {i : Nat} (h : i < w) : + (x.sshiftRight' y)[i] = + (!decide (w ≤ i) && if y.toNat + i < w then x.getLsbD (y.toNat + i) else x.msb) := by + simp only [← getLsbD_eq_getElem, BitVec.sshiftRight', BitVec.getLsbD_sshiftRight] + @[simp] theorem getMsbD_sshiftRight' {x y: BitVec w} {i : Nat} : (x.sshiftRight y.toNat).getMsbD i = (decide (i < w) && if i < y.toNat then x.msb else x.getMsbD (i - y.toNat)) := by @@ -3224,7 +3230,11 @@ theorem toNat_abs {x : BitVec w} : x.abs.toNat = if x.msb then 2^w - x.toNat els · simp [h] theorem getLsbD_abs {i : Nat} {x : BitVec w} : - getLsbD x.abs i = if x.msb then getLsbD (-x) i else getLsbD x i := by + getLsbD x.abs i = if x.msb then getLsbD (-x) i else getLsbD x i := by + by_cases h : x.msb <;> simp [BitVec.abs, h] + +theorem getElem_abs {i : Nat} {x : BitVec w} (h : i < w) : + x.abs[i] = if x.msb then (-x)[i] else x[i] := by by_cases h : x.msb <;> simp [BitVec.abs, h] theorem getMsbD_abs {i : Nat} {x : BitVec w} :