diff --git a/src/Init/Data/BitVec/Basic.lean b/src/Init/Data/BitVec/Basic.lean index 9566fe2ec8bc..0e335ad371ae 100644 --- a/src/Init/Data/BitVec/Basic.lean +++ b/src/Init/Data/BitVec/Basic.lean @@ -583,11 +583,9 @@ instance : HAppend (BitVec w) (BitVec v) (BitVec (w + v)) := ⟨.append⟩ -- TODO: write this using multiplication /-- `replicate i x` concatenates `i` copies of `x` into a new vector of length `w*i`. -/ def replicate : (i : Nat) → BitVec w → BitVec (w*i) - | 0, _ => 0 + | 0, _ => 0#0 | n+1, x => - have hEq : w + w*n = w*(n + 1) := by - rw [Nat.mul_add, Nat.add_comm, Nat.mul_one] - hEq ▸ (x ++ replicate n x) + (x ++ replicate n x).cast (by rw [Nat.mul_succ]; omega) /-! ### Cons and Concat diff --git a/src/Init/Data/BitVec/Lemmas.lean b/src/Init/Data/BitVec/Lemmas.lean index b7c8c0d35bcb..6976d00eba0b 100644 --- a/src/Init/Data/BitVec/Lemmas.lean +++ b/src/Init/Data/BitVec/Lemmas.lean @@ -1567,4 +1567,46 @@ theorem and_one_eq_zeroExtend_ofBool_getLsb {x : BitVec w} : Bool.true_and] by_cases h : (0 = (i : Nat)) <;> simp [h] <;> omega +@[simp] +theorem replicate_zero_eq {x : BitVec w} : x.replicate 0 = 0#0 := by + simp [replicate] + +@[simp] +theorem replicate_succ_eq {x : BitVec w} : + x.replicate (n + 1) = + (x ++ replicate n x).cast (by rw [Nat.mul_succ]; omega) := by + simp [replicate] + +/-- +If a number `w * n ≤ i < w * (n + 1)`, then `i - w * n` equals `i % w`. +This is true by subtracting `w * n` from the inequality, giving +`0 ≤ i - w * n < w`, which uniquely identifies `i % w`. +-/ +private theorem Nat.sub_mul_eq_mod_of_lt_of_le (hlo : w * n ≤ i) (hhi : i < w * (n + 1)) : + i - w * n = i % w := by + rw [Nat.mod_def] + congr + symm + apply Nat.div_eq_of_lt_le + (by rw [Nat.mul_comm]; omega) + (by rw [Nat.mul_comm]; omega) + +@[simp] +theorem getLsb_replicate {n w : Nat} (x : BitVec w) : + (x.replicate n).getLsb i = + (decide (i < w * n) && x.getLsb (i % w)) := by + induction n generalizing x + case zero => simp + case succ n ih => + simp only [replicate_succ_eq, getLsb_cast, getLsb_append] + by_cases hi : i < w * (n + 1) + · simp only [hi, decide_True, Bool.true_and] + by_cases hi' : i < w * n + · simp [hi', ih] + · simp only [hi', decide_False, cond_false] + rw [Nat.sub_mul_eq_mod_of_lt_of_le] <;> omega + · rw [Nat.mul_succ] at hi ⊢ + simp only [show ¬i < w * n by omega, decide_False, cond_false, hi, Bool.false_and] + apply BitVec.getLsb_ge (x := x) (i := i - w * n) (ge := by omega) + end BitVec diff --git a/src/Init/Data/Nat/Div.lean b/src/Init/Data/Nat/Div.lean index ae68082ce782..ed27dd428d31 100644 --- a/src/Init/Data/Nat/Div.lean +++ b/src/Init/Data/Nat/Div.lean @@ -203,6 +203,10 @@ theorem mod_add_div (m k : Nat) : m % k + k * (m / k) = m := by | base x y h => simp [h] | ind x y h IH => simp [h]; rw [Nat.mul_succ, ← Nat.add_assoc, IH, Nat.sub_add_cancel h.2] +theorem mod_def (m k : Nat) : m % k = m - k * (m / k) := by + rw [Nat.sub_eq_of_eq_add] + apply (Nat.mod_add_div _ _).symm + @[simp] protected theorem div_one (n : Nat) : n / 1 = n := by have := mod_add_div n 1 rwa [mod_one, Nat.zero_add, Nat.one_mul] at this