Skip to content

Commit 2f5ce55

Browse files
committed
feat: add BitVec.toInt_sub
This requires us to expand the theory of `Int.bmod`, add `Int.natCast_sub`, as well as `Int.ofNat_sub_ofNat` and a couple of related theorems.
1 parent 682173d commit 2f5ce55

File tree

4 files changed

+81
-6
lines changed

4 files changed

+81
-6
lines changed

src/Init/Data/BitVec/Lemmas.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@ theorem getLsbD_ofNat (n : Nat) (x : Nat) (i : Nat) :
316316
simp [Nat.sub_sub_eq_min, Nat.min_eq_right]
317317
omega
318318

319+
@[simp] theorem sub_add_bmod_cancel {x y : BitVec w} :
320+
((((2 ^ w : Nat) - y.toNat) : Int) + x.toNat).bmod (2 ^ w) =
321+
((x.toNat : Int) - y.toNat).bmod (2 ^ w) := by
322+
rw [Int.sub_eq_add_neg, Int.add_assoc, Int.add_comm, Int.bmod_add_cancel, Int.add_comm,
323+
Int.sub_eq_add_neg]
324+
319325
private theorem lt_two_pow_of_le {x m n : Nat} (lt : x < 2 ^ m) (le : m ≤ n) : x < 2 ^ n :=
320326
Nat.lt_of_lt_of_le lt (Nat.pow_le_pow_of_le_right (by trivial : 0 < 2) le)
321327

@@ -1974,6 +1980,10 @@ theorem sub_def {n} (x y : BitVec n) : x - y = .ofNat n ((2^n - y.toNat) + x.toN
19741980
@[simp] theorem toNat_sub {n} (x y : BitVec n) :
19751981
(x - y).toNat = (((2^n - y.toNat) + x.toNat) % 2^n) := rfl
19761982

1983+
@[simp, bv_toNat] theorem toInt_sub (x y : BitVec w) :
1984+
(x - y).toInt = (x.toInt - y.toInt).bmod (2^w) := by
1985+
simp [toInt_eq_toNat_bmod, Int.natCast_sub (2 ^ w) y.toNat (by omega)]
1986+
19771987
-- We prefer this lemma to `toNat_sub` for the `bv_toNat` simp set.
19781988
-- For reasons we don't yet understand, unfolding via `toNat_sub` sometimes
19791989
-- results in `omega` generating proof terms that are very slow in the kernel.

src/Init/Data/Int/DivModLemmas.lean

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,17 @@ theorem emod_add_bmod_congr (x : Int) (n : Nat) : Int.bmod (x%n + y) n = Int.bmo
11251125
simp [Int.emod_def, Int.sub_eq_add_neg]
11261126
rw [←Int.mul_neg, Int.add_right_comm, Int.bmod_add_mul_cancel]
11271127

1128+
@[simp]
1129+
theorem emod_sub_bmod_congr (x : Int) (n : Nat) : Int.bmod (x%n - y) n = Int.bmod (x - y) n := by
1130+
simp [Int.emod_def, Int.sub_eq_add_neg]
1131+
rw [←Int.mul_neg, Int.add_right_comm, Int.bmod_add_mul_cancel]
1132+
1133+
@[simp]
1134+
theorem sub_emod_bmod_congr (x : Int) (n : Nat) : Int.bmod (x - y%n) n = Int.bmod (x - y) n := by
1135+
simp [Int.emod_def]
1136+
rw [Int.sub_eq_add_neg, Int.neg_sub, Int.sub_eq_add_neg, ← Int.add_assoc, Int.add_right_comm,
1137+
Int.bmod_add_mul_cancel, Int.sub_eq_add_neg]
1138+
11281139
@[simp]
11291140
theorem emod_mul_bmod_congr (x : Int) (n : Nat) : Int.bmod (x%n * y) n = Int.bmod (x * y) n := by
11301141
simp [Int.emod_def, Int.sub_eq_add_neg]
@@ -1140,9 +1151,28 @@ theorem bmod_add_bmod_congr : Int.bmod (Int.bmod x n + y) n = Int.bmod (x + y) n
11401151
rw [Int.sub_eq_add_neg, Int.add_right_comm, ←Int.sub_eq_add_neg]
11411152
simp
11421153

1154+
@[simp]
1155+
theorem bmod_sub_bmod_congr : Int.bmod (Int.bmod x n - y) n = Int.bmod (x - y) n := by
1156+
rw [Int.bmod_def x n]
1157+
split
1158+
next p =>
1159+
simp only [emod_sub_bmod_congr]
1160+
next p =>
1161+
rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, Int.add_right_comm, ←Int.sub_eq_add_neg, ← Int.sub_eq_add_neg]
1162+
simp [emod_sub_bmod_congr]
1163+
11431164
@[simp] theorem add_bmod_bmod : Int.bmod (x + Int.bmod y n) n = Int.bmod (x + y) n := by
11441165
rw [Int.add_comm x, Int.bmod_add_bmod_congr, Int.add_comm y]
11451166

