1 (* Title: HOL/Old_Number_Theory/Legacy_GCD.thy |
1 (* Title: HOL/Old_Number_Theory/Legacy_GCD.thy |
2 Author: Christophe Tabacznyj and Lawrence C Paulson |
2 Author: Christophe Tabacznyj and Lawrence C Paulson |
3 Copyright 1996 University of Cambridge |
3 Copyright 1996 University of Cambridge |
4 *) |
4 *) |
5 |
5 |
6 section {* The Greatest Common Divisor *} |
6 section \<open>The Greatest Common Divisor\<close> |
7 |
7 |
8 theory Legacy_GCD |
8 theory Legacy_GCD |
9 imports Main |
9 imports Main |
10 begin |
10 begin |
11 |
11 |
12 text {* |
12 text \<open> |
13 See @{cite davenport92}. \bigskip |
13 See @{cite davenport92}. \bigskip |
14 *} |
14 \<close> |
15 |
15 |
16 subsection {* Specification of GCD on nats *} |
16 subsection \<open>Specification of GCD on nats\<close> |
17 |
17 |
18 definition |
18 definition |
19 is_gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where -- {* @{term gcd} as a relation *} |
19 is_gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where -- \<open>@{term gcd} as a relation\<close> |
20 "is_gcd m n p \<longleftrightarrow> p dvd m \<and> p dvd n \<and> |
20 "is_gcd m n p \<longleftrightarrow> p dvd m \<and> p dvd n \<and> |
21 (\<forall>d. d dvd m \<longrightarrow> d dvd n \<longrightarrow> d dvd p)" |
21 (\<forall>d. d dvd m \<longrightarrow> d dvd n \<longrightarrow> d dvd p)" |
22 |
22 |
23 text {* Uniqueness *} |
23 text \<open>Uniqueness\<close> |
24 |
24 |
25 lemma is_gcd_unique: "is_gcd a b m \<Longrightarrow> is_gcd a b n \<Longrightarrow> m = n" |
25 lemma is_gcd_unique: "is_gcd a b m \<Longrightarrow> is_gcd a b n \<Longrightarrow> m = n" |
26 by (simp add: is_gcd_def) (blast intro: dvd_antisym) |
26 by (simp add: is_gcd_def) (blast intro: dvd_antisym) |
27 |
27 |
28 text {* Connection to divides relation *} |
28 text \<open>Connection to divides relation\<close> |
29 |
29 |
30 lemma is_gcd_dvd: "is_gcd a b m \<Longrightarrow> k dvd a \<Longrightarrow> k dvd b \<Longrightarrow> k dvd m" |
30 lemma is_gcd_dvd: "is_gcd a b m \<Longrightarrow> k dvd a \<Longrightarrow> k dvd b \<Longrightarrow> k dvd m" |
31 by (auto simp add: is_gcd_def) |
31 by (auto simp add: is_gcd_def) |
32 |
32 |
33 text {* Commutativity *} |
33 text \<open>Commutativity\<close> |
34 |
34 |
35 lemma is_gcd_commute: "is_gcd m n k = is_gcd n m k" |
35 lemma is_gcd_commute: "is_gcd m n k = is_gcd n m k" |
36 by (auto simp add: is_gcd_def) |
36 by (auto simp add: is_gcd_def) |
37 |
37 |
38 |
38 |
39 subsection {* GCD on nat by Euclid's algorithm *} |
39 subsection \<open>GCD on nat by Euclid's algorithm\<close> |
40 |
40 |
41 fun gcd :: "nat => nat => nat" |
41 fun gcd :: "nat => nat => nat" |
42 where "gcd m n = (if n = 0 then m else gcd n (m mod n))" |
42 where "gcd m n = (if n = 0 then m else gcd n (m mod n))" |
43 |
43 |
44 lemma gcd_induct [case_names "0" rec]: |
44 lemma gcd_induct [case_names "0" rec]: |
66 lemma nat_gcd_1_right [simp, algebra]: "gcd m 1 = 1" |
66 lemma nat_gcd_1_right [simp, algebra]: "gcd m 1 = 1" |
67 unfolding One_nat_def by (rule gcd_1) |
67 unfolding One_nat_def by (rule gcd_1) |
68 |
68 |
69 declare gcd.simps [simp del] |
69 declare gcd.simps [simp del] |
70 |
70 |
71 text {* |
71 text \<open> |
72 \medskip @{term "gcd m n"} divides @{text m} and @{text n}. The |
72 \medskip @{term "gcd m n"} divides @{text m} and @{text n}. The |
73 conjunctions don't seem provable separately. |
73 conjunctions don't seem provable separately. |
74 *} |
74 \<close> |
75 |
75 |
76 lemma gcd_dvd1 [iff, algebra]: "gcd m n dvd m" |
76 lemma gcd_dvd1 [iff, algebra]: "gcd m n dvd m" |
77 and gcd_dvd2 [iff, algebra]: "gcd m n dvd n" |
77 and gcd_dvd2 [iff, algebra]: "gcd m n dvd n" |
78 apply (induct m n rule: gcd_induct) |
78 apply (induct m n rule: gcd_induct) |
79 apply (simp_all add: gcd_non_0) |
79 apply (simp_all add: gcd_non_0) |
80 apply (blast dest: dvd_mod_imp_dvd) |
80 apply (blast dest: dvd_mod_imp_dvd) |
81 done |
81 done |
82 |
82 |
83 text {* |
83 text \<open> |
84 \medskip Maximality: for all @{term m}, @{term n}, @{term k} |
84 \medskip Maximality: for all @{term m}, @{term n}, @{term k} |
85 naturals, if @{term k} divides @{term m} and @{term k} divides |
85 naturals, if @{term k} divides @{term m} and @{term k} divides |
86 @{term n} then @{term k} divides @{term "gcd m n"}. |
86 @{term n} then @{term k} divides @{term "gcd m n"}. |
87 *} |
87 \<close> |
88 |
88 |
89 lemma gcd_greatest: "k dvd m \<Longrightarrow> k dvd n \<Longrightarrow> k dvd gcd m n" |
89 lemma gcd_greatest: "k dvd m \<Longrightarrow> k dvd n \<Longrightarrow> k dvd gcd m n" |
90 by (induct m n rule: gcd_induct) (simp_all add: gcd_non_0 dvd_mod) |
90 by (induct m n rule: gcd_induct) (simp_all add: gcd_non_0 dvd_mod) |
91 |
91 |
92 text {* |
92 text \<open> |
93 \medskip Function gcd yields the Greatest Common Divisor. |
93 \medskip Function gcd yields the Greatest Common Divisor. |
94 *} |
94 \<close> |
95 |
95 |
96 lemma is_gcd: "is_gcd m n (gcd m n) " |
96 lemma is_gcd: "is_gcd m n (gcd m n) " |
97 by (simp add: is_gcd_def gcd_greatest) |
97 by (simp add: is_gcd_def gcd_greatest) |
98 |
98 |
99 |
99 |
100 subsection {* Derived laws for GCD *} |
100 subsection \<open>Derived laws for GCD\<close> |
101 |
101 |
102 lemma gcd_greatest_iff [iff, algebra]: "k dvd gcd m n \<longleftrightarrow> k dvd m \<and> k dvd n" |
102 lemma gcd_greatest_iff [iff, algebra]: "k dvd gcd m n \<longleftrightarrow> k dvd m \<and> k dvd n" |
103 by (blast intro!: gcd_greatest intro: dvd_trans) |
103 by (blast intro!: gcd_greatest intro: dvd_trans) |
104 |
104 |
105 lemma gcd_zero[algebra]: "gcd m n = 0 \<longleftrightarrow> m = 0 \<and> n = 0" |
105 lemma gcd_zero[algebra]: "gcd m n = 0 \<longleftrightarrow> m = 0 \<and> n = 0" |
123 by (simp add: gcd_commute) |
123 by (simp add: gcd_commute) |
124 |
124 |
125 lemma nat_gcd_1_left [simp, algebra]: "gcd 1 m = 1" |
125 lemma nat_gcd_1_left [simp, algebra]: "gcd 1 m = 1" |
126 unfolding One_nat_def by (rule gcd_1_left) |
126 unfolding One_nat_def by (rule gcd_1_left) |
127 |
127 |
128 text {* |
128 text \<open> |
129 \medskip Multiplication laws |
129 \medskip Multiplication laws |
130 *} |
130 \<close> |
131 |
131 |
132 lemma gcd_mult_distrib2: "k * gcd m n = gcd (k * m) (k * n)" |
132 lemma gcd_mult_distrib2: "k * gcd m n = gcd (k * m) (k * n)" |
133 -- {* @{cite \<open>page 27\<close> davenport92} *} |
133 -- \<open>@{cite \<open>page 27\<close> davenport92}\<close> |
134 apply (induct m n rule: gcd_induct) |
134 apply (induct m n rule: gcd_induct) |
135 apply simp |
135 apply simp |
136 apply (case_tac "k = 0") |
136 apply (case_tac "k = 0") |
137 apply (simp_all add: gcd_non_0) |
137 apply (simp_all add: gcd_non_0) |
138 done |
138 done |
163 apply (simp add: gcd_commute) |
163 apply (simp add: gcd_commute) |
164 apply (simp_all add: mult.commute) |
164 apply (simp_all add: mult.commute) |
165 done |
165 done |
166 |
166 |
167 |
167 |
168 text {* \medskip Addition laws *} |
168 text \<open>\medskip Addition laws\<close> |
169 |
169 |
170 lemma gcd_add1 [simp, algebra]: "gcd (m + n) n = gcd m n" |
170 lemma gcd_add1 [simp, algebra]: "gcd (m + n) n = gcd m n" |
171 by (cases "n = 0") (auto simp add: gcd_non_0) |
171 by (cases "n = 0") (auto simp add: gcd_non_0) |
172 |
172 |
173 lemma gcd_add2 [simp, algebra]: "gcd m (m + n) = gcd m n" |
173 lemma gcd_add2 [simp, algebra]: "gcd m (m + n) = gcd m n" |
188 by (induct k) (simp_all add: add.assoc) |
188 by (induct k) (simp_all add: add.assoc) |
189 |
189 |
190 lemma gcd_dvd_prod: "gcd m n dvd m * n" |
190 lemma gcd_dvd_prod: "gcd m n dvd m * n" |
191 using mult_dvd_mono [of 1] by auto |
191 using mult_dvd_mono [of 1] by auto |
192 |
192 |
193 text {* |
193 text \<open> |
194 \medskip Division by gcd yields rrelatively primes. |
194 \medskip Division by gcd yields rrelatively primes. |
195 *} |
195 \<close> |
196 |
196 |
197 lemma div_gcd_relprime: |
197 lemma div_gcd_relprime: |
198 assumes nz: "a \<noteq> 0 \<or> b \<noteq> 0" |
198 assumes nz: "a \<noteq> 0 \<or> b \<noteq> 0" |
199 shows "gcd (a div gcd a b) (b div gcd a b) = 1" |
199 shows "gcd (a div gcd a b) (b div gcd a b) = 1" |
200 proof - |
200 proof - |
311 apply (rule_tac x="y" in exI) |
311 apply (rule_tac x="y" in exI) |
312 apply auto |
312 apply auto |
313 done |
313 done |
314 |
314 |
315 |
315 |
316 text {* We can get a stronger version with a nonzeroness assumption. *} |
316 text \<open>We can get a stronger version with a nonzeroness assumption.\<close> |
317 lemma divides_le: "m dvd n ==> m <= n \<or> n = (0::nat)" by (auto simp add: dvd_def) |
317 lemma divides_le: "m dvd n ==> m <= n \<or> n = (0::nat)" by (auto simp add: dvd_def) |
318 |
318 |
319 lemma bezout_add_strong: assumes nz: "a \<noteq> (0::nat)" |
319 lemma bezout_add_strong: assumes nz: "a \<noteq> (0::nat)" |
320 shows "\<exists>d x y. d dvd a \<and> d dvd b \<and> a * x = b * y + d" |
320 shows "\<exists>d x y. d dvd a \<and> d dvd b \<and> a * x = b * y + d" |
321 proof- |
321 proof- |
560 apply (subgoal_tac "n = m + (n - m)") |
560 apply (subgoal_tac "n = m + (n - m)") |
561 apply (erule ssubst, rule gcd_add1_eq, simp) |
561 apply (erule ssubst, rule gcd_add1_eq, simp) |
562 done |
562 done |
563 |
563 |
564 |
564 |
565 subsection {* GCD and LCM on integers *} |
565 subsection \<open>GCD and LCM on integers\<close> |
566 |
566 |
567 definition |
567 definition |
568 zgcd :: "int \<Rightarrow> int \<Rightarrow> int" where |
568 zgcd :: "int \<Rightarrow> int \<Rightarrow> int" where |
569 "zgcd i j = int (gcd (nat (abs i)) (nat (abs j)))" |
569 "zgcd i j = int (gcd (nat (abs i)) (nat (abs j)))" |
570 |
570 |
593 lemma zrelprime_dvd_mult: "zgcd i j = 1 \<Longrightarrow> i dvd k * j \<Longrightarrow> i dvd k" |
593 lemma zrelprime_dvd_mult: "zgcd i j = 1 \<Longrightarrow> i dvd k * j \<Longrightarrow> i dvd k" |
594 unfolding zgcd_def |
594 unfolding zgcd_def |
595 proof - |
595 proof - |
596 assume "int (gcd (nat \<bar>i\<bar>) (nat \<bar>j\<bar>)) = 1" "i dvd k * j" |
596 assume "int (gcd (nat \<bar>i\<bar>) (nat \<bar>j\<bar>)) = 1" "i dvd k * j" |
597 then have g: "gcd (nat \<bar>i\<bar>) (nat \<bar>j\<bar>) = 1" by simp |
597 then have g: "gcd (nat \<bar>i\<bar>) (nat \<bar>j\<bar>) = 1" by simp |
598 from `i dvd k * j` obtain h where h: "k*j = i*h" unfolding dvd_def by blast |
598 from \<open>i dvd k * j\<close> obtain h where h: "k*j = i*h" unfolding dvd_def by blast |
599 have th: "nat \<bar>i\<bar> dvd nat \<bar>k\<bar> * nat \<bar>j\<bar>" |
599 have th: "nat \<bar>i\<bar> dvd nat \<bar>k\<bar> * nat \<bar>j\<bar>" |
600 unfolding dvd_def |
600 unfolding dvd_def |
601 by (rule_tac x= "nat \<bar>h\<bar>" in exI, simp add: h nat_abs_mult_distrib [symmetric]) |
601 by (rule_tac x= "nat \<bar>h\<bar>" in exI, simp add: h nat_abs_mult_distrib [symmetric]) |
602 from relprime_dvd_mult [OF g th] obtain h' where h': "nat \<bar>k\<bar> = nat \<bar>i\<bar> * h'" |
602 from relprime_dvd_mult [OF g th] obtain h' where h': "nat \<bar>k\<bar> = nat \<bar>i\<bar> * h'" |
603 unfolding dvd_def by blast |
603 unfolding dvd_def by blast |
618 shows "k dvd zgcd m n" |
618 shows "k dvd zgcd m n" |
619 proof - |
619 proof - |
620 let ?k' = "nat \<bar>k\<bar>" |
620 let ?k' = "nat \<bar>k\<bar>" |
621 let ?m' = "nat \<bar>m\<bar>" |
621 let ?m' = "nat \<bar>m\<bar>" |
622 let ?n' = "nat \<bar>n\<bar>" |
622 let ?n' = "nat \<bar>n\<bar>" |
623 from `k dvd m` and `k dvd n` have dvd': "?k' dvd ?m'" "?k' dvd ?n'" |
623 from \<open>k dvd m\<close> and \<open>k dvd n\<close> have dvd': "?k' dvd ?m'" "?k' dvd ?n'" |
624 unfolding zdvd_int by (simp_all only: int_nat_abs abs_dvd_iff dvd_abs_iff) |
624 unfolding zdvd_int by (simp_all only: int_nat_abs abs_dvd_iff dvd_abs_iff) |
625 from gcd_greatest [OF dvd'] have "int (nat \<bar>k\<bar>) dvd zgcd m n" |
625 from gcd_greatest [OF dvd'] have "int (nat \<bar>k\<bar>) dvd zgcd m n" |
626 unfolding zgcd_def by (simp only: zdvd_int) |
626 unfolding zgcd_def by (simp only: zdvd_int) |
627 then have "\<bar>k\<bar> dvd zgcd m n" by (simp only: int_nat_abs) |
627 then have "\<bar>k\<bar> dvd zgcd m n" by (simp only: int_nat_abs) |
628 then show "k dvd zgcd m n" by simp |
628 then show "k dvd zgcd m n" by simp |
694 apply (rule zgcd_assoc [THEN trans]) |
694 apply (rule zgcd_assoc [THEN trans]) |
695 apply (rule zgcd_commute [THEN arg_cong]) |
695 apply (rule zgcd_commute [THEN arg_cong]) |
696 done |
696 done |
697 |
697 |
698 lemmas zgcd_ac = zgcd_assoc zgcd_commute zgcd_left_commute |
698 lemmas zgcd_ac = zgcd_assoc zgcd_commute zgcd_left_commute |
699 -- {* addition is an AC-operator *} |
699 -- \<open>addition is an AC-operator\<close> |
700 |
700 |
701 lemma zgcd_zmult_distrib2: "0 \<le> k ==> k * zgcd m n = zgcd (k * m) (k * n)" |
701 lemma zgcd_zmult_distrib2: "0 \<le> k ==> k * zgcd m n = zgcd (k * m) (k * n)" |
702 by (simp del: minus_mult_right [symmetric] |
702 by (simp del: minus_mult_right [symmetric] |
703 add: minus_mult_right nat_mult_distrib zgcd_def abs_if |
703 add: minus_mult_right nat_mult_distrib zgcd_def abs_if |
704 mult_less_0_iff gcd_mult_distrib2 [symmetric] of_nat_mult) |
704 mult_less_0_iff gcd_mult_distrib2 [symmetric] of_nat_mult) |
726 |
726 |
727 |
727 |
728 lemma dvd_imp_dvd_zlcm1: |
728 lemma dvd_imp_dvd_zlcm1: |
729 assumes "k dvd i" shows "k dvd (zlcm i j)" |
729 assumes "k dvd i" shows "k dvd (zlcm i j)" |
730 proof - |
730 proof - |
731 have "nat(abs k) dvd nat(abs i)" using `k dvd i` |
731 have "nat(abs k) dvd nat(abs i)" using \<open>k dvd i\<close> |
732 by(simp add:int_dvd_iff[symmetric] dvd_int_iff[symmetric]) |
732 by(simp add:int_dvd_iff[symmetric] dvd_int_iff[symmetric]) |
733 thus ?thesis by(simp add:zlcm_def dvd_int_iff)(blast intro: dvd_trans) |
733 thus ?thesis by(simp add:zlcm_def dvd_int_iff)(blast intro: dvd_trans) |
734 qed |
734 qed |
735 |
735 |
736 lemma dvd_imp_dvd_zlcm2: |
736 lemma dvd_imp_dvd_zlcm2: |
737 assumes "k dvd j" shows "k dvd (zlcm i j)" |
737 assumes "k dvd j" shows "k dvd (zlcm i j)" |
738 proof - |
738 proof - |
739 have "nat(abs k) dvd nat(abs j)" using `k dvd j` |
739 have "nat(abs k) dvd nat(abs j)" using \<open>k dvd j\<close> |
740 by(simp add:int_dvd_iff[symmetric] dvd_int_iff[symmetric]) |
740 by(simp add:int_dvd_iff[symmetric] dvd_int_iff[symmetric]) |
741 thus ?thesis by(simp add:zlcm_def dvd_int_iff)(blast intro: dvd_trans) |
741 thus ?thesis by(simp add:zlcm_def dvd_int_iff)(blast intro: dvd_trans) |
742 qed |
742 qed |
743 |
743 |
744 |
744 |