feat: add BitVec.msb_(smod, srem) (#8974)
This PR adds `BitVec.msb_(smod, srem)`. co-authored with @tobiasgrosser and @bollu --------- Co-authored-by: Tobias Grosser <github@grosser.es> Co-authored-by: Siddharth <siddu.druid@gmail.com>
This commit is contained in:
parent
0ddd9341d6
commit
25b1b46572
1 changed files with 62 additions and 0 deletions
|
|
@ -1930,6 +1930,44 @@ theorem toInt_sub_neg_umod {x y : BitVec w} (hxmsb : x.msb = true) (hymsb : y.ms
|
|||
Int.dvd_neg] at hdvd
|
||||
simp only [hdvd, ↓reduceIte, Int.natAbs_cast]
|
||||
|
||||
theorem srem_zero_of_dvd {x y : BitVec w} (h : y.toInt ∣ x.toInt) :
|
||||
x.srem y = 0#w := by
|
||||
have := toInt_dvd_toInt_iff (x := x) (y := y)
|
||||
by_cases hx : x.msb <;> by_cases hy : y.msb
|
||||
<;> simp only [h, hx, reduceIte, hy, false_eq_true, true_iff] at this
|
||||
<;> simp [srem, hx, hy, this]
|
||||
|
||||
/--
|
||||
The remainder for `srem`, i.e. division with rounding to zero is negative
|
||||
iff `x` is negative and `y` does not divide `x`.
|
||||
|
||||
We can eventually build fast circuits for the divisibility test `x.srem y = 0`.
|
||||
-/
|
||||
theorem msb_srem {x y : BitVec w} : (x.srem y).msb =
|
||||
(x.msb && decide (x.srem y ≠ 0)) := by
|
||||
rw [msb_eq_toInt]
|
||||
by_cases hx : x.msb
|
||||
· by_cases hsrem : x.srem y = 0#w
|
||||
· simp [hsrem]
|
||||
· have := toInt_neg_of_msb_true hx
|
||||
by_cases hdvd : y.toInt ∣ x.toInt
|
||||
· simp [BitVec.srem_zero_of_dvd hdvd] at hsrem
|
||||
· simp only [toInt_srem, Int.tmod_eq_emod, show ¬0 ≤ x.toInt by omega, hdvd, _root_.or_self,
|
||||
reduceIte, hx, ofNat_eq_ofNat, ne_eq, hsrem, not_false_eq_true, decide_true, Bool.and_self,
|
||||
decide_eq_true_eq, gt_iff_lt]
|
||||
have hlt := Int.emod_lt (a := x.toInt) (b := y.toInt)
|
||||
by_cases hy0 : y = 0#w
|
||||
· simp only [hy0, toInt_zero, Int.emod_zero, Int.natAbs_zero, Int.cast_ofNat_Int,
|
||||
Int.sub_zero, gt_iff_lt]
|
||||
exact toInt_neg_of_msb_true hx
|
||||
· simp only [← toInt_inj, toInt_zero] at hy0
|
||||
simp only [ne_eq, hy0, not_false_eq_true, forall_const] at hlt
|
||||
have := Int.le_natAbs (a := y.toInt)
|
||||
omega
|
||||
· simp only [toInt_srem, hx, ofNat_eq_ofNat, ne_eq, decide_not, Bool.false_and,
|
||||
decide_eq_false_iff_not, Int.not_lt]
|
||||
apply Int.tmod_nonneg y.toInt (by exact toInt_nonneg_of_msb_false (by simp at hx; exact hx))
|
||||
|
||||
theorem toInt_smod {x y : BitVec w} :
|
||||
(x.smod y).toInt = x.toInt.fmod y.toInt := by
|
||||
rcases w with _|w
|
||||
|
|
@ -1998,6 +2036,30 @@ theorem getMsbD_smod {x y : BitVec w} :
|
|||
by_cases hx : x.msb <;> by_cases hy : y.msb
|
||||
<;> simp [hx, hy]
|
||||
|
||||
theorem msb_smod {x y : BitVec w} :
|
||||
(x.smod y).msb = (x.msb && y = 0) || (y.msb && (x.smod y) ≠ 0) := by
|
||||
rw [msb_eq_toInt]
|
||||
by_cases hx : x.msb <;> by_cases hy : y.msb
|
||||
· by_cases hsmod : x.smod y = 0#w <;> simp [hx, hy, hsmod]
|
||||
· simp only [hx, ofNat_eq_ofNat, Bool.true_and, decide_eq_decide, decide_iff_dist, hy, ne_eq,
|
||||
decide_not, Bool.false_and, Bool.or_false, beq_iff_eq]
|
||||
constructor
|
||||
· intro h
|
||||
apply Classical.byContradiction
|
||||
intro hcontra
|
||||
rw [toInt_smod] at h
|
||||
have := toInt_nonneg_of_msb_false (by simp at hy; exact hy)
|
||||
have := Int.fmod_nonneg_of_pos (a := x.toInt) (b := y.toInt) (by simp [← toInt_inj] at hcontra; omega)
|
||||
omega
|
||||
· intro h
|
||||
simp only [h, smod_zero]
|
||||
exact toInt_neg_of_msb_true hx
|
||||
· by_cases hsmod : x.smod y = 0#w <;> simp [hx, hy, hsmod]
|
||||
· simp only [toInt_smod, hx, ofNat_eq_ofNat, Bool.false_and, decide_eq_false_iff_not, Int.not_lt,
|
||||
hy, ne_eq, decide_not, Bool.or_false, decide_eq_true_eq]
|
||||
simp only [not_eq_true] at hx hy
|
||||
apply Int.fmod_nonneg (by exact toInt_nonneg_of_msb_false hx) (by exact toInt_nonneg_of_msb_false hy)
|
||||
|
||||
/-! ### Lemmas that use bit blasting circuits -/
|
||||
|
||||
theorem add_sub_comm {x y : BitVec w} : x + y - z = x - z + y := by
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue