| author | aspinall | 
| Wed, 20 Dec 2006 18:38:27 +0100 | |
| changeset 21889 | 682dbe947862 | 
| parent 21404 | eb85850d3eb7 | 
| child 22027 | e4a08629c4bd | 
| permissions | -rw-r--r-- | 
| 21256 | 1 | (* Title: HOL/GCD.thy | 
| 2 | ID: $Id$ | |
| 3 | Author: Christophe Tabacznyj and Lawrence C Paulson | |
| 4 | Copyright 1996 University of Cambridge | |
| 5 | *) | |
| 6 | ||
| 7 | header {* The Greatest Common Divisor *}
 | |
| 8 | ||
| 9 | theory GCD | |
| 10 | imports Main | |
| 11 | begin | |
| 12 | ||
| 13 | text {*
 | |
| 14 |   See \cite{davenport92}.
 | |
| 15 | \bigskip | |
| 16 | *} | |
| 17 | ||
| 18 | consts | |
| 19 |   gcd  :: "nat \<times> nat => nat"  -- {* Euclid's algorithm *}
 | |
| 20 | ||
| 21 | recdef gcd "measure ((\<lambda>(m, n). n) :: nat \<times> nat => nat)" | |
| 22 | "gcd (m, n) = (if n = 0 then m else gcd (n, m mod n))" | |
| 23 | ||
| 21263 | 24 | definition | 
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21263diff
changeset | 25 |   is_gcd :: "nat => nat => nat => bool" where -- {* @{term gcd} as a relation *}
 | 
| 21263 | 26 | "is_gcd p m n = (p dvd m \<and> p dvd n \<and> | 
| 27 | (\<forall>d. d dvd m \<and> d dvd n --> d dvd p))" | |
| 21256 | 28 | |
| 29 | ||
| 30 | lemma gcd_induct: | |
| 31 | "(!!m. P m 0) ==> | |
| 32 | (!!m n. 0 < n ==> P n (m mod n) ==> P m n) | |
| 33 | ==> P (m::nat) (n::nat)" | |
| 34 | apply (induct m n rule: gcd.induct) | |
| 35 | apply (case_tac "n = 0") | |
| 36 | apply simp_all | |
| 37 | done | |
| 38 | ||
| 39 | ||
| 40 | lemma gcd_0 [simp]: "gcd (m, 0) = m" | |
| 21263 | 41 | by simp | 
| 21256 | 42 | |
| 43 | lemma gcd_non_0: "0 < n ==> gcd (m, n) = gcd (n, m mod n)" | |
| 21263 | 44 | by simp | 
| 21256 | 45 | |
| 46 | declare gcd.simps [simp del] | |
| 47 | ||
| 48 | lemma gcd_1 [simp]: "gcd (m, Suc 0) = 1" | |
| 21263 | 49 | by (simp add: gcd_non_0) | 
| 21256 | 50 | |
| 51 | text {*
 | |
| 52 |   \medskip @{term "gcd (m, n)"} divides @{text m} and @{text n}.  The
 | |
| 53 | conjunctions don't seem provable separately. | |
| 54 | *} | |
| 55 | ||
| 56 | lemma gcd_dvd1 [iff]: "gcd (m, n) dvd m" | |
| 57 | and gcd_dvd2 [iff]: "gcd (m, n) dvd n" | |
| 58 | apply (induct m n rule: gcd_induct) | |
| 21263 | 59 | apply (simp_all add: gcd_non_0) | 
| 21256 | 60 | apply (blast dest: dvd_mod_imp_dvd) | 
| 61 | done | |
| 62 | ||
| 63 | text {*
 | |
| 64 |   \medskip Maximality: for all @{term m}, @{term n}, @{term k}
 | |
| 65 |   naturals, if @{term k} divides @{term m} and @{term k} divides
 | |
| 66 |   @{term n} then @{term k} divides @{term "gcd (m, n)"}.
 | |
| 67 | *} | |
| 68 | ||
| 69 | lemma gcd_greatest: "k dvd m ==> k dvd n ==> k dvd gcd (m, n)" | |
| 21263 | 70 | by (induct m n rule: gcd_induct) (simp_all add: gcd_non_0 dvd_mod) | 
| 21256 | 71 | |
| 72 | lemma gcd_greatest_iff [iff]: "(k dvd gcd (m, n)) = (k dvd m \<and> k dvd n)" | |
| 21263 | 73 | by (blast intro!: gcd_greatest intro: dvd_trans) | 
| 21256 | 74 | |
| 75 | lemma gcd_zero: "(gcd (m, n) = 0) = (m = 0 \<and> n = 0)" | |
| 21263 | 76 | by (simp only: dvd_0_left_iff [symmetric] gcd_greatest_iff) | 
| 21256 | 77 | |
| 78 | ||
| 79 | text {*
 | |
| 80 | \medskip Function gcd yields the Greatest Common Divisor. | |
| 81 | *} | |
| 82 | ||
| 83 | lemma is_gcd: "is_gcd (gcd (m, n)) m n" | |
| 84 | apply (simp add: is_gcd_def gcd_greatest) | |
| 85 | done | |
| 86 | ||
| 87 | text {*
 | |
| 88 | \medskip Uniqueness of GCDs. | |
| 89 | *} | |
| 90 | ||
| 91 | lemma is_gcd_unique: "is_gcd m a b ==> is_gcd n a b ==> m = n" | |
| 92 | apply (simp add: is_gcd_def) | |
| 93 | apply (blast intro: dvd_anti_sym) | |
| 94 | done | |
| 95 | ||
| 96 | lemma is_gcd_dvd: "is_gcd m a b ==> k dvd a ==> k dvd b ==> k dvd m" | |
| 97 | apply (auto simp add: is_gcd_def) | |
| 98 | done | |
| 99 | ||
| 100 | ||
| 101 | text {*
 | |
| 102 | \medskip Commutativity | |
| 103 | *} | |
| 104 | ||
| 105 | lemma is_gcd_commute: "is_gcd k m n = is_gcd k n m" | |
| 106 | apply (auto simp add: is_gcd_def) | |
| 107 | done | |
| 108 | ||
| 109 | lemma gcd_commute: "gcd (m, n) = gcd (n, m)" | |
| 110 | apply (rule is_gcd_unique) | |
| 111 | apply (rule is_gcd) | |
| 112 | apply (subst is_gcd_commute) | |
| 113 | apply (simp add: is_gcd) | |
| 114 | done | |
| 115 | ||
| 116 | lemma gcd_assoc: "gcd (gcd (k, m), n) = gcd (k, gcd (m, n))" | |
| 117 | apply (rule is_gcd_unique) | |
| 118 | apply (rule is_gcd) | |
| 119 | apply (simp add: is_gcd_def) | |
| 120 | apply (blast intro: dvd_trans) | |
| 121 | done | |
| 122 | ||
| 123 | lemma gcd_0_left [simp]: "gcd (0, m) = m" | |
| 124 | apply (simp add: gcd_commute [of 0]) | |
| 125 | done | |
| 126 | ||
| 127 | lemma gcd_1_left [simp]: "gcd (Suc 0, m) = 1" | |
| 128 | apply (simp add: gcd_commute [of "Suc 0"]) | |
| 129 | done | |
| 130 | ||
| 131 | ||
| 132 | text {*
 | |
| 133 | \medskip Multiplication laws | |
| 134 | *} | |
| 135 | ||
| 136 | lemma gcd_mult_distrib2: "k * gcd (m, n) = gcd (k * m, k * n)" | |
| 137 |     -- {* \cite[page 27]{davenport92} *}
 | |
