namespace Foam.FInt theorem add_sub_cancel (m n : Nat) : (m + n) - n = m := by induction n with | zero => rfl | succ k ih => rw [Nat.add_succ, Nat.succ_sub_succ]; exact ih theorem add_sub_cancel_left (m n : Nat) : (m + n) - m = n := by rw [Nat.add_comm]; exact add_sub_cancel n m theorem sub_eq_zero_of_le {m n : Nat} (h : m ≤ n) : m - n = 0 := by induction h with | refl => exact Nat.sub_self m | step _ ih => rw [Nat.sub_succ, ih]; rfl theorem subNatNat_of_ge {m n : Nat} (h : n ≤ m) : Int.subNatNat m n = Int.ofNat (m - n) := by show (match n - m with | 0 => Int.ofNat (m - n) | Nat.succ k => Int.negSucc k) = Int.ofNat (m - n) rw [sub_eq_zero_of_le h] theorem subNatNat_add_succ (m d : Nat) : Int.subNatNat m (m + d + 1) = Int.negSucc d := by show (match (m+d+1) - m with | 0 => Int.ofNat (m - (m+d+1)) | Nat.succ k => Int.negSucc k) = Int.negSucc d have h : (m + d + 1) - m = d + 1 := by rw [Nat.add_assoc m d 1, add_sub_cancel_left] rw [h] theorem subNatNat_succ_succ (m n : Nat) : Int.subNatNat (m+1) (n+1) = Int.subNatNat m n := by show (match (n+1) - (m+1) with | 0 => Int.ofNat ((m+1) - (n+1)) | Nat.succ c => Int.negSucc c) = (match n - m with | 0 => Int.ofNat (m - n) | Nat.succ c => Int.negSucc c) rw [Nat.succ_sub_succ, Nat.succ_sub_succ] theorem subNatNat_succ_right (a j : Nat) : Int.subNatNat a (j+1) + 1 = Int.subNatNat a j := by rcases Nat.lt_or_ge j a with hlt | hge · rw [subNatNat_of_ge hlt, subNatNat_of_ge (Nat.le_of_lt hlt)] obtain ⟨d, rfl⟩ := Nat.le.dest hlt have e1 : j + 1 + d - (j+1) = d := add_sub_cancel_left (j+1) d have e2 : j + 1 + d - j = d + 1 := by rw [Nat.add_assoc j 1 d, add_sub_cancel_left, Nat.add_comm 1 d] rw [e1, e2]; rfl · obtain ⟨d, rfl⟩ := Nat.le.dest hge rcases d with _ | d' · rw [Nat.add_zero] show Int.subNatNat a (a+1) + 1 = Int.subNatNat a a rw [subNatNat_add_succ a 0, subNatNat_of_ge (Nat.le_refl a), Nat.sub_self]; rfl · show Int.subNatNat a (a + (d'+1) + 1) + 1 = Int.subNatNat a (a + (d'+1)) rw [subNatNat_add_succ a (d'+1), show a + (d'+1) = a + d' + 1 from (Nat.add_assoc a d' 1).symm, subNatNat_add_succ a d'] rfl theorem ofNat_succ_add (a : Nat) (s : Int) : Int.ofNat (a+1) + s = (Int.ofNat a + s) + 1 := by cases s with | ofNat j => show Int.ofNat ((a+1)+j) = Int.ofNat (a+j) + 1 rw [show (a+1)+j = (a+j)+1 from by rw [Nat.add_right_comm a 1 j]]; rfl | negSucc j => show Int.subNatNat (a+1) (j+1) = Int.subNatNat a (j+1) + 1 rw [subNatNat_succ_succ a j, subNatNat_succ_right a j] theorem zero_add (a : Int) : 0 + a = a := by cases a with | ofNat n => show Int.ofNat (0 + n) = Int.ofNat n; rw [Nat.zero_add] | negSucc n => rfl theorem subNatNat_succ_left (m k : Nat) : Int.subNatNat (m+1) k = Int.subNatNat m k + 1 := by rcases Nat.lt_or_ge k (m+1) with hlt | hge · have hkm : k ≤ m := Nat.le_of_lt_succ hlt rw [subNatNat_of_ge (Nat.le_of_lt hlt), subNatNat_of_ge hkm] obtain ⟨d, rfl⟩ := Nat.le.dest hkm rw [add_sub_cancel_left, show (k+d+1) - k = d+1 from by rw [Nat.add_assoc k d 1, add_sub_cancel_left]] rfl · obtain ⟨e, rfl⟩ := Nat.le.dest hge rcases e with _ | e' · rw [Nat.add_zero, subNatNat_of_ge (Nat.le_refl _), Nat.sub_self] rw [show Int.subNatNat m (m+1) = Int.negSucc 0 from by have := subNatNat_add_succ m 0; rw [Nat.add_zero] at this; exact this] rfl · rw [show (m+1)+(e'+1) = (m+1)+e'+1 from (Nat.add_assoc (m+1) e' 1).symm, subNatNat_add_succ (m+1) e'] rw [show m+1+e'+1 = m+(e'+1)+1 from by rw [Nat.add_right_comm m 1 e', Nat.add_assoc m e' 1], subNatNat_add_succ m (e'+1)] rfl theorem subNatNat_add (m n k : Nat) : Int.subNatNat (m + n) k = Int.ofNat m + Int.subNatNat n k := by induction m with | zero => rw [Nat.zero_add, show Int.ofNat 0 = (0:Int) from rfl, zero_add] | succ a ih => rw [Nat.succ_add, subNatNat_succ_left (a+n) k, ih] exact (ofNat_succ_add a (Int.subNatNat n k)).symm theorem add_sub_add_left (k m n : Nat) : (k + m) - (k + n) = m - n := by induction k with | zero => rw [Nat.zero_add, Nat.zero_add] | succ d ih => rw [show d+1+m = (d+m)+1 from by rw [Nat.add_right_comm d 1 m], show d+1+n = (d+n)+1 from by rw [Nat.add_right_comm d 1 n], Nat.succ_sub_succ]; exact ih theorem add_sub_add_right (m k n : Nat) : (m + k) - (n + k) = m - n := by rw [Nat.add_comm m k, Nat.add_comm n k]; exact add_sub_add_left k m n theorem subNatNat_add_add (m n k : Nat) : Int.subNatNat (m + k) (n + k) = Int.subNatNat m n := by show (match (n+k) - (m+k) with | 0 => Int.ofNat ((m+k) - (n+k)) | Nat.succ c => Int.negSucc c) = (match n - m with | 0 => Int.ofNat (m - n) | Nat.succ c => Int.negSucc c) rw [add_sub_add_right n k m, add_sub_add_right m k n] theorem addComm (a b : Int) : a + b = b + a := by cases a with | ofNat m => cases b with | ofNat n => show Int.ofNat (m + n) = Int.ofNat (n + m); rw [Nat.add_comm] | negSucc n => rfl | negSucc m => cases b with | ofNat n => rfl | negSucc n => show Int.negSucc (m + n).succ = Int.negSucc (n + m).succ; rw [Nat.add_comm] theorem subNatNat_add_ofNat (m n k : Nat) : Int.subNatNat m n + Int.ofNat k = Int.subNatNat (m + k) n := by rw [Nat.add_comm m k, subNatNat_add k m n, addComm] theorem subNatNat_add_negSucc (m n k : Nat) : Int.subNatNat m n + Int.negSucc k = Int.subNatNat m (n + (k+1)) := by rcases Nat.lt_or_ge n m with hlt | hge · rw [subNatNat_of_ge (Nat.le_of_lt hlt)] show Int.subNatNat (m-n) (k+1) = Int.subNatNat m (n+(k+1)) obtain ⟨d, rfl⟩ := Nat.le.dest (Nat.le_of_lt hlt) rw [add_sub_cancel_left, show n+d = d+n from Nat.add_comm n d, show n+(k+1) = (k+1)+n from Nat.add_comm n (k+1), subNatNat_add_add d (k+1) n] · obtain ⟨d, rfl⟩ := Nat.le.dest hge rcases d with _ | d' · rw [Nat.add_zero, subNatNat_of_ge (Nat.le_refl m), Nat.sub_self] show Int.negSucc k = Int.subNatNat m (m + (k+1)) rw [show m+(k+1) = m+k+1 from (Nat.add_assoc m k 1).symm, subNatNat_add_succ m k] · rw [show m+(d'+1) = m+d'+1 from (Nat.add_assoc m d' 1).symm, subNatNat_add_succ m d'] show Int.negSucc (d' + k).succ = Int.subNatNat m (m + (d'+1) + (k+1)) rw [show m+(d'+1)+(k+1) = m + ((d'+k+1)+1) from by rw [Nat.add_assoc m (d'+1) (k+1)] apply congrArg (m + ·) rw [Nat.add_assoc d' 1 (k+1), Nat.add_comm 1 (k+1), ← Nat.add_assoc d' (k+1) 1, Nat.add_assoc d' k 1], show m + ((d'+k+1)+1) = m + (d'+k+1) + 1 from (Nat.add_assoc m (d'+k+1) 1).symm, subNatNat_add_succ m (d'+k+1)] theorem add_assoc (a b c : Int) : a + b + c = a + (b + c) := by cases a with | ofNat p => cases b with | ofNat q => cases c with | ofNat r => show Int.ofNat (p+q+r) = Int.ofNat (p+(q+r)); rw [Nat.add_assoc] | negSucc r => show Int.subNatNat (p+q) (r+1) = Int.ofNat p + Int.subNatNat q (r+1); rw [subNatNat_add] | negSucc q => cases c with | ofNat r => show Int.subNatNat p (q+1) + Int.ofNat r = Int.ofNat p + Int.subNatNat r (q+1) rw [subNatNat_add_ofNat p (q+1) r, subNatNat_add p r (q+1)] | negSucc r => show Int.subNatNat p (q+1) + Int.negSucc r = Int.ofNat p + Int.negSucc (q + r).succ rw [subNatNat_add_negSucc p (q+1) r] show Int.subNatNat p (q+1+(r+1)) = Int.subNatNat p ((q+r).succ + 1) rw [Nat.add_right_comm q 1 (r+1)]; show Int.subNatNat p (q+(r+1)+1) = Int.subNatNat p ((q+r)+1+1) rw [← Nat.add_assoc q r 1] | negSucc p => cases b with | ofNat q => cases c with | ofNat r => show Int.subNatNat q (p+1) + Int.ofNat r = Int.subNatNat (q+r) (p+1) rw [subNatNat_add_ofNat q (p+1) r] | negSucc r => show Int.subNatNat q (p+1) + Int.negSucc r = Int.negSucc p + Int.subNatNat q (r+1) rw [subNatNat_add_negSucc q (p+1) r, addComm (Int.negSucc p) (Int.subNatNat q (r+1)), subNatNat_add_negSucc q (r+1) p] show Int.subNatNat q (p+1+(r+1)) = Int.subNatNat q (r+1+(p+1)) rw [Nat.add_comm (p+1) (r+1)] | negSucc q => cases c with | ofNat r => show Int.subNatNat r ((p+q).succ+1) = Int.negSucc p + Int.subNatNat r (q+1) rw [addComm (Int.negSucc p) (Int.subNatNat r (q+1)), subNatNat_add_negSucc r (q+1) p] show Int.subNatNat r ((p+q).succ+1) = Int.subNatNat r (q+1+(p+1)) rw [Nat.add_right_comm q 1 (p+1)]; show Int.subNatNat r ((p+q)+1+1) = Int.subNatNat r (q+(p+1)+1) rw [← Nat.add_assoc q p 1, Nat.add_comm q p] | negSucc r => show Int.negSucc ((p+q).succ + r).succ = Int.negSucc (p + (q+r).succ).succ rw [show (p+q).succ + r = p + (q+r).succ from by rw [Nat.succ_add, Nat.add_succ, Nat.add_assoc]] theorem add_right_neg (a : Int) : a + (-a) = 0 := by cases a with | ofNat n => cases n with | zero => rfl | succ k => show Int.subNatNat (k+1) (k+1) = 0 rw [subNatNat_of_ge (Nat.le_refl _), Nat.sub_self]; rfl | negSucc n => show Int.subNatNat (n+1) (n+1) = 0 rw [subNatNat_of_ge (Nat.le_refl _), Nat.sub_self]; rfl theorem add_left_neg (a : Int) : (-a) + a = 0 := by rw [addComm]; exact add_right_neg a theorem neg_eq_of_add_eq_zero {a b : Int} (h : a + b = 0) : -a = b := by rw [← Int.add_zero (-a), ← h, ← add_assoc, add_left_neg, zero_add] theorem neg_add (a b : Int) : -(a + b) = -a + -b := by apply neg_eq_of_add_eq_zero rw [add_assoc, addComm (-a) (-b), ← add_assoc b (-b) (-a), add_right_neg, zero_add, add_right_neg] theorem subNatNat_of_lt {m n : Nat} (h : m < n) : Int.subNatNat m n = -(Int.ofNat (n - m)) := by obtain ⟨d, rfl⟩ := Nat.le.dest h rw [show Int.subNatNat m (m+1+d) = Int.negSucc d from by rw [show m+1+d = m+d+1 from by rw [Nat.add_right_comm m 1 d]]; exact subNatNat_add_succ m d] rw [show (m+1+d) - m = d+1 from by rw [Nat.add_right_comm m 1 d, Nat.add_assoc m d 1, add_sub_cancel_left]] rfl theorem mulComm (a b : Int) : a * b = b * a := by cases a with | ofNat m => cases b with | ofNat n => show Int.ofNat (m * n) = Int.ofNat (n * m); rw [Nat.mul_comm] | negSucc n => show Int.negOfNat (m * n.succ) = Int.negOfNat (n.succ * m); rw [Nat.mul_comm] | negSucc m => cases b with | ofNat n => show Int.negOfNat (m.succ * n) = Int.negOfNat (n * m.succ); rw [Nat.mul_comm] | negSucc n => show Int.ofNat (m.succ * n.succ) = Int.ofNat (n.succ * m.succ); rw [Nat.mul_comm] theorem zero_mul (a : Int) : 0 * a = 0 := by cases a with | ofNat n => show Int.ofNat (0 * n) = Int.ofNat 0; rw [Nat.zero_mul] | negSucc n => show Int.negOfNat (0 * n.succ) = (0:Int); rw [Nat.zero_mul]; rfl theorem mul_zero (a : Int) : a * 0 = 0 := by rw [mulComm]; exact zero_mul a theorem mul_one (a : Int) : a * 1 = a := by cases a with | ofNat n => show Int.ofNat (n * 1) = Int.ofNat n; rw [Nat.mul_one] | negSucc n => show Int.negOfNat (n.succ * 1) = Int.negSucc n; rw [Nat.mul_one]; rfl theorem one_mul (a : Int) : 1 * a = a := by rw [mulComm]; exact mul_one a theorem neg_mul (a b : Int) : (-a) * b = -(a * b) := by cases a with | ofNat m => cases m with | zero => show (0:Int) * b = -((0:Int) * b); rw [zero_mul]; rfl | succ k => cases b with | ofNat n => show Int.negOfNat ((k+1) * n) = -(Int.ofNat ((k+1)*n)); rw [Int.negOfNat_eq] | negSucc n => show Int.ofNat ((k+1) * n.succ) = -(Int.negOfNat ((k+1) * n.succ)); rw [Int.negOfNat_eq, Int.neg_neg] | negSucc m => cases b with | ofNat n => show Int.ofNat (m.succ * n) = -(Int.negOfNat (m.succ * n)); rw [Int.negOfNat_eq, Int.neg_neg] | negSucc n => show Int.negOfNat (m.succ * n.succ) = -(Int.ofNat (m.succ * n.succ)); rw [Int.negOfNat_eq] theorem mul_neg (a b : Int) : a * (-b) = -(a * b) := by rw [mulComm a (-b), neg_mul, mulComm] theorem nat_mul_sub (c m n : Nat) (h : n ≤ m) : c * (m - n) = c * m - c * n := by obtain ⟨d, rfl⟩ := Nat.le.dest h rw [add_sub_cancel_left n d, Nat.left_distrib c n d, add_sub_cancel_left (c*n) (c*d)] theorem ofNat_mul_subNatNat (c m n : Nat) : Int.ofNat c * Int.subNatNat m n = Int.subNatNat (c*m) (c*n) := by cases c with | zero => rw [show Int.ofNat 0 = (0:Int) from rfl, zero_mul, Nat.zero_mul, Nat.zero_mul]; rfl | succ c' => rcases Nat.lt_or_ge n m with hlt | hge · rw [subNatNat_of_ge (Nat.le_of_lt hlt), subNatNat_of_ge (Nat.mul_le_mul_left (c'+1) (Nat.le_of_lt hlt))] show Int.ofNat ((c'+1) * (m - n)) = Int.ofNat ((c'+1)*m - (c'+1)*n) rw [nat_mul_sub (c'+1) m n (Nat.le_of_lt hlt)] · rcases Nat.eq_or_lt_of_le hge with heq | hlt · rw [← heq, subNatNat_of_ge (Nat.le_refl m), Nat.sub_self, subNatNat_of_ge (Nat.le_refl ((c'+1)*m)), Nat.sub_self]; rfl · have hmul : (c'+1)*m < (c'+1)*n := Nat.mul_lt_mul_of_pos_left hlt (Nat.succ_pos c') rw [subNatNat_of_lt hlt, subNatNat_of_lt hmul, mul_neg] show -(Int.ofNat ((c'+1) * (n - m))) = -(Int.ofNat ((c'+1)*n - (c'+1)*m)) rw [nat_mul_sub (c'+1) n m (Nat.le_of_lt hlt)] theorem ofNat_mul_ofNat (p q : Nat) : Int.ofNat p * Int.ofNat q = Int.ofNat (p*q) := rfl theorem ofNat_mul_negSucc (p q : Nat) : Int.ofNat p * Int.negSucc q = -(Int.ofNat (p*(q+1))) := by rw [show Int.negSucc q = -(Int.ofNat (q+1)) from rfl, mul_neg]; rfl theorem ofNat_add_neg_ofNat (a b : Nat) : Int.ofNat a + -(Int.ofNat b) = Int.subNatNat a b := by cases b with | zero => show Int.ofNat a + 0 = Int.subNatNat a 0; rw [Int.add_zero, subNatNat_of_ge (Nat.zero_le a), Nat.sub_zero] | succ k => show Int.ofNat a + Int.negSucc k = Int.subNatNat a (k+1); rfl theorem neg_ofNat_add_ofNat (a b : Nat) : -(Int.ofNat a) + Int.ofNat b = Int.subNatNat b a := by rw [addComm, ofNat_add_neg_ofNat] theorem neg_ofNat_add_neg_ofNat (a b : Nat) : -(Int.ofNat a) + -(Int.ofNat b) = -(Int.ofNat (a + b)) := by rw [← neg_add]; rfl theorem ofNat_mul_add (p : Nat) (b c : Int) : Int.ofNat p * (b + c) = Int.ofNat p * b + Int.ofNat p * c := by cases b with | ofNat q => cases c with | ofNat r => show Int.ofNat (p*(q+r)) = Int.ofNat (p*q) + Int.ofNat (p*r) rw [Nat.left_distrib]; rfl | negSucc r => show Int.ofNat p * Int.subNatNat q (r+1) = Int.ofNat (p*q) + Int.ofNat p * Int.negSucc r rw [ofNat_mul_subNatNat p q (r+1), ofNat_mul_negSucc p r, ofNat_add_neg_ofNat] | negSucc q => cases c with | ofNat r => show Int.ofNat p * Int.subNatNat r (q+1) = Int.ofNat p * Int.negSucc q + Int.ofNat (p*r) rw [ofNat_mul_subNatNat p r (q+1), ofNat_mul_negSucc p q, addComm (-(Int.ofNat (p*(q+1)))) (Int.ofNat (p*r)), ofNat_add_neg_ofNat] | negSucc r => show Int.ofNat p * Int.negSucc (q + r).succ = Int.ofNat p * Int.negSucc q + Int.ofNat p * Int.negSucc r rw [ofNat_mul_negSucc p (q+r+1), ofNat_mul_negSucc p q, ofNat_mul_negSucc p r, neg_ofNat_add_neg_ofNat] show -(Int.ofNat (p * ((q+r)+1+1))) = -(Int.ofNat (p*(q+1) + p*(r+1))) rw [← Nat.left_distrib p (q+1) (r+1)] show -(Int.ofNat (p * ((q+r)+1+1))) = -(Int.ofNat (p*((q+1)+(r+1)))) rw [show (q+1)+(r+1) = (q+r)+1+1 from by rw [← Nat.add_assoc (q+1) r 1, Nat.add_right_comm q 1 r]] theorem mul_add (a b c : Int) : a * (b + c) = a * b + a * c := by cases a with | ofNat p => exact ofNat_mul_add p b c | negSucc p => show (-(Int.ofNat (p+1))) * (b + c) = (-(Int.ofNat (p+1))) * b + (-(Int.ofNat (p+1))) * c rw [neg_mul, neg_mul, neg_mul, ofNat_mul_add (p+1) b c, neg_add] theorem add_mul (a b c : Int) : (a + b) * c = a * c + b * c := by rw [mulComm (a+b) c, mul_add, mulComm c a, mulComm c b] theorem nat_mul_assoc (a b c : Nat) : a * b * c = a * (b * c) := by induction c with | zero => rfl | succ d ih => rw [Nat.mul_succ, Nat.mul_succ, Nat.left_distrib, ih] theorem mul_assoc (a b c : Int) : a * b * c = a * (b * c) := by cases a with | ofNat p => cases b with | ofNat q => cases c with | ofNat r => show Int.ofNat (p*q*r) = Int.ofNat (p*(q*r)); rw [nat_mul_assoc] | negSucc r => show Int.ofNat (p*q) * Int.negSucc r = Int.ofNat p * (Int.ofNat q * Int.negSucc r) rw [ofNat_mul_negSucc (p*q) r, ofNat_mul_negSucc q r, mul_neg, ofNat_mul_ofNat] show -(Int.ofNat (p*q*(r+1))) = -(Int.ofNat (p*(q*(r+1)))); rw [nat_mul_assoc] | negSucc q => cases c with | ofNat r => show Int.ofNat p * Int.negSucc q * Int.ofNat r = Int.ofNat p * (Int.negSucc q * Int.ofNat r) rw [ofNat_mul_negSucc p q, mulComm (Int.negSucc q) (Int.ofNat r), ofNat_mul_negSucc r q, neg_mul, mul_neg, ofNat_mul_ofNat] show -(Int.ofNat (p*(q+1)*r)) = -(Int.ofNat (p*(r*(q+1)))); rw [nat_mul_assoc, Nat.mul_comm r (q+1)] | negSucc r => show Int.ofNat p * Int.negSucc q * Int.negSucc r = Int.ofNat p * (Int.negSucc q * Int.negSucc r) rw [ofNat_mul_negSucc p q, neg_mul] show -(Int.ofNat (p*(q+1)) * Int.negSucc r) = Int.ofNat p * (Int.negSucc q * Int.negSucc r) rw [ofNat_mul_negSucc (p*(q+1)) r] show -(-(Int.ofNat (p*(q+1)*(r+1)))) = Int.ofNat p * (Int.negSucc q * Int.negSucc r) rw [Int.neg_neg] show Int.ofNat (p*(q+1)*(r+1)) = Int.ofNat p * Int.ofNat ((q+1)*(r+1)) rw [ofNat_mul_ofNat, nat_mul_assoc] | negSucc p => show (-(Int.ofNat (p+1))) * b * c = (-(Int.ofNat (p+1))) * (b * c) rw [neg_mul, neg_mul, neg_mul] apply congrArg Neg.neg cases b with | ofNat q => cases c with | ofNat r => show Int.ofNat ((p+1)*q*r) = Int.ofNat ((p+1)*(q*r)); rw [nat_mul_assoc] | negSucc r => show Int.ofNat ((p+1)*q) * Int.negSucc r = Int.ofNat (p+1) * (Int.ofNat q * Int.negSucc r) rw [ofNat_mul_negSucc ((p+1)*q) r, ofNat_mul_negSucc q r, mul_neg, ofNat_mul_ofNat] show -(Int.ofNat ((p+1)*q*(r+1))) = -(Int.ofNat ((p+1)*(q*(r+1)))); rw [nat_mul_assoc] | negSucc q => cases c with | ofNat r => show Int.ofNat (p+1) * Int.negSucc q * Int.ofNat r = Int.ofNat (p+1) * (Int.negSucc q * Int.ofNat r) rw [ofNat_mul_negSucc (p+1) q, mulComm (Int.negSucc q) (Int.ofNat r), ofNat_mul_negSucc r q, neg_mul, mul_neg, ofNat_mul_ofNat] show -(Int.ofNat ((p+1)*(q+1)*r)) = -(Int.ofNat ((p+1)*(r*(q+1)))); rw [nat_mul_assoc, Nat.mul_comm r (q+1)] | negSucc r => show Int.ofNat (p+1) * Int.negSucc q * Int.negSucc r = Int.ofNat (p+1) * (Int.negSucc q * Int.negSucc r) rw [ofNat_mul_negSucc (p+1) q, neg_mul, ofNat_mul_negSucc ((p+1)*(q+1)) r, Int.neg_neg] show Int.ofNat ((p+1)*(q+1)*(r+1)) = Int.ofNat (p+1) * Int.ofNat ((q+1)*(r+1)) rw [ofNat_mul_ofNat, nat_mul_assoc] theorem mul_neg_one (a : Int) : a * (-1) = -a := by rw [mul_neg, mul_one] theorem sub_zero (a : Int) : a - 0 = a := by rw [Int.sub_eq_add_neg]; show a + (-0) = a; rw [show (-0:Int) = 0 from rfl, Int.add_zero] theorem sub_add_cancel (a b : Int) : a - b + b = a := by rw [Int.sub_eq_add_neg, add_assoc, add_left_neg, Int.add_zero] theorem add_sub_cancel_right (a b : Int) : a + b - b = a := by rw [Int.sub_eq_add_neg, add_assoc, add_right_neg, Int.add_zero] theorem neg_sub (a b : Int) : -(a - b) = b - a := by rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, neg_add, Int.neg_neg, addComm] theorem mul_sub (a b c : Int) : a * (b - c) = a * b - a * c := by rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, mul_add, mul_neg] theorem sub_mul (a b c : Int) : (a - b) * c = a * c - b * c := by rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, add_mul, neg_mul] theorem sub_sub (a b c : Int) : a - b - c = a - (b + c) := by rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, Int.sub_eq_add_neg, add_assoc, neg_add] theorem two_mul (a : Int) : 2 * a = a + a := by rw [show (2:Int) = 1 + 1 from rfl, add_mul, one_mul] theorem mul_eq_zero {a b : Int} : a * b = 0 ↔ a = 0 ∨ b = 0 := by constructor · intro h cases a with | ofNat m => cases m with | zero => exact Or.inl rfl | succ k => cases b with | ofNat n => cases n with | zero => exact Or.inr rfl | succ j => exact absurd h (by show Int.ofNat ((k+1)*(j+1)) ≠ 0 rw [show (k+1)*(j+1) = k*(j+1)+(j+1) from Nat.succ_mul k (j+1)] intro hc; exact Nat.noConfusion (Int.ofNat.inj hc)) | negSucc n => exact absurd h (by show Int.negOfNat ((k+1)*(n+1)) ≠ 0 rw [show (k+1)*(n+1) = k*(n+1)+(n+1) from Nat.succ_mul k (n+1)] intro hc; exact Int.noConfusion hc) | negSucc m => cases b with | ofNat n => cases n with | zero => exact Or.inr rfl | succ j => exact absurd h (by show Int.negOfNat ((m+1)*(j+1)) ≠ 0 rw [show (m+1)*(j+1) = m*(j+1)+(j+1) from Nat.succ_mul m (j+1)] intro hc; exact Int.noConfusion hc) | negSucc n => exact absurd h (by show Int.ofNat ((m+1)*(n+1)) ≠ 0 rw [show (m+1)*(n+1) = m*(n+1)+(n+1) from Nat.succ_mul m (n+1)] intro hc; exact Nat.noConfusion (Int.ofNat.inj hc)) · intro h; cases h with | inl ha => rw [ha, zero_mul] | inr hb => rw [hb, mul_zero] /-- info: 'Foam.FInt.add_sub_cancel' does not depend on any axioms -/ #guard_msgs in #print axioms add_sub_cancel /-- info: 'Foam.FInt.add_sub_cancel_left' does not depend on any axioms -/ #guard_msgs in #print axioms add_sub_cancel_left /-- info: 'Foam.FInt.sub_eq_zero_of_le' does not depend on any axioms -/ #guard_msgs in #print axioms sub_eq_zero_of_le /-- info: 'Foam.FInt.subNatNat_of_ge' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_of_ge /-- info: 'Foam.FInt.subNatNat_add_succ' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_add_succ /-- info: 'Foam.FInt.subNatNat_succ_succ' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_succ_succ /-- info: 'Foam.FInt.subNatNat_succ_right' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_succ_right /-- info: 'Foam.FInt.ofNat_succ_add' does not depend on any axioms -/ #guard_msgs in #print axioms ofNat_succ_add /-- info: 'Foam.FInt.zero_add' does not depend on any axioms -/ #guard_msgs in #print axioms zero_add /-- info: 'Foam.FInt.subNatNat_succ_left' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_succ_left /-- info: 'Foam.FInt.subNatNat_add' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_add /-- info: 'Foam.FInt.add_sub_add_left' does not depend on any axioms -/ #guard_msgs in #print axioms add_sub_add_left /-- info: 'Foam.FInt.add_sub_add_right' does not depend on any axioms -/ #guard_msgs in #print axioms add_sub_add_right /-- info: 'Foam.FInt.subNatNat_add_add' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_add_add /-- info: 'Foam.FInt.addComm' does not depend on any axioms -/ #guard_msgs in #print axioms addComm /-- info: 'Foam.FInt.subNatNat_add_ofNat' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_add_ofNat /-- info: 'Foam.FInt.subNatNat_add_negSucc' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_add_negSucc /-- info: 'Foam.FInt.add_assoc' does not depend on any axioms -/ #guard_msgs in #print axioms add_assoc /-- info: 'Foam.FInt.add_right_neg' does not depend on any axioms -/ #guard_msgs in #print axioms add_right_neg /-- info: 'Foam.FInt.add_left_neg' does not depend on any axioms -/ #guard_msgs in #print axioms add_left_neg /-- info: 'Foam.FInt.neg_eq_of_add_eq_zero' does not depend on any axioms -/ #guard_msgs in #print axioms neg_eq_of_add_eq_zero /-- info: 'Foam.FInt.neg_add' does not depend on any axioms -/ #guard_msgs in #print axioms neg_add /-- info: 'Foam.FInt.subNatNat_of_lt' does not depend on any axioms -/ #guard_msgs in #print axioms subNatNat_of_lt /-- info: 'Foam.FInt.mulComm' does not depend on any axioms -/ #guard_msgs in #print axioms mulComm /-- info: 'Foam.FInt.zero_mul' does not depend on any axioms -/ #guard_msgs in #print axioms zero_mul /-- info: 'Foam.FInt.mul_zero' does not depend on any axioms -/ #guard_msgs in #print axioms mul_zero /-- info: 'Foam.FInt.mul_one' does not depend on any axioms -/ #guard_msgs in #print axioms mul_one /-- info: 'Foam.FInt.one_mul' does not depend on any axioms -/ #guard_msgs in #print axioms one_mul /-- info: 'Foam.FInt.neg_mul' does not depend on any axioms -/ #guard_msgs in #print axioms neg_mul /-- info: 'Foam.FInt.mul_neg' does not depend on any axioms -/ #guard_msgs in #print axioms mul_neg /-- info: 'Foam.FInt.nat_mul_sub' does not depend on any axioms -/ #guard_msgs in #print axioms nat_mul_sub /-- info: 'Foam.FInt.ofNat_mul_subNatNat' does not depend on any axioms -/ #guard_msgs in #print axioms ofNat_mul_subNatNat /-- info: 'Foam.FInt.ofNat_mul_ofNat' does not depend on any axioms -/ #guard_msgs in #print axioms ofNat_mul_ofNat /-- info: 'Foam.FInt.ofNat_mul_negSucc' does not depend on any axioms -/ #guard_msgs in #print axioms ofNat_mul_negSucc /-- info: 'Foam.FInt.ofNat_add_neg_ofNat' does not depend on any axioms -/ #guard_msgs in #print axioms ofNat_add_neg_ofNat /-- info: 'Foam.FInt.neg_ofNat_add_ofNat' does not depend on any axioms -/ #guard_msgs in #print axioms neg_ofNat_add_ofNat /-- info: 'Foam.FInt.neg_ofNat_add_neg_ofNat' does not depend on any axioms -/ #guard_msgs in #print axioms neg_ofNat_add_neg_ofNat /-- info: 'Foam.FInt.ofNat_mul_add' does not depend on any axioms -/ #guard_msgs in #print axioms ofNat_mul_add /-- info: 'Foam.FInt.mul_add' does not depend on any axioms -/ #guard_msgs in #print axioms mul_add /-- info: 'Foam.FInt.add_mul' does not depend on any axioms -/ #guard_msgs in #print axioms add_mul /-- info: 'Foam.FInt.nat_mul_assoc' does not depend on any axioms -/ #guard_msgs in #print axioms nat_mul_assoc /-- info: 'Foam.FInt.mul_assoc' does not depend on any axioms -/ #guard_msgs in #print axioms mul_assoc /-- info: 'Foam.FInt.mul_neg_one' does not depend on any axioms -/ #guard_msgs in #print axioms mul_neg_one /-- info: 'Foam.FInt.sub_zero' does not depend on any axioms -/ #guard_msgs in #print axioms sub_zero /-- info: 'Foam.FInt.sub_add_cancel' does not depend on any axioms -/ #guard_msgs in #print axioms sub_add_cancel /-- info: 'Foam.FInt.add_sub_cancel_right' does not depend on any axioms -/ #guard_msgs in #print axioms add_sub_cancel_right /-- info: 'Foam.FInt.neg_sub' does not depend on any axioms -/ #guard_msgs in #print axioms neg_sub /-- info: 'Foam.FInt.mul_sub' does not depend on any axioms -/ #guard_msgs in #print axioms mul_sub /-- info: 'Foam.FInt.sub_mul' does not depend on any axioms -/ #guard_msgs in #print axioms sub_mul /-- info: 'Foam.FInt.sub_sub' does not depend on any axioms -/ #guard_msgs in #print axioms sub_sub /-- info: 'Foam.FInt.two_mul' does not depend on any axioms -/ #guard_msgs in #print axioms two_mul /-- info: 'Foam.FInt.mul_eq_zero' does not depend on any axioms -/ #guard_msgs in #print axioms mul_eq_zero end Foam.FInt