src/HOL/NumberTheory/IntPrimes.thy
changeset 30240 5b25fee0362c
parent 29948 cdf12a1cb963
child 30242 aea5d7fa7ef5
equal deleted inserted replaced
30239:179ff9cb160b 30240:5b25fee0362c
    48 subsection {* Euclid's Algorithm and GCD *}
    48 subsection {* Euclid's Algorithm and GCD *}
    49 
    49 
    50 
    50 
    51 lemma zrelprime_zdvd_zmult_aux:
    51 lemma zrelprime_zdvd_zmult_aux:
    52      "zgcd n k = 1 ==> k dvd m * n ==> 0 \<le> m ==> k dvd m"
    52      "zgcd n k = 1 ==> k dvd m * n ==> 0 \<le> m ==> k dvd m"
    53     by (metis abs_of_nonneg zdvd_triv_right zgcd_greatest_iff zgcd_zmult_distrib2_abs zmult_1_right)
    53     by (metis abs_of_nonneg dvd_triv_right zgcd_greatest_iff zgcd_zmult_distrib2_abs zmult_1_right)
    54 
    54 
    55 lemma zrelprime_zdvd_zmult: "zgcd n k = 1 ==> k dvd m * n ==> k dvd m"
    55 lemma zrelprime_zdvd_zmult: "zgcd n k = 1 ==> k dvd m * n ==> k dvd m"
    56   apply (case_tac "0 \<le> m")
    56   apply (case_tac "0 \<le> m")
    57    apply (blast intro: zrelprime_zdvd_zmult_aux)
    57    apply (blast intro: zrelprime_zdvd_zmult_aux)
    58   apply (subgoal_tac "k dvd -m")
    58   apply (subgoal_tac "k dvd -m")
    71   done
    71   done
    72 
    72 
    73 lemma zprime_imp_zrelprime:
    73 lemma zprime_imp_zrelprime:
    74     "zprime p ==> \<not> p dvd n ==> zgcd n p = 1"
    74     "zprime p ==> \<not> p dvd n ==> zgcd n p = 1"
    75   apply (auto simp add: zprime_def)
    75   apply (auto simp add: zprime_def)
    76   apply (metis zgcd_commute zgcd_geq_zero zgcd_zdvd1 zgcd_zdvd2)
    76   apply (metis zgcd_geq_zero zgcd_zdvd1 zgcd_zdvd2)
    77   done
    77   done
    78 
    78 
    79 lemma zless_zprime_imp_zrelprime:
    79 lemma zless_zprime_imp_zrelprime:
    80     "zprime p ==> 0 < n ==> n < p ==> zgcd n p = 1"
    80     "zprime p ==> 0 < n ==> n < p ==> zgcd n p = 1"
    81   apply (erule zprime_imp_zrelprime)
    81   apply (erule zprime_imp_zrelprime)
    91   apply (simp add: mod_add_eq)
    91   apply (simp add: mod_add_eq)
    92   apply (rule zgcd_eq [symmetric])
    92   apply (rule zgcd_eq [symmetric])
    93   done
    93   done
    94 
    94 
    95 lemma zgcd_zdvd_zgcd_zmult: "zgcd m n dvd zgcd (k * m) n"
    95 lemma zgcd_zdvd_zgcd_zmult: "zgcd m n dvd zgcd (k * m) n"
    96   apply (simp add: zgcd_greatest_iff)
    96 by (simp add: zgcd_greatest_iff)
    97   apply (blast intro: zdvd_trans dvd_triv_right)
       
    98   done
       
    99 
    97 
   100 lemma zgcd_zmult_zdvd_zgcd:
    98 lemma zgcd_zmult_zdvd_zgcd:
   101     "zgcd k n = 1 ==> zgcd (k * m) n dvd zgcd m n"
    99     "zgcd k n = 1 ==> zgcd (k * m) n dvd zgcd m n"
   102   apply (simp add: zgcd_greatest_iff)
   100   apply (simp add: zgcd_greatest_iff)
   103   apply (rule_tac n = k in zrelprime_zdvd_zmult)
   101   apply (rule_tac n = k in zrelprime_zdvd_zmult)
   125 
   123 
   126 lemma zcong_refl [simp]: "[k = k] (mod m)"
   124 lemma zcong_refl [simp]: "[k = k] (mod m)"
   127   by (unfold zcong_def, auto)
   125   by (unfold zcong_def, auto)
   128 
   126 
   129 lemma zcong_sym: "[a = b] (mod m) = [b = a] (mod m)"
   127 lemma zcong_sym: "[a = b] (mod m) = [b = a] (mod m)"
   130   unfolding zcong_def minus_diff_eq [of a, symmetric] zdvd_zminus_iff ..
   128   unfolding zcong_def minus_diff_eq [of a, symmetric] dvd_minus_iff ..
   131 
   129 
   132 lemma zcong_zadd:
   130 lemma zcong_zadd:
   133     "[a = b] (mod m) ==> [c = d] (mod m) ==> [a + c = b + d] (mod m)"
   131     "[a = b] (mod m) ==> [c = d] (mod m) ==> [a + c = b + d] (mod m)"
   134   apply (unfold zcong_def)
   132   apply (unfold zcong_def)
   135   apply (rule_tac s = "(a - b) + (c - d)" in subst)
   133   apply (rule_tac s = "(a - b) + (c - d)" in subst)
   136    apply (rule_tac [2] zdvd_zadd, auto)
   134    apply (rule_tac [2] dvd_add, auto)
   137   done
   135   done
   138 
   136 
   139 lemma zcong_zdiff:
   137 lemma zcong_zdiff:
   140     "[a = b] (mod m) ==> [c = d] (mod m) ==> [a - c = b - d] (mod m)"
   138     "[a = b] (mod m) ==> [c = d] (mod m) ==> [a - c = b - d] (mod m)"
   141   apply (unfold zcong_def)
   139   apply (unfold zcong_def)
   142   apply (rule_tac s = "(a - b) - (c - d)" in subst)
   140   apply (rule_tac s = "(a - b) - (c - d)" in subst)
   143    apply (rule_tac [2] zdvd_zdiff, auto)
   141    apply (rule_tac [2] dvd_diff, auto)
   144   done
   142   done
   145 
   143 
   146 lemma zcong_trans:
   144 lemma zcong_trans:
   147   "[a = b] (mod m) ==> [b = c] (mod m) ==> [a = c] (mod m)"
   145   "[a = b] (mod m) ==> [b = c] (mod m) ==> [a = c] (mod m)"
   148 unfolding zcong_def by (auto elim!: dvdE simp add: algebra_simps)
   146 unfolding zcong_def by (auto elim!: dvdE simp add: algebra_simps)
   149 
   147 
   150 lemma zcong_zmult:
   148 lemma zcong_zmult:
   151     "[a = b] (mod m) ==> [c = d] (mod m) ==> [a * c = b * d] (mod m)"
   149     "[a = b] (mod m) ==> [c = d] (mod m) ==> [a * c = b * d] (mod m)"
   152   apply (rule_tac b = "b * c" in zcong_trans)
   150   apply (rule_tac b = "b * c" in zcong_trans)
   153    apply (unfold zcong_def)
   151    apply (unfold zcong_def)
   154   apply (metis zdiff_zmult_distrib2 zdvd_zmult zmult_commute)
   152   apply (metis zdiff_zmult_distrib2 dvd_mult zmult_commute)
   155   apply (metis zdiff_zmult_distrib2 zdvd_zmult)
   153   apply (metis zdiff_zmult_distrib2 dvd_mult)
   156   done
   154   done
   157 
   155 
   158 lemma zcong_scalar: "[a = b] (mod m) ==> [a * k = b * k] (mod m)"
   156 lemma zcong_scalar: "[a = b] (mod m) ==> [a * k = b * k] (mod m)"
   159   by (rule zcong_zmult, simp_all)
   157   by (rule zcong_zmult, simp_all)
   160 
   158 
   161 lemma zcong_scalar2: "[a = b] (mod m) ==> [k * a = k * b] (mod m)"
   159 lemma zcong_scalar2: "[a = b] (mod m) ==> [k * a = k * b] (mod m)"
   162   by (rule zcong_zmult, simp_all)
   160   by (rule zcong_zmult, simp_all)
   163 
   161 
   164 lemma zcong_zmult_self: "[a * m = b * m] (mod m)"
   162 lemma zcong_zmult_self: "[a * m = b * m] (mod m)"
   165   apply (unfold zcong_def)
   163   apply (unfold zcong_def)
   166   apply (rule zdvd_zdiff, simp_all)
   164   apply (rule dvd_diff, simp_all)
   167   done
   165   done
   168 
   166 
   169 lemma zcong_square:
   167 lemma zcong_square:
   170    "[| zprime p;  0 < a;  [a * a = 1] (mod p)|]
   168    "[| zprime p;  0 < a;  [a * a = 1] (mod p)|]
   171     ==> [a = 1] (mod p) \<or> [a = p - 1] (mod p)"
   169     ==> [a = 1] (mod p) \<or> [a = p - 1] (mod p)"
   189    apply (unfold zcong_def)
   187    apply (unfold zcong_def)
   190    apply (rule_tac [!] zrelprime_zdvd_zmult)
   188    apply (rule_tac [!] zrelprime_zdvd_zmult)
   191      apply (simp_all add: zdiff_zmult_distrib)
   189      apply (simp_all add: zdiff_zmult_distrib)
   192   apply (subgoal_tac "m dvd (-(a * k - b * k))")
   190   apply (subgoal_tac "m dvd (-(a * k - b * k))")
   193    apply simp
   191    apply simp
   194   apply (subst zdvd_zminus_iff, assumption)
   192   apply (subst dvd_minus_iff, assumption)
   195   done
   193   done
   196 
   194 
   197 lemma zcong_cancel2:
   195 lemma zcong_cancel2:
   198   "0 \<le> m ==>
   196   "0 \<le> m ==>
   199     zgcd k m = 1 ==> [k * a = k * b] (mod m) = [a = b] (mod m)"
   197     zgcd k m = 1 ==> [k * a = k * b] (mod m) = [a = b] (mod m)"
   204     ==> [a = b] (mod m * n)"
   202     ==> [a = b] (mod m * n)"
   205   apply (auto simp add: zcong_def dvd_def)
   203   apply (auto simp add: zcong_def dvd_def)
   206   apply (subgoal_tac "m dvd n * ka")
   204   apply (subgoal_tac "m dvd n * ka")
   207    apply (subgoal_tac "m dvd ka")
   205    apply (subgoal_tac "m dvd ka")
   208     apply (case_tac [2] "0 \<le> ka")
   206     apply (case_tac [2] "0 \<le> ka")
   209   apply (metis zdvd_mult_div_cancel zdvd_refl zdvd_zminus2_iff zdvd_zmultD2 zgcd_zminus zmult_commute zmult_zminus zrelprime_zdvd_zmult)
   207   apply (metis zdvd_mult_div_cancel dvd_refl dvd_mult_left zmult_commute zrelprime_zdvd_zmult)
   210   apply (metis IntDiv.zdvd_abs1 abs_of_nonneg zadd_0 zgcd_0_left zgcd_commute zgcd_zadd_zmult zgcd_zdvd_zgcd_zmult zgcd_zmult_distrib2_abs zmult_1_right zmult_commute)
   208   apply (metis abs_dvd_iff abs_of_nonneg zadd_0 zgcd_0_left zgcd_commute zgcd_zadd_zmult zgcd_zdvd_zgcd_zmult zgcd_zmult_distrib2_abs zmult_1_right zmult_commute)
   211   apply (metis abs_eq_0 int_0_neq_1 mult_le_0_iff  zdvd_mono zdvd_mult_cancel zdvd_mult_cancel1 zdvd_refl zdvd_triv_left zdvd_zmult2 zero_le_mult_iff zgcd_greatest_iff zle_anti_sym zle_linear zle_refl zmult_commute zrelprime_zdvd_zmult)
   209   apply (metis mult_le_0_iff  zdvd_mono zdvd_mult_cancel dvd_triv_left zero_le_mult_iff zle_anti_sym zle_linear zle_refl zmult_commute zrelprime_zdvd_zmult)
   212   apply (metis zdvd_triv_left)
   210   apply (metis dvd_triv_left)
   213   done
   211   done
   214 
   212 
   215 lemma zcong_zless_imp_eq:
   213 lemma zcong_zless_imp_eq:
   216   "0 \<le> a ==>
   214   "0 \<le> a ==>
   217     a < m ==> 0 \<le> b ==> b < m ==> [a = b] (mod m) ==> a = b"
   215     a < m ==> 0 \<le> b ==> b < m ==> [a = b] (mod m) ==> a = b"
   218   apply (unfold zcong_def dvd_def, auto)
   216   apply (unfold zcong_def dvd_def, auto)
   219   apply (drule_tac f = "\<lambda>z. z mod m" in arg_cong)
   217   apply (drule_tac f = "\<lambda>z. z mod m" in arg_cong)
   220   apply (metis diff_add_cancel mod_pos_pos_trivial zadd_0 zadd_commute zmod_eq_0_iff zmod_zadd_right_eq)
   218   apply (metis diff_add_cancel mod_pos_pos_trivial zadd_0 zadd_commute zmod_eq_0_iff mod_add_right_eq)
   221   done
   219   done
   222 
   220 
   223 lemma zcong_square_zless:
   221 lemma zcong_square_zless:
   224   "zprime p ==> 0 < a ==> a < p ==>
   222   "zprime p ==> 0 < a ==> a < p ==>
   225     [a * a = 1] (mod p) ==> a = 1 \<or> a = p - 1"
   223     [a * a = 1] (mod p) ==> a = 1 \<or> a = p - 1"
   235   done
   233   done
   236 
   234 
   237 lemma zcong_zless_0:
   235 lemma zcong_zless_0:
   238     "0 \<le> a ==> a < m ==> [a = 0] (mod m) ==> a = 0"
   236     "0 \<le> a ==> a < m ==> [a = 0] (mod m) ==> a = 0"
   239   apply (unfold zcong_def dvd_def, auto)
   237   apply (unfold zcong_def dvd_def, auto)
   240   apply (metis div_pos_pos_trivial linorder_not_less zdiv_zmult_self2 zle_refl zle_trans)
   238   apply (metis div_pos_pos_trivial linorder_not_less div_mult_self1_is_id)
   241   done
   239   done
   242 
   240 
   243 lemma zcong_zless_unique:
   241 lemma zcong_zless_unique:
   244     "0 < m ==> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))"
   242     "0 < m ==> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))"
   245   apply auto
   243   apply auto
   300 
   298 
   301 subsection {* Modulo *}
   299 subsection {* Modulo *}
   302 
   300 
   303 lemma zmod_zdvd_zmod:
   301 lemma zmod_zdvd_zmod:
   304     "0 < (m::int) ==> m dvd b ==> (a mod b mod m) = (a mod m)"
   302     "0 < (m::int) ==> m dvd b ==> (a mod b mod m) = (a mod m)"
   305   by (rule zmod_zmod_cancel) 
   303   by (rule mod_mod_cancel) 
   306 
   304 
   307 
   305 
   308 subsection {* Extended GCD *}
   306 subsection {* Extended GCD *}
   309 
   307 
   310 declare xzgcda.simps [simp del]
   308 declare xzgcda.simps [simp del]
   401   apply (rule_tac x = s in exI)
   399   apply (rule_tac x = s in exI)
   402   apply (rule_tac b = "s * a + t * n" in zcong_trans)
   400   apply (rule_tac b = "s * a + t * n" in zcong_trans)
   403    prefer 2
   401    prefer 2
   404    apply simp
   402    apply simp
   405   apply (unfold zcong_def)
   403   apply (unfold zcong_def)
   406   apply (simp (no_asm) add: zmult_commute zdvd_zminus_iff)
   404   apply (simp (no_asm) add: zmult_commute)
   407   done
   405   done
   408 
   406 
   409 lemma zcong_lineq_unique:
   407 lemma zcong_lineq_unique:
   410   "0 < n ==>
   408   "0 < n ==>
   411     zgcd a n = 1 ==> \<exists>!x. 0 \<le> x \<and> x < n \<and> [a * x = b] (mod n)"
   409     zgcd a n = 1 ==> \<exists>!x. 0 \<le> x \<and> x < n \<and> [a * x = b] (mod n)"