(* ========================================================================= *)
(* Taylor series for tan and cot, via partial fractions expansion of cot.    *)
(* ========================================================================= *)

needs "Library/analysis.ml";;
needs "Library/transc.ml";;
needs "Library/poly.ml";;
needs "Library/floor.ml";;
needs "Examples/machin.ml";;
needs "Library/iter.ml";;

(* ------------------------------------------------------------------------- *)
(* Compatibility stuff for some old proofs.                                  *)
(* ------------------------------------------------------------------------- *)

let REAL_LE_1_POW2 = 
prove (`!n. &1 <= &2 pow n`,
REWRITE_TAC[REAL_OF_NUM_POW; REAL_OF_NUM_LE; ARITH_RULE `1 <= n <=> 0 < n`; EXP_LT_0; ARITH]);;
let REAL_LT_1_POW2 = 
prove (`!n. &1 < &2 pow n <=> ~(n = 0)`,
GEN_TAC THEN ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `&2 pow 0`)) THEN MATCH_MP_TAC REAL_POW_MONO_LT THEN REWRITE_TAC[REAL_OF_NUM_LT] THEN POP_ASSUM MP_TAC THEN ARITH_TAC);;
let REAL_POW2_CLAUSES = 
prove (`(!n. &0 <= &2 pow n) /\ (!n. &0 < &2 pow n) /\ (!n. &0 <= inv(&2 pow n)) /\ (!n. &0 < inv(&2 pow n)) /\ (!n. inv(&2 pow n) <= &1) /\ (!n. &1 - inv(&2 pow n) <= &1) /\ (!n. &1 <= &2 pow n) /\ (!n. &1 < &2 pow n <=> ~(n = 0)) /\ (!n. &0 <= &1 - inv(&2 pow n)) /\ (!n. &0 <= &2 pow n - &1) /\ (!n. &0 < &1 - inv(&2 pow n) <=> ~(n = 0))`,
SIMP_TAC[REAL_LE_1_POW2; REAL_LT_1_POW2; REAL_SUB_LE; REAL_SUB_LT; REAL_INV_LE_1] THEN SIMP_TAC[REAL_LE_INV_EQ; REAL_LT_INV_EQ; REAL_POW_LT; REAL_POW_LE; REAL_OF_NUM_LE; REAL_OF_NUM_LT; ARITH; REAL_ARITH `&1 - x <= &1 <=> &0 <= x`] THEN GEN_TAC THEN ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&2 pow 1)` THEN ASM_SIMP_TAC[REAL_LE_INV2; REAL_POW_MONO; REAL_POW_LT; REAL_OF_NUM_LT; ARITH; REAL_OF_NUM_LE; ARITH_RULE `1 <= n <=> ~(n = 0)`] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let REAL_INTEGER_CLOSURES = 
prove (`(!n. ?p. abs(&n) = &p) /\ (!x y. (?m. abs(x) = &m) /\ (?n. abs(y) = &n) ==> ?p. abs(x + y) = &p) /\ (!x y. (?m. abs(x) = &m) /\ (?n. abs(y) = &n) ==> ?p. abs(x - y) = &p) /\ (!x y. (?m. abs(x) = &m) /\ (?n. abs(y) = &n) ==> ?p. abs(x * y) = &p) /\ (!x r. (?n. abs(x) = &n) ==> ?p. abs(x pow r) = &p) /\ (!x. (?n. abs(x) = &n) ==> ?p. abs(--x) = &p) /\ (!x. (?n. abs(x) = &n) ==> ?p. abs(abs x) = &p)`,
REWRITE_TAC[GSYM integer; INTEGER_CLOSED]);;
let PI_APPROX_25_BITS = time PI_APPROX_BINARY_RULE 25;; (* ------------------------------------------------------------------------- *) (* Convert a polynomial into a "canonical" list-based form. *) (* ------------------------------------------------------------------------- *) let POLYMERIZE_CONV =
let pth = 
prove (`a = poly [a] x`,
REWRITE_TAC[poly; REAL_MUL_RZERO; REAL_ADD_RID]) and qth = prove (`x * poly p x = poly (CONS (&0) p) x`, REWRITE_TAC[poly; REAL_ADD_LID]) in let conv_base = GEN_REWRITE_CONV I [pth] and conv_zero = GEN_REWRITE_CONV I [qth] and conv_step = GEN_REWRITE_CONV I [GSYM(CONJUNCT2 poly)] in let is_add = is_binop `(+):real->real->real` and is_mul = is_binop `(*):real->real->real` in let rec conv tm = if is_add tm then let l,r = dest_comb tm in let r1,r2 = dest_comb r in let th1 = AP_TERM l (AP_TERM r1 (conv r2)) in TRANS th1 (conv_step(rand(concl th1))) else if is_mul tm then let th1 = AP_TERM (rator tm) (conv (rand tm)) in TRANS th1 (conv_zero(rand(concl th1))) else conv_base tm in conv;; (* ------------------------------------------------------------------------- *) (* Basic definition of cotangent. *) (* ------------------------------------------------------------------------- *)
let cot = new_definition
  `cot x = cos x / sin x`;;
let COT_TAN = 
prove (`cot(x) = inv(tan(x))`,
REWRITE_TAC[cot; tan; REAL_INV_DIV]);;
(* ------------------------------------------------------------------------- *) (* We need to reverse sums to prove the grisly lemma below. *) (* ------------------------------------------------------------------------- *)
let SUM_PERMUTE_0 = 
prove (`!n p. (!y. y < n ==> ?!x. x < n /\ (p(x) = y)) ==> !f. sum(0,n)(\n. f(p n)) = sum(0,n) f`,
INDUCT_TAC THEN GEN_TAC THEN TRY(REWRITE_TAC[sum] THEN NO_TAC) THEN DISCH_TAC THEN GEN_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `n:num`) THEN REWRITE_TAC[LESS_SUC_REFL] THEN CONV_TAC(ONCE_DEPTH_CONV EXISTS_UNIQUE_CONV) THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN DISCH_THEN(X_CHOOSE_THEN `k:num` STRIP_ASSUME_TAC) THEN GEN_REWRITE_TAC RAND_CONV [sum] THEN REWRITE_TAC[ADD_CLAUSES] THEN ABBREV_TAC `q:num->num = \r. if r < k then p(r) else p(SUC r)` THEN SUBGOAL_THEN `!y:num. y < n ==> ?!x. x < n /\ (q x = y)` MP_TAC THENL [X_GEN_TAC `y:num` THEN DISCH_TAC THEN (MP_TAC o ASSUME) `!y. y < (SUC n) ==> ?!x. x < (SUC n) /\ (p x = y)` THEN DISCH_THEN(MP_TAC o SPEC `y:num`) THEN W(C SUBGOAL_THEN MP_TAC o funpow 2 (fst o dest_imp) o snd) THENL [MATCH_MP_TAC LT_TRANS THEN EXISTS_TAC `n:num` THEN ASM_REWRITE_TAC[LESS_SUC_REFL]; DISCH_THEN(fun th -> DISCH_THEN(MP_TAC o C MP th))] THEN CONV_TAC(ONCE_DEPTH_CONV EXISTS_UNIQUE_CONV) THEN DISCH_THEN(X_CHOOSE_THEN `x:num` STRIP_ASSUME_TAC o CONJUNCT1) THEN CONJ_TAC THENL [DISJ_CASES_TAC(SPECL [`x:num`; `k:num`] LTE_CASES) THENL [EXISTS_TAC `x:num` THEN EXPAND_TAC "q" THEN BETA_TAC THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM REAL_OF_NUM_LT] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&k` THEN ASM_REWRITE_TAC[REAL_OF_NUM_LE; REAL_OF_NUM_LT] THEN UNDISCH_TAC `k < (SUC n)` THEN REWRITE_TAC[GSYM LT_SUC_LE; LE_ADD2]; MP_TAC(ASSUME `k <= x:num`) THEN REWRITE_TAC[LE_LT] THEN DISCH_THEN(DISJ_CASES_THEN2 ASSUME_TAC SUBST_ALL_TAC) THENL [EXISTS_TAC `x - 1` THEN EXPAND_TAC "q" THEN BETA_TAC THEN UNDISCH_TAC `k < x:num` THEN DISCH_THEN(X_CHOOSE_THEN `d:num` MP_TAC o MATCH_MP LESS_ADD_1) THEN REWRITE_TAC[GSYM ADD1; ADD_CLAUSES] THEN DISCH_THEN SUBST_ALL_TAC THEN REWRITE_TAC[SUC_SUB1] THEN RULE_ASSUM_TAC(REWRITE_RULE[LT_SUC]) THEN ASM_REWRITE_TAC[] THEN COND_CASES_TAC THEN REWRITE_TAC[] THEN UNDISCH_TAC `(k + d) < k:num` THEN REWRITE_TAC[GSYM LE_SUC_LT] THEN CONV_TAC CONTRAPOS_CONV THEN REWRITE_TAC[GSYM NOT_LT; REWRITE_RULE[ADD_CLAUSES] LESS_ADD_SUC]; SUBST_ALL_TAC(ASSUME `(p:num->num) x = n`) THEN UNDISCH_TAC `y < n:num` THEN ASM_REWRITE_TAC[LT_REFL]]]; SUBGOAL_THEN `!z. q z :num = p(if z < k then z else SUC z)` MP_TAC THENL [GEN_TAC THEN EXPAND_TAC "q" THEN BETA_TAC THEN COND_CASES_TAC THEN REWRITE_TAC[]; DISCH_THEN(fun th -> REWRITE_TAC[th])] THEN MAP_EVERY X_GEN_TAC [`x1:num`; `x2:num`] THEN STRIP_TAC THEN UNDISCH_TAC `!y. y < (SUC n) ==> ?!x. x < (SUC n) /\ (p x = y)` THEN DISCH_THEN(MP_TAC o SPEC `y:num`) THEN REWRITE_TAC[MATCH_MP LESS_SUC (ASSUME `y < n:num`)] THEN CONV_TAC(ONCE_DEPTH_CONV EXISTS_UNIQUE_CONV) THEN DISCH_THEN(MP_TAC o SPECL [`if x1 < k then x1 else SUC x1`; `if x2 < k then x2 else SUC x2`] o CONJUNCT2) THEN ASM_REWRITE_TAC[] THEN W(C SUBGOAL_THEN MP_TAC o funpow 2 (fst o dest_imp) o snd) THENL [CONJ_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[LT_SUC] THEN MATCH_MP_TAC LESS_SUC THEN ASM_REWRITE_TAC[]; DISCH_THEN(fun th -> DISCH_THEN(MP_TAC o C MATCH_MP th)) THEN REPEAT COND_CASES_TAC THEN REWRITE_TAC[SUC_INJ] THENL [DISCH_THEN SUBST_ALL_TAC THEN UNDISCH_TAC `~(x2 < k:num)` THEN CONV_TAC CONTRAPOS_CONV THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN MATCH_MP_TAC LT_TRANS THEN EXISTS_TAC `SUC x2` THEN ASM_REWRITE_TAC[LESS_SUC_REFL]; DISCH_THEN(SUBST_ALL_TAC o SYM) THEN UNDISCH_TAC `~(x1 < k:num)` THEN CONV_TAC CONTRAPOS_CONV THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN MATCH_MP_TAC LT_TRANS THEN EXISTS_TAC `SUC x1` THEN ASM_REWRITE_TAC[LESS_SUC_REFL]]]]; DISCH_THEN(fun th -> FIRST_ASSUM(MP_TAC o C MATCH_MP th)) THEN DISCH_THEN(fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [GSYM th]) THEN BETA_TAC THEN UNDISCH_TAC `k < (SUC n)` THEN REWRITE_TAC[LE_SUC; LT_SUC_LE; LE_ADD2] THEN DISCH_THEN(X_CHOOSE_TAC `d:num` o MATCH_MP LESS_EQUAL_ADD) THEN GEN_REWRITE_TAC (RAND_CONV o RATOR_CONV o ONCE_DEPTH_CONV) [ASSUME `n = k + d:num`] THEN REWRITE_TAC[GSYM SUM_TWO] THEN GEN_REWRITE_TAC (RATOR_CONV o ONCE_DEPTH_CONV) [ASSUME `n = k + d:num`] THEN REWRITE_TAC[ONCE_REWRITE_RULE[ADD_SYM] (GSYM ADD_SUC)] THEN REWRITE_TAC[GSYM SUM_TWO; sum; ADD_CLAUSES] THEN BETA_TAC THEN REWRITE_TAC[GSYM REAL_ADD_ASSOC] THEN BINOP_TAC THENL [MATCH_MP_TAC SUM_EQ THEN X_GEN_TAC `r:num` THEN REWRITE_TAC[ADD_CLAUSES] THEN STRIP_TAC THEN BETA_TAC THEN EXPAND_TAC "q" THEN ASM_REWRITE_TAC[]; GEN_REWRITE_TAC RAND_CONV [REAL_ADD_SYM] THEN REWRITE_TAC[ASSUME `(p:num->num) k = n`; REAL_EQ_LADD] THEN REWRITE_TAC[ADD1; SUM_REINDEX] THEN BETA_TAC THEN MATCH_MP_TAC SUM_EQ THEN X_GEN_TAC `r:num` THEN BETA_TAC THEN REWRITE_TAC[GSYM NOT_LT] THEN DISCH_TAC THEN EXPAND_TAC "q" THEN BETA_TAC THEN ASM_REWRITE_TAC[ADD1]]]);;
let SUM_REVERSE_0 = 
prove (`!n f. sum(0,n) f = sum(0,n) (\k. f((n - 1) - k))`,
REPEAT GEN_TAC THEN MP_TAC(SPECL [`n:num`; `\x. (n - 1) - x`] SUM_PERMUTE_0) THEN REWRITE_TAC[] THEN W(C SUBGOAL_THEN (fun th -> SIMP_TAC[th]) o funpow 2 lhand o snd) THEN X_GEN_TAC `m:num` THEN REWRITE_TAC[EXISTS_UNIQUE_THM] THEN DISCH_TAC THEN REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN EXISTS_TAC `n - 1 - m` THEN CONJ_TAC THEN REPEAT GEN_TAC THEN POP_ASSUM MP_TAC THEN ARITH_TAC);;
let SUM_REVERSE = 
prove (`!n m f. sum(m,n) f = sum(m,n) (\k. f(((n + 2 * m) - 1) - k))`,
REPEAT GEN_TAC THEN SUBST1_TAC(ARITH_RULE `m = 0 + m`) THEN REWRITE_TAC[SUM_REINDEX] THEN GEN_REWRITE_TAC LAND_CONV [SUM_REVERSE_0] THEN REWRITE_TAC[] THEN MATCH_MP_TAC SUM_EQ THEN GEN_TAC THEN REWRITE_TAC[ADD_CLAUSES; LE_0] THEN DISCH_THEN(fun th -> AP_TERM_TAC THEN MP_TAC th) THEN ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Following is lifted from fsincos taylor series. *) (* ------------------------------------------------------------------------- *)
let MCLAURIN_SIN = 
prove (`!x n. abs(sin x - sum(0,n) (\m. (if EVEN m then &0 else -- &1 pow ((m - 1) DIV 2) / &(FACT m)) * x pow m)) <= inv(&(FACT n)) * abs(x) pow n`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`sin`; `\n x. if n MOD 4 = 0 then sin(x) else if n MOD 4 = 1 then cos(x) else if n MOD 4 = 2 then --sin(x) else --cos(x)`] MCLAURIN_ALL_LE) THEN W(C SUBGOAL_THEN (fun th -> REWRITE_TAC[th]) o funpow 2 lhand o snd) THENL [CONJ_TAC THENL [SIMP_TAC[MOD_0; ARITH_EQ; EQT_INTRO(SPEC_ALL ETA_AX)]; ALL_TAC] THEN X_GEN_TAC `m:num` THEN X_GEN_TAC `y:real` THEN REWRITE_TAC[] THEN MP_TAC(SPECL [`m:num`; `4`] DIVISION) THEN REWRITE_TAC[ARITH_EQ] THEN ABBREV_TAC `d = m MOD 4` THEN DISCH_THEN(CONJUNCTS_THEN2 SUBST1_TAC MP_TAC) THEN REWRITE_TAC[ADD1; GSYM ADD_ASSOC; MOD_MULT_ADD] THEN SPEC_TAC(`d:num`,`d:num`) THEN CONV_TAC EXPAND_CASES_CONV THEN CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[] THEN REPEAT CONJ_TAC THEN W(MP_TAC o DIFF_CONV o lhand o rator o snd) THEN SIMP_TAC[REAL_MUL_RID; REAL_NEG_NEG]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPECL [`x:real`; `n:num`]) THEN DISCH_THEN(X_CHOOSE_THEN `t:real` (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN MATCH_MP_TAC(REAL_ARITH `(x = y) /\ abs(u) <= v ==> abs((x + u) - y) <= v`) THEN CONJ_TAC THENL [MATCH_MP_TAC SUM_EQ THEN X_GEN_TAC `r:num` THEN STRIP_TAC THEN REWRITE_TAC[SIN_0; COS_0; REAL_NEG_0] THEN AP_THM_TAC THEN AP_TERM_TAC THEN MP_TAC(SPECL [`r:num`; `4`] DIVISION) THEN REWRITE_TAC[ARITH_EQ] THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN DISCH_THEN(fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [th] THEN MP_TAC(SYM th)) THEN REWRITE_TAC[EVEN_ADD; EVEN_MULT; ARITH_EVEN] THEN UNDISCH_TAC `r MOD 4 < 4` THEN SPEC_TAC(`r MOD 4`,`d:num`) THEN CONV_TAC EXPAND_CASES_CONV THEN CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[] THEN REWRITE_TAC[real_div; REAL_MUL_LZERO] THEN SIMP_TAC[ARITH_RULE `(x + 1) - 1 = x`; ARITH_RULE `(x + 3) - 1 = x + 2`; ARITH_RULE `x * 4 + 2 = 2 * (2 * x + 1)`; ARITH_RULE `x * 4 = 2 * 2 * x`] THEN SIMP_TAC[DIV_MULT; ARITH_EQ] THEN REWRITE_TAC[REAL_POW_NEG; EVEN_ADD; EVEN_MULT; ARITH_EVEN; REAL_POW_ONE]; ALL_TAC] THEN REWRITE_TAC[REAL_ABS_MUL; REAL_INV_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL [REWRITE_TAC[real_div; REAL_ABS_MUL] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN REWRITE_TAC[REAL_ABS_INV; REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_RMUL THEN SIMP_TAC[REAL_LE_INV_EQ; REAL_POS] THEN REPEAT COND_CASES_TAC THEN REWRITE_TAC[REAL_ABS_NEG; SIN_BOUND; COS_BOUND]; ALL_TAC] THEN REWRITE_TAC[REAL_ABS_POW; REAL_LE_REFL]);;
(* ------------------------------------------------------------------------- *) (* The formulas marked with a star on p. 205 of Knopp's book. *) (* ------------------------------------------------------------------------- *)
let COT_HALF_TAN = 
prove (`~(integer x) ==> (cot(pi * x) = &1 / &2 * (cot(pi * x / &2) - tan(pi * x / &2)))`,
REPEAT STRIP_TAC THEN REWRITE_TAC[real_div; REAL_ADD_RDISTRIB; REAL_ADD_LDISTRIB] THEN REWRITE_TAC[REAL_MUL_LID] THEN REWRITE_TAC[GSYM real_div] THEN REWRITE_TAC[cot; tan] THEN REWRITE_TAC[REAL_MUL_RID] THEN SUBGOAL_THEN `pi * x = &2 * pi * x / &2` (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th]) THENL [ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c = (a * c) * b`] THEN SIMP_TAC[REAL_DIV_LMUL; REAL_OF_NUM_EQ; ARITH_EQ] THEN REWRITE_TAC[REAL_MUL_AC]; ALL_TAC] THEN ABBREV_TAC `y = pi * x / &2` THEN REWRITE_TAC[COS_DOUBLE; SIN_DOUBLE] THEN SUBGOAL_THEN `~(sin y = &0) /\ ~(cos y = &0)` STRIP_ASSUME_TAC THENL [EXPAND_TAC "y" THEN REWRITE_TAC[SIN_ZERO; COS_ZERO; real_div] THEN CONJ_TAC THEN ONCE_REWRITE_TAC[REAL_ARITH `(a * b * c = d) <=> (b * a * c = d)`] THEN SIMP_TAC[GSYM REAL_MUL_LNEG; REAL_EQ_MUL_RCANCEL; REAL_ENTIRE; REAL_INV_EQ_0; REAL_OF_NUM_EQ; ARITH_EQ; REAL_LT_IMP_NZ; PI_POS] THEN REWRITE_TAC[OR_EXISTS_THM] THEN REWRITE_TAC[TAUT `a /\ b \/ a /\ c <=> a /\ (b \/ c)`] THEN DISCH_THEN(CHOOSE_THEN(DISJ_CASES_THEN (MP_TAC o AP_TERM `abs`) o CONJUNCT2)) THEN UNDISCH_TAC `~(integer x)` THEN SIMP_TAC[integer; REAL_ABS_NEG; REAL_ABS_NUM; NOT_EXISTS_THM]; ALL_TAC] THEN MATCH_MP_TAC REAL_EQ_RCANCEL_IMP THEN EXISTS_TAC `&2 * sin y * cos y` THEN ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH_EQ] THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_ARITH `(h * (c * s' - s * c')) * t * s * c = (t * h) * (c * c * s * s' - s * s * c * c')`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_OF_NUM_EQ; ARITH_EQ] THEN REWRITE_TAC[REAL_MUL_RID; REAL_MUL_LID; REAL_POW_2]);;
let COT_HALF_POS = 
prove (`~(integer x) ==> (cot(pi * x) = &1 / &2 * (cot(pi * x / &2) + cot(pi * (x + &1) / &2)))`,
REPEAT STRIP_TAC THEN REWRITE_TAC[real_div; REAL_ADD_RDISTRIB; REAL_ADD_LDISTRIB] THEN REWRITE_TAC[REAL_MUL_LID] THEN REWRITE_TAC[GSYM real_div] THEN REWRITE_TAC[cot; COS_ADD; SIN_ADD; COS_PI2; SIN_PI2] THEN REWRITE_TAC[REAL_MUL_RZERO; REAL_ADD_LID; REAL_SUB_LZERO] THEN REWRITE_TAC[REAL_MUL_RID] THEN SUBGOAL_THEN `pi * x = &2 * pi * x / &2` (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th]) THENL [ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c = (a * c) * b`] THEN SIMP_TAC[REAL_DIV_LMUL; REAL_OF_NUM_EQ; ARITH_EQ] THEN REWRITE_TAC[REAL_MUL_AC]; ALL_TAC] THEN ABBREV_TAC `y = pi * x / &2` THEN REWRITE_TAC[COS_DOUBLE; SIN_DOUBLE] THEN SUBGOAL_THEN `~(sin y = &0) /\ ~(cos y = &0)` STRIP_ASSUME_TAC THENL [EXPAND_TAC "y" THEN REWRITE_TAC[SIN_ZERO; COS_ZERO; real_div] THEN CONJ_TAC THEN ONCE_REWRITE_TAC[REAL_ARITH `(a * b * c = d) <=> (b * a * c = d)`] THEN SIMP_TAC[GSYM REAL_MUL_LNEG; REAL_EQ_MUL_RCANCEL; REAL_ENTIRE; REAL_INV_EQ_0; REAL_OF_NUM_EQ; ARITH_EQ; REAL_LT_IMP_NZ; PI_POS] THEN REWRITE_TAC[OR_EXISTS_THM] THEN REWRITE_TAC[TAUT `a /\ b \/ a /\ c <=> a /\ (b \/ c)`] THEN DISCH_THEN(CHOOSE_THEN(DISJ_CASES_THEN (MP_TAC o AP_TERM `abs`) o CONJUNCT2)) THEN UNDISCH_TAC `~(integer x)` THEN SIMP_TAC[integer; REAL_ABS_NEG; REAL_ABS_NUM; NOT_EXISTS_THM]; ALL_TAC] THEN MATCH_MP_TAC REAL_EQ_RCANCEL_IMP THEN EXISTS_TAC `&2 * sin y * cos y` THEN ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH_EQ] THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_ARITH `(h * c * s' + h * --s * c') * t * s * c = (t * h) * (c * c * s * s' - s * s * c * c')`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_OF_NUM_EQ; ARITH_EQ] THEN REWRITE_TAC[REAL_MUL_RID; REAL_MUL_LID; REAL_POW_2]);;
let COT_HALF_NEG = 
prove (`~(integer x) ==> (cot(pi * x) = &1 / &2 * (cot(pi * x / &2) + cot(pi * (x - &1) / &2)))`,
STRIP_TAC THEN ASM_SIMP_TAC[COT_HALF_POS] THEN AP_TERM_TAC THEN AP_TERM_TAC THEN SUBST1_TAC(REAL_ARITH `x + &1 = (x - &1) + &2`) THEN ABBREV_TAC `y = x - &1` THEN REWRITE_TAC[real_div; REAL_ADD_RDISTRIB; REAL_ADD_LDISTRIB] THEN SIMP_TAC[REAL_MUL_RINV; REAL_MUL_RID; REAL_OF_NUM_EQ; ARITH_EQ] THEN REWRITE_TAC[cot; SIN_ADD; COS_ADD; SIN_PI; COS_PI] THEN REWRITE_TAC[REAL_MUL_RZERO; REAL_ADD_RID; REAL_SUB_RZERO] THEN REWRITE_TAC[real_div; REAL_MUL_RNEG; REAL_MUL_LNEG; REAL_INV_NEG] THEN REWRITE_TAC[REAL_NEG_NEG; REAL_MUL_RID]);;
(* ------------------------------------------------------------------------- *) (* By induction, the formula marked with the dagger. *) (* ------------------------------------------------------------------------- *)
let COT_HALF_MULTIPLE = 
prove (`~(integer x) ==> !n. cot(pi * x) = sum(0,2 EXP n) (\k. cot(pi * (x + &k) / &2 pow n) + cot(pi * (x - &k) / &2 pow n)) / &2 pow (n + 1)`,
DISCH_TAC THEN INDUCT_TAC THENL [REWRITE_TAC[EXP; real_pow; REAL_DIV_1; ADD_CLAUSES; REAL_POW_1] THEN CONV_TAC(ONCE_DEPTH_CONV REAL_SUM_CONV) THEN REWRITE_TAC[real_div; REAL_ADD_RID; REAL_SUB_RZERO; GSYM REAL_MUL_2] THEN REWRITE_TAC[AC REAL_MUL_AC `(a * b) * c = b * a * c`] THEN SIMP_TAC[REAL_MUL_RINV; REAL_MUL_RID; REAL_OF_NUM_EQ; ARITH_EQ]; ALL_TAC] THEN FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [th]) THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `sum(0,2 EXP n) (\k. &1 / &2 * (cot (pi * (x + &k) / &2 pow n / &2) + cot (pi * ((x + &k) / &2 pow n + &1) / &2)) + &1 / &2 * (cot (pi * (x - &k) / &2 pow n / &2) + cot (pi * ((x - &k) / &2 pow n - &1) / &2))) / &2 pow (n + 1)` THEN CONJ_TAC THENL [AP_THM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC SUM_EQ THEN X_GEN_TAC `k:num` THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN BINOP_TAC THENL [MATCH_MP_TAC COT_HALF_POS THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = &2 pow n * (x + &k) / &2 pow n - &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [SIMP_TAC[REAL_DIV_LMUL; REAL_POW2_CLAUSES; REAL_LT_IMP_NZ] THEN REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]; MATCH_MP_TAC COT_HALF_NEG THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = &2 pow n * (x - &k) / &2 pow n + &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [SIMP_TAC[REAL_DIV_LMUL; REAL_POW2_CLAUSES; REAL_LT_IMP_NZ] THEN REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]]; ALL_TAC] THEN REWRITE_TAC[GSYM REAL_ADD_LDISTRIB; SUM_CMUL] THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [REAL_MUL_SYM] THEN ONCE_REWRITE_TAC[real_div] THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN BINOP_TAC THENL [ALL_TAC; REWRITE_TAC[real_pow; REAL_POW_ADD; REAL_INV_MUL; GSYM REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV] THEN SUBGOAL_THEN `!k. (x + &k) / &2 pow n + &1 = (x + &(2 EXP n + k)) / &2 pow n` (fun th -> ONCE_REWRITE_TAC[th]) THENL [GEN_TAC THEN MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `&2 pow n` THEN ASM_SIMP_TAC[REAL_DIV_LMUL; REAL_LT_IMP_NZ; REAL_POW2_CLAUSES; REAL_ADD_LDISTRIB] THEN REWRITE_TAC[REAL_MUL_RID; GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_POW] THEN REWRITE_TAC[REAL_ADD_AC]; ALL_TAC] THEN SUBGOAL_THEN `!k. (x - &k) / &2 pow n - &1 = (x - &(2 EXP n + k)) / &2 pow n` (fun th -> ONCE_REWRITE_TAC[th]) THENL [GEN_TAC THEN MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `&2 pow n` THEN ASM_SIMP_TAC[REAL_DIV_LMUL; REAL_LT_IMP_NZ; REAL_POW2_CLAUSES; REAL_SUB_LDISTRIB] THEN REWRITE_TAC[REAL_MUL_RID; GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_POW] THEN REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[EXP; MULT_2; GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_OFFSET)] THEN REWRITE_TAC[real_div; GSYM REAL_MUL_ASSOC; GSYM REAL_INV_MUL] THEN REWRITE_TAC[ONCE_REWRITE_RULE[REAL_MUL_SYM] (GSYM(CONJUNCT2 real_pow))] THEN REWRITE_TAC[SUM_ADD] THEN CONV_TAC(ONCE_DEPTH_CONV (ALPHA_CONV `j:num`)) THEN REWRITE_TAC[REAL_ADD_AC; ADD_AC]);;
let COT_HALF_KNOPP = 
prove (`~(integer x) ==> !n. cot(pi * x) = cot(pi * x / &2 pow n) / &2 pow n + sum(1,2 EXP n - 1) (\k. cot(pi * (x + &k) / &2 pow (n + 1)) + cot(pi * (x - &k) / &2 pow (n + 1))) / &2 pow (n + 1)`,
DISCH_TAC THEN GEN_TAC THEN FIRST_ASSUM(SUBST1_TAC o SPEC `n:num` o MATCH_MP COT_HALF_MULTIPLE) THEN SUBGOAL_THEN `!f. sum(0,2 EXP n) f = f 0 + sum(1,2 EXP n - 1) f` (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th]) THENL [GEN_TAC THEN SUBGOAL_THEN `2 EXP n = 1 + (2 EXP n - 1)` (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th]) THENL [SIMP_TAC[ARITH_RULE `~(x = 0) ==> (1 + (x - 1) = x)`; EXP_EQ_0; ARITH_EQ]; ALL_TAC] THEN REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_DIFF)] THEN REWRITE_TAC[SUM_1; REAL_ADD_AC]; ALL_TAC] THEN REWRITE_TAC[REAL_ADD_RID; REAL_SUB_RZERO; GSYM REAL_MUL_2] THEN GEN_REWRITE_TAC LAND_CONV [real_div] THEN GEN_REWRITE_TAC LAND_CONV [REAL_ADD_RDISTRIB] THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `(&2 * cot (pi * x / &2 pow n)) / &2 pow (n + 1) + sum(1,2 EXP n - 1) (\k. &1 / &2 * (cot (pi * (x + &k) / &2 pow n / &2) + cot (pi * ((x + &k) / &2 pow n - &1) / &2)) + &1 / &2 * (cot (pi * (x - &k) / &2 pow n / &2) + cot (pi * ((x - &k) / &2 pow n + &1) / &2))) / &2 pow (n + 1)` THEN CONJ_TAC THENL [AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC SUM_EQ THEN X_GEN_TAC `k:num` THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN BINOP_TAC THENL [MATCH_MP_TAC COT_HALF_NEG THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = &2 pow n * (x + &k) / &2 pow n - &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [SIMP_TAC[REAL_DIV_LMUL; REAL_POW2_CLAUSES; REAL_LT_IMP_NZ] THEN REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]; MATCH_MP_TAC COT_HALF_POS THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = &2 pow n * (x - &k) / &2 pow n + &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [SIMP_TAC[REAL_DIV_LMUL; REAL_POW2_CLAUSES; REAL_LT_IMP_NZ] THEN REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]]; ALL_TAC] THEN REWRITE_TAC[GSYM REAL_ADD_LDISTRIB; SUM_CMUL] THEN ONCE_REWRITE_TAC[AC REAL_ADD_AC `(a + b) + (c + d) = (a + c) + (b + d)`] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [SUM_ADD] THEN GEN_REWRITE_TAC (funpow 2 (LAND_CONV o RAND_CONV) o RAND_CONV) [SUM_REVERSE] THEN SUBGOAL_THEN `(2 EXP n - 1 + 2 * 1) - 1 = 2 EXP n` SUBST1_TAC THENL [SUBGOAL_THEN `~(2 EXP n = 0)` MP_TAC THENL [REWRITE_TAC[EXP_EQ_0; ARITH_EQ]; SPEC_TAC(`2 EXP n`,`m:num`) THEN ARITH_TAC]; ALL_TAC] THEN REWRITE_TAC[GSYM SUM_ADD] THEN BINOP_TAC THENL [GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [REAL_MUL_SYM] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN REWRITE_TAC[real_div; REAL_POW_ADD; REAL_INV_MUL; REAL_MUL_ASSOC] THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_MUL_RID]; ALL_TAC] THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[GSYM SUM_CMUL] THEN MATCH_MP_TAC SUM_EQ THEN X_GEN_TAC `k:num` THEN REWRITE_TAC[LE_0; ADD_CLAUSES] THEN STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [REAL_MUL_SYM] THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [real_div] THEN REWRITE_TAC[REAL_MUL_LID] THEN REWRITE_TAC[GSYM real_div] THEN SIMP_TAC[REAL_EQ_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN MATCH_MP_TAC(REAL_ARITH `(a = e) /\ (d = e) /\ (b = f) /\ (c = f) ==> ((a + b) + (c + d) = (e + f) * &2)`) THEN UNDISCH_TAC `k < 2 EXP n - 1 + 1` THEN SIMP_TAC[ARITH_RULE `~(p = 0) ==> (k < p - 1 + 1 <=> k < p)`; EXP_EQ_0; ARITH_EQ] THEN DISCH_TAC THEN SUBGOAL_THEN `!x. (x / &2 pow n + &1 = (x + &2 pow n) / &2 pow n) /\ (x / &2 pow n - &1 = (x - &2 pow n) / &2 pow n)` (fun th -> REWRITE_TAC[th]) THENL [SIMP_TAC[REAL_EQ_RDIV_EQ; REAL_POW2_CLAUSES; REAL_ADD_RDISTRIB; REAL_SUB_RDISTRIB; REAL_MUL_LID; REAL_DIV_RMUL; REAL_LT_IMP_NZ]; ALL_TAC] THEN SUBGOAL_THEN `!x. x / &2 pow n / &2 = x / &2 pow (n + 1)` (fun th -> REWRITE_TAC[th]) THENL [REWRITE_TAC[REAL_POW_ADD; real_div; REAL_POW_1; REAL_INV_MUL; GSYM REAL_MUL_ASSOC]; ALL_TAC] THEN ASM_SIMP_TAC[LT_IMP_LE; GSYM REAL_OF_NUM_SUB; GSYM REAL_OF_NUM_POW] THEN CONJ_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Bounds on the terms in this series. *) (* ------------------------------------------------------------------------- *)
let SIN_SUMDIFF_LEMMA = 
prove (`!x y. sin(x + y) * sin(x - y) = (sin x + sin y) * (sin x - sin y)`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_ARITH `(x + y) * (x - y) = x * x - y * y`] THEN REWRITE_TAC[SIN_ADD; real_sub; SIN_NEG; COS_NEG] THEN REWRITE_TAC[REAL_ADD_LDISTRIB; REAL_ADD_RDISTRIB] THEN REWRITE_TAC[GSYM REAL_ADD_ASSOC; GSYM REAL_MUL_ASSOC; REAL_MUL_LNEG; REAL_MUL_RNEG; REAL_NEG_NEG] THEN REWRITE_TAC[REAL_ARITH `(a = sx * sx + --(sy * sy)) <=> (a + sy * sy + --(sx * sx) = &0)`] THEN REWRITE_TAC[REAL_ARITH `a + --(sx * cy * cx * sy) + cx * sy * sx * cy + b = a + b`] THEN REWRITE_TAC[REAL_ARITH `(sx * cy * sx * cy + --(cx * sy * cx * sy)) + sy * sy + --(sx * sx) = (sy * sy + (sx * sx + cx * cx) * (cy * cy)) - (sx * sx + (sy * sy + cy * cy) * (cx * cx))`] THEN REWRITE_TAC[REWRITE_RULE[REAL_POW_2] SIN_CIRCLE; REAL_MUL_LID] THEN REWRITE_TAC[REAL_SUB_REFL]);;
let SIN_ZERO_LEMMA = 
prove (`!x. (sin(pi * x) = &0) <=> integer(x)`,
REWRITE_TAC[integer; SIN_ZERO; EVEN_EXISTS] THEN ONCE_REWRITE_TAC[TAUT `a /\ b <=> ~(a ==> ~b)`] THEN SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `(a * b) * c * d = c * b * a * d`] THEN SIMP_TAC[REAL_MUL_RINV; REAL_OF_NUM_EQ; ARITH_EQ; REAL_MUL_RID] THEN REWRITE_TAC[GSYM REAL_MUL_RNEG] THEN SIMP_TAC[GSYM REAL_ADD_LDISTRIB; GSYM REAL_SUB_LDISTRIB; REAL_EQ_MUL_LCANCEL; PI_POS; REAL_LT_IMP_NZ] THEN REWRITE_TAC[NOT_IMP; NOT_FORALL_THM] THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[LEFT_EXISTS_AND_THM; EXISTS_REFL] THEN REWRITE_TAC[REAL_MUL_RNEG; OR_EXISTS_THM] THEN REWRITE_TAC[REAL_ARITH `(abs(x) = a) <=> &0 <= a /\ ((x = a) \/ (x = --a))`] THEN REWRITE_TAC[REAL_POS]);;
let NOT_INTEGER_LEMMA = 
prove (`~(x = &0) /\ abs(x) < &1 ==> ~(integer x)`,
ONCE_REWRITE_TAC[GSYM REAL_ABS_ZERO] THEN CONV_TAC CONTRAPOS_CONV THEN SIMP_TAC[integer; LEFT_IMP_EXISTS_THM] THEN GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[REAL_OF_NUM_EQ; REAL_OF_NUM_LT] THEN ARITH_TAC);;
let NOT_INTEGER_DIV_POW2 = 
prove (`~(integer x) ==> ~(integer(x / &2 pow n))`,
REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = &2 pow n * x / &2 pow n` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [SIMP_TAC[REAL_DIV_LMUL; REAL_LT_IMP_NZ; REAL_POW2_CLAUSES]; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]);;
let SIN_ABS_LEMMA = 
prove (`!x. abs(x) < pi ==> (abs(sin x) = sin(abs x))`,
GEN_TAC THEN ASM_CASES_TAC `x = &0` THEN ASM_REWRITE_TAC[SIN_0; REAL_ABS_NUM] THEN REWRITE_TAC[real_abs] THEN ASM_CASES_TAC `&0 <= x` THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THENL [SUBGOAL_THEN `&0 < sin x` (fun th -> ASM_SIMP_TAC[th; REAL_LT_IMP_LE]) THEN MATCH_MP_TAC SIN_POS_PI THEN ASM_REWRITE_TAC[real_abs] THEN ASM_REWRITE_TAC[REAL_LT_LE]; SUBGOAL_THEN `&0 < --(sin x)` (fun th -> SIMP_TAC[th; SIN_NEG; REAL_ARITH `&0 < --x ==> ~(&0 <= x)`]) THEN REWRITE_TAC[GSYM SIN_NEG] THEN MATCH_MP_TAC SIN_POS_PI THEN ASM_SIMP_TAC[REAL_ARITH `~(x = &0) /\ ~(&0 <= x) ==> &0 < --x`]]);;
let SIN_EQ_LEMMA = 
prove (`!x y. &0 <= x /\ x < pi / &2 /\ &0 <= y /\ y < pi / &2 ==> ((sin x = sin y) <=> (x = y))`,
SUBGOAL_THEN `!x y. &0 <= x /\ x < pi / &2 /\ &0 <= y /\ y < pi / &2 /\ x < y ==> sin x < sin y` ASSUME_TAC THENL [ALL_TAC; REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[] THEN CONV_TAC CONTRAPOS_CONV THEN REWRITE_TAC[REAL_ARITH `~(x = y) <=> x < y \/ y < x`] THEN ASM_MESON_TAC[]] THEN REPEAT STRIP_TAC THEN MP_TAC(SPECL [`sin`; `cos`; `x:real`; `y:real`] MVT_ALT) THEN ASM_REWRITE_TAC[DIFF_SIN; REAL_EQ_SUB_RADD] THEN DISCH_THEN(X_CHOOSE_THEN `z:real` STRIP_ASSUME_TAC) THEN ASM_REWRITE_TAC[REAL_ARITH `x < a + x <=> &0 < a`] THEN MATCH_MP_TAC REAL_LT_MUL THEN ASM_REWRITE_TAC[REAL_SUB_LT] THEN MATCH_MP_TAC COS_POS_PI2 THEN ASM_MESON_TAC[REAL_LET_TRANS; REAL_LT_TRANS]);;
let KNOPP_TERM_EQUIVALENT = 
prove (`~(integer x) /\ k < 2 EXP n ==> ((cot(pi * (x + &k) / &2 pow (n + 1)) + cot(pi * (x - &k) / &2 pow (n + 1))) / &2 pow (n + 1) = cot(pi * x / &2 pow (n + 1)) / &2 pow n / (&1 - sin(pi * &k / &2 pow (n + 1)) pow 2 / sin(pi * x / &2 pow (n + 1)) pow 2))`,
let lemma = prove
   (`~(x = &0) /\ (x * a = b) ==> (a = b / x)`,
    REPEAT STRIP_TAC THEN
    MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `x:real` THEN
    ASM_SIMP_TAC[REAL_DIV_LMUL]) in
  REPEAT STRIP_TAC THEN SIMP_TAC[REAL_EQ_LDIV_EQ; REAL_POW2_CLAUSES] THEN
  GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [REAL_POW_ADD] THEN
  REWRITE_TAC[REAL_POW_1; real_div] THEN
  GEN_REWRITE_TAC RAND_CONV [AC REAL_MUL_AC
   `((a * b') * c) * b * &2 = (&2 * a) * c * b * b'`] THEN
  SIMP_TAC[REAL_MUL_RINV; REAL_POW_EQ_0; REAL_OF_NUM_EQ; ARITH_EQ] THEN
  REWRITE_TAC[real_div; REAL_ADD_LDISTRIB; REAL_SUB_LDISTRIB;
              REAL_ADD_RDISTRIB; REAL_SUB_RDISTRIB] THEN
  REWRITE_TAC[REAL_MUL_RID; GSYM real_div] THEN
  ABBREV_TAC `a = pi * x / &2 pow (n + 1)` THEN
  ABBREV_TAC `b = pi * &k / &2 pow (n + 1)` THEN
  SUBGOAL_THEN
   `~(sin(a + b) = &0) /\
    ~(sin a = &0) /\
    ~(sin(a - b) = &0) /\
    ~(&1 - sin(b) pow 2 / sin(a) pow 2 = &0)`
  STRIP_ASSUME_TAC THENL
   [MATCH_MP_TAC(TAUT
      `(a /\ b /\ c) /\ (b ==> d) ==> a /\ b /\ c /\ d`) THEN
    CONJ_TAC THENL
     [MAP_EVERY EXPAND_TAC ["a";
"b"] THEN REWRITE_TAC[GSYM REAL_ADD_LDISTRIB; GSYM REAL_SUB_LDISTRIB] THEN REWRITE_TAC[SIN_ZERO_LEMMA] THEN REWRITE_TAC[real_div] THEN REWRITE_TAC[GSYM REAL_ADD_RDISTRIB; GSYM REAL_SUB_RDISTRIB] THEN REWRITE_TAC[GSYM real_div] THEN REPEAT CONJ_TAC THEN MATCH_MP_TAC NOT_INTEGER_DIV_POW2 THEN ASM_REWRITE_TAC[] THENL [UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = (x + &k) - &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]; UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = (x - &k) + &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]]; ALL_TAC] THEN DISCH_TAC THEN REWRITE_TAC[REAL_SUB_0] THEN DISCH_THEN(MP_TAC o AP_TERM `( * ) (sin(a) pow 2)`) THEN ASM_SIMP_TAC[REAL_DIV_LMUL; REAL_POW_EQ_0; REAL_MUL_RID] THEN REWRITE_TAC[REAL_POW_2] THEN ONCE_REWRITE_TAC[REAL_ARITH `(a * a = b * b) <=> ((a + b) * (a - b) = &0)`] THEN REWRITE_TAC[GSYM SIN_SUMDIFF_LEMMA] THEN REWRITE_TAC[REAL_ENTIRE; DE_MORGAN_THM] THEN MAP_EVERY EXPAND_TAC ["a"; "b"] THEN REWRITE_TAC[GSYM REAL_ADD_LDISTRIB; GSYM REAL_SUB_LDISTRIB] THEN REWRITE_TAC[SIN_ZERO_LEMMA] THEN REWRITE_TAC[real_div; GSYM REAL_ADD_RDISTRIB; GSYM REAL_SUB_RDISTRIB] THEN REWRITE_TAC[GSYM real_div] THEN CONJ_TAC THEN MATCH_MP_TAC NOT_INTEGER_DIV_POW2 THENL [UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = (x + &k) - &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]; UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN SUBGOAL_THEN `x = (x - &k) + &k` (fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THENL [REAL_ARITH_TAC; SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]]; ALL_TAC] THEN REWRITE_TAC[cot; TAN_ADD; real_sub] THEN REWRITE_TAC[GSYM real_sub] THEN MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `sin(a + b)` THEN ASM_SIMP_TAC[REAL_ADD_LDISTRIB; REAL_DIV_LMUL] THEN MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `sin(a - b)` THEN ONCE_REWRITE_TAC[REAL_ARITH `a * (b + c * d) = a * b + c * a * d`] THEN ASM_SIMP_TAC[REAL_ADD_LDISTRIB; REAL_DIV_LMUL] THEN MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `&1 - sin(b) pow 2 / sin(a) pow 2` THEN ONCE_REWRITE_TAC[REAL_ARITH `a * b * c * da = b * c * a * da`] THEN ASM_SIMP_TAC[REAL_DIV_LMUL] THEN MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `sin(a) pow 2` THEN ASM_REWRITE_TAC[REAL_POW_2; REAL_ENTIRE] THEN REWRITE_TAC[real_div; REAL_INV_MUL] THEN ONCE_REWRITE_TAC[REAL_ARITH `((sa * sa) * (&1 - sb2 * sa' * sa') * others = (sa * sa) * v * w * x * y * sa') = (others * (sa * sa - sb2 * (sa * sa') * (sa * sa')) = sa * v * w * x * y * sa * sa')`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_MUL_LID; REAL_MUL_RID] THEN SUBGOAL_THEN `sin(a - b) * cos(a + b) + sin(a + b) * cos(a - b) = sin(&2 * a)` SUBST1_TAC THENL [GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [REAL_MUL_SYM] THEN REWRITE_TAC[GSYM SIN_ADD] THEN AP_TERM_TAC THEN REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[SIN_DOUBLE] THEN GEN_REWRITE_TAC RAND_CONV [REAL_ARITH `sa * samb * sapb * &2 * ca = (&2 * sa * ca) * samb * sapb`] THEN AP_TERM_TAC THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[SIN_SUMDIFF_LEMMA] THEN REAL_ARITH_TAC);;
let SIN_LINEAR_ABOVE = 
prove (`!x. abs(x) < &1 ==> abs(sin x) <= &2 * abs(x)`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`x:real`; `2`] MCLAURIN_SIN) THEN CONV_TAC(ONCE_DEPTH_CONV REAL_SUM_CONV) THEN REWRITE_TAC[real_pow; REAL_POW_1] THEN CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_DIV_1; REAL_MUL_LID; REAL_POW_1; REAL_ADD_LID] THEN MATCH_MP_TAC(REAL_ARITH `abs(a) <= abs(x) ==> abs(s - x) <= a ==> abs(s) <= &2 * abs(x)`) THEN REWRITE_TAC[REAL_POW_2; REAL_MUL_ASSOC; REAL_ABS_MUL] THEN REWRITE_TAC[REAL_ABS_ABS] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&1 / &2 * &1` THEN CONJ_TAC THENL [ALL_TAC; CONV_TAC REAL_RAT_REDUCE_CONV] THEN MATCH_MP_TAC REAL_LE_LMUL THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let SIN_LINEAR_BELOW = 
prove (`!x. abs(x) < &2 ==> abs(sin x) >= abs(x) / &3`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`x:real`; `3`] MCLAURIN_SIN) THEN CONV_TAC(ONCE_DEPTH_CONV REAL_SUM_CONV) THEN REWRITE_TAC[real_pow; REAL_POW_1] THEN CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_DIV_1; REAL_MUL_LID; REAL_POW_1; REAL_ADD_LID] THEN REWRITE_TAC[REAL_MUL_LZERO; REAL_ADD_RID] THEN SIMP_TAC[real_ge; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN MATCH_MP_TAC(REAL_ARITH `&3 * abs(a) <= &2 * abs(x) ==> abs(s - x) <= a ==> abs(x) <= abs(s) * &3`) THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_POW; REAL_ABS_ABS; REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN CONV_TAC(LAND_CONV(RAND_CONV(RAND_CONV num_CONV))) THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[real_pow; GSYM REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[real_div; REAL_MUL_LID] THEN REWRITE_TAC[GSYM real_div] THEN SIMP_TAC[REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN REWRITE_TAC[GSYM REAL_POW_2] THEN MATCH_MP_TAC REAL_POW_LE2 THEN ASM_SIMP_TAC[REAL_ABS_POS; REAL_LT_IMP_LE]);;
let KNOPP_TERM_BOUND_LEMMA = 
prove (`~(integer x) /\ k < 2 EXP n /\ &6 * abs(x) < &k ==> abs(a / (&1 - sin(pi * &k / &2 pow (n + 1)) pow 2 / sin(pi * x / &2 pow (n + 1)) pow 2)) <= abs(a) / ((&k / (&6 * x)) pow 2 - &1)`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `~(x = &0)` ASSUME_TAC THENL [UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `(~b ==> ~a) <=> (a ==> b)`] THEN SIMP_TAC[integer; REAL_ABS_NUM; REAL_OF_NUM_EQ; GSYM EXISTS_REFL]; ALL_TAC] THEN REWRITE_TAC[REAL_ABS_DIV] THEN ONCE_REWRITE_TAC[real_div] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN MATCH_MP_TAC REAL_LE_INV2 THEN CONJ_TAC THENL [REWRITE_TAC[REAL_SUB_LT] THEN ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN REWRITE_TAC[REAL_ABS_DIV; REAL_ABS_MUL; REAL_ABS_NUM] THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_MUL_LID] THEN REWRITE_TAC[GSYM REAL_POW_2] THEN MATCH_MP_TAC REAL_POW_LT2 THEN REWRITE_TAC[REAL_OF_NUM_LE; ARITH] THEN UNDISCH_TAC `&6 * abs(x) < &k` THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [GSYM REAL_MUL_LID] THEN MATCH_MP_TAC(TAUT `(b <=> a) ==> a ==> b`) THEN MATCH_MP_TAC REAL_LT_RDIV_EQ THEN ASM_SIMP_TAC[REAL_LT_MUL; REAL_OF_NUM_LT; ARITH; GSYM REAL_ABS_NZ]; ALL_TAC] THEN MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ x <= y ==> x - &1 <= abs(&1 - y)`) THEN CONJ_TAC THENL [REWRITE_TAC[REAL_POW_2; REAL_LE_SQUARE]; ALL_TAC] THEN REWRITE_TAC[GSYM REAL_POW_DIV] THEN ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN MATCH_MP_TAC REAL_POW_LE2 THEN REWRITE_TAC[REAL_ABS_POS] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `(abs(pi * &k / &2 pow (n + 1)) / &3) * inv(&2 * abs(pi * x / &2 pow (n + 1)))` THEN CONJ_TAC THENL [REWRITE_TAC[REAL_ABS_DIV; REAL_ABS_MUL; REAL_ABS_POW; REAL_ABS_NUM] THEN REWRITE_TAC[real_div; GSYM REAL_MUL_ASSOC; REAL_INV_MUL] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `p * k * q' * k1 * k2 * p' * x' * q = k * (k1 * k2) * x' * (p * p') * (q * q')`] THEN SIMP_TAC[REAL_INV_INV; REAL_MUL_RINV; REAL_ABS_ZERO; REAL_LT_IMP_NZ; REAL_POW2_CLAUSES; PI_POS] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_MUL_RID; REAL_LE_REFL]; ALL_TAC] THEN GEN_REWRITE_TAC RAND_CONV [REAL_ABS_DIV] THEN GEN_REWRITE_TAC RAND_CONV [real_div] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN SIMP_TAC[REAL_LE_INV_EQ; REAL_LE_DIV; REAL_LE_MUL; REAL_ABS_POS; REAL_POS] THEN CONJ_TAC THENL [REWRITE_TAC[GSYM real_ge] THEN MATCH_MP_TAC SIN_LINEAR_BELOW THEN REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN SIMP_TAC[REAL_ABS_DIV; REAL_ABS_POW; REAL_ABS_NUM; REAL_LT_LDIV_EQ; REAL_POW2_CLAUSES] THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM] THEN SIMP_TAC[real_abs; REAL_LT_IMP_LE; PI_POS] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `pi * &2 pow n` THEN CONJ_TAC THENL [ASM_SIMP_TAC[REAL_LT_LMUL_EQ; PI_POS; REAL_OF_NUM_POW; REAL_OF_NUM_LT]; ALL_TAC] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN REWRITE_TAC[REAL_POW_ADD; REAL_MUL_ASSOC] THEN SIMP_TAC[REAL_LE_RMUL_EQ; REAL_POW2_CLAUSES] THEN MATCH_MP_TAC(C MATCH_MP PI_APPROX_25_BITS (REAL_ARITH `abs(p - y) <= e ==> y + e <= a ==> p <= a`)) THEN CONV_TAC REAL_RAT_REDUCE_CONV; MATCH_MP_TAC REAL_LE_INV2 THEN REWRITE_TAC[GSYM REAL_ABS_NZ; SIN_ZERO_LEMMA] THEN ASM_SIMP_TAC[NOT_INTEGER_DIV_POW2] THEN MATCH_MP_TAC SIN_LINEAR_ABOVE THEN REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN SIMP_TAC[REAL_ABS_DIV; REAL_ABS_POW; REAL_ABS_NUM; REAL_LT_LDIV_EQ; REAL_POW2_CLAUSES] THEN REWRITE_TAC[REAL_MUL_LID] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN MATCH_MP_TAC REAL_LT_LCANCEL_IMP THEN EXISTS_TAC `abs(&6)` THEN CONV_TAC (LAND_CONV REAL_RAT_REDUCE_CONV) THEN REWRITE_TAC[GSYM REAL_ABS_MUL; REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `abs(&k * pi)` THEN CONJ_TAC THENL [ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LT_RMUL THEN ASM_REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM] THEN SIMP_TAC[PI_POS; REAL_ARITH `&0 < x ==> &0 < abs x`]; ALL_TAC] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs(&2 pow n * pi)` THEN CONJ_TAC THENL [ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[REAL_ABS_NUM; REAL_OF_NUM_POW; REAL_OF_NUM_LE] THEN ASM_SIMP_TAC[LT_IMP_LE]; ALL_TAC] THEN GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN REWRITE_TAC[REAL_POW_ADD; REAL_ABS_POW; REAL_ABS_NUM; REAL_ABS_MUL; GSYM REAL_MUL_ASSOC] THEN SIMP_TAC[REAL_LE_LMUL_EQ; REAL_POW2_CLAUSES] THEN MATCH_MP_TAC(C MATCH_MP PI_APPROX_25_BITS (REAL_ARITH `abs(p - y) <= e ==> abs y + e <= a ==> abs p <= a`)) THEN CONV_TAC REAL_RAT_REDUCE_CONV]);;
let KNOPP_TERM_BOUND = 
prove (`~(integer x) /\ k < 2 EXP n /\ &6 * abs(x) < &k ==> abs((cot(pi * (x + &k) / &2 pow (n + 1)) + cot(pi * (x - &k) / &2 pow (n + 1))) / &2 pow (n + 1)) <= abs(cot(pi * x / &2 pow (n + 1)) / &2 pow n) * (&36 * x pow 2) / (&k pow 2 - &36 * x pow 2)`,
REPEAT STRIP_TAC THEN ASM_SIMP_TAC[KNOPP_TERM_EQUIVALENT] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs(cot(pi * x / &2 pow (n + 1)) / &2 pow n) / ((&k / (&6 * x)) pow 2 - &1)` THEN ASM_SIMP_TAC[KNOPP_TERM_BOUND_LEMMA] THEN GEN_REWRITE_TAC LAND_CONV [real_div] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN MATCH_MP_TAC REAL_EQ_IMP_LE THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_INV_DIV] THEN AP_TERM_TAC THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `&6 pow 2`)) THEN REWRITE_TAC[GSYM REAL_POW_MUL] THEN REWRITE_TAC[REAL_POW_DIV] THEN SUBGOAL_THEN `&0 < (&6 * x) pow 2` (fun th -> SIMP_TAC[th; REAL_EQ_RDIV_EQ; REAL_SUB_RDISTRIB; REAL_MUL_LID; REAL_DIV_RMUL; REAL_LT_IMP_NZ]) THEN ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN MATCH_MP_TAC REAL_POW_LT THEN REWRITE_TAC[GSYM REAL_ABS_NZ; REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH_EQ] THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `(~b ==> ~a) <=> (a ==> b)`] THEN SIMP_TAC[integer; REAL_ABS_NUM; REAL_OF_NUM_EQ; GSYM EXISTS_REFL]);;
(* ------------------------------------------------------------------------- *) (* Show that the series we're looking at do in fact converge... *) (* ------------------------------------------------------------------------- *)
let SUMMABLE_INVERSE_SQUARES_LEMMA = 
prove (`(\n. inv(&(n + 1) * &(n + 2))) sums &1`,
REWRITE_TAC[sums] THEN SUBGOAL_THEN `!n. sum(0,n) (\m. inv(&(m + 1) * &(m + 2))) = &1 - inv(&(n + 1))` (fun th -> REWRITE_TAC[th]) THENL [INDUCT_TAC THEN REWRITE_TAC[sum] THEN CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[ADD_CLAUSES] THEN REWRITE_TAC[REAL_ARITH `(&1 - a + b = &1 - c) <=> (b + c = a)`] THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC REAL_MUL_LINV_UNIQ THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REAL_INV_MUL; REAL_MUL_ASSOC; REAL_ADD_LDISTRIB] THEN SIMP_TAC[REAL_MUL_RINV; REAL_OF_NUM_EQ; ARITH_RULE `~(n + 1 = 0)`] THEN REWRITE_TAC[REAL_MUL_LID; ARITH_RULE `SUC(n + 1) = n + 2`] THEN MATCH_MP_TAC REAL_EQ_RCANCEL_IMP THEN EXISTS_TAC `&(n + 2)` THEN SIMP_TAC[REAL_ADD_RDISTRIB; real_div; GSYM REAL_MUL_ASSOC; REAL_OF_NUM_EQ; REAL_MUL_LINV; ARITH_RULE `~(n + 2 = 0)`; REAL_MUL_LID; REAL_MUL_RID] THEN REWRITE_TAC[GSYM REAL_OF_NUM_ADD; REAL_OF_NUM_EQ] THEN ARITH_TAC; ALL_TAC] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_SUB_RZERO] THEN MATCH_MP_TAC SEQ_SUB THEN REWRITE_TAC[SEQ_CONST] THEN MATCH_MP_TAC SEQ_INV0 THEN X_GEN_TAC `x:real` THEN X_CHOOSE_TAC `N:num` (SPEC `x:real` REAL_ARCH_SIMPLE) THEN EXISTS_TAC `N:num` THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[real_gt; GE] THEN DISCH_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `&N` THEN ASM_REWRITE_TAC[] THEN ASM_SIMP_TAC[REAL_OF_NUM_LT; ARITH_RULE `a < b + 1 <=> a <= b`]);;
let SUMMABLE_INVERSE_SQUARES = 
prove (`summable (\n. inv(&n pow 2))`,
MATCH_MP_TAC SUM_SUMMABLE THEN EXISTS_TAC `sum(0,2) (\n. inv(&n pow 2)) + suminf (\n. inv(&(n + 2) pow 2))` THEN MATCH_MP_TAC SER_OFFSET_REV THEN MATCH_MP_TAC SER_ACONV THEN MATCH_MP_TAC SER_COMPARA THEN EXISTS_TAC `\n. inv(&(n + 1) * &(n + 2))` THEN CONJ_TAC THENL [ALL_TAC; MATCH_MP_TAC SUM_SUMMABLE THEN EXISTS_TAC `&1` THEN REWRITE_TAC[SUMMABLE_INVERSE_SQUARES_LEMMA]] THEN EXISTS_TAC `0` THEN X_GEN_TAC `n:num` THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[REAL_POW_2; REAL_INV_MUL; REAL_ABS_INV; REAL_ABS_NUM; REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_LE_INV_EQ; REAL_POS] THEN MATCH_MP_TAC REAL_LE_INV2 THEN REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_LE] THEN ARITH_TAC);;
let SUMMABLE_INVERSE_POWERS = 
prove (`!m. 2 <= m ==> summable (\n. inv(&(n + 1) pow m))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC SER_COMPAR THEN EXISTS_TAC `\m. inv (&(m + 1) pow 2)` THEN CONJ_TAC THENL [EXISTS_TAC `0` THEN X_GEN_TAC `n:num` THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[REAL_ABS_INV; REAL_ABS_POW; REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_INV2 THEN SIMP_TAC[REAL_POW_LT; REAL_OF_NUM_LT; ARITH_RULE `0 < n + 1`] THEN MATCH_MP_TAC REAL_POW_MONO THEN ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN ARITH_TAC; REWRITE_TAC[summable] THEN EXISTS_TAC `suminf (\m. inv (&m pow 2)) - sum(0,1) (\m. inv (&m pow 2))` THEN MATCH_MP_TAC(REWRITE_RULE[RIGHT_IMP_FORALL_THM] SER_OFFSET) THEN REWRITE_TAC[SUMMABLE_INVERSE_SQUARES]]);;
let COT_TYPE_SERIES_CONVERGES = 
prove (`!x. ~(integer x) ==> summable (\n. inv(&n pow 2 - x))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC SER_ACONV THEN MATCH_MP_TAC SER_COMPARA THEN EXISTS_TAC `\n. &2 / &n pow 2` THEN CONJ_TAC THENL [ALL_TAC; MATCH_MP_TAC SUM_SUMMABLE THEN EXISTS_TAC `&2 * suminf (\n. inv(&n pow 2))` THEN REWRITE_TAC[real_div] THEN MATCH_MP_TAC SER_CMUL THEN MATCH_MP_TAC SUMMABLE_SUM THEN REWRITE_TAC[SUMMABLE_INVERSE_SQUARES]] THEN MP_TAC(SPEC `&2 * abs x + &1` REAL_ARCH_SIMPLE) THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN EXISTS_TAC `N:num` THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[GE] THEN DISCH_TAC THEN SUBGOAL_THEN `&0 < &n pow 2` (fun th -> SIMP_TAC[th; REAL_LE_RDIV_EQ]) THENL [MATCH_MP_TAC REAL_POW_LT THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&N` THEN ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN UNDISCH_TAC `&2 * abs x + &1 <= &N` THEN REAL_ARITH_TAC; ALL_TAC] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REAL_ABS_INV] THEN REWRITE_TAC[GSYM real_div] THEN SUBGOAL_THEN `&0 < abs(&n pow 2 - x)` (fun th -> SIMP_TAC[REAL_LE_LDIV_EQ; th]) THENL [REWRITE_TAC[GSYM REAL_ABS_NZ] THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN DISCH_TAC THEN SUBST1_TAC(REAL_ARITH `x = &n pow 2 - (&n pow 2 - x)`) THEN ASM_REWRITE_TAC[REAL_SUB_RZERO] THEN SIMP_TAC[integer; REAL_INTEGER_CLOSURES]; ALL_TAC] THEN MATCH_MP_TAC(REAL_ARITH `&2 * abs(x) + &1 <= a ==> a <= &2 * abs(a - x)`) THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&N` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&N pow 2` THEN CONJ_TAC THENL [REWRITE_TAC[REAL_OF_NUM_POW; REAL_OF_NUM_LE; EXP_2; LE_SQUARE_REFL]; ASM_SIMP_TAC[REAL_POW_LE2; REAL_OF_NUM_LE; LE_0]]);;
(* ------------------------------------------------------------------------- *) (* Now the rather tricky limiting argument gives the result. *) (* ------------------------------------------------------------------------- *)
let SIN_X_RANGE = 
prove (`!x. abs(sin(x) - x) <= abs(x) pow 2 / &2`,
GEN_TAC THEN MP_TAC(SPECL [`x:real`; `2`] MCLAURIN_SIN) THEN CONV_TAC(ONCE_DEPTH_CONV REAL_SUM_CONV) THEN REWRITE_TAC[ARITH; REAL_MUL_LZERO; REAL_ADD_LID; REAL_ADD_RID] THEN CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_DIV_1; REAL_POW_1; REAL_MUL_LID] THEN REWRITE_TAC[real_div; REAL_MUL_LID] THEN REWRITE_TAC[REAL_MUL_AC]);;
let SIN_X_X_RANGE = 
prove (`!x. ~(x = &0) ==> abs(sin(x) / x - &1) <= abs(x) / &2`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_LCANCEL_IMP THEN EXISTS_TAC `abs(x)` THEN ASM_REWRITE_TAC[GSYM REAL_ABS_MUL; GSYM REAL_ABS_NZ] THEN ASM_SIMP_TAC[REAL_SUB_LDISTRIB; REAL_DIV_LMUL] THEN REWRITE_TAC[real_div; REAL_MUL_ASSOC; REAL_MUL_RID] THEN REWRITE_TAC[GSYM REAL_POW_2; SIN_X_RANGE; GSYM real_div]);;
let SIN_X_LIMIT = 
prove (`((\x. sin(x) / x) tends_real_real &1)(&0)`,
REWRITE_TAC[LIM] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN REWRITE_TAC[REAL_SUB_RZERO] THEN EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `x:real` THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `abs(x) / &2` THEN ASM_SIMP_TAC[SIN_X_X_RANGE; REAL_ABS_NZ] THEN ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN UNDISCH_TAC `abs(x) < e` THEN REAL_ARITH_TAC);;
let COT_X_LIMIT = 
prove (`((\x. x * cot(x)) tends_real_real &1)(&0)`,
SUBGOAL_THEN `(cos tends_real_real &1)(&0)` MP_TAC THENL [MP_TAC(SPEC `&0` DIFF_COS) THEN DISCH_THEN(MP_TAC o MATCH_MP DIFF_CONT) THEN REWRITE_TAC[contl; REAL_ADD_LID; COS_0] THEN CONV_TAC(ONCE_DEPTH_CONV ETA_CONV) THEN REWRITE_TAC[]; ALL_TAC] THEN DISCH_THEN(MP_TAC o C CONJ SIN_X_LIMIT) THEN DISCH_THEN(MP_TAC o C CONJ (REAL_ARITH `~(&1 = &0)`)) THEN REWRITE_TAC[GSYM CONJ_ASSOC] THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_DIV) THEN REWRITE_TAC[REAL_DIV_1; cot] THEN REWRITE_TAC[real_div; REAL_INV_MUL; REAL_MUL_AC; REAL_INV_INV]);;
let COT_LIMIT_LEMMA = 
prove (`!x. ~(x = &0) ==> (\n. (x / &2 pow n) * cot(x / &2 pow n)) tends_num_real &1`,
GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[SEQ] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN MP_TAC COT_X_LIMIT THEN REWRITE_TAC[LIM] THEN DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN REWRITE_TAC[REAL_SUB_RZERO] THEN DISCH_TAC THEN X_CHOOSE_TAC `N:num` (SPEC `abs(x) / d` REAL_ARCH_POW2) THEN EXISTS_TAC `N:num` THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[GE] THEN DISCH_TAC THEN FIRST_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[REAL_ABS_DIV; REAL_ABS_POW; REAL_ABS_NUM] THEN ASM_SIMP_TAC[REAL_POW2_CLAUSES; REAL_LT_DIV; GSYM REAL_ABS_NZ] THEN SIMP_TAC[REAL_LT_LDIV_EQ; REAL_POW2_CLAUSES] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&2 pow N` THEN ASM_REWRITE_TAC[REAL_POW2_THM]);;
let COT_LIMIT_LEMMA1 = 
prove (`~(x = &0) ==> (\n. (pi / &2 pow (n + 1)) * cot(pi * x / &2 pow (n + 1))) tends_num_real (inv(x))`,
DISCH_TAC THEN MP_TAC(SPEC `pi * x * inv(&2)` COT_LIMIT_LEMMA) THEN ASM_SIMP_TAC[REAL_ENTIRE; REAL_LT_IMP_NZ; PI_POS] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[real_div; REAL_MUL_LID; GSYM REAL_MUL_ASSOC] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `p * x * a * b * c = x * (p * (a * b)) * c`] THEN REWRITE_TAC[GSYM REAL_INV_MUL] THEN REWRITE_TAC[GSYM(CONJUNCT2 real_pow)] THEN REWRITE_TAC[ADD1; GSYM real_div] THEN DISCH_TAC THEN GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [GSYM REAL_MUL_LID] THEN FIRST_ASSUM(SUBST1_TAC o GSYM o MATCH_MP REAL_MUL_LINV) THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN MATCH_MP_TAC SEQ_MUL THEN REWRITE_TAC[SEQ_CONST] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `x * p * q * c = x * (p * q) * c`] THEN ASM_REWRITE_TAC[GSYM real_div]);;
let COT_X_BOUND_LEMMA_POS = 
prove (`?M. !x. &0 < x /\ abs(x) <= &1 ==> abs(x * cot(x)) <= M`,
MP_TAC COT_X_LIMIT THEN REWRITE_TAC[LIM] THEN DISCH_THEN(MP_TAC o SPEC `&1`) THEN REWRITE_TAC[REAL_LT_01] THEN REWRITE_TAC[REAL_SUB_RZERO] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN MP_TAC(SPECL [`\x. x * cot(x)`; `d:real`; `&1`] CONT_BOUNDED_ABS) THEN W(C SUBGOAL_THEN (fun th -> REWRITE_TAC[th]) o funpow 2 lhand o snd) THENL [X_GEN_TAC `x:real` THEN STRIP_TAC THEN MATCH_MP_TAC CONT_MUL THEN CONJ_TAC THENL [MATCH_MP_TAC DIFF_CONT THEN EXISTS_TAC `&1` THEN REWRITE_TAC[DIFF_X]; ALL_TAC] THEN GEN_REWRITE_TAC LAND_CONV [GSYM ETA_AX] THEN REWRITE_TAC[cot] THEN MATCH_MP_TAC CONT_DIV THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC DIFF_CONT THEN EXISTS_TAC `--(sin x)` THEN REWRITE_TAC[DIFF_COS]; MATCH_MP_TAC DIFF_CONT THEN EXISTS_TAC `cos x` THEN REWRITE_TAC[DIFF_SIN]; MATCH_MP_TAC REAL_LT_IMP_NZ THEN MATCH_MP_TAC SIN_POS_PI THEN SUBGOAL_THEN `&1 < pi` (fun th -> ASM_MESON_TAC[th; REAL_LET_TRANS; REAL_LTE_TRANS]) THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `&1 + e < a ==> abs(p - a) <= e ==> &1 < p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_TAC `M:real`) THEN EXISTS_TAC `abs M + &2` THEN X_GEN_TAC `x:real` THEN STRIP_TAC THEN DISJ_CASES_TAC(SPECL [`abs x`; `d:real`] REAL_LTE_TOTAL) THENL [MATCH_MP_TAC(REAL_ARITH `abs(x - &1) < &1 ==> abs(x) <= abs(m) + &2`) THEN FIRST_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[REAL_ARITH `&0 < x ==> &0 < abs(x)`]; MATCH_MP_TAC(REAL_ARITH `x <= m ==> x <= abs(m) + &2`) THEN FIRST_ASSUM MATCH_MP_TAC THEN MAP_EVERY UNDISCH_TAC [`&0 < x`; `abs(x) <= &1`; `d <= abs(x)`] THEN REAL_ARITH_TAC]);;
let COT_X_BOUND_LEMMA = 
prove (`?M. !x. ~(x = &0) /\ abs(x) <= &1 ==> abs(x * cot(x)) <= M`,
X_CHOOSE_TAC `M:real` COT_X_BOUND_LEMMA_POS THEN EXISTS_TAC `M:real` THEN X_GEN_TAC `x:real` THEN REPEAT STRIP_TAC THEN FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH `~(x = &0) ==> &0 < x \/ &0 < --x`)) THEN ASM_SIMP_TAC[] THEN SUBGOAL_THEN `x * cot(x) = --x * cot(--x)` SUBST1_TAC THENL [ALL_TAC; ASM_SIMP_TAC[REAL_ABS_NEG]] THEN REWRITE_TAC[cot; SIN_NEG; COS_NEG; real_div; REAL_INV_NEG; REAL_MUL_LNEG; REAL_MUL_RNEG; REAL_NEG_NEG]);;
let COT_PARTIAL_FRACTIONS = 
prove (`~(integer x) ==> (\n. (&2 * x pow 2) / (x pow 2 - &n pow 2)) sums ((pi * x) * cot(pi * x) + &1)`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `~(x = &0)` ASSUME_TAC THENL [UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `(~b ==> ~a) <=> (a ==> b)`] THEN SIMP_TAC[integer; REAL_ABS_NUM; REAL_OF_NUM_EQ; GSYM EXISTS_REFL]; ALL_TAC] THEN ABBREV_TAC `A = \n k. (pi * x / &2 pow n) * cot(pi * x / &2 pow n) + (pi * x / &2 pow (n + 1)) * sum(1,k) (\m. cot (pi * (x + &m) / &2 pow (n + 1)) + cot (pi * (x - &m) / &2 pow (n + 1)))` THEN ABBREV_TAC `B = \n k. (pi * x / &2 pow (n + 1)) * sum(k + 1,2 EXP n - 1 - k) (\m. cot(pi * (x + &m) / &2 pow (n + 1)) + cot(pi * (x - &m) / &2 pow (n + 1)))` THEN SUBGOAL_THEN `!n. ~(x - &n = &0)` ASSUME_TAC THENL [X_GEN_TAC `n:num` THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN DISCH_TAC THEN SUBGOAL_THEN `x = (x - &n) + &n` SUBST1_TAC THENL [REAL_ARITH_TAC; ASM_SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]; ALL_TAC] THEN SUBGOAL_THEN `!n. ~(x + &n = &0)` ASSUME_TAC THENL [X_GEN_TAC `n:num` THEN UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN DISCH_TAC THEN SUBGOAL_THEN `x = (x + &n) - &n` SUBST1_TAC THENL [REAL_ARITH_TAC; ASM_SIMP_TAC[integer; REAL_INTEGER_CLOSURES]]; ALL_TAC] THEN SUBGOAL_THEN `!n. ~(x pow 2 - &n pow 2 = &0)` ASSUME_TAC THENL [GEN_TAC THEN REWRITE_TAC[REAL_POW_2] THEN ONCE_REWRITE_TAC[REAL_ARITH `a * a - b * b = (a + b) * (a - b)`] THEN ASM_REWRITE_TAC[REAL_ENTIRE; DE_MORGAN_THM]; ALL_TAC] THEN SUBGOAL_THEN `!n. (&2 * x) / (x pow 2 - &n pow 2) = inv(x + &n) + inv(x - &n)` ASSUME_TAC THENL [X_GEN_TAC `n:num` THEN MATCH_MP_TAC REAL_EQ_LCANCEL_IMP THEN EXISTS_TAC `x pow 2 - &n pow 2` THEN ASM_SIMP_TAC[REAL_DIV_LMUL] THEN REWRITE_TAC[REAL_POW_2; REAL_ADD_LDISTRIB] THEN ONCE_REWRITE_TAC[REAL_ARITH `a * a - b * b = (a + b) * (a - b)`] THEN ONCE_REWRITE_TAC[REAL_ARITH `(p * m) * p' + (p * m) * m' = m * p * p' + p * m * m'`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_MUL_RID] THEN REAL_ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `!k. (\n. A n k) tends_num_real (&1 + sum(1,k) (\n. (&2 * x pow 2) / (x pow 2 - &n pow 2)))` ASSUME_TAC THENL [X_GEN_TAC `k:num` THEN EXPAND_TAC "A" THEN REWRITE_TAC[] THEN MATCH_MP_TAC SEQ_ADD THEN CONJ_TAC THENL [REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC COT_LIMIT_LEMMA THEN ASM_SIMP_TAC[REAL_ENTIRE; PI_POS; REAL_LT_IMP_NZ]; ALL_TAC] THEN REWRITE_TAC[GSYM SUM_CMUL] THEN MATCH_MP_TAC SEQ_SUM THEN X_GEN_TAC `r:num` THEN STRIP_TAC THEN REWRITE_TAC[REAL_POW_2; real_div] THEN ONCE_REWRITE_TAC[REAL_ARITH `(&2 * x * x) * d = x * (&2 * x) * d`] THEN REWRITE_TAC[GSYM REAL_POW_2; GSYM real_div] THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[REAL_ADD_LDISTRIB] THEN MATCH_MP_TAC SEQ_ADD THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_ARITH `(p * x * d) * cc = x * (p * d) * cc`] THEN CONJ_TAC THEN MATCH_MP_TAC SEQ_MUL THEN REWRITE_TAC[SEQ_CONST] THEN REWRITE_TAC[GSYM real_div] THEN ASM_SIMP_TAC[COT_LIMIT_LEMMA1]; ALL_TAC] THEN SUBGOAL_THEN `!k n. &6 * abs(x) < &k ==> abs(B n k) <= abs((pi * x / &2 pow (n + 1)) * cot(pi * x / &2 pow (n + 1))) * sum(k + 1,2 EXP n - 1 - k) (\m. (&72 * x pow 2) / (&m pow 2 - &36 * x pow 2))` ASSUME_TAC THENL [REPEAT STRIP_TAC THEN EXPAND_TAC "B" THEN REWRITE_TAC[GSYM SUM_CMUL] THEN W(fun (asl,w) -> MP_TAC(PART_MATCH lhand SUM_ABS_LE (lhand w))) THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN MATCH_MP_TAC SUM_LE THEN X_GEN_TAC `r:num` THEN REWRITE_TAC[ARITH_RULE `k + 1 <= r /\ r < (p - 1 - k) + k + 1 <=> k < r /\ r < p`] THEN STRIP_TAC THEN ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN MATCH_MP_TAC REAL_LE_RCANCEL_IMP THEN EXISTS_TAC `abs(inv(&2 pow (n + 1)))` THEN REWRITE_TAC[GSYM REAL_ABS_MUL] THEN REWRITE_TAC[GSYM real_div] THEN SIMP_TAC[REAL_ARITH `&0 < x ==> &0 < abs(x)`; REAL_LT_INV_EQ; REAL_POW2_CLAUSES] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs(cot (pi * x / &2 pow (n + 1)) / &2 pow n) * (&36 * x pow 2) / (&r pow 2 - &36 * x pow 2)` THEN CONJ_TAC THENL [MATCH_MP_TAC KNOPP_TERM_BOUND THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LT_TRANS THEN EXISTS_TAC `&k` THEN ASM_REWRITE_TAC[REAL_OF_NUM_LT]; ALL_TAC] THEN REWRITE_TAC[real_div; GSYM REAL_MUL_ASSOC; REAL_POW_ADD; REAL_ABS_MUL; REAL_INV_MUL] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN GEN_REWRITE_TAC RAND_CONV [AC REAL_MUL_AC `a * b * c * d * e = b * c * d * a * e`] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_MUL_AC; REAL_LE_REFL]; ALL_TAC] THEN SUBGOAL_THEN `!e. &0 < e ==> ?N. !n k:num. N <= k /\ pi * abs(x) <= &2 pow (n + 1) ==> abs(B n k) < e` ASSUME_TAC THENL [X_CHOOSE_TAC `Bd:real` COT_X_BOUND_LEMMA THEN SUBGOAL_THEN `!k n. &9 * abs x < &k ==> abs(sum(k + 1,2 EXP n - 1 - k) (\m. (&72 * x pow 2) / (&m pow 2 - &36 * x pow 2))) <= &144 * x pow 2 / &k` ASSUME_TAC THENL [REPEAT STRIP_TAC THEN REWRITE_TAC[real_div; SUM_CMUL] THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM; REAL_ABS_POW; REAL_POW2_ABS] THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN ONCE_REWRITE_TAC[REAL_ARITH `&144 * x * y = &72 * x * &2 * y`] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_LE_SQUARE; REAL_POW_2] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&2 * sum(k + 1,2 EXP n - 1 - k) (\m. inv(&m * &m))` THEN CONJ_TAC THENL [REWRITE_TAC[GSYM SUM_CMUL] THEN W(fun (asl,w) -> MP_TAC(PART_MATCH lhand SUM_ABS_LE (lhand w))) THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN MATCH_MP_TAC SUM_LE THEN X_GEN_TAC `r:num` THEN STRIP_TAC THEN REWRITE_TAC[] THEN SUBGOAL_THEN `&0 < &r * &r - &36 * x * x` ASSUME_TAC THENL [REWRITE_TAC[GSYM REAL_POW_2] THEN ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN REWRITE_TAC[REAL_POW_2] THEN REWRITE_TAC[REAL_ARITH `&0 < r * r - &36 * x * x <=> (&6 * x) * (&6 * x) < r * r`] THEN MATCH_MP_TAC REAL_LT_MUL2 THEN SIMP_TAC[REAL_LE_MUL; REAL_POS; REAL_ABS_POS] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&k` THEN ASM_REWRITE_TAC[REAL_ABS_NUM] THEN REWRITE_TAC[REAL_OF_NUM_LE] THEN ASM_SIMP_TAC[REAL_ARITH `&9 * abs(x) < a ==> &6 * abs(x) < a`] THEN UNDISCH_TAC `k + 1 <= r` THEN ARITH_TAC; ALL_TAC] THEN ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE; REAL_LE_INV_EQ] THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_MUL_LID] THEN ASM_SIMP_TAC[GSYM real_div; REAL_LE_LDIV_EQ] THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `(a * b) * c = (a * c) * b`] THEN REWRITE_TAC[GSYM real_div] THEN SUBGOAL_THEN `&0 < &r` ASSUME_TAC THENL [UNDISCH_TAC `k + 1 <= r` THEN REWRITE_TAC[REAL_OF_NUM_LT] THEN ARITH_TAC; ALL_TAC] THEN ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LT_MUL] THEN REWRITE_TAC[REAL_ARITH `&1 * x <= &2 * (x - y) <=> &2 * y <= x`] THEN MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ &81 * x <= y ==> &2 * &36 * x <= y`) THEN REWRITE_TAC[REAL_LE_SQUARE] THEN REWRITE_TAC[REAL_ARITH `&81 * x * x = (&9 * x) * (&9 * x)`] THEN REWRITE_TAC[GSYM REAL_POW_2] THEN ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN MATCH_MP_TAC REAL_POW_LE2 THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&k` THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN UNDISCH_TAC `k + 1 <= r` THEN REWRITE_TAC[REAL_OF_NUM_LE] THEN ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN REWRITE_TAC[SUM_REINDEX] THEN SUBGOAL_THEN `?d. k = 1 + d` (CHOOSE_THEN SUBST1_TAC) THENL [REWRITE_TAC[GSYM LE_EXISTS] THEN MATCH_MP_TAC(ARITH_RULE `0 < k ==> 1 <= k`) THEN REWRITE_TAC[GSYM REAL_OF_NUM_LT] THEN UNDISCH_TAC `&9 * abs(x) < &k` THEN REAL_ARITH_TAC; ALL_TAC] THEN SPEC_TAC(`2 EXP n - 1 - (1 + d)`,`n:num`) THEN POP_ASSUM_LIST(K ALL_TAC) THEN GEN_TAC THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o LAND_CONV) [ADD_SYM] THEN REWRITE_TAC[SUM_REINDEX] THEN REWRITE_TAC[ARITH_RULE `(r + 1) + 1 = r + 2`] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(d,n) (\r. inv(&(r + 1) * &(r + 2)))` THEN CONJ_TAC THENL [MATCH_MP_TAC SUM_LE THEN REPEAT STRIP_TAC THEN SIMP_TAC[REAL_LE_RMUL_EQ; REAL_LT_INV_EQ; REAL_OF_NUM_LT; REAL_INV_MUL; ARITH_RULE `0 < n + 2`] THEN MATCH_MP_TAC REAL_LE_INV2 THEN REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_LE] THEN ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `!n. sum(d,n) (\r. inv (&(r + 1) * &(r + 2))) = inv(&(d + 1)) - inv(&(d + n + 1))` (fun th -> REWRITE_TAC[th]) THENL [INDUCT_TAC THEN REWRITE_TAC[sum; ADD_CLAUSES; REAL_SUB_REFL] THEN ASM_REWRITE_TAC[REAL_ARITH `((a - x) + y = a - z) <=> (y + z = x)`] THEN REWRITE_TAC[GSYM ADD_ASSOC; REAL_INV_MUL; ARITH_RULE `SUC(d + n + 1) = d + n + 2`] THEN MATCH_MP_TAC REAL_EQ_RCANCEL_IMP THEN EXISTS_TAC `&(d + n + 1) * &(d + n + 2)` THEN REWRITE_TAC[REAL_ARITH `(dn1' * dn2' + dn2') * (dn1 * dn2) = (dn1 * dn1' + dn1) * (dn2 * dn2')`] THEN SIMP_TAC[REAL_ENTIRE; REAL_MUL_RINV; REAL_OF_NUM_EQ; ARITH_RULE `~(d + n + 1 = 0) /\ ~(d + n + 2 = 0)`] THEN SIMP_TAC[REAL_MUL_ASSOC; REAL_MUL_LINV; REAL_OF_NUM_EQ; ARITH_RULE `~(d + n + 1 = 0)`] THEN REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_ADD; REAL_OF_NUM_EQ] THEN ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[ADD_AC] THEN MATCH_MP_TAC(REAL_ARITH `&0 <= y ==> x - y <= x`) THEN REWRITE_TAC[REAL_LE_INV_EQ; REAL_POS]; ALL_TAC] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN SUBGOAL_THEN `?N. &9 * abs(x) + &1 <= &N /\ (Bd * &144 * x pow 2) / e + &1 <= &N` (X_CHOOSE_THEN `N:num` STRIP_ASSUME_TAC) THENL [X_CHOOSE_TAC `N1:num` (SPEC `&9 * abs(x) + &1` REAL_ARCH_SIMPLE) THEN X_CHOOSE_TAC `N2:num` (SPEC `(Bd * &144 * x pow 2) / e + &1` REAL_ARCH_SIMPLE) THEN EXISTS_TAC `N1 + N2:num` THEN REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN ASM_MESON_TAC[REAL_POS; REAL_ARITH `a <= m /\ b <= n /\ &0 <= m /\ &0 <= n ==> a <= m + n /\ b <= m + n`]; ALL_TAC] THEN EXISTS_TAC `N:num` THEN MAP_EVERY X_GEN_TAC [`n:num`; `k:num`] THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `abs((pi * x / &2 pow (n + 1)) * cot (pi * x / &2 pow (n + 1))) * sum(k + 1,2 EXP n - 1 - k) (\m. (&72 * x pow 2) / (&m pow 2 - &36 * x pow 2))` THEN CONJ_TAC THENL [FIRST_ASSUM MATCH_MP_TAC THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&N` THEN ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN UNDISCH_TAC `&9 * abs x + &1 <= &N` THEN REAL_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `Bd * &144 * x pow 2 / &k` THEN CONJ_TAC THENL [ALL_TAC; REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN SUBGOAL_THEN `&0 < &k` (fun th -> SIMP_TAC[REAL_LT_LDIV_EQ; th]) THENL [MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&N` THEN ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN UNDISCH_TAC `&9 * abs x + &1 <= &N` THEN REAL_ARITH_TAC; ALL_TAC] THEN GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ] THEN REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&N` THEN ASM_REWRITE_TAC[GSYM REAL_MUL_ASSOC; REAL_OF_NUM_LE] THEN ASM_SIMP_TAC[REAL_ARITH `x + &1 <= y ==> x < y`]] THEN MATCH_MP_TAC(REAL_ARITH `abs(x) <= a ==> x <= a`) THEN ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL [REWRITE_TAC[REAL_ABS_ABS] THEN FIRST_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[real_div; REAL_ENTIRE; REAL_LT_IMP_NZ; REAL_POW2_CLAUSES; REAL_MUL_ASSOC; REAL_LT_INV_EQ; PI_POS] THEN SIMP_TAC[GSYM real_div; REAL_ABS_DIV; REAL_ABS_POW; REAL_ABS_NUM] THEN SIMP_TAC[REAL_LE_LDIV_EQ; REAL_POW2_CLAUSES; REAL_MUL_LID] THEN REWRITE_TAC[REAL_ABS_MUL] THEN SIMP_TAC[real_abs; REAL_LT_IMP_LE; PI_POS] THEN ASM_REWRITE_TAC[GSYM real_abs]; ALL_TAC] THEN FIRST_ASSUM MATCH_MP_TAC THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&N:real` THEN ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN UNDISCH_TAC `&9 * abs x + &1 <= &N` THEN REAL_ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `!n k. k < 2 EXP n ==> ((pi * x) * (cot (pi * x / &2 pow n) / &2 pow n + sum (1,2 EXP n - 1) (\k. cot(pi * (x + &k) / &2 pow (n + 1)) + cot(pi * (x - &k) / &2 pow (n + 1))) / &2 pow (n + 1)) = A n k + B n k)` MP_TAC THENL [REPEAT GEN_TAC THEN DISCH_TAC THEN MAP_EVERY EXPAND_TAC ["A";
"B"] THEN REWRITE_TAC[GSYM REAL_ADD_ASSOC; GSYM REAL_ADD_LDISTRIB] THEN GEN_REWRITE_TAC (funpow 3 RAND_CONV o funpow 3 LAND_CONV) [ARITH_RULE `x = 0 + x`] THEN REWRITE_TAC[SUM_REINDEX] THEN ONCE_REWRITE_TAC [REWRITE_RULE[REAL_ARITH `(a = b - c) <=> (c + a = b)`] SUM_DIFF] THEN ASM_SIMP_TAC[ARITH_RULE `n < p ==> (n + p - 1 - n = p - 1)`] THEN GEN_REWRITE_TAC (LAND_CONV o funpow 2 RAND_CONV o funpow 3 LAND_CONV) [ARITH_RULE `x = 0 + x`] THEN REWRITE_TAC[SUM_REINDEX] THEN REWRITE_TAC[real_div; GSYM REAL_MUL_ASSOC; GSYM REAL_ADD_LDISTRIB] THEN REWRITE_TAC[REAL_MUL_AC]; ALL_TAC] THEN FIRST_ASSUM(MP_TAC o MATCH_MP COT_HALF_KNOPP) THEN DISCH_THEN(fun th -> ONCE_REWRITE_TAC[GSYM th]) THEN DISCH_TAC THEN REWRITE_TAC[sums; SEQ] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN UNDISCH_TAC `!e. &0 < e ==> ?N. !n k:num. N <= k /\ pi * abs(x) <= &2 pow (n + 1) ==> abs (B n k) < e` THEN DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN DISCH_THEN(X_CHOOSE_THEN `N1:num` STRIP_ASSUME_TAC) THEN EXISTS_TAC `N1 + 1` THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[GE] THEN DISCH_TAC THEN UNDISCH_TAC `!k. (\n. A n k) tends_num_real &1 + sum (1,k) (\n. (&2 * x pow 2) / (x pow 2 - &n pow 2))` THEN DISCH_THEN(MP_TAC o SPEC `n - 1`) THEN REWRITE_TAC[SEQ] THEN DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN REWRITE_TAC[GE] THEN DISCH_THEN(X_CHOOSE_THEN `N2:num` ASSUME_TAC) THEN SUBGOAL_THEN `?m. n - 1 < 2 EXP m /\ N2 <= m /\ pi * abs(x) <= &2 pow (m + 1)` MP_TAC THENL [SUBGOAL_THEN `?m. &(n - 1) + &1 <= &m /\ &N2 <= &m /\ pi * abs(x) <= &m` MP_TAC THENL [X_CHOOSE_TAC `m1:num` (SPEC `&(n - 1) + &1` REAL_ARCH_SIMPLE) THEN X_CHOOSE_TAC `m2:num` (SPEC `&N2` REAL_ARCH_SIMPLE) THEN X_CHOOSE_TAC `m3:num` (SPEC `pi * abs(x)` REAL_ARCH_SIMPLE) THEN EXISTS_TAC `m1 + m2 + m3:num` THEN REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN MATCH_MP_TAC(REAL_ARITH `x <= a /\ y <= b /\ z <= c /\ &0 <= a /\ &0 <= b /\ &0 <= c ==> x <= a + b + c /\ y <= a + b + c /\ z <= a + b + c`) THEN ASM_REWRITE_TAC[REAL_POS]; ALL_TAC] THEN REWRITE_TAC[GSYM REAL_OF_NUM_LT; GSYM REAL_OF_NUM_LE] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `m:num` THEN REWRITE_TAC[GSYM REAL_OF_NUM_POW] THEN MATCH_MP_TAC(REAL_ARITH `m <= m2 /\ m2 <= m22 ==> x1 + &1 <= m /\ x2 <= m /\ x3 <= m ==> x1 < m2 /\ x2 <= m /\ x3 <= m22`) THEN REWRITE_TAC[REAL_POW_ADD; REAL_POW_1] THEN REWRITE_TAC[REAL_ARITH `x <= x * &2 <=> &0 <= x`] THEN REWRITE_TAC[REAL_POW2_CLAUSES] THEN MATCH_MP_TAC REAL_LT_IMP_LE THEN REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_POW] THEN POP_ASSUM_LIST(K ALL_TAC) THEN SPEC_TAC(`m:num`,`n:num`) THEN INDUCT_TAC THEN REWRITE_TAC[EXP; ARITH] THEN MATCH_MP_TAC LTE_TRANS THEN EXISTS_TAC `SUC(2 EXP n)` THEN ASM_REWRITE_TAC[LT_SUC] THEN REWRITE_TAC[MULT_2; ADD1; LE_ADD_LCANCEL] THEN REWRITE_TAC[num_CONV `1`; LE_SUC_LT; EXP_LT_0; ARITH_EQ]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `m:num` STRIP_ASSUME_TAC) THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `e / &2 + e / &2` THEN CONJ_TAC THENL [ALL_TAC; SIMP_TAC[REAL_LE_REFL; GSYM REAL_MUL_2; REAL_DIV_LMUL; REAL_OF_NUM_EQ; ARITH_EQ]] THEN UNDISCH_TAC `!n k. k < 2 EXP n ==> ((pi * x) * cot (pi * x) = A n k + B n k)` THEN DISCH_THEN(MP_TAC o SPECL [`m:num`; `n - 1`]) THEN ASM_SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC) THEN MATCH_MP_TAC(REAL_ARITH `abs(b) < e /\ abs((s - &1) - a) < e ==> abs(s - ((a + b) + &1)) < e + e`) THEN CONJ_TAC THENL [FIRST_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN UNDISCH_TAC `N1 + 1 <= n` THEN ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `sum (0,n) (\r. (&2 * x pow 2) / (x pow 2 - &r pow 2)) - &1 = &1 + sum(1,n-1) (\r. (&2 * x pow 2) / (x pow 2 - &r pow 2))` SUBST1_TAC THENL [SUBGOAL_THEN `n = 1 + (n - 1)` (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th]) THENL [UNDISCH_TAC `N1 + 1 <= n` THEN ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[GSYM(REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_DIFF)] THEN MATCH_MP_TAC(REAL_ARITH `(a = &2) ==> ((x + a) - &1 = &1 + x)`) THEN CONV_TAC(ONCE_DEPTH_CONV REAL_SUM_CONV) THEN REWRITE_TAC[REAL_POW_2; REAL_MUL_LZERO; REAL_SUB_RZERO] THEN REWRITE_TAC[GSYM REAL_POW_2] THEN REWRITE_TAC[real_div] THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN ASM_SIMP_TAC[GSYM real_div; REAL_DIV_REFL; REAL_POW_EQ_0] THEN REWRITE_TAC[REAL_MUL_RID]; ALL_TAC] THEN ONCE_REWRITE_TAC[REAL_ABS_SUB] THEN FIRST_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[]);; (* ------------------------------------------------------------------------- *) (* Expansion of each term as a power series. *) (* ------------------------------------------------------------------------- *)
let COT_PARTIAL_FRACTIONS_SUBTERM = 
prove (`abs(x) < &n ==> (\k. --(&2) * (x pow 2 / &n pow 2) pow (k + 1)) sums ((&2 * x pow 2) / (x pow 2 - &n pow 2))`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `&0 < &n` ASSUME_TAC THENL [UNDISCH_TAC `abs(x) < &n` THEN REAL_ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `(\k. (x pow 2 / &n pow 2) pow k) sums inv(&1 - (x pow 2 / &n pow 2))` MP_TAC THENL [MATCH_MP_TAC GP THEN REWRITE_TAC[REAL_ABS_DIV; REAL_ABS_POW; REAL_ABS_NUM] THEN ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_POW_LT; REAL_MUL_LID] THEN ASM_SIMP_TAC[REAL_POW_LT2; REAL_ABS_POS; ARITH_EQ]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `--(&2) * (x pow 2 / &n pow 2)` o MATCH_MP SER_CMUL) THEN REWRITE_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN BINOP_TAC THENL [REWRITE_TAC[GSYM REAL_MUL_ASSOC; GSYM(CONJUNCT2 real_pow)] THEN REWRITE_TAC[ADD1]; ALL_TAC] THEN REWRITE_TAC[real_div; GSYM REAL_INV_MUL; GSYM REAL_MUL_ASSOC; REAL_MUL_LNEG] THEN REWRITE_TAC[GSYM REAL_MUL_RNEG; GSYM REAL_INV_NEG] THEN AP_TERM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[REAL_NEG_SUB; REAL_SUB_LDISTRIB; REAL_MUL_RID] THEN ASM_SIMP_TAC[GSYM real_div; REAL_DIV_LMUL; REAL_POW_LT; REAL_LT_IMP_NZ]);;
(* ------------------------------------------------------------------------- *) (* General theorem about swapping a double series of positive terms. *) (* ------------------------------------------------------------------------- *)
let SEQ_LE_CONST = 
prove (`!a x l N. (!n. n >= N ==> x(n) <= a) /\ x tends_num_real l ==> l <= a`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC SEQ_LE THEN MAP_EVERY EXISTS_TAC [`x:num->real`; `\n:num. a:real`] THEN ASM_REWRITE_TAC[SEQ_CONST] THEN ASM_MESON_TAC[]);;
let SEQ_GE_CONST = 
prove (`!a x l N. (!n. n >= N ==> a <= x(n)) /\ x tends_num_real l ==> a <= l`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC SEQ_LE THEN MAP_EVERY EXISTS_TAC [`\n:num. a:real`; `x:num->real`] THEN ASM_REWRITE_TAC[SEQ_CONST] THEN ASM_MESON_TAC[]);;
let SUM_SWAP_0 = 
prove (`!m n. sum(0,m) (\i. sum(0,n) (\j. a i j)) = sum(0,n) (\j. sum(0,m) (\i. a i j))`,
INDUCT_TAC THEN ASM_SIMP_TAC[sum; SUM_CONST; REAL_MUL_RZERO; SUM_ADD]);;
let SUM_SWAP = 
prove (`!m1 m2 n1 n2. sum(m1,m2) (\i. sum(n1,n2) (\j. a i j)) = sum(n1,n2) (\j. sum(m1,m2) (\i. a i j))`,
REPEAT GEN_TAC THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o LAND_CONV) [ARITH_RULE `m = 0 + m`] THEN GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o LAND_CONV) [ARITH_RULE `m = 0 + m`] THEN REPEAT GEN_TAC THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o BINDER_CONV o LAND_CONV o LAND_CONV) [ARITH_RULE `m = 0 + m`] THEN GEN_REWRITE_TAC (RAND_CONV o RAND_CONV o BINDER_CONV o LAND_CONV o LAND_CONV) [ARITH_RULE `m = 0 + m`] THEN REWRITE_TAC[SUM_REINDEX; SUM_SWAP_0]);;
let SER_SWAPDOUBLE_POS = 
prove (`!z a l. (!m n. &0 <= a m n) /\ (!m. (a m) sums (z m)) /\ z sums l ==> ?s. (!n. (\m. a m n) sums (s n)) /\ s sums l`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `!m:num n. sum(0,n) (a m) <= z m` ASSUME_TAC THENL [REPEAT GEN_TAC THEN MATCH_MP_TAC SEQ_GE_CONST THEN EXISTS_TAC `\n. sum(0,n) (a(m:num))` THEN ASM_REWRITE_TAC[GSYM sums] THEN EXISTS_TAC `n:num` THEN X_GEN_TAC `p:num` THEN SIMP_TAC[GE; LEFT_IMP_EXISTS_THM; LE_EXISTS] THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LE] THEN ASM_SIMP_TAC[GSYM SUM_DIFF; SUM_POS]; ALL_TAC] THEN SUBGOAL_THEN `!m:num. &0 <= z m` ASSUME_TAC THENL [GEN_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,n) (a(m:num))` THEN ASM_SIMP_TAC[SUM_POS]; ALL_TAC] THEN SUBGOAL_THEN `!n. sum(0,n) z <= l` ASSUME_TAC THENL [GEN_TAC THEN MATCH_MP_TAC SEQ_GE_CONST THEN EXISTS_TAC `\n. sum(0,n) z` THEN ASM_REWRITE_TAC[GSYM sums] THEN EXISTS_TAC `n:num` THEN X_GEN_TAC `p:num` THEN SIMP_TAC[GE; LEFT_IMP_EXISTS_THM; LE_EXISTS] THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LE] THEN ASM_SIMP_TAC[GSYM SUM_DIFF; SUM_POS]; ALL_TAC] THEN SUBGOAL_THEN `&0 <= l` ASSUME_TAC THENL [MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,n) z` THEN ASM_SIMP_TAC[SUM_POS]; ALL_TAC] THEN SUBGOAL_THEN `!e. &0 < e ==> ?M N. !m n. M <= m /\ N <= n ==> l - e <= sum(0,m) (\i. sum(0,n) (\j. a i j)) /\ sum(0,m) (\i. sum(0,n) (\j. a i j)) <= l` ASSUME_TAC THENL [X_GEN_TAC `e:real` THEN DISCH_TAC THEN UNDISCH_TAC `z sums l` THEN REWRITE_TAC[sums; SEQ] THEN DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_SIMP_TAC[REAL_LT_DIV; GE; REAL_OF_NUM_LT; ARITH] THEN DISCH_THEN(X_CHOOSE_TAC `M:num`) THEN SUBGOAL_THEN `?N. !m n. m < M /\ n >= N ==> abs(sum (0,n) (a m) - z m) < e / (&2 * &(M + 1))` MP_TAC THENL [SUBGOAL_THEN `&0 < e / (&2 * &(M + 1))` MP_TAC THENL [ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; REAL_LT_MUL; ARITH; ARITH_RULE `0 < n + 1`]; ALL_TAC] THEN SPEC_TAC(`e / (&2 * &(M + 1))`,`d:real`) THEN SPEC_TAC(`M:num`,`n:num`) THEN GEN_REWRITE_TAC I [SWAP_FORALL_THM] THEN REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN GEN_TAC THEN DISCH_TAC THEN INDUCT_TAC THEN REWRITE_TAC[CONJUNCT1 LT] THEN UNDISCH_TAC `!m:num. (a m) sums (z m)` THEN DISCH_THEN(MP_TAC o SPEC `n:num`) THEN REWRITE_TAC[sums; SEQ] THEN DISCH_THEN(MP_TAC o SPEC `d:real`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `N0:num`) THEN FIRST_X_ASSUM(X_CHOOSE_TAC `N1:num`) THEN EXISTS_TAC `N0 + N1:num` THEN X_GEN_TAC `m:num` THEN X_GEN_TAC `p:num` THEN REWRITE_TAC[LT] THEN ASM_MESON_TAC[ARITH_RULE `a >= m + n ==> a >= m /\ a >= n:num`]; ALL_TAC] THEN REWRITE_TAC[GE] THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN MAP_EVERY EXISTS_TAC [`M:num`; `N:num`] THEN MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN MATCH_MP_TAC(REAL_ARITH `!s0. s0 <= s /\ s <= l /\ abs(s0 - l) < e ==> l - e <= s /\ s <= l`) THEN EXISTS_TAC `sum(0,M) (\i. sum (0,n) (\j. a i j))` THEN CONJ_TAC THENL [UNDISCH_TAC `M <= m:num` THEN SIMP_TAC[LE_EXISTS; LEFT_IMP_EXISTS_THM] THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LE] THEN REWRITE_TAC[GSYM SUM_DIFF] THEN ASM_SIMP_TAC[SUM_POS]; ALL_TAC] THEN CONJ_TAC THENL [MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum (0,m) z` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUM_LE THEN CONV_TAC(ONCE_DEPTH_CONV ETA_CONV) THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `e / &2 + e / &2` THEN CONJ_TAC THENL [ALL_TAC; SIMP_TAC[REAL_LE_REFL; GSYM REAL_MUL_2; REAL_DIV_LMUL; REAL_OF_NUM_EQ; ARITH_EQ]] THEN MATCH_MP_TAC(REAL_ARITH `!z. abs(x - z) <= e /\ abs(z - y) < e ==> abs(x - y) < e + e`) THEN EXISTS_TAC `sum(0,M) z` THEN ASM_SIMP_TAC[LE_REFL] THEN REWRITE_TAC[GSYM SUM_SUB] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&M * e / (&2 * &(M + 1))` THEN CONJ_TAC THENL [ALL_TAC; REWRITE_TAC[real_div; REAL_INV_MUL] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c * d = (b * c) * a * d`] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN MATCH_MP_TAC REAL_LE_LMUL THEN ASM_SIMP_TAC[REAL_LE_MUL; REAL_LT_IMP_LE; REAL_LE_INV_EQ; REAL_POS] THEN SIMP_TAC[GSYM real_div; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; ARITH_RULE `0 < n + 1`] THEN REWRITE_TAC[REAL_MUL_LID; REAL_OF_NUM_LE; LE_ADD]] THEN W(fun (asl,w) -> MP_TAC(PART_MATCH lhand SUM_ABS_LE (lhand w))) THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,M) (\n. e / (&2 * &(M + 1)))` THEN CONJ_TAC THENL [MATCH_MP_TAC SUM_LE THEN CONV_TAC(ONCE_DEPTH_CONV ETA_CONV) THEN ASM_SIMP_TAC[ADD_CLAUSES; REAL_LT_IMP_LE]; REWRITE_TAC[SUM_CONST; REAL_LE_REFL]]; ALL_TAC] THEN SUBGOAL_THEN `!m n. sum(0,m) (\i. (a:num->num->real) i n) <= l` ASSUME_TAC THENL [REPEAT GEN_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `&1`) THEN REWRITE_TAC[REAL_LT_01] THEN DISCH_THEN(X_CHOOSE_THEN `M:num` MP_TAC) THEN DISCH_THEN(X_CHOOSE_THEN `N:num` ASSUME_TAC) THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,M+m) (\i. sum(0,N+n+1) (\j. a i j))` THEN ASM_SIMP_TAC[LE_ADD] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN ONCE_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_DIFF)] THEN MATCH_MP_TAC(REAL_ARITH `x <= y /\ &0 <= z ==> x <= z + y`) THEN ASM_SIMP_TAC[SUM_POS] THEN MATCH_MP_TAC SUM_LE THEN X_GEN_TAC `r:num` THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN REWRITE_TAC[GSYM ADD_ASSOC] THEN ONCE_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_DIFF)] THEN MATCH_MP_TAC(REAL_ARITH `x <= y /\ &0 <= z ==> x <= y + z`) THEN ASM_SIMP_TAC[SUM_POS] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(n,1) (\j. a (r:num) j)` THEN CONJ_TAC THENL [REWRITE_TAC[SUM_1; REAL_LE_REFL]; ALL_TAC] THEN SUBST1_TAC(ARITH_RULE `n = 0 + n`) THEN REWRITE_TAC[SUM_REINDEX] THEN ONCE_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_DIFF)] THEN ASM_SIMP_TAC[SUM_POS; REAL_LE_ADDL]; ALL_TAC] THEN SUBGOAL_THEN `!n:num. ?s. (\m. a m n) sums s` MP_TAC THENL [GEN_TAC THEN REWRITE_TAC[sums; GSYM convergent] THEN MATCH_MP_TAC SEQ_BCONV THEN CONJ_TAC THENL [MATCH_MP_TAC SEQ_BOUNDED_2 THEN MAP_EVERY EXISTS_TAC [`&0`; `l:real`] THEN ASM_SIMP_TAC[SUM_POS]; REWRITE_TAC[mono] THEN DISJ1_TAC THEN SIMP_TAC[LE_EXISTS; LEFT_IMP_EXISTS_THM] THEN REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_DIFF)] THEN ASM_SIMP_TAC[SUM_POS; REAL_LE_ADDL]]; ALL_TAC] THEN REWRITE_TAC[SKOLEM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `s:num->real` THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN SUBGOAL_THEN `!e. &0 < e ==> ?N. !n. N <= n ==> l - e <= sum (0,n) s /\ sum(0,n) s <= l` ASSUME_TAC THENL [X_GEN_TAC `e:real` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `M:num` MP_TAC) THEN DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC) THEN ONCE_REWRITE_TAC[SUM_SWAP_0] THEN DISCH_TAC THEN EXISTS_TAC `N:num` THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN CONJ_TAC THENL [MATCH_MP_TAC(REAL_ARITH `!s0. l - e <= s0 /\ s0 <= s ==> l - e <= s`) THEN EXISTS_TAC `sum (0,n) (\j. sum (0,M) (\i. a i j))` THEN ASM_SIMP_TAC[LE_REFL] THEN MATCH_MP_TAC SUM_LE THEN X_GEN_TAC `r:num` THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN MATCH_MP_TAC SEQ_GE_CONST THEN EXISTS_TAC `\m. sum(0,m) (\m. a m (r:num))` THEN EXISTS_TAC `M:num` THEN ASM_REWRITE_TAC[GSYM sums] THEN SIMP_TAC[GE; LEFT_IMP_EXISTS_THM; LE_EXISTS] THEN ONCE_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_DIFF)] THEN ASM_SIMP_TAC[SUM_POS; REAL_LE_ADDL]; ALL_TAC] THEN MATCH_MP_TAC SEQ_LE_CONST THEN EXISTS_TAC `\m. sum (0,n) (\j. sum (0,m) (\i. a i j))` THEN REWRITE_TAC[] THEN EXISTS_TAC `0` THEN CONJ_TAC THENL [X_GEN_TAC `m:num` THEN DISCH_THEN(K ALL_TAC) THEN ONCE_REWRITE_TAC[SUM_SWAP_0] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,m) z` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUM_LE THEN ASM_REWRITE_TAC[] THEN CONV_TAC(ONCE_DEPTH_CONV ETA_CONV) THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN MATCH_MP_TAC SEQ_SUM THEN X_GEN_TAC `m:num` THEN ASM_REWRITE_TAC[GSYM sums]; ALL_TAC] THEN REWRITE_TAC[sums; SEQ] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN UNDISCH_TAC `!e. &0 < e ==> (?N. !n. N <= n ==> l - e <= sum (0,n) s /\ sum (0,n) s <= l)` THEN DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN REWRITE_TAC[GE] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC(TAUT `(a ==> b ==> c) ==> (a ==> b) ==> (a ==> c)`) THEN DISCH_TAC THEN MATCH_MP_TAC(REAL_ARITH `d < e ==> l - d <= x /\ x <= l ==> abs(x - l) < e`) THEN SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN UNDISCH_TAC `&0 < e` THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Hence we get a power series for cot with nice convergence property. *) (* ------------------------------------------------------------------------- *)
let COT_PARTIAL_FRACTIONS_FROM1 = 
prove (`~integer x ==> (\n. (&2 * x pow 2) / (x pow 2 - &(n + 1) pow 2)) sums (pi * x) * cot (pi * x) - &1`,
DISCH_TAC THEN SUBGOAL_THEN `~(x = &0)` ASSUME_TAC THENL [UNDISCH_TAC `~(integer x)` THEN REWRITE_TAC[TAUT `(~b ==> ~a) <=> (a ==> b)`] THEN SIMP_TAC[integer; REAL_ABS_NUM; REAL_OF_NUM_EQ; GSYM EXISTS_REFL]; ALL_TAC] THEN FIRST_ASSUM(MP_TAC o MATCH_MP COT_PARTIAL_FRACTIONS) THEN DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN DISCH_THEN(MP_TAC o MATCH_MP SUM_SUMMABLE) THEN DISCH_THEN(MP_TAC o SPEC `1` o MATCH_MP SER_OFFSET) THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP SUM_UNIQ) THEN MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[] THEN AP_TERM_TAC THEN REWRITE_TAC[SUM_1] THEN REWRITE_TAC[REAL_POW_2; REAL_MUL_LZERO; REAL_SUB_RZERO] THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `(a * b * b) * c = a * (b * b) * c`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_ENTIRE; REAL_MUL_RID] THEN REAL_ARITH_TAC);;
let COT_ALT_POWSER = 
prove (`!x. &0 < abs(x) /\ abs(x) < &1 ==> ?s. (!n. (\m. &2 * (x pow 2 / &(m + 1) pow 2) pow (n + 1)) sums s n) /\ s sums --((pi * x) * cot(pi * x) - &1)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC SER_SWAPDOUBLE_POS THEN EXISTS_TAC `\n. (--(&2) * x pow 2) / (x pow 2 - &(n + 1) pow 2)` THEN REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL [SIMP_TAC[REAL_POS; REAL_POW_LE; REAL_LE_MUL; REAL_POW_2; REAL_LE_DIV; REAL_LE_SQUARE]; X_GEN_TAC `m:num` THEN GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV o LAND_CONV) [GSYM REAL_NEG_NEG] THEN REWRITE_TAC[real_div; REAL_MUL_LNEG] THEN MATCH_MP_TAC SER_NEG THEN REWRITE_TAC[GSYM REAL_MUL_LNEG] THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC COT_PARTIAL_FRACTIONS_SUBTERM THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&1` THEN ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN ARITH_TAC; REWRITE_TAC[real_div; REAL_MUL_LNEG] THEN MATCH_MP_TAC SER_NEG THEN REWRITE_TAC[GSYM REAL_MUL_LNEG] THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC COT_PARTIAL_FRACTIONS_FROM1 THEN UNDISCH_TAC `&0 < abs x` THEN UNDISCH_TAC `abs x < &1` THEN ONCE_REWRITE_TAC[TAUT `a ==> b ==> ~c <=> c ==> ~(a /\ b)`] THEN SIMP_TAC[integer; LEFT_IMP_EXISTS_THM] THEN GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[REAL_OF_NUM_LT] THEN ARITH_TAC]);;
(* ------------------------------------------------------------------------- *) (* General unpairing result. *) (* ------------------------------------------------------------------------- *)
let SER_INSERTZEROS = 
prove (`(\n. c(2 * n)) sums l ==> (\n. if ODD n then &0 else c(n)) sums l`,
REWRITE_TAC[sums; SEQ; GE] THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `N:num` STRIP_ASSUME_TAC) THEN EXISTS_TAC `2 * N` THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN DISJ_CASES_THEN MP_TAC (SPEC `n:num` EVEN_OR_ODD) THENL [REWRITE_TAC[EVEN_EXISTS; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `m:num` THEN DISCH_THEN SUBST_ALL_TAC THEN REWRITE_TAC[ONCE_REWRITE_RULE[MULT_SYM] (GSYM SUM_GROUP)] THEN REWRITE_TAC[SUM_2; ODD_ADD; ODD_MULT; ARITH_ODD; REAL_ADD_RID] THEN FIRST_ASSUM MATCH_MP_TAC THEN UNDISCH_TAC `2 * N <= 2 * m` THEN ARITH_TAC; REWRITE_TAC[ODD_EXISTS; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `m:num` THEN DISCH_THEN SUBST_ALL_TAC THEN REWRITE_TAC[GSYM ODD_EXISTS] THEN REWRITE_TAC[sum] THEN REWRITE_TAC[ONCE_REWRITE_RULE[MULT_SYM] (GSYM SUM_GROUP)] THEN REWRITE_TAC[SUM_2; ODD_ADD; ODD_MULT; ARITH_ODD; REAL_ADD_RID] THEN ONCE_REWRITE_TAC[ARITH_RULE `0 + 2 * m = 2 * (0 + m)`] THEN REWRITE_TAC[GSYM(CONJUNCT2 sum)] THEN FIRST_ASSUM MATCH_MP_TAC THEN UNDISCH_TAC `2 * N <= SUC(2 * m)` THEN ARITH_TAC]);;
(* ------------------------------------------------------------------------- *) (* Mangle this into a standard power series. *) (* ------------------------------------------------------------------------- *)
let COT_POWSER_SQUARED_FORM = 
prove (`!x. &0 < abs(x) /\ abs(x) < pi ==> (\n. &2 * (x / pi) pow (2 * (n + 1)) * suminf (\m. inv (&(m + 1) pow (2 * (n + 1))))) sums --(x * cot x - &1)`,
REPEAT STRIP_TAC THEN MP_TAC(SPEC `x / pi` COT_ALT_POWSER) THEN REWRITE_TAC[REAL_ABS_DIV] THEN SIMP_TAC[real_abs; REAL_LT_IMP_LE; PI_POS] THEN REWRITE_TAC[GSYM real_abs] THEN SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_LDIV_EQ; PI_POS] THEN ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID] THEN SIMP_TAC[REAL_DIV_LMUL; REAL_LT_IMP_NZ; PI_POS] THEN DISCH_THEN(X_CHOOSE_THEN `s:num->real` STRIP_ASSUME_TAC) THEN UNDISCH_TAC `s sums --(x * cot(x) - &1)` THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:num` THEN FIRST_ASSUM(MP_TAC o MATCH_MP SER_CMUL o SPEC `n:num`) THEN DISCH_THEN(MP_TAC o SPEC `inv(&2 * (x / pi) pow (2 * (n + 1)))`) THEN REWRITE_TAC[] THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o ABS_CONV o RAND_CONV o ONCE_DEPTH_CONV) [REAL_POW_DIV] THEN REWRITE_TAC[REAL_POW_POW] THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o ABS_CONV o RAND_CONV o ONCE_DEPTH_CONV) [real_div] THEN ONCE_REWRITE_TAC[REAL_ARITH `a * &2 * b * c = c * ((&2 * b) * a)`] THEN SUBGOAL_THEN `~(&2 * (x / pi) pow (2 * (n + 1)) = &0)` ASSUME_TAC THENL [REWRITE_TAC[REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH_EQ; REAL_POW_EQ_0] THEN REWRITE_TAC[DE_MORGAN_THM] THEN DISJ1_TAC THEN REWRITE_TAC[real_div; REAL_ENTIRE; REAL_INV_EQ_0] THEN ASM_SIMP_TAC[PI_POS; REAL_LT_IMP_NZ; snd(EQ_IMP_RULE(SPEC_ALL REAL_ABS_NZ))]; ALL_TAC] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_MUL_RID] THEN DISCH_THEN(MP_TAC o MATCH_MP SUM_UNIQ) THEN DISCH_THEN(MP_TAC o AP_TERM `( * ) (&2 * (x / pi) pow (2 * (n + 1)))`) THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [AC REAL_MUL_AC `a * b * c = (a * b) * c`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_MUL_LID] THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC]);;
let COT_POWSER_SQUAREDAGAIN = 
prove (`!x. &0 < abs(x) /\ abs(x) < pi ==> (\n. (if n = 0 then &1 else --(&2) * suminf (\m. inv (&(m + 1) pow (2 * n))) / pi pow (2 * n)) * x pow (2 * n)) sums (x * cot(x))`,
GEN_TAC THEN DISCH_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP COT_POWSER_SQUARED_FORM) THEN DISCH_THEN(MP_TAC o MATCH_MP SER_NEG) THEN REWRITE_TAC[REAL_NEG_NEG] THEN DISCH_TAC THEN SUBGOAL_THEN `(\n. if n = 0 then &1 else --(&2 * (x / pi) pow (2 * n) * suminf (\m. inv (&(m + 1) pow (2 * n))))) sums (sum(0,1) (\n. if n = 0 then &1 else --(&2 * (x / pi) pow (2 * n) * suminf (\m. inv (&(m + 1) pow (2 * n))))) + suminf (\n. if n + 1 = 0 then &1 else --(&2 * (x / pi) pow (2 * (n + 1)) * suminf (\m. inv (&(m + 1) pow (2 * (n + 1)))))))` MP_TAC THENL [MATCH_MP_TAC SER_OFFSET_REV THEN REWRITE_TAC[ARITH_RULE `~(n + 1 = 0)`] THEN REWRITE_TAC[summable] THEN EXISTS_TAC `x * cot(x) - &1` THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN REWRITE_TAC[SUM_1; ARITH_RULE `~(n + 1 = 0)`] THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP SUM_UNIQ) THEN REWRITE_TAC[REAL_ARITH `&1 + x - &1 = x`] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[MULT_CLAUSES; real_pow; REAL_MUL_LID] THEN REWRITE_TAC[REAL_POW_DIV; REAL_MUL_LNEG] THEN AP_TERM_TAC THEN REWRITE_TAC[real_div; REAL_INV_MUL; REAL_INV_INV] THEN REWRITE_TAC[REAL_MUL_AC]);;
let COT_X_POWSER = 
prove (`!x. &0 < abs(x) /\ abs(x) < pi ==> (\n. (if n = 0 then &1 else if ODD n then &0 else --(&2) * suminf (\m. inv (&(m + 1) pow n)) / pi pow n) * x pow n) sums (x * cot(x))`,
GEN_TAC THEN DISCH_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP COT_POWSER_SQUAREDAGAIN) THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [ARITH_RULE `(n = 0) <=> (2 * n = 0)`] THEN DISCH_THEN(MP_TAC o MATCH_MP SER_INSERTZEROS) THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[] THEN ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[ARITH] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_MUL_LZERO]);;
(* ------------------------------------------------------------------------- *) (* Hence use the double-angle formula to get a series for tangent. *) (* ------------------------------------------------------------------------- *)
let TAN_COT_DOUBLE = 
prove (`!x. &0 < abs(x) /\ abs(x) < pi / &2 ==> (tan(x) = cot(x) - &2 * cot(&2 * x))`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `~(sin x = &0)` ASSUME_TAC THENL [REWRITE_TAC[SIN_ZERO] THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN CONV_TAC CONTRAPOS_CONV THEN REWRITE_TAC[DE_MORGAN_THM] THEN REWRITE_TAC[OR_EXISTS_THM] THEN REWRITE_TAC[TAUT `a /\ b \/ a /\ c <=> a /\ (b \/ c)`] THEN DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH `(x = a) \/ (x = --a) ==> &0 <= a ==> (abs(x) = a)`)) THEN SIMP_TAC[REAL_LE_MUL; REAL_LE_DIV; REAL_LT_IMP_LE; PI_POS; REAL_POS] THEN DISCH_THEN(K ALL_TAC) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST1_TAC) THEN ASM_CASES_TAC `m = 0` THEN ASM_REWRITE_TAC[MULT_CLAUSES; REAL_MUL_LZERO; REAL_LT_REFL] THEN DISJ1_TAC THEN GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [REAL_ARITH `x = &1 * x`] THEN SIMP_TAC[REAL_LT_RMUL_EQ; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; PI_POS] THEN UNDISCH_TAC `~(m = 0)` THEN ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `~(cos x = &0)` ASSUME_TAC THENL [REWRITE_TAC[COS_ZERO] THEN MAP_EVERY UNDISCH_TAC [`abs x < pi / &2`; `&0 < abs x`] THEN REWRITE_TAC[IMP_IMP] THEN CONV_TAC CONTRAPOS_CONV THEN REWRITE_TAC[DE_MORGAN_THM] THEN REWRITE_TAC[OR_EXISTS_THM; NOT_EVEN] THEN REWRITE_TAC[TAUT `a /\ b \/ a /\ c <=> a /\ (b \/ c)`] THEN DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH `(x = a) \/ (x = --a) ==> &0 <= a ==> (abs(x) = a)`)) THEN SIMP_TAC[REAL_LE_MUL; REAL_LE_DIV; REAL_LT_IMP_LE; PI_POS; REAL_POS] THEN DISCH_THEN(K ALL_TAC) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST1_TAC) THEN DISJ2_TAC THEN GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [REAL_ARITH `x = &1 * x`] THEN SIMP_TAC[REAL_LT_RMUL_EQ; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; PI_POS] THEN ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `~(sin(&2 * x) = &0)` ASSUME_TAC THENL [REWRITE_TAC[SIN_ZERO] THEN MAP_EVERY UNDISCH_TAC [`abs x < pi / &2`; `&0 < abs x`] THEN REWRITE_TAC[IMP_IMP] THEN CONV_TAC CONTRAPOS_CONV THEN REWRITE_TAC[DE_MORGAN_THM] THEN REWRITE_TAC[OR_EXISTS_THM] THEN REWRITE_TAC[TAUT `a /\ b \/ a /\ c <=> a /\ (b \/ c)`] THEN DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH `(x = a) \/ (x = --a) ==> &0 <= a ==> (abs(x) = a)`)) THEN SIMP_TAC[REAL_LE_MUL; REAL_LE_DIV; REAL_LT_IMP_LE; PI_POS; REAL_POS] THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM] THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [REAL_MUL_SYM] THEN SIMP_TAC[GSYM REAL_EQ_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN DISCH_THEN(K ALL_TAC) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST1_TAC) THEN ASM_CASES_TAC `m = 0` THEN ASM_REWRITE_TAC[MULT_CLAUSES; REAL_MUL_LZERO; REAL_LT_REFL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN DISJ2_TAC THEN REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `(a * b) * c = b * a * c`] THEN SIMP_TAC[REAL_LT_DIV2_EQ; REAL_DIV_LMUL; REAL_OF_NUM_EQ; ARITH; REAL_OF_NUM_LT] THEN GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [REAL_ARITH `x = &1 * x`] THEN SIMP_TAC[REAL_LT_RMUL_EQ; PI_POS; REAL_OF_NUM_LT] THEN UNDISCH_TAC `~(m = 0)` THEN ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[tan; cot] THEN MATCH_MP_TAC REAL_EQ_RCANCEL_IMP THEN EXISTS_TAC `sin(&2 * x)` THEN ASM_REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_ARITH `(d * e - &2 * f * g) * h = h * d * e - &2 * f * (h * g)`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_MUL_RID] THEN MATCH_MP_TAC REAL_EQ_RCANCEL_IMP THEN EXISTS_TAC `sin(x)` THEN ASM_SIMP_TAC[REAL_SUB_RDISTRIB; GSYM REAL_MUL_ASSOC; REAL_MUL_LINV; REAL_MUL_RID] THEN GEN_REWRITE_TAC LAND_CONV [AC REAL_MUL_AC `a * b * c * d = a * c * d * b`] THEN MATCH_MP_TAC REAL_EQ_RCANCEL_IMP THEN EXISTS_TAC `cos(x)` THEN ASM_SIMP_TAC[GSYM REAL_MUL_ASSOC; REAL_MUL_LINV; REAL_MUL_RID] THEN REWRITE_TAC[SIN_DOUBLE; COS_DOUBLE; REAL_POW_2] THEN REWRITE_TAC[REAL_ARITH `((&2 * s * c) * c - &2 * (c * c - s * s) * s) * c = &2 * c * s * s * s`] THEN REWRITE_TAC[REAL_MUL_AC]);;
let TAN_POWSER_WEAK = 
prove (`!x. &0 < abs(x) /\ abs(x) < pi / &2 ==> (\n. (if EVEN n then &0 else &2 * (&2 pow (n + 1) - &1) * suminf (\m. inv (&(m + 1) pow (n + 1))) / pi pow (n + 1)) * x pow n) sums (tan x)`,
REPEAT STRIP_TAC THEN MP_TAC(SPEC `x:real` COT_X_POWSER) THEN W(C SUBGOAL_THEN (fun th -> REWRITE_TAC[th]) o funpow 2 lhand o snd) THENL [ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LT_TRANS THEN EXISTS_TAC `pi / &2` THEN ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN MP_TAC PI_POS THEN REAL_ARITH_TAC; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `inv(x)` o MATCH_MP SER_CMUL) THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [REAL_MUL_ASSOC] THEN ASM_SIMP_TAC[REAL_MUL_LINV; REAL_ABS_NZ; REAL_MUL_LID] THEN MP_TAC(SPEC `&2 * x` COT_X_POWSER) THEN W(C SUBGOAL_THEN (fun th -> REWRITE_TAC[th]) o funpow 2 lhand o snd) THENL [ASM_SIMP_TAC[REAL_ABS_MUL; REAL_ABS_NUM; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `inv(x)` o MATCH_MP SER_CMUL) THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [AC REAL_MUL_AC `a * (b * c) * d = (a * c) * b * d`] THEN ASM_SIMP_TAC[REAL_MUL_LINV; REAL_ABS_NZ; REAL_MUL_LID] THEN ONCE_REWRITE_TAC[TAUT `a ==> b ==> c <=> b /\ a ==> c`] THEN DISCH_THEN(MP_TAC o MATCH_MP SER_SUB) THEN ASM_SIMP_TAC[GSYM TAN_COT_DOUBLE] THEN DISCH_THEN(fun th -> MP_TAC th THEN MP_TAC th) THEN DISCH_THEN(ASSUME_TAC o SYM o MATCH_MP SUM_UNIQ) THEN DISCH_THEN(MP_TAC o MATCH_MP SUM_SUMMABLE) THEN DISCH_THEN(MP_TAC o SPEC `1` o MATCH_MP SER_OFFSET) THEN ASM_REWRITE_TAC[SUM_1] THEN REWRITE_TAC[real_pow; REAL_MUL_RID; REAL_SUB_REFL; REAL_SUB_RZERO] THEN REWRITE_TAC[ODD_ADD; ARITH_ODD; ADD_EQ_0; ARITH_EQ] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[NOT_ODD] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_SUB_REFL] THEN REWRITE_TAC[REAL_POW_ADD; REAL_POW_1; REAL_POW_MUL; GSYM REAL_MUL_ASSOC] THEN ONCE_REWRITE_TAC[REAL_ARITH `x' * m2 * s * xp * x - x' * m2 * s * pn * t * xp * x = (x' * x) * --m2 * (t * pn - &1) * s * xp`] THEN ASM_SIMP_TAC[REAL_NEG_NEG; REAL_MUL_LINV; REAL_ABS_NZ; REAL_MUL_LID] THEN REWRITE_TAC[REAL_MUL_AC]);;
let TAN_POWSER = 
prove (`!x. abs(x) < pi / &2 ==> (\n. (if EVEN n then &0 else &2 * (&2 pow (n + 1) - &1) * suminf (\m. inv (&(m + 1) pow (n + 1))) / pi pow (n + 1)) * x pow n) sums (tan x)`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 < abs(x)` THEN ASM_SIMP_TAC[TAN_POWSER_WEAK] THEN DISCH_THEN(K ALL_TAC) THEN POP_ASSUM MP_TAC THEN REWRITE_TAC[GSYM REAL_ABS_NZ] THEN DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[TAN_0] THEN W(fun (asl,w) -> MP_TAC(SPECL [lhand w; `0`] SER_0)) THEN REWRITE_TAC[sum] THEN DISCH_THEN MATCH_MP_TAC THEN X_GEN_TAC `n:num` THEN DISCH_THEN(K ALL_TAC) THEN ASM_CASES_TAC `EVEN n` THEN ASM_REWRITE_TAC[REAL_MUL_LZERO] THEN UNDISCH_TAC `~(EVEN n)` THEN REWRITE_TAC[NOT_EVEN; ODD_EXISTS; real_pow; LEFT_IMP_EXISTS_THM] THEN SIMP_TAC[real_pow; REAL_MUL_LZERO; REAL_MUL_RZERO]);;
(* ------------------------------------------------------------------------- *) (* Add polynomials to differentiator's known functions, for next proofs. *) (* ------------------------------------------------------------------------- *)
let th = 
prove (`(f diffl l)(x) ==> ((\x. poly p (f x)) diffl (l * poly (poly_diff p) (f x)))(x)`,
REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN MP_TAC(SPECL [`\x. poly p x`; `f:real->real`; `poly (poly_diff p) (f(x:real))`; `l:real`; `x:real`] DIFF_CHAIN) THEN ASM_REWRITE_TAC[POLY_DIFF]) in add_to_diff_net th;;
(* ------------------------------------------------------------------------- *) (* Main recurrence relation. *) (* ------------------------------------------------------------------------- *)
let DIFF_CHAIN_TAN = 
prove (`~(cos x = &0) ==> ((\x. poly p (tan x)) diffl (poly ([&1; &0; &1] ** poly_diff p) (tan x))) (x)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[tan] THEN W(MP_TAC o SPEC `x:real` o DIFF_CONV o lhand o rator o snd) THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[POLY_MUL] THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[poly; REAL_MUL_RID; REAL_MUL_RZERO; REAL_ADD_RID; REAL_ADD_LID] THEN REWRITE_TAC[REAL_ARITH `a - --s * s = (s * s + a)`] THEN REWRITE_TAC[GSYM REAL_POW_2; SIN_CIRCLE] THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM REAL_POW2_ABS] THEN ASM_SIMP_TAC[REAL_POW_LT; GSYM REAL_ABS_NZ; REAL_EQ_LDIV_EQ] THEN REWRITE_TAC[REAL_POW2_ABS] THEN REWRITE_TAC[REAL_ADD_RDISTRIB; GSYM REAL_POW_MUL] THEN ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_MUL_LID] THEN ONCE_REWRITE_TAC[REAL_ADD_SYM] THEN REWRITE_TAC[SIN_CIRCLE]);;
(* ------------------------------------------------------------------------- *) (* Define tangent polynomials and tangent numbers on this pattern. *) (* ------------------------------------------------------------------------- *)
let tanpoly = new_recursive_definition num_RECURSION
  `(tanpoly 0 = [&0; &1]) /\
   (!n. tanpoly (SUC n) = [&1; &0; &1] ** poly_diff(tanpoly n))`;;
