@@ -1681,6 +1681,81 @@ theorem toInt_sdiv (a b : BitVec w) : (a.sdiv b).toInt = (a.toInt.tdiv b.toInt).
16811681 · rw [← toInt_bmod_cancel]
16821682 rw [BitVec.toInt_sdiv_of_ne_or_ne _ _ (by simpa only [Decidable.not_and_iff_not_or_not] using h)]
16831683
1684+ /--
1685+ Rewrite `(x.sdiv y).toInt` as an exceptional case of `intMin / -1`,
1686+ and a uniform uniformly expression as `x.toInt.tdiv y.toInt` for all other cases.
1687+
1688+ Recall that `x.tdiv 0 = 0`, so there is an implicit case analysis on `y`.
1689+ -/
1690+ theorem toInt_sdiv_eq_ite {x y : BitVec w} :
1691+ (x.sdiv y).toInt =
1692+ if x = intMin w ∧ y = -1 #w then (intMin w).toInt
1693+ else x.toInt.tdiv y.toInt := by
1694+ by_cases hx : x = intMin w
1695+ · simp only [hx, _root_.true_and]
1696+ by_cases hy : y = -1 #w
1697+ · simp [hy, intMin_sdiv_neg_one]
1698+ · simp only [hy, ↓reduceIte]
1699+ apply toInt_sdiv_of_ne_or_ne
1700+ simp [hy]
1701+ · simp only [hx, _root_.false_and, ↓reduceIte]
1702+ apply toInt_sdiv_of_ne_or_ne
1703+ simp [hx]
1704+
1705+ #eval (0 #0 ).msb
1706+ #check Int.tdiv_nonpos_of_nonneg_of_nonpos
1707+ #check Int.tdiv_nonpos_of_nonneg_of_nonpos
1708+
1709+
1710+ /--
1711+ The sign of a division is determined as follows:
1712+ - if the denominator is zero, then the output is zero and the msb is false as it is non-negative.
1713+ - If the deminator is positive, then the sign of the output is the same as the sign of the numerator.
1714+ - If the denominator is negative, then the sign of the output is the opposite of the sign of the numerator,
1715+ except for the case where the numerator is `intMin`, in which case the result is `true`.
1716+ -/
1717+ theorem msb_sdiv_eq_ite {x y : BitVec w} :
1718+ (x.sdiv y).msb = ((decide (0 < w)) &&
1719+ (!decide (y = 0 #w) &&
1720+ (decide (x = intMin w) && decide (y = -1 #w) || x.msb ^^ y.msb)))
1721+ := by
1722+ by_cases hw : w = 0 ; subst hw; decide +revert
1723+ simp [show 0 < w by omega]
1724+ by_cases hy : y = 0 #w
1725+ · simp [hy]
1726+ · simp [hy]
1727+ by_cases h : x = intMin w ∧ y = -1 #w
1728+ · simp [h, intMin_sdiv_neg_one, msb_intMin]; omega
1729+ · suffices (decide (x = intMin w) && decide (y = -1 #w)) = false by
1730+ simp [this]
1731+ rw [msb_eq_toInt, toInt_sdiv_of_ne_or_ne]
1732+ · rw [msb_eq_toInt, msb_eq_toInt]
1733+ by_cases hx : 0 ≤ x.toInt
1734+ · by_cases hy : 0 ≤ y.toInt
1735+ · have := Int.tdiv_nonneg hx hy
1736+ simp [show ¬ (x.toInt < 0 ) by omega
1737+ , show ¬ (y.toInt < 0 ) by omega,
1738+ show ¬ (x.toInt.tdiv y.toInt < 0 ) by omega]
1739+ · simp [show ¬ x.toInt < 0 by omega]
1740+ simp [show y.toInt < 0 by omega]
1741+ have := Int.tdiv_neg
1742+ sorry
1743+ · by_cases hy : 0 ≤ y.toInt
1744+ · simp [show ¬ y.toInt < 0 by omega]
1745+ simp [show x.toInt < 0 by omega]
1746+ sorry
1747+ · simp [show x.toInt < 0 by omega]
1748+ simp [show y.toInt < 0 by omega]
1749+ rw [Int.tdiv_nonneg_of_nonpos_of_nonpos]
1750+ -- apply Int.tdiv_nonneg_of_nonpos_of_nonpos
1751+ -- · omega
1752+ -- · omega
1753+
1754+ -- simp only [ bool_to_prop ] -- TODO: teach bool_to_prop about xor.
1755+ · rw [Classical.not_and_iff_not_or_not] at h
1756+ rcases h with h | h <;> simp [h]
1757+ simpa using h
1758+
16841759theorem msb_umod_eq_false_of_left {x : BitVec w} (hx : x.msb = false ) (y : BitVec w) : (x % y).msb = false := by
16851760 rw [msb_eq_false_iff_two_mul_lt] at hx ⊢
16861761 rw [toNat_umod]
0 commit comments