| 26126 |      1 | (*  Title:      HOL/Library/Pocklington.thy
 | 
| 27368 |      2 |     ID:         $Id$
 | 
| 26126 |      3 |     Author:     Amine Chaieb 
 | 
|  |      4 | *)
 | 
|  |      5 | 
 | 
|  |      6 | header {* Pocklington's Theorem for Primes *}
 | 
|  |      7 | 
 | 
|  |      8 | 
 | 
|  |      9 | theory Pocklington
 | 
| 27487 |     10 | imports Plain "~~/src/HOL/List" "~~/src/HOL/Primes"
 | 
| 26126 |     11 | begin
 | 
|  |     12 | 
 | 
|  |     13 | definition modeq:: "nat => nat => nat => bool"    ("(1[_ = _] '(mod _'))")
 | 
|  |     14 |   where "[a = b] (mod p) == ((a mod p) = (b mod p))"
 | 
|  |     15 | 
 | 
|  |     16 | definition modneq:: "nat => nat => nat => bool"    ("(1[_ \<noteq> _] '(mod _'))")
 | 
|  |     17 |   where "[a \<noteq> b] (mod p) == ((a mod p) \<noteq> (b mod p))"
 | 
|  |     18 | 
 | 
|  |     19 | lemma modeq_trans:
 | 
|  |     20 |   "\<lbrakk> [a = b] (mod p); [b = c] (mod p) \<rbrakk> \<Longrightarrow> [a = c] (mod p)"
 | 
|  |     21 |   by (simp add:modeq_def)
 | 
|  |     22 | 
 | 
|  |     23 | 
 | 
|  |     24 | lemma nat_mod_lemma: assumes xyn: "[x = y] (mod n)" and xy:"y \<le> x"
 | 
|  |     25 |   shows "\<exists>q. x = y + n * q"
 | 
| 27668 |     26 | using xyn xy unfolding modeq_def using nat_mod_eq_lemma by blast
 | 
| 26126 |     27 | 
 | 
| 27668 |     28 | lemma nat_mod[algebra]: "[x = y] (mod n) \<longleftrightarrow> (\<exists>q1 q2. x + n * q1 = y + n * q2)" 
 | 
|  |     29 | unfolding modeq_def nat_mod_eq_iff ..
 | 
| 26126 |     30 | 
 | 
|  |     31 | (* Lemmas about previously defined terms.                                    *)
 | 
|  |     32 | 
 | 
|  |     33 | lemma prime: "prime p \<longleftrightarrow> p \<noteq> 0 \<and> p\<noteq>1 \<and> (\<forall>m. 0 < m \<and> m < p \<longrightarrow> coprime p m)" 
 | 
|  |     34 |   (is "?lhs \<longleftrightarrow> ?rhs") 
 | 
|  |     35 | proof-
 | 
|  |     36 |   {assume "p=0 \<or> p=1" hence ?thesis using prime_0 prime_1 by (cases "p=0", simp_all)}
 | 
|  |     37 |   moreover
 | 
|  |     38 |   {assume p0: "p\<noteq>0" "p\<noteq>1"
 | 
|  |     39 |     {assume H: "?lhs"
 | 
|  |     40 |       {fix m assume m: "m > 0" "m < p"
 | 
|  |     41 | 	{assume "m=1" hence "coprime p m" by simp}
 | 
|  |     42 | 	moreover
 | 
|  |     43 | 	{assume "p dvd m" hence "p \<le> m" using dvd_imp_le m by blast with m(2) 
 | 
|  |     44 | 	  have "coprime p m" by simp}
 | 
|  |     45 | 	ultimately have "coprime p m" using prime_coprime[OF H, of m] by blast}
 | 
|  |     46 |       hence ?rhs using p0 by auto}
 | 
|  |     47 |     moreover
 | 
|  |     48 |     { assume H: "\<forall>m. 0 < m \<and> m < p \<longrightarrow> coprime p m"
 | 
|  |     49 |       from prime_factor[OF p0(2)] obtain q where q: "prime q" "q dvd p" by blast
 | 
|  |     50 |       from prime_ge_2[OF q(1)] have q0: "q > 0" by arith
 | 
|  |     51 |       from dvd_imp_le[OF q(2)] p0 have qp: "q \<le> p" by arith
 | 
|  |     52 |       {assume "q = p" hence ?lhs using q(1) by blast}
 | 
|  |     53 |       moreover
 | 
|  |     54 |       {assume "q\<noteq>p" with qp have qplt: "q < p" by arith
 | 
|  |     55 | 	from H[rule_format, of q] qplt q0 have "coprime p q" by arith
 | 
|  |     56 | 	with coprime_prime[of p q q] q have False by simp hence ?lhs by blast}
 | 
|  |     57 |       ultimately have ?lhs by blast}
 | 
|  |     58 |     ultimately have ?thesis by blast}
 | 
|  |     59 |   ultimately show ?thesis  by (cases"p=0 \<or> p=1", auto)
 | 
|  |     60 | qed
 | 
|  |     61 | 
 | 
|  |     62 | lemma finite_number_segment: "card { m. 0 < m \<and> m < n } = n - 1"
 | 
|  |     63 | proof-
 | 
|  |     64 |   have "{ m. 0 < m \<and> m < n } = {1..<n}" by auto
 | 
|  |     65 |   thus ?thesis by simp
 | 
|  |     66 | qed
 | 
|  |     67 | 
 | 
|  |     68 | lemma coprime_mod: assumes n: "n \<noteq> 0" shows "coprime (a mod n) n \<longleftrightarrow> coprime a n"
 | 
|  |     69 |   using n dvd_mod_iff[of _ n a] by (auto simp add: coprime)
 | 
|  |     70 | 
 | 
|  |     71 | (* Congruences.                                                              *)
 | 
|  |     72 | 
 | 
|  |     73 | lemma cong_mod_01[simp,presburger]: 
 | 
|  |     74 |   "[x = y] (mod 0) \<longleftrightarrow> x = y" "[x = y] (mod 1)" "[x = 0] (mod n) \<longleftrightarrow> n dvd x"
 | 
|  |     75 |   by (simp_all add: modeq_def, presburger)
 | 
|  |     76 | 
 | 
|  |     77 | lemma cong_sub_cases: 
 | 
|  |     78 |   "[x = y] (mod n) \<longleftrightarrow> (if x <= y then [y - x = 0] (mod n) else [x - y = 0] (mod n))"
 | 
|  |     79 | apply (auto simp add: nat_mod)
 | 
|  |     80 | apply (rule_tac x="q2" in exI)
 | 
|  |     81 | apply (rule_tac x="q1" in exI, simp)
 | 
|  |     82 | apply (rule_tac x="q2" in exI)
 | 
|  |     83 | apply (rule_tac x="q1" in exI, simp)
 | 
|  |     84 | apply (rule_tac x="q1" in exI)
 | 
|  |     85 | apply (rule_tac x="q2" in exI, simp)
 | 
|  |     86 | apply (rule_tac x="q1" in exI)
 | 
|  |     87 | apply (rule_tac x="q2" in exI, simp)
 | 
|  |     88 | done
 | 
|  |     89 | 
 | 
|  |     90 | lemma cong_mult_lcancel: assumes an: "coprime a n" and axy:"[a * x = a * y] (mod n)"
 | 
|  |     91 |   shows "[x = y] (mod n)"
 | 
|  |     92 | proof-
 | 
|  |     93 |   {assume "a = 0" with an axy coprime_0'[of n] have ?thesis by (simp add: modeq_def) }
 | 
|  |     94 |   moreover
 | 
|  |     95 |   {assume az: "a\<noteq>0"
 | 
|  |     96 |     {assume xy: "x \<le> y" hence axy': "a*x \<le> a*y" by simp
 | 
|  |     97 |       with axy cong_sub_cases[of "a*x" "a*y" n]  have "[a*(y - x) = 0] (mod n)"
 | 
|  |     98 | 	by (simp only: if_True diff_mult_distrib2) 
 | 
|  |     99 |       hence th: "n dvd a*(y -x)" by simp 
 | 
|  |    100 |       from coprime_divprod[OF th] an have "n dvd y - x"
 | 
|  |    101 | 	by (simp add: coprime_commute)
 | 
|  |    102 |       hence ?thesis using xy cong_sub_cases[of x y n] by simp}
 | 
|  |    103 |     moreover
 | 
|  |    104 |     {assume H: "\<not>x \<le> y" hence xy: "y \<le> x"  by arith 
 | 
|  |    105 |       from H az have axy': "\<not> a*x \<le> a*y" by auto
 | 
|  |    106 |       with axy H cong_sub_cases[of "a*x" "a*y" n]  have "[a*(x - y) = 0] (mod n)"
 | 
|  |    107 | 	by (simp only: if_False diff_mult_distrib2) 
 | 
|  |    108 |       hence th: "n dvd a*(x - y)" by simp 
 | 
|  |    109 |       from coprime_divprod[OF th] an have "n dvd x - y"
 | 
|  |    110 | 	by (simp add: coprime_commute)
 | 
|  |    111 |       hence ?thesis using xy cong_sub_cases[of x y n] by simp}
 | 
|  |    112 |     ultimately have ?thesis by blast}
 | 
|  |    113 |   ultimately show ?thesis by blast
 | 
|  |    114 | qed
 | 
|  |    115 | 
 | 
|  |    116 | lemma cong_mult_rcancel: assumes an: "coprime a n" and axy:"[x*a = y*a] (mod n)"
 | 
|  |    117 |   shows "[x = y] (mod n)"
 | 
|  |    118 |   using cong_mult_lcancel[OF an axy[unfolded mult_commute[of _a]]] .
 | 
|  |    119 | 
 | 
|  |    120 | lemma cong_refl: "[x = x] (mod n)" by (simp add: modeq_def)
 | 
|  |    121 | 
 | 
|  |    122 | lemma eq_imp_cong: "a = b \<Longrightarrow> [a = b] (mod n)" by (simp add: cong_refl)
 | 
|  |    123 | 
 | 
|  |    124 | lemma cong_commute: "[x = y] (mod n) \<longleftrightarrow> [y = x] (mod n)" 
 | 
|  |    125 |   by (auto simp add: modeq_def)
 | 
|  |    126 | 
 | 
|  |    127 | lemma cong_trans[trans]: "[x = y] (mod n) \<Longrightarrow> [y = z] (mod n) \<Longrightarrow> [x = z] (mod n)"
 | 
|  |    128 |   by (simp add: modeq_def)
 | 
|  |    129 | 
 | 
|  |    130 | lemma cong_add: assumes xx': "[x = x'] (mod n)" and yy':"[y = y'] (mod n)"
 | 
|  |    131 |   shows "[x + y = x' + y'] (mod n)"
 | 
|  |    132 | proof-
 | 
|  |    133 |   have "(x + y) mod n = (x mod n + y mod n) mod n"
 | 
|  |    134 |     by (simp add: mod_add_left_eq[of x y n] mod_add_right_eq[of "x mod n" y n])
 | 
|  |    135 |   also have "\<dots> = (x' mod n + y' mod n) mod n" using xx' yy' modeq_def by simp 
 | 
|  |    136 |   also have "\<dots> = (x' + y') mod n"
 | 
|  |    137 |     by (simp add: mod_add_left_eq[of x' y' n] mod_add_right_eq[of "x' mod n" y' n])
 | 
|  |    138 |   finally show ?thesis unfolding modeq_def . 
 | 
|  |    139 | qed
 | 
|  |    140 | 
 | 
|  |    141 | lemma cong_mult: assumes xx': "[x = x'] (mod n)" and yy':"[y = y'] (mod n)"
 | 
|  |    142 |   shows "[x * y = x' * y'] (mod n)"
 | 
|  |    143 | proof-
 | 
|  |    144 |   have "(x * y) mod n = (x mod n) * (y mod n) mod n"  
 | 
|  |    145 |     by (simp add: mod_mult1_eq'[of x y n] mod_mult1_eq[of "x mod n" y n])
 | 
|  |    146 |   also have "\<dots> = (x' mod n) * (y' mod n) mod n" using xx'[unfolded modeq_def] yy'[unfolded modeq_def] by simp  
 | 
|  |    147 |   also have "\<dots> = (x' * y') mod n"
 | 
|  |    148 |     by (simp add: mod_mult1_eq'[of x' y' n] mod_mult1_eq[of "x' mod n" y' n])
 | 
|  |    149 |   finally show ?thesis unfolding modeq_def . 
 | 
|  |    150 | qed
 | 
|  |    151 | 
 | 
|  |    152 | lemma cong_exp: "[x = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)"
 | 
|  |    153 |   by (induct k, auto simp add: cong_refl cong_mult)
 | 
|  |    154 | lemma cong_sub: assumes xx': "[x = x'] (mod n)" and yy': "[y = y'] (mod n)"
 | 
|  |    155 |   and yx: "y <= x" and yx': "y' <= x'"
 | 
|  |    156 |   shows "[x - y = x' - y'] (mod n)"
 | 
|  |    157 | proof-
 | 
|  |    158 |   { fix x a x' a' y b y' b' 
 | 
|  |    159 |     have "(x::nat) + a = x' + a' \<Longrightarrow> y + b = y' + b' \<Longrightarrow> y <= x \<Longrightarrow> y' <= x'
 | 
|  |    160 |       \<Longrightarrow> (x - y) + (a + b') = (x' - y') + (a' + b)" by arith}
 | 
|  |    161 |   note th = this
 | 
|  |    162 |   from xx' yy' obtain q1 q2 q1' q2' where q12: "x + n*q1 = x'+n*q2" 
 | 
|  |    163 |     and q12': "y + n*q1' = y'+n*q2'" unfolding nat_mod by blast+
 | 
|  |    164 |   from th[OF q12 q12' yx yx']
 | 
|  |    165 |   have "(x - y) + n*(q1 + q2') = (x' - y') + n*(q2 + q1')" 
 | 
|  |    166 |     by (simp add: right_distrib)
 | 
|  |    167 |   thus ?thesis unfolding nat_mod by blast
 | 
|  |    168 | qed
 | 
|  |    169 | 
 | 
|  |    170 | lemma cong_mult_lcancel_eq: assumes an: "coprime a n" 
 | 
|  |    171 |   shows "[a * x = a * y] (mod n) \<longleftrightarrow> [x = y] (mod n)" (is "?lhs \<longleftrightarrow> ?rhs")
 | 
|  |    172 | proof
 | 
|  |    173 |   assume H: "?rhs" from cong_mult[OF cong_refl[of a n] H] show ?lhs .
 | 
|  |    174 | next
 | 
|  |    175 |   assume H: "?lhs" hence H': "[x*a = y*a] (mod n)" by (simp add: mult_commute)
 | 
|  |    176 |   from cong_mult_rcancel[OF an H'] show ?rhs  .
 | 
|  |    177 | qed
 | 
|  |    178 | 
 | 
|  |    179 | lemma cong_mult_rcancel_eq: assumes an: "coprime a n" 
 | 
|  |    180 |   shows "[x * a = y * a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
 | 
|  |    181 | using cong_mult_lcancel_eq[OF an, of x y] by (simp add: mult_commute)
 | 
|  |    182 | 
 | 
|  |    183 | lemma cong_add_lcancel_eq: "[a + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" 
 | 
|  |    184 |   by (simp add: nat_mod)
 | 
|  |    185 | 
 | 
|  |    186 | lemma cong_add_rcancel_eq: "[x + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
 | 
|  |    187 |   by (simp add: nat_mod)
 | 
|  |    188 | 
 | 
|  |    189 | lemma cong_add_rcancel: "[x + a = y + a] (mod n) \<Longrightarrow> [x = y] (mod n)" 
 | 
|  |    190 |   by (simp add: nat_mod)
 | 
|  |    191 | 
 | 
|  |    192 | lemma cong_add_lcancel: "[a + x = a + y] (mod n) \<Longrightarrow> [x = y] (mod n)"
 | 
|  |    193 |   by (simp add: nat_mod)
 | 
|  |    194 | 
 | 
|  |    195 | lemma cong_add_lcancel_eq_0: "[a + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
 | 
|  |    196 |   by (simp add: nat_mod)
 | 
|  |    197 | 
 | 
|  |    198 | lemma cong_add_rcancel_eq_0: "[x + a = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)"
 | 
|  |    199 |   by (simp add: nat_mod)
 | 
|  |    200 | 
 | 
|  |    201 | lemma cong_imp_eq: assumes xn: "x < n" and yn: "y < n" and xy: "[x = y] (mod n)"
 | 
|  |    202 |   shows "x = y"
 | 
|  |    203 |   using xy[unfolded modeq_def mod_less[OF xn] mod_less[OF yn]] . 
 | 
|  |    204 | 
 | 
|  |    205 | lemma cong_divides_modulus: "[x = y] (mod m) \<Longrightarrow> n dvd m ==> [x = y] (mod n)"
 | 
|  |    206 |   apply (auto simp add: nat_mod dvd_def)
 | 
|  |    207 |   apply (rule_tac x="k*q1" in exI)
 | 
|  |    208 |   apply (rule_tac x="k*q2" in exI)
 | 
|  |    209 |   by simp
 | 
|  |    210 |   
 | 
|  |    211 | lemma cong_0_divides: "[x = 0] (mod n) \<longleftrightarrow> n dvd x" by simp
 | 
|  |    212 | 
 | 
|  |    213 | lemma cong_1_divides:"[x = 1] (mod n) ==> n dvd x - 1"
 | 
|  |    214 |   apply (cases "x\<le>1", simp_all)
 | 
|  |    215 |   using cong_sub_cases[of x 1 n] by auto
 | 
|  |    216 | 
 | 
|  |    217 | lemma cong_divides: "[x = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y"
 | 
|  |    218 | apply (auto simp add: nat_mod dvd_def)
 | 
|  |    219 | apply (rule_tac x="k + q1 - q2" in exI, simp add: add_mult_distrib2 diff_mult_distrib2)
 | 
|  |    220 | apply (rule_tac x="k + q2 - q1" in exI, simp add: add_mult_distrib2 diff_mult_distrib2)
 | 
|  |    221 | done
 | 
|  |    222 | 
 | 
|  |    223 | lemma cong_coprime: assumes xy: "[x = y] (mod n)" 
 | 
|  |    224 |   shows "coprime n x \<longleftrightarrow> coprime n y"
 | 
|  |    225 | proof-
 | 
|  |    226 |   {assume "n=0" hence ?thesis using xy by simp}
 | 
|  |    227 |   moreover
 | 
|  |    228 |   {assume nz: "n \<noteq> 0"
 | 
|  |    229 |   have "coprime n x \<longleftrightarrow> coprime (x mod n) n" 
 | 
|  |    230 |     by (simp add: coprime_mod[OF nz, of x] coprime_commute[of n x])
 | 
|  |    231 |   also have "\<dots> \<longleftrightarrow> coprime (y mod n) n" using xy[unfolded modeq_def] by simp
 | 
|  |    232 |   also have "\<dots> \<longleftrightarrow> coprime y n" by (simp add: coprime_mod[OF nz, of y])
 | 
|  |    233 |   finally have ?thesis by (simp add: coprime_commute) }
 | 
|  |    234 | ultimately show ?thesis by blast
 | 
|  |    235 | qed
 | 
|  |    236 | 
 | 
|  |    237 | lemma cong_mod: "~(n = 0) \<Longrightarrow> [a mod n = a] (mod n)" by (simp add: modeq_def)
 | 
|  |    238 | 
 | 
|  |    239 | lemma mod_mult_cong: "~(a = 0) \<Longrightarrow> ~(b = 0) 
 | 
|  |    240 |   \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)"
 | 
|  |    241 |   by (simp add: modeq_def mod_mult2_eq mod_add_left_eq)
 | 
|  |    242 | 
 | 
|  |    243 | lemma cong_mod_mult: "[x = y] (mod n) \<Longrightarrow> m dvd n \<Longrightarrow> [x = y] (mod m)"
 | 
|  |    244 |   apply (auto simp add: nat_mod dvd_def)
 | 
|  |    245 |   apply (rule_tac x="k*q1" in exI)
 | 
|  |    246 |   apply (rule_tac x="k*q2" in exI, simp)
 | 
|  |    247 |   done
 | 
|  |    248 | 
 | 
|  |    249 | (* Some things when we know more about the order.                            *)
 | 
|  |    250 | 
 | 
|  |    251 | lemma cong_le: "y <= x \<Longrightarrow> [x = y] (mod n) \<longleftrightarrow> (\<exists>q. x = q * n + y)"
 | 
|  |    252 |   using nat_mod_lemma[of x y n]
 | 
|  |    253 |   apply auto
 | 
|  |    254 |   apply (simp add: nat_mod)
 | 
|  |    255 |   apply (rule_tac x="q" in exI)
 | 
|  |    256 |   apply (rule_tac x="q + q" in exI)
 | 
|  |    257 |   by (auto simp: ring_simps)
 | 
|  |    258 | 
 | 
|  |    259 | lemma cong_to_1: "[a = 1] (mod n) \<longleftrightarrow> a = 0 \<and> n = 1 \<or> (\<exists>m. a = 1 + m * n)"
 | 
|  |    260 | proof-
 | 
|  |    261 |   {assume "n = 0 \<or> n = 1\<or> a = 0 \<or> a = 1" hence ?thesis 
 | 
|  |    262 |       apply (cases "n=0", simp_all add: cong_commute)
 | 
|  |    263 |       apply (cases "n=1", simp_all add: cong_commute modeq_def)
 | 
|  |    264 |       apply arith 
 | 
|  |    265 |       by (cases "a=1", simp_all add: modeq_def cong_commute)}
 | 
|  |    266 |   moreover
 | 
|  |    267 |   {assume n: "n\<noteq>0" "n\<noteq>1" and a:"a\<noteq>0" "a \<noteq> 1" hence a': "a \<ge> 1" by simp
 | 
|  |    268 |     hence ?thesis using cong_le[OF a', of n] by auto }
 | 
|  |    269 |   ultimately show ?thesis by auto
 | 
|  |    270 | qed
 | 
|  |    271 | 
 | 
|  |    272 | (* Some basic theorems about solving congruences.                            *)
 | 
|  |    273 | 
 | 
|  |    274 | 
 | 
|  |    275 | lemma cong_solve: assumes an: "coprime a n" shows "\<exists>x. [a * x = b] (mod n)"
 | 
|  |    276 | proof-
 | 
|  |    277 |   {assume "a=0" hence ?thesis using an by (simp add: modeq_def)}
 | 
|  |    278 |   moreover
 | 
|  |    279 |   {assume az: "a\<noteq>0"
 | 
|  |    280 |   from bezout_add_strong[OF az, of n] 
 | 
|  |    281 |   obtain d x y where dxy: "d dvd a" "d dvd n" "a*x = n*y + d" by blast
 | 
|  |    282 |   from an[unfolded coprime, rule_format, of d] dxy(1,2) have d1: "d = 1" by blast
 | 
|  |    283 |   hence "a*x*b = (n*y + 1)*b" using dxy(3) by simp
 | 
|  |    284 |   hence "a*(x*b) = n*(y*b) + b" by algebra
 | 
|  |    285 |   hence "a*(x*b) mod n = (n*(y*b) + b) mod n" by simp
 | 
|  |    286 |   hence "a*(x*b) mod n = b mod n" by (simp add: mod_add_left_eq)
 | 
|  |    287 |   hence "[a*(x*b) = b] (mod n)" unfolding modeq_def .
 | 
|  |    288 |   hence ?thesis by blast}
 | 
|  |    289 | ultimately  show ?thesis by blast
 | 
|  |    290 | qed
 | 
|  |    291 | 
 | 
|  |    292 | lemma cong_solve_unique: assumes an: "coprime a n" and nz: "n \<noteq> 0"
 | 
|  |    293 |   shows "\<exists>!x. x < n \<and> [a * x = b] (mod n)"
 | 
|  |    294 | proof-
 | 
|  |    295 |   let ?P = "\<lambda>x. x < n \<and> [a * x = b] (mod n)"
 | 
|  |    296 |   from cong_solve[OF an] obtain x where x: "[a*x = b] (mod n)" by blast
 | 
|  |    297 |   let ?x = "x mod n"
 | 
|  |    298 |   from x have th: "[a * ?x = b] (mod n)"
 | 
|  |    299 |     by (simp add: modeq_def mod_mult1_eq[of a x n])
 | 
|  |    300 |   from mod_less_divisor[ of n x] nz th have Px: "?P ?x" by simp
 | 
|  |    301 |   {fix y assume Py: "y < n" "[a * y = b] (mod n)"
 | 
|  |    302 |     from Py(2) th have "[a * y = a*?x] (mod n)" by (simp add: modeq_def)
 | 
|  |    303 |     hence "[y = ?x] (mod n)" by (simp add: cong_mult_lcancel_eq[OF an])
 | 
|  |    304 |     with mod_less[OF Py(1)] mod_less_divisor[ of n x] nz
 | 
|  |    305 |     have "y = ?x" by (simp add: modeq_def)}
 | 
|  |    306 |   with Px show ?thesis by blast
 | 
|  |    307 | qed
 | 
|  |    308 | 
 | 
|  |    309 | lemma cong_solve_unique_nontrivial:
 | 
|  |    310 |   assumes p: "prime p" and pa: "coprime p a" and x0: "0 < x" and xp: "x < p"
 | 
|  |    311 |   shows "\<exists>!y. 0 < y \<and> y < p \<and> [x * y = a] (mod p)"
 | 
|  |    312 | proof-
 | 
|  |    313 |   from p have p1: "p > 1" using prime_ge_2[OF p] by arith
 | 
|  |    314 |   hence p01: "p \<noteq> 0" "p \<noteq> 1" by arith+
 | 
|  |    315 |   from pa have ap: "coprime a p" by (simp add: coprime_commute)
 | 
|  |    316 |   from prime_coprime[OF p, of x] dvd_imp_le[of p x] x0 xp have px:"coprime x p"
 | 
|  |    317 |     by (auto simp add: coprime_commute)
 | 
|  |    318 |   from cong_solve_unique[OF px p01(1)] 
 | 
|  |    319 |   obtain y where y: "y < p" "[x * y = a] (mod p)" "\<forall>z. z < p \<and> [x * z = a] (mod p) \<longrightarrow> z = y" by blast
 | 
|  |    320 |   {assume y0: "y = 0"
 | 
|  |    321 |     with y(2) have th: "p dvd a" by (simp add: cong_commute[of 0 a p])
 | 
|  |    322 |     with p coprime_prime[OF pa, of p] have False by simp}
 | 
|  |    323 |   with y show ?thesis unfolding Ex1_def using neq0_conv by blast 
 | 
|  |    324 | qed
 | 
|  |    325 | lemma cong_unique_inverse_prime:
 | 
|  |    326 |   assumes p: "prime p" and x0: "0 < x" and xp: "x < p"
 | 
|  |    327 |   shows "\<exists>!y. 0 < y \<and> y < p \<and> [x * y = 1] (mod p)"
 | 
|  |    328 |   using cong_solve_unique_nontrivial[OF p coprime_1[of p] x0 xp] .
 | 
|  |    329 | 
 | 
|  |    330 | (* Forms of the Chinese remainder theorem.                                   *)
 | 
|  |    331 | 
 | 
|  |    332 | lemma cong_chinese: 
 | 
|  |    333 |   assumes ab: "coprime a b" and  xya: "[x = y] (mod a)" 
 | 
|  |    334 |   and xyb: "[x = y] (mod b)"
 | 
|  |    335 |   shows "[x = y] (mod a*b)"
 | 
|  |    336 |   using ab xya xyb
 | 
|  |    337 |   by (simp add: cong_sub_cases[of x y a] cong_sub_cases[of x y b] 
 | 
|  |    338 |     cong_sub_cases[of x y "a*b"]) 
 | 
|  |    339 | (cases "x \<le> y", simp_all add: divides_mul[of a _ b])
 | 
|  |    340 | 
 | 
|  |    341 | lemma chinese_remainder_unique:
 | 
|  |    342 |   assumes ab: "coprime a b" and az: "a \<noteq> 0" and bz: "b\<noteq>0"
 | 
|  |    343 |   shows "\<exists>!x. x < a * b \<and> [x = m] (mod a) \<and> [x = n] (mod b)"
 | 
|  |    344 | proof-
 | 
|  |    345 |   from az bz have abpos: "a*b > 0" by simp
 | 
|  |    346 |   from chinese_remainder[OF ab az bz] obtain x q1 q2 where 
 | 
|  |    347 |     xq12: "x = m + q1 * a" "x = n + q2 * b" by blast
 | 
|  |    348 |   let ?w = "x mod (a*b)" 
 | 
|  |    349 |   have wab: "?w < a*b" by (simp add: mod_less_divisor[OF abpos])
 | 
|  |    350 |   from xq12(1) have "?w mod a = ((m + q1 * a) mod (a*b)) mod a" by simp
 | 
|  |    351 |   also have "\<dots> = m mod a" apply (simp add: mod_mult2_eq)
 | 
|  |    352 |     apply (subst mod_add_left_eq)
 | 
|  |    353 |     by simp
 | 
|  |    354 |   finally have th1: "[?w = m] (mod a)" by (simp add: modeq_def)
 | 
|  |    355 |   from xq12(2) have "?w mod b = ((n + q2 * b) mod (a*b)) mod b" by simp
 | 
|  |    356 |   also have "\<dots> = ((n + q2 * b) mod (b*a)) mod b" by (simp add: mult_commute)
 | 
|  |    357 |   also have "\<dots> = n mod b" apply (simp add: mod_mult2_eq)
 | 
|  |    358 |     apply (subst mod_add_left_eq)
 | 
|  |    359 |     by simp
 | 
|  |    360 |   finally have th2: "[?w = n] (mod b)" by (simp add: modeq_def)
 | 
|  |    361 |   {fix y assume H: "y < a*b" "[y = m] (mod a)" "[y = n] (mod b)"
 | 
|  |    362 |     with th1 th2 have H': "[y = ?w] (mod a)" "[y = ?w] (mod b)"
 | 
|  |    363 |       by (simp_all add: modeq_def)
 | 
|  |    364 |     from cong_chinese[OF ab H'] mod_less[OF H(1)] mod_less[OF wab] 
 | 
|  |    365 |     have "y = ?w" by (simp add: modeq_def)}
 | 
|  |    366 |   with th1 th2 wab show ?thesis by blast
 | 
|  |    367 | qed
 | 
|  |    368 | 
 | 
|  |    369 | lemma chinese_remainder_coprime_unique:
 | 
|  |    370 |   assumes ab: "coprime a b" and az: "a \<noteq> 0" and bz: "b \<noteq> 0" 
 | 
|  |    371 |   and ma: "coprime m a" and nb: "coprime n b"
 | 
|  |    372 |   shows "\<exists>!x. coprime x (a * b) \<and> x < a * b \<and> [x = m] (mod a) \<and> [x = n] (mod b)"
 | 
|  |    373 | proof-
 | 
|  |    374 |   let ?P = "\<lambda>x. x < a * b \<and> [x = m] (mod a) \<and> [x = n] (mod b)"
 | 
|  |    375 |   from chinese_remainder_unique[OF ab az bz]
 | 
|  |    376 |   obtain x where x: "x < a * b" "[x = m] (mod a)" "[x = n] (mod b)" 
 | 
|  |    377 |     "\<forall>y. ?P y \<longrightarrow> y = x" by blast
 | 
|  |    378 |   from ma nb cong_coprime[OF x(2)] cong_coprime[OF x(3)]
 | 
|  |    379 |   have "coprime x a" "coprime x b" by (simp_all add: coprime_commute)
 | 
|  |    380 |   with coprime_mul[of x a b] have "coprime x (a*b)" by simp
 | 
|  |    381 |   with x show ?thesis by blast
 | 
|  |    382 | qed
 | 
|  |    383 | 
 | 
|  |    384 | (* Euler totient function.                                                   *)
 | 
|  |    385 | 
 | 
|  |    386 | definition phi_def: "\<phi> n = card { m. 0 < m \<and> m <= n \<and> coprime m n }"
 | 
|  |    387 | lemma phi_0[simp]: "\<phi> 0 = 0"
 | 
|  |    388 |   unfolding phi_def by (auto simp add: card_eq_0_iff)
 | 
|  |    389 | 
 | 
|  |    390 | lemma phi_finite[simp]: "finite ({ m. 0 < m \<and> m <= n \<and> coprime m n })"
 | 
|  |    391 | proof-
 | 
|  |    392 |   have "{ m. 0 < m \<and> m <= n \<and> coprime m n } \<subseteq> {0..n}" by auto
 | 
|  |    393 |   thus ?thesis by (auto intro: finite_subset)
 | 
|  |    394 | qed
 | 
|  |    395 | 
 | 
|  |    396 | declare coprime_1[presburger]
 | 
|  |    397 | lemma phi_1[simp]: "\<phi> 1 = 1"
 | 
|  |    398 | proof-
 | 
|  |    399 |   {fix m 
 | 
|  |    400 |     have "0 < m \<and> m <= 1 \<and> coprime m 1 \<longleftrightarrow> m = 1" by presburger }
 | 
|  |    401 |   thus ?thesis by (simp add: phi_def)
 | 
|  |    402 | qed
 | 
|  |    403 | 
 | 
|  |    404 | lemma [simp]: "\<phi> (Suc 0) = Suc 0" using phi_1 by simp
 | 
|  |    405 | 
 | 
|  |    406 | lemma phi_alt: "\<phi>(n) = card { m. coprime m n \<and> m < n}"
 | 
|  |    407 | proof-
 | 
|  |    408 |   {assume "n=0 \<or> n=1" hence ?thesis by (cases "n=0", simp_all)}
 | 
|  |    409 |   moreover
 | 
|  |    410 |   {assume n: "n\<noteq>0" "n\<noteq>1"
 | 
|  |    411 |     {fix m
 | 
|  |    412 |       from n have "0 < m \<and> m <= n \<and> coprime m n \<longleftrightarrow> coprime m n \<and> m < n"
 | 
|  |    413 | 	apply (cases "m = 0", simp_all)
 | 
|  |    414 | 	apply (cases "m = 1", simp_all)
 | 
|  |    415 | 	apply (cases "m = n", auto)
 | 
|  |    416 | 	done }
 | 
|  |    417 |     hence ?thesis unfolding phi_def by simp}
 | 
|  |    418 |   ultimately show ?thesis by auto
 | 
|  |    419 | qed
 | 
|  |    420 | 
 | 
|  |    421 | lemma phi_finite_lemma[simp]: "finite {m. coprime m n \<and>  m < n}" (is "finite ?S")
 | 
|  |    422 |   by (rule finite_subset[of "?S" "{0..n}"], auto)
 | 
|  |    423 | 
 | 
|  |    424 | lemma phi_another: assumes n: "n\<noteq>1"
 | 
|  |    425 |   shows "\<phi> n = card {m. 0 < m \<and> m < n \<and> coprime m n }"
 | 
|  |    426 | proof-
 | 
|  |    427 |   {fix m 
 | 
|  |    428 |     from n have "0 < m \<and> m < n \<and> coprime m n \<longleftrightarrow> coprime m n \<and> m < n"
 | 
|  |    429 |       by (cases "m=0", auto)}
 | 
|  |    430 |   thus ?thesis unfolding phi_alt by auto
 | 
|  |    431 | qed
 | 
|  |    432 | 
 | 
|  |    433 | lemma phi_limit: "\<phi> n \<le> n"
 | 
|  |    434 | proof-
 | 
|  |    435 |   have "{ m. coprime m n \<and> m < n} \<subseteq> {0 ..<n}" by auto
 | 
|  |    436 |   with card_mono[of "{0 ..<n}" "{ m. coprime m n \<and> m < n}"]
 | 
|  |    437 |   show ?thesis unfolding phi_alt by auto
 | 
|  |    438 | qed
 | 
|  |    439 | 
 | 
|  |    440 | lemma stupid[simp]: "{m. (0::nat) < m \<and> m < n} = {1..<n}"
 | 
|  |    441 |   by auto
 | 
|  |    442 | 
 | 
|  |    443 | lemma phi_limit_strong: assumes n: "n\<noteq>1" 
 | 
|  |    444 |   shows "\<phi>(n) \<le> n - 1"
 | 
|  |    445 | proof-
 | 
|  |    446 |   show ?thesis
 | 
|  |    447 |     unfolding phi_another[OF n] finite_number_segment[of n, symmetric] 
 | 
|  |    448 |     by (rule card_mono[of "{m. 0 < m \<and> m < n}" "{m. 0 < m \<and> m < n \<and> coprime m n}"], auto)
 | 
|  |    449 | qed
 | 
|  |    450 | 
 | 
|  |    451 | lemma phi_lowerbound_1_strong: assumes n: "n \<ge> 1"
 | 
|  |    452 |   shows "\<phi>(n) \<ge> 1"
 | 
|  |    453 | proof-
 | 
|  |    454 |   let ?S = "{ m. 0 < m \<and> m <= n \<and> coprime m n }"
 | 
|  |    455 |   from card_0_eq[of ?S] n have "\<phi> n \<noteq> 0" unfolding phi_alt 
 | 
|  |    456 |     apply auto
 | 
|  |    457 |     apply (cases "n=1", simp_all)
 | 
|  |    458 |     apply (rule exI[where x=1], simp)
 | 
|  |    459 |     done
 | 
|  |    460 |   thus ?thesis by arith
 | 
|  |    461 | qed
 | 
|  |    462 | 
 | 
|  |    463 | lemma phi_lowerbound_1: "2 <= n ==> 1 <= \<phi>(n)"
 | 
|  |    464 |   using phi_lowerbound_1_strong[of n] by auto
 | 
|  |    465 | 
 | 
|  |    466 | lemma phi_lowerbound_2: assumes n: "3 <= n" shows "2 <= \<phi> (n)"
 | 
|  |    467 | proof-
 | 
|  |    468 |   let ?S = "{ m. 0 < m \<and> m <= n \<and> coprime m n }"
 | 
|  |    469 |   have inS: "{1, n - 1} \<subseteq> ?S" using n coprime_plus1[of "n - 1"] 
 | 
|  |    470 |     by (auto simp add: coprime_commute)
 | 
|  |    471 |   from n have c2: "card {1, n - 1} = 2" by (auto simp add: card_insert_if)
 | 
|  |    472 |   from card_mono[of ?S "{1, n - 1}", simplified inS c2] show ?thesis 
 | 
|  |    473 |     unfolding phi_def by auto
 | 
|  |    474 | qed
 | 
|  |    475 | 
 | 
|  |    476 | lemma phi_prime: "\<phi> n = n - 1 \<and> n\<noteq>0 \<and> n\<noteq>1 \<longleftrightarrow> prime n"
 | 
|  |    477 | proof-
 | 
|  |    478 |   {assume "n=0 \<or> n=1" hence ?thesis by (cases "n=1", simp_all)}
 | 
|  |    479 |   moreover
 | 
|  |    480 |   {assume n: "n\<noteq>0" "n\<noteq>1"
 | 
|  |    481 |     let ?S = "{m. 0 < m \<and> m < n}"
 | 
|  |    482 |     have fS: "finite ?S" by simp
 | 
|  |    483 |     let ?S' = "{m. 0 < m \<and> m < n \<and> coprime m n}"
 | 
|  |    484 |     have fS':"finite ?S'" apply (rule finite_subset[of ?S' ?S]) by auto
 | 
|  |    485 |     {assume H: "\<phi> n = n - 1 \<and> n\<noteq>0 \<and> n\<noteq>1"
 | 
|  |    486 |       hence ceq: "card ?S' = card ?S" 
 | 
|  |    487 |       using n finite_number_segment[of n] phi_another[OF n(2)] by simp
 | 
|  |    488 |       {fix m assume m: "0 < m" "m < n" "\<not> coprime m n"
 | 
|  |    489 | 	hence mS': "m \<notin> ?S'" by auto
 | 
|  |    490 | 	have "insert m ?S' \<le> ?S" using m by auto
 | 
|  |    491 | 	from m have "card (insert m ?S') \<le> card ?S" 
 | 
|  |    492 | 	  by - (rule card_mono[of ?S "insert m ?S'"], auto)
 | 
|  |    493 | 	hence False
 | 
|  |    494 | 	  unfolding card_insert_disjoint[of "?S'" m, OF fS' mS'] ceq
 | 
|  |    495 | 	  by simp }
 | 
|  |    496 |       hence "\<forall>m. 0 <m \<and> m < n \<longrightarrow> coprime m n" by blast
 | 
|  |    497 |       hence "prime n" unfolding prime using n by (simp add: coprime_commute)}
 | 
|  |    498 |     moreover
 | 
|  |    499 |     {assume H: "prime n"
 | 
|  |    500 |       hence "?S = ?S'" unfolding prime using n 
 | 
|  |    501 | 	by (auto simp add: coprime_commute)
 | 
|  |    502 |       hence "card ?S = card ?S'" by simp
 | 
|  |    503 |       hence "\<phi> n = n - 1" unfolding phi_another[OF n(2)] by simp}
 | 
|  |    504 |     ultimately have ?thesis using n by blast}
 | 
|  |    505 |   ultimately show ?thesis by (cases "n=0") blast+
 | 
|  |    506 | qed
 | 
|  |    507 | 
 | 
|  |    508 | (* Multiplicativity property.                                                *)
 | 
|  |    509 | 
 | 
|  |    510 | lemma phi_multiplicative: assumes ab: "coprime a b"
 | 
|  |    511 |   shows "\<phi> (a * b) = \<phi> a * \<phi> b"
 | 
|  |    512 | proof-
 | 
|  |    513 |   {assume "a = 0 \<or> b = 0 \<or> a = 1 \<or> b = 1" 
 | 
|  |    514 |     hence ?thesis
 | 
|  |    515 |       by (cases "a=0", simp, cases "b=0", simp, cases"a=1", simp_all) }
 | 
|  |    516 |   moreover
 | 
|  |    517 |   {assume a: "a\<noteq>0" "a\<noteq>1" and b: "b\<noteq>0" "b\<noteq>1"
 | 
|  |    518 |     hence ab0: "a*b \<noteq> 0" by simp
 | 
|  |    519 |     let ?S = "\<lambda>k. {m. coprime m k \<and> m < k}"
 | 
|  |    520 |     let ?f = "\<lambda>x. (x mod a, x mod b)"
 | 
|  |    521 |     have eq: "?f ` (?S (a*b)) = (?S a \<times> ?S b)"
 | 
|  |    522 |     proof-
 | 
|  |    523 |       {fix x assume x:"x \<in> ?S (a*b)"
 | 
|  |    524 | 	hence x': "coprime x (a*b)" "x < a*b" by simp_all
 | 
|  |    525 | 	hence xab: "coprime x a" "coprime x b" by (simp_all add: coprime_mul_eq)
 | 
|  |    526 | 	from mod_less_divisor a b have xab':"x mod a < a" "x mod b < b" by auto
 | 
|  |    527 | 	from xab xab' have "?f x \<in> (?S a \<times> ?S b)" 
 | 
|  |    528 | 	  by (simp add: coprime_mod[OF a(1)] coprime_mod[OF b(1)])}
 | 
|  |    529 |       moreover
 | 
|  |    530 |       {fix x y assume x: "x \<in> ?S a" and y: "y \<in> ?S b"
 | 
|  |    531 | 	hence x': "coprime x a" "x < a" and y': "coprime y b" "y < b" by simp_all	
 | 
|  |    532 | 	from chinese_remainder_coprime_unique[OF ab a(1) b(1) x'(1) y'(1)]
 | 
|  |    533 | 	obtain z where z: "coprime z (a * b)" "z < a * b" "[z = x] (mod a)"
 | 
|  |    534 | 	  "[z = y] (mod b)" by blast
 | 
|  |    535 | 	hence "(x,y) \<in> ?f ` (?S (a*b))"
 | 
|  |    536 | 	  using y'(2) mod_less_divisor[of b y] x'(2) mod_less_divisor[of a x]
 | 
|  |    537 | 	  by (auto simp add: image_iff modeq_def)}
 | 
|  |    538 |       ultimately show ?thesis by auto
 | 
|  |    539 |     qed
 | 
|  |    540 |     have finj: "inj_on ?f (?S (a*b))"
 | 
|  |    541 |       unfolding inj_on_def
 | 
|  |    542 |     proof(clarify)
 | 
|  |    543 |       fix x y assume H: "coprime x (a * b)" "x < a * b" "coprime y (a * b)" 
 | 
|  |    544 | 	"y < a * b" "x mod a = y mod a" "x mod b = y mod b"
 | 
|  |    545 |       hence cp: "coprime x a" "coprime x b" "coprime y a" "coprime y b" 
 | 
|  |    546 | 	by (simp_all add: coprime_mul_eq)
 | 
|  |    547 |       from chinese_remainder_coprime_unique[OF ab a(1) b(1) cp(3,4)] H
 | 
|  |    548 |       show "x = y" unfolding modeq_def by blast
 | 
|  |    549 |     qed
 | 
|  |    550 |     from card_image[OF finj, unfolded eq] have ?thesis
 | 
|  |    551 |       unfolding phi_alt by simp }
 | 
|  |    552 |   ultimately show ?thesis by auto
 | 
|  |    553 | qed
 | 
|  |    554 | 
 | 
|  |    555 | (* Fermat's Little theorem / Fermat-Euler theorem.                           *)
 | 
|  |    556 | 
 | 
|  |    557 | lemma (in comm_monoid_mult) fold_related: 
 | 
|  |    558 |   assumes Re: "R e e" 
 | 
|  |    559 |   and Rop: "\<forall>x1 y1 x2 y2. R x1 x2 \<and> R y1 y2 \<longrightarrow> R (x1 * y1) (x2 * y2)" 
 | 
|  |    560 |   and fS: "finite S" and Rfg: "\<forall>x\<in>S. R (h x) (g x)"
 | 
|  |    561 |   shows "R (fold (op *) h e S) (fold (op *) g e S)"
 | 
| 27368 |    562 |   using fS by (rule finite_subset_induct) (insert assms, auto)
 | 
| 26126 |    563 | 
 | 
|  |    564 | lemma nproduct_mod:
 | 
|  |    565 |   assumes fS: "finite S" and n0: "n \<noteq> 0"
 | 
|  |    566 |   shows "[setprod (\<lambda>m. a(m) mod n) S = setprod a S] (mod n)"
 | 
|  |    567 | proof-
 | 
|  |    568 |   have th1:"[1 = 1] (mod n)" by (simp add: modeq_def)
 | 
|  |    569 |   from cong_mult
 | 
|  |    570 |   have th3:"\<forall>x1 y1 x2 y2.
 | 
|  |    571 |     [x1 = x2] (mod n) \<and> [y1 = y2] (mod n) \<longrightarrow> [x1 * y1 = x2 * y2] (mod n)"
 | 
|  |    572 |     by blast
 | 
|  |    573 |   have th4:"\<forall>x\<in>S. [a x mod n = a x] (mod n)" by (simp add: modeq_def)
 | 
|  |    574 |   from fold_related[where h="(\<lambda>m. a(m) mod n)" and g=a, OF th1 th3 fS, OF th4] show ?thesis unfolding setprod_def by (simp add: fS)
 | 
|  |    575 | qed
 | 
|  |    576 | 
 | 
|  |    577 | lemma nproduct_cmul:
 | 
|  |    578 |   assumes fS:"finite S"
 | 
|  |    579 |   shows "setprod (\<lambda>m. (c::'a::{comm_monoid_mult,recpower})* a(m)) S = c ^ (card S) * setprod a S"
 | 
|  |    580 | unfolding setprod_timesf setprod_constant[OF fS, of c] ..
 | 
|  |    581 | 
 | 
|  |    582 | lemma coprime_nproduct:
 | 
|  |    583 |   assumes fS: "finite S" and Sn: "\<forall>x\<in>S. coprime n (a x)"
 | 
|  |    584 |   shows "coprime n (setprod a S)"
 | 
| 27368 |    585 |   using fS unfolding setprod_def by (rule finite_subset_induct)
 | 
|  |    586 |     (insert Sn, auto simp add: coprime_mul)
 | 
| 26126 |    587 | 
 | 
|  |    588 | lemma (in comm_monoid_mult) 
 | 
|  |    589 |   fold_eq_general:
 | 
|  |    590 |   assumes fS: "finite S"
 | 
|  |    591 |   and h: "\<forall>y\<in>S'. \<exists>!x. x\<in> S \<and> h(x) = y" 
 | 
|  |    592 |   and f12:  "\<forall>x\<in>S. h x \<in> S' \<and> f2(h x) = f1 x"
 | 
|  |    593 |   shows "fold (op *) f1 e S = fold (op *) f2 e S'"
 | 
|  |    594 | proof-
 | 
|  |    595 |   from h f12 have hS: "h ` S = S'" by auto
 | 
|  |    596 |   {fix x y assume H: "x \<in> S" "y \<in> S" "h x = h y"
 | 
|  |    597 |     from f12 h H  have "x = y" by auto }
 | 
|  |    598 |   hence hinj: "inj_on h S" unfolding inj_on_def Ex1_def by blast
 | 
|  |    599 |   from f12 have th: "\<And>x. x \<in> S \<Longrightarrow> (f2 \<circ> h) x = f1 x" by auto 
 | 
|  |    600 |   from hS have "fold (op *) f2 e S' = fold (op *) f2 e (h ` S)" by simp
 | 
|  |    601 |   also have "\<dots> = fold (op *) (f2 o h) e S" 
 | 
|  |    602 |     using fold_reindex[OF fS hinj, of f2 e] .
 | 
|  |    603 |   also have "\<dots> = fold (op *) f1 e S " using th fold_cong[OF fS, of "f2 o h" f1 e]
 | 
|  |    604 |     by blast
 | 
|  |    605 |   finally show ?thesis ..
 | 
|  |    606 | qed
 | 
|  |    607 | 
 | 
|  |    608 | lemma fermat_little: assumes an: "coprime a n"
 | 
|  |    609 |   shows "[a ^ (\<phi> n) = 1] (mod n)"
 | 
|  |    610 | proof-
 | 
|  |    611 |   {assume "n=0" hence ?thesis by simp}
 | 
|  |    612 |   moreover
 | 
|  |    613 |   {assume "n=1" hence ?thesis by (simp add: modeq_def)}
 | 
|  |    614 |   moreover
 | 
|  |    615 |   {assume nz: "n \<noteq> 0" and n1: "n \<noteq> 1"
 | 
|  |    616 |     let ?S = "{m. coprime m n \<and> m < n}"
 | 
|  |    617 |     let ?P = "\<Prod> ?S"
 | 
|  |    618 |     have fS: "finite ?S" by simp
 | 
|  |    619 |     have cardfS: "\<phi> n = card ?S" unfolding phi_alt ..
 | 
|  |    620 |     {fix m assume m: "m \<in> ?S"
 | 
|  |    621 |       hence "coprime m n" by simp
 | 
|  |    622 |       with coprime_mul[of n a m] an have "coprime (a*m) n" 
 | 
|  |    623 | 	by (simp add: coprime_commute)}
 | 
|  |    624 |     hence Sn: "\<forall>m\<in> ?S. coprime (a*m) n " by blast
 | 
|  |    625 |     from coprime_nproduct[OF fS, of n "\<lambda>m. m"] have nP:"coprime ?P n"
 | 
|  |    626 |       by (simp add: coprime_commute)
 | 
|  |    627 |     have Paphi: "[?P*a^ (\<phi> n) = ?P*1] (mod n)"
 | 
|  |    628 |     proof-
 | 
|  |    629 |       let ?h = "\<lambda>m. m mod n"
 | 
|  |    630 |       {fix m assume mS: "m\<in> ?S"
 | 
|  |    631 | 	hence "?h m \<in> ?S" by simp}
 | 
|  |    632 |       hence hS: "?h ` ?S = ?S"by (auto simp add: image_iff)
 | 
|  |    633 |       have "a\<noteq>0" using an n1 nz apply- apply (rule ccontr) by simp
 | 
|  |    634 |       hence inj: "inj_on (op * a) ?S" unfolding inj_on_def by simp
 | 
|  |    635 |       
 | 
|  |    636 |       have eq0: "fold op * (?h \<circ> op * a) 1 {m. coprime m n \<and> m < n} =
 | 
|  |    637 |      fold op * (\<lambda>m. m) 1 {m. coprime m n \<and> m < n}"
 | 
|  |    638 |       proof (rule fold_eq_general[where h="?h o (op * a)"])
 | 
|  |    639 | 	show "finite ?S" using fS .
 | 
|  |    640 |       next
 | 
|  |    641 | 	{fix y assume yS: "y \<in> ?S" hence y: "coprime y n" "y < n" by simp_all
 | 
|  |    642 | 	  from cong_solve_unique[OF an nz, of y]
 | 
|  |    643 | 	  obtain x where x:"x < n" "[a * x = y] (mod n)" "\<forall>z. z < n \<and> [a * z = y] (mod n) \<longrightarrow> z=x" by blast  
 | 
|  |    644 | 	  from cong_coprime[OF x(2)] y(1)
 | 
|  |    645 | 	  have xm: "coprime x n" by (simp add: coprime_mul_eq coprime_commute)
 | 
|  |    646 | 	  {fix z assume "z \<in> ?S" "(?h \<circ> op * a) z = y"
 | 
|  |    647 | 	    hence z: "coprime z n" "z < n" "(?h \<circ> op * a) z = y" by simp_all
 | 
|  |    648 | 	    from x(3)[rule_format, of z] z(2,3) have "z=x" 
 | 
|  |    649 | 	      unfolding modeq_def mod_less[OF y(2)] by simp}
 | 
|  |    650 | 	  with xm x(1,2) have "\<exists>!x. x \<in> ?S \<and> (?h \<circ> op * a) x = y"
 | 
|  |    651 | 	    unfolding modeq_def mod_less[OF y(2)] by auto }
 | 
|  |    652 | 	thus "\<forall>y\<in>{m. coprime m n \<and> m < n}.
 | 
|  |    653 |        \<exists>!x. x \<in> {m. coprime m n \<and> m < n} \<and> ((\<lambda>m. m mod n) \<circ> op * a) x = y" by blast
 | 
|  |    654 |       next
 | 
|  |    655 | 	{fix x assume xS: "x\<in> ?S"
 | 
|  |    656 | 	  hence x: "coprime x n" "x < n" by simp_all
 | 
|  |    657 | 	  with an have "coprime (a*x) n"
 | 
|  |    658 | 	    by (simp add: coprime_mul_eq[of n a x] coprime_commute)
 | 
|  |    659 | 	  hence "?h (a*x) \<in> ?S" using nz 
 | 
|  |    660 | 	    by (simp add: coprime_mod[OF nz] mod_less_divisor)}
 | 
|  |    661 | 	thus " \<forall>x\<in>{m. coprime m n \<and> m < n}.
 | 
|  |    662 |        ((\<lambda>m. m mod n) \<circ> op * a) x \<in> {m. coprime m n \<and> m < n} \<and>
 | 
|  |    663 |        ((\<lambda>m. m mod n) \<circ> op * a) x = ((\<lambda>m. m mod n) \<circ> op * a) x" by simp
 | 
|  |    664 |       qed
 | 
|  |    665 |       from nproduct_mod[OF fS nz, of "op * a"]
 | 
|  |    666 |       have "[(setprod (op *a) ?S) = (setprod (?h o (op * a)) ?S)] (mod n)"
 | 
|  |    667 | 	unfolding o_def
 | 
|  |    668 | 	by (simp add: cong_commute)
 | 
|  |    669 |       also have "[setprod (?h o (op * a)) ?S = ?P ] (mod n)"
 | 
|  |    670 | 	using eq0 fS an by (simp add: setprod_def modeq_def o_def)
 | 
|  |    671 |       finally show "[?P*a^ (\<phi> n) = ?P*1] (mod n)"
 | 
|  |    672 | 	unfolding cardfS mult_commute[of ?P "a^ (card ?S)"] 
 | 
|  |    673 | 	  nproduct_cmul[OF fS, symmetric] mult_1_right by simp
 | 
|  |    674 |     qed
 | 
|  |    675 |     from cong_mult_lcancel[OF nP Paphi] have ?thesis . }
 | 
|  |    676 |   ultimately show ?thesis by blast
 | 
|  |    677 | qed
 | 
|  |    678 | 
 | 
|  |    679 | lemma fermat_little_prime: assumes p: "prime p" and ap: "coprime a p"
 | 
|  |    680 |   shows "[a^ (p - 1) = 1] (mod p)"
 | 
|  |    681 |   using fermat_little[OF ap] p[unfolded phi_prime[symmetric]]
 | 
|  |    682 | by simp
 | 
|  |    683 | 
 | 
|  |    684 | 
 | 
|  |    685 | (* Lucas's theorem.                                                          *)
 | 
|  |    686 | 
 | 
|  |    687 | lemma lucas_coprime_lemma:
 | 
|  |    688 |   assumes m: "m\<noteq>0" and am: "[a^m = 1] (mod n)"
 | 
|  |    689 |   shows "coprime a n"
 | 
|  |    690 | proof-
 | 
|  |    691 |   {assume "n=1" hence ?thesis by simp}
 | 
|  |    692 |   moreover
 | 
|  |    693 |   {assume "n = 0" hence ?thesis using am m exp_eq_1[of a m] by simp}
 | 
|  |    694 |   moreover
 | 
|  |    695 |   {assume n: "n\<noteq>0" "n\<noteq>1"
 | 
|  |    696 |     from m obtain m' where m': "m = Suc m'" by (cases m, blast+)
 | 
|  |    697 |     {fix d
 | 
|  |    698 |       assume d: "d dvd a" "d dvd n"
 | 
|  |    699 |       from n have n1: "1 < n" by arith      
 | 
|  |    700 |       from am mod_less[OF n1] have am1: "a^m mod n = 1" unfolding modeq_def by simp
 | 
|  |    701 |       from dvd_mult2[OF d(1), of "a^m'"] have dam:"d dvd a^m" by (simp add: m')
 | 
|  |    702 |       from dvd_mod_iff[OF d(2), of "a^m"] dam am1
 | 
|  |    703 |       have "d = 1" by simp }
 | 
|  |    704 |     hence ?thesis unfolding coprime by auto
 | 
|  |    705 |   }
 | 
|  |    706 |   ultimately show ?thesis by blast 
 | 
|  |    707 | qed
 | 
|  |    708 | 
 | 
|  |    709 | lemma lucas_weak:
 | 
|  |    710 |   assumes n: "n \<ge> 2" and an:"[a^(n - 1) = 1] (mod n)" 
 | 
|  |    711 |   and nm: "\<forall>m. 0 <m \<and> m < n - 1 \<longrightarrow> \<not> [a^m = 1] (mod n)"
 | 
|  |    712 |   shows "prime n"
 | 
|  |    713 | proof-
 | 
|  |    714 |   from n have n1: "n \<noteq> 1" "n\<noteq>0" "n - 1 \<noteq> 0" "n - 1 > 0" "n - 1 < n" by arith+
 | 
|  |    715 |   from lucas_coprime_lemma[OF n1(3) an] have can: "coprime a n" .
 | 
|  |    716 |   from fermat_little[OF can] have afn: "[a ^ \<phi> n = 1] (mod n)" .
 | 
|  |    717 |   {assume "\<phi> n \<noteq> n - 1"
 | 
|  |    718 |     with phi_limit_strong[OF n1(1)] phi_lowerbound_1[OF n]
 | 
|  |    719 |     have c:"\<phi> n > 0 \<and> \<phi> n < n - 1" by arith
 | 
|  |    720 |     from nm[rule_format, OF c] afn have False ..}
 | 
|  |    721 |   hence "\<phi> n = n - 1" by blast
 | 
|  |    722 |   with phi_prime[of n] n1(1,2) show ?thesis by simp
 | 
|  |    723 | qed
 | 
|  |    724 | 
 | 
|  |    725 | lemma nat_exists_least_iff: "(\<exists>(n::nat). P n) \<longleftrightarrow> (\<exists>n. P n \<and> (\<forall>m < n. \<not> P m))" 
 | 
|  |    726 |   (is "?lhs \<longleftrightarrow> ?rhs")
 | 
|  |    727 | proof
 | 
|  |    728 |   assume ?rhs thus ?lhs by blast
 | 
|  |    729 | next
 | 
|  |    730 |   assume H: ?lhs then obtain n where n: "P n" by blast
 | 
|  |    731 |   let ?x = "Least P"
 | 
|  |    732 |   {fix m assume m: "m < ?x"
 | 
|  |    733 |     from not_less_Least[OF m] have "\<not> P m" .}
 | 
|  |    734 |   with LeastI_ex[OF H] show ?rhs by blast
 | 
|  |    735 | qed
 | 
|  |    736 | 
 | 
|  |    737 | lemma nat_exists_least_iff': "(\<exists>(n::nat). P n) \<longleftrightarrow> (P (Least P) \<and> (\<forall>m < (Least P). \<not> P m))" 
 | 
|  |    738 |   (is "?lhs \<longleftrightarrow> ?rhs")
 | 
|  |    739 | proof-
 | 
|  |    740 |   {assume ?rhs hence ?lhs by blast}
 | 
|  |    741 |   moreover 
 | 
|  |    742 |   { assume H: ?lhs then obtain n where n: "P n" by blast
 | 
|  |    743 |     let ?x = "Least P"
 | 
|  |    744 |     {fix m assume m: "m < ?x"
 | 
|  |    745 |       from not_less_Least[OF m] have "\<not> P m" .}
 | 
|  |    746 |     with LeastI_ex[OF H] have ?rhs by blast}
 | 
|  |    747 |   ultimately show ?thesis by blast
 | 
|  |    748 | qed
 | 
|  |    749 |  
 | 
|  |    750 | lemma power_mod: "((x::nat) mod m)^n mod m = x^n mod m"
 | 
|  |    751 | proof(induct n)
 | 
|  |    752 |   case 0 thus ?case by simp
 | 
|  |    753 | next
 | 
|  |    754 |   case (Suc n) 
 | 
|  |    755 |   have "(x mod m)^(Suc n) mod m = ((x mod m) * (((x mod m) ^ n) mod m)) mod m" 
 | 
|  |    756 |     by (simp add: mod_mult1_eq[symmetric])
 | 
|  |    757 |   also have "\<dots> = ((x mod m) * (x^n mod m)) mod m" using Suc.hyps by simp
 | 
|  |    758 |   also have "\<dots> = x^(Suc n) mod m"
 | 
|  |    759 |     by (simp add: mod_mult1_eq'[symmetric] mod_mult1_eq[symmetric])
 | 
|  |    760 |   finally show ?case .
 | 
|  |    761 | qed
 | 
|  |    762 | 
 | 
|  |    763 | lemma lucas:
 | 
|  |    764 |   assumes n2: "n \<ge> 2" and an1: "[a^(n - 1) = 1] (mod n)" 
 | 
|  |    765 |   and pn: "\<forall>p. prime p \<and> p dvd n - 1 \<longrightarrow> \<not> [a^((n - 1) div p) = 1] (mod n)"
 | 
|  |    766 |   shows "prime n"
 | 
|  |    767 | proof-
 | 
|  |    768 |   from n2 have n01: "n\<noteq>0" "n\<noteq>1" "n - 1 \<noteq> 0" by arith+
 | 
|  |    769 |   from mod_less_divisor[of n 1] n01 have onen: "1 mod n = 1" by simp
 | 
|  |    770 |   from lucas_coprime_lemma[OF n01(3) an1] cong_coprime[OF an1] 
 | 
|  |    771 |   have an: "coprime a n" "coprime (a^(n - 1)) n" by (simp_all add: coprime_commute)
 | 
|  |    772 |   {assume H0: "\<exists>m. 0 < m \<and> m < n - 1 \<and> [a ^ m = 1] (mod n)" (is "EX m. ?P m")
 | 
|  |    773 |     from H0[unfolded nat_exists_least_iff[of ?P]] obtain m where 
 | 
|  |    774 |       m: "0 < m" "m < n - 1" "[a ^ m = 1] (mod n)" "\<forall>k <m. \<not>?P k" by blast
 | 
|  |    775 |     {assume nm1: "(n - 1) mod m > 0" 
 | 
|  |    776 |       from mod_less_divisor[OF m(1)] have th0:"(n - 1) mod m < m" by blast 
 | 
|  |    777 |       let ?y = "a^ ((n - 1) div m * m)"
 | 
|  |    778 |       note mdeq = mod_div_equality[of "(n - 1)" m]
 | 
|  |    779 |       from coprime_exp[OF an(1)[unfolded coprime_commute[of a n]], 
 | 
|  |    780 | 	of "(n - 1) div m * m"]
 | 
|  |    781 |       have yn: "coprime ?y n" by (simp add: coprime_commute) 
 | 
|  |    782 |       have "?y mod n = (a^m)^((n - 1) div m) mod n" 
 | 
|  |    783 | 	by (simp add: ring_simps power_mult)
 | 
|  |    784 |       also have "\<dots> = (a^m mod n)^((n - 1) div m) mod n" 
 | 
|  |    785 | 	using power_mod[of "a^m" n "(n - 1) div m"] by simp
 | 
| 26158 |    786 |       also have "\<dots> = 1" using m(3)[unfolded modeq_def onen] onen 
 | 
|  |    787 | 	by (simp add: power_Suc0)
 | 
| 26126 |    788 |       finally have th3: "?y mod n = 1"  . 
 | 
|  |    789 |       have th2: "[?y * a ^ ((n - 1) mod m) = ?y* 1] (mod n)" 
 | 
|  |    790 | 	using an1[unfolded modeq_def onen] onen
 | 
|  |    791 | 	  mod_div_equality[of "(n - 1)" m, symmetric]
 | 
|  |    792 | 	by (simp add:power_add[symmetric] modeq_def th3 del: One_nat_def)
 | 
|  |    793 |       from cong_mult_lcancel[of ?y n "a^((n - 1) mod m)" 1, OF yn th2]
 | 
|  |    794 |       have th1: "[a ^ ((n - 1) mod m) = 1] (mod n)"  . 
 | 
|  |    795 |       from m(4)[rule_format, OF th0] nm1 
 | 
|  |    796 | 	less_trans[OF mod_less_divisor[OF m(1), of "n - 1"] m(2)] th1
 | 
|  |    797 |       have False by blast }
 | 
|  |    798 |     hence "(n - 1) mod m = 0" by auto
 | 
|  |    799 |     then have mn: "m dvd n - 1" by presburger
 | 
|  |    800 |     then obtain r where r: "n - 1 = m*r" unfolding dvd_def by blast
 | 
|  |    801 |     from n01 r m(2) have r01: "r\<noteq>0" "r\<noteq>1" by - (rule ccontr, simp)+
 | 
|  |    802 |     from prime_factor[OF r01(2)] obtain p where p: "prime p" "p dvd r" by blast
 | 
|  |    803 |     hence th: "prime p \<and> p dvd n - 1" unfolding r by (auto intro: dvd_mult)
 | 
|  |    804 |     have "(a ^ ((n - 1) div p)) mod n = (a^(m*r div p)) mod n" using r
 | 
|  |    805 |       by (simp add: power_mult)
 | 
|  |    806 |     also have "\<dots> = (a^(m*(r div p))) mod n" using div_mult1_eq[of m r p] p(2)[unfolded dvd_eq_mod_eq_0] by simp
 | 
|  |    807 |     also have "\<dots> = ((a^m)^(r div p)) mod n" by (simp add: power_mult)
 | 
|  |    808 |     also have "\<dots> = ((a^m mod n)^(r div p)) mod n" using power_mod[of "a^m" "n" "r div p" ] ..
 | 
| 26158 |    809 |     also have "\<dots> = 1" using m(3) onen by (simp add: modeq_def power_Suc0)
 | 
| 26126 |    810 |     finally have "[(a ^ ((n - 1) div p))= 1] (mod n)" 
 | 
|  |    811 |       using onen by (simp add: modeq_def)
 | 
|  |    812 |     with pn[rule_format, OF th] have False by blast}
 | 
|  |    813 |   hence th: "\<forall>m. 0 < m \<and> m < n - 1 \<longrightarrow> \<not> [a ^ m = 1] (mod n)" by blast
 | 
|  |    814 |   from lucas_weak[OF n2 an1 th] show ?thesis .
 | 
|  |    815 | qed
 | 
|  |    816 | 
 | 
|  |    817 | (* Definition of the order of a number mod n (0 in non-coprime case).        *)
 | 
|  |    818 | 
 | 
|  |    819 | definition "ord n a = (if coprime n a then Least (\<lambda>d. d > 0 \<and> [a ^d = 1] (mod n)) else 0)"
 | 
|  |    820 | 
 | 
|  |    821 | (* This has the expected properties.                                         *)
 | 
|  |    822 | 
 | 
|  |    823 | lemma coprime_ord:
 | 
|  |    824 |   assumes na: "coprime n a" 
 | 
|  |    825 |   shows "ord n a > 0 \<and> [a ^(ord n a) = 1] (mod n) \<and> (\<forall>m. 0 < m \<and> m < ord n a \<longrightarrow> \<not> [a^ m = 1] (mod n))"
 | 
|  |    826 | proof-
 | 
|  |    827 |   let ?P = "\<lambda>d. 0 < d \<and> [a ^ d = 1] (mod n)"
 | 
|  |    828 |   from euclid[of a] obtain p where p: "prime p" "a < p" by blast
 | 
|  |    829 |   from na have o: "ord n a = Least ?P" by (simp add: ord_def)
 | 
|  |    830 |   {assume "n=0 \<or> n=1" with na have "\<exists>m>0. ?P m" apply auto apply (rule exI[where x=1]) by (simp  add: modeq_def)}
 | 
|  |    831 |   moreover
 | 
|  |    832 |   {assume "n\<noteq>0 \<and> n\<noteq>1" hence n2:"n \<ge> 2" by arith 
 | 
|  |    833 |     from na have na': "coprime a n" by (simp add: coprime_commute)
 | 
|  |    834 |     from phi_lowerbound_1[OF n2] fermat_little[OF na']
 | 
|  |    835 |     have ex: "\<exists>m>0. ?P m" by - (rule exI[where x="\<phi> n"], auto) }
 | 
|  |    836 |   ultimately have ex: "\<exists>m>0. ?P m" by blast
 | 
|  |    837 |   from nat_exists_least_iff'[of ?P] ex na show ?thesis 
 | 
|  |    838 |     unfolding o[symmetric] by auto
 | 
|  |    839 | qed
 | 
|  |    840 | (* With the special value 0 for non-coprime case, it's more convenient.      *)
 | 
|  |    841 | lemma ord_works:
 | 
|  |    842 |  "[a ^ (ord n a) = 1] (mod n) \<and> (\<forall>m. 0 < m \<and> m < ord n a \<longrightarrow> ~[a^ m = 1] (mod n))"
 | 
|  |    843 | apply (cases "coprime n a")
 | 
|  |    844 | using coprime_ord[of n a]
 | 
|  |    845 | by (blast, simp add: ord_def modeq_def)
 | 
|  |    846 | 
 | 
|  |    847 | lemma ord: "[a^(ord n a) = 1] (mod n)" using ord_works by blast 
 | 
|  |    848 | lemma ord_minimal: "0 < m \<Longrightarrow> m < ord n a \<Longrightarrow> ~[a^m = 1] (mod n)" 
 | 
|  |    849 |   using ord_works by blast
 | 
|  |    850 | lemma ord_eq_0: "ord n a = 0 \<longleftrightarrow> ~coprime n a"
 | 
|  |    851 | by (cases "coprime n a", simp add: neq0_conv coprime_ord, simp add: neq0_conv ord_def)
 | 
|  |    852 | 
 | 
|  |    853 | lemma ord_divides:
 | 
|  |    854 |  "[a ^ d = 1] (mod n) \<longleftrightarrow> ord n a dvd d" (is "?lhs \<longleftrightarrow> ?rhs")
 | 
|  |    855 | proof
 | 
|  |    856 |   assume rh: ?rhs
 | 
|  |    857 |   then obtain k where "d = ord n a * k" unfolding dvd_def by blast
 | 
|  |    858 |   hence "[a ^ d = (a ^ (ord n a) mod n)^k] (mod n)"
 | 
|  |    859 |     by (simp add : modeq_def power_mult power_mod)
 | 
|  |    860 |   also have "[(a ^ (ord n a) mod n)^k = 1] (mod n)" 
 | 
| 26158 |    861 |     using ord[of a n, unfolded modeq_def] 
 | 
|  |    862 |     by (simp add: modeq_def power_mod power_Suc0)
 | 
| 26126 |    863 |   finally  show ?lhs .
 | 
|  |    864 | next 
 | 
|  |    865 |   assume lh: ?lhs
 | 
|  |    866 |   { assume H: "\<not> coprime n a"
 | 
|  |    867 |     hence o: "ord n a = 0" by (simp add: ord_def)
 | 
|  |    868 |     {assume d: "d=0" with o H have ?rhs by (simp add: modeq_def)}
 | 
|  |    869 |     moreover
 | 
|  |    870 |     {assume d0: "d\<noteq>0" then obtain d' where d': "d = Suc d'" by (cases d, auto)
 | 
|  |    871 |       from H[unfolded coprime] 
 | 
|  |    872 |       obtain p where p: "p dvd n" "p dvd a" "p \<noteq> 1" by auto 
 | 
|  |    873 |       from lh[unfolded nat_mod] 
 | 
|  |    874 |       obtain q1 q2 where q12:"a ^ d + n * q1 = 1 + n * q2" by blast
 | 
|  |    875 |       hence "a ^ d + n * q1 - n * q2 = 1" by simp
 | 
|  |    876 |       with dvd_diff [OF dvd_add [OF divides_rexp[OF p(2), of d'] dvd_mult2[OF p(1), of q1]] dvd_mult2[OF p(1), of q2]] d' have "p dvd 1" by simp 
 | 
|  |    877 |       with p(3) have False by simp
 | 
|  |    878 |       hence ?rhs ..}
 | 
|  |    879 |     ultimately have ?rhs by blast}
 | 
|  |    880 |   moreover
 | 
|  |    881 |   {assume H: "coprime n a"
 | 
|  |    882 |     let ?o = "ord n a"
 | 
|  |    883 |     let ?q = "d div ord n a"
 | 
|  |    884 |     let ?r = "d mod ord n a"
 | 
|  |    885 |     from cong_exp[OF ord[of a n], of ?q] 
 | 
| 26158 |    886 |     have eqo: "[(a^?o)^?q = 1] (mod n)"  by (simp add: modeq_def power_Suc0)
 | 
| 26126 |    887 |     from H have onz: "?o \<noteq> 0" by (simp add: ord_eq_0)
 | 
|  |    888 |     hence op: "?o > 0" by simp
 | 
|  |    889 |     from mod_div_equality[of d "ord n a"] lh
 | 
|  |    890 |     have "[a^(?o*?q + ?r) = 1] (mod n)" by (simp add: modeq_def mult_commute)
 | 
|  |    891 |     hence "[(a^?o)^?q * (a^?r) = 1] (mod n)" 
 | 
|  |    892 |       by (simp add: modeq_def power_mult[symmetric] power_add[symmetric])
 | 
|  |    893 |     hence th: "[a^?r = 1] (mod n)"
 | 
|  |    894 |       using eqo mod_mult1_eq'[of "(a^?o)^?q" "a^?r" n]
 | 
|  |    895 |       apply (simp add: modeq_def del: One_nat_def)
 | 
|  |    896 |       by (simp add: mod_mult1_eq'[symmetric])
 | 
|  |    897 |     {assume r: "?r = 0" hence ?rhs by (simp add: dvd_eq_mod_eq_0)}
 | 
|  |    898 |     moreover
 | 
|  |    899 |     {assume r: "?r \<noteq> 0" 
 | 
|  |    900 |       with mod_less_divisor[OF op, of d] have r0o:"?r >0 \<and> ?r < ?o" by simp
 | 
|  |    901 |       from conjunct2[OF ord_works[of a n], rule_format, OF r0o] th     
 | 
|  |    902 |       have ?rhs by blast}
 | 
|  |    903 |     ultimately have ?rhs by blast}
 | 
|  |    904 |   ultimately  show ?rhs by blast
 | 
|  |    905 | qed
 | 
|  |    906 | 
 | 
|  |    907 | lemma order_divides_phi: "coprime n a \<Longrightarrow> ord n a dvd \<phi> n"
 | 
|  |    908 | using ord_divides fermat_little coprime_commute by simp
 | 
|  |    909 | lemma order_divides_expdiff: 
 | 
|  |    910 |   assumes na: "coprime n a"
 | 
|  |    911 |   shows "[a^d = a^e] (mod n) \<longleftrightarrow> [d = e] (mod (ord n a))"
 | 
|  |    912 | proof-
 | 
|  |    913 |   {fix n a d e 
 | 
|  |    914 |     assume na: "coprime n a" and ed: "(e::nat) \<le> d"
 | 
|  |    915 |     hence "\<exists>c. d = e + c" by arith
 | 
|  |    916 |     then obtain c where c: "d = e + c" by arith
 | 
|  |    917 |     from na have an: "coprime a n" by (simp add: coprime_commute)
 | 
|  |    918 |     from coprime_exp[OF na, of e] 
 | 
|  |    919 |     have aen: "coprime (a^e) n" by (simp add: coprime_commute)
 | 
|  |    920 |     from coprime_exp[OF na, of c] 
 | 
|  |    921 |     have acn: "coprime (a^c) n" by (simp add: coprime_commute)
 | 
|  |    922 |     have "[a^d = a^e] (mod n) \<longleftrightarrow> [a^(e + c) = a^(e + 0)] (mod n)"
 | 
|  |    923 |       using c by simp
 | 
|  |    924 |     also have "\<dots> \<longleftrightarrow> [a^e* a^c = a^e *a^0] (mod n)" by (simp add: power_add)
 | 
|  |    925 |     also have  "\<dots> \<longleftrightarrow> [a ^ c = 1] (mod n)"
 | 
|  |    926 |       using cong_mult_lcancel_eq[OF aen, of "a^c" "a^0"] by simp
 | 
|  |    927 |     also  have "\<dots> \<longleftrightarrow> ord n a dvd c" by (simp only: ord_divides)
 | 
|  |    928 |     also have "\<dots> \<longleftrightarrow> [e + c = e + 0] (mod ord n a)"
 | 
|  |    929 |       using cong_add_lcancel_eq[of e c 0 "ord n a", simplified cong_0_divides]
 | 
|  |    930 |       by simp
 | 
|  |    931 |     finally have "[a^d = a^e] (mod n) \<longleftrightarrow> [d = e] (mod (ord n a))"
 | 
|  |    932 |       using c by simp }
 | 
|  |    933 |   note th = this
 | 
|  |    934 |   have "e \<le> d \<or> d \<le> e" by arith
 | 
|  |    935 |   moreover
 | 
|  |    936 |   {assume ed: "e \<le> d" from th[OF na ed] have ?thesis .}
 | 
|  |    937 |   moreover
 | 
|  |    938 |   {assume de: "d \<le> e"
 | 
|  |    939 |     from th[OF na de] have ?thesis by (simp add: cong_commute) }
 | 
|  |    940 |   ultimately show ?thesis by blast
 | 
|  |    941 | qed
 | 
|  |    942 | 
 | 
|  |    943 | (* Another trivial primality characterization.                               *)
 | 
|  |    944 | 
 | 
|  |    945 | lemma prime_prime_factor:
 | 
|  |    946 |   "prime n \<longleftrightarrow> n \<noteq> 1\<and> (\<forall>p. prime p \<and> p dvd n \<longrightarrow> p = n)"
 | 
|  |    947 | proof-
 | 
|  |    948 |   {assume n: "n=0 \<or> n=1" hence ?thesis using prime_0 two_is_prime by auto}
 | 
|  |    949 |   moreover
 | 
|  |    950 |   {assume n: "n\<noteq>0" "n\<noteq>1"
 | 
|  |    951 |     {assume pn: "prime n"
 | 
|  |    952 |       
 | 
|  |    953 |       from pn[unfolded prime_def] have "\<forall>p. prime p \<and> p dvd n \<longrightarrow> p = n"
 | 
|  |    954 | 	using n 
 | 
|  |    955 | 	apply (cases "n = 0 \<or> n=1",simp)
 | 
|  |    956 | 	by (clarsimp, erule_tac x="p" in allE, auto)}
 | 
|  |    957 |     moreover
 | 
|  |    958 |     {assume H: "\<forall>p. prime p \<and> p dvd n \<longrightarrow> p = n"
 | 
|  |    959 |       from n have n1: "n > 1" by arith
 | 
|  |    960 |       {fix m assume m: "m dvd n" "m\<noteq>1"
 | 
|  |    961 | 	from prime_factor[OF m(2)] obtain p where 
 | 
|  |    962 | 	  p: "prime p" "p dvd m" by blast
 | 
|  |    963 | 	from dvd_trans[OF p(2) m(1)] p(1) H have "p = n" by blast  
 | 
|  |    964 | 	with p(2) have "n dvd m"  by simp
 | 
|  |    965 | 	hence "m=n"  using dvd_anti_sym[OF m(1)] by simp }
 | 
|  |    966 |       with n1 have "prime n"  unfolding prime_def by auto }
 | 
|  |    967 |     ultimately have ?thesis using n by blast} 
 | 
|  |    968 |   ultimately       show ?thesis by auto 
 | 
|  |    969 | qed
 | 
|  |    970 | 
 | 
|  |    971 | lemma prime_divisor_sqrt:
 | 
|  |    972 |   "prime n \<longleftrightarrow> n \<noteq> 1 \<and> (\<forall>d. d dvd n \<and> d^2 \<le> n \<longrightarrow> d = 1)"
 | 
|  |    973 | proof-
 | 
|  |    974 |   {assume "n=0 \<or> n=1" hence ?thesis using prime_0 prime_1 
 | 
|  |    975 |     by (auto simp add: nat_power_eq_0_iff)}
 | 
|  |    976 |   moreover
 | 
|  |    977 |   {assume n: "n\<noteq>0" "n\<noteq>1"
 | 
|  |    978 |     hence np: "n > 1" by arith
 | 
|  |    979 |     {fix d assume d: "d dvd n" "d^2 \<le> n" and H: "\<forall>m. m dvd n \<longrightarrow> m=1 \<or> m=n"
 | 
|  |    980 |       from H d have d1n: "d = 1 \<or> d=n" by blast
 | 
|  |    981 |       {assume dn: "d=n"
 | 
|  |    982 | 	have "n^2 > n*1" using n 
 | 
|  |    983 | 	  by (simp add: power2_eq_square mult_less_cancel1)
 | 
|  |    984 | 	with dn d(2) have "d=1" by simp}
 | 
|  |    985 |       with d1n have "d = 1" by blast  }
 | 
|  |    986 |     moreover
 | 
|  |    987 |     {fix d assume d: "d dvd n" and H: "\<forall>d'. d' dvd n \<and> d'^2 \<le> n \<longrightarrow> d' = 1"
 | 
|  |    988 |       from d n have "d \<noteq> 0" apply - apply (rule ccontr) by simp
 | 
|  |    989 |       hence dp: "d > 0" by simp
 | 
|  |    990 |       from d[unfolded dvd_def] obtain e where e: "n= d*e" by blast
 | 
|  |    991 |       from n dp e have ep:"e > 0" by simp
 | 
|  |    992 |       have "d^2 \<le> n \<or> e^2 \<le> n" using dp ep
 | 
|  |    993 | 	by (auto simp add: e power2_eq_square mult_le_cancel_left)
 | 
|  |    994 |       moreover
 | 
|  |    995 |       {assume h: "d^2 \<le> n"
 | 
|  |    996 | 	from H[rule_format, of d] h d have "d = 1" by blast}
 | 
|  |    997 |       moreover
 | 
|  |    998 |       {assume h: "e^2 \<le> n"
 | 
|  |    999 | 	from e have "e dvd n" unfolding dvd_def by (simp add: mult_commute)
 | 
|  |   1000 | 	with H[rule_format, of e] h have "e=1" by simp
 | 
|  |   1001 | 	with e have "d = n" by simp}
 | 
|  |   1002 |       ultimately have "d=1 \<or> d=n"  by blast}
 | 
|  |   1003 |     ultimately have ?thesis unfolding prime_def using np n(2) by blast}
 | 
|  |   1004 |   ultimately show ?thesis by auto
 | 
|  |   1005 | qed
 | 
|  |   1006 | lemma prime_prime_factor_sqrt:
 | 
|  |   1007 |   "prime n \<longleftrightarrow> n \<noteq> 0 \<and> n \<noteq> 1 \<and> \<not> (\<exists>p. prime p \<and> p dvd n \<and> p^2 \<le> n)" 
 | 
|  |   1008 |   (is "?lhs \<longleftrightarrow>?rhs")
 | 
|  |   1009 | proof-
 | 
|  |   1010 |   {assume "n=0 \<or> n=1" hence ?thesis using prime_0 prime_1 by auto}
 | 
|  |   1011 |   moreover
 | 
|  |   1012 |   {assume n: "n\<noteq>0" "n\<noteq>1"
 | 
|  |   1013 |     {assume H: ?lhs
 | 
|  |   1014 |       from H[unfolded prime_divisor_sqrt] n 
 | 
|  |   1015 |       have ?rhs  apply clarsimp by (erule_tac x="p" in allE, simp add: prime_1)
 | 
|  |   1016 |     }
 | 
|  |   1017 |     moreover
 | 
|  |   1018 |     {assume H: ?rhs
 | 
|  |   1019 |       {fix d assume d: "d dvd n" "d^2 \<le> n" "d\<noteq>1"
 | 
|  |   1020 | 	from prime_factor[OF d(3)] 
 | 
|  |   1021 | 	obtain p where p: "prime p" "p dvd d" by blast
 | 
|  |   1022 | 	from n have np: "n > 0" by arith
 | 
|  |   1023 | 	from d(1) n have "d \<noteq> 0" by - (rule ccontr, auto)
 | 
|  |   1024 | 	hence dp: "d > 0" by arith
 | 
|  |   1025 | 	from mult_mono[OF dvd_imp_le[OF p(2) dp] dvd_imp_le[OF p(2) dp]] d(2)
 | 
|  |   1026 | 	have "p^2 \<le> n" unfolding power2_eq_square by arith
 | 
|  |   1027 | 	with H n p(1) dvd_trans[OF p(2) d(1)] have False  by blast}
 | 
|  |   1028 |       with n prime_divisor_sqrt  have ?lhs by auto}
 | 
|  |   1029 |     ultimately have ?thesis by blast }
 | 
|  |   1030 |   ultimately show ?thesis by (cases "n=0 \<or> n=1", auto)
 | 
|  |   1031 | qed
 | 
|  |   1032 | (* Pocklington theorem. *)
 | 
|  |   1033 | 
 | 
|  |   1034 | lemma pocklington_lemma:
 | 
|  |   1035 |   assumes n: "n \<ge> 2" and nqr: "n - 1 = q*r" and an: "[a^ (n - 1) = 1] (mod n)"
 | 
|  |   1036 |   and aq:"\<forall>p. prime p \<and> p dvd q \<longrightarrow> coprime (a^ ((n - 1) div p) - 1) n"
 | 
|  |   1037 |   and pp: "prime p" and pn: "p dvd n"
 | 
|  |   1038 |   shows "[p = 1] (mod q)"
 | 
|  |   1039 | proof-
 | 
|  |   1040 |   from pp prime_0 prime_1 have p01: "p \<noteq> 0" "p \<noteq> 1" by - (rule ccontr, simp)+
 | 
|  |   1041 |   from cong_1_divides[OF an, unfolded nqr, unfolded dvd_def] 
 | 
|  |   1042 |   obtain k where k: "a ^ (q * r) - 1 = n*k" by blast
 | 
|  |   1043 |   from pn[unfolded dvd_def] obtain l where l: "n = p*l" by blast
 | 
|  |   1044 |   {assume a0: "a = 0"
 | 
|  |   1045 |     hence "a^ (n - 1) = 0" using n by (simp add: power_0_left)
 | 
|  |   1046 |     with n an mod_less[of 1 n]  have False by (simp add: power_0_left modeq_def)}
 | 
|  |   1047 |   hence a0: "a\<noteq>0" ..
 | 
|  |   1048 |   from n nqr have aqr0: "a ^ (q * r) \<noteq> 0" using a0 by (simp add: neq0_conv)
 | 
|  |   1049 |   hence "(a ^ (q * r) - 1) + 1  = a ^ (q * r)" by simp
 | 
|  |   1050 |   with k l have "a ^ (q * r) = p*l*k + 1" by simp
 | 
|  |   1051 |   hence "a ^ (r * q) + p * 0 = 1 + p * (l*k)" by (simp add: mult_ac)
 | 
|  |   1052 |   hence odq: "ord p (a^r) dvd q"
 | 
|  |   1053 |     unfolding ord_divides[symmetric] power_mult[symmetric] nat_mod  by blast
 | 
|  |   1054 |   from odq[unfolded dvd_def] obtain d where d: "q = ord p (a^r) * d" by blast
 | 
|  |   1055 |   {assume d1: "d \<noteq> 1" 
 | 
|  |   1056 |     from prime_factor[OF d1] obtain P where P: "prime P" "P dvd d" by blast
 | 
|  |   1057 |     from d dvd_mult[OF P(2), of "ord p (a^r)"] have Pq: "P dvd q" by simp
 | 
|  |   1058 |     from aq P(1) Pq have caP:"coprime (a^ ((n - 1) div P) - 1) n" by blast
 | 
|  |   1059 |     from Pq obtain s where s: "q = P*s" unfolding dvd_def by blast
 | 
|  |   1060 |     have P0: "P \<noteq> 0" using P(1) prime_0 by - (rule ccontr, simp)
 | 
|  |   1061 |     from P(2) obtain t where t: "d = P*t" unfolding dvd_def by blast
 | 
|  |   1062 |     from d s t P0  have s': "ord p (a^r) * t = s" by algebra
 | 
|  |   1063 |     have "ord p (a^r) * t*r = r * ord p (a^r) * t" by algebra
 | 
|  |   1064 |     hence exps: "a^(ord p (a^r) * t*r) = ((a ^ r) ^ ord p (a^r)) ^ t"
 | 
|  |   1065 |       by (simp only: power_mult)
 | 
|  |   1066 |     have "[((a ^ r) ^ ord p (a^r)) ^ t= 1^t] (mod p)" 
 | 
|  |   1067 |       by (rule cong_exp, rule ord)
 | 
| 26158 |   1068 |     then have th: "[((a ^ r) ^ ord p (a^r)) ^ t= 1] (mod p)" 
 | 
|  |   1069 |       by (simp add: power_Suc0)
 | 
| 26126 |   1070 |     from cong_1_divides[OF th] exps have pd0: "p dvd a^(ord p (a^r) * t*r) - 1" by simp
 | 
|  |   1071 |     from nqr s s' have "(n - 1) div P = ord p (a^r) * t*r" using P0 by simp
 | 
|  |   1072 |     with caP have "coprime (a^(ord p (a^r) * t*r) - 1) n" by simp
 | 
|  |   1073 |     with p01 pn pd0 have False unfolding coprime by auto}
 | 
|  |   1074 |   hence d1: "d = 1" by blast 
 | 
|  |   1075 |   hence o: "ord p (a^r) = q" using d by simp  
 | 
|  |   1076 |   from pp phi_prime[of p] have phip: " \<phi> p = p - 1" by simp
 | 
|  |   1077 |   {fix d assume d: "d dvd p" "d dvd a" "d \<noteq> 1"
 | 
|  |   1078 |     from pp[unfolded prime_def] d have dp: "d = p" by blast
 | 
|  |   1079 |     from n have n12:"Suc (n - 2) = n - 1" by arith
 | 
|  |   1080 |     with divides_rexp[OF d(2)[unfolded dp], of "n - 2"]
 | 
|  |   1081 |     have th0: "p dvd a ^ (n - 1)" by simp
 | 
|  |   1082 |     from n have n0: "n \<noteq> 0" by simp
 | 
|  |   1083 |     from d(2) an n12[symmetric] have a0: "a \<noteq> 0" 
 | 
|  |   1084 |       by - (rule ccontr, simp add: modeq_def)
 | 
|  |   1085 |     have th1: "a^ (n - 1) \<noteq> 0" using n d(2) dp a0 by (auto simp add: neq0_conv)
 | 
|  |   1086 |     from coprime_minus1[OF th1, unfolded coprime] 
 | 
|  |   1087 |       dvd_trans[OF pn cong_1_divides[OF an]] th0 d(3) dp
 | 
|  |   1088 |     have False by auto}
 | 
|  |   1089 |   hence cpa: "coprime p a" using coprime by auto 
 | 
|  |   1090 |   from coprime_exp[OF cpa, of r] coprime_commute 
 | 
|  |   1091 |   have arp: "coprime (a^r) p" by blast
 | 
|  |   1092 |   from fermat_little[OF arp, simplified ord_divides] o phip
 | 
|  |   1093 |   have "q dvd (p - 1)" by simp
 | 
|  |   1094 |   then obtain d where d:"p - 1 = q * d" unfolding dvd_def by blast
 | 
|  |   1095 |   from prime_0 pp have p0:"p \<noteq> 0" by -  (rule ccontr, auto)
 | 
|  |   1096 |   from p0 d have "p + q * 0 = 1 + q * d" by simp
 | 
|  |   1097 |   with nat_mod[of p 1 q, symmetric]
 | 
|  |   1098 |   show ?thesis by blast
 | 
|  |   1099 | qed
 | 
|  |   1100 | 
 | 
|  |   1101 | lemma pocklington:
 | 
|  |   1102 |   assumes n: "n \<ge> 2" and nqr: "n - 1 = q*r" and sqr: "n \<le> q^2"
 | 
|  |   1103 |   and an: "[a^ (n - 1) = 1] (mod n)"
 | 
|  |   1104 |   and aq:"\<forall>p. prime p \<and> p dvd q \<longrightarrow> coprime (a^ ((n - 1) div p) - 1) n"
 | 
|  |   1105 |   shows "prime n"
 | 
|  |   1106 | unfolding prime_prime_factor_sqrt[of n]
 | 
|  |   1107 | proof-
 | 
|  |   1108 |   let ?ths = "n \<noteq> 0 \<and> n \<noteq> 1 \<and> \<not> (\<exists>p. prime p \<and> p dvd n \<and> p\<twosuperior> \<le> n)"
 | 
|  |   1109 |   from n have n01: "n\<noteq>0" "n\<noteq>1" by arith+
 | 
|  |   1110 |   {fix p assume p: "prime p" "p dvd n" "p^2 \<le> n"
 | 
|  |   1111 |     from p(3) sqr have "p^(Suc 1) \<le> q^(Suc 1)" by (simp add: power2_eq_square)
 | 
|  |   1112 |     hence pq: "p \<le> q" unfolding exp_mono_le .
 | 
|  |   1113 |     from pocklington_lemma[OF n nqr an aq p(1,2)]  cong_1_divides
 | 
|  |   1114 |     have th: "q dvd p - 1" by blast
 | 
|  |   1115 |     have "p - 1 \<noteq> 0"using prime_ge_2[OF p(1)] by arith
 | 
|  |   1116 |     with divides_ge[OF th] pq have False by arith }
 | 
|  |   1117 |   with n01 show ?ths by blast
 | 
|  |   1118 | qed
 | 
|  |   1119 | 
 | 
|  |   1120 | (* Variant for application, to separate the exponentiation.                  *)
 | 
|  |   1121 | lemma pocklington_alt:
 | 
|  |   1122 |   assumes n: "n \<ge> 2" and nqr: "n - 1 = q*r" and sqr: "n \<le> q^2"
 | 
|  |   1123 |   and an: "[a^ (n - 1) = 1] (mod n)"
 | 
|  |   1124 |   and aq:"\<forall>p. prime p \<and> p dvd q \<longrightarrow> (\<exists>b. [a^((n - 1) div p) = b] (mod n) \<and> coprime (b - 1) n)"
 | 
|  |   1125 |   shows "prime n"
 | 
|  |   1126 | proof-
 | 
|  |   1127 |   {fix p assume p: "prime p" "p dvd q"
 | 
|  |   1128 |     from aq[rule_format] p obtain b where 
 | 
|  |   1129 |       b: "[a^((n - 1) div p) = b] (mod n)" "coprime (b - 1) n" by blast
 | 
|  |   1130 |     {assume a0: "a=0"
 | 
|  |   1131 |       from n an have "[0 = 1] (mod n)" unfolding a0 power_0_left by auto
 | 
|  |   1132 |       hence False using n by (simp add: modeq_def dvd_eq_mod_eq_0[symmetric])}
 | 
|  |   1133 |     hence a0: "a\<noteq> 0" ..
 | 
|  |   1134 |     hence a1: "a \<ge> 1" by arith
 | 
|  |   1135 |     from one_le_power[OF a1] have ath: "1 \<le> a ^ ((n - 1) div p)" .
 | 
|  |   1136 |     {assume b0: "b = 0"
 | 
|  |   1137 |       from p(2) nqr have "(n - 1) mod p = 0" 
 | 
|  |   1138 | 	apply (simp only: dvd_eq_mod_eq_0[symmetric]) by (rule dvd_mult2, simp)
 | 
|  |   1139 |       with mod_div_equality[of "n - 1" p] 
 | 
|  |   1140 |       have "(n - 1) div p * p= n - 1" by auto 
 | 
|  |   1141 |       hence eq: "(a^((n - 1) div p))^p = a^(n - 1)"
 | 
|  |   1142 | 	by (simp only: power_mult[symmetric])
 | 
|  |   1143 |       from prime_ge_2[OF p(1)] have pS: "Suc (p - 1) = p" by arith
 | 
|  |   1144 |       from b(1) have d: "n dvd a^((n - 1) div p)" unfolding b0 cong_0_divides .
 | 
|  |   1145 |       from divides_rexp[OF d, of "p - 1"] pS eq cong_divides[OF an] n
 | 
|  |   1146 |       have False by simp}
 | 
|  |   1147 |     then have b0: "b \<noteq> 0" ..  
 | 
|  |   1148 |     hence b1: "b \<ge> 1" by arith    
 | 
|  |   1149 |     from cong_coprime[OF cong_sub[OF b(1) cong_refl[of 1] ath b1]] b(2) nqr
 | 
|  |   1150 |     have "coprime (a ^ ((n - 1) div p) - 1) n" by (simp add: coprime_commute)}
 | 
|  |   1151 |   hence th: "\<forall>p. prime p \<and> p dvd q \<longrightarrow> coprime (a ^ ((n - 1) div p) - 1) n " 
 | 
|  |   1152 |     by blast
 | 
|  |   1153 |   from pocklington[OF n nqr sqr an th] show ?thesis .
 | 
|  |   1154 | qed
 | 
|  |   1155 | 
 | 
|  |   1156 | (* Prime factorizations.                                                     *)
 | 
|  |   1157 | 
 | 
|  |   1158 | definition "primefact ps n = (foldr op * ps  1 = n \<and> (\<forall>p\<in> set ps. prime p))"
 | 
|  |   1159 | 
 | 
|  |   1160 | lemma primefact: assumes n: "n \<noteq> 0"
 | 
|  |   1161 |   shows "\<exists>ps. primefact ps n"
 | 
|  |   1162 | using n
 | 
|  |   1163 | proof(induct n rule: nat_less_induct)
 | 
|  |   1164 |   fix n assume H: "\<forall>m<n. m \<noteq> 0 \<longrightarrow> (\<exists>ps. primefact ps m)" and n: "n\<noteq>0"
 | 
|  |   1165 |   let ?ths = "\<exists>ps. primefact ps n"
 | 
|  |   1166 |   {assume "n = 1" 
 | 
|  |   1167 |     hence "primefact [] n" by (simp add: primefact_def)
 | 
|  |   1168 |     hence ?ths by blast }
 | 
|  |   1169 |   moreover
 | 
|  |   1170 |   {assume n1: "n \<noteq> 1"
 | 
|  |   1171 |     with n have n2: "n \<ge> 2" by arith
 | 
|  |   1172 |     from prime_factor[OF n1] obtain p where p: "prime p" "p dvd n" by blast
 | 
|  |   1173 |     from p(2) obtain m where m: "n = p*m" unfolding dvd_def by blast
 | 
|  |   1174 |     from n m have m0: "m > 0" "m\<noteq>0" by auto
 | 
|  |   1175 |     from prime_ge_2[OF p(1)] have "1 < p" by arith
 | 
|  |   1176 |     with m0 m have mn: "m < n" by auto
 | 
|  |   1177 |     from H[rule_format, OF mn m0(2)] obtain ps where ps: "primefact ps m" ..
 | 
|  |   1178 |     from ps m p(1) have "primefact (p#ps) n" by (simp add: primefact_def)
 | 
|  |   1179 |     hence ?ths by blast}
 | 
|  |   1180 |   ultimately show ?ths by blast
 | 
|  |   1181 | qed
 | 
|  |   1182 | 
 | 
|  |   1183 | lemma primefact_contains: 
 | 
|  |   1184 |   assumes pf: "primefact ps n" and p: "prime p" and pn: "p dvd n"
 | 
|  |   1185 |   shows "p \<in> set ps"
 | 
|  |   1186 |   using pf p pn
 | 
|  |   1187 | proof(induct ps arbitrary: p n)
 | 
|  |   1188 |   case Nil thus ?case by (auto simp add: primefact_def)
 | 
|  |   1189 | next
 | 
|  |   1190 |   case (Cons q qs p n)
 | 
|  |   1191 |   from Cons.prems[unfolded primefact_def] 
 | 
|  |   1192 |   have q: "prime q" "q * foldr op * qs 1 = n" "\<forall>p \<in>set qs. prime p"  and p: "prime p" "p dvd q * foldr op * qs 1" by simp_all
 | 
|  |   1193 |   {assume "p dvd q"
 | 
|  |   1194 |     with p(1) q(1) have "p = q" unfolding prime_def by auto
 | 
|  |   1195 |     hence ?case by simp}
 | 
|  |   1196 |   moreover
 | 
|  |   1197 |   { assume h: "p dvd foldr op * qs 1"
 | 
|  |   1198 |     from q(3) have pqs: "primefact qs (foldr op * qs 1)" 
 | 
|  |   1199 |       by (simp add: primefact_def)
 | 
|  |   1200 |     from Cons.hyps[OF pqs p(1) h] have ?case by simp}
 | 
|  |   1201 |   ultimately show ?case using prime_divprod[OF p] by blast
 | 
|  |   1202 | qed
 | 
|  |   1203 | 
 | 
|  |   1204 | lemma primefact_variant: "primefact ps n \<longleftrightarrow> foldr op * ps 1 = n \<and> list_all prime ps" by (auto simp add: primefact_def list_all_iff)
 | 
|  |   1205 | 
 | 
|  |   1206 | (* Variant of Lucas theorem.                                                 *)
 | 
|  |   1207 | 
 | 
|  |   1208 | lemma lucas_primefact:
 | 
|  |   1209 |   assumes n: "n \<ge> 2" and an: "[a^(n - 1) = 1] (mod n)" 
 | 
|  |   1210 |   and psn: "foldr op * ps 1 = n - 1" 
 | 
|  |   1211 |   and psp: "list_all (\<lambda>p. prime p \<and> \<not> [a^((n - 1) div p) = 1] (mod n)) ps"
 | 
|  |   1212 |   shows "prime n"
 | 
|  |   1213 | proof-
 | 
|  |   1214 |   {fix p assume p: "prime p" "p dvd n - 1" "[a ^ ((n - 1) div p) = 1] (mod n)"
 | 
|  |   1215 |     from psn psp have psn1: "primefact ps (n - 1)" 
 | 
|  |   1216 |       by (auto simp add: list_all_iff primefact_variant)
 | 
|  |   1217 |     from p(3) primefact_contains[OF psn1 p(1,2)] psp
 | 
|  |   1218 |     have False by (induct ps, auto)}
 | 
|  |   1219 |   with lucas[OF n an] show ?thesis by blast
 | 
|  |   1220 | qed
 | 
|  |   1221 | 
 | 
|  |   1222 | (* Variant of Pocklington theorem.                                           *)
 | 
|  |   1223 | 
 | 
|  |   1224 | lemma mod_le: assumes n: "n \<noteq> (0::nat)" shows "m mod n \<le> m"
 | 
|  |   1225 | proof-
 | 
|  |   1226 |     from mod_div_equality[of m n]
 | 
|  |   1227 |     have "\<exists>x. x + m mod n = m" by blast 
 | 
|  |   1228 |     then show ?thesis by auto
 | 
|  |   1229 | qed
 | 
|  |   1230 |   
 | 
|  |   1231 | 
 | 
|  |   1232 | lemma pocklington_primefact:
 | 
|  |   1233 |   assumes n: "n \<ge> 2" and qrn: "q*r = n - 1" and nq2: "n \<le> q^2"
 | 
|  |   1234 |   and arnb: "(a^r) mod n = b" and psq: "foldr op * ps 1 = q" 
 | 
|  |   1235 |   and bqn: "(b^q) mod n = 1"
 | 
|  |   1236 |   and psp: "list_all (\<lambda>p. prime p \<and> coprime ((b^(q div p)) mod n - 1) n) ps"
 | 
|  |   1237 |   shows "prime n"
 | 
|  |   1238 | proof-
 | 
|  |   1239 |   from bqn psp qrn
 | 
|  |   1240 |   have bqn: "a ^ (n - 1) mod n = 1"
 | 
|  |   1241 |     and psp: "list_all (\<lambda>p. prime p \<and> coprime (a^(r *(q div p)) mod n - 1) n) ps"  unfolding arnb[symmetric] power_mod 
 | 
|  |   1242 |     by (simp_all add: power_mult[symmetric] ring_simps)
 | 
|  |   1243 |   from n  have n0: "n > 0" by arith
 | 
|  |   1244 |   from mod_div_equality[of "a^(n - 1)" n]
 | 
|  |   1245 |     mod_less_divisor[OF n0, of "a^(n - 1)"]
 | 
|  |   1246 |   have an1: "[a ^ (n - 1) = 1] (mod n)" 
 | 
|  |   1247 |     unfolding nat_mod bqn
 | 
|  |   1248 |     apply -
 | 
|  |   1249 |     apply (rule exI[where x="0"])
 | 
|  |   1250 |     apply (rule exI[where x="a^(n - 1) div n"])
 | 
|  |   1251 |     by (simp add: ring_simps)
 | 
|  |   1252 |   {fix p assume p: "prime p" "p dvd q"
 | 
|  |   1253 |     from psp psq have pfpsq: "primefact ps q"
 | 
|  |   1254 |       by (auto simp add: primefact_variant list_all_iff)
 | 
|  |   1255 |     from psp primefact_contains[OF pfpsq p] 
 | 
|  |   1256 |     have p': "coprime (a ^ (r * (q div p)) mod n - 1) n"
 | 
|  |   1257 |       by (simp add: list_all_iff)
 | 
|  |   1258 |     from prime_ge_2[OF p(1)] have p01: "p \<noteq> 0" "p \<noteq> 1" "p =Suc(p - 1)" by arith+
 | 
|  |   1259 |     from div_mult1_eq[of r q p] p(2) 
 | 
|  |   1260 |     have eq1: "r* (q div p) = (n - 1) div p"
 | 
|  |   1261 |       unfolding qrn[symmetric] dvd_eq_mod_eq_0 by (simp add: mult_commute)
 | 
|  |   1262 |     have ath: "\<And>a (b::nat). a <= b \<Longrightarrow> a \<noteq> 0 ==> 1 <= a \<and> 1 <= b" by arith
 | 
|  |   1263 |     from n0 have n00: "n \<noteq> 0" by arith
 | 
|  |   1264 |     from mod_le[OF n00]
 | 
|  |   1265 |     have th10: "a ^ ((n - 1) div p) mod n \<le> a ^ ((n - 1) div p)" .
 | 
|  |   1266 |     {assume "a ^ ((n - 1) div p) mod n = 0"
 | 
|  |   1267 |       then obtain s where s: "a ^ ((n - 1) div p) = n*s"
 | 
|  |   1268 | 	unfolding mod_eq_0_iff by blast
 | 
|  |   1269 |       hence eq0: "(a^((n - 1) div p))^p = (n*s)^p" by simp
 | 
|  |   1270 |       from qrn[symmetric] have qn1: "q dvd n - 1" unfolding dvd_def by auto
 | 
|  |   1271 |       from dvd_trans[OF p(2) qn1] div_mod_equality'[of "n - 1" p]
 | 
|  |   1272 |       have npp: "(n - 1) div p * p = n - 1" by (simp add: dvd_eq_mod_eq_0)  
 | 
|  |   1273 |       with eq0 have "a^ (n - 1) = (n*s)^p"
 | 
|  |   1274 | 	by (simp add: power_mult[symmetric])
 | 
|  |   1275 |       hence "1 = (n*s)^(Suc (p - 1)) mod n" using bqn p01 by simp
 | 
|  |   1276 |       also have "\<dots> = 0" by (simp add: mult_assoc mod_mult_self_is_0)
 | 
|  |   1277 |       finally have False by simp }
 | 
|  |   1278 |       then have th11: "a ^ ((n - 1) div p) mod n \<noteq> 0" by auto 
 | 
|  |   1279 |     have th1: "[a ^ ((n - 1) div p) mod n = a ^ ((n - 1) div p)] (mod n)"  
 | 
|  |   1280 |       unfolding modeq_def by simp 
 | 
|  |   1281 |     from cong_sub[OF th1 cong_refl[of 1]]  ath[OF th10 th11]
 | 
|  |   1282 |     have th: "[a ^ ((n - 1) div p) mod n - 1 = a ^ ((n - 1) div p) - 1] (mod n)"
 | 
|  |   1283 |       by blast 
 | 
|  |   1284 |     from cong_coprime[OF th] p'[unfolded eq1] 
 | 
|  |   1285 |     have "coprime (a ^ ((n - 1) div p) - 1) n" by (simp add: coprime_commute) }
 | 
|  |   1286 |   with pocklington[OF n qrn[symmetric] nq2 an1]
 | 
|  |   1287 |   show ?thesis by blast    
 | 
|  |   1288 | qed
 | 
|  |   1289 | 
 | 
|  |   1290 | 
 | 
|  |   1291 | end
 |