src/HOL/Old_Number_Theory/Legacy_GCD.thy
changeset 61382 efac889fccbc
parent 58889 5b7a9633cfa8
child 61762 d50b993b4fb9
equal deleted inserted replaced
61381:ddca85598c65 61382:efac889fccbc
     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-
   447   from th[OF ab] show "gcd a (b - a) = gcd a b" 
   447   from th[OF ab] show "gcd a (b - a) = gcd a b" 
   448     by (simp add: gcd_commute)}
   448     by (simp add: gcd_commute)}
   449 qed
   449 qed
   450 
   450 
   451 
   451 
   452 subsection {* LCM defined by GCD *}
   452 subsection \<open>LCM defined by GCD\<close>
   453 
   453 
   454 
   454 
   455 definition
   455 definition
   456   lcm :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   456   lcm :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   457 where
   457 where
   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