1167+
@[simp] theorem sub_bmod_bmod : Int.bmod (x - Int.bmod y n) n = Int.bmod (x - y) n := by
1168+
rw [Int.bmod_def y n]
1169+
split
1170+
next p =>
1171+
simp [sub_emod_bmod_congr]
1172+
next p =>
1173+
rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, Int.neg_add, Int.neg_neg, ← Int.add_assoc, ← Int.sub_eq_add_neg]
1174+
simp [sub_emod_bmod_congr]
1175+
11461176
@[simp]
11471177
theorem bmod_mul_bmod : Int.bmod (Int.bmod x n * y) n = Int.bmod (x * y) n := by
11481178
rw [bmod_def x n]

src/Init/Data/Int/Lemmas.lean

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ theorem subNatNat_of_sub_eq_zero {m n : Nat} (h : n - m = 0) : subNatNat m n =
2121
theorem subNatNat_of_sub_eq_succ {m n k : Nat} (h : n - m = succ k) : subNatNat m n = -[k+1] := by
2222
rw [subNatNat, h]
2323

24+
theorem subNatNat_of_sub {m n : Nat} (h : n ≤ m) : subNatNat m n = ↑(m - n) := by
25+
rw [subNatNat, ofNat_eq_coe]
26+
split
27+
case h_1 _ _ =>
28+
simp
29+
case h_2 _ h' =>
30+
rw [Nat.sub_eq_zero_of_le h] at h'
31+
simp at h'
32+
2433
@[simp] protected theorem neg_zero : -(0:Int) = 0 := rfl
2534

2635
@[norm_cast] theorem ofNat_add (n m : Nat) : (↑(n + m) : Int) = n + m := rfl
@@ -54,8 +63,32 @@ theorem negOfNat_eq : negOfNat n = -ofNat n := rfl
5463

5564
/- ## some basic functions and properties -/
5665

66+
def eq_add_one_iff_neg_eq_negSucc {m n : Nat} : m = n + 1 ↔ -↑m = -[n+1] := by
67+
simp [Neg.neg, instNegInt, Int.neg, negOfNat]
68+
split <;> simp [Nat.add_one_inj]
69+
5770
@[norm_cast] theorem ofNat_inj : ((m : Nat) : Int) = (n : Nat) ↔ m = n := ⟨ofNat.inj, congrArg _⟩
5871

72+
@[local simp] theorem ofNat_sub_ofNat (m n : Nat) (h : n ≤ m) : (↑m - ↑n : Int) = ↑(m - n) := by
73+
simp only [HSub.hSub, instHSub, Sub.sub, instSub, Int.sub]
74+
simp only [HAdd.hAdd, instHAdd, Add.add, instAdd, Int.add]
75+
simp only [add_eq, ofNat_eq_coe, succ_eq_add_one, sub_eq]
76+
split
77+
case h_1 ia ib na nb ha hb =>
78+
simp only [ofNat_eq_coe] at ha hb
79+
symm at hb
80+
have := (@ofNat_inj nb 0).mp
81+
cases n <;> simp_all
82+
case h_2 ia ib na nb ha hb =>
83+
have h' := eq_add_one_iff_neg_eq_negSucc.mpr hb
84+
have h'' := (@ofNat_inj m na).mp ha
85+
rw [h'] at h
86+
rw [h''] at h
87+
rw [subNatNat_of_sub h]
88+
congr <;> simp_all
89+
· simp_all
90+
· simp_all
91+
5992
theorem ofNat_eq_zero : ((n : Nat) : Int) = 0 ↔ n = 0 := ofNat_inj
6093

6194
theorem ofNat_ne_zero : ((n : Nat) : Int) ≠ 0 ↔ n ≠ 0 := not_congr ofNat_eq_zero
@@ -528,6 +561,12 @@ theorem natCast_one : ((1 : Nat) : Int) = (1 : Int) := rfl
528561
-- so it still makes sense to tag the lemmas with `@[simp]`.
529562
simp
530563

564+
@[simp] theorem natCast_sub (a b : Nat) (h : b ≤ a) :
565+
((a - b : Nat) : Int) = (a : Int) - (b : Int) := by
566+
simp [h]
567+
-- Note this only works because of local simp attributes in this file,
568+
-- so it still makes sense to tag the lemmas with `@[simp]`.
569+
531570
@[simp] theorem natCast_mul (a b : Nat) : ((a * b : Nat) : Int) = (a : Int) * (b : Int) := by
532571
simp
533572

src/Init/Omega/Int.lean

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,9 @@ theorem ofNat_sub_dichotomy {a b : Nat} :
9494
b ≤ a ∧ ((a - b : Nat) : Int) = a - b ∨ a < b ∧ ((a - b : Nat) : Int) = 0 := by
9595
by_cases h : b ≤ a
9696
· left
97-
have t := Int.ofNat_sub h
98-
simp at t
99-
exact ⟨h, t⟩
97+
simp [h]
10098
· right
101-
have t := Nat.not_le.mp h
102-
simp [Int.ofNat_sub_eq_zero h]
103-
exact t
99+
simp [Int.ofNat_sub_eq_zero, Nat.not_le.mp, h]
104100

105101
theorem ofNat_congr {a b : Nat} (h : a = b) : (a : Int) = (b : Int) := congrArg _ h
106102

0 commit comments

Comments
 (0)