src/HOL/NewNumberTheory/Cong.thy
changeset 31719 29f5b20e8ee8
child 31792 d5a6096b94ad
equal deleted inserted replaced
31718:7715d4d3586f 31719:29f5b20e8ee8
       
     1 (*  Title:      HOL/Library/Cong.thy
       
     2     ID:         
       
     3     Authors:    Christophe Tabacznyj, Lawrence C. Paulson, Amine Chaieb,
       
     4                 Thomas M. Rasmussen, Jeremy Avigad
       
     5 
       
     6 
       
     7 Defines congruence (notation: [x = y] (mod z)) for natural numbers and
       
     8 integers.
       
     9 
       
    10 This file combines and revises a number of prior developments.
       
    11 
       
    12 The original theories "GCD" and "Primes" were by Christophe Tabacznyj
       
    13 and Lawrence C. Paulson, based on \cite{davenport92}. They introduced
       
    14 gcd, lcm, and prime for the natural numbers.
       
    15 
       
    16 The original theory "IntPrimes" was by Thomas M. Rasmussen, and
       
    17 extended gcd, lcm, primes to the integers. Amine Chaieb provided
       
    18 another extension of the notions to the integers, and added a number
       
    19 of results to "Primes" and "GCD". 
       
    20 
       
    21 The original theory, "IntPrimes", by Thomas M. Rasmussen, defined and
       
    22 developed the congruence relations on the integers. The notion was
       
    23 extended to the natural numbers by Chiaeb. Jeremy Avigad combined
       
    24 these, revised and tidied them, made the development uniform for the
       
    25 natural numbers and the integers, and added a number of new theorems.
       
    26 
       
    27 *)
       
    28 
       
    29 
       
    30 header {* Congruence *}
       
    31 
       
    32 theory Cong
       
    33 imports GCD
       
    34 begin
       
    35 
       
    36 subsection {* Turn off One_nat_def *}
       
    37 
       
    38 lemma nat_induct' [case_names zero plus1, induct type: nat]: 
       
    39     "\<lbrakk> P (0::nat); !!n. P n \<Longrightarrow> P (n + 1)\<rbrakk> \<Longrightarrow> P n"
       
    40 by (erule nat_induct) (simp add:One_nat_def)
       
    41 
       
    42 lemma nat_cases [case_names zero plus1, cases type: nat]: 
       
    43     "P (0::nat) \<Longrightarrow> (!!n. P (n + 1)) \<Longrightarrow> P n"
       
    44 by(metis nat_induct')
       
    45 
       
    46 lemma power_plus_one [simp]: "(x::'a::power)^(n + 1) = x * x^n"
       
    47 by (simp add: One_nat_def)
       
    48 
       
    49 lemma nat_power_eq_one_eq [simp]: 
       
    50   "((x::nat)^m = 1) = (m = 0 | x = 1)"
       
    51 by (induct m, auto)
       
    52 
       
    53 lemma card_insert_if' [simp]: "finite A \<Longrightarrow>
       
    54   card (insert x A) = (if x \<in> A then (card A) else (card A) + 1)"
       
    55 by (auto simp add: insert_absorb)
       
    56 
       
    57 (* why wasn't card_insert_if a simp rule? *)
       
    58 declare card_insert_disjoint [simp del]
       
    59 
       
    60 lemma nat_1' [simp]: "nat 1 = 1"
       
    61 by simp
       
    62 
       
    63 (* For those annoying moments where Suc reappears *)
       
    64 lemma Suc_remove: "Suc n = n + 1"
       
    65 by simp
       
    66 
       
    67 declare nat_1 [simp del]
       
    68 declare add_2_eq_Suc [simp del] 
       
    69 declare add_2_eq_Suc' [simp del]
       
    70 
       
    71 
       
    72 declare mod_pos_pos_trivial [simp]
       
    73 
       
    74 
       
    75 subsection {* Main definitions *}
       
    76 
       
    77 class cong =
       
    78 
       
    79 fixes 
       
    80   cong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ = _] '(mod _'))")
       
    81 
       
    82 begin
       
    83 
       
    84 abbreviation
       
    85   notcong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ \<noteq> _] '(mod _'))")
       
    86 where
       
    87   "notcong x y m == (~cong x y m)" 
       
    88 
       
    89 end
       
    90 
       
    91 (* definitions for the natural numbers *)
       
    92 
       
    93 instantiation nat :: cong
       
    94 
       
    95 begin 
       
    96 
       
    97 definition 
       
    98   cong_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
       
    99 where 
       
   100   "cong_nat x y m = ((x mod m) = (y mod m))"
       
   101 
       
   102 instance proof qed
       
   103 
       
   104 end
       
   105 
       
   106 
       
   107 (* definitions for the integers *)
       
   108 
       
   109 instantiation int :: cong
       
   110 
       
   111 begin 
       
   112 
       
   113 definition 
       
   114   cong_int :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> bool"
       
   115 where 
       
   116   "cong_int x y m = ((x mod m) = (y mod m))"
       
   117 
       
   118 instance proof qed
       
   119 
       
   120 end
       
   121 
       
   122 
       
   123 subsection {* Set up Transfer *}
       
   124 
       
   125 
       
   126 lemma transfer_nat_int_cong:
       
   127   "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> m >= 0 \<Longrightarrow> 
       
   128     ([(nat x) = (nat y)] (mod (nat m))) = ([x = y] (mod m))"
       
   129   unfolding cong_int_def cong_nat_def 
       
   130   apply (auto simp add: nat_mod_distrib [symmetric])
       
   131   apply (subst (asm) eq_nat_nat_iff)
       
   132   apply (case_tac "m = 0", force, rule pos_mod_sign, force)+
       
   133   apply assumption
       
   134 done
       
   135 
       
   136 declare TransferMorphism_nat_int[transfer add return: 
       
   137     transfer_nat_int_cong]
       
   138 
       
   139 lemma transfer_int_nat_cong:
       
   140   "[(int x) = (int y)] (mod (int m)) = [x = y] (mod m)"
       
   141   apply (auto simp add: cong_int_def cong_nat_def)
       
   142   apply (auto simp add: zmod_int [symmetric])
       
   143 done
       
   144 
       
   145 declare TransferMorphism_int_nat[transfer add return: 
       
   146     transfer_int_nat_cong]
       
   147 
       
   148 
       
   149 subsection {* Congruence *}
       
   150 
       
   151 (* was zcong_0, etc. *)
       
   152 lemma nat_cong_0 [simp, presburger]: "([(a::nat) = b] (mod 0)) = (a = b)"
       
   153   by (unfold cong_nat_def, auto)
       
   154 
       
   155 lemma int_cong_0 [simp, presburger]: "([(a::int) = b] (mod 0)) = (a = b)"
       
   156   by (unfold cong_int_def, auto)
       
   157 
       
   158 lemma nat_cong_1 [simp, presburger]: "[(a::nat) = b] (mod 1)"
       
   159   by (unfold cong_nat_def, auto)
       
   160 
       
   161 lemma nat_cong_Suc_0 [simp, presburger]: "[(a::nat) = b] (mod Suc 0)"
       
   162   by (unfold cong_nat_def, auto simp add: One_nat_def)
       
   163 
       
   164 lemma int_cong_1 [simp, presburger]: "[(a::int) = b] (mod 1)"
       
   165   by (unfold cong_int_def, auto)
       
   166 
       
   167 lemma nat_cong_refl [simp]: "[(k::nat) = k] (mod m)"
       
   168   by (unfold cong_nat_def, auto)
       
   169 
       
   170 lemma int_cong_refl [simp]: "[(k::int) = k] (mod m)"
       
   171   by (unfold cong_int_def, auto)
       
   172 
       
   173 lemma nat_cong_sym: "[(a::nat) = b] (mod m) \<Longrightarrow> [b = a] (mod m)"
       
   174   by (unfold cong_nat_def, auto)
       
   175 
       
   176 lemma int_cong_sym: "[(a::int) = b] (mod m) \<Longrightarrow> [b = a] (mod m)"
       
   177   by (unfold cong_int_def, auto)
       
   178 
       
   179 lemma nat_cong_sym_eq: "[(a::nat) = b] (mod m) = [b = a] (mod m)"
       
   180   by (unfold cong_nat_def, auto)
       
   181 
       
   182 lemma int_cong_sym_eq: "[(a::int) = b] (mod m) = [b = a] (mod m)"
       
   183   by (unfold cong_int_def, auto)
       
   184 
       
   185 lemma nat_cong_trans [trans]:
       
   186     "[(a::nat) = b] (mod m) \<Longrightarrow> [b = c] (mod m) \<Longrightarrow> [a = c] (mod m)"
       
   187   by (unfold cong_nat_def, auto)
       
   188 
       
   189 lemma int_cong_trans [trans]:
       
   190     "[(a::int) = b] (mod m) \<Longrightarrow> [b = c] (mod m) \<Longrightarrow> [a = c] (mod m)"
       
   191   by (unfold cong_int_def, auto)
       
   192 
       
   193 lemma nat_cong_add:
       
   194     "[(a::nat) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a + c = b + d] (mod m)"
       
   195   apply (unfold cong_nat_def)
       
   196   apply (subst (1 2) mod_add_eq)
       
   197   apply simp
       
   198 done
       
   199 
       
   200 lemma int_cong_add:
       
   201     "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a + c = b + d] (mod m)"
       
   202   apply (unfold cong_int_def)
       
   203   apply (subst (1 2) mod_add_left_eq)
       
   204   apply (subst (1 2) mod_add_right_eq)
       
   205   apply simp
       
   206 done
       
   207 
       
   208 lemma int_cong_diff:
       
   209     "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a - c = b - d] (mod m)"
       
   210   apply (unfold cong_int_def)
       
   211   apply (subst (1 2) mod_diff_eq)
       
   212   apply simp
       
   213 done
       
   214 
       
   215 lemma int_cong_diff_aux:
       
   216   "(a::int) >= c \<Longrightarrow> b >= d \<Longrightarrow> [(a::int) = b] (mod m) \<Longrightarrow> 
       
   217       [c = d] (mod m) \<Longrightarrow> [tsub a c = tsub b d] (mod m)"
       
   218   apply (subst (1 2) tsub_eq)
       
   219   apply (auto intro: int_cong_diff)
       
   220 done;
       
   221 
       
   222 lemma nat_cong_diff:
       
   223   assumes "(a::nat) >= c" and "b >= d" and "[a = b] (mod m)" and
       
   224     "[c = d] (mod m)"
       
   225   shows "[a - c = b - d] (mod m)"
       
   226 
       
   227   using prems by (rule int_cong_diff_aux [transferred]);
       
   228 
       
   229 lemma nat_cong_mult:
       
   230     "[(a::nat) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a * c = b * d] (mod m)"
       
   231   apply (unfold cong_nat_def)
       
   232   apply (subst (1 2) mod_mult_eq)
       
   233   apply simp
       
   234 done
       
   235 
       
   236 lemma int_cong_mult:
       
   237     "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a * c = b * d] (mod m)"
       
   238   apply (unfold cong_int_def)
       
   239   apply (subst (1 2) zmod_zmult1_eq)
       
   240   apply (subst (1 2) mult_commute)
       
   241   apply (subst (1 2) zmod_zmult1_eq)
       
   242   apply simp
       
   243 done
       
   244 
       
   245 lemma nat_cong_exp: "[(x::nat) = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)"
       
   246   apply (induct k)
       
   247   apply (auto simp add: nat_cong_refl nat_cong_mult)
       
   248 done
       
   249 
       
   250 lemma int_cong_exp: "[(x::int) = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)"
       
   251   apply (induct k)
       
   252   apply (auto simp add: int_cong_refl int_cong_mult)
       
   253 done
       
   254 
       
   255 lemma nat_cong_setsum [rule_format]: 
       
   256     "(ALL x: A. [((f x)::nat) = g x] (mod m)) \<longrightarrow> 
       
   257       [(SUM x:A. f x) = (SUM x:A. g x)] (mod m)"
       
   258   apply (case_tac "finite A")
       
   259   apply (induct set: finite)
       
   260   apply (auto intro: nat_cong_add)
       
   261 done
       
   262 
       
   263 lemma int_cong_setsum [rule_format]:
       
   264     "(ALL x: A. [((f x)::int) = g x] (mod m)) \<longrightarrow> 
       
   265       [(SUM x:A. f x) = (SUM x:A. g x)] (mod m)"
       
   266   apply (case_tac "finite A")
       
   267   apply (induct set: finite)
       
   268   apply (auto intro: int_cong_add)
       
   269 done
       
   270 
       
   271 lemma nat_cong_setprod [rule_format]: 
       
   272     "(ALL x: A. [((f x)::nat) = g x] (mod m)) \<longrightarrow> 
       
   273       [(PROD x:A. f x) = (PROD x:A. g x)] (mod m)"
       
   274   apply (case_tac "finite A")
       
   275   apply (induct set: finite)
       
   276   apply (auto intro: nat_cong_mult)
       
   277 done
       
   278 
       
   279 lemma int_cong_setprod [rule_format]: 
       
   280     "(ALL x: A. [((f x)::int) = g x] (mod m)) \<longrightarrow> 
       
   281       [(PROD x:A. f x) = (PROD x:A. g x)] (mod m)"
       
   282   apply (case_tac "finite A")
       
   283   apply (induct set: finite)
       
   284   apply (auto intro: int_cong_mult)
       
   285 done
       
   286 
       
   287 lemma nat_cong_scalar: "[(a::nat)= b] (mod m) \<Longrightarrow> [a * k = b * k] (mod m)"
       
   288   by (rule nat_cong_mult, simp_all)
       
   289 
       
   290 lemma int_cong_scalar: "[(a::int)= b] (mod m) \<Longrightarrow> [a * k = b * k] (mod m)"
       
   291   by (rule int_cong_mult, simp_all)
       
   292 
       
   293 lemma nat_cong_scalar2: "[(a::nat)= b] (mod m) \<Longrightarrow> [k * a = k * b] (mod m)"
       
   294   by (rule nat_cong_mult, simp_all)
       
   295 
       
   296 lemma int_cong_scalar2: "[(a::int)= b] (mod m) \<Longrightarrow> [k * a = k * b] (mod m)"
       
   297   by (rule int_cong_mult, simp_all)
       
   298 
       
   299 lemma nat_cong_mult_self: "[(a::nat) * m = 0] (mod m)"
       
   300   by (unfold cong_nat_def, auto)
       
   301 
       
   302 lemma int_cong_mult_self: "[(a::int) * m = 0] (mod m)"
       
   303   by (unfold cong_int_def, auto)
       
   304 
       
   305 lemma int_cong_eq_diff_cong_0: "[(a::int) = b] (mod m) = [a - b = 0] (mod m)"
       
   306   apply (rule iffI)
       
   307   apply (erule int_cong_diff [of a b m b b, simplified])
       
   308   apply (erule int_cong_add [of "a - b" 0 m b b, simplified])
       
   309 done
       
   310 
       
   311 lemma int_cong_eq_diff_cong_0_aux: "a >= b \<Longrightarrow>
       
   312     [(a::int) = b] (mod m) = [tsub a b = 0] (mod m)"
       
   313   by (subst tsub_eq, assumption, rule int_cong_eq_diff_cong_0)
       
   314 
       
   315 lemma nat_cong_eq_diff_cong_0:
       
   316   assumes "(a::nat) >= b"
       
   317   shows "[a = b] (mod m) = [a - b = 0] (mod m)"
       
   318 
       
   319   using prems by (rule int_cong_eq_diff_cong_0_aux [transferred])
       
   320 
       
   321 lemma nat_cong_diff_cong_0': 
       
   322   "[(x::nat) = y] (mod n) \<longleftrightarrow> 
       
   323     (if x <= y then [y - x = 0] (mod n) else [x - y = 0] (mod n))"
       
   324   apply (case_tac "y <= x")
       
   325   apply (frule nat_cong_eq_diff_cong_0 [where m = n])
       
   326   apply auto [1]
       
   327   apply (subgoal_tac "x <= y")
       
   328   apply (frule nat_cong_eq_diff_cong_0 [where m = n])
       
   329   apply (subst nat_cong_sym_eq)
       
   330   apply auto
       
   331 done
       
   332 
       
   333 lemma nat_cong_altdef: "(a::nat) >= b \<Longrightarrow> [a = b] (mod m) = (m dvd (a - b))"
       
   334   apply (subst nat_cong_eq_diff_cong_0, assumption)
       
   335   apply (unfold cong_nat_def)
       
   336   apply (simp add: dvd_eq_mod_eq_0 [symmetric])
       
   337 done
       
   338 
       
   339 lemma int_cong_altdef: "[(a::int) = b] (mod m) = (m dvd (a - b))"
       
   340   apply (subst int_cong_eq_diff_cong_0)
       
   341   apply (unfold cong_int_def)
       
   342   apply (simp add: dvd_eq_mod_eq_0 [symmetric])
       
   343 done
       
   344 
       
   345 lemma int_cong_abs: "[(x::int) = y] (mod abs m) = [x = y] (mod m)"
       
   346   by (simp add: int_cong_altdef)
       
   347 
       
   348 lemma int_cong_square:
       
   349    "\<lbrakk> prime (p::int); 0 < a; [a * a = 1] (mod p) \<rbrakk>
       
   350     \<Longrightarrow> [a = 1] (mod p) \<or> [a = - 1] (mod p)"
       
   351   apply (simp only: int_cong_altdef)
       
   352   apply (subst int_prime_dvd_mult_eq [symmetric], assumption)
       
   353   (* any way around this? *)
       
   354   apply (subgoal_tac "a * a - 1 = (a - 1) * (a - -1)")
       
   355   apply (auto simp add: ring_simps)
       
   356 done
       
   357 
       
   358 lemma int_cong_mult_rcancel:
       
   359   "coprime k (m::int) \<Longrightarrow> [a * k = b * k] (mod m) = [a = b] (mod m)"
       
   360   apply (subst (1 2) int_cong_altdef)
       
   361   apply (subst left_diff_distrib [symmetric])
       
   362   apply (rule int_coprime_dvd_mult_iff)
       
   363   apply (subst int_gcd_commute, assumption)
       
   364 done
       
   365 
       
   366 lemma nat_cong_mult_rcancel:
       
   367   assumes  "coprime k (m::nat)"
       
   368   shows "[a * k = b * k] (mod m) = [a = b] (mod m)"
       
   369 
       
   370   apply (rule int_cong_mult_rcancel [transferred])
       
   371   using prems apply auto
       
   372 done
       
   373 
       
   374 lemma nat_cong_mult_lcancel:
       
   375   "coprime k (m::nat) \<Longrightarrow> [k * a = k * b ] (mod m) = [a = b] (mod m)"
       
   376   by (simp add: mult_commute nat_cong_mult_rcancel)
       
   377 
       
   378 lemma int_cong_mult_lcancel:
       
   379   "coprime k (m::int) \<Longrightarrow> [k * a = k * b] (mod m) = [a = b] (mod m)"
       
   380   by (simp add: mult_commute int_cong_mult_rcancel)
       
   381 
       
   382 (* was zcong_zgcd_zmult_zmod *)
       
   383 lemma int_coprime_cong_mult:
       
   384   "[(a::int) = b] (mod m) \<Longrightarrow> [a = b] (mod n) \<Longrightarrow> coprime m n
       
   385     \<Longrightarrow> [a = b] (mod m * n)"
       
   386   apply (simp only: int_cong_altdef)
       
   387   apply (erule (2) int_divides_mult)
       
   388 done
       
   389 
       
   390 lemma nat_coprime_cong_mult:
       
   391   assumes "[(a::nat) = b] (mod m)" and "[a = b] (mod n)" and "coprime m n"
       
   392   shows "[a = b] (mod m * n)"
       
   393 
       
   394   apply (rule int_coprime_cong_mult [transferred])
       
   395   using prems apply auto
       
   396 done
       
   397 
       
   398 lemma nat_cong_less_imp_eq: "0 \<le> (a::nat) \<Longrightarrow>
       
   399     a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b"
       
   400   by (auto simp add: cong_nat_def mod_pos_pos_trivial)
       
   401 
       
   402 lemma int_cong_less_imp_eq: "0 \<le> (a::int) \<Longrightarrow>
       
   403     a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b"
       
   404   by (auto simp add: cong_int_def mod_pos_pos_trivial)
       
   405 
       
   406 lemma nat_cong_less_unique:
       
   407     "0 < (m::nat) \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))"
       
   408   apply auto
       
   409   apply (rule_tac x = "a mod m" in exI)
       
   410   apply (unfold cong_nat_def, auto)
       
   411 done
       
   412 
       
   413 lemma int_cong_less_unique:
       
   414     "0 < (m::int) \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))"
       
   415   apply auto
       
   416   apply (rule_tac x = "a mod m" in exI)
       
   417   apply (unfold cong_int_def, auto simp add: mod_pos_pos_trivial)
       
   418 done
       
   419 
       
   420 lemma int_cong_iff_lin: "([(a::int) = b] (mod m)) = (\<exists>k. b = a + m * k)"
       
   421   apply (auto simp add: int_cong_altdef dvd_def ring_simps)
       
   422   apply (rule_tac [!] x = "-k" in exI, auto)
       
   423 done
       
   424 
       
   425 lemma nat_cong_iff_lin: "([(a::nat) = b] (mod m)) = 
       
   426     (\<exists>k1 k2. b + k1 * m = a + k2 * m)"
       
   427   apply (rule iffI)
       
   428   apply (case_tac "b <= a")
       
   429   apply (subst (asm) nat_cong_altdef, assumption)
       
   430   apply (unfold dvd_def, auto)
       
   431   apply (rule_tac x = k in exI)
       
   432   apply (rule_tac x = 0 in exI)
       
   433   apply (auto simp add: ring_simps)
       
   434   apply (subst (asm) nat_cong_sym_eq)
       
   435   apply (subst (asm) nat_cong_altdef)
       
   436   apply force
       
   437   apply (unfold dvd_def, auto)
       
   438   apply (rule_tac x = 0 in exI)
       
   439   apply (rule_tac x = k in exI)
       
   440   apply (auto simp add: ring_simps)
       
   441   apply (unfold cong_nat_def)
       
   442   apply (subgoal_tac "a mod m = (a + k2 * m) mod m")
       
   443   apply (erule ssubst)back
       
   444   apply (erule subst)
       
   445   apply auto
       
   446 done
       
   447 
       
   448 lemma int_cong_gcd_eq: "[(a::int) = b] (mod m) \<Longrightarrow> gcd a m = gcd b m"
       
   449   apply (subst (asm) int_cong_iff_lin, auto)
       
   450   apply (subst add_commute) 
       
   451   apply (subst (2) int_gcd_commute)
       
   452   apply (subst mult_commute)
       
   453   apply (subst int_gcd_add_mult)
       
   454   apply (rule int_gcd_commute)
       
   455 done
       
   456 
       
   457 lemma nat_cong_gcd_eq: 
       
   458   assumes "[(a::nat) = b] (mod m)"
       
   459   shows "gcd a m = gcd b m"
       
   460 
       
   461   apply (rule int_cong_gcd_eq [transferred])
       
   462   using prems apply auto
       
   463 done
       
   464 
       
   465 lemma nat_cong_imp_coprime: "[(a::nat) = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> 
       
   466     coprime b m"
       
   467   by (auto simp add: nat_cong_gcd_eq)
       
   468 
       
   469 lemma int_cong_imp_coprime: "[(a::int) = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> 
       
   470     coprime b m"
       
   471   by (auto simp add: int_cong_gcd_eq)
       
   472 
       
   473 lemma nat_cong_cong_mod: "[(a::nat) = b] (mod m) = 
       
   474     [a mod m = b mod m] (mod m)"
       
   475   by (auto simp add: cong_nat_def)
       
   476 
       
   477 lemma int_cong_cong_mod: "[(a::int) = b] (mod m) = 
       
   478     [a mod m = b mod m] (mod m)"
       
   479   by (auto simp add: cong_int_def)
       
   480 
       
   481 lemma int_cong_minus [iff]: "[(a::int) = b] (mod -m) = [a = b] (mod m)"
       
   482   by (subst (1 2) int_cong_altdef, auto)
       
   483 
       
   484 lemma nat_cong_zero [iff]: "[(a::nat) = b] (mod 0) = (a = b)"
       
   485   by (auto simp add: cong_nat_def)
       
   486 
       
   487 lemma int_cong_zero [iff]: "[(a::int) = b] (mod 0) = (a = b)"
       
   488   by (auto simp add: cong_int_def)
       
   489 
       
   490 (*
       
   491 lemma int_mod_dvd_mod:
       
   492     "0 < (m::int) \<Longrightarrow> m dvd b \<Longrightarrow> (a mod b mod m) = (a mod m)"
       
   493   apply (unfold dvd_def, auto)
       
   494   apply (rule mod_mod_cancel)
       
   495   apply auto
       
   496 done
       
   497 
       
   498 lemma mod_dvd_mod:
       
   499   assumes "0 < (m::nat)" and "m dvd b"
       
   500   shows "(a mod b mod m) = (a mod m)"
       
   501 
       
   502   apply (rule int_mod_dvd_mod [transferred])
       
   503   using prems apply auto
       
   504 done
       
   505 *)
       
   506 
       
   507 lemma nat_cong_add_lcancel: 
       
   508     "[(a::nat) + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" 
       
   509   by (simp add: nat_cong_iff_lin)
       
   510 
       
   511 lemma int_cong_add_lcancel: 
       
   512     "[(a::int) + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" 
       
   513   by (simp add: int_cong_iff_lin)
       
   514 
       
   515 lemma nat_cong_add_rcancel: "[(x::nat) + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
       
   516   by (simp add: nat_cong_iff_lin)
       
   517 
       
   518 lemma int_cong_add_rcancel: "[(x::int) + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
       
   519   by (simp add: int_cong_iff_lin)
       
   520 
       
   521 lemma nat_cong_add_lcancel_0: "[(a::nat) + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
       
   522   by (simp add: nat_cong_iff_lin)
       
   523 
       
   524 lemma int_cong_add_lcancel_0: "[(a::int) + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
       
   525   by (simp add: int_cong_iff_lin)
       
   526 
       
   527 lemma nat_cong_add_rcancel_0: "[x + (a::nat) = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
       
   528   by (simp add: nat_cong_iff_lin)
       
   529 
       
   530 lemma int_cong_add_rcancel_0: "[x + (a::int) = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
       
   531   by (simp add: int_cong_iff_lin)
       
   532 
       
   533 lemma nat_cong_dvd_modulus: "[(x::nat) = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> 
       
   534     [x = y] (mod n)"
       
   535   apply (auto simp add: nat_cong_iff_lin dvd_def)
       
   536   apply (rule_tac x="k1 * k" in exI)
       
   537   apply (rule_tac x="k2 * k" in exI)
       
   538   apply (simp add: ring_simps)
       
   539 done
       
   540 
       
   541 lemma int_cong_dvd_modulus: "[(x::int) = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> 
       
   542     [x = y] (mod n)"
       
   543   by (auto simp add: int_cong_altdef dvd_def)
       
   544 
       
   545 lemma nat_cong_dvd_eq: "[(x::nat) = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y"
       
   546   by (unfold cong_nat_def, auto simp add: dvd_eq_mod_eq_0)
       
   547 
       
   548 lemma int_cong_dvd_eq: "[(x::int) = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y"
       
   549   by (unfold cong_int_def, auto simp add: dvd_eq_mod_eq_0)
       
   550 
       
   551 lemma nat_cong_mod: "(n::nat) ~= 0 \<Longrightarrow> [a mod n = a] (mod n)" 
       
   552   by (simp add: cong_nat_def)
       
   553 
       
   554 lemma int_cong_mod: "(n::int) ~= 0 \<Longrightarrow> [a mod n = a] (mod n)" 
       
   555   by (simp add: cong_int_def)
       
   556 
       
   557 lemma nat_mod_mult_cong: "(a::nat) ~= 0 \<Longrightarrow> b ~= 0 
       
   558     \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)"
       
   559   by (simp add: cong_nat_def mod_mult2_eq  mod_add_left_eq)
       
   560 
       
   561 lemma int_neg_cong: "([(a::int) = b] (mod m)) = ([-a = -b] (mod m))"
       
   562   apply (simp add: int_cong_altdef)
       
   563   apply (subst dvd_minus_iff [symmetric])
       
   564   apply (simp add: ring_simps)
       
   565 done
       
   566 
       
   567 lemma int_cong_modulus_neg: "([(a::int) = b] (mod m)) = ([a = b] (mod -m))"
       
   568   by (auto simp add: int_cong_altdef)
       
   569 
       
   570 lemma int_mod_mult_cong: "(a::int) ~= 0 \<Longrightarrow> b ~= 0 
       
   571     \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)"
       
   572   apply (case_tac "b > 0")
       
   573   apply (simp add: cong_int_def mod_mod_cancel mod_add_left_eq)
       
   574   apply (subst (1 2) int_cong_modulus_neg)
       
   575   apply (unfold cong_int_def)
       
   576   apply (subgoal_tac "a * b = (-a * -b)")
       
   577   apply (erule ssubst)
       
   578   apply (subst zmod_zmult2_eq)
       
   579   apply (auto simp add: mod_add_left_eq) 
       
   580 done
       
   581 
       
   582 lemma nat_cong_to_1: "([(a::nat) = 1] (mod n)) \<Longrightarrow> (n dvd (a - 1))"
       
   583   apply (case_tac "a = 0")
       
   584   apply force
       
   585   apply (subst (asm) nat_cong_altdef)
       
   586   apply auto
       
   587 done
       
   588 
       
   589 lemma nat_0_cong_1: "[(0::nat) = 1] (mod n) = (n = 1)"
       
   590   by (unfold cong_nat_def, auto)
       
   591 
       
   592 lemma int_0_cong_1: "[(0::int) = 1] (mod n) = ((n = 1) | (n = -1))"
       
   593   by (unfold cong_int_def, auto simp add: zmult_eq_1_iff)
       
   594 
       
   595 lemma nat_cong_to_1': "[(a::nat) = 1] (mod n) \<longleftrightarrow> 
       
   596     a = 0 \<and> n = 1 \<or> (\<exists>m. a = 1 + m * n)"
       
   597   apply (case_tac "n = 1")
       
   598   apply auto [1]
       
   599   apply (drule_tac x = "a - 1" in spec)
       
   600   apply force
       
   601   apply (case_tac "a = 0")
       
   602   apply (auto simp add: nat_0_cong_1) [1]
       
   603   apply (rule iffI)
       
   604   apply (drule nat_cong_to_1)
       
   605   apply (unfold dvd_def)
       
   606   apply auto [1]
       
   607   apply (rule_tac x = k in exI)
       
   608   apply (auto simp add: ring_simps) [1]
       
   609   apply (subst nat_cong_altdef)
       
   610   apply (auto simp add: dvd_def)
       
   611 done
       
   612 
       
   613 lemma nat_cong_le: "(y::nat) <= x \<Longrightarrow> [x = y] (mod n) \<longleftrightarrow> (\<exists>q. x = q * n + y)"
       
   614   apply (subst nat_cong_altdef)
       
   615   apply assumption
       
   616   apply (unfold dvd_def, auto simp add: ring_simps)
       
   617   apply (rule_tac x = k in exI)
       
   618   apply auto
       
   619 done
       
   620 
       
   621 lemma nat_cong_solve: "(a::nat) \<noteq> 0 \<Longrightarrow> EX x. [a * x = gcd a n] (mod n)"
       
   622   apply (case_tac "n = 0")
       
   623   apply force
       
   624   apply (frule nat_bezout [of a n], auto)
       
   625   apply (rule exI, erule ssubst)
       
   626   apply (rule nat_cong_trans)
       
   627   apply (rule nat_cong_add)
       
   628   apply (subst mult_commute)
       
   629   apply (rule nat_cong_mult_self)
       
   630   prefer 2
       
   631   apply simp
       
   632   apply (rule nat_cong_refl)
       
   633   apply (rule nat_cong_refl)
       
   634 done
       
   635 
       
   636 lemma int_cong_solve: "(a::int) \<noteq> 0 \<Longrightarrow> EX x. [a * x = gcd a n] (mod n)"
       
   637   apply (case_tac "n = 0")
       
   638   apply (case_tac "a \<ge> 0")
       
   639   apply auto
       
   640   apply (rule_tac x = "-1" in exI)
       
   641   apply auto
       
   642   apply (insert int_bezout [of a n], auto)
       
   643   apply (rule exI)
       
   644   apply (erule subst)
       
   645   apply (rule int_cong_trans)
       
   646   prefer 2
       
   647   apply (rule int_cong_add)
       
   648   apply (rule int_cong_refl)
       
   649   apply (rule int_cong_sym)
       
   650   apply (rule int_cong_mult_self)
       
   651   apply simp
       
   652   apply (subst mult_commute)
       
   653   apply (rule int_cong_refl)
       
   654 done
       
   655   
       
   656 lemma nat_cong_solve_dvd: 
       
   657   assumes a: "(a::nat) \<noteq> 0" and b: "gcd a n dvd d"
       
   658   shows "EX x. [a * x = d] (mod n)"
       
   659 proof -
       
   660   from nat_cong_solve [OF a] obtain x where 
       
   661       "[a * x = gcd a n](mod n)"
       
   662     by auto
       
   663   hence "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" 
       
   664     by (elim nat_cong_scalar2)
       
   665   also from b have "(d div gcd a n) * gcd a n = d"
       
   666     by (rule dvd_div_mult_self)
       
   667   also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)"
       
   668     by auto
       
   669   finally show ?thesis
       
   670     by auto
       
   671 qed
       
   672 
       
   673 lemma int_cong_solve_dvd: 
       
   674   assumes a: "(a::int) \<noteq> 0" and b: "gcd a n dvd d"
       
   675   shows "EX x. [a * x = d] (mod n)"
       
   676 proof -
       
   677   from int_cong_solve [OF a] obtain x where 
       
   678       "[a * x = gcd a n](mod n)"
       
   679     by auto
       
   680   hence "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" 
       
   681     by (elim int_cong_scalar2)
       
   682   also from b have "(d div gcd a n) * gcd a n = d"
       
   683     by (rule dvd_div_mult_self)
       
   684   also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)"
       
   685     by auto
       
   686   finally show ?thesis
       
   687     by auto
       
   688 qed
       
   689 
       
   690 lemma nat_cong_solve_coprime: "coprime (a::nat) n \<Longrightarrow> 
       
   691     EX x. [a * x = 1] (mod n)"
       
   692   apply (case_tac "a = 0")
       
   693   apply force
       
   694   apply (frule nat_cong_solve [of a n])
       
   695   apply auto
       
   696 done
       
   697 
       
   698 lemma int_cong_solve_coprime: "coprime (a::int) n \<Longrightarrow> 
       
   699     EX x. [a * x = 1] (mod n)"
       
   700   apply (case_tac "a = 0")
       
   701   apply auto
       
   702   apply (case_tac "n \<ge> 0")
       
   703   apply auto
       
   704   apply (subst cong_int_def, auto)
       
   705   apply (frule int_cong_solve [of a n])
       
   706   apply auto
       
   707 done
       
   708 
       
   709 lemma nat_coprime_iff_invertible: "m > (1::nat) \<Longrightarrow> coprime a m = 
       
   710     (EX x. [a * x = 1] (mod m))"
       
   711   apply (auto intro: nat_cong_solve_coprime)
       
   712   apply (unfold cong_nat_def, auto intro: nat_invertible_coprime)
       
   713 done
       
   714 
       
   715 lemma int_coprime_iff_invertible: "m > (1::int) \<Longrightarrow> coprime a m = 
       
   716     (EX x. [a * x = 1] (mod m))"
       
   717   apply (auto intro: int_cong_solve_coprime)
       
   718   apply (unfold cong_int_def)
       
   719   apply (auto intro: int_invertible_coprime)
       
   720 done
       
   721 
       
   722 lemma int_coprime_iff_invertible': "m > (1::int) \<Longrightarrow> coprime a m = 
       
   723     (EX x. 0 <= x & x < m & [a * x = 1] (mod m))"
       
   724   apply (subst int_coprime_iff_invertible)
       
   725   apply auto
       
   726   apply (auto simp add: cong_int_def)
       
   727   apply (rule_tac x = "x mod m" in exI)
       
   728   apply (auto simp add: mod_mult_right_eq [symmetric])
       
   729 done
       
   730 
       
   731 
       
   732 lemma nat_cong_cong_lcm: "[(x::nat) = y] (mod a) \<Longrightarrow>
       
   733     [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)"
       
   734   apply (case_tac "y \<le> x")
       
   735   apply (auto simp add: nat_cong_altdef nat_lcm_least) [1]
       
   736   apply (rule nat_cong_sym)
       
   737   apply (subst (asm) (1 2) nat_cong_sym_eq)
       
   738   apply (auto simp add: nat_cong_altdef nat_lcm_least)
       
   739 done
       
   740 
       
   741 lemma int_cong_cong_lcm: "[(x::int) = y] (mod a) \<Longrightarrow>
       
   742     [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)"
       
   743   by (auto simp add: int_cong_altdef int_lcm_least) [1]
       
   744 
       
   745 lemma nat_cong_cong_coprime: "coprime a b \<Longrightarrow> [(x::nat) = y] (mod a) \<Longrightarrow>
       
   746     [x = y] (mod b) \<Longrightarrow> [x = y] (mod a * b)"
       
   747   apply (frule (1) nat_cong_cong_lcm)back
       
   748   apply (simp add: lcm_nat_def)
       
   749 done
       
   750 
       
   751 lemma int_cong_cong_coprime: "coprime a b \<Longrightarrow> [(x::int) = y] (mod a) \<Longrightarrow>
       
   752     [x = y] (mod b) \<Longrightarrow> [x = y] (mod a * b)"
       
   753   apply (frule (1) int_cong_cong_lcm)back
       
   754   apply (simp add: int_lcm_altdef int_cong_abs abs_mult [symmetric])
       
   755 done
       
   756 
       
   757 lemma nat_cong_cong_setprod_coprime [rule_format]: "finite A \<Longrightarrow>
       
   758     (ALL i:A. (ALL j:A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow>
       
   759     (ALL i:A. [(x::nat) = y] (mod m i)) \<longrightarrow>
       
   760       [x = y] (mod (PROD i:A. m i))"
       
   761   apply (induct set: finite)
       
   762   apply auto
       
   763   apply (rule nat_cong_cong_coprime)
       
   764   apply (subst nat_gcd_commute)
       
   765   apply (rule nat_setprod_coprime)
       
   766   apply auto
       
   767 done
       
   768 
       
   769 lemma int_cong_cong_setprod_coprime [rule_format]: "finite A \<Longrightarrow>
       
   770     (ALL i:A. (ALL j:A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow>
       
   771     (ALL i:A. [(x::int) = y] (mod m i)) \<longrightarrow>
       
   772       [x = y] (mod (PROD i:A. m i))"
       
   773   apply (induct set: finite)
       
   774   apply auto
       
   775   apply (rule int_cong_cong_coprime)
       
   776   apply (subst int_gcd_commute)
       
   777   apply (rule int_setprod_coprime)
       
   778   apply auto
       
   779 done
       
   780 
       
   781 lemma nat_binary_chinese_remainder_aux: 
       
   782   assumes a: "coprime (m1::nat) m2"
       
   783   shows "EX b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and>
       
   784     [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)"
       
   785 proof -
       
   786   from nat_cong_solve_coprime [OF a]
       
   787       obtain x1 where one: "[m1 * x1 = 1] (mod m2)"
       
   788     by auto
       
   789   from a have b: "coprime m2 m1" 
       
   790     by (subst nat_gcd_commute)
       
   791   from nat_cong_solve_coprime [OF b]
       
   792       obtain x2 where two: "[m2 * x2 = 1] (mod m1)"
       
   793     by auto
       
   794   have "[m1 * x1 = 0] (mod m1)"
       
   795     by (subst mult_commute, rule nat_cong_mult_self)
       
   796   moreover have "[m2 * x2 = 0] (mod m2)"
       
   797     by (subst mult_commute, rule nat_cong_mult_self)
       
   798   moreover note one two
       
   799   ultimately show ?thesis by blast
       
   800 qed
       
   801 
       
   802 lemma int_binary_chinese_remainder_aux: 
       
   803   assumes a: "coprime (m1::int) m2"
       
   804   shows "EX b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and>
       
   805     [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)"
       
   806 proof -
       
   807   from int_cong_solve_coprime [OF a]
       
   808       obtain x1 where one: "[m1 * x1 = 1] (mod m2)"
       
   809     by auto
       
   810   from a have b: "coprime m2 m1" 
       
   811     by (subst int_gcd_commute)
       
   812   from int_cong_solve_coprime [OF b]
       
   813       obtain x2 where two: "[m2 * x2 = 1] (mod m1)"
       
   814     by auto
       
   815   have "[m1 * x1 = 0] (mod m1)"
       
   816     by (subst mult_commute, rule int_cong_mult_self)
       
   817   moreover have "[m2 * x2 = 0] (mod m2)"
       
   818     by (subst mult_commute, rule int_cong_mult_self)
       
   819   moreover note one two
       
   820   ultimately show ?thesis by blast
       
   821 qed
       
   822 
       
   823 lemma nat_binary_chinese_remainder:
       
   824   assumes a: "coprime (m1::nat) m2"
       
   825   shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
       
   826 proof -
       
   827   from nat_binary_chinese_remainder_aux [OF a] obtain b1 b2
       
   828     where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" and
       
   829           "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)"
       
   830     by blast
       
   831   let ?x = "u1 * b1 + u2 * b2"
       
   832   have "[?x = u1 * 1 + u2 * 0] (mod m1)"
       
   833     apply (rule nat_cong_add)
       
   834     apply (rule nat_cong_scalar2)
       
   835     apply (rule `[b1 = 1] (mod m1)`)
       
   836     apply (rule nat_cong_scalar2)
       
   837     apply (rule `[b2 = 0] (mod m1)`)
       
   838     done
       
   839   hence "[?x = u1] (mod m1)" by simp
       
   840   have "[?x = u1 * 0 + u2 * 1] (mod m2)"
       
   841     apply (rule nat_cong_add)
       
   842     apply (rule nat_cong_scalar2)
       
   843     apply (rule `[b1 = 0] (mod m2)`)
       
   844     apply (rule nat_cong_scalar2)
       
   845     apply (rule `[b2 = 1] (mod m2)`)
       
   846     done
       
   847   hence "[?x = u2] (mod m2)" by simp
       
   848   with `[?x = u1] (mod m1)` show ?thesis by blast
       
   849 qed
       
   850 
       
   851 lemma int_binary_chinese_remainder:
       
   852   assumes a: "coprime (m1::int) m2"
       
   853   shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
       
   854 proof -
       
   855   from int_binary_chinese_remainder_aux [OF a] obtain b1 b2
       
   856     where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" and
       
   857           "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)"
       
   858     by blast
       
   859   let ?x = "u1 * b1 + u2 * b2"
       
   860   have "[?x = u1 * 1 + u2 * 0] (mod m1)"
       
   861     apply (rule int_cong_add)
       
   862     apply (rule int_cong_scalar2)
       
   863     apply (rule `[b1 = 1] (mod m1)`)
       
   864     apply (rule int_cong_scalar2)
       
   865     apply (rule `[b2 = 0] (mod m1)`)
       
   866     done
       
   867   hence "[?x = u1] (mod m1)" by simp
       
   868   have "[?x = u1 * 0 + u2 * 1] (mod m2)"
       
   869     apply (rule int_cong_add)
       
   870     apply (rule int_cong_scalar2)
       
   871     apply (rule `[b1 = 0] (mod m2)`)
       
   872     apply (rule int_cong_scalar2)
       
   873     apply (rule `[b2 = 1] (mod m2)`)
       
   874     done
       
   875   hence "[?x = u2] (mod m2)" by simp
       
   876   with `[?x = u1] (mod m1)` show ?thesis by blast
       
   877 qed
       
   878 
       
   879 lemma nat_cong_modulus_mult: "[(x::nat) = y] (mod m * n) \<Longrightarrow> 
       
   880     [x = y] (mod m)"
       
   881   apply (case_tac "y \<le> x")
       
   882   apply (simp add: nat_cong_altdef)
       
   883   apply (erule dvd_mult_left)
       
   884   apply (rule nat_cong_sym)
       
   885   apply (subst (asm) nat_cong_sym_eq)
       
   886   apply (simp add: nat_cong_altdef) 
       
   887   apply (erule dvd_mult_left)
       
   888 done
       
   889 
       
   890 lemma int_cong_modulus_mult: "[(x::int) = y] (mod m * n) \<Longrightarrow> 
       
   891     [x = y] (mod m)"
       
   892   apply (simp add: int_cong_altdef) 
       
   893   apply (erule dvd_mult_left)
       
   894 done
       
   895 
       
   896 lemma nat_cong_less_modulus_unique: 
       
   897     "[(x::nat) = y] (mod m) \<Longrightarrow> x < m \<Longrightarrow> y < m \<Longrightarrow> x = y"
       
   898   by (simp add: cong_nat_def)
       
   899 
       
   900 lemma nat_binary_chinese_remainder_unique:
       
   901   assumes a: "coprime (m1::nat) m2" and
       
   902          nz: "m1 \<noteq> 0" "m2 \<noteq> 0"
       
   903   shows "EX! x. x < m1 * m2 \<and> [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
       
   904 proof -
       
   905   from nat_binary_chinese_remainder [OF a] obtain y where 
       
   906       "[y = u1] (mod m1)" and "[y = u2] (mod m2)"
       
   907     by blast
       
   908   let ?x = "y mod (m1 * m2)"
       
   909   from nz have less: "?x < m1 * m2"
       
   910     by auto   
       
   911   have one: "[?x = u1] (mod m1)"
       
   912     apply (rule nat_cong_trans)
       
   913     prefer 2
       
   914     apply (rule `[y = u1] (mod m1)`)
       
   915     apply (rule nat_cong_modulus_mult)
       
   916     apply (rule nat_cong_mod)
       
   917     using nz apply auto
       
   918     done
       
   919   have two: "[?x = u2] (mod m2)"
       
   920     apply (rule nat_cong_trans)
       
   921     prefer 2
       
   922     apply (rule `[y = u2] (mod m2)`)
       
   923     apply (subst mult_commute)
       
   924     apply (rule nat_cong_modulus_mult)
       
   925     apply (rule nat_cong_mod)
       
   926     using nz apply auto
       
   927     done
       
   928   have "ALL z. z < m1 * m2 \<and> [z = u1] (mod m1) \<and> [z = u2] (mod m2) \<longrightarrow>
       
   929       z = ?x"
       
   930   proof (clarify)
       
   931     fix z
       
   932     assume "z < m1 * m2"
       
   933     assume "[z = u1] (mod m1)" and  "[z = u2] (mod m2)"
       
   934     have "[?x = z] (mod m1)"
       
   935       apply (rule nat_cong_trans)
       
   936       apply (rule `[?x = u1] (mod m1)`)
       
   937       apply (rule nat_cong_sym)
       
   938       apply (rule `[z = u1] (mod m1)`)
       
   939       done
       
   940     moreover have "[?x = z] (mod m2)"
       
   941       apply (rule nat_cong_trans)
       
   942       apply (rule `[?x = u2] (mod m2)`)
       
   943       apply (rule nat_cong_sym)
       
   944       apply (rule `[z = u2] (mod m2)`)
       
   945       done
       
   946     ultimately have "[?x = z] (mod m1 * m2)"
       
   947       by (auto intro: nat_coprime_cong_mult a)
       
   948     with `z < m1 * m2` `?x < m1 * m2` show "z = ?x"
       
   949       apply (intro nat_cong_less_modulus_unique)
       
   950       apply (auto, erule nat_cong_sym)
       
   951       done
       
   952   qed  
       
   953   with less one two show ?thesis
       
   954     by auto
       
   955  qed
       
   956 
       
   957 lemma nat_chinese_remainder_aux:
       
   958   fixes A :: "'a set" and
       
   959         m :: "'a \<Rightarrow> nat"
       
   960   assumes fin: "finite A" and
       
   961           cop: "ALL i : A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))"
       
   962   shows "EX b. (ALL i : A. 
       
   963       [b i = 1] (mod m i) \<and> [b i = 0] (mod (PROD j : A - {i}. m j)))"
       
   964 proof (rule finite_set_choice, rule fin, rule ballI)
       
   965   fix i
       
   966   assume "i : A"
       
   967   with cop have "coprime (PROD j : A - {i}. m j) (m i)"
       
   968     by (intro nat_setprod_coprime, auto)
       
   969   hence "EX x. [(PROD j : A - {i}. m j) * x = 1] (mod m i)"
       
   970     by (elim nat_cong_solve_coprime)
       
   971   then obtain x where "[(PROD j : A - {i}. m j) * x = 1] (mod m i)"
       
   972     by auto
       
   973   moreover have "[(PROD j : A - {i}. m j) * x = 0] 
       
   974     (mod (PROD j : A - {i}. m j))"
       
   975     by (subst mult_commute, rule nat_cong_mult_self)
       
   976   ultimately show "\<exists>a. [a = 1] (mod m i) \<and> [a = 0] 
       
   977       (mod setprod m (A - {i}))"
       
   978     by blast
       
   979 qed
       
   980 
       
   981 lemma nat_chinese_remainder:
       
   982   fixes A :: "'a set" and
       
   983         m :: "'a \<Rightarrow> nat" and
       
   984         u :: "'a \<Rightarrow> nat"
       
   985   assumes 
       
   986         fin: "finite A" and
       
   987         cop: "ALL i:A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))"
       
   988   shows "EX x. (ALL i:A. [x = u i] (mod m i))"
       
   989 proof -
       
   990   from nat_chinese_remainder_aux [OF fin cop] obtain b where
       
   991     bprop: "ALL i:A. [b i = 1] (mod m i) \<and> 
       
   992       [b i = 0] (mod (PROD j : A - {i}. m j))"
       
   993     by blast
       
   994   let ?x = "SUM i:A. (u i) * (b i)"
       
   995   show "?thesis"
       
   996   proof (rule exI, clarify)
       
   997     fix i
       
   998     assume a: "i : A"
       
   999     show "[?x = u i] (mod m i)" 
       
  1000     proof -
       
  1001       from fin a have "?x = (SUM j:{i}. u j * b j) + 
       
  1002           (SUM j:A-{i}. u j * b j)"
       
  1003         by (subst setsum_Un_disjoint [symmetric], auto intro: setsum_cong)
       
  1004       hence "[?x = u i * b i + (SUM j:A-{i}. u j * b j)] (mod m i)"
       
  1005         by auto
       
  1006       also have "[u i * b i + (SUM j:A-{i}. u j * b j) =
       
  1007                   u i * 1 + (SUM j:A-{i}. u j * 0)] (mod m i)"
       
  1008         apply (rule nat_cong_add)
       
  1009         apply (rule nat_cong_scalar2)
       
  1010         using bprop a apply blast
       
  1011         apply (rule nat_cong_setsum)
       
  1012         apply (rule nat_cong_scalar2)
       
  1013         using bprop apply auto
       
  1014         apply (rule nat_cong_dvd_modulus)
       
  1015         apply (drule (1) bspec)
       
  1016         apply (erule conjE)
       
  1017         apply assumption
       
  1018         apply (rule dvd_setprod)
       
  1019         using fin a apply auto
       
  1020         done
       
  1021       finally show ?thesis
       
  1022         by simp
       
  1023     qed
       
  1024   qed
       
  1025 qed
       
  1026 
       
  1027 lemma nat_coprime_cong_prod [rule_format]: "finite A \<Longrightarrow> 
       
  1028     (ALL i: A. (ALL j: A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow>
       
  1029       (ALL i: A. [(x::nat) = y] (mod m i)) \<longrightarrow>
       
  1030          [x = y] (mod (PROD i:A. m i))" 
       
  1031   apply (induct set: finite)
       
  1032   apply auto
       
  1033   apply (erule (1) nat_coprime_cong_mult)
       
  1034   apply (subst nat_gcd_commute)
       
  1035   apply (rule nat_setprod_coprime)
       
  1036   apply auto
       
  1037 done
       
  1038 
       
  1039 lemma nat_chinese_remainder_unique:
       
  1040   fixes A :: "'a set" and
       
  1041         m :: "'a \<Rightarrow> nat" and
       
  1042         u :: "'a \<Rightarrow> nat"
       
  1043   assumes 
       
  1044         fin: "finite A" and
       
  1045          nz: "ALL i:A. m i \<noteq> 0" and
       
  1046         cop: "ALL i:A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))"
       
  1047   shows "EX! x. x < (PROD i:A. m i) \<and> (ALL i:A. [x = u i] (mod m i))"
       
  1048 proof -
       
  1049   from nat_chinese_remainder [OF fin cop] obtain y where
       
  1050       one: "(ALL i:A. [y = u i] (mod m i))" 
       
  1051     by blast
       
  1052   let ?x = "y mod (PROD i:A. m i)"
       
  1053   from fin nz have prodnz: "(PROD i:A. m i) \<noteq> 0"
       
  1054     by auto
       
  1055   hence less: "?x < (PROD i:A. m i)"
       
  1056     by auto
       
  1057   have cong: "ALL i:A. [?x = u i] (mod m i)"
       
  1058     apply auto
       
  1059     apply (rule nat_cong_trans)
       
  1060     prefer 2
       
  1061     using one apply auto
       
  1062     apply (rule nat_cong_dvd_modulus)
       
  1063     apply (rule nat_cong_mod)
       
  1064     using prodnz apply auto
       
  1065     apply (rule dvd_setprod)
       
  1066     apply (rule fin)
       
  1067     apply assumption
       
  1068     done
       
  1069   have unique: "ALL z. z < (PROD i:A. m i) \<and> 
       
  1070       (ALL i:A. [z = u i] (mod m i)) \<longrightarrow> z = ?x"
       
  1071   proof (clarify)
       
  1072     fix z
       
  1073     assume zless: "z < (PROD i:A. m i)"
       
  1074     assume zcong: "(ALL i:A. [z = u i] (mod m i))"
       
  1075     have "ALL i:A. [?x = z] (mod m i)"
       
  1076       apply clarify     
       
  1077       apply (rule nat_cong_trans)
       
  1078       using cong apply (erule bspec)
       
  1079       apply (rule nat_cong_sym)
       
  1080       using zcong apply auto
       
  1081       done
       
  1082     with fin cop have "[?x = z] (mod (PROD i:A. m i))"
       
  1083       by (intro nat_coprime_cong_prod, auto)
       
  1084     with zless less show "z = ?x"
       
  1085       apply (intro nat_cong_less_modulus_unique)
       
  1086       apply (auto, erule nat_cong_sym)
       
  1087       done
       
  1088   qed 
       
  1089   from less cong unique show ?thesis
       
  1090     by blast  
       
  1091 qed
       
  1092 
       
  1093 end