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

Commit 5df7cac

Browse files
committed
refactor(data/int/gcd): move int gcd proofs to the GCD theory
1 parent a89f28e commit 5df7cac

File tree

5 files changed

+107
-111
lines changed

5 files changed

+107
-111
lines changed

data/int/basic.lean

Lines changed: 1 addition & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Authors: Jeremy Avigad
55
66
The integers, with addition, multiplication, and subtraction.
77
-/
8-
import data.nat.prime algebra.char_zero algebra.order_functions
8+
import data.nat.basic algebra.char_zero algebra.order_functions
99
open nat
1010

1111
namespace int
@@ -125,23 +125,6 @@ by cases n; refl
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-
145128
theorem neg_succ_of_nat_eq' (m : ℕ) : -[1+ m] = -m - 1 :=
146129
by simp [neg_succ_of_nat_eq]
147130

@@ -613,18 +596,6 @@ begin
613596
exact hdiv }
614597
end
615598

616-
lemma succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul {p : ℕ} (p_prime : nat.prime p) {m n : ℤ} {k l : ℕ}
617-
(hpm : ↑(p ^ k) ∣ m)
618-
(hpn : ↑(p ^ l) ∣ n) (hpmn : ↑(p ^ (k+l+1)) ∣ m*n) : ↑(p ^ (k+1)) ∣ m ∨ ↑(p ^ (l+1)) ∣ n :=
619-
have hpm' : p ^ k ∣ m.nat_abs, from int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpm,
620-
have hpn' : p ^ l ∣ n.nat_abs, from int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpn,
621-
have hpmn' : (p ^ (k+l+1)) ∣ m.nat_abs*n.nat_abs,
622-
by rw ←int.nat_abs_mul; apply (int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpmn),
623-
let hsd := nat.succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul p_prime hpm' hpn' hpmn' in
624-
hsd.elim
625-
(λ hsd1, or.inl begin apply int.dvd_nat_abs.1, apply int.coe_nat_dvd.2 hsd1 end)
626-
(λ hsd2, or.inr begin apply int.dvd_nat_abs.1, apply int.coe_nat_dvd.2 hsd2 end)
627-
628599
/- / and ordering -/
629600

630601
protected theorem div_mul_le (a : ℤ) {b : ℤ} (H : b ≠ 0) : a / b * b ≤ a :=
@@ -1136,57 +1107,3 @@ by simp [abs]
11361107
end cast
11371108

