-- Mathlib/.lake/packages/lean4/src/lean/Init/Data/BitVec/Lemmas.lean
theorem getMsbD_setWidth_add {x : BitVec w} (h : k ≤ i) :
    (x.setWidth (w + k)).getMsbD i = x.getMsbD (i - k)

Proof state:
case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
⊢ (decide (i < w + k) && (decide (w + k - 1 - i < w + k) && x.getLsbD (w + k - 1 - i))) =
    (decide (i - k < w) && x.getLsbD (w - 1 - (i - k)))

Tactic:
by_cases h₁ : i < w + k <;> by_cases h₂ : i - k < w <;> by_cases h₃ : w + k - 1 - i < w + k
  <;> simp [h₁, h₂, h₃]

Result:
case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : i - k < w
h₃ : w + k - 1 - i < w + k
⊢ x.getLsbD (w + k - 1 - i) = x.getLsbD (w - 1 - (i - k))

case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : ¬i - k < w
h₃ : w + k - 1 - i < w + k
⊢ x.getLsbD (w + k - 1 - i) = false

case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

Proof state:
case pos.e_i
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : i - k < w
h₃ : w + k - 1 - i < w + k
⊢ w + k - 1 - i = w - 1 - (i - k)

Tactic:
omega

Result:
no goals

Proof state:
case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

Tactic:
apply getLsbD_ge

Result:
case neg.ge
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ w ≤ w - 1 - (i - k)

Proof state:
case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : ¬i - k < w
h₃ : w + k - 1 - i < w + k
⊢ x.getLsbD (w + k - 1 - i) = false

case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

Tactic:
all_goals (first | apply getLsbD_ge | apply Eq.symm; apply getLsbD_ge)
  <;> omega

Result:
no goals

Proof state:
case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : i - k < w
h₃ : w + k - 1 - i < w + k
⊢ x.getLsbD (w + k - 1 - i) = x.getLsbD (w - 1 - (i - k))

Tactic:
congr 1

Result:
case pos.e_i
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : i < w + k
h₂ : i - k < w
h₃ : w + k - 1 - i < w + k
⊢ w + k - 1 - i = w - 1 - (i - k)

Proof state:
case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

Tactic:
first | apply getLsbD_ge | apply Eq.symm; apply getLsbD_ge

Result:
case neg.ge
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ w ≤ w - 1 - (i - k)

Proof state:
case pos
k i : Nat
h : k ≤ i
x : BitVec 0
⊢ (setWidth (0 + k) x).getMsbD i = x.getMsbD (i - k)

Tactic:
simp [of_length_zero]

Result:
no goals

Proof state:
w k i : Nat
x : BitVec w
h : k ≤ i
⊢ (setWidth (w + k) x).getMsbD i = x.getMsbD (i - k)

Tactic:
by_cases h : w = 0

Result:
case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : w = 0
⊢ (setWidth (w + k) x).getMsbD i = x.getMsbD (i - k)

case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
⊢ (setWidth (w + k) x).getMsbD i = x.getMsbD (i - k)

Proof state:
case pos
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : w = 0
⊢ (setWidth (w + k) x).getMsbD i = x.getMsbD (i - k)

Tactic:
subst h

Result:
case pos
k i : Nat
h : k ≤ i
x : BitVec 0
⊢ (setWidth (0 + k) x).getMsbD i = x.getMsbD (i - k)

Proof state:
case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
⊢ (setWidth (w + k) x).getMsbD i = x.getMsbD (i - k)

Tactic:
simp only [getMsbD, getLsbD_setWidth]

Result:
case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
⊢ (decide (i < w + k) && (decide (w + k - 1 - i < w + k) && x.getLsbD (w + k - 1 - i))) =
    (decide (i - k < w) && x.getLsbD (w - 1 - (i - k)))

Proof state:
case neg
w k i : Nat
x : BitVec w
h✝ : k ≤ i
h : ¬w = 0
h₁ : ¬i < w + k
h₂ : i - k < w
h₃ : ¬w + k - 1 - i < w + k
⊢ x.getLsbD (w - 1 - (i - k)) = false

Tactic:
(first | apply getLsbD_ge | apply Eq.symm; apply getLsbD_ge)
<;> omega

Result:
no goals