Skip to content

Commit 34296f6

Browse files
luisacicolinibollu
authored andcommitted
feat: associativity lemmas for BitVec.(umul, smul, uadd, sadd)Overflow (leanprover#8740)
This PR introduces associativity rules and preservation of `(umul, smul, uadd, sadd)Overflow`flags. --------- Co-authored-by: Siddharth <[email protected]>
1 parent 494340d commit 34296f6

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

src/Init/Data/BitVec/Lemmas.lean

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3354,6 +3354,17 @@ theorem toNat_add_of_not_uaddOverflow {x y : BitVec w} (h : ¬ uaddOverflow x y)
33543354
· simp only [uaddOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
33553355
rw [toNat_add, Nat.mod_eq_of_lt h]
33563356

3357+
/--
3358+
Unsigned addition overflow reassociation.
3359+
If `(x + y)` and `(y + z)` do not overflow, then `(x + y) + z` overflows iff `x + (y + z)` overflows.
3360+
-/
3361+
theorem uaddOverflow_assoc {x y z : BitVec w} (h : ¬ x.uaddOverflow y) (h' : ¬ y.uaddOverflow z) :
3362+
(x + y).uaddOverflow z = x.uaddOverflow (y + z) := by
3363+
simp only [uaddOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h h'
3364+
simp only [uaddOverflow, toNat_add, ge_iff_le, decide_eq_decide]
3365+
repeat rw [Nat.mod_eq_of_lt (by omega)]
3366+
omega
3367+
33573368
protected theorem add_assoc (x y z : BitVec n) : x + y + z = x + (y + z) := by
33583369
apply eq_of_toNat_eq ; simp [Nat.add_assoc]
33593370
instance : Std.Associative (α := BitVec n) (· + ·) := ⟨BitVec.add_assoc⟩
@@ -3392,6 +3403,20 @@ theorem toInt_add_of_not_saddOverflow {x y : BitVec w} (h : ¬ saddOverflow x y)
33923403
_root_.not_or, Int.not_le, Int.not_lt] at h
33933404
rw [toInt_add, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
33943405

3406+
/--
3407+
Signed addition overflow reassociation.
3408+
If `(x + y)` and `(y + z)` do not overflow, then `(x + y) + z` overflows iff `x + (y + z)` overflows.
3409+
-/
3410+
theorem saddOverflow_assoc {x y z : BitVec w} (h : ¬ x.saddOverflow y) (h' : ¬ y.saddOverflow z) :
3411+
(x + y).saddOverflow z = x.saddOverflow (y + z) := by
3412+
rcases w with _|w
3413+
· simp [of_length_zero]
3414+
· simp only [saddOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
3415+
_root_.not_or, Int.not_le, Int.not_lt] at h h'
3416+
simp only [bool_to_prop, saddOverflow, toInt_add, ge_iff_le, Nat.add_one_sub_one]
3417+
repeat rw [Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
3418+
omega
3419+
33953420
@[simp]
33963421
theorem shiftLeft_add_distrib {x y : BitVec w} {n : Nat} :
33973422
(x + y) <<< n = x <<< n + y <<< n := by
@@ -3820,6 +3845,18 @@ theorem toNat_mul_of_not_umulOverflow {x y : BitVec w} (h : ¬ umulOverflow x y)
38203845
· simp only [umulOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
38213846
rw [toNat_mul, Nat.mod_eq_of_lt h]
38223847

3848+
/--
3849+
Unsigned multiplication overflow reassociation.
3850+
If `(x * y)` and `(y * z)` do not overflow, then `(x * y) * z` overflows iff `x * (y * z)` overflows.
3851+
-/
3852+
theorem umulOverflow_assoc {x y z : BitVec w} (h : ¬ x.umulOverflow y) (h' : ¬ y.umulOverflow z) :
3853+
3854+
(x * y).umulOverflow z = x.umulOverflow (y * z) := by
3855+
simp only [umulOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h h'
3856+
simp only [umulOverflow, toNat_mul, ge_iff_le, decide_eq_decide]
3857+
repeat rw [Nat.mod_eq_of_lt (by omega)]
3858+
rw [Nat.mul_assoc]
3859+
38233860
@[simp]
38243861
theorem toInt_mul_of_not_smulOverflow {x y : BitVec w} (h : ¬ smulOverflow x y) :
38253862
(x * y).toInt = x.toInt * y.toInt := by
@@ -3829,6 +3866,20 @@ theorem toInt_mul_of_not_smulOverflow {x y : BitVec w} (h : ¬ smulOverflow x y)
38293866
_root_.not_or, Int.not_le, Int.not_lt] at h
38303867
rw [toInt_mul, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
38313868

3869+
/--
3870+
Signed multiplication overflow reassociation.
3871+
If `(x * y)` and `(y * z)` do not overflow, then `(x * y) * z` overflows iff `x * (y * z)` overflows.
3872+
-/
3873+
theorem smulOverflow_assoc {x y z : BitVec w} (h : ¬ x.smulOverflow y) (h' : ¬ y.smulOverflow z) :
3874+
(x * y).smulOverflow z = x.smulOverflow (y * z) := by
3875+
rcases w with _|w
3876+
· simp [of_length_zero]
3877+
· simp only [smulOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
3878+
_root_.not_or, Int.not_le, Int.not_lt] at h h'
3879+
simp only [smulOverflow, toInt_mul, Nat.add_one_sub_one, ge_iff_le, bool_to_prop]
3880+
repeat rw [Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
3881+
rw [Int.mul_assoc]
3882+
38323883
theorem ofInt_mul {n} (x y : Int) : BitVec.ofInt n (x * y) =
38333884
BitVec.ofInt n x * BitVec.ofInt n y := by
38343885
apply eq_of_toInt_eq

0 commit comments

Comments
 (0)