Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit a89f28e

Browse files
gml16johoelzl
authored andcommitted
feat(data/int/gcd): extended gcd to integers (#218)
Resurrected by @johoelzl. The original commit was not available anymore.
1 parent ee9bf5c commit a89f28e

File tree

2 files changed

+173
-1
lines changed

2 files changed

+173
-1
lines changed

data/int/basic.lean

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,29 @@ begin
119119
try {refl}; [skip, rw add_comm a b]; apply this
120120
end
121121

122-
theorem nat_abs_neg_of_nat (n : nat) : nat_abs (neg_of_nat n) = n :=
122+
theorem nat_abs_neg_of_nat (n : ) : nat_abs (neg_of_nat n) = n :=
123123
by cases n; refl
124124

125125
theorem nat_abs_mul (a b : ℤ) : nat_abs (a * b) = (nat_abs a) * (nat_abs b) :=
126126
by cases a; cases b; simp [(*), int.mul, nat_abs_neg_of_nat]
127127

128+
theorem nat_abs_div (a b : ℤ) (H : b ∣ a) : nat_abs (a / b) = (nat_abs a) / (nat_abs b) :=
129+
begin
130+
cases (nat.eq_zero_or_pos (nat_abs b)),
131+
rw eq_zero_of_nat_abs_eq_zero h,
132+
simp,
133+
calc
134+
nat_abs (a / b) = nat_abs (a / b) * 1 : by rw mul_one
135+
... = nat_abs (a / b) * (nat_abs b / nat_abs b) : by rw nat.div_self h
136+
... = nat_abs (a / b) * nat_abs b / nat_abs b : by rw (nat.mul_div_assoc _ (dvd_refl _))
137+
... = nat_abs (a / b * b) / nat_abs b : by rw (nat_abs_mul (a / b) b)
138+
... = nat_abs a / nat_abs b : by rw int.div_mul_cancel H,
139+
end
140+
141+
theorem nat_abs_dvd_abs_iff {i j : ℤ} : i.nat_abs ∣ j.nat_abs ↔ i ∣ j :=
142+
⟨assume (H : i.nat_abs ∣ j.nat_abs), dvd_nat_abs.mp (nat_abs_dvd.mp (coe_nat_dvd.mpr H)),
143+
assume H : (i ∣ j), coe_nat_dvd.mp (dvd_nat_abs.mpr (nat_abs_dvd.mpr H))⟩
144+
128145
theorem neg_succ_of_nat_eq' (m : ℕ) : -[1+ m] = -m - 1 :=
129146
by simp [neg_succ_of_nat_eq]
130147

data/int/gcd.lean

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/-
2+
Copyright (c) 2018 Guy Leroy. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Sangwoo Jo (aka Jason), Guy Leroy
5+
6+
Lemmas and extended definitions and properties of gcd and lcm for integers.
7+
-/
8+
9+
import data.int.basic data.nat.basic data.nat.gcd
10+
11+
namespace int
12+
13+
/- gcd -/
14+
15+
@[simp] theorem gcd_self (i : ℤ) : gcd i i = nat_abs i :=
16+
by cases i; simp [gcd, mod_self]
17+
18+
@[simp] theorem gcd_zero_left (i : ℤ) : gcd 0 i = nat_abs i := by simp [gcd]
19+
20+
@[simp] theorem gcd_zero_right (i : ℤ) : gcd i 0 = nat_abs i :=
21+
by cases i; simp [gcd]
22+
23+
theorem gcd_dvd_left (i j : ℤ) : (gcd i j : ℤ) ∣ i :=
24+
dvd_nat_abs.mp (coe_nat_dvd.mpr (nat.gcd_dvd_left (nat_abs i) (nat_abs j)))
25+
26+
theorem gcd_dvd_right (i j : ℤ) : (gcd i j : ℤ) ∣ j :=
27+
dvd_nat_abs.mp (coe_nat_dvd.mpr (nat.gcd_dvd_right (nat_abs i) (nat_abs j)))
28+
29+
theorem gcd_dvd (i j : ℤ) : ((gcd i j : ℤ) ∣ i) ∧ ((gcd i j : ℤ) ∣ j) :=
30+
⟨gcd_dvd_left i j, gcd_dvd_right i j⟩
31+
32+
theorem dvd_gcd {i j k : ℤ} : k ∣ i → k ∣ j → k ∣ gcd i j :=
33+
by intros H1 H2;
34+
exact nat_abs_dvd.mp (coe_nat_dvd.mpr (nat.dvd_gcd (nat_abs_dvd_abs_iff.mpr H1)
35+
(nat_abs_dvd_abs_iff.mpr H2)))
36+
37+
theorem gcd_comm (i j : ℤ) : gcd i j = gcd j i :=
38+
nat.gcd_comm (nat_abs i) (nat_abs j)
39+
40+
theorem gcd_assoc (i j k : ℤ) : gcd (gcd i j) k = gcd i (gcd j k) :=
41+
nat.gcd_assoc (nat_abs i) (nat_abs j) (nat_abs k)
42+
43+
@[simp] theorem gcd_one_left (i : ℤ) : gcd 1 i = 1 := nat.gcd_one_left _
44+
45+
@[simp] theorem gcd_one_right (i : ℤ) : gcd i 1 = 1 :=
46+
eq.trans (gcd_comm i 1) $ gcd_one_left i
47+
48+
theorem gcd_mul_left (i j k : ℤ) : gcd (i * j) (i * k) = nat_abs i * gcd j k :=
49+
by rw [gcd, nat_abs_mul, nat_abs_mul];
50+
exact nat.gcd_mul_left (nat_abs i) (nat_abs j) (nat_abs k)
51+
52+
theorem gcd_mul_right (i j k : ℤ) : gcd (i * j) (k * j) = gcd i k * nat_abs j :=
53+
by rw [gcd, nat_abs_mul, nat_abs_mul];
54+
exact nat.gcd_mul_right (nat_abs i) (nat_abs j) (nat_abs k)
55+
56+
theorem gcd_pos_of_non_zero_left {i : ℤ} (j : ℤ) (i_non_zero : i ≠ 0) : gcd i j > 0 :=
57+
nat.gcd_pos_of_pos_left (nat_abs j) (nat_abs_pos_of_ne_zero i_non_zero)
58+
59+
theorem gcd_pos_of_non_zero_right (i : ℤ) {j : ℤ} (j_non_zero : j ≠ 0) : gcd i j > 0 :=
60+
nat.gcd_pos_of_pos_right (nat_abs i) (nat_abs_pos_of_ne_zero j_non_zero)
61+
62+
theorem eq_zero_of_gcd_eq_zero_left {i j : ℤ} (H : gcd i j = 0) : i = 0 :=
63+
eq_zero_of_nat_abs_eq_zero (nat.eq_zero_of_gcd_eq_zero_left H)
64+
65+
theorem eq_zero_of_gcd_eq_zero_right {i j : ℤ} (H : gcd i j = 0) : j = 0 :=
66+
eq_zero_of_nat_abs_eq_zero (nat.eq_zero_of_gcd_eq_zero_right H)
67+
68+
theorem gcd_div {i j k : ℤ} (H1 : k ∣ i) (H2 : k ∣ j) :
69+
gcd (i / k) (j / k) = gcd i j / nat_abs k :=
70+
by rw [gcd, nat_abs_div i k H1, nat_abs_div j k H2];
71+
exact nat.gcd_div (nat_abs_dvd_abs_iff.mpr H1) (nat_abs_dvd_abs_iff.mpr H2)
72+
73+
theorem gcd_dvd_gcd_of_dvd_left {i k : ℤ} (j : ℤ) (H : i ∣ k) : gcd i j ∣ gcd k j :=
74+
int.coe_nat_dvd.1 $ dvd_gcd (dvd.trans (gcd_dvd_left i j) H) (gcd_dvd_right i j)
75+
76+
theorem gcd_dvd_gcd_of_dvd_right {i k : ℤ} (j : ℤ) (H : i ∣ k) : gcd j i ∣ gcd j k :=
77+
int.coe_nat_dvd.1 $ dvd_gcd (gcd_dvd_left j i) (dvd.trans (gcd_dvd_right j i) H)
78+
79+
theorem gcd_dvd_gcd_mul_left (i j k : ℤ) : gcd i j ∣ gcd (k * i) j :=
80+
gcd_dvd_gcd_of_dvd_left _ (dvd_mul_left _ _)
81+
82+
theorem gcd_dvd_gcd_mul_right (i j k : ℤ) : gcd i j ∣ gcd (i * k) j :=
83+
gcd_dvd_gcd_of_dvd_left _ (dvd_mul_right _ _)
84+
85+
theorem gcd_dvd_gcd_mul_left_right (i j k : ℤ) : gcd i j ∣ gcd i (k * j) :=
86+
gcd_dvd_gcd_of_dvd_right _ (dvd_mul_left _ _)
87+
88+
theorem gcd_dvd_gcd_mul_right_right (i j k : ℤ) : gcd i j ∣ gcd i (j * k) :=
89+
gcd_dvd_gcd_of_dvd_right _ (dvd_mul_right _ _)
90+
91+
theorem gcd_eq_left {i j : ℤ} (H : i ∣ j) : gcd i j = nat_abs i :=
92+
nat.dvd_antisymm (by unfold gcd; exact nat.gcd_dvd_left _ _)
93+
(by unfold gcd; exact nat.dvd_gcd (dvd_refl _) (nat_abs_dvd_abs_iff.mpr H))
94+
95+
theorem gcd_eq_right {i j : ℤ} (H : j ∣ i) : gcd i j = nat_abs j :=
96+
by rw [gcd_comm, gcd_eq_left H]
97+
98+
/- lcm -/
99+
100+
def lcm (i j : ℤ) : ℕ := nat_abs(i * j) / (gcd i j)
101+
102+
theorem lcm_def (i j : ℤ) : lcm i j = nat.lcm (nat_abs i) (nat_abs j) :=
103+
by rw [lcm, nat.lcm, gcd, nat_abs_mul]
104+
105+
theorem lcm_comm (i j : ℤ) : lcm i j = lcm j i :=
106+
by delta lcm; rw [mul_comm, gcd_comm]
107+
108+
theorem lcm_zero_left (i : ℤ) : lcm 0 i = 0 :=
109+
by rw [lcm, zero_mul, gcd_zero_left]; by simp
110+
111+
theorem lcm_zero_right (i : ℤ) : lcm i 0 = 0 := lcm_comm 0 i ▸ lcm_zero_left i
112+
113+
theorem lcm_one_left (i : ℤ) : lcm 1 i = nat_abs i :=
114+
by rw [lcm, one_mul, gcd_one_left, nat.div_one]
115+
116+
theorem lcm_one_right (i : ℤ) : lcm i 1 = nat_abs i :=
117+
by unfold lcm; simp
118+
119+
theorem lcm_self (i : ℤ) : lcm i i = nat_abs i :=
120+
by rw [lcm, gcd_self, nat_abs_mul, nat.mul_div_assoc, mul_comm, nat.div_mul_cancel];
121+
simp; simp
122+
123+
theorem dvd_lcm_left (i j : ℤ) : i ∣ lcm i j :=
124+
nat_abs_dvd.mp (coe_nat_dvd.mpr (eq.subst (eq.symm (lcm_def i j))
125+
(nat.dvd_lcm_left (nat_abs i) (nat_abs j))))
126+
127+
theorem dvd_lcm_right (i j : ℤ) : j ∣ lcm i j :=
128+
lcm_comm j i ▸ dvd_lcm_left j i
129+
130+
theorem gcd_mul_lcm (i j : ℤ) : gcd i j * lcm i j = nat_abs (i * j) :=
131+
begin
132+
rw [lcm, mul_comm, nat.div_mul_cancel],
133+
exact eq.subst (eq.symm (nat_abs_mul i j))
134+
(dvd_mul_of_dvd_left (coe_nat_dvd.mp (dvd_nat_abs.mpr (gcd_dvd_left i j))) _),
135+
end
136+
137+
theorem lcm_dvd {i j k : ℤ} (H1 : i ∣ k) (H2 : j ∣ k) : (lcm i j : ℤ) ∣ k :=
138+
dvd_nat_abs.mp (coe_nat_dvd.mpr (eq.subst (eq.symm (lcm_def i j))
139+
(nat.lcm_dvd (nat_abs_dvd_abs_iff.mpr H1)
140+
(nat_abs_dvd_abs_iff.mpr H2))))
141+
142+
theorem lcm_assoc (i j k : ℤ) : lcm (lcm i j) k = lcm i (lcm j k) :=
143+
by rw [lcm_def, lcm_def, lcm_def, lcm_def];
144+
exact nat.lcm_assoc (nat_abs i) (nat_abs j) (nat_abs k)
145+
146+
/- lemmas -/
147+
148+
theorem dvd_of_mul_dvd_mul_left {i j k : ℤ} (k_non_zero : k ≠ 0) (H : k * i ∣ k * j) : i ∣ j :=
149+
dvd.elim H (λl H1, by rw mul_assoc at H1; exact ⟨_, eq_of_mul_eq_mul_left k_non_zero H1⟩)
150+
151+
theorem dvd_of_mul_dvd_mul_right {i j k : ℤ} (k_non_zero : k ≠ 0) (H : i * k ∣ j * k) : i ∣ j :=
152+
by rw [mul_comm i k, mul_comm j k] at H; exact dvd_of_mul_dvd_mul_left k_non_zero H
153+
154+
155+
end int

0 commit comments

Comments
 (0)