Skip to content
Merged
Changes from all commits
Commits
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
51 changes: 51 additions & 0 deletions src/Init/Data/BitVec/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -3354,6 +3354,17 @@ theorem toNat_add_of_not_uaddOverflow {x y : BitVec w} (h : ¬ uaddOverflow x y)
· simp only [uaddOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
rw [toNat_add, Nat.mod_eq_of_lt h]

/--
Unsigned addition overflow reassociation.
If `(x + y)` and `(y + z)` do not overflow, then `(x + y) + z` overflows iff `x + (y + z)` overflows.
-/
theorem uaddOverflow_assoc {x y z : BitVec w} (h : ¬ x.uaddOverflow y) (h' : ¬ y.uaddOverflow z) :
(x + y).uaddOverflow z = x.uaddOverflow (y + z) := by
simp only [uaddOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h h'
simp only [uaddOverflow, toNat_add, ge_iff_le, decide_eq_decide]
repeat rw [Nat.mod_eq_of_lt (by omega)]
omega

protected theorem add_assoc (x y z : BitVec n) : x + y + z = x + (y + z) := by
apply eq_of_toNat_eq ; simp [Nat.add_assoc]
instance : Std.Associative (α := BitVec n) (· + ·) := ⟨BitVec.add_assoc⟩
Expand Down Expand Up @@ -3392,6 +3403,20 @@ theorem toInt_add_of_not_saddOverflow {x y : BitVec w} (h : ¬ saddOverflow x y)
_root_.not_or, Int.not_le, Int.not_lt] at h
rw [toInt_add, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]

/--
Signed addition overflow reassociation.
If `(x + y)` and `(y + z)` do not overflow, then `(x + y) + z` overflows iff `x + (y + z)` overflows.
-/
theorem saddOverflow_assoc {x y z : BitVec w} (h : ¬ x.saddOverflow y) (h' : ¬ y.saddOverflow z) :
(x + y).saddOverflow z = x.saddOverflow (y + z) := by
rcases w with _|w
· simp [of_length_zero]
· simp only [saddOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
_root_.not_or, Int.not_le, Int.not_lt] at h h'
simp only [bool_to_prop, saddOverflow, toInt_add, ge_iff_le, Nat.add_one_sub_one]
repeat rw [Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
omega

@[simp]
theorem shiftLeft_add_distrib {x y : BitVec w} {n : Nat} :
(x + y) <<< n = x <<< n + y <<< n := by
Expand Down Expand Up @@ -3820,6 +3845,18 @@ theorem toNat_mul_of_not_umulOverflow {x y : BitVec w} (h : ¬ umulOverflow x y)
· simp only [umulOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
rw [toNat_mul, Nat.mod_eq_of_lt h]

/--
Unsigned multiplication overflow reassociation.
If `(x * y)` and `(y * z)` do not overflow, then `(x * y) * z` overflows iff `x * (y * z)` overflows.
-/
theorem umulOverflow_assoc {x y z : BitVec w} (h : ¬ x.umulOverflow y) (h' : ¬ y.umulOverflow z) :

(x * y).umulOverflow z = x.umulOverflow (y * z) := by
simp only [umulOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h h'
simp only [umulOverflow, toNat_mul, ge_iff_le, decide_eq_decide]
repeat rw [Nat.mod_eq_of_lt (by omega)]
rw [Nat.mul_assoc]

@[simp]
theorem toInt_mul_of_not_smulOverflow {x y : BitVec w} (h : ¬ smulOverflow x y) :
(x * y).toInt = x.toInt * y.toInt := by
Expand All @@ -3829,6 +3866,20 @@ theorem toInt_mul_of_not_smulOverflow {x y : BitVec w} (h : ¬ smulOverflow x y)
_root_.not_or, Int.not_le, Int.not_lt] at h
rw [toInt_mul, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]

/--
Signed multiplication overflow reassociation.
If `(x * y)` and `(y * z)` do not overflow, then `(x * y) * z` overflows iff `x * (y * z)` overflows.
-/
theorem smulOverflow_assoc {x y z : BitVec w} (h : ¬ x.smulOverflow y) (h' : ¬ y.smulOverflow z) :
(x * y).smulOverflow z = x.smulOverflow (y * z) := by
rcases w with _|w
· simp [of_length_zero]
· simp only [smulOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
_root_.not_or, Int.not_le, Int.not_lt] at h h'
simp only [smulOverflow, toInt_mul, Nat.add_one_sub_one, ge_iff_le, bool_to_prop]
repeat rw [Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
rw [Int.mul_assoc]

theorem ofInt_mul {n} (x y : Int) : BitVec.ofInt n (x * y) =
BitVec.ofInt n x * BitVec.ofInt n y := by
apply eq_of_toInt_eq
Expand Down
Loading