(`!p. prime p /\ 3 <= p
==> ?g. !j. 1 <= j ==> order(p
REPEAT STRIP_TAC THEN
FIRST_ASSUM(MP_TAC o MATCH_MP
PRIMITIVE_ROOT_MODULO_PRIME) THEN
REWRITE_TAC[
IN_NUMSEG] THEN
DISCH_THEN(X_CHOOSE_THEN `g:num` STRIP_ASSUME_TAC) THEN
MP_TAC(ISPECL [`p:num`; `g:num`]
ORDER) THEN
ASM_SIMP_TAC[
CONG_TO_1;
EXP_EQ_0;
LE_1] THEN
DISCH_THEN(X_CHOOSE_THEN `y:num` STRIP_ASSUME_TAC) THEN
SUBGOAL_THEN `?x. coprime(p,y + (p - 1) * g
EXP (p - 2) * x)` CHOOSE_TAC THENL
[MP_TAC(ISPECL [`(&p - &1:int) * &g pow (p - 2)`; `&1 - &y:int`; `&p:int`]
INT_CONG_SOLVE_POS) THEN
ANTS_TAC THENL
[REWRITE_TAC[
INT_COPRIME_LMUL;
INT_COPRIME_LPOW] THEN
REWRITE_TAC[INTEGER_RULE `coprime(p - &1,p)`; GSYM
num_coprime] THEN
ASM_SIMP_TAC[
INT_OF_NUM_EQ; ARITH_RULE `3 <= p ==> ~(p = 0)`] THEN
DISJ1_TAC THEN MATCH_MP_TAC
PRIME_COPRIME_LT THEN
ASM_REWRITE_TAC[] THEN ASM_ARITH_TAC;
REWRITE_TAC[GSYM
INT_EXISTS_POS] THEN MATCH_MP_TAC
MONO_EXISTS THEN
GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP (INTEGER_RULE
`(x:int == &1 - y) (mod n) ==> coprime(n,y + x)`)) THEN
ASM_SIMP_TAC[
INT_OF_NUM_SUB;
INT_OF_NUM_POW;
INT_OF_NUM_MUL;
INT_OF_NUM_ADD; GSYM
num_coprime;
ARITH_RULE `3 <= p ==> 1 <= p`] THEN
REWRITE_TAC[
MULT_ASSOC]];
ALL_TAC] THEN
EXISTS_TAC `g + p * x:num` THEN X_GEN_TAC `j:num` THEN DISCH_TAC THEN
STRIP_ASSUME_TAC(ISPECL [`p
EXP j`; `g + p * x:num`]
ORDER_WORKS) THEN
MP_TAC(SPECL [`p:num`; `g + p * x:num`; `order (p
EXP j) (g + p * x)`]
ORDER_DIVIDES) THEN
SUBGOAL_THEN `order p (g + p * x) = p - 1` SUBST1_TAC THENL
[ASM_MESON_TAC[
ORDER_CONG; NUMBER_RULE `(g:num == g + p * x) (mod p)`];
ALL_TAC] THEN
MATCH_MP_TAC(TAUT `a /\ (b ==> c) ==> (a <=> b) ==> c`) THEN CONJ_TAC THENL
[MATCH_MP_TAC(NUMBER_RULE
`!y. (a == 1) (mod y) /\ x divides y ==> (a == 1) (mod x)`) THEN
EXISTS_TAC `p
EXP j` THEN ASM_REWRITE_TAC[] THEN
ASM_SIMP_TAC[
DIVIDES_REFL;
DIVIDES_REXP;
LE_1];
REWRITE_TAC[divides;
LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `d:num` THEN
DISCH_THEN(fun th -> SUBST_ALL_TAC th THEN ASSUME_TAC th)] THEN
MP_TAC(ISPECL [`g + p * x:num`; `p
EXP j`]
ORDER_DIVIDES_PHI) THEN
ASM_SIMP_TAC[
PHI_PRIMEPOW;
LE_1;
COPRIME_LEXP] THEN ANTS_TAC THENL
[REWRITE_TAC[NUMBER_RULE `coprime(p,g + p * x) <=> coprime(g,p)`] THEN
MATCH_MP_TAC
PRIME_COPRIME_LT THEN
ASM_REWRITE_TAC[] THEN ASM_ARITH_TAC;
ALL_TAC] THEN
SUBGOAL_THEN `p
EXP j - p
EXP (j - 1) = (p - 1) * p
EXP (j - 1)`
SUBST1_TAC THENL
[UNDISCH_TAC `1 <= j` THEN SPEC_TAC(`j:num`,`j:num`) THEN
INDUCT_TAC THEN REWRITE_TAC[ARITH;
SUC_SUB1] THEN
REWRITE_TAC[
EXP;
RIGHT_SUB_DISTRIB] THEN ARITH_TAC;
ALL_TAC] THEN
DISCH_THEN(MP_TAC o MATCH_MP (NUMBER_RULE
`(a * x:num) divides (a * y) ==> ~(a = 0) ==> x divides y`)) THEN
ASM_SIMP_TAC[
DIVIDES_PRIMEPOW; ARITH_RULE `3 <= p ==> ~(p - 1 = 0)`] THEN
DISCH_THEN(X_CHOOSE_THEN `k:num`
(CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
AP_TERM_TAC THEN AP_TERM_TAC THEN
SUBGOAL_THEN `?z. (g + p * x)
EXP (p - 1) = 1 + z * p /\ coprime(z,p)`
STRIP_ASSUME_TAC THENL
[REWRITE_TAC[
BINOMIAL_THEOREM] THEN
ASM_SIMP_TAC[
NSUM_CLAUSES_RIGHT;
LE_0; ARITH_RULE
`3 <= p ==> 0 < p - 1`] THEN
REWRITE_TAC[
BINOM_REFL;
SUB_REFL;
EXP;
MULT_CLAUSES] THEN
EXISTS_TAC
`y + nsum(0..p-2) (\k. binom(p - 1,k) * g
EXP k *
p
EXP (p - 2 - k) * x
EXP (p - 1 - k))` THEN
REWRITE_TAC[ARITH_RULE `n - 1 - 1 = n - 2`] THEN
SIMP_TAC[ARITH_RULE `s + 1 + y * p = 1 + (y + t) * p <=> s = p * t`] THEN
CONJ_TAC THENL
[REWRITE_TAC[GSYM
NSUM_LMUL] THEN MATCH_MP_TAC
NSUM_EQ THEN
X_GEN_TAC `i:num` THEN REWRITE_TAC[
IN_NUMSEG] THEN STRIP_TAC THEN
SIMP_TAC[ARITH_RULE `p * b * g * pp * x:num = b * g * (p * pp) * x`] THEN
AP_TERM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[
MULT_EXP] THEN
REWRITE_TAC[GSYM(CONJUNCT2
EXP)] THEN
AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN ASM_ARITH_TAC;
ALL_TAC] THEN
ASM_SIMP_TAC[
NSUM_CLAUSES_RIGHT;
LE_0; ARITH_RULE
`3 <= p ==> 0 < p - 2`] THEN
REWRITE_TAC[
BINOM_REFL;
SUB_REFL;
EXP;
MULT_CLAUSES] THEN
ASM_SIMP_TAC[
EXP_1; ARITH_RULE `3 <= p ==> p - 1 - (p - 2) = 1`] THEN
SUBGOAL_THEN `binom(p - 1,p - 2) = p - 1` SUBST1_TAC THENL
[SUBGOAL_THEN `p - 1 = SUC(p - 2)` SUBST1_TAC THENL
[ASM_ARITH_TAC; REWRITE_TAC[
BINOM_PENULT]];
ALL_TAC] THEN
MATCH_MP_TAC(NUMBER_RULE
`coprime(p:num,y + x) /\ p divides z ==> coprime(y + z + x,p)`) THEN
ASM_REWRITE_TAC[] THEN MATCH_MP_TAC
NSUM_CLOSED THEN
REWRITE_TAC[
DIVIDES_0;
DIVIDES_ADD;
IN_NUMSEG] THEN
X_GEN_TAC `i:num` THEN STRIP_TAC THEN
REPLICATE_TAC 2 (MATCH_MP_TAC
DIVIDES_LMUL) THEN
MATCH_MP_TAC
DIVIDES_RMUL THEN MATCH_MP_TAC
DIVIDES_REXP THEN
REWRITE_TAC[
DIVIDES_REFL] THEN ASM_ARITH_TAC;
ALL_TAC] THEN
SUBGOAL_THEN
`?w. (g + p * x)
EXP ((p - 1) * p
EXP k) = 1 + p
EXP (k + 1) * w /\
coprime(w,p)`
STRIP_ASSUME_TAC THENL
[ASM_REWRITE_TAC[GSYM
EXP_EXP] THEN
ONCE_REWRITE_TAC[
CONJ_SYM] THEN
GEN_REWRITE_TAC (BINDER_CONV o funpow 3 RAND_CONV) [
MULT_SYM] THEN
MATCH_MP_TAC
COPRIME_1_PLUS_POWER THEN ASM_REWRITE_TAC[];
UNDISCH_TAC
`((g + p * x)
EXP ((p - 1) * p
EXP k) == 1) (mod (p
EXP j))` THEN
ASM_REWRITE_TAC[NUMBER_RULE `(1 + x == 1) (mod n) <=> n divides x`] THEN
ONCE_REWRITE_TAC[
MULT_SYM] THEN DISCH_TAC THEN
MP_TAC(SPECL [`p:num`; `j:num`; `w:num`; `p
EXP (k + 1)`]
COPRIME_EXP_DIVPROD) THEN
ONCE_REWRITE_TAC[
COPRIME_SYM] THEN ASM_REWRITE_TAC[] THEN
ASM_SIMP_TAC[
DIVIDES_EXP_LE; ARITH_RULE `3 <= p ==> 2 <= p`] THEN
UNDISCH_TAC `k <= j - 1` THEN ARITH_TAC]);;