1
1
/-
2
2
Copyright (c) 2018 Guy Leroy. All rights reserved.
3
3
Released under Apache 2.0 license as described in the file LICENSE.
4
- Authors: Sangwoo Jo (aka Jason), Guy Leroy, Johannes Hölzl
4
+ Authors: Sangwoo Jo (aka Jason), Guy Leroy, Johannes Hölzl, Mario Carneiro
5
+ -/
6
+ import data.int.basic data.nat.prime
7
+ /-!
8
+ # Extended GCD and divisibility over ℤ
9
+
10
+ ## Main definitions
11
+
12
+ * Given `x y : ℕ`, `xgcd x y` computes the pair of integers `(a, b)` such that
13
+ `gcd x y = x * a + y * b`. `gcd_a x y` and `gcd_b x y` are defined to be `a` and `b`,
14
+ respectively.
5
15
6
- Greatest common divisor (gcd) and least common multiple (lcm) for integers.
16
+ ## Main statements
17
+
18
+ * `gcd_eq_gcd_ab`: Bézout's lemma, given `x y : ℕ`, `gcd x y = x * gcd_a x y + y * gcd_b x y`.
7
19
8
- This sets up ℤ to be a GCD domain, and introduces rules about `int.gcd`, as well as `int.lcm`.
9
- NOTE: If you add rules to this theory, check that the corresponding rules are available for
10
- `gcd_domain`.
11
20
-/
12
- import data.int.basic data.nat.prime
13
21
14
- /- Extended Euclidean algorithm -/
22
+ /-! ### Extended Euclidean algorithm -/
15
23
namespace nat
16
24
25
+ /-- Helper function for the extended GCD algorithm (`nat.xgcd`). -/
17
26
def xgcd_aux : ℕ → ℤ → ℤ → ℕ → ℤ → ℤ → ℕ × ℤ × ℤ
18
27
| 0 s t r' s' t' := (r', s', t')
19
28
| r@(succ _) s t r' s' t' :=
@@ -23,7 +32,8 @@ def xgcd_aux : ℕ → ℤ → ℤ → ℕ → ℤ → ℤ → ℕ × ℤ × ℤ
23
32
@[simp] theorem xgcd_zero_left {s t r' s' t'} : xgcd_aux 0 s t r' s' t' = (r', s', t') :=
24
33
by simp [xgcd_aux]
25
34
26
- @[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 :=
35
+ @[simp] theorem xgcd_aux_rec {r s t r' s' t'} (h : 0 < r) :
36
+ xgcd_aux r s t r' s' t' = xgcd_aux (r' % r) (s' - (r' / r) * s) (t' - (r' / r) * t) r s t :=
27
37
by cases r; [exact absurd h (lt_irrefl _), {simp only [xgcd_aux], refl}]
28
38
29
39
/-- Use the extended GCD algorithm to generate the `a` and `b` values
@@ -47,25 +57,31 @@ theorem xgcd_val (x y) : xgcd x y = (gcd_a x y, gcd_b x y) :=
47
57
by unfold gcd_a gcd_b; cases xgcd x y; refl
48
58
49
59
section
50
- parameters (a b : ℕ)
60
+ parameters (x y : ℕ)
51
61
52
- private def P : ℕ × ℤ × ℤ → Prop | (r, s, t) := (r : ℤ) = a * s + b * t
62
+ private def P : ℕ × ℤ × ℤ → Prop
63
+ | (r, s, t) := (r : ℤ) = x * s + y * t
53
64
54
- 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') :=
55
- gcd.induction r r' (by simp) $ λ x y h IH s t s' t' p p', begin
65
+ theorem xgcd_aux_P {r r'} : ∀ {s t s' t'}, P (r, s, t) → P (r', s', t') →
66
+ P (xgcd_aux r s t r' s' t') :=
67
+ gcd.induction r r' (by simp) $ λ a b h IH s t s' t' p p', begin
56
68
rw [xgcd_aux_rec h], refine IH _ p, dsimp [P] at *,
57
- rw [int.mod_def], generalize : (y / x : ℤ) = k,
69
+ rw [int.mod_def], generalize : (b / a : ℤ) = k,
58
70
rw [p, p'],
59
71
simp [mul_add, mul_comm, mul_left_comm, add_comm, add_left_comm, sub_eq_neg_add]
60
72
end
61
73
62
- theorem gcd_eq_gcd_ab : (gcd a b : ℤ) = a * gcd_a a b + b * gcd_b a b :=
63
- by have := @xgcd_aux_P a b a b 1 0 0 1 (by simp [P]) (by simp [P]);
74
+ /-- Bézout's lemma: given `x y : ℕ`, `gcd x y = x * a + y * b`, where `a = gcd_a x y` and
75
+ `b = gcd_b x y` are computed by the extended Euclidean algorithm.
76
+ -/
77
+ theorem gcd_eq_gcd_ab : (gcd x y : ℤ) = x * gcd_a x y + y * gcd_b x y :=
78
+ by have := @xgcd_aux_P x y x y 1 0 0 1 (by simp [P]) (by simp [P]);
64
79
rwa [xgcd_aux_val, xgcd_val] at this
65
80
end
66
81
67
82
end nat
68
83
84
+ /-! ### Divisibility over ℤ -/
69
85
namespace int
70
86
71
87
theorem nat_abs_div (a b : ℤ) (H : b ∣ a) : nat_abs (a / b) = (nat_abs a) / (nat_abs b) :=
0 commit comments