src/HOL/GCD.thy
changeset 32040 830141c9e528
parent 32036 8a9228872fbd
parent 31996 1d93369079c4
child 32045 efc5f4806cd5
     1.1 --- a/src/HOL/GCD.thy	Tue Jul 14 17:17:37 2009 +0200
     1.2 +++ b/src/HOL/GCD.thy	Tue Jul 14 17:18:51 2009 +0200
     1.3 @@ -37,7 +37,7 @@
     1.4  
     1.5  subsection {* gcd *}
     1.6  
     1.7 -class gcd = one +
     1.8 +class gcd = zero + one + dvd +
     1.9  
    1.10  fixes
    1.11    gcd :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" and
    1.12 @@ -540,15 +540,15 @@
    1.13  
    1.14  (* to do: add the three variations of these, and for ints? *)
    1.15  
    1.16 -lemma finite_divisors_nat:
    1.17 -  assumes "(m::nat)~= 0" shows "finite{d. d dvd m}"
    1.18 +lemma finite_divisors_nat[simp]:
    1.19 +  assumes "(m::nat) ~= 0" shows "finite{d. d dvd m}"
    1.20  proof-
    1.21    have "finite{d. d <= m}" by(blast intro: bounded_nat_set_is_finite)
    1.22    from finite_subset[OF _ this] show ?thesis using assms
    1.23      by(bestsimp intro!:dvd_imp_le)
    1.24  qed
    1.25  
    1.26 -lemma finite_divisors_int:
    1.27 +lemma finite_divisors_int[simp]:
    1.28    assumes "(i::int) ~= 0" shows "finite{d. d dvd i}"
    1.29  proof-
    1.30    have "{d. abs d <= abs i} = {- abs i .. abs i}" by(auto simp:abs_if)
    1.31 @@ -557,10 +557,25 @@
    1.32      by(bestsimp intro!:dvd_imp_le_int)
    1.33  qed
    1.34  
    1.35 +lemma Max_divisors_self_nat[simp]: "n\<noteq>0 \<Longrightarrow> Max{d::nat. d dvd n} = n"
    1.36 +apply(rule antisym)
    1.37 + apply (fastsimp intro: Max_le_iff[THEN iffD2] simp: dvd_imp_le)
    1.38 +apply simp
    1.39 +done
    1.40 +
    1.41 +lemma Max_divisors_self_int[simp]: "n\<noteq>0 \<Longrightarrow> Max{d::int. d dvd n} = abs n"
    1.42 +apply(rule antisym)
    1.43 + apply(rule Max_le_iff[THEN iffD2])
    1.44 +   apply simp
    1.45 +  apply fastsimp
    1.46 + apply (metis Collect_def abs_ge_self dvd_imp_le_int mem_def zle_trans)
    1.47 +apply simp
    1.48 +done
    1.49 +
    1.50  lemma gcd_is_Max_divisors_nat:
    1.51    "m ~= 0 \<Longrightarrow> n ~= 0 \<Longrightarrow> gcd (m::nat) n = (Max {d. d dvd m & d dvd n})"
    1.52  apply(rule Max_eqI[THEN sym])
    1.53 -  apply (metis dvd.eq_iff finite_Collect_conjI finite_divisors_nat)
    1.54 +  apply (metis finite_Collect_conjI finite_divisors_nat)
    1.55   apply simp
    1.56   apply(metis Suc_diff_1 Suc_neq_Zero dvd_imp_le gcd_greatest_iff_nat gcd_pos_nat)
    1.57  apply simp
    1.58 @@ -569,7 +584,7 @@
    1.59  lemma gcd_is_Max_divisors_int:
    1.60    "m ~= 0 ==> n ~= 0 ==> gcd (m::int) n = (Max {d. d dvd m & d dvd n})"
    1.61  apply(rule Max_eqI[THEN sym])
    1.62 -  apply (metis dvd.eq_iff finite_Collect_conjI finite_divisors_int)
    1.63 +  apply (metis finite_Collect_conjI finite_divisors_int)
    1.64   apply simp
    1.65   apply (metis gcd_greatest_iff_int gcd_pos_int zdvd_imp_le)
    1.66  apply simp
    1.67 @@ -1442,31 +1457,61 @@
    1.68  lemma lcm_proj1_if_dvd_int [simp]: "(x::int) dvd y \<Longrightarrow> lcm y x = abs y"
    1.69  by (subst lcm_commute_int, erule lcm_proj2_if_dvd_int)
    1.70  
    1.71 +lemma lcm_proj1_iff_nat[simp]: "lcm m n = (m::nat) \<longleftrightarrow> n dvd m"
    1.72 +by (metis lcm_proj1_if_dvd_nat lcm_unique_nat)
    1.73 +
    1.74 +lemma lcm_proj2_iff_nat[simp]: "lcm m n = (n::nat) \<longleftrightarrow> m dvd n"
    1.75 +by (metis lcm_proj2_if_dvd_nat lcm_unique_nat)
    1.76 +
    1.77 +lemma lcm_proj1_iff_int[simp]: "lcm m n = abs(m::int) \<longleftrightarrow> n dvd m"
    1.78 +by (metis dvd_abs_iff lcm_proj1_if_dvd_int lcm_unique_int)
    1.79 +
    1.80 +lemma lcm_proj2_iff_int[simp]: "lcm m n = abs(n::int) \<longleftrightarrow> m dvd n"
    1.81 +by (metis dvd_abs_iff lcm_proj2_if_dvd_int lcm_unique_int)
    1.82  
    1.83  lemma lcm_assoc_nat: "lcm (lcm n m) (p::nat) = lcm n (lcm m p)"
    1.84 -apply(rule lcm_unique_nat[THEN iffD1])
    1.85 -apply (metis dvd.order_trans lcm_unique_nat)
    1.86 -done
    1.87 +by(rule lcm_unique_nat[THEN iffD1])(metis dvd.order_trans lcm_unique_nat)
    1.88  
    1.89  lemma lcm_assoc_int: "lcm (lcm n m) (p::int) = lcm n (lcm m p)"
    1.90 -apply(rule lcm_unique_int[THEN iffD1])
    1.91 -apply (metis dvd_trans lcm_unique_int)
    1.92 -done
    1.93 +by(rule lcm_unique_int[THEN iffD1])(metis dvd_trans lcm_unique_int)
    1.94  
    1.95 -lemmas lcm_left_commute_nat =
    1.96 -  mk_left_commute[of lcm, OF lcm_assoc_nat lcm_commute_nat]
    1.97 -
    1.98 -lemmas lcm_left_commute_int =
    1.99 -  mk_left_commute[of lcm, OF lcm_assoc_int lcm_commute_int]
   1.100 +lemmas lcm_left_commute_nat = mk_left_commute[of lcm, OF lcm_assoc_nat lcm_commute_nat]
   1.101 +lemmas lcm_left_commute_int = mk_left_commute[of lcm, OF lcm_assoc_int lcm_commute_int]
   1.102  
   1.103  lemmas lcm_ac_nat = lcm_assoc_nat lcm_commute_nat lcm_left_commute_nat
   1.104  lemmas lcm_ac_int = lcm_assoc_int lcm_commute_int lcm_left_commute_int
   1.105  
   1.106 +lemma fun_left_comm_idem_gcd_nat: "fun_left_comm_idem (gcd :: nat\<Rightarrow>nat\<Rightarrow>nat)"
   1.107 +proof qed (auto simp add: gcd_ac_nat)
   1.108 +
   1.109 +lemma fun_left_comm_idem_gcd_int: "fun_left_comm_idem (gcd :: int\<Rightarrow>int\<Rightarrow>int)"
   1.110 +proof qed (auto simp add: gcd_ac_int)
   1.111 +
   1.112 +lemma fun_left_comm_idem_lcm_nat: "fun_left_comm_idem (lcm :: nat\<Rightarrow>nat\<Rightarrow>nat)"
   1.113 +proof qed (auto simp add: lcm_ac_nat)
   1.114 +
   1.115 +lemma fun_left_comm_idem_lcm_int: "fun_left_comm_idem (lcm :: int\<Rightarrow>int\<Rightarrow>int)"
   1.116 +proof qed (auto simp add: lcm_ac_int)
   1.117 +
   1.118 +
   1.119 +(* FIXME introduce selimattice_bot/top and derive the following lemmas in there: *)
   1.120 +
   1.121 +lemma lcm_0_iff_nat[simp]: "lcm (m::nat) n = 0 \<longleftrightarrow> m=0 \<or> n=0"
   1.122 +by (metis lcm_0_left_nat lcm_0_nat mult_is_0 prod_gcd_lcm_nat)
   1.123 +
   1.124 +lemma lcm_0_iff_int[simp]: "lcm (m::int) n = 0 \<longleftrightarrow> m=0 \<or> n=0"
   1.125 +by (metis lcm_0_int lcm_0_left_int lcm_pos_int zless_le)
   1.126 +
   1.127 +lemma lcm_1_iff_nat[simp]: "lcm (m::nat) n = 1 \<longleftrightarrow> m=1 \<and> n=1"
   1.128 +by (metis gcd_1_nat lcm_unique_nat nat_mult_1 prod_gcd_lcm_nat)
   1.129 +
   1.130 +lemma lcm_1_iff_int[simp]: "lcm (m::int) n = 1 \<longleftrightarrow> (m=1 \<or> m = -1) \<and> (n=1 \<or> n = -1)"
   1.131 +by (auto simp add: abs_mult_self trans [OF lcm_unique_int eq_commute, symmetric] zmult_eq_1_iff)
   1.132 +
   1.133  
   1.134  subsection {* Primes *}
   1.135  
   1.136 -(* Is there a better way to handle these, rather than making them
   1.137 -   elim rules? *)
   1.138 +(* FIXME Is there a better way to handle these, rather than making them elim rules? *)
   1.139  
   1.140  lemma prime_ge_0_nat [elim]: "prime (p::nat) \<Longrightarrow> p >= 0"
   1.141    by (unfold prime_nat_def, auto)
   1.142 @@ -1490,7 +1535,7 @@
   1.143    by (unfold prime_nat_def, auto)
   1.144  
   1.145  lemma prime_ge_0_int [elim]: "prime (p::int) \<Longrightarrow> p >= 0"
   1.146 -  by (unfold prime_int_def prime_nat_def, auto)
   1.147 +  by (unfold prime_int_def prime_nat_def) auto
   1.148  
   1.149  lemma prime_gt_0_int [elim]: "prime (p::int) \<Longrightarrow> p > 0"
   1.150    by (unfold prime_int_def prime_nat_def, auto)
   1.151 @@ -1504,8 +1549,6 @@
   1.152  lemma prime_ge_2_int [elim]: "prime (p::int) \<Longrightarrow> p >= 2"
   1.153    by (unfold prime_int_def prime_nat_def, auto)
   1.154  
   1.155 -thm prime_nat_def;
   1.156 -thm prime_nat_def [transferred];
   1.157  
   1.158  lemma prime_int_altdef: "prime (p::int) = (1 < p \<and> (\<forall>m \<ge> 0. m dvd p \<longrightarrow>
   1.159      m = 1 \<or> m = p))"
   1.160 @@ -1566,35 +1609,13 @@
   1.161  lemma not_prime_eq_prod_nat: "(n::nat) > 1 \<Longrightarrow> ~ prime n \<Longrightarrow>
   1.162      EX m k. n = m * k & 1 < m & m < n & 1 < k & k < n"
   1.163    unfolding prime_nat_def dvd_def apply auto
   1.164 -  apply (subgoal_tac "k > 1")
   1.165 -  apply force
   1.166 -  apply (subgoal_tac "k ~= 0")
   1.167 -  apply force
   1.168 -  apply (rule notI)
   1.169 -  apply force
   1.170 -done
   1.171 +  by(metis mult_commute linorder_neq_iff linorder_not_le mult_1 n_less_n_mult_m one_le_mult_iff less_imp_le_nat)
   1.172  
   1.173 -(* there's a lot of messing around with signs of products here --
   1.174 -   could this be made more automatic? *)
   1.175  lemma not_prime_eq_prod_int: "(n::int) > 1 \<Longrightarrow> ~ prime n \<Longrightarrow>
   1.176      EX m k. n = m * k & 1 < m & m < n & 1 < k & k < n"
   1.177    unfolding prime_int_altdef dvd_def
   1.178    apply auto
   1.179 -  apply (rule_tac x = m in exI)
   1.180 -  apply (rule_tac x = k in exI)
   1.181 -  apply (auto simp add: mult_compare_simps)
   1.182 -  apply (subgoal_tac "k > 0")
   1.183 -  apply arith
   1.184 -  apply (case_tac "k <= 0")
   1.185 -  apply (subgoal_tac "m * k <= 0")
   1.186 -  apply force
   1.187 -  apply (subst zero_compare_simps(8))
   1.188 -  apply auto
   1.189 -  apply (subgoal_tac "m * k <= 0")
   1.190 -  apply force
   1.191 -  apply (subst zero_compare_simps(8))
   1.192 -  apply auto
   1.193 -done
   1.194 +  by(metis div_mult_self1_is_id div_mult_self2_is_id int_div_less_self int_one_le_iff_zero_less zero_less_mult_pos zless_le)
   1.195  
   1.196  lemma prime_dvd_power_nat [rule_format]: "prime (p::nat) -->
   1.197      n > 0 --> (p dvd x^n --> p dvd x)"