let TANPOLYS_RULE = let pth1,pth2 = CONJ_PAIR tanpoly in let base = [pth1] and rule = GEN_REWRITE_RULE LAND_CONV [GSYM pth2] in let poly_diff_tm = `poly_diff` and poly_mul_tm = `( ** ) [&1; &0; &1]` in let rec tanpolys n = if n < 0 then [] else if n = 0 then base else let thl = tanpolys (n - 1) in let th1 = AP_TERM poly_diff_tm (hd thl) in let th2 = TRANS th1 (POLY_DIFF_CONV (rand(concl th1))) in let th3 = AP_TERM poly_mul_tm th2 in let th4 = TRANS th3 (POLY_MUL_CONV (rand(concl th3))) in let th5 = rule th4 in let th6 = CONV_RULE (LAND_CONV(RAND_CONV NUM_SUC_CONV)) th5 in th6::thl in rev o tanpolys;; let TANPOLY_CONV = let tanpoly_tm = `tanpoly` in fun tm -> let l,r = dest_comb tm in if l <> tanpoly_tm then failwith "TANPOLY_CONV" else last(TANPOLYS_RULE(dest_small_numeral r));;
let tannumber = new_definition
  `tannumber n = poly (tanpoly n) (&0)`;;
let TANNUMBERS_RULE,TANNUMBER_CONV =
let POLY_0_THM = 
prove (`(poly [] (&0) = &0) /\ (poly (CONS h t) (&0) = h)`,
REWRITE_TAC[poly; REAL_MUL_LZERO; REAL_ADD_RID]) in let poly_tm = `poly` and zero_tm = `&0` and tannumber_tm = `tannumber` and depoly_conv = GEN_REWRITE_CONV I [POLY_0_THM] and tannumber_rule = GEN_REWRITE_RULE LAND_CONV [GSYM tannumber] in let process th = let th1 = AP_THM (AP_TERM poly_tm th) zero_tm in let th2 = TRANS th1 (depoly_conv (rand(concl th1))) in let th3 = tannumber_rule th2 in th3 in let TANNUMBERS_RULE = map process o TANPOLYS_RULE and TANNUMBER_CONV tm = let l,r = dest_comb tm in if l <> tannumber_tm then failwith "TANNUMBER_CONV" else process(last(TANPOLYS_RULE(dest_small_numeral r))) in TANNUMBERS_RULE,TANNUMBER_CONV;;
(* ------------------------------------------------------------------------- *) (* Chaining rules using the tangent polynomials. *) (* ------------------------------------------------------------------------- *)
let DIFF_CHAIN_TAN_TANPOLYS = 
prove (`~(cos x = &0) ==> ((\x. poly (tanpoly n) (tan x)) diffl (poly (tanpoly(SUC n)) (tan x))) (x)`,
REWRITE_TAC[tanpoly; DIFF_CHAIN_TAN]);;
let th = 
prove (`(f diffl l)(x) /\ ~(cos(f x) = &0) ==> ((\x. poly (tanpoly n) (tan(f x))) diffl (l * poly (tanpoly(SUC n)) (tan(f x))))(x)`,
REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN MP_TAC(SPECL [`\x. poly (tanpoly n) (tan x)`; `f:real->real`; `poly (tanpoly(SUC n)) (tan(f(x:real)))`; `l:real`; `x:real`] DIFF_CHAIN) THEN ASM_SIMP_TAC[DIFF_CHAIN_TAN_TANPOLYS]) in add_to_diff_net th;;
(* ------------------------------------------------------------------------- *) (* Hence rewrite coefficients of tan and cot series in terms of tannumbers. *) (* ------------------------------------------------------------------------- *)
let TERMDIFF_ALT = 
prove (`!f f' c k. (!x. abs(x) < k ==> (\n. c(n) * x pow n) sums f(x)) ==> (!x. abs(x) < k ==> (f diffl f'(x))(x)) ==> (!x. abs(x) < k ==> (\n. (diffs c)(n) * x pow n) sums f'(x))`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `summable (\n. diffs c n * x pow n) /\ (f'(x) = suminf (\n. diffs c n * x pow n))` MP_TAC THENL [ALL_TAC; SIMP_TAC[SUMMABLE_SUM]] THEN CONJ_TAC THENL [UNDISCH_TAC `abs(x) < k` THEN SPEC_TAC(`x:real`,`x:real`) THEN MATCH_MP_TAC TERMDIFF_CONVERGES THEN REPEAT STRIP_TAC THEN REWRITE_TAC[summable] THEN EXISTS_TAC `(f:real->real) x` THEN ASM_SIMP_TAC[]; ALL_TAC] THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN MATCH_MP_TAC DIFF_LCONST THEN EXISTS_TAC `\x. f x - suminf (\n. c(n) * x pow n)` THEN EXISTS_TAC `x:real` THEN CONJ_TAC THENL [MATCH_MP_TAC DIFF_SUB THEN ASM_SIMP_TAC[] THEN MATCH_MP_TAC TERMDIFF_STRONG THEN EXISTS_TAC `(abs(x) + k) / &2` THEN CONJ_TAC THENL [REWRITE_TAC[summable] THEN EXISTS_TAC `(f:real->real)((abs(x) + k) / &2)` THEN FIRST_ASSUM MATCH_MP_TAC; ALL_TAC] THEN SIMP_TAC[REAL_ABS_DIV; REAL_ABS_NUM; REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN UNDISCH_TAC `abs(x) < k` THEN REAL_ARITH_TAC; ALL_TAC] THEN EXISTS_TAC `k - abs(x)` THEN ASM_REWRITE_TAC[REAL_SUB_LT] THEN X_GEN_TAC `y:real` THEN DISCH_TAC THEN MATCH_MP_TAC(REAL_ARITH `(a = b) /\ (c = d) ==> (a - b = c - d)`) THEN CONJ_TAC THEN MATCH_MP_TAC SUM_UNIQ THEN FIRST_ASSUM MATCH_MP_TAC THEN UNDISCH_TAC `abs(x - y) < k - abs(x)` THEN REAL_ARITH_TAC);;
let TAN_DERIV_POWSER = 
prove (`!n x. abs(x) < pi / &2 ==> (\m. ITER n diffs (\i. if EVEN i then &0 else &2 * (&2 pow (i + 1) - &1) * suminf (\m. inv (&(m + 1) pow (i + 1))) / pi pow (i + 1)) m * x pow m) sums (poly (tanpoly n) (tan x))`,
INDUCT_TAC THENL [REPEAT STRIP_TAC THEN REWRITE_TAC[ITER; tanpoly; poly] THEN REWRITE_TAC[REAL_ADD_LID; REAL_ADD_RID; REAL_MUL_RZERO; REAL_MUL_RID] THEN ASM_SIMP_TAC[TAN_POWSER]; ALL_TAC] THEN FIRST_ASSUM(MP_TAC o MATCH_MP TERMDIFF_ALT) THEN REWRITE_TAC[ITER] THEN CONV_TAC(ONCE_DEPTH_CONV ETA_CONV) THEN DISCH_THEN MATCH_MP_TAC THEN X_GEN_TAC `x:real` THEN DISCH_TAC THEN MATCH_MP_TAC DIFF_CHAIN_TAN_TANPOLYS THEN REWRITE_TAC[COS_ZERO] THEN UNDISCH_TAC `abs x < pi / &2` THEN CONV_TAC CONTRAPOS_CONV THEN REWRITE_TAC[DE_MORGAN_THM] THEN REWRITE_TAC[OR_EXISTS_THM; NOT_EVEN] THEN REWRITE_TAC[TAUT `a /\ b \/ a /\ c <=> a /\ (b \/ c)`] THEN DISCH_THEN(CHOOSE_THEN MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH `(x = a) \/ (x = --a) ==> &0 <= a ==> (abs(x) = a)`)) THEN SIMP_TAC[REAL_LE_MUL; REAL_LE_DIV; REAL_LT_IMP_LE; PI_POS; REAL_POS] THEN DISCH_THEN(K ALL_TAC) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN DISCH_THEN(CHOOSE_THEN SUBST1_TAC) THEN GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [REAL_ARITH `x = &1 * x`] THEN SIMP_TAC[REAL_LT_RMUL_EQ; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; PI_POS] THEN ARITH_TAC);;
let ITER_DIFFS_LEMMA = 
prove (`!n c. ITER n diffs c 0 = &(FACT n) * c(n)`,
INDUCT_TAC THEN ASM_REWRITE_TAC[ITER_ALT; diffs; FACT; REAL_MUL_LID] THEN REWRITE_TAC[GSYM REAL_OF_NUM_MUL; REAL_MUL_AC]);;
let TANNUMBER_HARMONICSUMS = 
prove (`!n. ODD n ==> (&2 * (&2 pow (n + 1) - &1) * &(FACT n) * suminf (\m. inv (&(m + 1) pow (n + 1))) / pi pow (n + 1) = tannumber n)`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`n:num`; `&0`] TAN_DERIV_POWSER) THEN SIMP_TAC[REAL_ABS_NUM; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; PI_POS] THEN REWRITE_TAC[TAN_0; GSYM tannumber] THEN MP_TAC(SPECL [`\m. ITER n diffs (\i. if EVEN i then &0 else &2 * (&2 pow (i + 1) - &1) * suminf (\m. inv (&(m + 1) pow (i + 1))) / pi pow (i + 1)) m * &0 pow m`; `1`] SER_0) THEN REWRITE_TAC[SUM_1] THEN SIMP_TAC[snd(EQ_IMP_RULE(SPEC_ALL REAL_POW_EQ_0)); ARITH_RULE `1 <= n ==> ~(n = 0)`] THEN REWRITE_TAC[REAL_MUL_RZERO; real_pow] THEN ONCE_REWRITE_TAC[IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP SER_UNIQ) THEN DISCH_THEN(SUBST1_TAC o SYM) THEN REWRITE_TAC[ITER_DIFFS_LEMMA; REAL_MUL_RID] THEN ASM_REWRITE_TAC[GSYM NOT_ODD] THEN REWRITE_TAC[REAL_MUL_AC]);;
let HARMONICSUMS_TANNUMBER = 
prove (`!n. EVEN n /\ ~(n = 0) ==> (suminf (\m. inv (&(m + 1) pow n)) / pi pow n = tannumber(n - 1) / (&2 * &(FACT(n - 1)) * (&2 pow n - &1)))`,
INDUCT_TAC THEN REWRITE_TAC[NOT_SUC; EVEN; NOT_EVEN] THEN REWRITE_TAC[SUC_SUB1] THEN SIMP_TAC[GSYM TANNUMBER_HARMONICSUMS] THEN REWRITE_TAC[ADD1] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c * d = (a * c * b) * d`] THEN REWRITE_TAC[real_div] THEN DISCH_TAC THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `(a * b * c) * d = a * (b * c) * d`] THEN REWRITE_TAC[GSYM real_div] THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC REAL_DIV_LMUL THEN MATCH_MP_TAC REAL_LT_IMP_NZ THEN MATCH_MP_TAC REAL_LT_MUL THEN REWRITE_TAC[REAL_OF_NUM_LT; ARITH] THEN MATCH_MP_TAC REAL_LT_MUL THEN REWRITE_TAC[REAL_OF_NUM_LT; FACT_LT] THEN REWRITE_TAC[REAL_SUB_LT] THEN REWRITE_TAC[REAL_POW2_CLAUSES; ADD_EQ_0; ARITH_EQ]);;
(* ------------------------------------------------------------------------- *) (* For uniformity, show that even tannumbers are zero. *) (* ------------------------------------------------------------------------- *)
let ODD_POLY_DIFF = 
prove (`(!x. poly p (--x) = poly p x) ==> (!x. poly (poly_diff p) (--x) = --(poly(poly_diff p) x))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC DIFF_UNIQ THEN EXISTS_TAC `\x. poly p (--x)` THEN EXISTS_TAC `--x` THEN CONJ_TAC THENL [FIRST_ASSUM(SUBST1_TAC o SYM o HALF_MK_ABS o GSYM) THEN REWRITE_TAC[CONV_RULE(ONCE_DEPTH_CONV ETA_CONV) POLY_DIFF]; MP_TAC(SPECL [`\x. poly p x`; `\x. --x`; `poly (poly_diff p) x`; `--(&1)`; `--x`] DIFF_CHAIN) THEN REWRITE_TAC[POLY_DIFF; REAL_MUL_RNEG; REAL_MUL_RID; REAL_NEG_NEG] THEN DISCH_THEN MATCH_MP_TAC THEN W(MP_TAC o SPEC `--x` o DIFF_CONV o lhand o rator o snd) THEN REWRITE_TAC[]]);;
let EVEN_POLY_DIFF = 
prove (`(!x. poly p (--x) = --(poly p x)) ==> (!x. poly (poly_diff p) (--x) = poly(poly_diff p) x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC DIFF_UNIQ THEN EXISTS_TAC `\x. poly p x` THEN EXISTS_TAC `--x` THEN REWRITE_TAC[POLY_DIFF] THEN FIRST_ASSUM(MP_TAC o ONCE_REWRITE_RULE[REAL_ARITH `(a = --b) <=> (--a = b)`]) THEN DISCH_THEN(SUBST1_TAC o HALF_MK_ABS o GSYM) THEN REWRITE_TAC[] THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_NEG_NEG] THEN MATCH_MP_TAC DIFF_NEG THEN MP_TAC(SPECL [`\x. poly p x`; `\x. --x`; `poly (poly_diff p) x`; `--(&1)`; `--x`] DIFF_CHAIN) THEN REWRITE_TAC[POLY_DIFF; REAL_MUL_RNEG; REAL_MUL_RID; REAL_NEG_NEG] THEN DISCH_THEN MATCH_MP_TAC THEN W(MP_TAC o SPEC `--x` o DIFF_CONV o lhand o rator o snd) THEN REWRITE_TAC[]);;
let TANPOLY_ODD_EVEN = 
prove (`!n x. (poly (tanpoly n) (--x) = if EVEN n then --(poly (tanpoly n) x) else poly (tanpoly n) x)`,
INDUCT_TAC THENL [REWRITE_TAC[EVEN; tanpoly] THEN CONV_TAC(ONCE_DEPTH_CONV POLY_DIFF_CONV) THEN REWRITE_TAC[poly] THEN REAL_ARITH_TAC; ALL_TAC] THEN POP_ASSUM MP_TAC THEN REWRITE_TAC[EVEN] THEN ASM_CASES_TAC `EVEN n` THEN ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC[tanpoly; POLY_MUL; ODD_POLY_DIFF; EVEN_POLY_DIFF] THEN REWRITE_TAC[REAL_MUL_RNEG] THEN TRY AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[poly] THEN REAL_ARITH_TAC);;
let TANNUMBER_EVEN = 
prove (`!n. EVEN n ==> (tannumber n = &0)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[tannumber] THEN MATCH_MP_TAC(REAL_ARITH `(x = --x) ==> (x = &0)`) THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM REAL_NEG_0] THEN ASM_SIMP_TAC[TANPOLY_ODD_EVEN]);;
(* ------------------------------------------------------------------------- *) (* Hence get tidy series. *) (* ------------------------------------------------------------------------- *)
let TAYLOR_TAN_CONVERGES = 
prove (`!x. abs(x) < pi / &2 ==> (\n. tannumber n / &(FACT n) * x pow n) sums (tan x)`,
GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP TAN_POWSER) THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:num` THEN COND_CASES_TAC THENL [ASM_SIMP_TAC[real_div; TANNUMBER_EVEN; REAL_MUL_LZERO; REAL_MUL_RZERO]; ALL_TAC] THEN ASM_SIMP_TAC[HARMONICSUMS_TANNUMBER; EVEN_ADD; ARITH; ADD_EQ_0] THEN REWRITE_TAC[ADD_SUB; real_div; REAL_INV_MUL; GSYM REAL_MUL_ASSOC] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c * a' * d * b' * e = (c * d * e) * ((a * a') * (b * b'))`] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN AP_TERM_TAC THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_MUL_LID] THEN MATCH_MP_TAC REAL_MUL_RINV THEN SIMP_TAC[REAL_ARITH `&1 < x ==> ~(x - &1 = &0)`; REAL_POW2_CLAUSES; ADD_EQ_0; ARITH_EQ]);;
let TAYLOR_X_COT_CONVERGES = 
prove (`!x. &0 < abs(x) /\ abs(x) < pi ==> (\n. (if n = 0 then &1 else tannumber (n - 1) / ((&1 - &2 pow n) * &(FACT(n - 1)))) * x pow n) sums (x * cot(x))`,
GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP COT_X_POWSER) THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:num` THEN ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `ODD n` THEN ASM_REWRITE_TAC[] THENL [SUBGOAL_THEN `tannumber(n - 1) = &0` (fun th -> SIMP_TAC[th; real_div; REAL_MUL_LZERO; REAL_MUL_RZERO]) THEN MATCH_MP_TAC TANNUMBER_EVEN THEN UNDISCH_TAC `ODD n` THEN SUBGOAL_THEN `n = SUC(n - 1)` MP_TAC THENL [UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC; ALL_TAC] THEN DISCH_THEN(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [th]) THEN REWRITE_TAC[ODD; NOT_ODD]; ALL_TAC] THEN AP_THM_TAC THEN AP_TERM_TAC THEN ASM_SIMP_TAC[HARMONICSUMS_TANNUMBER; GSYM NOT_ODD] THEN REWRITE_TAC[real_div; REAL_INV_MUL; GSYM REAL_MUL_ASSOC] THEN ONCE_REWRITE_TAC[REAL_ARITH `--(&2) * x * y * z * a = (&2 * y) * x * --a * z`] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[GSYM REAL_INV_NEG; REAL_NEG_SUB; REAL_MUL_LID]);;
(* ------------------------------------------------------------------------- *) (* Get a simple bound on the tannumbers. *) (* ------------------------------------------------------------------------- *)
let TANNUMBER_BOUND = 
prove (`!n. abs(tannumber n) <= &4 * &(FACT n) * (&2 / pi) pow (n + 1)`,
GEN_TAC THEN DISJ_CASES_TAC(SPEC `n:num` EVEN_OR_ODD) THEN ASM_SIMP_TAC[TANNUMBER_EVEN; GSYM TANNUMBER_HARMONICSUMS] THEN (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 5) [REAL_ABS_NUM; REAL_LE_MUL; REAL_POW_LE; REAL_POS; REAL_LE_DIV; PI_POS; REAL_LT_IMP_LE] THEN REWRITE_TAC[real_div; GSYM REAL_MUL_ASSOC] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c * d * e = (a * d) * c * b * e`] THEN ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL [REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM] THEN REWRITE_TAC[REAL_ARITH `&2 * x <= &4 <=> x <= &2`] THEN MP_TAC(SPEC `\m. inv (&(m + 1) pow (n + 1))` SER_ABS) THEN REWRITE_TAC[REAL_ABS_INV; REAL_ABS_NUM; REAL_ABS_POW] THEN W(C SUBGOAL_THEN (fun th -> REWRITE_TAC[th]) o funpow 2 lhand o snd) THENL [MATCH_MP_TAC SUMMABLE_INVERSE_POWERS THEN UNDISCH_TAC `ODD n` THEN SIMP_TAC[ODD_EXISTS; LEFT_IMP_EXISTS_THM] THEN REPEAT STRIP_TAC THEN ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC(REAL_ARITH `b <= c ==> a <= b ==> a <= c`) THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `suminf (\m. inv(&(m + 1) pow 2))` THEN CONJ_TAC THENL [MATCH_MP_TAC SER_LE THEN REPEAT CONJ_TAC THENL [GEN_TAC THEN REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN SIMP_TAC[REAL_POW_LT; REAL_OF_NUM_LT; ARITH_RULE `0 < n + 1`] THEN MATCH_MP_TAC REAL_POW_MONO THEN REWRITE_TAC[REAL_OF_NUM_LE] THEN UNDISCH_TAC `ODD n` THEN SIMP_TAC[ODD_EXISTS; LEFT_IMP_EXISTS_THM] THEN REPEAT STRIP_TAC THEN ARITH_TAC; MATCH_MP_TAC SUMMABLE_INVERSE_POWERS THEN UNDISCH_TAC `ODD n` THEN SIMP_TAC[ODD_EXISTS; LEFT_IMP_EXISTS_THM] THEN REPEAT STRIP_TAC THEN ARITH_TAC; MATCH_MP_TAC SUMMABLE_INVERSE_POWERS THEN REWRITE_TAC[LE_REFL]]; ALL_TAC] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,1) (\n. inv(&(n + 1) pow 2)) + suminf (\n. inv(&((n + 1) + 1) pow 2))` THEN CONJ_TAC THENL [MATCH_MP_TAC(REAL_ARITH `(y = x) ==> x <= y`) THEN MATCH_MP_TAC SUM_UNIQ THEN MATCH_MP_TAC SER_OFFSET_REV THEN REWRITE_TAC[summable] THEN EXISTS_TAC `suminf (\n. inv(&(n + 1) pow 2)) - sum(0,1) (\n. inv(&(n + 1) pow 2))` THEN MATCH_MP_TAC(REWRITE_RULE[RIGHT_IMP_FORALL_THM] SER_OFFSET) THEN MATCH_MP_TAC SUMMABLE_INVERSE_POWERS THEN REWRITE_TAC[LE_REFL]; ALL_TAC] THEN REWRITE_TAC[SUM_1; ADD_CLAUSES] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_ARITH `&1 + x <= &2 <=> x <= &1`] THEN SUBST1_TAC(MATCH_MP SUM_UNIQ SUMMABLE_INVERSE_SQUARES_LEMMA) THEN MATCH_MP_TAC SER_LE THEN REPEAT CONJ_TAC THENL [X_GEN_TAC `m:num` THEN REWRITE_TAC[REAL_POW_2] THEN REWRITE_TAC[ARITH_RULE `(n + 1) + 1 = n + 2`] THEN REWRITE_TAC[REAL_POW_2; REAL_INV_MUL; REAL_ABS_INV; REAL_ABS_NUM; REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_LE_INV_EQ; REAL_POS] THEN MATCH_MP_TAC REAL_LE_INV2 THEN REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_LE] THEN ARITH_TAC; REWRITE_TAC[summable] THEN EXISTS_TAC `suminf (\n. inv(&(n + 1) pow 2)) - sum(0,1) (\n. inv(&(n + 1) pow 2))` THEN MATCH_MP_TAC(REWRITE_RULE[RIGHT_IMP_FORALL_THM] SER_OFFSET) THEN MATCH_MP_TAC SUMMABLE_INVERSE_POWERS THEN REWRITE_TAC[LE_REFL]; REWRITE_TAC[summable] THEN EXISTS_TAC `&1` THEN REWRITE_TAC[SUMMABLE_INVERSE_SQUARES_LEMMA]]; ALL_TAC] THEN ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN REWRITE_TAC[REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN REWRITE_TAC[REAL_POW_MUL; REAL_POW_INV] THEN ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN REWRITE_TAC[REAL_ABS_INV; REAL_ABS_POW] THEN SIMP_TAC[real_abs; PI_POS; REAL_LT_IMP_LE] THEN REWRITE_TAC[GSYM real_abs] THEN MATCH_MP_TAC REAL_LE_RMUL THEN SIMP_TAC[REAL_LE_INV_EQ; REAL_POW_LT; REAL_LT_IMP_LE; PI_POS] THEN MATCH_MP_TAC(REAL_ARITH `&1 <= x ==> abs(x - &1) <= x`) THEN REWRITE_TAC[REAL_POW2_CLAUSES]);;
(* ------------------------------------------------------------------------- *) (* Also get some harmonic sums. *) (* ------------------------------------------------------------------------- *)
let HARMONIC_SUMS = 
prove (`!n. (\m. inv (&(m + 1) pow (2 * (n + 1)))) sums (pi pow (2 * (n + 1)) * tannumber(2 * n + 1) / (&2 * (&2 pow (2 * (n + 1)) - &1) * &(FACT(2 * n + 1))))`,
GEN_TAC THEN SUBGOAL_THEN `summable (\m. inv (&(m + 1) pow (2 * (n + 1))))` MP_TAC THENL [MATCH_MP_TAC SUMMABLE_INVERSE_POWERS THEN ARITH_TAC; ALL_TAC] THEN DISCH_THEN(MP_TAC o MATCH_MP SUMMABLE_SUM) THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN SIMP_TAC[GSYM REAL_EQ_LDIV_EQ; REAL_POW_LT; PI_POS] THEN REWRITE_TAC[ARITH_RULE `2 * n + 1 = 2 * (n + 1) - 1`] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c = a * c * b`] THEN MATCH_MP_TAC HARMONICSUMS_TANNUMBER THEN REWRITE_TAC[MULT_EQ_0; ADD_EQ_0; ARITH; EVEN_MULT]);;
let mk_harmonic =
let pth = 
prove (`x * &1 / n = x / n`,
REWRITE_TAC[real_div; REAL_MUL_LID]) in let final_RULE = CONV_RULE(TRY_CONV(GEN_REWRITE_CONV RAND_CONV [pth])) in fun n -> let th1 = SPEC(mk_small_numeral((n-1)/2)) HARMONIC_SUMS in let th2 = CONV_RULE NUM_REDUCE_CONV th1 in let th3 = CONV_RULE(ONCE_DEPTH_CONV TANNUMBER_CONV) th2 in let th4 = CONV_RULE REAL_RAT_REDUCE_CONV th3 in final_RULE th4;;
(* ------------------------------------------------------------------------- *) (* A little test. *) (* ------------------------------------------------------------------------- *) map (fun n -> time mk_harmonic (2 * n)) (0--8);; (* ------------------------------------------------------------------------- *) (* Isolate the most famous special case. *) (* ------------------------------------------------------------------------- *) let EULER_HARMONIC_SUM = mk_harmonic 2;; (* ------------------------------------------------------------------------- *) (* Canonical Taylor series for tan and cot with truncation bounds. *) (* ------------------------------------------------------------------------- *)
let TAYLOR_TAN_BOUND_GENERAL = 
prove (`!x n. abs(x) <= &1 ==> abs(tan x - sum (0,n) (\m. tannumber m / &(FACT m) * x pow m)) <= &12 * (&2 / &3) pow (n + 1) * abs(x) pow n`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `abs(x) < pi / &2` MP_TAC THENL [MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `&1` THEN ASM_REWRITE_TAC[] THEN SIMP_TAC[REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e < a ==> abs(p - a) <= e ==> b < p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN DISCH_THEN(MP_TAC o MATCH_MP TAYLOR_TAN_CONVERGES) THEN DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC(MATCH_MP SUM_SUMMABLE th)) THEN DISCH_THEN(MP_TAC o SPEC `n:num` o MATCH_MP SER_OFFSET) THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP SUM_UNIQ) THEN REWRITE_TAC[sums] THEN DISCH_THEN(MP_TAC o MATCH_MP SEQ_ABS_IMP) THEN REWRITE_TAC[] THEN DISCH_TAC THEN MATCH_MP_TAC SEQ_LE_CONST THEN EXISTS_TAC `\r. abs(sum(0,r) (\m. (tannumber(m + n) / &(FACT(m + n))) * x pow (m + n)))` THEN EXISTS_TAC `0` THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `m:num` THEN DISCH_THEN(K ALL_TAC) THEN W(MP_TAC o PART_MATCH lhand SUM_ABS_LE o lhand o snd) THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,m) (\r. &4 * (&2 / pi) pow (r + n + 1) * abs(x pow (r + n)))` THEN REWRITE_TAC[] THEN CONJ_TAC THENL [MATCH_MP_TAC SUM_LE THEN X_GEN_TAC `r:num` THEN REWRITE_TAC[ADD_CLAUSES] THEN STRIP_TAC THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_DIV; REAL_ABS_NUM] THEN REWRITE_TAC[REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN SIMP_TAC[REAL_ABS_DIV; REAL_ABS_NUM; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; FACT_LT] THEN MP_TAC(SPEC `r + n:num` TANNUMBER_BOUND) THEN REWRITE_TAC[REAL_MUL_AC; GSYM ADD_ASSOC]; ALL_TAC] THEN REWRITE_TAC[GSYM ADD1; ADD_CLAUSES] THEN REWRITE_TAC[real_pow; GSYM REAL_MUL_ASSOC] THEN REWRITE_TAC[REAL_ABS_POW; GSYM REAL_POW_MUL] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN REWRITE_TAC[REAL_POW_ADD; REAL_MUL_ASSOC] THEN REWRITE_TAC[SUM_CMUL] THEN SUBGOAL_THEN `&2 / pi * abs(x) < &2 / &3` ASSUME_TAC THENL [MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `&2 / pi * &1` THEN CONJ_TAC THENL [ASM_SIMP_TAC[REAL_LE_LMUL; REAL_LE_DIV; REAL_POS; REAL_LT_IMP_LE; PI_POS]; ALL_TAC] THEN REWRITE_TAC[REAL_MUL_RID] THEN SIMP_TAC[REAL_LT_LDIV_EQ; PI_POS] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN SIMP_TAC[GSYM REAL_LT_LDIV_EQ; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e < a ==> abs(p - a) <= e ==> b < p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN SUBGOAL_THEN `~(&2 / pi * abs(x) = &1)` ASSUME_TAC THENL [UNDISCH_TAC `&2 / pi * abs x < &2 / &3` THEN ONCE_REWRITE_TAC[TAUT `a ==> ~b <=> b ==> ~a`] THEN SIMP_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN GEN_REWRITE_TAC LAND_CONV [AC REAL_MUL_AC `(a * b) * c = (a * c) * b`] THEN MATCH_MP_TAC(REAL_ARITH `abs(x) <= a ==> x <= a`) THEN ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL [ALL_TAC; REWRITE_TAC[REAL_POW_MUL; GSYM REAL_ABS_POW; REAL_ABS_MUL; REAL_ABS_ABS] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[REAL_ABS_POW] THEN MATCH_MP_TAC REAL_POW_LE2 THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[REAL_ABS_MUL; real_div; REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN REWRITE_TAC[REAL_OF_NUM_LT; ARITH] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e <= a ==> abs(p - a) <= e ==> b <= abs p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV] THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM; GSYM REAL_MUL_ASSOC] THEN REWRITE_TAC[REAL_ARITH `&4 * x * y <= &12 * z <=> x * y <= z * &3`] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL [REWRITE_TAC[REAL_ABS_MUL; real_div; REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN REWRITE_TAC[REAL_OF_NUM_LT; ARITH] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e <= a ==> abs(p - a) <= e ==> b <= abs p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN ASM_SIMP_TAC[GP_FINITE] THEN REWRITE_TAC[REAL_ABS_DIV] THEN ONCE_REWRITE_TAC[REAL_ABS_SUB] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN REWRITE_TAC[real_div; GSYM REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[GSYM real_div] THEN CONJ_TAC THENL [MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ x <= &1 ==> abs(&1 - x) <= &1`) THEN (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 4) [REAL_POW_LE; REAL_LE_DIV; REAL_LE_MUL; REAL_POS; REAL_ABS_POS; PI_POS; REAL_LT_IMP_LE] THEN MATCH_MP_TAC REAL_POW_1_LE THEN (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 4) [REAL_POW_LE; REAL_LE_DIV; REAL_LE_MUL; REAL_POS; REAL_ABS_POS; PI_POS; REAL_LT_IMP_LE] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&2 / pi * &1` THEN ASM_SIMP_TAC[REAL_LE_LMUL; REAL_LE_DIV; REAL_POS; REAL_LT_IMP_LE; PI_POS] THEN SIMP_TAC[REAL_MUL_RID; REAL_LE_LDIV_EQ; PI_POS] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e <= a ==> abs(p - a) <= e ==> b <= &1 * p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN REWRITE_TAC[REAL_ABS_INV] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_INV_INV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN MATCH_MP_TAC(REAL_ARITH `x <= (&1 - a) * &1 ==> a <= abs(&1 - x)`) THEN MATCH_MP_TAC REAL_LE_MUL2 THEN ASM_REWRITE_TAC[REAL_ABS_POS] THEN SIMP_TAC[REAL_LE_DIV; REAL_POS; REAL_LT_IMP_LE; PI_POS] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[real_div] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN MATCH_MP_TAC REAL_LE_INV2 THEN REWRITE_TAC[REAL_OF_NUM_LT; ARITH] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e <= a ==> abs(p - a) <= e ==> b <= p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let TAYLOR_TAN_BOUND = 
prove (`!x n k. abs(x) <= inv(&2 pow k) ==> abs(tan x - sum (0,n) (\m. tannumber(m) / &(FACT(m)) * x pow m)) <= &12 * (&2 / &3) pow (n + 1) * inv(&2 pow (k * n))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&12 * (&2 / &3) pow (n + 1) * abs(x) pow n` THEN CONJ_TAC THENL [MATCH_MP_TAC TAYLOR_TAN_BOUND_GENERAL THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `inv(&2 pow 0)`)) THEN REWRITE_TAC[REAL_POW2_THM; LE_0]; REWRITE_TAC[REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_LMUL THEN SIMP_TAC[REAL_LE_MUL; REAL_POW_LE; REAL_LE_DIV; REAL_POS] THEN REWRITE_TAC[GSYM REAL_POW_POW] THEN ONCE_REWRITE_TAC[GSYM REAL_POW_INV] THEN MATCH_MP_TAC REAL_POW_LE2 THEN ASM_REWRITE_TAC[REAL_ABS_POS]]);;
let TAYLOR_TANX_BOUND = 
prove (`!x n k. abs(x) <= inv(&2 pow k) /\ ~(x = &0) ==> abs(tan x / x - sum (0,n) (\m. tannumber(m+1) / &(FACT(m+1)) * x pow m)) <= &12 * (&2 / &3) pow (n + 2) * inv(&2 pow (k * n))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_RCANCEL_IMP THEN EXISTS_TAC `abs(x)` THEN ASM_SIMP_TAC[GSYM REAL_ABS_NZ] THEN REWRITE_TAC[GSYM REAL_ABS_MUL; REAL_SUB_RDISTRIB] THEN ASM_SIMP_TAC[REAL_DIV_RMUL] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [REAL_MUL_SYM] THEN REWRITE_TAC[GSYM SUM_CMUL] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [AC REAL_MUL_AC `a * b * c = b * (a * c)`] THEN REWRITE_TAC[GSYM(CONJUNCT2 real_pow)] THEN REWRITE_TAC[ADD1; SPECL [`f:num->real`; `n:num`; `1`] SUM_OFFSET] THEN REWRITE_TAC[SUM_1] THEN CONV_TAC(ONCE_DEPTH_CONV TANNUMBER_CONV) THEN CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[real_pow] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_SUB_RZERO] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&12 * (&2 / &3) pow ((n + 1) + 1) * abs(x) pow (n + 1)` THEN CONJ_TAC THENL [MATCH_MP_TAC TAYLOR_TAN_BOUND_GENERAL THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `inv(&2 pow 0)`)) THEN REWRITE_TAC[REAL_POW2_THM; LE_0]; ALL_TAC] THEN REWRITE_TAC[ARITH_RULE `(n + 1) + 1 = n + 2`] THEN REWRITE_TAC[GSYM ADD1; real_pow] THEN GEN_REWRITE_TAC RAND_CONV [AC REAL_MUL_AC `(a * b * c) * d = (a * b * d) * c`] THEN REWRITE_TAC[REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_LMUL THEN (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 4) [REAL_LE_MUL; REAL_POW_LE; REAL_ABS_POS; REAL_LE_DIV; REAL_POS] THEN REWRITE_TAC[GSYM REAL_POW_POW] THEN ONCE_REWRITE_TAC[GSYM REAL_POW_INV] THEN MATCH_MP_TAC REAL_POW_LE2 THEN ASM_REWRITE_TAC[REAL_ABS_POS]);;
let TAYLOR_TANX_SQRT_BOUND = 
prove (`!x n k. abs(x) <= inv(&2 pow k) /\ &0 < x ==> abs(tan (sqrt x) / sqrt(x) - sum(0,n) (\m. tannumber(2 * m + 1) / &(FACT(2 * m + 1)) * x pow m)) <= &12 * (&2 / &3) pow (2 * n + 2) * inv(&2 pow (k DIV 2 * 2 * n))`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`sqrt x`; `2 * n`; `k DIV 2`] TAYLOR_TANX_BOUND) THEN W(C SUBGOAL_THEN (fun th -> REWRITE_TAC[th]) o funpow 2 lhand o snd) THENL [ASM_SIMP_TAC[SQRT_POS_LT; REAL_LT_IMP_NZ; DIV_EQ_0; ARITH_EQ; NOT_LT] THEN SUBGOAL_THEN `&2 pow (k DIV 2) = sqrt(&2 pow (2 * (k DIV 2)))` SUBST1_TAC THENL [SIMP_TAC[SQRT_EVEN_POW2; EVEN_MULT; ARITH_EVEN; DIV_MULT; ARITH_EQ]; ALL_TAC] THEN ASM_SIMP_TAC[GSYM SQRT_INV; REAL_LT_IMP_LE; REAL_POW2_CLAUSES] THEN ASM_SIMP_TAC[real_abs; SQRT_POS_LT; REAL_LT_IMP_LE] THEN MATCH_MP_TAC SQRT_MONO_LE THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN MATCH_MP_TAC(REAL_ARITH `abs(x) <= a ==> x <= a`) THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN SIMP_TAC[REAL_POW2_CLAUSES] THEN MATCH_MP_TAC REAL_POW_MONO THEN REWRITE_TAC[REAL_OF_NUM_LE; ARITH] THEN MESON_TAC[LE_ADD; DIVISION; NUM_EQ_CONV `2 = 0`; MULT_SYM]; ALL_TAC] THEN MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[GSYM MULT_ASSOC] THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN ONCE_REWRITE_TAC[MULT_SYM] THEN REWRITE_TAC[GSYM SUM_GROUP] THEN SIMP_TAC[SUM_2; TANNUMBER_EVEN; ARITH_EVEN; EVEN_ADD; EVEN_MULT] THEN REWRITE_TAC[real_div; REAL_MUL_LZERO; REAL_ADD_RID] THEN ONCE_REWRITE_TAC[MULT_SYM] THEN ASM_SIMP_TAC[GSYM REAL_POW_POW; SQRT_POW_2; REAL_LT_IMP_LE]);;
let TAYLOR_COT_BOUND_GENERAL = 
prove (`!x n. abs(x) <= &1 /\ ~(x = &0) ==> abs((&1 / x - cot x) - sum (0,n) (\m. (tannumber m / ((&2 pow (m+1) - &1) * &(FACT(m)))) * x pow m)) <= &4 * (abs(x) / &3) pow n`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_LCANCEL_IMP THEN EXISTS_TAC `abs(x)` THEN ASM_SIMP_TAC[GSYM REAL_ABS_NZ] THEN REWRITE_TAC[GSYM REAL_ABS_MUL; REAL_SUB_LDISTRIB] THEN ASM_SIMP_TAC[REAL_DIV_LMUL] THEN REWRITE_TAC[GSYM SUM_CMUL] THEN REWRITE_TAC[GSYM REAL_SUB_LDISTRIB] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `x * a * y = a * x * y`] THEN REWRITE_TAC[GSYM(CONJUNCT2 real_pow)] THEN REWRITE_TAC[ADD1] THEN REWRITE_TAC[SUM_1; REAL_MUL_LZERO; REAL_SUB_RZERO; real_pow] THEN CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_SUB_RZERO] THEN SUBGOAL_THEN `abs(x) < pi` MP_TAC THENL [MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `&1` THEN ASM_REWRITE_TAC[] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e < a ==> abs(p - a) <= e ==> b < p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [REAL_ABS_NZ]) THEN REWRITE_TAC[IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP TAYLOR_X_COT_CONVERGES) THEN DISCH_THEN(fun th -> MP_TAC th THEN MP_TAC th) THEN DISCH_THEN(ASSUME_TAC o SYM o MATCH_MP SUM_UNIQ) THEN DISCH_THEN(MP_TAC o MATCH_MP SUM_SUMMABLE) THEN DISCH_THEN(MP_TAC o SPEC `1` o MATCH_MP SER_OFFSET) THEN ASM_REWRITE_TAC[SUM_1; ADD_EQ_0; ARITH_EQ] THEN REWRITE_TAC[real_pow; REAL_MUL_LID] THEN DISCH_THEN(MP_TAC o MATCH_MP SER_NEG) THEN REWRITE_TAC[REAL_NEG_SUB] THEN ONCE_REWRITE_TAC[GSYM REAL_MUL_LNEG] THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[GSYM REAL_MUL_RNEG] THEN REWRITE_TAC[GSYM REAL_INV_NEG] THEN REWRITE_TAC[GSYM real_div] THEN ONCE_REWRITE_TAC[GSYM REAL_MUL_LNEG] THEN REWRITE_TAC[REAL_NEG_SUB] THEN REWRITE_TAC[ADD_SUB] THEN DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC(MATCH_MP SUM_SUMMABLE th)) THEN DISCH_THEN(MP_TAC o SPEC `n:num` o MATCH_MP SER_OFFSET) THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP SUM_UNIQ) THEN REWRITE_TAC[sums] THEN DISCH_THEN(MP_TAC o MATCH_MP SEQ_ABS_IMP) THEN REWRITE_TAC[] THEN DISCH_TAC THEN MATCH_MP_TAC SEQ_LE_CONST THEN FIRST_ASSUM(fun th -> EXISTS_TAC(lhand(concl th)) THEN EXISTS_TAC `0` THEN CONJ_TAC THENL [ALL_TAC; ACCEPT_TAC th]) THEN X_GEN_TAC `m:num` THEN DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN W(MP_TAC o PART_MATCH lhand SUM_ABS_LE o lhand o snd) THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN REWRITE_TAC[GSYM ADD_ASSOC] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,m) (\r. &4 * (&2 / pi) pow (r + n + 1) / (&2 pow (r + n + 1) - &1) * abs(x pow (r + n + 1)))` THEN REWRITE_TAC[] THEN CONJ_TAC THENL [MATCH_MP_TAC SUM_LE THEN X_GEN_TAC `r:num` THEN REWRITE_TAC[ADD_CLAUSES] THEN STRIP_TAC THEN REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_DIV; REAL_ABS_NUM] THEN REWRITE_TAC[REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REAL_ABS_MUL] THEN REWRITE_TAC[real_div; REAL_INV_MUL; GSYM REAL_MUL_ASSOC] THEN GEN_REWRITE_TAC RAND_CONV [AC REAL_MUL_AC `a * b * c = (c * a) * b`] THEN REWRITE_TAC[REAL_MUL_ASSOC; real_abs; REAL_SUB_LE] THEN REWRITE_TAC[REAL_POW2_CLAUSES] THEN REWRITE_TAC[GSYM real_abs] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_LE_INV_EQ; REAL_SUB_LE; REAL_POW2_CLAUSES] THEN SIMP_TAC[GSYM real_div; REAL_ABS_DIV; REAL_ABS_NUM; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; FACT_LT] THEN MP_TAC(SPEC `r + n:num` TANNUMBER_BOUND) THEN REWRITE_TAC[REAL_MUL_AC; GSYM ADD_ASSOC]; ALL_TAC] THEN REWRITE_TAC[real_div] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [AC REAL_MUL_AC `a * (b * c) * d = a * c * (b * d)`] THEN REWRITE_TAC[REAL_ABS_POW; GSYM REAL_POW_MUL] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(0,m) (\r. &8 * inv(&2 pow (r + n + 1)) * ((&2 * inv pi) * abs x) pow (r + n + 1))` THEN CONJ_TAC THENL [MATCH_MP_TAC SUM_LE THEN X_GEN_TAC `r:num` THEN STRIP_TAC THEN REWRITE_TAC[] THEN REWRITE_TAC[REAL_ARITH `&4 * x <= &8 * y <=> x <= &2 * y`] THEN REWRITE_TAC[REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_RMUL THEN (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 4) [REAL_POW_LE; REAL_LE_MUL; REAL_ABS_POS; REAL_POS; REAL_LT_IMP_LE; PI_POS; REAL_LE_INV_EQ] THEN GEN_REWRITE_TAC (RAND_CONV o LAND_CONV) [GSYM REAL_INV_INV] THEN REWRITE_TAC[GSYM REAL_INV_MUL] THEN MATCH_MP_TAC REAL_LE_INV2 THEN SIMP_TAC[REAL_LT_MUL; REAL_LT_INV_EQ; REAL_OF_NUM_LT; ARITH; REAL_POW_LT] THEN REWRITE_TAC[GSYM ADD1; ADD_CLAUSES; real_pow] THEN REWRITE_TAC[REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_ARITH `&1 * x <= &2 * x - &1 <=> &1 <= x`] THEN REWRITE_TAC[REAL_POW2_CLAUSES]; ALL_TAC] THEN REWRITE_TAC[GSYM REAL_POW_INV; GSYM REAL_POW_MUL] THEN REWRITE_TAC[REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_ARITH `(&1 * x) * y = y * x`] THEN REWRITE_TAC[GSYM real_div] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [REAL_POW_ADD] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [AC REAL_MUL_AC `a * b * c = (a * c) * b`] THEN REWRITE_TAC[SUM_CMUL] THEN SUBGOAL_THEN `(&4 * abs x) * (abs x * &1 / &3) pow n = &12 * (abs x / &3) pow (n + 1)` SUBST1_TAC THENL [REWRITE_TAC[REAL_POW_ADD; REAL_POW_1] THEN REWRITE_TAC[real_div; REAL_MUL_LID] THEN REWRITE_TAC[REAL_POW_MUL; GSYM REAL_MUL_ASSOC] THEN GEN_REWRITE_TAC RAND_CONV [AC REAL_MUL_AC `a * b * c * d * e = (a * e) * d * b * c`] THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `&8 * &3 / &2`)) THEN GEN_REWRITE_TAC RAND_CONV [AC REAL_MUL_AC `(a * b) * c = (a * c) * b`] THEN MATCH_MP_TAC(REAL_ARITH `abs(x) <= a ==> x <= a`) THEN ONCE_REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL [REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN REWRITE_TAC[REAL_ABS_POW] THEN MATCH_MP_TAC REAL_POW_LE2 THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[real_div; REAL_ABS_MUL; REAL_ABS_ABS] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e <= a ==> abs(p - a) <= e ==> b <= abs p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN SUBGOAL_THEN `abs(x) / pi < &1 / &3` ASSUME_TAC THENL [MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `&1 / pi` THEN ASM_SIMP_TAC[REAL_LE_DIV2_EQ; PI_POS] THEN REWRITE_TAC[real_div; REAL_MUL_LID] THEN MATCH_MP_TAC REAL_LT_INV2 THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e < a ==> abs(p - a) <= e ==> b < p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN SUBGOAL_THEN `~(abs(x) / pi = &1)` ASSUME_TAC THENL [UNDISCH_TAC `abs x / pi < &1 / &3` THEN ONCE_REWRITE_TAC[TAUT `a ==> ~b <=> b ==> ~a`] THEN SIMP_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN ASM_SIMP_TAC[GP_FINITE] THEN ONCE_REWRITE_TAC[REAL_ARITH `x - &1 = --(&1 - x)`] THEN REWRITE_TAC[real_div; REAL_INV_NEG; REAL_MUL_LNEG; REAL_MUL_RNEG] THEN REWRITE_TAC[REAL_NEG_NEG] THEN REWRITE_TAC[REAL_ABS_MUL] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL [MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ x <= &1 ==> abs(&1 - x) <= &1`) THEN SIMP_TAC[REAL_POW_LE; REAL_LE_MUL; REAL_LE_INV_EQ; REAL_ABS_POS; REAL_LT_IMP_LE; PI_POS] THEN MATCH_MP_TAC REAL_POW_1_LE THEN SIMP_TAC[REAL_LE_MUL; REAL_ABS_POS; REAL_LE_INV_EQ; REAL_LT_IMP_LE; PI_POS] THEN SIMP_TAC[GSYM real_div; REAL_LE_LDIV_EQ; PI_POS] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&1` THEN ASM_REWRITE_TAC[] THEN MP_TAC PI_APPROX_25_BITS THEN MATCH_MP_TAC(REAL_ARITH `b + e <= a ==> abs(p - a) <= e ==> b <= &1 * p`) THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_INV_INV] THEN REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[GSYM real_div] THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH `x < a ==> b <= &1 - a ==> b <= abs(&1 - x)`)) THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let TAYLOR_COT_BOUND = 
prove (`!x n k. abs(x) <= inv(&2 pow k) /\ ~(x = &0) ==> abs((&1 / x - cot x) - sum (0,n) (\m. (tannumber m / ((&2 pow (m+1) - &1) * &(FACT(m)))) * x pow m)) <= &4 / &3 pow n * inv(&2 pow (k * n))`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `abs(x) <= &1 /\ ~(x = &0)` MP_TAC THENL [ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `inv(&2 pow 0)`)) THEN REWRITE_TAC[REAL_POW2_THM; LE_0]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `n:num` o MATCH_MP TAYLOR_COT_BOUND_GENERAL) THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN REWRITE_TAC[real_div; REAL_POW_MUL; GSYM REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN REWRITE_TAC[GSYM REAL_POW_INV; GSYM REAL_POW_POW] THEN REWRITE_TAC[GSYM REAL_POW_MUL] THEN MATCH_MP_TAC REAL_POW_LE2 THEN SIMP_TAC[REAL_LE_MUL; REAL_LE_INV_EQ; REAL_POS; REAL_ABS_POS] THEN GEN_REWRITE_TAC LAND_CONV [REAL_MUL_SYM] THEN MATCH_MP_TAC REAL_LE_LMUL THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[real_div; REAL_MUL_LID; REAL_POW_INV]);;
let TAYLOR_COTX_BOUND = 
prove (`!x n k. abs(x) <= inv(&2 pow k) /\ ~(x = &0) ==> abs((&1 / x - cot x) / x - sum (0,n) (\m. (tannumber(m+1) / ((&2 pow (m+2) - &1) * &(FACT(m+1)))) * x pow m)) <= (&4 / &3) / &3 pow n * inv(&2 pow (k * n))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_RCANCEL_IMP THEN EXISTS_TAC `abs(x)` THEN ASM_SIMP_TAC[GSYM REAL_ABS_NZ] THEN REWRITE_TAC[GSYM REAL_ABS_MUL; REAL_SUB_RDISTRIB] THEN ASM_SIMP_TAC[REAL_DIV_RMUL] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [REAL_MUL_SYM] THEN REWRITE_TAC[GSYM SUM_CMUL] THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [AC REAL_MUL_AC `a * b * c = b * (a * c)`] THEN REWRITE_TAC[GSYM(CONJUNCT2 real_pow)] THEN REWRITE_TAC[ARITH_RULE `n + 2 = (n + 1) + 1`] THEN REWRITE_TAC[ADD1; SPECL [`f:num->real`; `n:num`; `1`] SUM_OFFSET] THEN REWRITE_TAC[SUM_1] THEN CONV_TAC(ONCE_DEPTH_CONV TANNUMBER_CONV) THEN CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[real_pow] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_SUB_RZERO] THEN REWRITE_TAC[GSYM REAL_SUB_RDISTRIB] THEN SUBGOAL_THEN `abs(x) <= &1 /\ ~(x = &0)` MP_TAC THENL [ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `inv(&2 pow 0)`)) THEN REWRITE_TAC[REAL_POW2_THM; LE_0]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `n + 1` o MATCH_MP TAYLOR_COT_BOUND_GENERAL) THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN REWRITE_TAC[REAL_POW_ADD; REAL_POW_1] THEN REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[AC REAL_MUL_AC `a * b * c * d = ((a * d) * b) * c`] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC; GSYM REAL_POW_MUL; GSYM REAL_INV_MUL] THEN REWRITE_TAC[GSYM REAL_POW_POW; GSYM REAL_POW_MUL] THEN REWRITE_TAC[REAL_INV_MUL; REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN MATCH_MP_TAC REAL_LE_LMUL THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[GSYM REAL_POW_INV] THEN MATCH_MP_TAC REAL_POW_LE2 THEN SIMP_TAC[REAL_LE_MUL; REAL_ABS_POS; REAL_LE_DIV; REAL_POS] THEN REWRITE_TAC[REAL_INV_MUL] THEN GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN MATCH_MP_TAC REAL_LE_RMUL THEN ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let TAYLOR_COTXX_BOUND = 
prove (`!x n k. abs(x) <= inv(&2 pow k) /\ ~(x = &0) ==> abs((&1 - x * cot(x)) - sum(0,n) (\m. (tannumber (m-1) / ((&2 pow m - &1) * &(FACT(m-1)))) * x pow m)) <= &12 / &3 pow n * inv(&2 pow (k * n))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_RCANCEL_IMP THEN EXISTS_TAC `abs(inv x)` THEN ASM_SIMP_TAC[GSYM REAL_ABS_NZ; REAL_INV_EQ_0] THEN REWRITE_TAC[GSYM REAL_ABS_MUL; REAL_SUB_RDISTRIB] THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o LAND_CONV o RAND_CONV) [AC REAL_MUL_AC `(a * b) * c = b * a * c`] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_MUL_RID] THEN REWRITE_TAC[GSYM real_div] THEN REWRITE_TAC[GSYM REAL_SUB_RDISTRIB] THEN SUBGOAL_THEN `abs(x) <= &1 /\ ~(x = &0)` MP_TAC THENL [ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN SUBST1_TAC(SYM(REAL_RAT_REDUCE_CONV `inv(&2 pow 0)`)) THEN REWRITE_TAC[REAL_POW2_THM; LE_0]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `n - 1` o MATCH_MP TAYLOR_COT_BOUND_GENERAL) THEN ASM_CASES_TAC `n = 0` THENL [ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[sum] THEN REWRITE_TAC[real_pow; real_div; REAL_MUL_LZERO; REAL_SUB_RZERO] THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN REWRITE_TAC[real_div; REAL_MUL_ASSOC; MULT_CLAUSES; REAL_INV_MUL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN SIMP_TAC[GSYM REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_INV_DIV] THEN REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN ASM_REWRITE_TAC[GSYM REAL_ABS_NZ] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow 0)` THEN REWRITE_TAC[REAL_POW2_THM; LE_0] THEN CONV_TAC REAL_RAT_REDUCE_CONV; ALL_TAC] THEN SUBGOAL_THEN `n = (n - 1) + 1` MP_TAC THENL [UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC; ALL_TAC] THEN DISCH_THEN(fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [th]) THEN REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_EQ_SUB_LADD] SUM_OFFSET)] THEN REWRITE_TAC[SUB_0; ADD_SUB; SUM_1] THEN SIMP_TAC[TANNUMBER_EVEN; EVEN] THEN REWRITE_TAC[real_div; REAL_MUL_LZERO; REAL_ADD_RID] THEN GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o RAND_CONV o RAND_CONV) [REAL_MUL_SYM] THEN REWRITE_TAC[GSYM SUM_CMUL] THEN GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o RAND_CONV o ONCE_DEPTH_CONV) [REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC(REAL_ARITH `(s1 = s2) /\ a <= b ==> s1 <= a ==> s2 <= b`) THEN CONJ_TAC THENL [AP_TERM_TAC THEN REWRITE_TAC[real_div; REAL_MUL_LID; REAL_MUL_RID] THEN AP_TERM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN GEN_TAC THEN REWRITE_TAC[REAL_POW_ADD; REAL_POW_1; GSYM REAL_MUL_ASSOC] THEN REPEAT AP_TERM_TAC THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_MUL_RID]; ALL_TAC] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN REWRITE_TAC[REAL_POW_ADD; REAL_INV_MUL; REAL_MUL_ASSOC; real_div] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_POS] THEN REWRITE_TAC[real_div; REAL_MUL_LID] THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [REAL_MUL_SYM] THEN REWRITE_TAC[REAL_POW_MUL; REAL_POW_INV] THEN MATCH_MP_TAC REAL_LE_LMUL THEN SIMP_TAC[REAL_LE_INV_EQ; REAL_POW_LE; REAL_POS] THEN REWRITE_TAC[REAL_ABS_INV; GSYM real_div] THEN ASM_SIMP_TAC[REAL_LE_RDIV_EQ; GSYM REAL_ABS_NZ] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM(CONJUNCT2 real_pow)] THEN REWRITE_TAC[GSYM REAL_POW_POW] THEN REWRITE_TAC[GSYM REAL_POW_INV] THEN REWRITE_TAC[ONCE_REWRITE_RULE[ADD_SYM] ADD1] THEN MATCH_MP_TAC REAL_POW_LE2 THEN ASM_REWRITE_TAC[REAL_ABS_POS; REAL_POW_INV]);;
let TAYLOR_COTXX_SQRT_BOUND = 
prove (`!x n k. abs(x) <= inv(&2 pow k) /\ &0 < x ==> abs((&1 - sqrt(x) * cot(sqrt(x))) - sum(0,n) (\m. (tannumber (2*m-1) / ((&2 pow (2*m) - &1) * &(FACT(2*m-1)))) * x pow m)) <= &12 / &3 pow (2 * n) * inv(&2 pow (k DIV 2 * 2 * n))`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`sqrt x`; `2 * n`; `k DIV 2`] TAYLOR_COTXX_BOUND) THEN W(C SUBGOAL_THEN (fun th -> REWRITE_TAC[th]) o funpow 2 lhand o snd) THENL [ASM_SIMP_TAC[SQRT_POS_LT; REAL_LT_IMP_NZ; DIV_EQ_0; ARITH_EQ; NOT_LT] THEN SUBGOAL_THEN `&2 pow (k DIV 2) = sqrt(&2 pow (2 * (k DIV 2)))` SUBST1_TAC THENL [SIMP_TAC[SQRT_EVEN_POW2; EVEN_MULT; ARITH_EVEN; DIV_MULT; ARITH_EQ]; ALL_TAC] THEN ASM_SIMP_TAC[GSYM SQRT_INV; REAL_LT_IMP_LE; REAL_POW2_CLAUSES] THEN ASM_SIMP_TAC[real_abs; SQRT_POS_LT; REAL_LT_IMP_LE] THEN MATCH_MP_TAC SQRT_MONO_LE THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN MATCH_MP_TAC(REAL_ARITH `abs(x) <= a ==> x <= a`) THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&2 pow k)` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN SIMP_TAC[REAL_POW2_CLAUSES] THEN MATCH_MP_TAC REAL_POW_MONO THEN REWRITE_TAC[REAL_OF_NUM_LE; ARITH] THEN MESON_TAC[LE_ADD; DIVISION; NUM_EQ_CONV `2 = 0`; MULT_SYM]; ALL_TAC] THEN MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[GSYM MULT_ASSOC] THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN ONCE_REWRITE_TAC[MULT_SYM] THEN REWRITE_TAC[GSYM SUM_GROUP] THEN SUBGOAL_THEN `!n. EVEN(((n * 2) + 1) - 1)` ASSUME_TAC THENL [INDUCT_TAC THEN REWRITE_TAC[ADD_CLAUSES; SUC_SUB1; SUB_0; MULT_CLAUSES; SUB_REFL; ADD_SUB] THEN REWRITE_TAC[EVEN_ADD; EVEN_MULT; ARITH]; ALL_TAC] THEN ASM_SIMP_TAC[SUM_2; TANNUMBER_EVEN; ARITH_EVEN; EVEN_ADD; EVEN_MULT] THEN REWRITE_TAC[real_div; REAL_MUL_LZERO; REAL_ADD_RID] THEN ONCE_REWRITE_TAC[MULT_SYM] THEN ASM_SIMP_TAC[GSYM REAL_POW_POW; SQRT_POW_2; REAL_LT_IMP_LE]);;