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