src/HOL/ex/Primes.thy
author wenzelm
Tue Sep 12 22:13:23 2000 +0200 (2000-09-12)
changeset 9941 fe05af7ec816
parent 9912 4b02467a4412
permissions -rw-r--r--
renamed atts: rulify to rule_format, elimify to elim_format;
paulson@1804
     1
(*  Title:      HOL/ex/Primes.thy
paulson@1804
     2
    ID:         $Id$
paulson@1804
     3
    Author:     Christophe Tabacznyj and Lawrence C Paulson
paulson@1804
     4
    Copyright   1996  University of Cambridge
paulson@1804
     5
paulson@3376
     6
The Greatest Common Divisor and Euclid's algorithm
paulson@3495
     7
paulson@9824
     8
See H. Davenport, "The Higher Arithmetic".  6th edition.  (CUP, 1992)
paulson@1804
     9
*)
paulson@1804
    10
paulson@9824
    11
theory Primes = Main:
paulson@1804
    12
consts
paulson@3242
    13
  gcd     :: "nat*nat=>nat"               (*Euclid's algorithm *)
paulson@9824
    14
paulson@3495
    15
recdef gcd "measure ((%(m,n).n) ::nat*nat=>nat)"
paulson@3242
    16
    "gcd (m, n) = (if n=0 then m else gcd(n, m mod n))"
paulson@3242
    17
paulson@9824
    18
constdefs
paulson@9824
    19
  is_gcd  :: "[nat,nat,nat]=>bool"        (*gcd as a relation*)
paulson@9824
    20
    "is_gcd p m n == p dvd m  &  p dvd n  &
paulson@9824
    21
                     (ALL d. d dvd m & d dvd n --> d dvd p)"
paulson@9824
    22
paulson@9824
    23
  coprime :: "[nat,nat]=>bool"
paulson@9824
    24
    "coprime m n == gcd(m,n) = 1"
paulson@9824
    25
paulson@9824
    26
  prime   :: "nat set"
paulson@9824
    27
    "prime == {p. 1<p & (ALL m. m dvd p --> m=1 | m=p)}"
paulson@9824
    28
paulson@9824
    29
paulson@9824
    30
(************************************************)
paulson@9824
    31
(** Greatest Common Divisor                    **)
paulson@9824
    32
(************************************************)
paulson@9824
    33
paulson@9824
    34
(*** Euclid's Algorithm ***)
paulson@9824
    35
paulson@9824
    36
paulson@9824
    37
lemma gcd_induct:
paulson@9824
    38
     "[| !!m. P m 0;     
paulson@9824
    39
         !!m n. [| 0<n;  P n (m mod n) |] ==> P m n  
paulson@9824
    40
      |] ==> P (m::nat) (n::nat)"
paulson@9843
    41
  apply (induct_tac m n rule: gcd.induct)
paulson@9824
    42
  apply (case_tac "n=0")
paulson@9824
    43
  apply (simp_all)
paulson@9824
    44
  done
paulson@9824
    45
paulson@9824
    46
paulson@9824
    47
lemma gcd_0 [simp]: "gcd(m,0) = m"
paulson@9824
    48
  apply (simp);
paulson@9824
    49
  done
paulson@9824
    50
paulson@9824
    51
lemma gcd_non_0: "0<n ==> gcd(m,n) = gcd (n, m mod n)"
paulson@9824
    52
  apply (simp)
paulson@9824
    53
  done;
paulson@9824
    54
paulson@9824
    55
declare gcd.simps [simp del];
paulson@9824
    56
paulson@9824
    57
lemma gcd_1 [simp]: "gcd(m,1) = 1"
paulson@9824
    58
  apply (simp add: gcd_non_0)
paulson@9824
    59
  done
paulson@9824
    60
paulson@9824
    61
(*gcd(m,n) divides m and n.  The conjunctions don't seem provable separately*)
paulson@9824
    62
lemma gcd_dvd_both: "(gcd(m,n) dvd m) & (gcd(m,n) dvd n)"
paulson@9843
    63
  apply (induct_tac m n rule: gcd_induct)
paulson@9824
    64
  apply (simp_all add: gcd_non_0)
paulson@9824
    65
  apply (blast dest: dvd_mod_imp_dvd)
paulson@9824
    66
  done
paulson@9824
    67
paulson@9912
    68
lemmas gcd_dvd1 [iff] = gcd_dvd_both [THEN conjunct1]
paulson@9912
    69
lemmas gcd_dvd2 [iff] = gcd_dvd_both [THEN conjunct2];
paulson@9824
    70
paulson@9824
    71
paulson@9912
    72
(*Maximality: for all m,n,k naturals, 
paulson@9912
    73
                if k divides m and k divides n then k divides gcd(m,n)*)
wenzelm@9941
    74
lemma gcd_greatest [rule_format]: "(k dvd m) --> (k dvd n) --> k dvd gcd(m,n)"
paulson@9843
    75
  apply (induct_tac m n rule: gcd_induct)
paulson@9824
    76
  apply (simp_all add: gcd_non_0 dvd_mod);
paulson@9824
    77
  done;
paulson@9824
    78
paulson@9912
    79
lemma gcd_greatest_iff [iff]: "k dvd gcd(m,n) = (k dvd m & k dvd n)"
paulson@9912
    80
  apply (blast intro!: gcd_greatest intro: dvd_trans);
paulson@9843
    81
  done;
paulson@9843
    82
paulson@9824
    83
(*Function gcd yields the Greatest Common Divisor*)
paulson@9824
    84
lemma is_gcd: "is_gcd (gcd(m,n)) m n"
paulson@9912
    85
  apply (simp add: is_gcd_def gcd_greatest)
paulson@9824
    86
  done
paulson@9824
    87
paulson@9824
    88
(*uniqueness of GCDs*)
paulson@9824
    89
lemma is_gcd_unique: "[| is_gcd m a b; is_gcd n a b |] ==> m=n"
paulson@9824
    90
  apply (simp add: is_gcd_def);
paulson@9824
    91
  apply (blast intro: dvd_anti_sym)
paulson@9824
    92
  done
paulson@9824
    93
paulson@9824
    94
lemma is_gcd_dvd: "[| is_gcd m a b; k dvd a; k dvd b |] ==> k dvd m"
paulson@9824
    95
  apply (auto simp add: is_gcd_def);
paulson@9824
    96
  done
paulson@9824
    97
paulson@9824
    98
(** Commutativity **)
paulson@9824
    99
paulson@9824
   100
lemma is_gcd_commute: "is_gcd k m n = is_gcd k n m"
paulson@9824
   101
  apply (auto simp add: is_gcd_def);
paulson@9824
   102
  done
paulson@9824
   103
paulson@9824
   104
lemma gcd_commute: "gcd(m,n) = gcd(n,m)"
paulson@9824
   105
  apply (rule is_gcd_unique)
paulson@9824
   106
  apply (rule is_gcd)
paulson@9824
   107
  apply (subst is_gcd_commute)
paulson@9824
   108
  apply (simp add: is_gcd)
paulson@9824
   109
  done
paulson@9824
   110
paulson@9824
   111
lemma gcd_assoc: "gcd(gcd(k,m),n) = gcd(k,gcd(m,n))"
paulson@9824
   112
  apply (rule is_gcd_unique)
paulson@9824
   113
  apply (rule is_gcd)
paulson@9824
   114
  apply (simp add: is_gcd_def);
paulson@9912
   115
  apply (blast intro: dvd_trans);
paulson@9824
   116
  done 
paulson@1804
   117
paulson@9824
   118
lemma gcd_0_left [simp]: "gcd(0,m) = m"
paulson@9824
   119
  apply (simp add: gcd_commute [of 0])
paulson@9824
   120
  done
paulson@9824
   121
paulson@9824
   122
lemma gcd_1_left [simp]: "gcd(1,m) = 1"
paulson@9824
   123
  apply (simp add: gcd_commute [of 1])
paulson@9824
   124
  done
paulson@9824
   125
paulson@9824
   126
paulson@9824
   127
(** Multiplication laws **)
paulson@9824
   128
paulson@9824
   129
(*Davenport, page 27*)
paulson@9824
   130
lemma gcd_mult_distrib2: "k * gcd(m,n) = gcd(k*m, k*n)"
paulson@9843
   131
  apply (induct_tac m n rule: gcd_induct)
paulson@9824
   132
  apply (simp)
paulson@9824
   133
  apply (case_tac "k=0")
paulson@9824
   134
  apply (simp_all add: mod_geq gcd_non_0 mod_mult_distrib2)
paulson@9824
   135
  done
paulson@9824
   136
paulson@9824
   137
lemma gcd_self [simp]: "gcd(m,m) = m"
paulson@9912
   138
  apply (rule gcd_mult_distrib2 [of m 1 1, simplified, THEN sym])
paulson@9912
   139
  done
paulson@9824
   140
paulson@9824
   141
lemma gcd_mult [simp]: "gcd(k, k*n) = k"
paulson@9912
   142
  apply (rule gcd_mult_distrib2 [of k 1 n, simplified, THEN sym])
paulson@9912
   143
  done
paulson@9824
   144
paulson@9824
   145
lemma relprime_dvd_mult: "[| gcd(k,n)=1; k dvd (m*n) |] ==> k dvd m";
paulson@9824
   146
   apply (subgoal_tac "gcd(m*k, m*n) = m")
paulson@9843
   147
   apply (erule_tac t="m" in subst);
paulson@9843
   148
   apply (simp)
paulson@9824
   149
   apply (simp add: gcd_mult_distrib2 [THEN sym]);
paulson@9843
   150
  done
paulson@9843
   151
paulson@9843
   152
lemma relprime_dvd_mult_iff: "gcd(k,n)=1 \<Longrightarrow> k dvd (m*n) = k dvd m";
paulson@9843
   153
  apply (blast intro: relprime_dvd_mult dvd_trans)
paulson@9824
   154
  done
paulson@1804
   155
paulson@9824
   156
lemma prime_imp_relprime: "[| p: prime;  ~ p dvd n |] ==> gcd (p, n) = 1"
paulson@9912
   157
  apply (auto simp add: prime_def)
paulson@9912
   158
  apply (drule_tac x="gcd(p,n)" in spec)
paulson@9824
   159
  apply auto
paulson@9912
   160
  apply (insert gcd_dvd2 [of p n])
paulson@9912
   161
  apply (simp)
paulson@9824
   162
  done
paulson@9824
   163
paulson@9824
   164
(*This theorem leads immediately to a proof of the uniqueness of factorization.
paulson@9824
   165
  If p divides a product of primes then it is one of those primes.*)
paulson@9824
   166
lemma prime_dvd_mult: "[| p: prime; p dvd (m*n) |] ==> p dvd m | p dvd n"
paulson@9824
   167
  apply (blast intro: relprime_dvd_mult prime_imp_relprime)
paulson@9824
   168
  done
paulson@9824
   169
paulson@9824
   170
paulson@9824
   171
(** Addition laws **)
paulson@9824
   172
paulson@9824
   173
lemma gcd_add1 [simp]: "gcd(m+n, n) = gcd(m,n)"
paulson@9824
   174
  apply (case_tac "n=0")
paulson@9824
   175
  apply (simp_all add: gcd_non_0)
paulson@9824
   176
  done
paulson@9824
   177
paulson@9824
   178
lemma gcd_add2 [simp]: "gcd(m, m+n) = gcd(m,n)"
paulson@9824
   179
  apply (rule gcd_commute [THEN trans])
paulson@9824
   180
  apply (subst add_commute)
paulson@9824
   181
  apply (simp add: gcd_add1)
paulson@9824
   182
  apply (rule gcd_commute)
paulson@9824
   183
  done
paulson@9824
   184
paulson@9824
   185
lemma gcd_add2' [simp]: "gcd(m, n+m) = gcd(m,n)"
paulson@9824
   186
  apply (subst add_commute)
paulson@9824
   187
  apply (rule gcd_add2)
paulson@9824
   188
  done
paulson@9824
   189
paulson@9824
   190
lemma gcd_add_mult: "gcd(m, k*m+n) = gcd(m,n)"
paulson@9824
   191
  apply (induct_tac "k")
paulson@9824
   192
  apply (simp_all add: gcd_add2 add_assoc)
paulson@9824
   193
  done
paulson@9824
   194
paulson@9824
   195
paulson@9824
   196
(** More multiplication laws **)
paulson@9824
   197
paulson@9824
   198
lemma gcd_mult_cancel: "gcd(k,n) = 1 ==> gcd(k*m, n) = gcd(m,n)"
paulson@9824
   199
  apply (rule dvd_anti_sym)
paulson@9824
   200
   apply (rule gcd_greatest)
paulson@9824
   201
    apply (rule_tac n="k" in relprime_dvd_mult)
paulson@9824
   202
     apply (simp add: gcd_assoc)
paulson@9824
   203
     apply (simp add: gcd_commute)
paulson@9843
   204
    apply (simp_all add: mult_commute gcd_dvd1 gcd_dvd2)
paulson@9843
   205
  apply (blast intro: gcd_dvd1 dvd_trans);
paulson@9824
   206
  done
paulson@1804
   207
paulson@1804
   208
end