11381109
end int
1139-
1140-
/- extended euclidean algorithm -/
1141-
namespace nat
1142-
1143-
def xgcd_aux : ℕ → ℤ → ℤ → ℕ → ℤ → ℤ → ℕ × ℤ × ℤ
1144-
| 0 s t r' s' t' := (r', s', t')
1145-
| r@(succ _) s t r' s' t' :=
1146-
have r' % r < r, from mod_lt _ $ succ_pos _,
1147-
let q := r' / r in xgcd_aux (r' % r) (s' - q * s) (t' - q * t) r s t
1148-
1149-
@[simp] theorem xgcd_zero_left {s t r' s' t'} : xgcd_aux 0 s t r' s' t' = (r', s', t') :=
1150-
by simp [xgcd_aux]
1151-
1152-
@[simp] theorem xgcd_aux_rec {r s t r' s' t'} (h : 0 < r) : xgcd_aux r s t r' s' t' = xgcd_aux (r' % r) (s' - (r' / r) * s) (t' - (r' / r) * t) r s t :=
1153-
by cases r; [exact absurd h (lt_irrefl _), {simp only [xgcd_aux], refl}]
1154-
1155-
/-- Use the extended GCD algorithm to generate the `a` and `b` values
1156-
satisfying `gcd x y = x * a + y * b`. -/
1157-
def xgcd (x y : ℕ) : ℤ × ℤ := (xgcd_aux x 1 0 y 0 1).2
1158-
1159-
/-- The extended GCD `a` value in the equation `gcd x y = x * a + y * b`. -/
1160-
def gcd_a (x y : ℕ) : ℤ := (xgcd x y).1
1161-
1162-
/-- The extended GCD `b` value in the equation `gcd x y = x * a + y * b`. -/
1163-
def gcd_b (x y : ℕ) : ℤ := (xgcd x y).2
1164-
1165-
@[simp] theorem xgcd_aux_fst (x y) : ∀ s t s' t',
1166-
(xgcd_aux x s t y s' t').1 = gcd x y :=
1167-
gcd.induction x y (by simp) (λ x y h IH s t s' t', by simp [h, IH]; rw ← gcd_rec)
1168-
1169-
theorem xgcd_aux_val (x y) : xgcd_aux x 1 0 y 0 1 = (gcd x y, xgcd x y) :=
1170-
by rw [xgcd, ← xgcd_aux_fst x y 1 0 0 1]; cases xgcd_aux x 1 0 y 0 1; refl
1171-
1172-
theorem xgcd_val (x y) : xgcd x y = (gcd_a x y, gcd_b x y) :=
1173-
by unfold gcd_a gcd_b; cases xgcd x y; refl
1174-
1175-
section
1176-
parameters (a b : ℕ)
1177-
1178-
private def P : ℕ × ℤ × ℤ → Prop | (r, s, t) := (r : ℤ) = a * s + b * t
1179-
1180-
theorem xgcd_aux_P {r r'} : ∀ {s t s' t'}, P (r, s, t) → P (r', s', t') → P (xgcd_aux r s t r' s' t') :=
1181-
gcd.induction r r' (by simp) $ λ x y h IH s t s' t' p p', begin
1182-
rw [xgcd_aux_rec h], refine IH _ p, dsimp [P] at *,
1183-
rw [int.mod_def], generalize : (y / x : ℤ) = k,
1184-
rw [p, p'], simp [mul_add, mul_comm, mul_left_comm]
1185-
end
1186-
1187-
theorem gcd_eq_gcd_ab : (gcd a b : ℤ) = a * gcd_a a b + b * gcd_b a b :=
1188-
by have := @xgcd_aux_P a b a b 1 0 0 1 (by simp [P]) (by simp [P]);
1189-
rwa [xgcd_aux_val, xgcd_val] at this
1190-
end
1191-
1192-
end nat

data/int/gcd.lean

Lines changed: 103 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,101 @@ Copyright (c) 2018 Guy Leroy. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Sangwoo Jo (aka Jason), Guy Leroy
55
6-
Lemmas and extended definitions and properties of gcd and lcm for integers.
6+
Greatest common divisor (gcd) and least common multiple (lcm) for integers.
77
-/
8+
import data.int.basic data.nat.prime
89

9-
import data.int.basic data.nat.basic data.nat.gcd
10+
/- extended euclidean algorithm -/
11+
namespace nat
12+
13+
def xgcd_aux : ℕ → ℤ → ℤ → ℕ → ℤ → ℤ → ℕ × ℤ × ℤ
14+
| 0 s t r' s' t' := (r', s', t')
15+
| r@(succ _) s t r' s' t' :=
16+
have r' % r < r, from mod_lt _ $ succ_pos _,
17+
let q := r' / r in xgcd_aux (r' % r) (s' - q * s) (t' - q * t) r s t
18+
19+
@[simp] theorem xgcd_zero_left {s t r' s' t'} : xgcd_aux 0 s t r' s' t' = (r', s', t') :=
20+
by simp [xgcd_aux]
21+
22+
@[simp] theorem xgcd_aux_rec {r s t r' s' t'} (h : 0 < r) : xgcd_aux r s t r' s' t' = xgcd_aux (r' % r) (s' - (r' / r) * s) (t' - (r' / r) * t) r s t :=
23+
by cases r; [exact absurd h (lt_irrefl _), {simp only [xgcd_aux], refl}]
24+
25+
/-- Use the extended GCD algorithm to generate the `a` and `b` values
26+
satisfying `gcd x y = x * a + y * b`. -/
27+
def xgcd (x y : ℕ) : ℤ × ℤ := (xgcd_aux x 1 0 y 0 1).2
28+
29+
/-- The extended GCD `a` value in the equation `gcd x y = x * a + y * b`. -/
30+
def gcd_a (x y : ℕ) : ℤ := (xgcd x y).1
31+
32+
/-- The extended GCD `b` value in the equation `gcd x y = x * a + y * b`. -/
33+
def gcd_b (x y : ℕ) : ℤ := (xgcd x y).2
34+
35+
@[simp] theorem xgcd_aux_fst (x y) : ∀ s t s' t',
36+
(xgcd_aux x s t y s' t').1 = gcd x y :=
37+
gcd.induction x y (by simp) (λ x y h IH s t s' t', by simp [h, IH]; rw ← gcd_rec)
38+
39+
theorem xgcd_aux_val (x y) : xgcd_aux x 1 0 y 0 1 = (gcd x y, xgcd x y) :=
40+
by rw [xgcd, ← xgcd_aux_fst x y 1 0 0 1]; cases xgcd_aux x 1 0 y 0 1; refl
41+
42+
theorem xgcd_val (x y) : xgcd x y = (gcd_a x y, gcd_b x y) :=
43+
by unfold gcd_a gcd_b; cases xgcd x y; refl
44+
45+
section
46+
parameters (a b : ℕ)
47+
48+
private def P : ℕ × ℤ × ℤ → Prop | (r, s, t) := (r : ℤ) = a * s + b * t
49+
50+
theorem xgcd_aux_P {r r'} : ∀ {s t s' t'}, P (r, s, t) → P (r', s', t') → P (xgcd_aux r s t r' s' t') :=
51+
gcd.induction r r' (by simp) $ λ x y h IH s t s' t' p p', begin
52+
rw [xgcd_aux_rec h], refine IH _ p, dsimp [P] at *,
53+
rw [int.mod_def], generalize : (y / x : ℤ) = k,
54+
rw [p, p'], simp [mul_add, mul_comm, mul_left_comm]
55+
end
56+
57+
theorem gcd_eq_gcd_ab : (gcd a b : ℤ) = a * gcd_a a b + b * gcd_b a b :=
58+
by have := @xgcd_aux_P a b a b 1 0 0 1 (by simp [P]) (by simp [P]);
59+
rwa [xgcd_aux_val, xgcd_val] at this
60+
end
61+
62+
end nat
1063

1164
namespace int
1265

66+
theorem nat_abs_div (a b : ℤ) (H : b ∣ a) : nat_abs (a / b) = (nat_abs a) / (nat_abs b) :=
67+
begin
68+
cases (nat.eq_zero_or_pos (nat_abs b)),
69+
rw eq_zero_of_nat_abs_eq_zero h,
70+
simp,
71+
calc
72+
nat_abs (a / b) = nat_abs (a / b) * 1 : by rw mul_one
73+
... = nat_abs (a / b) * (nat_abs b / nat_abs b) : by rw nat.div_self h
74+
... = nat_abs (a / b) * nat_abs b / nat_abs b : by rw (nat.mul_div_assoc _ (dvd_refl _))
75+
... = nat_abs (a / b * b) / nat_abs b : by rw (nat_abs_mul (a / b) b)
76+
... = nat_abs a / nat_abs b : by rw int.div_mul_cancel H,
77+
end
78+
79+
theorem nat_abs_dvd_abs_iff {i j : ℤ} : i.nat_abs ∣ j.nat_abs ↔ i ∣ j :=
80+
⟨assume (H : i.nat_abs ∣ j.nat_abs), dvd_nat_abs.mp (nat_abs_dvd.mp (coe_nat_dvd.mpr H)),
81+
assume H : (i ∣ j), coe_nat_dvd.mp (dvd_nat_abs.mpr (nat_abs_dvd.mpr H))⟩
82+
83+
lemma succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul {p : ℕ} (p_prime : nat.prime p) {m n : ℤ} {k l : ℕ}
84+
(hpm : ↑(p ^ k) ∣ m)
85+
(hpn : ↑(p ^ l) ∣ n) (hpmn : ↑(p ^ (k+l+1)) ∣ m*n) : ↑(p ^ (k+1)) ∣ m ∨ ↑(p ^ (l+1)) ∣ n :=
86+
have hpm' : p ^ k ∣ m.nat_abs, from int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpm,
87+
have hpn' : p ^ l ∣ n.nat_abs, from int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpn,
88+
have hpmn' : (p ^ (k+l+1)) ∣ m.nat_abs*n.nat_abs,
89+
by rw ←int.nat_abs_mul; apply (int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpmn),
90+
let hsd := nat.succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul p_prime hpm' hpn' hpmn' in
91+
hsd.elim
92+
(λ hsd1, or.inl begin apply int.dvd_nat_abs.1, apply int.coe_nat_dvd.2 hsd1 end)
93+
(λ hsd2, or.inr begin apply int.dvd_nat_abs.1, apply int.coe_nat_dvd.2 hsd2 end)
94+
95+
theorem dvd_of_mul_dvd_mul_left {i j k : ℤ} (k_non_zero : k ≠ 0) (H : k * i ∣ k * j) : i ∣ j :=
96+
dvd.elim H (λl H1, by rw mul_assoc at H1; exact ⟨_, eq_of_mul_eq_mul_left k_non_zero H1⟩)
97+
98+
theorem dvd_of_mul_dvd_mul_right {i j k : ℤ} (k_non_zero : k ≠ 0) (H : i * k ∣ j * k) : i ∣ j :=
99+
by rw [mul_comm i k, mul_comm j k] at H; exact dvd_of_mul_dvd_mul_left k_non_zero H
100+
13101
/- gcd -/
14102

15103
@[simp] theorem gcd_self (i : ℤ) : gcd i i = nat_abs i :=
@@ -20,21 +108,21 @@ by cases i; simp [gcd, mod_self]
20108
@[simp] theorem gcd_zero_right (i : ℤ) : gcd i 0 = nat_abs i :=
21109
by cases i; simp [gcd]
22110

23-
theorem gcd_dvd_left (i j : ℤ) : (gcd i j : ℤ) ∣ i :=
111+
theorem gcd_dvd_left (i j : ℤ) : (gcd i j : ℤ) ∣ i :=
24112
dvd_nat_abs.mp (coe_nat_dvd.mpr (nat.gcd_dvd_left (nat_abs i) (nat_abs j)))
25113

26114
theorem gcd_dvd_right (i j : ℤ) : (gcd i j : ℤ) ∣ j :=
27115
dvd_nat_abs.mp (coe_nat_dvd.mpr (nat.gcd_dvd_right (nat_abs i) (nat_abs j)))
28116

29-
theorem gcd_dvd (i j : ℤ) : ((gcd i j : ℤ) ∣ i) ∧ ((gcd i j : ℤ) ∣ j) :=
117+
theorem gcd_dvd (i j : ℤ) : ((gcd i j : ℤ) ∣ i) ∧ ((gcd i j : ℤ) ∣ j) :=
30118
⟨gcd_dvd_left i j, gcd_dvd_right i j⟩
31119

32120
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)
121+
by intros H1 H2;
122+
exact nat_abs_dvd.mp (coe_nat_dvd.mpr (nat.dvd_gcd (nat_abs_dvd_abs_iff.mpr H1)
35123
(nat_abs_dvd_abs_iff.mpr H2)))
36124

37-
theorem gcd_comm (i j : ℤ) : gcd i j = gcd j i :=
125+
theorem gcd_comm (i j : ℤ) : gcd i j = gcd j i :=
38126
nat.gcd_comm (nat_abs i) (nat_abs j)
39127

40128
theorem gcd_assoc (i j k : ℤ) : gcd (gcd i j) k = gcd i (gcd j k) :=
@@ -46,11 +134,11 @@ nat.gcd_assoc (nat_abs i) (nat_abs j) (nat_abs k)
46134
eq.trans (gcd_comm i 1) $ gcd_one_left i
47135

48136
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];
137+
by rw [gcd, nat_abs_mul, nat_abs_mul];
50138
exact nat.gcd_mul_left (nat_abs i) (nat_abs j) (nat_abs k)
51139

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];
140+
theorem gcd_mul_right (i j k : ℤ) : gcd (i * j) (k * j) = gcd i k * nat_abs j :=
141+
by rw [gcd, nat_abs_mul, nat_abs_mul];
54142
exact nat.gcd_mul_right (nat_abs i) (nat_abs j) (nat_abs k)
55143

56144
theorem gcd_pos_of_non_zero_left {i : ℤ} (j : ℤ) (i_non_zero : i ≠ 0) : gcd i j > 0 :=
@@ -113,15 +201,15 @@ theorem lcm_zero_right (i : ℤ) : lcm i 0 = 0 := lcm_comm 0 i ▸ lcm_zero_left
113201
theorem lcm_one_left (i : ℤ) : lcm 1 i = nat_abs i :=
114202
by rw [lcm, one_mul, gcd_one_left, nat.div_one]
115203

116-
theorem lcm_one_right (i : ℤ) : lcm i 1 = nat_abs i :=
204+
theorem lcm_one_right (i : ℤ) : lcm i 1 = nat_abs i :=
117205
by unfold lcm; simp
118206

119207
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];
208+
by rw [lcm, gcd_self, nat_abs_mul, nat.mul_div_assoc, mul_comm, nat.div_mul_cancel];
121209
simp; simp
122210

123211
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))
212+
nat_abs_dvd.mp (coe_nat_dvd.mpr (eq.subst (eq.symm (lcm_def i j))
125213
(nat.dvd_lcm_left (nat_abs i) (nat_abs j))))
126214

127215
theorem dvd_lcm_right (i j : ℤ) : j ∣ lcm i j :=
@@ -130,26 +218,17 @@ lcm_comm j i ▸ dvd_lcm_left j i
130218
theorem gcd_mul_lcm (i j : ℤ) : gcd i j * lcm i j = nat_abs (i * j) :=
131219
begin
132220
rw [lcm, mul_comm, nat.div_mul_cancel],
133-
exact eq.subst (eq.symm (nat_abs_mul i j))
221+
exact eq.subst (eq.symm (nat_abs_mul i j))
134222
(dvd_mul_of_dvd_left (coe_nat_dvd.mp (dvd_nat_abs.mpr (gcd_dvd_left i j))) _),
135223
end
136224

137225
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))
226+
dvd_nat_abs.mp (coe_nat_dvd.mpr (eq.subst (eq.symm (lcm_def i j))
139227
(nat.lcm_dvd (nat_abs_dvd_abs_iff.mpr H1)
140228
(nat_abs_dvd_abs_iff.mpr H2))))
141229

142230
theorem lcm_assoc (i j k : ℤ) : lcm (lcm i j) k = lcm i (lcm j k) :=
143231
by rw [lcm_def, lcm_def, lcm_def, lcm_def];
144232
exact nat.lcm_assoc (nat_abs i) (nat_abs j) (nat_abs k)
145233

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-
155234
end int

data/nat/modeq.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Authors: Mario Carneiro
55
66
Modular equality relation.
77
-/
8-
import data.int.basic data.nat.gcd
8+
import data.int.gcd
99

1010
namespace nat
1111

data/padics/padic_norm.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Authors: Robert Y. Lewis
66
Define the p-adic valuation on ℤ and ℚ, and the p-adic norm on ℚ
77
-/
88

9-
import data.rat data.int.basic algebra.field_power
9+
import data.rat data.int.gcd algebra.field_power
1010
import tactic.wlog tactic.ring
1111

1212
universe u

data/zmod.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Author: Chris Hughes
55
-/
6-
import data.int.modeq data.fintype data.nat.prime data.nat.gcd data.pnat
6+
import data.int.modeq data.int.gcd data.fintype data.pnat
77

88
open nat nat.modeq int
99

0 commit comments

Comments
 (0)