| 138 | apply (induct m n rule: gcd_induct) | |
| 139 | apply simp | |
| 140 | apply (case_tac "k = 0") | |
| 141 | apply (simp_all add: mod_geq gcd_non_0 mod_mult_distrib2) | |
| 142 | done | |
| 143 | ||
| 144 | lemma gcd_mult [simp]: "gcd (k, k * n) = k" | |
| 145 | apply (rule gcd_mult_distrib2 [of k 1 n, simplified, symmetric]) | |
| 146 | done | |
| 147 | ||
| 148 | lemma gcd_self [simp]: "gcd (k, k) = k" | |
| 149 | apply (rule gcd_mult [of k 1, simplified]) | |
| 150 | done | |
| 151 | ||
| 152 | lemma relprime_dvd_mult: "gcd (k, n) = 1 ==> k dvd m * n ==> k dvd m" | |
| 153 | apply (insert gcd_mult_distrib2 [of m k n]) | |
| 154 | apply simp | |
| 155 | apply (erule_tac t = m in ssubst) | |
| 156 | apply simp | |
| 157 | done | |
| 158 | ||
| 159 | lemma relprime_dvd_mult_iff: "gcd (k, n) = 1 ==> (k dvd m * n) = (k dvd m)" | |
| 160 | apply (blast intro: relprime_dvd_mult dvd_trans) | |
| 161 | done | |
| 162 | ||
| 163 | lemma gcd_mult_cancel: "gcd (k, n) = 1 ==> gcd (k * m, n) = gcd (m, n)" | |
| 164 | apply (rule dvd_anti_sym) | |
| 165 | apply (rule gcd_greatest) | |
| 166 | apply (rule_tac n = k in relprime_dvd_mult) | |
| 167 | apply (simp add: gcd_assoc) | |
| 168 | apply (simp add: gcd_commute) | |
| 169 | apply (simp_all add: mult_commute) | |
| 170 | apply (blast intro: dvd_trans) | |
| 171 | done | |
| 172 | ||
| 173 | ||
| 174 | text {* \medskip Addition laws *}
 | |
| 175 | ||
| 176 | lemma gcd_add1 [simp]: "gcd (m + n, n) = gcd (m, n)" | |
| 177 | apply (case_tac "n = 0") | |
| 178 | apply (simp_all add: gcd_non_0) | |
| 179 | done | |
| 180 | ||
| 181 | lemma gcd_add2 [simp]: "gcd (m, m + n) = gcd (m, n)" | |
| 182 | proof - | |
| 183 | have "gcd (m, m + n) = gcd (m + n, m)" by (rule gcd_commute) | |
| 184 | also have "... = gcd (n + m, m)" by (simp add: add_commute) | |
| 185 | also have "... = gcd (n, m)" by simp | |
| 186 | also have "... = gcd (m, n)" by (rule gcd_commute) | |
| 187 | finally show ?thesis . | |
| 188 | qed | |
| 189 | ||
| 190 | lemma gcd_add2' [simp]: "gcd (m, n + m) = gcd (m, n)" | |
| 191 | apply (subst add_commute) | |
| 192 | apply (rule gcd_add2) | |
| 193 | done | |
| 194 | ||
| 195 | lemma gcd_add_mult: "gcd (m, k * m + n) = gcd (m, n)" | |
| 21263 | 196 | by (induct k) (simp_all add: add_assoc) | 
| 21256 | 197 | |
| 198 | end |