(* ========================================================================= *)
(* Some analytic concepts for R instead of R^1.                              *)
(*                                                                           *)
(*              (c) Copyright, John Harrison 1998-2008                       *)
(* ========================================================================= *)

needs "Library/binomial.ml";;
needs "Multivariate/measure.ml";;
needs "Multivariate/polytope.ml";;
needs "Multivariate/transcendentals.ml";;

(* ------------------------------------------------------------------------- *)
(* Open-ness and closedness of a set of reals.                               *)
(* ------------------------------------------------------------------------- *)

let real_open = new_definition
  `real_open s <=>
      !x. x IN s ==> ?e. &0 < e /\ !x'. abs(x' - x) < e ==> x' IN s`;;
let real_closed = new_definition
 `real_closed s <=> real_open((:real) DIFF s)`;;
let euclideanreal = new_definition
 `euclideanreal = topology real_open`;;
let REAL_OPEN_EMPTY = 
prove (`real_open {}`,
REWRITE_TAC[real_open; NOT_IN_EMPTY]);;
let REAL_OPEN_UNIV = 
prove (`real_open(:real)`,
REWRITE_TAC[real_open; IN_UNIV] THEN MESON_TAC[REAL_LT_01]);;
let REAL_OPEN_INTER = 
prove (`!s t. real_open s /\ real_open t ==> real_open (s INTER t)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_open; AND_FORALL_THM; IN_INTER] THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `d1:real`) (X_CHOOSE_TAC `d2:real`)) THEN MP_TAC(SPECL [`d1:real`; `d2:real`] REAL_DOWN2) THEN ASM_MESON_TAC[REAL_LT_TRANS]);;
let REAL_OPEN_UNIONS = 
prove (`(!s. s IN f ==> real_open s) ==> real_open(UNIONS f)`,
REWRITE_TAC[real_open; IN_UNIONS] THEN MESON_TAC[]);;
let REAL_OPEN_IN = 
prove (`!s. real_open s <=> open_in euclideanreal s`,
GEN_TAC THEN REWRITE_TAC[euclideanreal] THEN CONV_TAC SYM_CONV THEN AP_THM_TAC THEN REWRITE_TAC[GSYM(CONJUNCT2 topology_tybij)] THEN REWRITE_TAC[REWRITE_RULE[IN] istopology] THEN REWRITE_TAC[REAL_OPEN_EMPTY; REAL_OPEN_INTER; SUBSET] THEN MESON_TAC[IN; REAL_OPEN_UNIONS]);;
let TOPSPACE_EUCLIDEANREAL = 
prove (`topspace euclideanreal = (:real)`,
let TOPSPACE_EUCLIDEANREAL_SUBTOPOLOGY = 
prove (`!s. topspace (subtopology euclideanreal s) = s`,
let REAL_CLOSED_IN = 
prove (`!s. real_closed s <=> closed_in euclideanreal s`,
let REAL_OPEN_UNION = 
prove (`!s t. real_open s /\ real_open t ==> real_open(s UNION t)`,
REWRITE_TAC[REAL_OPEN_IN; OPEN_IN_UNION]);;
let REAL_OPEN_SUBREAL_OPEN = 
prove (`!s. real_open s <=> !x. x IN s ==> ?t. real_open t /\ x IN t /\ t SUBSET s`,
REWRITE_TAC[REAL_OPEN_IN; GSYM OPEN_IN_SUBOPEN]);;
let REAL_CLOSED_EMPTY = 
prove (`real_closed {}`,
let REAL_CLOSED_UNIV = 
prove (`real_closed(:real)`,
let REAL_CLOSED_UNION = 
prove (`!s t. real_closed s /\ real_closed t ==> real_closed(s UNION t)`,
let REAL_CLOSED_INTER = 
prove (`!s t. real_closed s /\ real_closed t ==> real_closed(s INTER t)`,
let REAL_CLOSED_INTERS = 
prove (`!f. (!s. s IN f ==> real_closed s) ==> real_closed(INTERS f)`,
REWRITE_TAC[REAL_CLOSED_IN] THEN REPEAT STRIP_TAC THEN ASM_CASES_TAC `f:(real->bool)->bool = {}` THEN ASM_SIMP_TAC[CLOSED_IN_INTERS; INTERS_0] THEN REWRITE_TAC[GSYM TOPSPACE_EUCLIDEANREAL; CLOSED_IN_TOPSPACE]);;
let REAL_OPEN_REAL_CLOSED = 
prove (`!s. real_open s <=> real_closed(UNIV DIFF s)`,
let REAL_OPEN_DIFF = 
prove (`!s t. real_open s /\ real_closed t ==> real_open(s DIFF t)`,
let REAL_CLOSED_DIFF = 
prove (`!s t. real_closed s /\ real_open t ==> real_closed(s DIFF t)`,
let REAL_OPEN_INTERS = 
prove (`!s. FINITE s /\ (!t. t IN s ==> real_open t) ==> real_open(INTERS s)`,
REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN REWRITE_TAC[INTERS_INSERT; INTERS_0; REAL_OPEN_UNIV; IN_INSERT] THEN MESON_TAC[REAL_OPEN_INTER]);;
let REAL_CLOSED_UNIONS = 
prove (`!s. FINITE s /\ (!t. t IN s ==> real_closed t) ==> real_closed(UNIONS s)`,
REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN REWRITE_TAC[UNIONS_INSERT; UNIONS_0; REAL_CLOSED_EMPTY; IN_INSERT] THEN MESON_TAC[REAL_CLOSED_UNION]);;
let REAL_OPEN = 
prove (`!s. real_open s <=> open(IMAGE lift s)`,
let REAL_CLOSED = 
prove (`!s. real_closed s <=> closed(IMAGE lift s)`,
GEN_TAC THEN REWRITE_TAC[real_closed; REAL_OPEN; closed] THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_DIFF; IN_UNIV] THEN MESON_TAC[LIFT_DROP]);;
let REAL_CLOSED_HALFSPACE_LE = 
prove (`!a. real_closed {x | x <= a}`,
GEN_TAC THEN SUBGOAL_THEN `closed {x | drop x <= a}` MP_TAC THENL [REWRITE_TAC[drop; CLOSED_HALFSPACE_COMPONENT_LE]; ALL_TAC] THEN MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[REAL_CLOSED] THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM] THEN MESON_TAC[LIFT_DROP]);;
let REAL_CLOSED_HALFSPACE_GE = 
prove (`!a. real_closed {x | x >= a}`,
GEN_TAC THEN SUBGOAL_THEN `closed {x | drop x >= a}` MP_TAC THENL [REWRITE_TAC[drop; CLOSED_HALFSPACE_COMPONENT_GE]; ALL_TAC] THEN MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[REAL_CLOSED] THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM] THEN MESON_TAC[LIFT_DROP]);;
let REAL_OPEN_HALFSPACE_LT = 
prove (`!a. real_open {x | x < a}`,
GEN_TAC THEN SUBGOAL_THEN `open {x | drop x < a}` MP_TAC THENL [REWRITE_TAC[drop; OPEN_HALFSPACE_COMPONENT_LT]; ALL_TAC] THEN MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[REAL_OPEN] THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM] THEN MESON_TAC[LIFT_DROP]);;
let REAL_OPEN_HALFSPACE_GT = 
prove (`!a. real_open {x | x > a}`,
GEN_TAC THEN SUBGOAL_THEN `open {x | drop x > a}` MP_TAC THENL [REWRITE_TAC[drop; OPEN_HALFSPACE_COMPONENT_GT]; ALL_TAC] THEN MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[REAL_OPEN] THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM] THEN MESON_TAC[LIFT_DROP]);;
(* ------------------------------------------------------------------------- *) (* Compactness of a set of reals. *) (* ------------------------------------------------------------------------- *)
let real_bounded = new_definition
 `real_bounded s <=> ?B. !x. x IN s ==> abs(x) <= B`;;
let REAL_BOUNDED = 
prove (`real_bounded s <=> bounded(IMAGE lift s)`,
REWRITE_TAC[BOUNDED_LIFT; real_bounded]);;
let REAL_BOUNDED_POS = 
prove (`!s. real_bounded s <=> ?B. &0 < B /\ !x. x IN s ==> abs(x) <= B`,
REWRITE_TAC[real_bounded] THEN MESON_TAC[REAL_ARITH `&0 < &1 + abs B /\ (x <= B ==> x <= &1 + abs B)`]);;
let REAL_BOUNDED_POS_LT = 
prove (`!s. real_bounded s <=> ?b. &0 < b /\ !x. x IN s ==> abs(x) < b`,
REWRITE_TAC[real_bounded] THEN MESON_TAC[REAL_LT_IMP_LE; REAL_ARITH `&0 < &1 + abs(y) /\ (x <= y ==> x < &1 + abs(y))`]);;
let REAL_BOUNDED_SUBSET = 
prove (`!s t. real_bounded t /\ s SUBSET t ==> real_bounded s`,
let REAL_BOUNDED_UNION = 
prove (`!s t. real_bounded(s UNION t) <=> real_bounded s /\ real_bounded t`,
let real_compact = new_definition
 `real_compact s <=> compact(IMAGE lift s)`;;
let REAL_COMPACT_IMP_BOUNDED = 
prove (`!s. real_compact s ==> real_bounded s`,
let REAL_COMPACT_IMP_CLOSED = 
prove (`!s. real_compact s ==> real_closed s`,
let REAL_COMPACT_EQ_BOUNDED_CLOSED = 
prove (`!s. real_compact s <=> real_bounded s /\ real_closed s`,
REWRITE_TAC[real_compact; REAL_BOUNDED; REAL_CLOSED] THEN REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED]);;
let REAL_COMPACT_UNION = 
prove (`!s t. real_compact s /\ real_compact t ==> real_compact(s UNION t)`,
let REAL_COMPACT_ATTAINS_INF = 
prove (`!s. real_compact s /\ ~(s = {}) ==> ?x. x IN s /\ !y. y IN s ==> x <= y`,
let REAL_COMPACT_ATTAINS_SUP = 
prove (`!s. real_compact s /\ ~(s = {}) ==> ?x. x IN s /\ !y. y IN s ==> y <= x`,
(* ------------------------------------------------------------------------- *) (* Limits of functions with real range. *) (* ------------------------------------------------------------------------- *) parse_as_infix("--->",(12,"right"));;
let tendsto_real = new_definition
  `(f ---> l) net <=> !e. &0 < e ==> eventually (\x. abs(f(x) - l) < e) net`;;
let reallim = new_definition
 `reallim net f = @l. (f ---> l) net`;;
let TENDSTO_REAL = 
prove (`(s ---> l) = ((lift o s) --> lift l)`,
let REAL_TENDSTO = 
prove (`(s --> l) = (drop o s ---> drop l)`,
REWRITE_TAC[TENDSTO_REAL; o_DEF; LIFT_DROP; ETA_AX]);;
let REALLIM_COMPLEX = 
prove (`(s ---> l) = ((Cx o s) --> Cx(l))`,
let REALLIM_UNIQUE = 
prove (`!net f l l'. ~trivial_limit net /\ (f ---> l) net /\ (f ---> l') net ==> l = l'`,
REPEAT GEN_TAC THEN REWRITE_TAC[TENDSTO_REAL] THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_UNIQUE) THEN REWRITE_TAC[LIFT_EQ]);;
let REALLIM_CONST = 
prove (`!net a. ((\x. a) ---> a) net`,
REWRITE_TAC[TENDSTO_REAL; o_DEF; LIM_CONST]);;
let REALLIM_LMUL = 
prove (`!f l c. (f ---> l) net ==> ((\x. c * f x) ---> c * l) net`,
REWRITE_TAC[TENDSTO_REAL; o_DEF; LIFT_CMUL; LIM_CMUL]);;
let REALLIM_RMUL = 
prove (`!f l c. (f ---> l) net ==> ((\x. f x * c) ---> l * c) net`,
ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REALLIM_LMUL]);;
let REALLIM_LMUL_EQ = 
prove (`!net f l c. ~(c = &0) ==> (((\x. c * f x) ---> c * l) net <=> (f ---> l) net)`,
REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[REALLIM_LMUL] THEN DISCH_THEN(MP_TAC o SPEC `inv c:real` o MATCH_MP REALLIM_LMUL) THEN ASM_SIMP_TAC[REAL_MUL_ASSOC; REAL_MUL_LINV; REAL_MUL_LID; ETA_AX]);;
let REALLIM_RMUL_EQ = 
prove (`!net f l c. ~(c = &0) ==> (((\x. f x * c) ---> l * c) net <=> (f ---> l) net)`,
ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REALLIM_LMUL_EQ]);;
let REALLIM_NEG = 
prove (`!net f l. (f ---> l) net ==> ((\x. --(f x)) ---> --l) net`,
REWRITE_TAC[TENDSTO_REAL; o_DEF; LIFT_NEG; LIM_NEG]);;
let REALLIM_NEG_EQ = 
prove (`!net f l. ((\x. --(f x)) ---> --l) net <=> (f ---> l) net`,
let REALLIM_ADD = 
prove (`!net:(A)net f g l m. (f ---> l) net /\ (g ---> m) net ==> ((\x. f(x) + g(x)) ---> l + m) net`,
REWRITE_TAC[TENDSTO_REAL; o_DEF; LIFT_ADD; LIM_ADD]);;
let REALLIM_SUB = 
prove (`!net:(A)net f g l m. (f ---> l) net /\ (g ---> m) net ==> ((\x. f(x) - g(x)) ---> l - m) net`,
REWRITE_TAC[TENDSTO_REAL; o_DEF; LIFT_SUB; LIM_SUB]);;
let REALLIM_MUL = 
prove (`!net:(A)net f g l m. (f ---> l) net /\ (g ---> m) net ==> ((\x. f(x) * g(x)) ---> l * m) net`,
let REALLIM_INV = 
prove (`!net f l. (f ---> l) net /\ ~(l = &0) ==> ((\x. inv(f x)) ---> inv l) net`,
let REALLIM_DIV = 
prove (`!net:(A)net f g l m. (f ---> l) net /\ (g ---> m) net /\ ~(m = &0) ==> ((\x. f(x) / g(x)) ---> l / m) net`,
let REALLIM_ABS = 
prove (`!net f l. (f ---> l) net ==> ((\x. abs(f x)) ---> abs l) net`,
REPEAT GEN_TAC THEN REWRITE_TAC[tendsto_real] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN REWRITE_TAC[] THEN REAL_ARITH_TAC);;
let REALLIM_POW = 
prove (`!net f l n. (f ---> l) net ==> ((\x. f x pow n) ---> l pow n) net`,
REPLICATE_TAC 3 GEN_TAC THEN INDUCT_TAC THEN ASM_SIMP_TAC[real_pow; REALLIM_CONST; REALLIM_MUL]);;
let REALLIM_MAX = 
prove (`!net:(A)net f g l m. (f ---> l) net /\ (g ---> m) net ==> ((\x. max (f x) (g x)) ---> max l m) net`,
REWRITE_TAC[REAL_ARITH `max x y = inv(&2) * ((x + y) + abs(x - y))`] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REALLIM_LMUL THEN ASM_SIMP_TAC[REALLIM_ADD; REALLIM_ABS; REALLIM_SUB]);;
let REALLIM_MIN = 
prove (`!net:(A)net f g l m. (f ---> l) net /\ (g ---> m) net ==> ((\x. min (f x) (g x)) ---> min l m) net`,
REWRITE_TAC[REAL_ARITH `min x y = inv(&2) * ((x + y) - abs(x - y))`] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REALLIM_LMUL THEN ASM_SIMP_TAC[REALLIM_ADD; REALLIM_ABS; REALLIM_SUB]);;
let REALLIM_NULL = 
prove (`!net f l. (f ---> l) net <=> ((\x. f(x) - l) ---> &0) net`,
REWRITE_TAC[tendsto_real; REAL_SUB_RZERO]);;
let REALLIM_NULL_ADD = 
prove (`!net:(A)net f g. (f ---> &0) net /\ (g ---> &0) net ==> ((\x. f(x) + g(x)) ---> &0) net`,
REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP REALLIM_ADD) THEN REWRITE_TAC[REAL_ADD_LID]);;
let REALLIM_NULL_LMUL = 
prove (`!net f c. (f ---> &0) net ==> ((\x. c * f x) ---> &0) net`,
REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o SPEC `c:real` o MATCH_MP REALLIM_LMUL) THEN REWRITE_TAC[REAL_MUL_RZERO]);;
let REALLIM_NULL_RMUL = 
prove (`!net f c. (f ---> &0) net ==> ((\x. f x * c) ---> &0) net`,
REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o SPEC `c:real` o MATCH_MP REALLIM_RMUL) THEN REWRITE_TAC[REAL_MUL_LZERO]);;
let REALLIM_NULL_POW = 
prove (`!net f n. (f ---> &0) net /\ ~(n = 0) ==> ((\x. f x pow n) ---> &0) net`,
REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o SPEC `n:num` o MATCH_MP REALLIM_POW) ASSUME_TAC) THEN ASM_REWRITE_TAC[REAL_POW_ZERO]);;
let REALLIM_NULL_LMUL_EQ = 
prove (`!net f c. ~(c = &0) ==> (((\x. c * f x) ---> &0) net <=> (f ---> &0) net)`,
let REALLIM_NULL_RMUL_EQ = 
prove (`!net f c. ~(c = &0) ==> (((\x. f x * c) ---> &0) net <=> (f ---> &0) net)`,
let REALLIM_RE = 
prove (`!net f l. (f --> l) net ==> ((Re o f) ---> Re l) net`,
REWRITE_TAC[REALLIM_COMPLEX] THEN REWRITE_TAC[tendsto; dist; o_THM; GSYM CX_SUB; COMPLEX_NORM_CX] THEN REWRITE_TAC[GSYM RE_SUB; eventually] THEN MESON_TAC[REAL_LET_TRANS; COMPLEX_NORM_GE_RE_IM]);;
let REALLIM_IM = 
prove (`!net f l. (f --> l) net ==> ((Im o f) ---> Im l) net`,
REWRITE_TAC[REALLIM_COMPLEX] THEN REWRITE_TAC[tendsto; dist; o_THM; GSYM CX_SUB; COMPLEX_NORM_CX] THEN REWRITE_TAC[GSYM IM_SUB; eventually] THEN MESON_TAC[REAL_LET_TRANS; COMPLEX_NORM_GE_RE_IM]);;
let REALLIM_TRANSFORM_EVENTUALLY = 
prove (`!net f g l. eventually (\x. f x = g x) net /\ (f ---> l) net ==> (g ---> l) net`,
REPEAT GEN_TAC THEN REWRITE_TAC[TENDSTO_REAL] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN POP_ASSUM MP_TAC THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN SIMP_TAC[o_THM]);;
let REALLIM_TRANSFORM = 
prove (`!net f g l. ((\x. f x - g x) ---> &0) net /\ (f ---> l) net ==> (g ---> l) net`,
REPEAT GEN_TAC THEN REWRITE_TAC[TENDSTO_REAL] THEN REWRITE_TAC[o_DEF; LIFT_NUM; LIFT_SUB; LIM_TRANSFORM]);;
let REALLIM_TRANSFORM_EQ = 
prove (`!net f:A->real g l. ((\x. f x - g x) ---> &0) net ==> ((f ---> l) net <=> (g ---> l) net)`,
REPEAT GEN_TAC THEN REWRITE_TAC[TENDSTO_REAL] THEN REWRITE_TAC[o_DEF; LIFT_NUM; LIFT_SUB; LIM_TRANSFORM_EQ]);;
let REAL_SEQ_OFFSET = 
prove (`!f l k. (f ---> l) sequentially ==> ((\i. f (i + k)) ---> l) sequentially`,
REPEAT GEN_TAC THEN SIMP_TAC[TENDSTO_REAL; o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP SEQ_OFFSET) THEN SIMP_TAC[]);;
let REAL_SEQ_OFFSET_REV = 
prove (`!f l k. ((\i. f (i + k)) ---> l) sequentially ==> (f ---> l) sequentially`,
SIMP_TAC[TENDSTO_REAL; o_DEF] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SEQ_OFFSET_REV THEN EXISTS_TAC `k:num` THEN ASM_SIMP_TAC[]);;
let REALLIM_TRANSFORM_STRADDLE = 
prove (`!f g h a. eventually (\n. f(n) <= g(n)) net /\ (f ---> a) net /\ eventually (\n. g(n) <= h(n)) net /\ (h ---> a) net ==> (g ---> a) net`,
REPEAT GEN_TAC THEN REWRITE_TAC[RIGHT_AND_FORALL_THM; tendsto_real; AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM EVENTUALLY_AND] THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN REAL_ARITH_TAC);;
let REALLIM_TRANSFORM_BOUND = 
prove (`!f g. eventually (\n. abs(f n) <= g n) net /\ (g ---> &0) net ==> (f ---> &0) net`,
REPEAT GEN_TAC THEN REWRITE_TAC[RIGHT_AND_FORALL_THM; tendsto_real; AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM EVENTUALLY_AND] THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN REAL_ARITH_TAC);;
let REAL_CONVERGENT_IMP_BOUNDED = 
prove (`!s l. (s ---> l) sequentially ==> real_bounded (IMAGE s (:num))`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_BOUNDED; TENDSTO_REAL] THEN DISCH_THEN(MP_TAC o MATCH_MP CONVERGENT_IMP_BOUNDED) THEN REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE; IN_UNIV] THEN REWRITE_TAC[o_DEF; NORM_LIFT]);;
let REALLIM = 
prove (`(f ---> l) net <=> trivial_limit net \/ !e. &0 < e ==> ?y. (?x. netord(net) x y) /\ !x. netord(net) x y ==> abs(f(x) -l) < e`,
REWRITE_TAC[tendsto_real; eventually] THEN MESON_TAC[]);;
let REALLIM_NULL_ABS = 
prove (`!net f. ((\x. abs(f x)) ---> &0) net <=> (f ---> &0) net`,
let REALLIM_WITHIN_LE = 
prove (`!f:real^N->real l a s. (f ---> l) (at a within s) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) <= d ==> abs(f(x) - l) < e`,
let REALLIM_WITHIN = 
prove (`!f:real^N->real l a s. (f ---> l) (at a within s) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) < d ==> abs(f(x) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_WITHIN] THEN MESON_TAC[]);;
let REALLIM_AT = 
prove (`!f l a:real^N. (f ---> l) (at a) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. &0 < dist(x,a) /\ dist(x,a) < d ==> abs(f(x) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_AT] THEN MESON_TAC[]);;
let REALLIM_AT_INFINITY = 
prove (`!f l. (f ---> l) at_infinity <=> !e. &0 < e ==> ?b. !x. norm(x) >= b ==> abs(f(x) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_AT_INFINITY] THEN MESON_TAC[]);;
let REALLIM_SEQUENTIALLY = 
prove (`!s l. (s ---> l) sequentially <=> !e. &0 < e ==> ?N. !n. N <= n ==> abs(s(n) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_SEQUENTIALLY] THEN MESON_TAC[]);;
let REALLIM_EVENTUALLY = 
prove (`!net f l. eventually (\x. f x = l) net ==> (f ---> l) net`,
REWRITE_TAC[eventually; REALLIM] THEN MESON_TAC[REAL_ARITH `abs(x - x) = &0`]);;
let LIM_COMPONENTWISE = 
prove (`!net f:A->real^N. (f --> l) net <=> !i. 1 <= i /\ i <= dimindex(:N) ==> ((\x. (f x)$i) ---> l$i) net`,
ONCE_REWRITE_TAC[LIM_COMPONENTWISE_LIFT] THEN REWRITE_TAC[TENDSTO_REAL; o_DEF]);;
let REALLIM_UBOUND = 
prove (`!(net:A net) f l b. (f ---> l) net /\ ~trivial_limit net /\ eventually (\x. f x <= b) net ==> l <= b`,
REWRITE_TAC[FORALL_DROP; TENDSTO_REAL; LIFT_DROP] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC(ISPEC `net:A net` LIM_DROP_UBOUND) THEN EXISTS_TAC `lift o (f:A->real)` THEN ASM_REWRITE_TAC[o_THM; LIFT_DROP]);;
let REALLIM_LBOUND = 
prove (`!(net:A net) f l b. (f ---> l) net /\ ~trivial_limit net /\ eventually (\x. b <= f x) net ==> b <= l`,
ONCE_REWRITE_TAC[GSYM REAL_LE_NEG2] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC(ISPEC `net:A net` REALLIM_UBOUND) THEN EXISTS_TAC `\a:A. --(f a:real)` THEN ASM_REWRITE_TAC[REALLIM_NEG_EQ]);;
let REALLIM_LE = 
prove (`!net f g l m. (f ---> l) net /\ (g ---> m) net /\ ~trivial_limit net /\ eventually (\x. f x <= g x) net ==> l <= m`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[CONJ_ASSOC] THEN DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o MATCH_MP REALLIM_SUB o ONCE_REWRITE_RULE[CONJ_SYM]) MP_TAC) THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LE] THEN REWRITE_TAC[GSYM IMP_CONJ_ALT; GSYM CONJ_ASSOC] THEN DISCH_THEN(ACCEPT_TAC o MATCH_MP REALLIM_LBOUND));;
let REALLIM_CONST_EQ = 
prove (`!net:(A net) c d. ((\x. c) ---> d) net <=> trivial_limit net \/ c = d`,
let REALLIM_SUM = 
prove (`!f:A->B->real s. FINITE s /\ (!i. i IN s ==> ((f i) ---> (l i)) net) ==> ((\x. sum s (\i. f i x)) ---> sum s l) net`,
GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[SUM_CLAUSES; REALLIM_CONST; REALLIM_ADD; IN_INSERT; ETA_AX]);;
let REALLIM_NULL_COMPARISON = 
prove (`!net:(A)net f g. eventually (\x. abs(f x) <= g x) net /\ (g ---> &0) net ==> (f ---> &0) net`,
REWRITE_TAC[TENDSTO_REAL; LIFT_NUM; o_DEF] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_NULL_COMPARISON THEN EXISTS_TAC `g:A->real` THEN ASM_REWRITE_TAC[NORM_LIFT]);;
(* ------------------------------------------------------------------------- *) (* Real series. *) (* ------------------------------------------------------------------------- *) parse_as_infix("real_sums",(12,"right"));;
let real_sums = new_definition
 `(f real_sums l) s <=> ((\n. sum (s INTER (0..n)) f) ---> l) sequentially`;;
let real_infsum = new_definition
 `real_infsum s f = @l. (f real_sums l) s`;;
let real_summable = new_definition
 `real_summable s f = ?l. (f real_sums l) s`;;
let REAL_SUMS = 
prove (`(f real_sums l) = ((lift o f) sums (lift l))`,
let REAL_SUMS_RE = 
prove (`!f l s. (f sums l) s ==> ((Re o f) real_sums (Re l)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_sums; sums] THEN DISCH_THEN(MP_TAC o MATCH_MP REALLIM_RE) THEN SIMP_TAC[o_DEF; RE_VSUM; FINITE_INTER_NUMSEG]);;
let REAL_SUMS_IM = 
prove (`!f l s. (f sums l) s ==> ((Im o f) real_sums (Im l)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_sums; sums] THEN DISCH_THEN(MP_TAC o MATCH_MP REALLIM_IM) THEN SIMP_TAC[o_DEF; IM_VSUM; FINITE_INTER_NUMSEG]);;
let REAL_SUMS_COMPLEX = 
prove (`!f l s. (f real_sums l) s <=> ((Cx o f) sums (Cx l)) s`,
let REAL_SUMMABLE = 
prove (`real_summable s f <=> summable s (lift o f)`,
REWRITE_TAC[real_summable; summable; REAL_SUMS; GSYM EXISTS_LIFT]);;
let REAL_SUMMABLE_COMPLEX = 
prove (`real_summable s f <=> summable s (Cx o f)`,
REWRITE_TAC[real_summable; summable; REAL_SUMS_COMPLEX] THEN EQ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_TAC `l:complex`) THEN EXISTS_TAC `Re l` THEN SUBGOAL_THEN `Cx(Re l) = l` (fun th -> ASM_REWRITE_TAC[th]) THEN REWRITE_TAC[GSYM REAL] THEN MATCH_MP_TAC REAL_SERIES THEN MAP_EVERY EXISTS_TAC [`Cx o (f:num->real)`; `s:num->bool`] THEN ASM_REWRITE_TAC[o_THM; REAL_CX]);;
let REAL_SERIES_CAUCHY = 
prove (`(?l. (f real_sums l) s) <=> (!e. &0 < e ==> ?N. !m n. m >= N ==> abs(sum(s INTER (m..n)) f) < e)`,
REWRITE_TAC[REAL_SUMS; SERIES_CAUCHY; GSYM EXISTS_LIFT] THEN SIMP_TAC[NORM_REAL; GSYM drop; DROP_VSUM; FINITE_INTER_NUMSEG] THEN REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX]);;
let REAL_SUMS_SUMMABLE = 
prove (`!f l s. (f real_sums l) s ==> real_summable s f`,
REWRITE_TAC[real_summable] THEN MESON_TAC[]);;
let REAL_SUMS_INFSUM = 
prove (`!f s. (f real_sums (real_infsum s f)) s <=> real_summable s f`,
REWRITE_TAC[real_infsum; real_summable] THEN MESON_TAC[]);;
let REAL_INFSUM_COMPLEX = 
prove (`!f s. real_summable s f ==> real_infsum s f = Re(infsum s (Cx o f))`,
REPEAT GEN_TAC THEN REWRITE_TAC[GSYM REAL_SUMS_INFSUM; REAL_SUMS_COMPLEX] THEN DISCH_THEN(MP_TAC o MATCH_MP INFSUM_UNIQUE) THEN MESON_TAC[RE_CX]);;
let REAL_SERIES_FROM = 
prove (`!f l k. (f real_sums l) (from k) = ((\n. sum(k..n) f) ---> l) sequentially`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_sums] THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; numseg; from; IN_ELIM_THM; IN_INTER] THEN ARITH_TAC);;
let REAL_SERIES_UNIQUE = 
prove (`!f l l' s. (f real_sums l) s /\ (f real_sums l') s ==> l = l'`,
REWRITE_TAC[real_sums] THEN MESON_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; REALLIM_UNIQUE]);;
let REAL_INFSUM_UNIQUE = 
prove (`!f l s. (f real_sums l) s ==> real_infsum s f = l`,
let REAL_SERIES_FINITE = 
prove (`!f s. FINITE s ==> (f real_sums (sum s f)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[num_FINITE; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `n:num` THEN REWRITE_TAC[real_sums; REALLIM_SEQUENTIALLY] THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `n:num` THEN X_GEN_TAC `m:num` THEN DISCH_TAC THEN SUBGOAL_THEN `s INTER (0..m) = s` (fun th -> ASM_REWRITE_TAC[th; REAL_SUB_REFL; REAL_ABS_NUM]) THEN REWRITE_TAC[EXTENSION; IN_INTER; IN_NUMSEG; LE_0] THEN ASM_MESON_TAC[LE_TRANS]);;
let REAL_SUMMABLE_IFF_EVENTUALLY = 
prove (`!f g k. (?N. !n. N <= n /\ n IN k ==> f n = g n) ==> (real_summable k f <=> real_summable k g)`,
REWRITE_TAC[REAL_SUMMABLE] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMMABLE_IFF_EVENTUALLY THEN REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[]);;
let REAL_SUMMABLE_EQ_EVENTUALLY = 
prove (`!f g k. (?N. !n. N <= n /\ n IN k ==> f n = g n) /\ real_summable k f ==> real_summable k g`,
let REAL_SUMMABLE_IFF_COFINITE = 
prove (`!f s t. FINITE((s DIFF t) UNION (t DIFF s)) ==> (real_summable s f <=> real_summable t f)`,
SIMP_TAC[REAL_SUMMABLE] THEN MESON_TAC[SUMMABLE_IFF_COFINITE]);;
let REAL_SUMMABLE_EQ_COFINITE = 
prove (`!f s t. FINITE((s DIFF t) UNION (t DIFF s)) /\ real_summable s f ==> real_summable t f`,
let REAL_SUMMABLE_FROM_ELSEWHERE = 
prove (`!f m n. real_summable (from m) f ==> real_summable (from n) f`,
REPEAT GEN_TAC THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] REAL_SUMMABLE_EQ_COFINITE) THEN MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `0..(m+n)` THEN SIMP_TAC[FINITE_NUMSEG; SUBSET; IN_NUMSEG; IN_UNION; IN_DIFF; IN_FROM] THEN ARITH_TAC);;
let REAL_SERIES_GOESTOZERO = 
prove (`!s x. real_summable s x ==> !e. &0 < e ==> eventually (\n. n IN s ==> abs(x n) < e) sequentially`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_SUMMABLE] THEN DISCH_THEN(MP_TAC o MATCH_MP SERIES_GOESTOZERO) THEN REWRITE_TAC[o_THM; NORM_LIFT]);;
let REAL_SUMMABLE_IMP_TOZERO = 
prove (`!f:num->real k. real_summable k f ==> ((\n. if n IN k then f(n) else &0) ---> &0) sequentially`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_SUMMABLE] THEN DISCH_THEN(MP_TAC o MATCH_MP SUMMABLE_IMP_TOZERO) THEN REWRITE_TAC[TENDSTO_REAL] THEN REWRITE_TAC[o_DEF; GSYM LIFT_NUM; GSYM COND_RAND]);;
let REAL_SUMMABLE_IMP_BOUNDED = 
prove (`!f:num->real k. real_summable k f ==> real_bounded (IMAGE f k)`,
let REAL_SUMMABLE_IMP_REAL_SUMS_BOUNDED = 
prove (`!f:num->real k. real_summable (from k) f ==> real_bounded { sum(k..n) f | n IN (:num) }`,
REWRITE_TAC[real_summable; real_sums; LEFT_IMP_EXISTS_THM] THEN REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP REAL_CONVERGENT_IMP_BOUNDED) THEN REWRITE_TAC[FROM_INTER_NUMSEG; SIMPLE_IMAGE]);;
let REAL_SERIES_0 = 
prove (`!s. ((\n. &0) real_sums (&0)) s`,
REWRITE_TAC[real_sums; SUM_0; REALLIM_CONST]);;
let REAL_SERIES_ADD = 
prove (`!x x0 y y0 s. (x real_sums x0) s /\ (y real_sums y0) s ==> ((\n. x n + y n) real_sums (x0 + y0)) s`,
let REAL_SERIES_SUB = 
prove (`!x x0 y y0 s. (x real_sums x0) s /\ (y real_sums y0) s ==> ((\n. x n - y n) real_sums (x0 - y0)) s`,
let REAL_SERIES_LMUL = 
prove (`!x x0 c s. (x real_sums x0) s ==> ((\n. c * x n) real_sums (c * x0)) s`,
let REAL_SERIES_RMUL = 
prove (`!x x0 c s. (x real_sums x0) s ==> ((\n. x n * c) real_sums (x0 * c)) s`,
let REAL_SERIES_NEG = 
prove (`!x x0 s. (x real_sums x0) s ==> ((\n. --(x n)) real_sums (--x0)) s`,
let REAL_SUMS_IFF = 
prove (`!f g k. (!x. x IN k ==> f x = g x) ==> ((f real_sums l) k <=> (g real_sums l) k)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[real_sums] THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN MATCH_MP_TAC SUM_EQ THEN ASM_SIMP_TAC[IN_INTER]);;
let REAL_SUMS_EQ = 
prove (`!f g k. (!x. x IN k ==> f x = g x) /\ (f real_sums l) k ==> (g real_sums l) k`,
MESON_TAC[REAL_SUMS_IFF]);;
let REAL_SERIES_FINITE_SUPPORT = 
prove (`!f s k. FINITE (s INTER k) /\ (!x. ~(x IN s INTER k) ==> f x = &0) ==> (f real_sums sum(s INTER k) f) k`,
REWRITE_TAC[real_sums; REALLIM_SEQUENTIALLY] THEN REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o ISPEC `\x:num. x` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN STRIP_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN SUBGOAL_THEN `sum (k INTER (0..n)) (f:num->real) = sum(s INTER k) f` (fun th -> ASM_REWRITE_TAC[REAL_SUB_REFL; REAL_ABS_NUM; th]) THEN MATCH_MP_TAC SUM_SUPERSET THEN ASM_SIMP_TAC[SUBSET; IN_INTER; IN_NUMSEG; LE_0] THEN ASM_MESON_TAC[IN_INTER; LE_TRANS]);;
let REAL_SERIES_DIFFS = 
prove (`!f k. (f ---> &0) sequentially ==> ((\n. f(n) - f(n + 1)) real_sums f(k)) (from k)`,
REWRITE_TAC[real_sums; FROM_INTER_NUMSEG; SUM_DIFFS] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REALLIM_TRANSFORM_EVENTUALLY THEN EXISTS_TAC `\n. (f:num->real) k - f(n + 1)` THEN CONJ_TAC THENL [REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `k:num` THEN SIMP_TAC[]; GEN_REWRITE_TAC LAND_CONV [GSYM REAL_SUB_RZERO] THEN MATCH_MP_TAC REALLIM_SUB THEN REWRITE_TAC[REALLIM_CONST] THEN MATCH_MP_TAC REAL_SEQ_OFFSET THEN ASM_REWRITE_TAC[]]);;
let REAL_SERIES_TRIVIAL = 
prove (`!f. (f real_sums &0) {}`,
let REAL_SERIES_RESTRICT = 
prove (`!f k l:real. ((\n. if n IN k then f(n) else &0) real_sums l) (:num) <=> (f real_sums l) k`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_sums] THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM; INTER_UNIV] THEN GEN_TAC THEN MATCH_MP_TAC(MESON[] `sum s f = sum t f /\ sum t f = sum t g ==> sum s f = sum t g`) THEN CONJ_TAC THENL [MATCH_MP_TAC SUM_SUPERSET THEN SET_TAC[]; MATCH_MP_TAC SUM_EQ THEN SIMP_TAC[IN_INTER]]);;
let REAL_SERIES_SUM = 
prove (`!f l k s. FINITE s /\ s SUBSET k /\ (!x. ~(x IN s) ==> f x = &0) /\ sum s f = l ==> (f real_sums l) k`,
REPEAT STRIP_TAC THEN EXPAND_TAC "l" THEN SUBGOAL_THEN `s INTER k = s:num->bool` ASSUME_TAC THENL [ASM SET_TAC[]; ASM_MESON_TAC [REAL_SERIES_FINITE_SUPPORT]]);;
let REAL_SUMS_LE2 = 
prove (`!f g s y z. (f real_sums y) s /\ (g real_sums z) s /\ (!i. i IN s ==> f(i) <= g(i)) ==> y <= z`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_sums] THEN ONCE_REWRITE_TAC[CONJ_ASSOC] THEN DISCH_THEN(CONJUNCTS_THEN2 (MATCH_MP_TAC o MATCH_MP (ONCE_REWRITE_RULE[IMP_CONJ] (ONCE_REWRITE_RULE[CONJ_ASSOC] REALLIM_LE))) ASSUME_TAC) THEN ASM_SIMP_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN ASM_SIMP_TAC[SUM_LE; FINITE_INTER; IN_INTER; FINITE_NUMSEG] THEN REWRITE_TAC[EVENTUALLY_TRUE]);;
let REAL_SUMS_REINDEX = 
prove (`!k a l n. ((\x. a(x + k)) real_sums l) (from n) <=> (a real_sums l) (from(n + k))`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_sums; FROM_INTER_NUMSEG] THEN REPEAT GEN_TAC THEN REWRITE_TAC[GSYM SUM_OFFSET] THEN REWRITE_TAC[REALLIM_SEQUENTIALLY] THEN ASM_MESON_TAC[ARITH_RULE `N + k:num <= n ==> n = (n - k) + k /\ N <= n - k`; ARITH_RULE `N + k:num <= n ==> N <= n + k`]);;
let REAL_INFSUM = 
prove (`!f s. real_summable s f ==> real_infsum s f = drop(infsum s (lift o f))`,
REPEAT GEN_TAC THEN REWRITE_TAC[GSYM REAL_SUMS_INFSUM; REAL_SUMS] THEN DISCH_THEN(MP_TAC o MATCH_MP INFSUM_UNIQUE) THEN MESON_TAC[LIFT_DROP]);;
let REAL_PARTIAL_SUMS_LE_INFSUM = 
prove (`!f s n. (!i. i IN s ==> &0 <= f i) /\ real_summable s f ==> sum (s INTER (0..n)) f <= real_infsum s f`,
REPEAT GEN_TAC THEN SIMP_TAC[REAL_INFSUM] THEN REWRITE_TAC[REAL_SUMMABLE] THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o BINDER_CONV o RAND_CONV o RAND_CONV) [GSYM LIFT_DROP] THEN REWRITE_TAC[o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP PARTIAL_SUMS_DROP_LE_INFSUM) THEN SIMP_TAC[DROP_VSUM; FINITE_INTER; FINITE_NUMSEG; o_DEF; LIFT_DROP; ETA_AX]);;
(* ------------------------------------------------------------------------- *) (* Similar combining theorems just for summability. *) (* ------------------------------------------------------------------------- *)
let REAL_SUMMABLE_0 = 
prove (`!s. real_summable s (\n. &0)`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SERIES_0]);;
let REAL_SUMMABLE_ADD = 
prove (`!x y s. real_summable s x /\ real_summable s y ==> real_summable s (\n. x n + y n)`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SERIES_ADD]);;
let REAL_SUMMABLE_SUB = 
prove (`!x y s. real_summable s x /\ real_summable s y ==> real_summable s (\n. x n - y n)`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SERIES_SUB]);;
let REAL_SUMMABLE_LMUL = 
prove (`!s x c. real_summable s x ==> real_summable s (\n. c * x n)`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SERIES_LMUL]);;
let REAL_SUMMABLE_RMUL = 
prove (`!s x c. real_summable s x ==> real_summable s (\n. x n * c)`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SERIES_RMUL]);;
let REAL_SUMMABLE_NEG = 
prove (`!x s. real_summable s x ==> real_summable s (\n. --(x n))`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SERIES_NEG]);;
let REAL_SUMMABLE_IFF = 
prove (`!f g k. (!x. x IN k ==> f x = g x) ==> (real_summable k f <=> real_summable k g)`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SUMS_IFF]);;
let REAL_SUMMABLE_EQ = 
prove (`!f g k. (!x. x IN k ==> f x = g x) /\ real_summable k f ==> real_summable k g`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SUMS_EQ]);;
let REAL_SERIES_SUBSET = 
prove (`!x s t l. s SUBSET t /\ ((\i. if i IN s then x i else &0) real_sums l) t ==> (x real_sums l) s`,
REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN REWRITE_TAC[real_sums] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN ASM_SIMP_TAC[GSYM SUM_RESTRICT_SET; FINITE_INTER_NUMSEG] THEN AP_THM_TAC THEN AP_TERM_TAC THEN POP_ASSUM MP_TAC THEN SET_TAC[]);;
let REAL_SUMMABLE_SUBSET = 
prove (`!x s t. s SUBSET t /\ real_summable t (\i. if i IN s then x i else &0) ==> real_summable s x`,
REWRITE_TAC[real_summable] THEN MESON_TAC[REAL_SERIES_SUBSET]);;
let REAL_SUMMABLE_TRIVIAL = 
prove (`!f. real_summable {} f`,
GEN_TAC THEN REWRITE_TAC[real_summable] THEN EXISTS_TAC `&0` THEN REWRITE_TAC[REAL_SERIES_TRIVIAL]);;
let REAL_SUMMABLE_RESTRICT = 
prove (`!f k. real_summable (:num) (\n. if n IN k then f(n) else &0) <=> real_summable k f`,
let REAL_SUMS_FINITE_DIFF = 
prove (`!f t s l. t SUBSET s /\ FINITE t /\ (f real_sums l) s ==> (f real_sums (l - sum t f)) (s DIFF t)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN FIRST_ASSUM(MP_TAC o ISPEC `f:num->real` o MATCH_MP REAL_SERIES_FINITE) THEN ONCE_REWRITE_TAC[GSYM REAL_SERIES_RESTRICT] THEN REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN DISCH_THEN(MP_TAC o MATCH_MP REAL_SERIES_SUB) THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `x:num` THEN REWRITE_TAC[IN_DIFF] THEN FIRST_ASSUM(MP_TAC o SPEC `x:num` o GEN_REWRITE_RULE I [SUBSET]) THEN MAP_EVERY ASM_CASES_TAC [`(x:num) IN s`; `(x:num) IN t`] THEN ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
let REAL_SUMS_FINITE_UNION = 
prove (`!f s t l. FINITE t /\ (f real_sums l) s ==> (f real_sums (l + sum (t DIFF s) f)) (s UNION t)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN FIRST_ASSUM(MP_TAC o SPEC `s:num->bool` o MATCH_MP FINITE_DIFF) THEN DISCH_THEN(MP_TAC o ISPEC `f:num->real` o MATCH_MP REAL_SERIES_FINITE) THEN ONCE_REWRITE_TAC[GSYM REAL_SERIES_RESTRICT] THEN REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN DISCH_THEN(MP_TAC o MATCH_MP REAL_SERIES_ADD) THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `x:num` THEN REWRITE_TAC[IN_DIFF; IN_UNION] THEN MAP_EVERY ASM_CASES_TAC [`(x:num) IN s`; `(x:num) IN t`] THEN ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
let REAL_SUMS_OFFSET = 
prove (`!f l m n. (f real_sums l) (from m) /\ m < n ==> (f real_sums (l - sum(m..(n-1)) f)) (from n)`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `from n = from m DIFF (m..(n-1))` SUBST1_TAC THENL [REWRITE_TAC[EXTENSION; IN_FROM; IN_DIFF; IN_NUMSEG] THEN ASM_ARITH_TAC; MATCH_MP_TAC REAL_SUMS_FINITE_DIFF THEN ASM_REWRITE_TAC[FINITE_NUMSEG] THEN SIMP_TAC[SUBSET; IN_FROM; IN_NUMSEG]]);;
let REAL_SUMS_OFFSET_REV = 
prove (`!f l m n. (f real_sums l) (from m) /\ n < m ==> (f real_sums (l + sum(n..m-1) f)) (from n)`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`f:num->real`; `from m`; `n..m-1`; `l:real`] REAL_SUMS_FINITE_UNION) THEN ASM_REWRITE_TAC[FINITE_NUMSEG] THEN MATCH_MP_TAC EQ_IMP THEN BINOP_TAC THENL [AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC; ALL_TAC] THEN REWRITE_TAC[EXTENSION; IN_DIFF; IN_UNION; IN_FROM; IN_NUMSEG] THEN ASM_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Similar combining theorems for infsum. *) (* ------------------------------------------------------------------------- *)
let REAL_INFSUM_0 = 
prove (`real_infsum s (\i. &0) = &0`,
MATCH_MP_TAC REAL_INFSUM_UNIQUE THEN REWRITE_TAC[REAL_SERIES_0]);;
let REAL_INFSUM_ADD = 
prove (`!x y s. real_summable s x /\ real_summable s y ==> real_infsum s (\i. x i + y i) = real_infsum s x + real_infsum s y`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INFSUM_UNIQUE THEN MATCH_MP_TAC REAL_SERIES_ADD THEN ASM_REWRITE_TAC[REAL_SUMS_INFSUM]);;
let REAL_INFSUM_SUB = 
prove (`!x y s. real_summable s x /\ real_summable s y ==> real_infsum s (\i. x i - y i) = real_infsum s x - real_infsum s y`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INFSUM_UNIQUE THEN MATCH_MP_TAC REAL_SERIES_SUB THEN ASM_REWRITE_TAC[REAL_SUMS_INFSUM]);;
let REAL_INFSUM_LMUL = 
prove (`!s x c. real_summable s x ==> real_infsum s (\n. c * x n) = c * real_infsum s x`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INFSUM_UNIQUE THEN MATCH_MP_TAC REAL_SERIES_LMUL THEN ASM_REWRITE_TAC[REAL_SUMS_INFSUM]);;
let REAL_INFSUM_RMUL = 
prove (`!s x c. real_summable s x ==> real_infsum s (\n. x n * c) = real_infsum s x * c`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INFSUM_UNIQUE THEN MATCH_MP_TAC REAL_SERIES_RMUL THEN ASM_REWRITE_TAC[REAL_SUMS_INFSUM]);;
let REAL_INFSUM_NEG = 
prove (`!s x. real_summable s x ==> real_infsum s (\n. --(x n)) = --(real_infsum s x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INFSUM_UNIQUE THEN MATCH_MP_TAC REAL_SERIES_NEG THEN ASM_REWRITE_TAC[REAL_SUMS_INFSUM]);;
let REAL_INFSUM_EQ = 
prove (`!f g k. real_summable k f /\ real_summable k g /\ (!x. x IN k ==> f x = g x) ==> real_infsum k f = real_infsum k g`,
REPEAT STRIP_TAC THEN REWRITE_TAC[real_infsum] THEN AP_TERM_TAC THEN ABS_TAC THEN ASM_MESON_TAC[REAL_SUMS_EQ; REAL_SUMS_INFSUM]);;
let REAL_INFSUM_RESTRICT = 
prove (`!k a. real_infsum (:num) (\n. if n IN k then a n else &0) = real_infsum k a`,
REPEAT GEN_TAC THEN MP_TAC(ISPECL [`a:num->real`; `k:num->bool`] REAL_SUMMABLE_RESTRICT) THEN ASM_CASES_TAC `real_summable k a` THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THENL [MATCH_MP_TAC REAL_INFSUM_UNIQUE THEN ASM_REWRITE_TAC[REAL_SERIES_RESTRICT; REAL_SUMS_INFSUM]; RULE_ASSUM_TAC(REWRITE_RULE[real_summable; NOT_EXISTS_THM]) THEN ASM_REWRITE_TAC[real_infsum]]);;
(* ------------------------------------------------------------------------- *) (* Convergence tests for real series. *) (* ------------------------------------------------------------------------- *)
let REAL_SERIES_CAUCHY_UNIFORM = 
prove (`!P:A->bool f k. (?l. !e. &0 < e ==> ?N. !n x. N <= n /\ P x ==> abs(sum(k INTER (0..n)) (f x) - l x) < e) <=> (!e. &0 < e ==> ?N. !m n x. N <= m /\ P x ==> abs(sum(k INTER (m..n)) (f x)) < e)`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`P:A->bool`; `\x:A n:num. lift(f x n)`; `k:num->bool`] SERIES_CAUCHY_UNIFORM) THEN SIMP_TAC[VSUM_REAL; FINITE_INTER; FINITE_NUMSEG] THEN REWRITE_TAC[NORM_LIFT; o_DEF; LIFT_DROP; ETA_AX] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN EQ_TAC THENL [DISCH_THEN(X_CHOOSE_TAC `l:A->real`) THEN EXISTS_TAC `lift o (l:A->real)` THEN ASM_SIMP_TAC[o_THM; DIST_LIFT]; DISCH_THEN(X_CHOOSE_TAC `l:A->real^1`) THEN EXISTS_TAC `drop o (l:A->real^1)` THEN ASM_SIMP_TAC[SUM_VSUM; FINITE_INTER; FINITE_NUMSEG] THEN REWRITE_TAC[o_THM; GSYM DROP_SUB; GSYM ABS_DROP] THEN SIMP_TAC[GSYM dist; VSUM_REAL; FINITE_INTER; FINITE_NUMSEG] THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX]]);;
let REAL_SERIES_COMPARISON = 
prove (`!f g s. (?l. (g real_sums l) s) /\ (?N. !n. n >= N /\ n IN s ==> abs(f n) <= g n) ==> ?l. (f real_sums l) s`,
REWRITE_TAC[REAL_SUMS; GSYM EXISTS_LIFT] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SERIES_COMPARISON THEN EXISTS_TAC `g:num->real` THEN REWRITE_TAC[NORM_LIFT; o_THM] THEN ASM_MESON_TAC[]);;
let REAL_SUMMABLE_COMPARISON = 
prove (`!f g s. real_summable s g /\ (?N. !n. n >= N /\ n IN s ==> abs(f n) <= g n) ==> real_summable s f`,
let REAL_SERIES_COMPARISON_UNIFORM = 
prove (`!f g P s. (?l. (g real_sums l) s) /\ (?N. !n x. N <= n /\ n IN s /\ P x ==> abs(f x n) <= g n) ==> ?l:A->real. !e. &0 < e ==> ?N. !n x. N <= n /\ P x ==> abs(sum(s INTER (0..n)) (f x) - l x) < e`,
REPEAT GEN_TAC THEN SIMP_TAC[GE; REAL_SERIES_CAUCHY; REAL_SERIES_CAUCHY_UNIFORM] THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC (X_CHOOSE_TAC `N1:num`)) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN EXISTS_TAC `N1 + N2:num` THEN MAP_EVERY X_GEN_TAC [`m:num`; `n:num`; `x:A`] THEN DISCH_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `abs (sum (s INTER (m .. n)) g)` THEN CONJ_TAC THENL [SIMP_TAC[GSYM LIFT_SUM; FINITE_INTER_NUMSEG; NORM_LIFT] THEN MATCH_MP_TAC(REAL_ARITH `x <= a ==> x <= abs(a)`) THEN MATCH_MP_TAC SUM_ABS_LE THEN REWRITE_TAC[FINITE_INTER_NUMSEG; IN_INTER; IN_NUMSEG] THEN ASM_MESON_TAC[ARITH_RULE `N1 + N2:num <= m /\ m <= x ==> N1 <= x`]; ASM_MESON_TAC[ARITH_RULE `N1 + N2:num <= m ==> N2 <= m`]]);;
let REAL_SERIES_RATIO = 
prove (`!c a s N. c < &1 /\ (!n. n >= N ==> abs(a(SUC n)) <= c * abs(a(n))) ==> ?l:real. (a real_sums l) s`,
REWRITE_TAC[REAL_SUMS; GSYM EXISTS_LIFT] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SERIES_RATIO THEN REWRITE_TAC[o_THM; NORM_LIFT] THEN ASM_MESON_TAC[]);;
let BOUNDED_PARTIAL_REAL_SUMS = 
prove (`!f:num->real k. real_bounded { sum(k..n) f | n IN (:num) } ==> real_bounded { sum(m..n) f | m IN (:num) /\ n IN (:num) }`,
REWRITE_TAC[REAL_BOUNDED] THEN REWRITE_TAC[SET_RULE `IMAGE f {g x | P x} = {f(g x) | P x}`; SET_RULE `IMAGE f {g x y | P x /\ Q y} = {f(g x y) | P x /\ Q y}`] THEN SIMP_TAC[LIFT_SUM; FINITE_INTER; FINITE_NUMSEG] THEN REWRITE_TAC[BOUNDED_PARTIAL_SUMS]);;
let REAL_SERIES_DIRICHLET = 
prove (`!f:num->real g N k m. real_bounded { sum (m..n) f | n IN (:num)} /\ (!n. N <= n ==> g(n + 1) <= g(n)) /\ (g ---> &0) sequentially ==> real_summable (from k) (\n. g(n) * f(n))`,
REWRITE_TAC[REAL_SUMMABLE; REAL_BOUNDED; TENDSTO_REAL] THEN REWRITE_TAC[LIFT_NUM; LIFT_CMUL; o_DEF] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SERIES_DIRICHLET THEN MAP_EVERY EXISTS_TAC [`N:num`; `m:num`] THEN ASM_REWRITE_TAC[o_DEF] THEN SIMP_TAC[VSUM_REAL; FINITE_INTER; FINITE_NUMSEG] THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX] THEN ASM_REWRITE_TAC[SET_RULE `{lift(f x) | P x} = IMAGE lift {f x | P x}`]);;
let REAL_SERIES_ABSCONV_IMP_CONV = 
prove (`!x:num->real k. real_summable k (\n. abs(x n)) ==> real_summable k x`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_SUMMABLE_COMPARISON THEN EXISTS_TAC `\n:num. abs(x n)` THEN ASM_REWRITE_TAC[REAL_LE_REFL]);;
let REAL_SUMS_GP = 
prove (`!n x. abs(x) < &1 ==> ((\k. x pow k) real_sums (x pow n / (&1 - x))) (from n)`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`n:num`; `Cx x`] SUMS_GP) THEN ASM_REWRITE_TAC[REAL_SUMS_COMPLEX; GSYM CX_SUB; GSYM CX_POW; GSYM CX_DIV; o_DEF; COMPLEX_NORM_CX]);;
let REAL_SUMMABLE_GP = 
prove (`!x k. abs(x) < &1 ==> real_summable k (\n. x pow n)`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`Cx x`; `k:num->bool`] SUMMABLE_GP) THEN ASM_REWRITE_TAC[REAL_SUMMABLE_COMPLEX] THEN ASM_REWRITE_TAC[COMPLEX_NORM_CX; o_DEF; CX_POW]);;
let REAL_ABEL_LEMMA = 
prove (`!a M r r0. &0 <= r /\ r < r0 /\ (!n. n IN k ==> abs(a n) * r0 pow n <= M) ==> real_summable k (\n. abs(a(n)) * r pow n)`,
REWRITE_TAC[REAL_SUMMABLE_COMPLEX] THEN REWRITE_TAC[o_DEF; CX_MUL; CX_ABS] THEN REWRITE_TAC[GSYM CX_MUL] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC ABEL_LEMMA THEN REWRITE_TAC[COMPLEX_NORM_CX] THEN ASM_MESON_TAC[]);;
let REAL_POWER_SERIES_CONV_IMP_ABSCONV = 
prove (`!a k w z. real_summable k (\n. a(n) * z pow n) /\ abs(w) < abs(z) ==> real_summable k (\n. abs(a(n) * w pow n))`,
REWRITE_TAC[REAL_SUMMABLE_COMPLEX; o_DEF; CX_MUL; CX_ABS; CX_POW] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC POWER_SERIES_CONV_IMP_ABSCONV THEN EXISTS_TAC `Cx z` THEN ASM_REWRITE_TAC[COMPLEX_NORM_CX]);;
let POWER_REAL_SERIES_CONV_IMP_ABSCONV_WEAK = 
prove (`!a k w z. real_summable k (\n. a(n) * z pow n) /\ abs(w) < abs(z) ==> real_summable k (\n. abs(a n) * w pow n)`,
REWRITE_TAC[REAL_SUMMABLE_COMPLEX; o_DEF; CX_MUL; CX_ABS; CX_POW] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC POWER_SERIES_CONV_IMP_ABSCONV_WEAK THEN EXISTS_TAC `Cx z` THEN ASM_REWRITE_TAC[COMPLEX_NORM_CX]);;
(* ------------------------------------------------------------------------- *) (* Some real limits involving transcendentals. *) (* ------------------------------------------------------------------------- *)
let REALLIM_1_OVER_N = 
prove (`((\n. inv(&n)) ---> &0) sequentially`,
let REALLIM_LOG_OVER_N = 
prove (`((\n. log(&n) / &n) ---> &0) sequentially`,
REWRITE_TAC[REALLIM_COMPLEX] THEN MP_TAC LIM_LOG_OVER_N THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `1` THEN SIMP_TAC[o_DEF; CX_DIV; CX_LOG; REAL_OF_NUM_LT; ARITH_RULE `1 <= n ==> 0 < n`]);;
let REALLIM_1_OVER_LOG = 
prove (`((\n. inv(log(&n))) ---> &0) sequentially`,
REWRITE_TAC[REALLIM_COMPLEX] THEN MP_TAC LIM_1_OVER_LOG THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN REWRITE_TAC[o_DEF; complex_div; COMPLEX_MUL_LID; CX_INV] THEN REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `1` THEN SIMP_TAC[CX_LOG; REAL_OF_NUM_LT; ARITH_RULE `1 <= n ==> 0 < n`]);;
let REALLIM_POWN = 
prove (`!z. abs(z) < &1 ==> ((\n. z pow n) ---> &0) sequentially`,
REWRITE_TAC[REALLIM_COMPLEX; o_DEF; CX_POW] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_POWN THEN ASM_REWRITE_TAC[COMPLEX_NORM_CX]);;
(* ------------------------------------------------------------------------- *) (* Nets for real limit. *) (* ------------------------------------------------------------------------- *)
let atreal = new_definition
 `atreal a = mk_net(\x y. &0 < abs(x - a) /\ abs(x - a) <= abs(y - a))`;;
let at_posinfinity = new_definition
  `at_posinfinity = mk_net(\x y:real. x >= y)`;;
let at_neginfinity = new_definition
  `at_neginfinity = mk_net(\x y:real. x <= y)`;;
let ATREAL = 
prove (`!a x y. netord(atreal a) x y <=> &0 < abs(x - a) /\ abs(x - a) <= abs(y - a)`,
GEN_TAC THEN NET_PROVE_TAC[atreal] THEN MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS; REAL_LET_TRANS]);;
let AT_POSINFINITY = 
prove (`!x y. netord at_posinfinity x y <=> x >= y`,
NET_PROVE_TAC[at_posinfinity] THEN REWRITE_TAC[real_ge; REAL_LE_REFL] THEN MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS]);;
let AT_NEGINFINITY = 
prove (`!x y. netord at_neginfinity x y <=> x <= y`,
NET_PROVE_TAC[at_neginfinity] THEN REWRITE_TAC[real_ge; REAL_LE_REFL] THEN MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS]);;
let WITHINREAL_UNIV = 
prove (`!x. atreal x within (:real) = atreal x`,
REWRITE_TAC[within; atreal; IN_UNIV] THEN REWRITE_TAC[ETA_AX; net_tybij]);;
let TRIVIAL_LIMIT_ATREAL = 
prove (`!a. ~(trivial_limit (atreal a))`,
X_GEN_TAC `a:real` THEN SIMP_TAC[trivial_limit; ATREAL; DE_MORGAN_THM] THEN CONJ_TAC THENL [DISCH_THEN(MP_TAC o SPECL [`&0`; `&1`]) THEN REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[NOT_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`b:real`; `c:real`] THEN ASM_CASES_TAC `b:real = c` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM DE_MORGAN_THM; GSYM NOT_EXISTS_THM] THEN SUBGOAL_THEN `~(b:real = a) \/ ~(c = a)` DISJ_CASES_TAC THENL [ASM_MESON_TAC[]; EXISTS_TAC `(a + b) / &2` THEN ASM_REAL_ARITH_TAC; EXISTS_TAC `(a + c) / &2` THEN ASM_REAL_ARITH_TAC]);;
let TRIVIAL_LIMIT_AT_POSINFINITY = 
prove (`~(trivial_limit at_posinfinity)`,
REWRITE_TAC[trivial_limit; AT_POSINFINITY; DE_MORGAN_THM] THEN CONJ_TAC THENL [DISCH_THEN(MP_TAC o SPECL [`&0`; `&1`]) THEN REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[DE_MORGAN_THM; NOT_EXISTS_THM; real_ge; REAL_NOT_LE] THEN MESON_TAC[REAL_LT_TOTAL; REAL_LT_ANTISYM]);;
let TRIVIAL_LIMIT_AT_NEGINFINITY = 
prove (`~(trivial_limit at_neginfinity)`,
REWRITE_TAC[trivial_limit; AT_NEGINFINITY; DE_MORGAN_THM] THEN CONJ_TAC THENL [DISCH_THEN(MP_TAC o SPECL [`&0`; `&1`]) THEN REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[DE_MORGAN_THM; NOT_EXISTS_THM; real_ge; REAL_NOT_LE] THEN MESON_TAC[REAL_LT_TOTAL; REAL_LT_ANTISYM]);;
let NETLIMIT_WITHINREAL = 
prove (`!a s. ~(trivial_limit (atreal a within s)) ==> (netlimit (atreal a within s) = a)`,
REWRITE_TAC[trivial_limit; netlimit; ATREAL; WITHIN; DE_MORGAN_THM] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SELECT_UNIQUE THEN REWRITE_TAC[] THEN SUBGOAL_THEN `!x. ~(&0 < abs(x - a) /\ abs(x - a) <= abs(a - a) /\ x IN s)` ASSUME_TAC THENL [REAL_ARITH_TAC; ASM_MESON_TAC[]]);;
let NETLIMIT_ATREAL = 
prove (`!a. netlimit(atreal a) = a`,
GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN MATCH_MP_TAC NETLIMIT_WITHINREAL THEN SIMP_TAC[TRIVIAL_LIMIT_ATREAL; WITHINREAL_UNIV]);;
let EVENTUALLY_WITHINREAL_LE = 
prove (`!s a p. eventually p (atreal a within s) <=> ?d. &0 < d /\ !x. x IN s /\ &0 < abs(x - a) /\ abs(x - a) <= d ==> p(x)`,
REWRITE_TAC[eventually; ATREAL; WITHIN; trivial_limit] THEN REWRITE_TAC[MESON[REAL_LT_01; REAL_LT_REFL] `~(!a b:real. a = b)`] THEN REPEAT GEN_TAC THEN EQ_TAC THENL [DISCH_THEN(DISJ_CASES_THEN(X_CHOOSE_THEN `b:real` MP_TAC)) THENL [DISCH_THEN(X_CHOOSE_THEN `c:real` STRIP_ASSUME_TAC) THEN FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH `~(b = c) ==> &0 < abs(b - a) \/ &0 < abs(c - a)`)) THEN ASM_MESON_TAC[]; MESON_TAC[REAL_LTE_TRANS]]; DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN ASM_CASES_TAC `?x. x IN s /\ &0 < abs(x - a) /\ abs(x - a) <= d` THENL [DISJ2_TAC THEN FIRST_X_ASSUM(X_CHOOSE_TAC `b:real`) THEN EXISTS_TAC `b:real` THEN ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_REFL]; DISJ1_TAC THEN MAP_EVERY EXISTS_TAC [`a + d:real`; `a:real`] THEN ASM_SIMP_TAC[REAL_ADD_SUB; REAL_EQ_ADD_LCANCEL_0; REAL_LT_IMP_NZ] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `x:real` THEN ASM_CASES_TAC `(x:real) IN s` THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC]]);;
let EVENTUALLY_WITHINREAL = 
prove (`!s a p. eventually p (atreal a within s) <=> ?d. &0 < d /\ !x. x IN s /\ &0 < abs(x - a) /\ abs(x - a) < d ==> p(x)`,
REWRITE_TAC[EVENTUALLY_WITHINREAL_LE] THEN ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> c ==> a /\ b ==> d`] THEN REWRITE_TAC[APPROACHABLE_LT_LE]);;
let EVENTUALLY_ATREAL = 
prove (`!a p. eventually p (atreal a) <=> ?d. &0 < d /\ !x. &0 < abs(x - a) /\ abs(x - a) < d ==> p(x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[EVENTUALLY_WITHINREAL; IN_UNIV]);;
let EVENTUALLY_AT_POSINFINITY = 
prove (`!p. eventually p at_posinfinity <=> ?b. !x. x >= b ==> p x`,
REWRITE_TAC[eventually; TRIVIAL_LIMIT_AT_POSINFINITY; AT_POSINFINITY] THEN MESON_TAC[REAL_ARITH `x >= x`]);;
let EVENTUALLY_AT_NEGINFINITY = 
prove (`!p. eventually p at_neginfinity <=> ?b. !x. x <= b ==> p x`,
(* ------------------------------------------------------------------------- *) (* Usual limit results with real domain and either vector or real range. *) (* ------------------------------------------------------------------------- *)
let LIM_WITHINREAL_LE = 
prove (`!f:real->real^N l a s. (f --> l) (atreal a within s) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. x IN s /\ &0 < abs(x - a) /\ abs(x - a) <= d ==> dist(f(x),l) < e`,
let LIM_WITHINREAL = 
prove (`!f:real->real^N l a s. (f --> l) (atreal a within s) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. x IN s /\ &0 < abs(x - a) /\ abs(x - a) < d ==> dist(f(x),l) < e`,
REWRITE_TAC[tendsto; EVENTUALLY_WITHINREAL] THEN MESON_TAC[]);;
let LIM_ATREAL = 
prove (`!f l:real^N a. (f --> l) (atreal a) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. &0 < abs(x - a) /\ abs(x - a) < d ==> dist(f(x),l) < e`,
REWRITE_TAC[tendsto; EVENTUALLY_ATREAL] THEN MESON_TAC[]);;
let LIM_AT_POSINFINITY = 
prove (`!f l. (f --> l) at_posinfinity <=> !e. &0 < e ==> ?b. !x. x >= b ==> dist(f(x),l) < e`,
REWRITE_TAC[tendsto; EVENTUALLY_AT_POSINFINITY] THEN MESON_TAC[]);;
let LIM_AT_NEGINFINITY = 
prove (`!f l. (f --> l) at_neginfinity <=> !e. &0 < e ==> ?b. !x. x <= b ==> dist(f(x),l) < e`,
REWRITE_TAC[tendsto; EVENTUALLY_AT_NEGINFINITY] THEN MESON_TAC[]);;
let REALLIM_WITHINREAL_LE = 
prove (`!f l a s. (f ---> l) (atreal a within s) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. x IN s /\ &0 < abs(x - a) /\ abs(x - a) <= d ==> abs(f(x) - l) < e`,
let REALLIM_WITHINREAL = 
prove (`!f l a s. (f ---> l) (atreal a within s) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. x IN s /\ &0 < abs(x - a) /\ abs(x - a) < d ==> abs(f(x) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_WITHINREAL] THEN MESON_TAC[]);;
let REALLIM_ATREAL = 
prove (`!f l a. (f ---> l) (atreal a) <=> !e. &0 < e ==> ?d. &0 < d /\ !x. &0 < abs(x - a) /\ abs(x - a) < d ==> abs(f(x) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_ATREAL] THEN MESON_TAC[]);;
let REALLIM_AT_POSINFINITY = 
prove (`!f l. (f ---> l) at_posinfinity <=> !e. &0 < e ==> ?b. !x. x >= b ==> abs(f(x) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_AT_POSINFINITY] THEN MESON_TAC[]);;
let REALLIM_AT_NEGINFINITY = 
prove (`!f l. (f ---> l) at_neginfinity <=> !e. &0 < e ==> ?b. !x. x <= b ==> abs(f(x) - l) < e`,
REWRITE_TAC[tendsto_real; EVENTUALLY_AT_NEGINFINITY] THEN MESON_TAC[]);;
let LIM_ATREAL_WITHINREAL = 
prove (`!f l a s. (f --> l) (atreal a) ==> (f --> l) (atreal a within s)`,
REWRITE_TAC[LIM_ATREAL; LIM_WITHINREAL] THEN MESON_TAC[]);;
let REALLIM_ATREAL_WITHINREAL = 
prove (`!f l a s. (f ---> l) (atreal a) ==> (f ---> l) (atreal a within s)`,
REWRITE_TAC[REALLIM_ATREAL; REALLIM_WITHINREAL] THEN MESON_TAC[]);;
let REALLIM_WITHIN_SUBSET = 
prove (`!f l a s t. (f ---> l) (at a within s) /\ t SUBSET s ==> (f ---> l) (at a within t)`,
REWRITE_TAC[REALLIM_WITHIN; SUBSET] THEN MESON_TAC[]);;
let REALLIM_WITHINREAL_SUBSET = 
prove (`!f l a s t. (f ---> l) (atreal a within s) /\ t SUBSET s ==> (f ---> l) (atreal a within t)`,
REWRITE_TAC[REALLIM_WITHINREAL; SUBSET] THEN MESON_TAC[]);;
let LIM_WITHINREAL_SUBSET = 
prove (`!f l a s t. (f --> l) (atreal a within s) /\ t SUBSET s ==> (f --> l) (atreal a within t)`,
REWRITE_TAC[LIM_WITHINREAL; SUBSET] THEN MESON_TAC[]);;
let REALLIM_ATREAL_ID = 
prove (`((\x. x) ---> a) (atreal a)`,
REWRITE_TAC[REALLIM_ATREAL] THEN MESON_TAC[]);;
let REALLIM_WITHINREAL_ID = 
prove (`!a. ((\x. x) ---> a) (atreal a within s)`,
REWRITE_TAC[REALLIM_WITHINREAL] THEN MESON_TAC[]);;
let LIM_TRANSFORM_WITHINREAL_SET = 
prove (`!f a s t. eventually (\x. x IN s <=> x IN t) (atreal a) ==> ((f --> l) (atreal a within s) <=> (f --> l) (atreal a within t))`,
REPEAT GEN_TAC THEN REWRITE_TAC[EVENTUALLY_ATREAL; LIM_WITHINREAL] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN EQ_TAC 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 `k:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `min d k:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN ASM_MESON_TAC[]);;
let REALLIM_TRANSFORM_WITHIN_SET = 
prove (`!f a s t. eventually (\x. x IN s <=> x IN t) (at a) ==> ((f ---> l) (at a within s) <=> (f ---> l) (at a within t))`,
REPEAT GEN_TAC THEN REWRITE_TAC[EVENTUALLY_AT; REALLIM_WITHIN] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN EQ_TAC 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 `k:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `min d k:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN ASM_MESON_TAC[]);;
let REALLIM_TRANSFORM_WITHINREAL_SET = 
prove (`!f a s t. eventually (\x. x IN s <=> x IN t) (atreal a) ==> ((f ---> l) (atreal a within s) <=> (f ---> l) (atreal a within t))`,
REPEAT GEN_TAC THEN REWRITE_TAC[EVENTUALLY_ATREAL; REALLIM_WITHINREAL] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN EQ_TAC 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 `k:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `min d k:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN ASM_MESON_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Relations between limits at real and complex limit points. *) (* ------------------------------------------------------------------------- *)
let TRIVIAL_LIMIT_WITHINREAL_WITHIN = 
prove (`trivial_limit(atreal x within s) <=> trivial_limit(at (lift x) within (IMAGE lift s))`,
REWRITE_TAC[trivial_limit; AT; WITHIN; ATREAL] THEN REWRITE_TAC[FORALL_LIFT; EXISTS_LIFT; LIFT_EQ; DIST_LIFT] THEN REWRITE_TAC[IN_IMAGE_LIFT_DROP; LIFT_DROP]);;
let TRIVIAL_LIMIT_WITHINREAL_WITHINCOMPLEX = 
prove (`trivial_limit(atreal x within s) <=> trivial_limit(at (Cx x) within (real INTER IMAGE Cx s))`,
REWRITE_TAC[trivial_limit; AT; WITHIN; ATREAL] THEN REWRITE_TAC[SET_RULE `x IN real INTER s <=> real x /\ x IN s`] THEN REWRITE_TAC[TAUT `~(p /\ x /\ q) /\ ~(r /\ x /\ s) <=> x ==> ~(p /\ q) /\ ~(r /\ s)`] THEN REWRITE_TAC[FORALL_REAL; MESON[IN_IMAGE; CX_INJ] `Cx x IN IMAGE Cx s <=> x IN s`] THEN REWRITE_TAC[dist; GSYM CX_SUB; o_THM; RE_CX; COMPLEX_NORM_CX] THEN MATCH_MP_TAC(TAUT `~p /\ ~q /\ (r <=> s) ==> (p \/ r <=> q \/ s)`) THEN REPEAT CONJ_TAC THEN TRY EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL [DISCH_THEN(MP_TAC o SPECL [`&0`; `&1`]) THEN CONV_TAC REAL_RING; DISCH_THEN(MP_TAC o SPECL [`Cx(&0)`; `Cx(&1)`]) THEN CONV_TAC COMPLEX_RING; MAP_EVERY X_GEN_TAC [`a:real`; `b:real`] THEN STRIP_TAC THEN MAP_EVERY EXISTS_TAC [`Cx a`; `Cx b`] THEN ASM_REWRITE_TAC[CX_INJ] THEN ASM_REWRITE_TAC[GSYM CX_SUB; COMPLEX_NORM_CX]; MAP_EVERY X_GEN_TAC [`a:complex`; `b:complex`] THEN STRIP_TAC THEN SUBGOAL_THEN `?d. &0 < d /\ !z. &0 < abs(z - x) /\ abs(z - x) <= d ==> ~(z IN s)` STRIP_ASSUME_TAC THENL [MATCH_MP_TAC(MESON[] `!a b. P a \/ P b ==> ?x. P x`) THEN MAP_EVERY EXISTS_TAC [`norm(a - Cx x)`; `norm(b - Cx x)`] THEN ASM_REWRITE_TAC[TAUT `a ==> ~b <=> ~(a /\ b)`] THEN UNDISCH_TAC `~(a:complex = b)` THEN NORM_ARITH_TAC; ALL_TAC] THEN MAP_EVERY EXISTS_TAC [`x + d:real`; `x - d:real`] THEN ASM_SIMP_TAC[REAL_ARITH `&0 < d ==> ~(x + d = x - d)`; REAL_ARITH `&0 < d ==> abs((x + d) - x) = d`; REAL_ARITH `&0 < d ==> abs(x - d - x) = d`] THEN ASM_MESON_TAC[]]);;
let LIM_WITHINREAL_WITHINCOMPLEX = 
prove (`(f --> a) (atreal x within s) <=> ((f o Re) --> a) (at(Cx x) within (real INTER IMAGE Cx s))`,
REWRITE_TAC[LIM_WITHINREAL; LIM_WITHIN] THEN REWRITE_TAC[SET_RULE `x IN real INTER s <=> real x /\ x IN s`] THEN REWRITE_TAC[IMP_CONJ; FORALL_REAL; MESON[IN_IMAGE; CX_INJ] `Cx x IN IMAGE Cx s <=> x IN s`] THEN REWRITE_TAC[dist; GSYM CX_SUB; o_THM; RE_CX; COMPLEX_NORM_CX]);;
let LIM_ATREAL_ATCOMPLEX = 
prove (`(f --> a) (atreal x) <=> ((f o Re) --> a) (at (Cx x) within real)`,
REWRITE_TAC[LIM_ATREAL; LIM_WITHIN] THEN REWRITE_TAC[IMP_CONJ; FORALL_REAL; IN; dist; GSYM CX_SUB; COMPLEX_NORM_CX; o_THM; RE_CX]);;
(* ------------------------------------------------------------------------- *) (* Simpler theorems relating limits in real and real^1. *) (* ------------------------------------------------------------------------- *)
let LIM_WITHINREAL_WITHIN = 
prove (`(f --> a) (atreal x within s) <=> ((f o drop) --> a) (at (lift x) within (IMAGE lift s))`,
let LIM_ATREAL_AT = 
prove (`(f --> a) (atreal x) <=> ((f o drop) --> a) (at (lift x))`,
let REALLIM_WITHINREAL_WITHIN = 
prove (`(f ---> a) (atreal x within s) <=> ((f o drop) ---> a) (at (lift x) within (IMAGE lift s))`,
let REALLIM_ATREAL_AT = 
prove (`(f ---> a) (atreal x) <=> ((f o drop) ---> a) (at (lift x))`,
let REALLIM_WITHIN_OPEN = 
prove (`!f:real^N->real l a s. a IN s /\ open s ==> ((f ---> l) (at a within s) <=> (f ---> l) (at a))`,
REWRITE_TAC[TENDSTO_REAL; LIM_WITHIN_OPEN]);;
let LIM_WITHIN_REAL_OPEN = 
prove (`!f:real->real^N l a s. a IN s /\ real_open s ==> ((f --> l) (atreal a within s) <=> (f --> l) (atreal a))`,
REWRITE_TAC[LIM_WITHINREAL_WITHIN; LIM_ATREAL_AT; REAL_OPEN] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_WITHIN_OPEN THEN ASM SET_TAC[]);;
let REALLIM_WITHIN_REAL_OPEN = 
prove (`!f l a s. a IN s /\ real_open s ==> ((f ---> l) (atreal a within s) <=> (f ---> l) (atreal a))`,
(* ------------------------------------------------------------------------- *) (* Additional congruence rules for simplifying limits. *) (* ------------------------------------------------------------------------- *)
let LIM_CONG_WITHINREAL = 
prove (`(!x. ~(x = a) ==> f x = g x) ==> (((\x. f x) --> l) (atreal a within s) <=> ((g --> l) (atreal a within s)))`,
let LIM_CONG_ATREAL = 
prove (`(!x. ~(x = a) ==> f x = g x) ==> (((\x. f x) --> l) (atreal a) <=> ((g --> l) (atreal a)))`,
SIMP_TAC[LIM_ATREAL; GSYM REAL_ABS_NZ; REAL_SUB_0]);;
extend_basic_congs [LIM_CONG_WITHINREAL; LIM_CONG_ATREAL];;
let REALLIM_CONG_WITHIN = 
prove (`(!x. ~(x = a) ==> f x = g x) ==> (((\x. f x) ---> l) (at a within s) <=> ((g ---> l) (at a within s)))`,
REWRITE_TAC[REALLIM_WITHIN; GSYM DIST_NZ] THEN SIMP_TAC[]);;
let REALLIM_CONG_AT = 
prove (`(!x. ~(x = a) ==> f x = g x) ==> (((\x. f x) ---> l) (at a) <=> ((g ---> l) (at a)))`,
REWRITE_TAC[REALLIM_AT; GSYM DIST_NZ] THEN SIMP_TAC[]);;
extend_basic_congs [REALLIM_CONG_WITHIN; REALLIM_CONG_AT];;
let REALLIM_CONG_WITHINREAL = 
prove (`(!x. ~(x = a) ==> f x = g x) ==> (((\x. f x) ---> l) (atreal a within s) <=> ((g ---> l) (atreal a within s)))`,
let REALLIM_CONG_ATREAL = 
prove (`(!x. ~(x = a) ==> f x = g x) ==> (((\x. f x) ---> l) (atreal a) <=> ((g ---> l) (atreal a)))`,
extend_basic_congs [REALLIM_CONG_WITHINREAL; REALLIM_CONG_ATREAL];; (* ------------------------------------------------------------------------- *) (* Real version of Abel limit theorem. *) (* ------------------------------------------------------------------------- *)
let REAL_ABEL_LIMIT_THEOREM = 
prove (`!s a. real_summable s a ==> (!r. abs(r) < &1 ==> real_summable s (\i. a i * r pow i)) /\ ((\r. real_infsum s (\i. a i * r pow i)) ---> real_infsum s a) (atreal (&1) within {z | z <= &1})`,
REPEAT GEN_TAC THEN STRIP_TAC THEN MP_TAC(ISPECL [`&1`; `s:num->bool`; `Cx o (a:num->real)`] ABEL_LIMIT_THEOREM) THEN ASM_REWRITE_TAC[GSYM REAL_SUMMABLE_COMPLEX; REAL_LT_01] THEN STRIP_TAC THEN MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL [X_GEN_TAC `r:real` THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `Cx r`) THEN ASM_REWRITE_TAC[COMPLEX_NORM_CX; REAL_SUMMABLE_COMPLEX] THEN REWRITE_TAC[o_DEF; CX_MUL; CX_POW]; DISCH_TAC] THEN REWRITE_TAC[REALLIM_COMPLEX; LIM_WITHINREAL_WITHINCOMPLEX] THEN MATCH_MP_TAC LIM_TRANSFORM_WITHIN THEN EXISTS_TAC `\z. infsum s (\i. (Cx o a) i * z pow i)` THEN EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN CONJ_TAC THENL [REWRITE_TAC[IMP_CONJ; IN_INTER; IN_ELIM_THM; IN_IMAGE] THEN REWRITE_TAC[IN; FORALL_REAL] THEN X_GEN_TAC `r:real` THEN REWRITE_TAC[CX_INJ; UNWIND_THM1; dist; GSYM CX_SUB; COMPLEX_NORM_CX] THEN DISCH_TAC THEN ASM_SIMP_TAC[REAL_ARITH `r <= &1 ==> (&0 < abs(r - &1) <=> r < &1)`] THEN REPEAT DISCH_TAC THEN SUBGOAL_THEN `abs(r) < &1` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN ASM_SIMP_TAC[REAL_INFSUM_COMPLEX; o_THM; RE_CX] THEN CONV_TAC SYM_CONV THEN REWRITE_TAC[GSYM REAL; o_DEF; CX_MUL; CX_POW] THEN MATCH_MP_TAC(ISPEC `sequentially` REAL_LIM) THEN EXISTS_TAC `\n. vsum(s INTER (0..n)) (\i. Cx(a i) * Cx r pow i)` THEN REWRITE_TAC[SEQUENTIALLY; TRIVIAL_LIMIT_SEQUENTIALLY; GSYM sums] THEN SIMP_TAC[GSYM CX_POW; GSYM CX_MUL; REAL_VSUM; FINITE_INTER; FINITE_NUMSEG; SUMS_INFSUM; REAL_CX; GE] THEN CONJ_TAC THENL [ALL_TAC; MESON_TAC[LE_REFL]] THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN ASM_SIMP_TAC[GSYM REAL_SUMMABLE_COMPLEX]; ALL_TAC] THEN ASM_SIMP_TAC[REAL_INFSUM_COMPLEX] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_WITHIN]) THEN REWRITE_TAC[LIM_WITHIN] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[REAL_MUL_LID; IN_ELIM_THM; IN_INTER; IN_IMAGE] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "*"))) THEN EXISTS_TAC `min d (&1)` THEN ASM_REWRITE_TAC[REAL_LT_MIN; REAL_LT_01] THEN REWRITE_TAC[IMP_CONJ; IN; FORALL_REAL] THEN REWRITE_TAC[CX_INJ; UNWIND_THM1; dist; GSYM CX_SUB; COMPLEX_NORM_CX] THEN X_GEN_TAC `r:real` THEN DISCH_TAC THEN ASM_SIMP_TAC[REAL_ARITH `r <= &1 ==> (&0 < abs(r - &1) <=> r < &1)`] THEN REPEAT DISCH_TAC THEN SUBGOAL_THEN `abs(r) < &1` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN REMOVE_THEN "*" (MP_TAC o SPEC `Cx r`) THEN REWRITE_TAC[CX_INJ; UNWIND_THM1; dist; GSYM CX_SUB; COMPLEX_NORM_CX] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC(NORM_ARITH `b = a ==> norm(x - a) < e ==> norm(x - b) < e`) THEN REWRITE_TAC[GSYM REAL] THEN MATCH_MP_TAC(ISPEC `sequentially` REAL_LIM) THEN EXISTS_TAC `\n. vsum(s INTER (0..n)) (Cx o a)` THEN REWRITE_TAC[SEQUENTIALLY; TRIVIAL_LIMIT_SEQUENTIALLY; GSYM sums] THEN SIMP_TAC[GSYM CX_POW; GSYM CX_MUL; REAL_VSUM; FINITE_INTER; FINITE_NUMSEG; SUMS_INFSUM; REAL_CX; GE; o_DEF] THEN CONJ_TAC THENL [ALL_TAC; MESON_TAC[LE_REFL]] THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN ASM_SIMP_TAC[GSYM REAL_SUMMABLE_COMPLEX]);;
(* ------------------------------------------------------------------------- *) (* Continuity of a function into the reals. *) (* ------------------------------------------------------------------------- *) parse_as_infix ("real_continuous",(12,"right"));;
let real_continuous = new_definition
  `f real_continuous net <=> (f ---> f(netlimit net)) net`;;
let REAL_CONTINUOUS_TRIVIAL_LIMIT = 
prove (`!f net. trivial_limit net ==> f real_continuous net`,
SIMP_TAC[real_continuous; REALLIM]);;
let REAL_CONTINUOUS_WITHIN = 
prove (`!f x:real^N s. f real_continuous (at x within s) <=> (f ---> f(x)) (at x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous] THEN ASM_CASES_TAC `trivial_limit(at(x:real^N) within s)` THENL [ASM_REWRITE_TAC[REALLIM]; ASM_SIMP_TAC[NETLIMIT_WITHIN]]);;
let REAL_CONTINUOUS_AT = 
prove (`!f x. f real_continuous (at x) <=> (f ---> f(x)) (at x)`,
ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_WITHIN; IN_UNIV]);;
let REAL_CONTINUOUS_WITHINREAL = 
prove (`!f x s. f real_continuous (atreal x within s) <=> (f ---> f(x)) (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous] THEN ASM_CASES_TAC `trivial_limit(atreal x within s)` THENL [ASM_REWRITE_TAC[REALLIM]; ASM_SIMP_TAC[NETLIMIT_WITHINREAL]]);;
let REAL_CONTINUOUS_ATREAL = 
prove (`!f x. f real_continuous (atreal x) <=> (f ---> f(x)) (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_WITHINREAL; IN_UNIV]);;
let CONTINUOUS_WITHINREAL = 
prove (`!f x s. f continuous (atreal x within s) <=> (f --> f(x)) (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[continuous] THEN ASM_CASES_TAC `trivial_limit(atreal x within s)` THENL [ASM_REWRITE_TAC[LIM]; ASM_SIMP_TAC[NETLIMIT_WITHINREAL]]);;
let CONTINUOUS_ATREAL = 
prove (`!f x. f continuous (atreal x) <=> (f --> f(x)) (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[CONTINUOUS_WITHINREAL; IN_UNIV]);;
let real_continuous_within = 
prove (`f real_continuous (at x within s) <=> !e. &0 < e ==> ?d. &0 < d /\ (!x'. x' IN s /\ dist(x',x) < d ==> abs(f x' - f x) < e)`,
REWRITE_TAC[REAL_CONTINUOUS_WITHIN; REALLIM_WITHIN] THEN REWRITE_TAC[GSYM DIST_NZ] THEN EQ_TAC THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN ASM_MESON_TAC[REAL_ARITH `abs(x - x) = &0`]);;
let real_continuous_at = 
prove (`f real_continuous (at x) <=> !e. &0 < e ==> ?d. &0 < d /\ (!x'. dist(x',x) < d ==> abs(f x' - f x) < e)`,
ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[real_continuous_within; IN_UNIV]);;
let real_continuous_withinreal = 
prove (`f real_continuous (atreal x within s) <=> !e. &0 < e ==> ?d. &0 < d /\ (!x'. x' IN s /\ abs(x' - x) < d ==> abs(f x' - f x) < e)`,
REWRITE_TAC[REAL_CONTINUOUS_WITHINREAL; REALLIM_WITHINREAL] THEN REWRITE_TAC[REAL_ARITH `&0 < abs(x - y) <=> ~(x = y)`] THEN EQ_TAC THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN ASM_MESON_TAC[REAL_ARITH `abs(x - x) = &0`]);;
let real_continuous_atreal = 
prove (`f real_continuous (atreal x) <=> !e. &0 < e ==> ?d. &0 < d /\ (!x'. abs(x' - x) < d ==> abs(f x' - f x) < e)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[real_continuous_withinreal; IN_UNIV]);;
let REAL_CONTINUOUS_AT_WITHIN = 
prove (`!f s x. f real_continuous (at x) ==> f real_continuous (at x within s)`,
REWRITE_TAC[real_continuous_within; real_continuous_at] THEN MESON_TAC[]);;
let REAL_CONTINUOUS_ATREAL_WITHINREAL = 
prove (`!f s x. f real_continuous (atreal x) ==> f real_continuous (atreal x within s)`,
REWRITE_TAC[real_continuous_withinreal; real_continuous_atreal] THEN MESON_TAC[]);;
let REAL_CONTINUOUS_WITHINREAL_SUBSET = 
prove (`!f s t. f real_continuous (atreal x within s) /\ t SUBSET s ==> f real_continuous (atreal x within t)`,
let REAL_CONTINUOUS_WITHIN_SUBSET = 
prove (`!f s t. f real_continuous (at x within s) /\ t SUBSET s ==> f real_continuous (at x within t)`,
let CONTINUOUS_WITHINREAL_SUBSET = 
prove (`!f s t. f continuous (atreal x within s) /\ t SUBSET s ==> f continuous (atreal x within t)`,
let continuous_withinreal = 
prove (`f continuous (atreal x within s) <=> !e. &0 < e ==> ?d. &0 < d /\ (!x'. x' IN s /\ abs(x' - x) < d ==> dist(f x',f x) < e)`,
REWRITE_TAC[CONTINUOUS_WITHINREAL; LIM_WITHINREAL] THEN REWRITE_TAC[REAL_ARITH `&0 < abs(x - y) <=> ~(x = y)`] THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `d:real` THEN ASM_CASES_TAC `&0 < d` THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN ABS_TAC THEN ASM_MESON_TAC[DIST_REFL]);;
let continuous_atreal = 
prove (`f continuous (atreal x) <=> !e. &0 < e ==> ?d. &0 < d /\ (!x'. abs(x' - x) < d ==> dist(f x',f x) < e)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[continuous_withinreal; IN_UNIV]);;
let CONTINUOUS_ATREAL_WITHINREAL = 
prove (`!f x s. f continuous (atreal x) ==> f continuous (atreal x within s)`,
SIMP_TAC[continuous_atreal; continuous_withinreal] THEN MESON_TAC[]);;
let CONTINUOUS_CX_ATREAL = 
prove (`!x. Cx continuous (atreal x)`,
GEN_TAC THEN REWRITE_TAC[continuous_atreal; dist] THEN REWRITE_TAC[COMPLEX_NORM_CX; GSYM CX_SUB] THEN MESON_TAC[]);;
let CONTINUOUS_CX_WITHINREAL = 
prove (`!s x. Cx continuous (atreal x within s)`,
(* ------------------------------------------------------------------------- *) (* Arithmetic combining theorems. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_CONST = 
prove (`!net c. (\x. c) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_CONST]);;
let REAL_CONTINUOUS_LMUL = 
prove (`!f c net. f real_continuous net ==> (\x. c * f(x)) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_LMUL]);;
let REAL_CONTINUOUS_RMUL = 
prove (`!f c net. f real_continuous net ==> (\x. f(x) * c) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_RMUL]);;
let REAL_CONTINUOUS_NEG = 
prove (`!f net. f real_continuous net ==> (\x. --(f x)) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_NEG]);;
let REAL_CONTINUOUS_ADD = 
prove (`!f g net. f real_continuous net /\ g real_continuous net ==> (\x. f(x) + g(x)) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_ADD]);;
let REAL_CONTINUOUS_SUB = 
prove (`!f g net. f real_continuous net /\ g real_continuous net ==> (\x. f(x) - g(x)) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_SUB]);;
let REAL_CONTINUOUS_MUL = 
prove (`!net f g. f real_continuous net /\ g real_continuous net ==> (\x. f(x) * g(x)) real_continuous net`,
let REAL_CONTINUOUS_INV = 
prove (`!net f. f real_continuous net /\ ~(f(netlimit net) = &0) ==> (\x. inv(f x)) real_continuous net`,
let REAL_CONTINUOUS_DIV = 
prove (`!net f g. f real_continuous net /\ g real_continuous net /\ ~(g(netlimit net) = &0) ==> (\x. f(x) / g(x)) real_continuous net`,
let REAL_CONTINUOUS_POW = 
prove (`!net f n. f real_continuous net ==> (\x. f(x) pow n) real_continuous net`,
let REAL_CONTINUOUS_ABS = 
prove (`!net f. f real_continuous net ==> (\x. abs(f(x))) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_ABS]);;
let REAL_CONTINUOUS_MAX = 
prove (`!f g net. f real_continuous net /\ g real_continuous net ==> (\x. max (f x) (g x)) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_MAX]);;
let REAL_CONTINUOUS_MIN = 
prove (`!f g net. f real_continuous net /\ g real_continuous net ==> (\x. min (f x) (g x)) real_continuous net`,
REWRITE_TAC[real_continuous; REALLIM_MIN]);;
(* ------------------------------------------------------------------------- *) (* Some of these without netlimit, but with many different cases. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_WITHIN_ID = 
prove (`!x s. (\x. x) real_continuous (atreal x within s)`,
REWRITE_TAC[real_continuous_withinreal] THEN MESON_TAC[]);;
let REAL_CONTINUOUS_AT_ID = 
prove (`!x. (\x. x) real_continuous (atreal x)`,
REWRITE_TAC[real_continuous_atreal] THEN MESON_TAC[]);;
let REAL_CONTINUOUS_INV_WITHIN = 
prove (`!f s a. f real_continuous (at a within s) /\ ~(f a = &0) ==> (\x. inv(f x)) real_continuous (at a within s)`,
let REAL_CONTINUOUS_INV_AT = 
prove (`!f a. f real_continuous (at a) /\ ~(f a = &0) ==> (\x. inv(f x)) real_continuous (at a)`,
ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_INV_WITHIN]);;
let REAL_CONTINUOUS_INV_WITHINREAL = 
prove (`!f s a. f real_continuous (atreal a within s) /\ ~(f a = &0) ==> (\x. inv(f x)) real_continuous (atreal a within s)`,
let REAL_CONTINUOUS_INV_ATREAL = 
prove (`!f a. f real_continuous (atreal a) /\ ~(f a = &0) ==> (\x. inv(f x)) real_continuous (atreal a)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_INV_WITHINREAL]);;
let REAL_CONTINUOUS_DIV_WITHIN = 
prove (`!f s a. f real_continuous (at a within s) /\ g real_continuous (at a within s) /\ ~(g a = &0) ==> (\x. f x / g x) real_continuous (at a within s)`,
let REAL_CONTINUOUS_DIV_AT = 
prove (`!f a. f real_continuous (at a) /\ g real_continuous (at a) /\ ~(g a = &0) ==> (\x. f x / g x) real_continuous (at a)`,
ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_DIV_WITHIN]);;
let REAL_CONTINUOUS_DIV_WITHINREAL = 
prove (`!f s a. f real_continuous (atreal a within s) /\ g real_continuous (atreal a within s) /\ ~(g a = &0) ==> (\x. f x / g x) real_continuous (atreal a within s)`,
let REAL_CONTINUOUS_DIV_ATREAL = 
prove (`!f a. f real_continuous (atreal a) /\ g real_continuous (atreal a) /\ ~(g a = &0) ==> (\x. f x / g x) real_continuous (atreal a)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_DIV_WITHINREAL]);;
(* ------------------------------------------------------------------------- *) (* Composition of (real->real) o (real->real) functions. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_WITHINREAL_COMPOSE = 
prove (`!f g x s. f real_continuous (atreal x within s) /\ g real_continuous (atreal (f x) within IMAGE f s) ==> (g o f) real_continuous (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous_withinreal; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
let REAL_CONTINUOUS_ATREAL_COMPOSE = 
prove (`!f g x. f real_continuous (atreal x) /\ g real_continuous (atreal (f x)) ==> (g o f) real_continuous (atreal x)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous_atreal; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Composition of (real->real) o (real^N->real) functions. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_WITHIN_COMPOSE = 
prove (`!f g x s. f real_continuous (at x within s) /\ g real_continuous (atreal (f x) within IMAGE f s) ==> (g o f) real_continuous (at x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous_withinreal; real_continuous_within; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
let REAL_CONTINUOUS_AT_COMPOSE = 
prove (`!f g x. f real_continuous (at x) /\ g real_continuous (atreal (f x) within IMAGE f (:real^N)) ==> (g o f) real_continuous (at x)`,
ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_WITHIN_COMPOSE]);;
(* ------------------------------------------------------------------------- *) (* Composition of (real^N->real) o (real^M->real^N) functions. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_CONTINUOUS_WITHIN_COMPOSE = 
prove (`!f g x s. f continuous (at x within s) /\ g real_continuous (at (f x) within IMAGE f s) ==> (g o f) real_continuous (at x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous_within; continuous_within; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
let REAL_CONTINUOUS_CONTINUOUS_AT_COMPOSE = 
prove (`!f g x. f continuous (at x) /\ g real_continuous (at (f x) within IMAGE f (:real^N)) ==> (g o f) real_continuous (at x)`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[WITHIN_WITHIN; INTER_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_CONTINUOUS_WITHIN_COMPOSE]);;
(* ------------------------------------------------------------------------- *) (* Composition of (real^N->real) o (real->real^N) functions. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_CONTINUOUS_WITHINREAL_COMPOSE = 
prove (`!f g x s. f continuous (atreal x within s) /\ g real_continuous (at (f x) within IMAGE f s) ==> (g o f) real_continuous (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous_within; continuous_withinreal; real_continuous_withinreal; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
let REAL_CONTINUOUS_CONTINUOUS_ATREAL_COMPOSE = 
prove (`!f g x. f continuous (atreal x) /\ g real_continuous (at (f x) within IMAGE f (:real)) ==> (g o f) real_continuous (atreal x)`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[REAL_CONTINUOUS_CONTINUOUS_WITHINREAL_COMPOSE]);;
(* ------------------------------------------------------------------------- *) (* Composition of (real->real^N) o (real->real) functions. *) (* ------------------------------------------------------------------------- *)
let CONTINUOUS_REAL_CONTINUOUS_WITHINREAL_COMPOSE = 
prove (`!f g x s. f real_continuous (atreal x within s) /\ g continuous (atreal (f x) within IMAGE f s) ==> (g o f) continuous (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_continuous_within; continuous_withinreal; real_continuous_withinreal; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
let CONTINUOUS_REAL_CONTINUOUS_ATREAL_COMPOSE = 
prove (`!f g x. f real_continuous (atreal x) /\ g continuous (atreal (f x) within IMAGE f (:real)) ==> (g o f) continuous (atreal x)`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[WITHIN_WITHIN; INTER_UNIV] THEN REWRITE_TAC[CONTINUOUS_REAL_CONTINUOUS_WITHINREAL_COMPOSE]);;
(* ------------------------------------------------------------------------- *) (* Composition of (real^M->real^N) o (real->real^M) functions. *) (* ------------------------------------------------------------------------- *)
let CONTINUOUS_WITHINREAL_COMPOSE = 
prove (`!f g x s. f continuous (atreal x within s) /\ g continuous (at (f x) within IMAGE f s) ==> (g o f) continuous (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within; continuous_withinreal; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
let CONTINUOUS_ATREAL_COMPOSE = 
prove (`!f g x. f continuous (atreal x) /\ g continuous (at (f x) within IMAGE f (:real)) ==> (g o f) continuous (atreal x)`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[WITHIN_WITHIN; INTER_UNIV] THEN REWRITE_TAC[CONTINUOUS_WITHINREAL_COMPOSE]);;
(* ------------------------------------------------------------------------- *) (* Composition of (real->real^N) o (real^M->real) functions. *) (* ------------------------------------------------------------------------- *)
let CONTINUOUS_REAL_CONTINUOUS_WITHIN_COMPOSE = 
prove (`!f g x s. f real_continuous (at x within s) /\ g continuous (atreal (f x) within IMAGE f s) ==> (g o f) continuous (at x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within; real_continuous_within; continuous_withinreal; o_THM; IN_IMAGE] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_MESON_TAC[]);;
let CONTINUOUS_REAL_CONTINUOUS_AT_COMPOSE = 
prove (`!f g x. f real_continuous (at x) /\ g continuous (atreal (f x) within IMAGE f (:real^M)) ==> (g o f) continuous (at x)`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[WITHIN_WITHIN; INTER_UNIV] THEN REWRITE_TAC[CONTINUOUS_REAL_CONTINUOUS_WITHIN_COMPOSE]);;
(* ------------------------------------------------------------------------- *) (* Continuity of a real->real function on a set. *) (* ------------------------------------------------------------------------- *) parse_as_infix ("real_continuous_on",(12,"right"));;
let real_continuous_on = new_definition
  `f real_continuous_on s <=>
        !x. x IN s ==> !e. &0 < e
                           ==> ?d. &0 < d /\
                                   !x'. x' IN s /\ abs(x' - x) < d
                                        ==> abs(f(x') - f(x)) < e`;;
let REAL_CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN = 
prove (`!f s. f real_continuous_on s <=> !x. x IN s ==> f real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_SUBSET = 
prove (`!f s t. f real_continuous_on s /\ t SUBSET s ==> f real_continuous_on t`,
REWRITE_TAC[real_continuous_on; SUBSET] THEN MESON_TAC[]);;
let REAL_CONTINUOUS_ON_COMPOSE = 
prove (`!f g s. f real_continuous_on s /\ g real_continuous_on (IMAGE f s) ==> (g o f) real_continuous_on s`,
let REAL_CONTINUOUS_ON = 
prove (`!f s. f real_continuous_on s <=> (lift o f o drop) continuous_on (IMAGE lift s)`,
let REAL_CONTINUOUS_ON_CONST = 
prove (`!s c. (\x. c) real_continuous_on s`,
let REAL_CONTINUOUS_ON_ID = 
prove (`!s. (\x. x) real_continuous_on s`,
let REAL_CONTINUOUS_ON_LMUL = 
prove (`!f c s. f real_continuous_on s ==> (\x. c * f(x)) real_continuous_on s`,
let REAL_CONTINUOUS_ON_RMUL = 
prove (`!f c s. f real_continuous_on s ==> (\x. f(x) * c) real_continuous_on s`,
let REAL_CONTINUOUS_ON_NEG = 
prove (`!f s. f real_continuous_on s ==> (\x. --(f x)) real_continuous_on s`,
let REAL_CONTINUOUS_ON_ADD = 
prove (`!f g s. f real_continuous_on s /\ g real_continuous_on s ==> (\x. f(x) + g(x)) real_continuous_on s`,
let REAL_CONTINUOUS_ON_SUB = 
prove (`!f g s. f real_continuous_on s /\ g real_continuous_on s ==> (\x. f(x) - g(x)) real_continuous_on s`,
let REAL_CONTINUOUS_ON_MUL = 
prove (`!f g s. f real_continuous_on s /\ g real_continuous_on s ==> (\x. f(x) * g(x)) real_continuous_on s`,
let REAL_CONTINUOUS_ON_POW = 
prove (`!f n s. f real_continuous_on s ==> (\x. f(x) pow n) real_continuous_on s`,
let REAL_CONTINUOUS_ON_EQ = 
prove (`!f g s. (!x. x IN s ==> f(x) = g(x)) /\ f real_continuous_on s ==> g real_continuous_on s`,
let REAL_CONTINUOUS_ON_UNION = 
prove (`!f s t. real_closed s /\ real_closed t /\ f real_continuous_on s /\ f real_continuous_on t ==> f real_continuous_on (s UNION t)`,
let REAL_CONTINUOUS_ON_UNION_OPEN = 
prove (`!f s t. real_open s /\ real_open t /\ f real_continuous_on s /\ f real_continuous_on t ==> f real_continuous_on (s UNION t)`,
let REAL_CONTINUOUS_ON_CASES = 
prove (`!P f g s t. real_closed s /\ real_closed t /\ f real_continuous_on s /\ g real_continuous_on t /\ (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x) ==> (\x. if P x then f x else g x) real_continuous_on (s UNION t)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_ON_UNION THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_ON_EQ THENL [EXISTS_TAC `f:real->real`; EXISTS_TAC `g:real->real`] THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
let REAL_CONTINUOUS_ON_CASES_OPEN = 
prove (`!P f g s t. real_open s /\ real_open t /\ f real_continuous_on s /\ g real_continuous_on t /\ (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x) ==> (\x. if P x then f x else g x) real_continuous_on (s UNION t)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_ON_UNION_OPEN THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_ON_EQ THENL [EXISTS_TAC `f:real->real`; EXISTS_TAC `g:real->real`] THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
let REAL_CONTINUOUS_ON_SUM = 
prove (`!t f s. FINITE s /\ (!a. a IN s ==> f a real_continuous_on t) ==> (\x. sum s (\a. f a x)) real_continuous_on t`,
REPEAT GEN_TAC THEN SIMP_TAC[REAL_CONTINUOUS_ON; o_DEF; LIFT_SUM] THEN DISCH_THEN(MP_TAC o MATCH_MP CONTINUOUS_ON_VSUM) THEN REWRITE_TAC[]);;
let REALLIM_CONTINUOUS_FUNCTION = 
prove (`!f net g l. f continuous (atreal l) /\ (g ---> l) net ==> ((\x. f(g x)) --> f l) net`,
REWRITE_TAC[tendsto_real; tendsto; continuous_atreal; eventually] THEN MESON_TAC[]);;
let LIM_REAL_CONTINUOUS_FUNCTION = 
prove (`!f net g l. f real_continuous (at l) /\ (g --> l) net ==> ((\x. f(g x)) ---> f l) net`,
REWRITE_TAC[tendsto_real; tendsto; real_continuous_at; eventually] THEN MESON_TAC[]);;
let REALLIM_REAL_CONTINUOUS_FUNCTION = 
prove (`!f net g l. f real_continuous (atreal l) /\ (g ---> l) net ==> ((\x. f(g x)) ---> f l) net`,
REWRITE_TAC[tendsto_real; real_continuous_atreal; eventually] THEN MESON_TAC[]);;
let REAL_CONTINUOUS_ON_EQ_REAL_CONTINUOUS_AT = 
prove (`!f s. real_open s ==> (f real_continuous_on s <=> !x. x IN s ==> f real_continuous atreal x)`,
let REAL_CONTINUOUS_ATTAINS_SUP = 
prove (`!f s. real_compact s /\ ~(s = {}) /\ f real_continuous_on s ==> ?x. x IN s /\ (!y. y IN s ==> f y <= f x)`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`(f:real->real) o drop`; `IMAGE lift s`] CONTINUOUS_ATTAINS_SUP) THEN ASM_REWRITE_TAC[GSYM REAL_CONTINUOUS_ON; GSYM real_compact] THEN ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; EXISTS_IN_IMAGE; FORALL_IN_IMAGE] THEN REWRITE_TAC[o_THM; LIFT_DROP]);;
let REAL_CONTINUOUS_ATTAINS_INF = 
prove (`!f s. real_compact s /\ ~(s = {}) /\ f real_continuous_on s ==> ?x. x IN s /\ (!y. y IN s ==> f x <= f y)`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`(f:real->real) o drop`; `IMAGE lift s`] CONTINUOUS_ATTAINS_INF) THEN ASM_REWRITE_TAC[GSYM REAL_CONTINUOUS_ON; GSYM real_compact] THEN ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; EXISTS_IN_IMAGE; FORALL_IN_IMAGE] THEN REWRITE_TAC[o_THM; LIFT_DROP]);;
(* ------------------------------------------------------------------------- *) (* Real version of uniform continuity. *) (* ------------------------------------------------------------------------- *) parse_as_infix ("real_uniformly_continuous_on",(12,"right"));;
let real_uniformly_continuous_on = new_definition
  `f real_uniformly_continuous_on s <=>
        !e. &0 < e
            ==> ?d. &0 < d /\
                    !x x'. x IN s /\ x' IN s /\ abs(x' - x) < d
                           ==> abs(f x' - f x) < e`;;
let REAL_UNIFORMLY_CONTINUOUS_ON = 
prove (`!f s. f real_uniformly_continuous_on s <=> (lift o f o drop) uniformly_continuous_on (IMAGE lift s)`,
let REAL_UNIFORMLY_CONTINUOUS_IMP_REAL_CONTINUOUS = 
prove (`!f s. f real_uniformly_continuous_on s ==> f real_continuous_on s`,
REWRITE_TAC[real_uniformly_continuous_on; real_continuous_on] THEN MESON_TAC[]);;
let REAL_UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY = 
prove (`!f s. f real_uniformly_continuous_on s <=> !x y. (!n. x(n) IN s) /\ (!n. y(n) IN s) /\ ((\n. x(n) - y(n)) ---> &0) sequentially ==> ((\n. f(x(n)) - f(y(n))) ---> &0) sequentially`,
let REAL_UNIFORMLY_CONTINUOUS_ON_SUBSET = 
prove (`!f s t. f real_uniformly_continuous_on s /\ t SUBSET s ==> f real_uniformly_continuous_on t`,
REWRITE_TAC[real_uniformly_continuous_on; SUBSET] THEN MESON_TAC[]);;
let REAL_UNIFORMLY_CONTINUOUS_ON_COMPOSE = 
prove (`!f g s. f real_uniformly_continuous_on s /\ g real_uniformly_continuous_on (IMAGE f s) ==> (g o f) real_uniformly_continuous_on s`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_UNIFORMLY_CONTINUOUS_ON] THEN SUBGOAL_THEN `IMAGE lift (IMAGE f s) = IMAGE (lift o f o drop) (IMAGE lift s)` SUBST1_TAC THENL [ALL_TAC; DISCH_THEN(MP_TAC o MATCH_MP UNIFORMLY_CONTINUOUS_ON_COMPOSE)] THEN REWRITE_TAC[GSYM IMAGE_o; o_DEF; LIFT_DROP]);;
let REAL_UNIFORMLY_CONTINUOUS_ON_CONST = 
prove (`!s c. (\x. c) real_uniformly_continuous_on s`,
let REAL_UNIFORMLY_CONTINUOUS_ON_LMUL = 
prove (`!f c s. f real_uniformly_continuous_on s ==> (\x. c * f(x)) real_uniformly_continuous_on s`,
let REAL_UNIFORMLY_CONTINUOUS_ON_RMUL = 
prove (`!f c s. f real_uniformly_continuous_on s ==> (\x. f(x) * c) real_uniformly_continuous_on s`,
ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REAL_UNIFORMLY_CONTINUOUS_ON_LMUL]);;
let REAL_UNIFORMLY_CONTINUOUS_ON_ID = 
prove (`!s. (\x. x) real_uniformly_continuous_on s`,
REWRITE_TAC[real_uniformly_continuous_on] THEN MESON_TAC[]);;
let REAL_UNIFORMLY_CONTINUOUS_ON_NEG = 
prove (`!f s. f real_uniformly_continuous_on s ==> (\x. --(f x)) real_uniformly_continuous_on s`,
ONCE_REWRITE_TAC[REAL_ARITH `--x = -- &1 * x`] THEN REWRITE_TAC[REAL_UNIFORMLY_CONTINUOUS_ON_LMUL]);;
let REAL_UNIFORMLY_CONTINUOUS_ON_ADD = 
prove (`!f g s. f real_uniformly_continuous_on s /\ g real_uniformly_continuous_on s ==> (\x. f(x) + g(x)) real_uniformly_continuous_on s`,
let REAL_UNIFORMLY_CONTINUOUS_ON_SUB = 
prove (`!f g s. f real_uniformly_continuous_on s /\ g real_uniformly_continuous_on s ==> (\x. f(x) - g(x)) real_uniformly_continuous_on s`,
let REAL_UNIFORMLY_CONTINUOUS_ON_SUM = 
prove (`!t f s. FINITE s /\ (!a. a IN s ==> f a real_uniformly_continuous_on t) ==> (\x. sum s (\a. f a x)) real_uniformly_continuous_on t`,
REPEAT GEN_TAC THEN SIMP_TAC[REAL_UNIFORMLY_CONTINUOUS_ON; o_DEF; LIFT_SUM] THEN DISCH_THEN(MP_TAC o MATCH_MP UNIFORMLY_CONTINUOUS_ON_VSUM) THEN REWRITE_TAC[]);;
let REAL_COMPACT_UNIFORMLY_CONTINUOUS = 
prove (`!f s. f real_continuous_on s /\ real_compact s ==> f real_uniformly_continuous_on s`,
let REAL_COMPACT_CONTINUOUS_IMAGE = 
prove (`!f s. f real_continuous_on s /\ real_compact s ==> real_compact (IMAGE f s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_compact; REAL_CONTINUOUS_ON] THEN DISCH_THEN(MP_TAC o MATCH_MP COMPACT_CONTINUOUS_IMAGE) THEN REWRITE_TAC[GSYM IMAGE_o; o_DEF; LIFT_DROP]);;
let REAL_DINI = 
prove (`!f g s. real_compact s /\ (!n. (f n) real_continuous_on s) /\ g real_continuous_on s /\ (!x. x IN s ==> ((\n. (f n x)) ---> g x) sequentially) /\ (!n x. x IN s ==> f n x <= f (n + 1) x) ==> !e. &0 < e ==> eventually (\n. !x. x IN s ==> abs(f n x - g x) < e) sequentially`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`\n:num. lift o f n o drop`; `lift o g o drop`; `IMAGE lift s`] DINI) THEN ASM_REWRITE_TAC[GSYM real_compact; GSYM REAL_CONTINUOUS_ON] THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE; o_DEF; LIFT_DROP; REAL_TENDSTO] THEN ASM_SIMP_TAC[GSYM LIFT_SUB; NORM_LIFT]);;
(* ------------------------------------------------------------------------- *) (* Continuity versus componentwise continuity. *) (* ------------------------------------------------------------------------- *)
let CONTINUOUS_COMPONENTWISE = 
prove (`!net f:A->real^N. f continuous net <=> !i. 1 <= i /\ i <= dimindex(:N) ==> (\x. (f x)$i) real_continuous net`,
let REAL_CONTINUOUS_COMPLEX_COMPONENTS_AT = 
prove (`!z. Re real_continuous (at z) /\ Im real_continuous (at z)`,
GEN_TAC THEN MP_TAC(ISPECL [`at(z:complex)`; `\z:complex. z`] CONTINUOUS_COMPONENTWISE) THEN REWRITE_TAC[CONTINUOUS_AT_ID; DIMINDEX_2; FORALL_2] THEN REWRITE_TAC[GSYM RE_DEF; GSYM IM_DEF; ETA_AX]);;
let REAL_CONTINUOUS_COMPLEX_COMPONENTS_WITHIN = 
prove (`!s z. Re real_continuous (at z within s) /\ Im real_continuous (at z within s)`,
let REAL_CONTINUOUS_NORM_AT = 
prove (`!z. norm real_continuous (at z)`,
REWRITE_TAC[real_continuous_at; dist] THEN GEN_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN NORM_ARITH_TAC);;
let REAL_CONTINUOUS_NORM_WITHIN = 
prove (`!s z. norm real_continuous (at z within s)`,
let REAL_CONTINUOUS_DIST_AT = 
prove (`!a z. (\x. dist(a,x)) real_continuous (at z)`,
REWRITE_TAC[real_continuous_at; dist] THEN GEN_TAC THEN GEN_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN NORM_ARITH_TAC);;
let REAL_CONTINUOUS_DIST_WITHIN = 
prove (`!a s z. (\x. dist(a,x)) real_continuous (at z within s)`,
(* ------------------------------------------------------------------------- *) (* Derivative of real->real function. *) (* ------------------------------------------------------------------------- *) parse_as_infix ("has_real_derivative",(12,"right"));; parse_as_infix ("real_differentiable",(12,"right"));; parse_as_infix ("real_differentiable_on",(12,"right"));;
let has_real_derivative = new_definition
 `(f has_real_derivative f') net <=>
        ((\x. inv(x - netlimit net) *
              (f x - (f(netlimit net) + f' * (x - netlimit net))))
         ---> &0) net`;;
let real_differentiable = new_definition
 `f real_differentiable net <=> ?f'. (f has_real_derivative f') net`;;
let real_derivative = new_definition
 `real_derivative f x = @f'. (f has_real_derivative f') (atreal x)`;;
let higher_real_derivative = define
 `higher_real_derivative 0 f = f /\
  (!n. higher_real_derivative (SUC n) f =
                real_derivative (higher_real_derivative n f))`;;
let real_differentiable_on = new_definition
 `f real_differentiable_on s <=>
     !x. x IN s ==> ?f'. (f has_real_derivative f') (atreal x within s)`;;
(* ------------------------------------------------------------------------- *) (* Basic limit definitions in the useful cases. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_WITHINREAL = 
prove (`(f has_real_derivative f') (atreal a within s) <=> ((\x. (f x - f a) / (x - a)) ---> f') (atreal a within s)`,
REWRITE_TAC[has_real_derivative] THEN ASM_CASES_TAC `trivial_limit(atreal a within s)` THENL [ASM_REWRITE_TAC[REALLIM]; ALL_TAC] THEN ASM_SIMP_TAC[NETLIMIT_WITHINREAL] THEN GEN_REWRITE_TAC RAND_CONV [REALLIM_NULL] THEN REWRITE_TAC[REALLIM_WITHINREAL; REAL_SUB_RZERO] THEN SIMP_TAC[REAL_FIELD `&0 < abs(x - a) ==> (fy - fa) / (x - a) - f' = inv(x - a) * (fy - (fa + f' * (x - a)))`]);;
let HAS_REAL_DERIVATIVE_ATREAL = 
prove (`(f has_real_derivative f') (atreal a) <=> ((\x. (f x - f a) / (x - a)) ---> f') (atreal a)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_WITHINREAL]);;
(* ------------------------------------------------------------------------- *) (* Relation to Frechet derivative. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_FRECHET_DERIVATIVE_WITHIN = 
prove (`(f has_real_derivative f') (atreal x within s) <=> ((lift o f o drop) has_derivative (\x. f' % x)) (at (lift x) within (IMAGE lift s))`,
REWRITE_TAC[has_derivative_within; HAS_REAL_DERIVATIVE_WITHINREAL] THEN REWRITE_TAC[o_THM; LIFT_DROP; LIM_WITHIN; REALLIM_WITHINREAL] THEN SIMP_TAC[LINEAR_COMPOSE_CMUL; LINEAR_ID; IMP_CONJ] THEN REWRITE_TAC[FORALL_IN_IMAGE; DIST_LIFT; GSYM LIFT_SUB; LIFT_DROP; NORM_ARITH `dist(x,vec 0) = norm x`; GSYM LIFT_CMUL; GSYM LIFT_ADD; NORM_LIFT] THEN SIMP_TAC[REAL_FIELD `&0 < abs(y - x) ==> fy - (fx + f' * (y - x)) = (y - x) * ((fy - fx) / (y - x) - f')`] THEN REWRITE_TAC[REAL_ABS_MUL; REAL_MUL_ASSOC; REAL_ABS_INV; REAL_ABS_ABS] THEN SIMP_TAC[REAL_LT_IMP_NZ; REAL_MUL_LINV; REAL_MUL_LID]);;
let HAS_REAL_FRECHET_DERIVATIVE_AT = 
prove (`(f has_real_derivative f') (atreal x) <=> ((lift o f o drop) has_derivative (\x. f' % x)) (at (lift x))`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV; GSYM WITHIN_UNIV] THEN REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN] THEN REWRITE_TAC[IMAGE_LIFT_UNIV]);;
let HAS_REAL_VECTOR_DERIVATIVE_WITHIN = 
prove (`(f has_real_derivative f') (atreal x within s) <=> ((lift o f o drop) has_vector_derivative (lift f')) (at (lift x) within (IMAGE lift s))`,
REWRITE_TAC[has_vector_derivative; HAS_REAL_FRECHET_DERIVATIVE_WITHIN] THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM; FORALL_LIFT; GSYM LIFT_CMUL] THEN REWRITE_TAC[LIFT_DROP; LIFT_EQ; REAL_MUL_SYM]);;
let HAS_REAL_VECTOR_DERIVATIVE_AT = 
prove (`(f has_real_derivative f') (atreal x) <=> ((lift o f o drop) has_vector_derivative (lift f')) (at (lift x))`,
REWRITE_TAC[has_vector_derivative; HAS_REAL_FRECHET_DERIVATIVE_AT] THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM; FORALL_LIFT; GSYM LIFT_CMUL] THEN REWRITE_TAC[LIFT_DROP; LIFT_EQ; REAL_MUL_SYM]);;
let REAL_DIFFERENTIABLE_AT = 
prove (`!f a. f real_differentiable (atreal x) <=> (lift o f o drop) differentiable (at(lift x))`,
REWRITE_TAC[real_differentiable; HAS_REAL_FRECHET_DERIVATIVE_AT] THEN REWRITE_TAC[differentiable; has_derivative; LINEAR_SCALING] THEN REWRITE_TAC[LINEAR_1; LEFT_AND_EXISTS_THM] THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2]);;
let REAL_DIFFERENTIABLE_WITHIN = 
prove (`!f a s. f real_differentiable (atreal x within s) <=> (lift o f o drop) differentiable (at(lift x) within IMAGE lift s)`,
REWRITE_TAC[real_differentiable; HAS_REAL_FRECHET_DERIVATIVE_WITHIN] THEN REWRITE_TAC[differentiable; has_derivative; LINEAR_SCALING] THEN REWRITE_TAC[LINEAR_1; LEFT_AND_EXISTS_THM] THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2]);;
(* ------------------------------------------------------------------------- *) (* Relation to complex derivative. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_COMPLEX_DERIVATIVE_WITHIN = 
prove (`(f has_real_derivative f') (atreal a within s) <=> ((Cx o f o Re) has_complex_derivative (Cx f')) (at (Cx a) within {z | real z /\ Re z IN s})`,
let HAS_REAL_COMPLEX_DERIVATIVE_AT = 
prove (`(f has_real_derivative f') (atreal a) <=> ((Cx o f o Re) has_complex_derivative (Cx f')) (at (Cx a) within real)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN AP_TERM_TAC THEN AP_TERM_TAC THEN SET_TAC[]);;
let REAL_DIFFERENTIABLE_ON_DIFFERENTIABLE = 
prove (`!f s. f real_differentiable_on s <=> !x. x IN s ==> f real_differentiable (atreal x within s)`,
let REAL_DIFFERENTIABLE_ON_REAL_OPEN = 
prove (`!f s. real_open s ==> (f real_differentiable_on s <=> !x. x IN s ==> ?f'. (f has_real_derivative f') (atreal x))`,
let REAL_DIFFERENTIABLE_ON_IMP_DIFFERENTIABLE_WITHIN = 
prove (`!f s x. f real_differentiable_on s /\ x IN s ==> f real_differentiable (atreal x within s)`,
let REAL_DIFFERENTIABLE_ON_IMP_DIFFERENTIABLE_ATREAL = 
prove (`!f s x. f real_differentiable_on s /\ real_open s /\ x IN s ==> f real_differentiable (atreal x)`,
let HAS_COMPLEX_REAL_DERIVATIVE_WITHIN_GEN = 
prove (`!f g h s d. &0 < d /\ x IN s /\ (h has_complex_derivative Cx(g)) (at (Cx x) within {z | real z /\ Re(z) IN s}) /\ (!y. y IN s /\ abs(y - x) < d ==> h(Cx y) = Cx(f y)) ==> (f has_real_derivative g) (atreal x within s)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN THEN MAP_EVERY EXISTS_TAC [`h:complex->complex`; `d:real`] THEN ASM_REWRITE_TAC[IN_ELIM_THM; o_THM; REAL_CX; RE_CX; dist] THEN X_GEN_TAC `w:complex` THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `Re w`) THEN FIRST_X_ASSUM(SUBST_ALL_TAC o SYM o GEN_REWRITE_RULE I [REAL]) THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM CX_SUB; COMPLEX_NORM_CX]) THEN ASM_REWRITE_TAC[RE_CX]);;
let HAS_COMPLEX_REAL_DERIVATIVE_AT_GEN = 
prove (`!f g h d. &0 < d /\ (h has_complex_derivative Cx(g)) (at (Cx x) within real) /\ (!y. abs(y - x) < d ==> h(Cx y) = Cx(f y)) ==> (f has_real_derivative g) (atreal x)`,
REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_WITHIN_GEN THEN MAP_EVERY EXISTS_TAC [`h:complex->complex`; `d:real`] THEN ASM_REWRITE_TAC[IN_UNIV; ETA_AX; SET_RULE `{x | r x} = r`]);;
let HAS_COMPLEX_REAL_DERIVATIVE_WITHIN = 
prove (`!f g h s. x IN s /\ (h has_complex_derivative Cx(g)) (at (Cx x) within {z | real z /\ Re(z) IN s}) /\ (!y. y IN s ==> h(Cx y) = Cx(f y)) ==> (f has_real_derivative g) (atreal x within s)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_WITHIN_GEN THEN MAP_EVERY EXISTS_TAC [`h:complex->complex`; `&1`] THEN ASM_SIMP_TAC[REAL_LT_01]);;
let HAS_COMPLEX_REAL_DERIVATIVE_AT = 
prove (`!f g h. (h has_complex_derivative Cx(g)) (at (Cx x) within real) /\ (!y. h(Cx y) = Cx(f y)) ==> (f has_real_derivative g) (atreal x)`,
REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_WITHIN THEN EXISTS_TAC `h:complex->complex` THEN ASM_REWRITE_TAC[IN_UNIV; ETA_AX; SET_RULE `{x | r x} = r`]);;
(* ------------------------------------------------------------------------- *) (* Caratheodory characterization. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_CARATHEODORY_ATREAL = 
prove (`!f f' z. (f has_real_derivative f') (atreal z) <=> ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\ g real_continuous atreal z /\ g(z) = f'`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_RING `w' - z':real = a <=> w' = z' + a`] THEN SIMP_TAC[GSYM FUN_EQ_THM; HAS_REAL_DERIVATIVE_ATREAL; REAL_CONTINUOUS_ATREAL] THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THENL [EXISTS_TAC `\w. if w = z then f':real else (f(w) - f(z)) / (w - z)` THEN ASM_SIMP_TAC[FUN_EQ_THM; COND_RAND; COND_RATOR; REAL_SUB_REFL] THEN CONV_TAC REAL_FIELD; FIRST_X_ASSUM SUBST_ALL_TAC THEN FIRST_X_ASSUM SUBST1_TAC THEN ASM_SIMP_TAC[REAL_RING `(z + a) - (z + b * (w - w)):real = a`] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT] REALLIM_TRANSFORM)) THEN SIMP_TAC[REALLIM_CONST; REAL_FIELD `~(w = z) ==> x - (x * (w - z)) / (w - z) = &0`]]);;
let HAS_REAL_DERIVATIVE_CARATHEODORY_WITHINREAL = 
prove (`!f f' z s. (f has_real_derivative f') (atreal z within s) <=> ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\ g real_continuous (atreal z within s) /\ g(z) = f'`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_RING `w' - z':real = a <=> w' = z' + a`] THEN SIMP_TAC[GSYM FUN_EQ_THM; HAS_REAL_DERIVATIVE_WITHINREAL; REAL_CONTINUOUS_WITHINREAL] THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THENL [EXISTS_TAC `\w. if w = z then f':real else (f(w) - f(z)) / (w - z)` THEN ASM_SIMP_TAC[FUN_EQ_THM; COND_RAND; COND_RATOR; REAL_SUB_REFL] THEN CONV_TAC REAL_FIELD; FIRST_X_ASSUM SUBST_ALL_TAC THEN FIRST_X_ASSUM SUBST1_TAC THEN ASM_SIMP_TAC[REAL_RING `(z + a) - (z + b * (w - w)):real = a`] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT] REALLIM_TRANSFORM)) THEN SIMP_TAC[REALLIM_CONST; REAL_FIELD `~(w = z) ==> x - (x * (w - z)) / (w - z) = &0`]]);;
let REAL_DIFFERENTIABLE_CARATHEODORY_ATREAL = 
prove (`!f z. f real_differentiable atreal z <=> ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\ g real_continuous atreal z`,
let REAL_DIFFERENTIABLE_CARATHEODORY_WITHINREAL = 
prove (`!f z s. f real_differentiable (atreal z within s) <=> ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\ g real_continuous (atreal z within s)`,
(* ------------------------------------------------------------------------- *) (* Property of being an interval (equivalent to convex or connected). *) (* ------------------------------------------------------------------------- *)
let is_realinterval = new_definition
 `is_realinterval s <=>
        !a b c. a IN s /\ b IN s /\ a <= c /\ c <= b ==> c IN s`;;
let IS_REALINTERVAL_IS_INTERVAL = 
prove (`!s. is_realinterval s <=> is_interval(IMAGE lift s)`,
REWRITE_TAC[IS_INTERVAL_1; is_realinterval] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[LIFT_DROP; IN_IMAGE; EXISTS_DROP; UNWIND_THM1] THEN REWRITE_TAC[GSYM FORALL_DROP]);;
let IS_REALINTERVAL_CONVEX = 
prove (`!s. is_realinterval s <=> convex(IMAGE lift s)`,
let IS_REALINTERVAL_CONNECTED = 
prove (`!s. is_realinterval s <=> connected(IMAGE lift s)`,
let TRIVIAL_LIMIT_WITHIN_REALINTERVAL = 
prove (`!s x. is_realinterval s /\ x IN s ==> (trivial_limit(atreal x within s) <=> s = {x})`,
REWRITE_TAC[TRIVIAL_LIMIT_WITHINREAL_WITHIN; IS_REALINTERVAL_CONVEX] THEN REWRITE_TAC[FORALL_DROP; GSYM IN_IMAGE_LIFT_DROP; LIFT_DROP] THEN SIMP_TAC[TRIVIAL_LIMIT_WITHIN_CONVEX] THEN REPEAT STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE_LIFT_DROP; IN_SING] THEN MESON_TAC[LIFT_DROP]);;
let IS_REALINTERVAL_EMPTY = 
prove (`is_realinterval {}`,
REWRITE_TAC[is_realinterval; NOT_IN_EMPTY]);;
let IS_REALINTERVAL_UNION = 
prove (`!s t. is_realinterval s /\ is_realinterval t /\ ~(s INTER t = {}) ==> is_realinterval(s UNION t)`,
let IS_REALINTERVAL_UNIV = 
prove (`is_realinterval (:real)`,
REWRITE_TAC[is_realinterval; IN_UNIV]);;
let IS_REAL_INTERVAL_CASES = 
prove (`!s. is_realinterval s <=> s = {} \/ s = (:real) \/ (?a. s = {x | a < x}) \/ (?a. s = {x | a <= x}) \/ (?b. s = {x | x <= b}) \/ (?b. s = {x | x < b}) \/ (?a b. s = {x | a < x /\ x < b}) \/ (?a b. s = {x | a < x /\ x <= b}) \/ (?a b. s = {x | a <= x /\ x < b}) \/ (?a b. s = {x | a <= x /\ x <= b})`,
(* ------------------------------------------------------------------------- *) (* Some relations with the complex numbers can also be useful. *) (* ------------------------------------------------------------------------- *)
let IS_REALINTERVAL_CONVEX_COMPLEX = 
prove (`!s. is_realinterval s <=> convex {z | real z /\ Re z IN s}`,
GEN_TAC THEN REWRITE_TAC[GSYM IMAGE_CX; IS_REALINTERVAL_CONVEX] THEN EQ_TAC THENL [DISCH_THEN(MP_TAC o ISPEC `Cx o drop` o MATCH_MP (REWRITE_RULE[IMP_CONJ] CONVEX_LINEAR_IMAGE)) THEN REWRITE_TAC[GSYM IMAGE_o; GSYM o_ASSOC] THEN ONCE_REWRITE_TAC[IMAGE_o] THEN REWRITE_TAC[IMAGE_LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[linear; o_THM; CX_ADD; CX_MUL; DROP_ADD; DROP_CMUL; COMPLEX_CMUL]; DISCH_THEN(MP_TAC o ISPEC `lift o Re` o MATCH_MP (REWRITE_RULE[IMP_CONJ] CONVEX_LINEAR_IMAGE)) THEN REWRITE_TAC[GSYM IMAGE_o; GSYM o_ASSOC] THEN ONCE_REWRITE_TAC[IMAGE_o] THEN REWRITE_TAC[o_DEF; RE_CX; SET_RULE `IMAGE (\x. x) s = s`] THEN DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[linear; o_THM; RE_CMUL; RE_ADD; RE_MUL_CX; LIFT_ADD; LIFT_CMUL]]);;
(* ------------------------------------------------------------------------- *) (* The same tricks to define closed and open intervals. *) (* ------------------------------------------------------------------------- *)
let open_real_interval = new_definition
  `open_real_interval(a:real,b:real) = {x:real | a < x /\ x < b}`;;
let closed_real_interval = define
  `closed_real_interval[a:real,b:real] = {x:real | a <= x /\ x <= b}`;;
make_overloadable "real_interval" `:A`;; overload_interface("real_interval",`open_real_interval`);; overload_interface("real_interval",`closed_real_interval`);;
let real_interval = 
prove (`real_interval(a,b) = {x | a < x /\ x < b} /\ real_interval[a,b] = {x | a <= x /\ x <= b}`,
let IN_REAL_INTERVAL = 
prove (`!a b x. (x IN real_interval[a,b] <=> a <= x /\ x <= b) /\ (x IN real_interval(a,b) <=> a < x /\ x < b)`,
REWRITE_TAC[real_interval; IN_ELIM_THM]);;
let REAL_INTERVAL_INTERVAL = 
prove (`real_interval[a,b] = IMAGE drop (interval[lift a,lift b]) /\ real_interval(a,b) = IMAGE drop (interval(lift a,lift b))`,
let INTERVAL_REAL_INTERVAL = 
prove (`interval[a,b] = IMAGE lift (real_interval[drop a,drop b]) /\ interval(a,b) = IMAGE lift (real_interval(drop a,drop b))`,
let EMPTY_AS_REAL_INTERVAL = 
prove (`{} = real_interval[&1,&0]`,
REWRITE_TAC[REAL_INTERVAL_INTERVAL; LIFT_NUM; GSYM EMPTY_AS_INTERVAL] THEN REWRITE_TAC[IMAGE_CLAUSES]);;
let IMAGE_LIFT_REAL_INTERVAL = 
prove (`IMAGE lift (real_interval[a,b]) = interval[lift a,lift b] /\ IMAGE lift (real_interval(a,b)) = interval(lift a,lift b)`,
REWRITE_TAC[REAL_INTERVAL_INTERVAL; GSYM IMAGE_o; o_DEF; LIFT_DROP] THEN SET_TAC[]);;
let IMAGE_DROP_INTERVAL = 
prove (`IMAGE drop (interval[a,b]) = real_interval[drop a,drop b] /\ IMAGE drop (interval(a,b)) = real_interval(drop a,drop b)`,
REWRITE_TAC[INTERVAL_REAL_INTERVAL; GSYM IMAGE_o; o_DEF; LIFT_DROP] THEN SET_TAC[]);;
let SUBSET_REAL_INTERVAL = 
prove (`!a b c d. (real_interval[a,b] SUBSET real_interval[c,d] <=> b < a \/ c <= a /\ a <= b /\ b <= d) /\ (real_interval[a,b] SUBSET real_interval(c,d) <=> b < a \/ c < a /\ a <= b /\ b < d) /\ (real_interval(a,b) SUBSET real_interval[c,d] <=> b <= a \/ c <= a /\ a < b /\ b <= d) /\ (real_interval(a,b) SUBSET real_interval(c,d) <=> b <= a \/ c <= a /\ a < b /\ b <= d)`,
let lemma = prove
   (`IMAGE drop s SUBSET IMAGE drop t <=> s SUBSET t`,
    SET_TAC[LIFT_DROP]) in
  REWRITE_TAC[REAL_INTERVAL_INTERVAL; lemma; SUBSET_INTERVAL_1] THEN
  REWRITE_TAC[LIFT_DROP]);;
let REAL_INTERVAL_OPEN_SUBSET_CLOSED = 
prove (`!a b. real_interval(a,b) SUBSET real_interval[a,b]`,
REWRITE_TAC[SUBSET; IN_REAL_INTERVAL] THEN REAL_ARITH_TAC);;
let REAL_INTERVAL_EQ_EMPTY = 
prove (`(!a b. real_interval[a,b] = {} <=> b < a) /\ (!a b. real_interval(a,b) = {} <=> b <= a)`,
let REAL_INTERVAL_NE_EMPTY = 
prove (`(!a b. ~(real_interval[a,b] = {}) <=> a <= b) /\ (!a b. ~(real_interval(a,b) = {}) <=> a < b)`,
let REAL_OPEN_CLOSED_INTERVAL = 
prove (`!a b. real_interval(a,b) = real_interval[a,b] DIFF {a,b}`,
SIMP_TAC[EXTENSION; IN_DIFF; IN_REAL_INTERVAL; IN_INSERT; NOT_IN_EMPTY] THEN REAL_ARITH_TAC);;
let REAL_CLOSED_OPEN_INTERVAL = 
prove (`!a b. a <= b ==> real_interval[a,b] = real_interval(a,b) UNION {a,b}`,
SIMP_TAC[EXTENSION; IN_UNION; IN_REAL_INTERVAL; IN_INSERT; NOT_IN_EMPTY] THEN REAL_ARITH_TAC);;
let REAL_CLOSED_REAL_INTERVAL = 
prove (`!a b. real_closed(real_interval[a,b])`,
let REAL_OPEN_REAL_INTERVAL = 
prove (`!a b. real_open(real_interval(a,b))`,
let REAL_INTERVAL_SING = 
prove (`!a. real_interval[a,a] = {a} /\ real_interval(a,a) = {}`,
REWRITE_TAC[EXTENSION; IN_SING; NOT_IN_EMPTY; IN_REAL_INTERVAL] THEN REAL_ARITH_TAC);;
let REAL_COMPACT_INTERVAL = 
prove (`!a b. real_compact(real_interval[a,b])`,
let IS_REALINTERVAL_INTERVAL = 
prove (`!a b. is_realinterval(real_interval(a,b)) /\ is_realinterval(real_interval[a,b])`,
REWRITE_TAC[is_realinterval; IN_REAL_INTERVAL] THEN REAL_ARITH_TAC);;
let REAL_BOUNDED_REAL_INTERVAL = 
prove (`(!a b. real_bounded(real_interval[a,b])) /\ (!a b. real_bounded(real_interval(a,b)))`,
let ENDS_IN_REAL_INTERVAL = 
prove (`(!a b. a IN real_interval[a,b] <=> ~(real_interval[a,b] = {})) /\ (!a b. b IN real_interval[a,b] <=> ~(real_interval[a,b] = {})) /\ (!a b. ~(a IN real_interval(a,b))) /\ (!a b. ~(b IN real_interval(a,b)))`,
REWRITE_TAC[IN_REAL_INTERVAL; REAL_INTERVAL_EQ_EMPTY] THEN REAL_ARITH_TAC);;
let IMAGE_AFFINITY_REAL_INTERVAL = 
prove (`!a b m c. IMAGE (\x. m * x + c) (real_interval[a,b]) = (if real_interval[a,b] = {} then {} else if &0 <= m then real_interval[m * a + c,m * b + c] else real_interval[m * b + c,m * a + c])`,
REWRITE_TAC[REAL_INTERVAL_INTERVAL; GSYM IMAGE_o; o_DEF; IMAGE_EQ_EMPTY] THEN REWRITE_TAC[FORALL_DROP; LIFT_DROP; GSYM DROP_CMUL; GSYM DROP_ADD] THEN REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o; IMAGE_AFFINITY_INTERVAL] THEN MESON_TAC[IMAGE_CLAUSES]);;
let IMAGE_STRETCH_REAL_INTERVAL = 
prove (`!a b m. IMAGE (\x. m * x) (real_interval[a,b]) = (if real_interval[a,b] = {} then {} else if &0 <= m then real_interval[m * a,m * b] else real_interval[m * b,m * a])`,
ONCE_REWRITE_TAC[REAL_ARITH `m * x = m * x + &0`] THEN REWRITE_TAC[IMAGE_AFFINITY_REAL_INTERVAL]);;
let REAL_INTERVAL_TRANSLATION = 
prove (`(!c a b. real_interval[c + a,c + b] = IMAGE (\x. c + x) (real_interval[a,b])) /\ (!c a b. real_interval(c + a,c + b) = IMAGE (\x. c + x) (real_interval(a,b)))`,
REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN REWRITE_TAC[REAL_ARITH `c + x:real = y <=> x = y - c`; EXISTS_REFL] THEN REWRITE_TAC[IN_REAL_INTERVAL] THEN REAL_ARITH_TAC);;
let IN_REAL_INTERVAL_REFLECT = 
prove (`(!a b x. --x IN real_interval[--b,--a] <=> x IN real_interval[a,b]) /\ (!a b x. --x IN real_interval(--b,--a) <=> x IN real_interval(a,b))`,
REWRITE_TAC[IN_REAL_INTERVAL] THEN REAL_ARITH_TAC);;
let REFLECT_REAL_INTERVAL = 
prove (`(!a b. IMAGE (--) (real_interval[a,b]) = real_interval[--b,--a]) /\ (!a b. IMAGE (--) (real_interval(a,b)) = real_interval(--b,--a))`,
REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; IN_REAL_INTERVAL] THEN ONCE_REWRITE_TAC[REAL_ARITH `x:real = --y <=> --x = y`] THEN REWRITE_TAC[UNWIND_THM1] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Real continuity and differentiability. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_CONTINUOUS = 
prove (`f real_continuous net <=> (Cx o f) continuous net`,
let REAL_CONTINUOUS_CONTINUOUS1 = 
prove (`f real_continuous net <=> (lift o f) continuous net`,
let REAL_CONTINUOUS_CONTINUOUS_ATREAL = 
prove (`f real_continuous (atreal x) <=> (lift o f o drop) continuous (at(lift x))`,
let REAL_CONTINUOUS_CONTINUOUS_WITHINREAL = 
prove (`f real_continuous (atreal x within s) <=> (lift o f o drop) continuous (at(lift x) within IMAGE lift s)`,
let REAL_COMPLEX_CONTINUOUS_WITHINREAL = 
prove (`f real_continuous (atreal x within s) <=> (Cx o f o Re) continuous (at (Cx x) within (real INTER IMAGE Cx s))`,
let REAL_COMPLEX_CONTINUOUS_ATREAL = 
prove (`f real_continuous (atreal x) <=> (Cx o f o Re) continuous (at (Cx x) within real)`,
REWRITE_TAC[real_continuous; continuous; REALLIM_COMPLEX; LIM_ATREAL_ATCOMPLEX; NETLIMIT_ATREAL; GSYM o_ASSOC] THEN ASM_CASES_TAC `trivial_limit(at(Cx x) within real)` THENL [ASM_REWRITE_TAC[LIM]; ASM_SIMP_TAC[NETLIMIT_WITHIN; RE_CX; o_THM]]);;
let CONTINUOUS_CONTINUOUS_WITHINREAL = 
prove (`!f x s. f continuous (atreal x within s) <=> (f o drop) continuous (at (lift x) within IMAGE lift s)`,
let CONTINUOUS_CONTINUOUS_ATREAL = 
prove (`!f x. f continuous (atreal x) <=> (f o drop) continuous (at (lift x))`,
let REAL_CONTINUOUS_REAL_CONTINUOUS_WITHINREAL = 
prove (`!f x s. f real_continuous (atreal x within s) <=> (f o drop) real_continuous (at (lift x) within IMAGE lift s)`,
let REAL_CONTINUOUS_REAL_CONTINUOUS_ATREAL = 
prove (`!f x. f real_continuous (atreal x) <=> (f o drop) real_continuous (at (lift x))`,
let HAS_REAL_DERIVATIVE_IMP_CONTINUOUS_WITHINREAL = 
prove (`!f f' x s. (f has_real_derivative f') (atreal x within s) ==> f real_continuous (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN; REAL_COMPLEX_CONTINUOUS_WITHINREAL] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_WITHIN) THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_INTER; IN_IMAGE] THEN MESON_TAC[REAL; RE_CX; REAL_CX; IN]);;
let REAL_DIFFERENTIABLE_IMP_CONTINUOUS_WITHINREAL = 
prove (`!f x s. f real_differentiable (atreal x within s) ==> f real_continuous (atreal x within s)`,
let HAS_REAL_DERIVATIVE_IMP_CONTINUOUS_ATREAL = 
prove (`!f f' x. (f has_real_derivative f') (atreal x) ==> f real_continuous (atreal x)`,
let REAL_DIFFERENTIABLE_IMP_CONTINUOUS_ATREAL = 
prove (`!f x. f real_differentiable atreal x ==> f real_continuous atreal x`,
let REAL_DIFFERENTIABLE_ON_IMP_REAL_CONTINUOUS_ON = 
prove (`!f s. f real_differentiable_on s ==> f real_continuous_on s`,
let REAL_CONTINUOUS_AT_COMPONENT = 
prove (`!i a. 1 <= i /\ i <= dimindex(:N) ==> (\x:real^N. x$i) real_continuous at a`,
let REAL_CONTINUOUS_AT_TRANSLATION = 
prove (`!a z f:real^N->real. f real_continuous at (a + z) <=> (\x. f(a + x)) real_continuous at z`,
add_translation_invariants [REAL_CONTINUOUS_AT_TRANSLATION];;
let REAL_CONTINUOUS_AT_LINEAR_IMAGE = 
prove (`!h:real^N->real^N z f:real^N->real. linear h /\ (!x. norm(h x) = norm x) ==> (f real_continuous at (h z) <=> (\x. f(h x)) real_continuous at z)`,
add_linear_invariants [REAL_CONTINUOUS_AT_LINEAR_IMAGE];;
let REAL_CONTINUOUS_AT_ARG = 
prove (`!z. ~(real z /\ &0 <= Re z) ==> Arg real_continuous (at z)`,
(* ------------------------------------------------------------------------- *) (* More basics about real derivatives. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_WITHIN_SUBSET = 
prove (`!f s t x. (f has_real_derivative f') (atreal x within s) /\ t SUBSET s ==> (f has_real_derivative f') (atreal x within t)`,
REPEAT GEN_TAC THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET) THEN ASM SET_TAC[]);;
let REAL_DIFFERENTIABLE_ON_SUBSET = 
prove (`!f s t. f real_differentiable_on s /\ t SUBSET s ==> f real_differentiable_on t`,
let REAL_DIFFERENTIABLE_WITHIN_SUBSET = 
prove (`!f s t. f real_differentiable (atreal x within s) /\ t SUBSET s ==> f real_differentiable (atreal x within t)`,
let HAS_REAL_DERIVATIVE_ATREAL_WITHIN = 
prove (`!f f' x s. (f has_real_derivative f') (atreal x) ==> (f has_real_derivative f') (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN; HAS_REAL_COMPLEX_DERIVATIVE_AT] THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET) THEN ASM SET_TAC[]);;
let HAS_REAL_DERIVATIVE_WITHIN_REAL_OPEN = 
prove (`!f f' a s. a IN s /\ real_open s ==> ((f has_real_derivative f') (atreal a within s) <=> (f has_real_derivative f') (atreal a))`,
let REAL_DIFFERENTIABLE_ATREAL_WITHIN = 
prove (`!f s z. f real_differentiable (atreal z) ==> f real_differentiable (atreal z within s)`,
let HAS_REAL_DERIVATIVE_TRANSFORM_WITHIN = 
prove (`!f f' g x s d. &0 < d /\ x IN s /\ (!x'. x' IN s /\ abs(x' - x) < d ==> f x' = g x') /\ (f has_real_derivative f') (atreal x within s) ==> (g has_real_derivative f') (atreal x within s)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN MATCH_MP_TAC(ONCE_REWRITE_RULE [TAUT `a /\ b /\ c /\ d ==> e <=> a /\ b /\ c ==> d ==> e`] HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN) THEN EXISTS_TAC `d:real` THEN ASM_REWRITE_TAC[IN_ELIM_THM; REAL_CX; RE_CX] THEN REPEAT STRIP_TAC THEN REWRITE_TAC[o_THM] THEN AP_TERM_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (NORM_ARITH `dist(a,b) < d ==> z <= norm(a - b) ==> z < d`)) THEN W(MP_TAC o PART_MATCH (rand o rand) COMPLEX_NORM_GE_RE_IM o rand o snd) THEN SIMP_TAC[RE_SUB; RE_CX]);;
let HAS_REAL_DERIVATIVE_TRANSFORM_ATREAL = 
prove (`!f f' g x d. &0 < d /\ (!x'. abs(x' - x) < d ==> f x' = g x') /\ (f has_real_derivative f') (atreal x) ==> (g has_real_derivative f') (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN MESON_TAC[HAS_REAL_DERIVATIVE_TRANSFORM_WITHIN; IN_UNIV]);;
let HAS_REAL_DERIVATIVE_ZERO_CONSTANT = 
prove (`!f s. is_realinterval s /\ (!x. x IN s ==> (f has_real_derivative (&0)) (atreal x within s)) ==> ?c. !x. x IN s ==> f(x) = c`,
REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`Cx o f o Re`; `{z | real z /\ Re z IN s}`] HAS_COMPLEX_DERIVATIVE_ZERO_CONSTANT) THEN ASM_REWRITE_TAC[IN_ELIM_THM; IMP_CONJ; FORALL_REAL; RE_CX; o_THM] THEN ASM_REWRITE_TAC[GSYM IS_REALINTERVAL_CONVEX_COMPLEX] THEN MESON_TAC[RE_CX]);;
let HAS_REAL_DERIVATIVE_ZERO_UNIQUE = 
prove (`!f s c a. is_realinterval s /\ a IN s /\ f a = c /\ (!x. x IN s ==> (f has_real_derivative (&0)) (atreal x within s)) ==> !x. x IN s ==> f(x) = c`,
let REAL_DIFF_CHAIN_WITHIN = 
prove (`!f g f' g' x s. (f has_real_derivative f') (atreal x within s) /\ (g has_real_derivative g') (atreal (f x) within (IMAGE f s)) ==> ((g o f) has_real_derivative (g' * f'))(atreal x within s)`,
REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN REPEAT STRIP_TAC THEN SUBGOAL_THEN `Cx o (g o f) o Re = (Cx o g o Re) o (Cx o f o Re)` SUBST1_TAC THENL [REWRITE_TAC[FUN_EQ_THM; o_DEF; RE_CX]; ALL_TAC] THEN REWRITE_TAC[CX_MUL] THEN MATCH_MP_TAC COMPLEX_DIFF_CHAIN_WITHIN THEN ASM_REWRITE_TAC[o_THM; RE_CX] THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET)) THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN REWRITE_TAC[IN_ELIM_THM; o_THM; REAL_CX; RE_CX] THEN SET_TAC[]);;
let REAL_DIFF_CHAIN_ATREAL = 
prove (`!f g f' g' x. (f has_real_derivative f') (atreal x) /\ (g has_real_derivative g') (atreal (f x)) ==> ((g o f) has_real_derivative (g' * f')) (atreal x)`,
let HAS_REAL_DERIVATIVE_CHAIN = 
prove (`!P f g. (!x. P x ==> (g has_real_derivative g'(x)) (atreal x)) ==> (!x s. (f has_real_derivative f') (atreal x within s) /\ P(f x) ==> ((\x. g(f x)) has_real_derivative f' * g'(f x)) (atreal x within s)) /\ (!x. (f has_real_derivative f') (atreal x) /\ P(f x) ==> ((\x. g(f x)) has_real_derivative f' * g'(f x)) (atreal x))`,
REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM o_DEF] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN ASM_MESON_TAC[REAL_DIFF_CHAIN_WITHIN; REAL_DIFF_CHAIN_ATREAL; HAS_REAL_DERIVATIVE_ATREAL_WITHIN]);;
let HAS_REAL_DERIVATIVE_CHAIN_UNIV = 
prove (`!f g. (!x. (g has_real_derivative g'(x)) (atreal x)) ==> (!x s. (f has_real_derivative f') (atreal x within s) ==> ((\x. g(f x)) has_real_derivative f' * g'(f x)) (atreal x within s)) /\ (!x. (f has_real_derivative f') (atreal x) ==> ((\x. g(f x)) has_real_derivative f' * g'(f x)) (atreal x))`,
MP_TAC(SPEC `\x:real. T` HAS_REAL_DERIVATIVE_CHAIN) THEN SIMP_TAC[]);;
let REAL_DERIVATIVE_UNIQUE_ATREAL = 
prove (`!f z f' f''. (f has_real_derivative f') (atreal z) /\ (f has_real_derivative f'') (atreal z) ==> f' = f''`,
REPEAT GEN_TAC THEN REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_AT] THEN DISCH_THEN(MP_TAC o MATCH_MP FRECHET_DERIVATIVE_UNIQUE_AT) THEN DISCH_THEN(MP_TAC o C AP_THM `vec 1:real^1`) THEN REWRITE_TAC[VECTOR_MUL_RCANCEL; VEC_EQ; ARITH_EQ]);;
(* ------------------------------------------------------------------------- *) (* Some handy theorems about the actual differentition function. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_DERIVATIVE = 
prove (`!f f' x. (f has_real_derivative f') (atreal x) ==> real_derivative f x = f'`,
REWRITE_TAC[real_derivative] THEN MESON_TAC[REAL_DERIVATIVE_UNIQUE_ATREAL]);;
let HAS_REAL_DERIVATIVE_DIFFERENTIABLE = 
prove (`!f x. (f has_real_derivative (real_derivative f x)) (atreal x) <=> f real_differentiable atreal x`,
REWRITE_TAC[real_differentiable; real_derivative] THEN MESON_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Arithmetical combining theorems. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_LMUL_WITHIN = 
prove (`!f f' c x s. (f has_real_derivative f') (atreal x within s) ==> ((\x. c * f(x)) has_real_derivative (c * f')) (atreal x within s)`,
let HAS_REAL_DERIVATIVE_LMUL_ATREAL = 
prove (`!f f' c x. (f has_real_derivative f') (atreal x) ==> ((\x. c * f(x)) has_real_derivative (c * f')) (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_LMUL_WITHIN]);;
let HAS_REAL_DERIVATIVE_RMUL_WITHIN = 
prove (`!f f' c x s. (f has_real_derivative f') (atreal x within s) ==> ((\x. f(x) * c) has_real_derivative (f' * c)) (atreal x within s)`,
ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_LMUL_WITHIN]);;
let HAS_REAL_DERIVATIVE_RMUL_ATREAL = 
prove (`!f f' c x. (f has_real_derivative f') (atreal x) ==> ((\x. f(x) * c) has_real_derivative (f' * c)) (atreal x)`,
ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_LMUL_ATREAL]);;
let HAS_REAL_DERIVATIVE_CDIV_WITHIN = 
prove (`!f f' c x s. (f has_real_derivative f') (atreal x within s) ==> ((\x. f(x) / c) has_real_derivative (f' / c)) (atreal x within s)`,
let HAS_REAL_DERIVATIVE_CDIV_ATREAL = 
prove (`!f f' c x. (f has_real_derivative f') (atreal x) ==> ((\x. f(x) / c) has_real_derivative (f' / c)) (atreal x)`,
let HAS_REAL_DERIVATIVE_ID = 
prove (`!net. ((\x. x) has_real_derivative &1) net`,
REWRITE_TAC[has_real_derivative; TENDSTO_REAL; REAL_ARITH `x - (a + &1 * (x - a)) = &0`] THEN REWRITE_TAC[REAL_MUL_RZERO; LIM_CONST; o_DEF]);;
let HAS_REAL_DERIVATIVE_CONST = 
prove (`!c net. ((\x. c) has_real_derivative &0) net`,
let HAS_REAL_DERIVATIVE_NEG = 
prove (`!f f' net. (f has_real_derivative f') net ==> ((\x. --(f(x))) has_real_derivative (--f')) net`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_derivative] THEN DISCH_THEN(MP_TAC o MATCH_MP REALLIM_NEG) THEN REWRITE_TAC[REAL_NEG_0; REAL_ARITH `a * (--b - (--c + --d * e:real)) = --(a * (b - (c + d * e)))`]);;
let HAS_REAL_DERIVATIVE_ADD = 
prove (`!f f' g g' net. (f has_real_derivative f') net /\ (g has_real_derivative g') net ==> ((\x. f(x) + g(x)) has_real_derivative (f' + g')) net`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_derivative] THEN DISCH_THEN(MP_TAC o MATCH_MP REALLIM_ADD) THEN REWRITE_TAC[GSYM REAL_ADD_LDISTRIB; REAL_ADD_RID] THEN REWRITE_TAC[REAL_ARITH `(fx - (fa + f' * (x - a))) + (gx - (ga + g' * (x - a))):real = (fx + gx) - ((fa + ga) + (f' + g') * (x - a))`]);;
let HAS_REAL_DERIVATIVE_SUB = 
prove (`!f f' g g' net. (f has_real_derivative f') net /\ (g has_real_derivative g') net ==> ((\x. f(x) - g(x)) has_real_derivative (f' - g')) net`,
let HAS_REAL_DERIVATIVE_MUL_WITHIN = 
prove (`!f f' g g' x s. (f has_real_derivative f') (atreal x within s) /\ (g has_real_derivative g') (atreal x within s) ==> ((\x. f(x) * g(x)) has_real_derivative (f(x) * g' + f' * g(x))) (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_COMPLEX_DERIVATIVE_MUL_WITHIN) THEN REWRITE_TAC[o_DEF; CX_MUL; CX_ADD; RE_CX]);;
let HAS_REAL_DERIVATIVE_MUL_ATREAL = 
prove (`!f f' g g' x. (f has_real_derivative f') (atreal x) /\ (g has_real_derivative g') (atreal x) ==> ((\x. f(x) * g(x)) has_real_derivative (f(x) * g' + f' * g(x))) (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_MUL_WITHIN]);;
let HAS_REAL_DERIVATIVE_POW_WITHIN = 
prove (`!f f' x s n. (f has_real_derivative f') (atreal x within s) ==> ((\x. f(x) pow n) has_real_derivative (&n * f(x) pow (n - 1) * f')) (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_WITHIN] THEN DISCH_THEN(MP_TAC o SPEC `n:num` o MATCH_MP HAS_COMPLEX_DERIVATIVE_POW_WITHIN) THEN REWRITE_TAC[o_DEF; CX_MUL; CX_POW; RE_CX]);;
let HAS_REAL_DERIVATIVE_POW_ATREAL = 
prove (`!f f' x n. (f has_real_derivative f') (atreal x) ==> ((\x. f(x) pow n) has_real_derivative (&n * f(x) pow (n - 1) * f')) (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_POW_WITHIN]);;
let HAS_REAL_DERIVATIVE_INV_BASIC = 
prove (`!x. ~(x = &0) ==> ((inv) has_real_derivative (--inv(x pow 2))) (atreal x)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[HAS_REAL_COMPLEX_DERIVATIVE_AT] THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN THEN EXISTS_TAC `inv:complex->complex` THEN ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_INV_BASIC; CX_INJ; CX_NEG; CX_INV; CX_POW; HAS_COMPLEX_DERIVATIVE_AT_WITHIN] THEN SIMP_TAC[IN; FORALL_REAL; IMP_CONJ; o_DEF; REAL_CX; RE_CX; CX_INV] THEN MESON_TAC[REAL_LT_01]);;
let HAS_REAL_DERIVATIVE_INV_WITHIN = 
prove (`!f f' x s. (f has_real_derivative f') (atreal x within s) /\ ~(f x = &0) ==> ((\x. inv(f(x))) has_real_derivative (--f' / f(x) pow 2)) (atreal x within s)`,
REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN ASM_SIMP_TAC[REAL_FIELD `~(g = &0) ==> --f / g pow 2 = --inv(g pow 2) * f`] THEN MATCH_MP_TAC REAL_DIFF_CHAIN_WITHIN THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_ATREAL_WITHIN THEN ASM_SIMP_TAC[HAS_REAL_DERIVATIVE_INV_BASIC]);;
let HAS_REAL_DERIVATIVE_INV_ATREAL = 
prove (`!f f' x. (f has_real_derivative f') (atreal x) /\ ~(f x = &0) ==> ((\x. inv(f(x))) has_real_derivative (--f' / f(x) pow 2)) (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_INV_WITHIN]);;
let HAS_REAL_DERIVATIVE_DIV_WITHIN = 
prove (`!f f' g g' x s. (f has_real_derivative f') (atreal x within s) /\ (g has_real_derivative g') (atreal x within s) /\ ~(g(x) = &0) ==> ((\x. f(x) / g(x)) has_real_derivative (f' * g(x) - f(x) * g') / g(x) pow 2) (atreal x within s)`,
REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN DISCH_THEN(fun th -> ASSUME_TAC(CONJUNCT2 th) THEN MP_TAC th) THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_REAL_DERIVATIVE_INV_WITHIN) THEN UNDISCH_TAC `(f has_real_derivative f') (atreal x within s)` THEN REWRITE_TAC[IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_REAL_DERIVATIVE_MUL_WITHIN) THEN REWRITE_TAC[GSYM real_div] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN POP_ASSUM MP_TAC THEN CONV_TAC REAL_FIELD);;
let HAS_REAL_DERIVATIVE_DIV_ATREAL = 
prove (`!f f' g g' x. (f has_real_derivative f') (atreal x) /\ (g has_real_derivative g') (atreal x) /\ ~(g(x) = &0) ==> ((\x. f(x) / g(x)) has_real_derivative (f' * g(x) - f(x) * g') / g(x) pow 2) (atreal x)`,
ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN REWRITE_TAC[HAS_REAL_DERIVATIVE_DIV_WITHIN]);;
let HAS_REAL_DERIVATIVE_SUM = 
prove (`!f net s. FINITE s /\ (!a. a IN s ==> (f a has_real_derivative f' a) net) ==> ((\x. sum s (\a. f a x)) has_real_derivative (sum s f')) net`,
GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY; SUM_CLAUSES] THEN SIMP_TAC[HAS_REAL_DERIVATIVE_CONST; HAS_REAL_DERIVATIVE_ADD; ETA_AX]);;
(* ------------------------------------------------------------------------- *) (* Same thing just for real differentiability. *) (* ------------------------------------------------------------------------- *)
let REAL_DIFFERENTIABLE_CONST = 
prove (`!c net. (\z. c) real_differentiable net`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_CONST]);;
let REAL_DIFFERENTIABLE_ID = 
prove (`!net. (\z. z) real_differentiable net`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_ID]);;
let REAL_DIFFERENTIABLE_NEG = 
prove (`!f net. f real_differentiable net ==> (\z. --(f z)) real_differentiable net`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_NEG]);;
let REAL_DIFFERENTIABLE_ADD = 
prove (`!f g net. f real_differentiable net /\ g real_differentiable net ==> (\z. f z + g z) real_differentiable net`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_ADD]);;
let REAL_DIFFERENTIABLE_SUB = 
prove (`!f g net. f real_differentiable net /\ g real_differentiable net ==> (\z. f z - g z) real_differentiable net`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_SUB]);;
let REAL_DIFFERENTIABLE_INV_WITHIN = 
prove (`!f z s. f real_differentiable (atreal z within s) /\ ~(f z = &0) ==> (\z. inv(f z)) real_differentiable (atreal z within s)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_INV_WITHIN]);;
let REAL_DIFFERENTIABLE_MUL_WITHIN = 
prove (`!f g z s. f real_differentiable (atreal z within s) /\ g real_differentiable (atreal z within s) ==> (\z. f z * g z) real_differentiable (atreal z within s)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_MUL_WITHIN]);;
let REAL_DIFFERENTIABLE_DIV_WITHIN = 
prove (`!f g z s. f real_differentiable (atreal z within s) /\ g real_differentiable (atreal z within s) /\ ~(g z = &0) ==> (\z. f z / g z) real_differentiable (atreal z within s)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_DIV_WITHIN]);;
let REAL_DIFFERENTIABLE_POW_WITHIN = 
prove (`!f n z s. f real_differentiable (atreal z within s) ==> (\z. f z pow n) real_differentiable (atreal z within s)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_POW_WITHIN]);;
let REAL_DIFFERENTIABLE_TRANSFORM_WITHIN = 
prove (`!f g x s d. &0 < d /\ x IN s /\ (!x'. x' IN s /\ abs(x' - x) < d ==> f x' = g x') /\ f real_differentiable (atreal x within s) ==> g real_differentiable (atreal x within s)`,
let REAL_DIFFERENTIABLE_TRANSFORM = 
prove (`!f g s. (!x. x IN s ==> f x = g x) /\ f real_differentiable_on s ==> g real_differentiable_on s`,
REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN REWRITE_TAC[real_differentiable_on; GSYM real_differentiable] THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN DISCH_TAC THEN MATCH_MP_TAC REAL_DIFFERENTIABLE_TRANSFORM_WITHIN THEN MAP_EVERY EXISTS_TAC [`f:real->real`; `&1`] THEN ASM_SIMP_TAC[REAL_LT_01]);;
let REAL_DIFFERENTIABLE_EQ = 
prove (`!f g s. (!x. x IN s ==> f x = g x) ==> (f real_differentiable_on s <=> g real_differentiable_on s)`,
let REAL_DIFFERENTIABLE_INV_ATREAL = 
prove (`!f z. f real_differentiable atreal z /\ ~(f z = &0) ==> (\z. inv(f z)) real_differentiable atreal z`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_INV_ATREAL]);;
let REAL_DIFFERENTIABLE_MUL_ATREAL = 
prove (`!f g z. f real_differentiable atreal z /\ g real_differentiable atreal z ==> (\z. f z * g z) real_differentiable atreal z`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_MUL_ATREAL]);;
let REAL_DIFFERENTIABLE_DIV_ATREAL = 
prove (`!f g z. f real_differentiable atreal z /\ g real_differentiable atreal z /\ ~(g z = &0) ==> (\z. f z / g z) real_differentiable atreal z`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_DIV_ATREAL]);;
let REAL_DIFFERENTIABLE_POW_ATREAL = 
prove (`!f n z. f real_differentiable atreal z ==> (\z. f z pow n) real_differentiable atreal z`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_POW_ATREAL]);;
let REAL_DIFFERENTIABLE_TRANSFORM_ATREAL = 
prove (`!f g x d. &0 < d /\ (!x'. abs(x' - x) < d ==> f x' = g x') /\ f real_differentiable atreal x ==> g real_differentiable atreal x`,
let REAL_DIFFERENTIABLE_COMPOSE_WITHIN = 
prove (`!f g x s. f real_differentiable (atreal x within s) /\ g real_differentiable (atreal (f x) within IMAGE f s) ==> (g o f) real_differentiable (atreal x within s)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[REAL_DIFF_CHAIN_WITHIN]);;
let REAL_DIFFERENTIABLE_COMPOSE_ATREAL = 
prove (`!f g x. f real_differentiable (atreal x) /\ g real_differentiable (atreal (f x)) ==> (g o f) real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[REAL_DIFF_CHAIN_ATREAL]);;
(* ------------------------------------------------------------------------- *) (* Same again for being differentiable on a set. *) (* ------------------------------------------------------------------------- *)
let REAL_DIFFERENTIABLE_ON_CONST = 
prove (`!c s. (\z. c) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_ID = 
prove (`!s. (\z. z) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_COMPOSE = 
prove (`!f g s. f real_differentiable_on s /\ g real_differentiable_on (IMAGE f s) ==> (g o f) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_NEG = 
prove (`!f s. f real_differentiable_on s ==> (\z. --(f z)) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_ADD = 
prove (`!f g s. f real_differentiable_on s /\ g real_differentiable_on s ==> (\z. f z + g z) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_SUB = 
prove (`!f g s. f real_differentiable_on s /\ g real_differentiable_on s ==> (\z. f z - g z) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_MUL = 
prove (`!f g s. f real_differentiable_on s /\ g real_differentiable_on s ==> (\z. f z * g z) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_INV = 
prove (`!f s. f real_differentiable_on s /\ (!z. z IN s ==> ~(f z = &0)) ==> (\z. inv(f z)) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_DIV = 
prove (`!f g s. f real_differentiable_on s /\ g real_differentiable_on s /\ (!z. z IN s ==> ~(g z = &0)) ==> (\z. f z / g z) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_POW = 
prove (`!f s n. f real_differentiable_on s ==> (\z. (f z) pow n) real_differentiable_on s`,
let REAL_DIFFERENTIABLE_ON_SUM = 
prove (`!f s k. FINITE k /\ (!a. a IN k ==> (f a) real_differentiable_on s) ==> (\x. sum k (\a. f a x)) real_differentiable_on s`,
GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[SUM_CLAUSES] THEN SIMP_TAC[REAL_DIFFERENTIABLE_ON_CONST; IN_INSERT; NOT_IN_EMPTY] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_DIFFERENTIABLE_ON_ADD THEN ASM_SIMP_TAC[ETA_AX]);;
(* ------------------------------------------------------------------------- *) (* Derivative (and continuity) theorems for real transcendental functions. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_EXP = 
prove (`!x. (exp has_real_derivative exp(x)) (atreal x)`,
GEN_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT THEN EXISTS_TAC `cexp` THEN ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CEXP; CX_EXP]);;
let REAL_DIFFERENTIABLE_AT_EXP = 
prove (`!x. exp real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_EXP]);;
let REAL_DIFFERENTIABLE_WITHIN_EXP = 
prove (`!s x. exp real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_EXP = 
prove (`!x. exp real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_EXP = 
prove (`!s x. exp real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_EXP = 
prove (`!s. exp real_continuous_on s`,
let HAS_REAL_DERIVATIVE_SIN = 
prove (`!x. (sin has_real_derivative cos(x)) (atreal x)`,
GEN_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT THEN EXISTS_TAC `csin` THEN ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CSIN; CX_SIN; CX_COS]);;
let REAL_DIFFERENTIABLE_AT_SIN = 
prove (`!x. sin real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_SIN]);;
let REAL_DIFFERENTIABLE_WITHIN_SIN = 
prove (`!s x. sin real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_SIN = 
prove (`!x. sin real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_SIN = 
prove (`!s x. sin real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_SIN = 
prove (`!s. sin real_continuous_on s`,
let HAS_REAL_DERIVATIVE_COS = 
prove (`!x. (cos has_real_derivative --sin(x)) (atreal x)`,
GEN_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT THEN EXISTS_TAC `ccos` THEN ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CCOS; CX_SIN; CX_COS; CX_NEG]);;
let REAL_DIFFERENTIABLE_AT_COS = 
prove (`!x. cos real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_COS]);;
let REAL_DIFFERENTIABLE_WITHIN_COS = 
prove (`!s x. cos real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_COS = 
prove (`!x. cos real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_COS = 
prove (`!s x. cos real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_COS = 
prove (`!s. cos real_continuous_on s`,
let HAS_REAL_DERIVATIVE_TAN = 
prove (`!x. ~(cos x = &0) ==> (tan has_real_derivative inv(cos(x) pow 2)) (atreal x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT THEN EXISTS_TAC `ctan` THEN REWRITE_TAC[CX_INV; CX_POW; CX_COS] THEN ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CTAN; GSYM CX_COS; CX_INJ; CX_TAN]);;
let REAL_DIFFERENTIABLE_AT_TAN = 
prove (`!x. ~(cos x = &0) ==> tan real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_TAN]);;
let REAL_DIFFERENTIABLE_WITHIN_TAN = 
prove (`!s x. ~(cos x = &0) ==> tan real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_TAN = 
prove (`!x. ~(cos x = &0) ==> tan real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_TAN = 
prove (`!s x. ~(cos x = &0) ==> tan real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_TAN = 
prove (`!s. (!x. x IN s ==> ~(cos x = &0)) ==> tan real_continuous_on s`,
let HAS_REAL_DERIVATIVE_LOG = 
prove (`!x. &0 < x ==> (log has_real_derivative inv(x)) (atreal x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT_GEN THEN MAP_EVERY EXISTS_TAC [`clog`; `x:real`] THEN ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THENL [REWRITE_TAC[CX_INV] THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_CLOG THEN ASM_REWRITE_TAC[RE_CX]; MATCH_MP_TAC(GSYM CX_LOG) THEN ASM_REAL_ARITH_TAC]);;
let REAL_DIFFERENTIABLE_AT_LOG = 
prove (`!x. &0 < x ==> log real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_LOG]);;
let REAL_DIFFERENTIABLE_WITHIN_LOG = 
prove (`!s x. &0 < x ==> log real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_LOG = 
prove (`!x. &0 < x ==> log real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_LOG = 
prove (`!s x. &0 < x ==> log real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_LOG = 
prove (`!s. (!x. x IN s ==> &0 < x) ==> log real_continuous_on s`,
let HAS_REAL_DERIVATIVE_SQRT = 
prove (`!x. &0 < x ==> (sqrt has_real_derivative inv(&2 * sqrt x)) (atreal x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT_GEN THEN MAP_EVERY EXISTS_TAC [`csqrt`; `x:real`] THEN ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THENL [ASM_SIMP_TAC[CX_INV; CX_MUL; CX_SQRT; REAL_LT_IMP_LE] THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_CSQRT THEN ASM_SIMP_TAC[RE_CX]; MATCH_MP_TAC(GSYM CX_SQRT) THEN ASM_REAL_ARITH_TAC]);;
let REAL_DIFFERENTIABLE_AT_SQRT = 
prove (`!x. &0 < x ==> sqrt real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_SQRT]);;
let REAL_DIFFERENTIABLE_WITHIN_SQRT = 
prove (`!s x. &0 < x ==> sqrt real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_SQRT = 
prove (`!x. &0 < x ==> sqrt real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_SQRT = 
prove (`!s x. &0 < x ==> sqrt real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_WITHIN_SQRT_COMPOSE = 
prove (`!f s a:real^N. f real_continuous (at a within s) /\ (&0 < f a \/ !x. x IN s ==> &0 <= f x) ==> (\x. sqrt(f x)) real_continuous (at a within s)`,
let REAL_CONTINUOUS_AT_SQRT_COMPOSE = 
prove (`!f a:real^N. f real_continuous (at a) /\ (&0 < f a \/ !x. &0 <= f x) ==> (\x. sqrt(f x)) real_continuous (at a)`,
let CONTINUOUS_WITHINREAL_SQRT_COMPOSE = 
prove (`!f s a. (\x. lift(f x)) continuous (atreal a within s) /\ (&0 < f a \/ !x. x IN s ==> &0 <= f x) ==> (\x. lift(sqrt(f x))) continuous (atreal a within s)`,
REWRITE_TAC[CONTINUOUS_CONTINUOUS_WITHINREAL] THEN REWRITE_TAC[o_DEF] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC CONTINUOUS_WITHIN_SQRT_COMPOSE THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE; LIFT_DROP]);;
let CONTINUOUS_ATREAL_SQRT_COMPOSE = 
prove (`!f a. (\x. lift(f x)) continuous (atreal a) /\ (&0 < f a \/ !x. &0 <= f x) ==> (\x. lift(sqrt(f x))) continuous (atreal a)`,
REPEAT GEN_TAC THEN MP_TAC(ISPECL [`f:real->real`; `(:real)`; `a:real`] CONTINUOUS_WITHINREAL_SQRT_COMPOSE) THEN REWRITE_TAC[WITHINREAL_UNIV; IN_UNIV]);;
let REAL_CONTINUOUS_WITHINREAL_SQRT_COMPOSE = 
prove (`!f s a. f real_continuous (atreal a within s) /\ (&0 < f a \/ !x. x IN s ==> &0 <= f x) ==> (\x. sqrt(f x)) real_continuous (atreal a within s)`,
let REAL_CONTINUOUS_ATREAL_SQRT_COMPOSE = 
prove (`!f a. f real_continuous (atreal a) /\ (&0 < f a \/ !x. &0 <= f x) ==> (\x. sqrt(f x)) real_continuous (atreal a)`,
let HAS_REAL_DERIVATIVE_ATN = 
prove (`!x. (atn has_real_derivative inv(&1 + x pow 2)) (atreal x)`,
GEN_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT THEN EXISTS_TAC `catn` THEN REWRITE_TAC[CX_INV; CX_ADD; CX_ATN; CX_POW] THEN ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CATN; IM_CX; REAL_ABS_NUM; REAL_LT_01]);;
let REAL_DIFFERENTIABLE_AT_ATN = 
prove (`!x. atn real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_ATN]);;
let REAL_DIFFERENTIABLE_WITHIN_ATN = 
prove (`!s x. atn real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_ATN = 
prove (`!x. atn real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_ATN = 
prove (`!s x. atn real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_ATN = 
prove (`!s. atn real_continuous_on s`,
let HAS_REAL_DERIVATIVE_ASN_COS = 
prove (`!x. abs(x) < &1 ==> (asn has_real_derivative inv(cos(asn x))) (atreal x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT_GEN THEN MAP_EVERY EXISTS_TAC [`casn`; `&1 - abs x`] THEN ASM_REWRITE_TAC[REAL_SUB_LT] THEN REPEAT STRIP_TAC THENL [ASM_SIMP_TAC[CX_INV; CX_COS; CX_ASN; REAL_LT_IMP_LE] THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_CASN THEN ASM_REWRITE_TAC[RE_CX]; MATCH_MP_TAC(GSYM CX_ASN) THEN ASM_REAL_ARITH_TAC]);;
let HAS_REAL_DERIVATIVE_ASN = 
prove (`!x. abs(x) < &1 ==> (asn has_real_derivative inv(sqrt(&1 - x pow 2))) (atreal x)`,
REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP HAS_REAL_DERIVATIVE_ASN_COS) THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC COS_ASN THEN ASM_REAL_ARITH_TAC);;
let REAL_DIFFERENTIABLE_AT_ASN = 
prove (`!x. abs(x) < &1 ==> asn real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_ASN]);;
let REAL_DIFFERENTIABLE_WITHIN_ASN = 
prove (`!s x. abs(x) < &1 ==> asn real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_ASN = 
prove (`!x. abs(x) < &1 ==> asn real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_ASN = 
prove (`!s x. abs(x) < &1 ==> asn real_continuous (atreal x within s)`,
let HAS_REAL_DERIVATIVE_ACS_SIN = 
prove (`!x. abs(x) < &1 ==> (acs has_real_derivative --inv(sin(acs x))) (atreal x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_REAL_DERIVATIVE_AT_GEN THEN MAP_EVERY EXISTS_TAC [`cacs`; `&1 - abs x`] THEN ASM_REWRITE_TAC[REAL_SUB_LT] THEN REPEAT STRIP_TAC THENL [ASM_SIMP_TAC[CX_INV; CX_SIN; CX_ACS; CX_NEG; REAL_LT_IMP_LE] THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_CACS THEN ASM_REWRITE_TAC[RE_CX]; MATCH_MP_TAC(GSYM CX_ACS) THEN ASM_REAL_ARITH_TAC]);;
let HAS_REAL_DERIVATIVE_ACS = 
prove (`!x. abs(x) < &1 ==> (acs has_real_derivative --inv(sqrt(&1 - x pow 2))) (atreal x)`,
REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP HAS_REAL_DERIVATIVE_ACS_SIN) THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC SIN_ACS THEN ASM_REAL_ARITH_TAC);;
let REAL_DIFFERENTIABLE_AT_ACS = 
prove (`!x. abs(x) < &1 ==> acs real_differentiable (atreal x)`,
REWRITE_TAC[real_differentiable] THEN MESON_TAC[HAS_REAL_DERIVATIVE_ACS]);;
let REAL_DIFFERENTIABLE_WITHIN_ACS = 
prove (`!s x. abs(x) < &1 ==> acs real_differentiable (atreal x within s)`,
let REAL_CONTINUOUS_AT_ACS = 
prove (`!x. abs(x) < &1 ==> acs real_continuous (atreal x)`,
let REAL_CONTINUOUS_WITHIN_ACS = 
prove (`!s x. abs(x) < &1 ==> acs real_continuous (atreal x within s)`,
(* ------------------------------------------------------------------------- *) (* Hence differentiation of the norm. *) (* ------------------------------------------------------------------------- *)
let DIFFERENTIABLE_NORM_AT = 
prove (`!a:real^N. ~(a = vec 0) ==> (\x. lift(norm x)) differentiable (at a)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[vector_norm] THEN SUBGOAL_THEN `(\x:real^N. lift(sqrt(x dot x))) = (lift o sqrt o drop) o (\x. lift(x dot x))` SUBST1_TAC THENL [REWRITE_TAC[o_DEF; LIFT_DROP]; ALL_TAC] THEN MATCH_MP_TAC DIFFERENTIABLE_CHAIN_AT THEN REWRITE_TAC[DIFFERENTIABLE_SQNORM_AT; GSYM NORM_POW_2] THEN MP_TAC(ISPEC `norm(a:real^N) pow 2` REAL_DIFFERENTIABLE_AT_SQRT) THEN ASM_SIMP_TAC[REAL_POW_LT; NORM_POS_LT; REAL_DIFFERENTIABLE_AT]);;
let DIFFERENTIABLE_ON_NORM = 
prove (`!s:real^N->bool. ~(vec 0 IN s) ==> (\x. lift(norm x)) differentiable_on s`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC DIFFERENTIABLE_AT_IMP_DIFFERENTIABLE_ON THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC DIFFERENTIABLE_NORM_AT THEN ASM_MESON_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Some somewhat sharper continuity theorems including endpoints. *) (* ------------------------------------------------------------------------- *)
let REAL_CONTINUOUS_WITHIN_SQRT_STRONG = 
prove (`!x. sqrt real_continuous (atreal x within {t | &0 <= t})`,
GEN_TAC THEN REWRITE_TAC[REAL_COMPLEX_CONTINUOUS_WITHINREAL] THEN ASM_CASES_TAC `x IN {t | &0 <= t}` THENL [MATCH_MP_TAC CONTINUOUS_TRANSFORM_WITHIN THEN MAP_EVERY EXISTS_TAC [`csqrt`; `&1`] THEN REWRITE_TAC[IMAGE_CX; IN_ELIM_THM; REAL_LT_01; CONTINUOUS_WITHIN_CSQRT_POSREAL; SET_RULE `real INTER {z | real z /\ P z} = {z | real z /\ P z}`] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_ELIM_THM]) THEN ASM_REWRITE_TAC[REAL_CX; RE_CX; IMP_CONJ; FORALL_REAL; o_THM] THEN SIMP_TAC[CX_SQRT]; MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN CONJ_TAC THENL [SUBGOAL_THEN `real INTER IMAGE Cx {t | &0 <= t} = real INTER {t | Re t >= &0}` (fun th -> SIMP_TAC[th; CLOSED_INTER; CLOSED_REAL; CLOSED_HALFSPACE_RE_GE]) THEN REWRITE_TAC[EXTENSION; IMAGE_CX; IN_ELIM_THM; IN_CBALL; IN_INTER] THEN REWRITE_TAC[real_ge; IN; CONJ_ACI]; MATCH_MP_TAC(SET_RULE `(!x y. f x = f y ==> x = y) /\ ~(x IN s) ==> ~(f x IN t INTER IMAGE f s)`) THEN ASM_REWRITE_TAC[CX_INJ]]]);;
let REAL_CONTINUOUS_ON_SQRT = 
prove (`!s. (!x. x IN s ==> &0 <= x) ==> sqrt real_continuous_on s`,
REWRITE_TAC[REAL_CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_WITHINREAL_SUBSET THEN EXISTS_TAC `{x | &0 <= x}` THEN ASM_REWRITE_TAC[SUBSET; IN_ELIM_THM; REAL_CONTINUOUS_WITHIN_SQRT_STRONG]);;
let REAL_CONTINUOUS_WITHIN_ASN_STRONG = 
prove (`!x. asn real_continuous (atreal x within {t | abs(t) <= &1})`,
GEN_TAC THEN REWRITE_TAC[REAL_COMPLEX_CONTINUOUS_WITHINREAL] THEN ASM_CASES_TAC `x IN {t | abs(t) <= &1}` THENL [MATCH_MP_TAC CONTINUOUS_TRANSFORM_WITHIN THEN MAP_EVERY EXISTS_TAC [`casn`; `&1`] THEN REWRITE_TAC[IMAGE_CX; IN_ELIM_THM; CONTINUOUS_WITHIN_CASN_REAL; REAL_LT_01; SET_RULE `real INTER {z | real z /\ P z} = {z | real z /\ P z}`] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_ELIM_THM]) THEN ASM_REWRITE_TAC[REAL_CX; RE_CX; IMP_CONJ; FORALL_REAL; o_THM] THEN SIMP_TAC[CX_ASN]; MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN CONJ_TAC THENL [SUBGOAL_THEN `real INTER IMAGE Cx {t | abs t <= &1} = real INTER cball(Cx(&0),&1)` (fun th -> SIMP_TAC[th; CLOSED_INTER; CLOSED_REAL; CLOSED_CBALL]) THEN REWRITE_TAC[EXTENSION; IMAGE_CX; IN_ELIM_THM; IN_CBALL; IN_INTER] THEN REWRITE_TAC[dist; COMPLEX_SUB_LZERO; NORM_NEG; IN] THEN MESON_TAC[REAL_NORM]; MATCH_MP_TAC(SET_RULE `(!x y. f x = f y ==> x = y) /\ ~(x IN s) ==> ~(f x IN t INTER IMAGE f s)`) THEN ASM_REWRITE_TAC[CX_INJ]]]);;
let REAL_CONTINUOUS_ON_ASN = 
prove (`!s. (!x. x IN s ==> abs(x) <= &1) ==> asn real_continuous_on s`,
REWRITE_TAC[REAL_CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_WITHINREAL_SUBSET THEN EXISTS_TAC `{x | abs(x) <= &1}` THEN ASM_REWRITE_TAC[SUBSET; IN_ELIM_THM; REAL_CONTINUOUS_WITHIN_ASN_STRONG]);;
let REAL_CONTINUOUS_WITHIN_ACS_STRONG = 
prove (`!x. acs real_continuous (atreal x within {t | abs(t) <= &1})`,
GEN_TAC THEN REWRITE_TAC[REAL_COMPLEX_CONTINUOUS_WITHINREAL] THEN ASM_CASES_TAC `x IN {t | abs(t) <= &1}` THENL [MATCH_MP_TAC CONTINUOUS_TRANSFORM_WITHIN THEN MAP_EVERY EXISTS_TAC [`cacs`; `&1`] THEN REWRITE_TAC[IMAGE_CX; IN_ELIM_THM; CONTINUOUS_WITHIN_CACS_REAL; REAL_LT_01; SET_RULE `real INTER {z | real z /\ P z} = {z | real z /\ P z}`] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_ELIM_THM]) THEN ASM_REWRITE_TAC[REAL_CX; RE_CX; IMP_CONJ; FORALL_REAL; o_THM] THEN SIMP_TAC[CX_ACS]; MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN CONJ_TAC THENL [SUBGOAL_THEN `real INTER IMAGE Cx {t | abs t <= &1} = real INTER cball(Cx(&0),&1)` (fun th -> SIMP_TAC[th; CLOSED_INTER; CLOSED_REAL; CLOSED_CBALL]) THEN REWRITE_TAC[EXTENSION; IMAGE_CX; IN_ELIM_THM; IN_CBALL; IN_INTER] THEN REWRITE_TAC[dist; COMPLEX_SUB_LZERO; NORM_NEG; IN] THEN MESON_TAC[REAL_NORM]; MATCH_MP_TAC(SET_RULE `(!x y. f x = f y ==> x = y) /\ ~(x IN s) ==> ~(f x IN t INTER IMAGE f s)`) THEN ASM_REWRITE_TAC[CX_INJ]]]);;
let REAL_CONTINUOUS_ON_ACS = 
prove (`!s. (!x. x IN s ==> abs(x) <= &1) ==> acs real_continuous_on s`,
REWRITE_TAC[REAL_CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_WITHINREAL_SUBSET THEN EXISTS_TAC `{x | abs(x) <= &1}` THEN ASM_REWRITE_TAC[SUBSET; IN_ELIM_THM; REAL_CONTINUOUS_WITHIN_ACS_STRONG]);;
(* ------------------------------------------------------------------------- *) (* Differentiation conversion. *) (* ------------------------------------------------------------------------- *) let real_differentiation_theorems = ref [];; let add_real_differentiation_theorems =
let ETA_THM = 
prove (`(f has_real_derivative f') net <=> ((\x. f x) has_real_derivative f') net`,
REWRITE_TAC[ETA_AX]) in let ETA_TWEAK = PURE_REWRITE_RULE [IMP_CONJ] o GEN_REWRITE_RULE (LAND_CONV o ONCE_DEPTH_CONV) [ETA_THM] o SPEC_ALL in fun l -> real_differentiation_theorems := !real_differentiation_theorems @ map ETA_TWEAK l;;
add_real_differentiation_theorems ([HAS_REAL_DERIVATIVE_LMUL_WITHIN; HAS_REAL_DERIVATIVE_LMUL_ATREAL; HAS_REAL_DERIVATIVE_RMUL_WITHIN; HAS_REAL_DERIVATIVE_RMUL_ATREAL; HAS_REAL_DERIVATIVE_CDIV_WITHIN; HAS_REAL_DERIVATIVE_CDIV_ATREAL; HAS_REAL_DERIVATIVE_ID; HAS_REAL_DERIVATIVE_CONST; HAS_REAL_DERIVATIVE_NEG; HAS_REAL_DERIVATIVE_ADD; HAS_REAL_DERIVATIVE_SUB; HAS_REAL_DERIVATIVE_MUL_WITHIN; HAS_REAL_DERIVATIVE_MUL_ATREAL; HAS_REAL_DERIVATIVE_DIV_WITHIN; HAS_REAL_DERIVATIVE_DIV_ATREAL; HAS_REAL_DERIVATIVE_POW_WITHIN; HAS_REAL_DERIVATIVE_POW_ATREAL; HAS_REAL_DERIVATIVE_INV_WITHIN; HAS_REAL_DERIVATIVE_INV_ATREAL] @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN_UNIV HAS_REAL_DERIVATIVE_EXP))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN_UNIV HAS_REAL_DERIVATIVE_SIN))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN_UNIV HAS_REAL_DERIVATIVE_COS))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN HAS_REAL_DERIVATIVE_TAN))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN HAS_REAL_DERIVATIVE_LOG))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN HAS_REAL_DERIVATIVE_SQRT))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN_UNIV HAS_REAL_DERIVATIVE_ATN))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN HAS_REAL_DERIVATIVE_ASN))) @ (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN HAS_REAL_DERIVATIVE_ACS))));; let rec REAL_DIFF_CONV = let partfn tm = let l,r = dest_comb tm in mk_pair(lhand l,r) and is_deriv = can (term_match [] `(f has_real_derivative f') net`) in let rec REAL_DIFF_CONV tm = try tryfind (fun th -> PART_MATCH partfn th (partfn tm)) (!real_differentiation_theorems) with Failure _ -> let ith = tryfind (fun th -> PART_MATCH (partfn o repeat (snd o dest_imp)) th (partfn tm)) (!real_differentiation_theorems) in REAL_DIFF_ELIM ith and REAL_DIFF_ELIM th = let tm = concl th in if not(is_imp tm) then th else let t = lhand tm in if not(is_deriv t) then UNDISCH th else REAL_DIFF_ELIM (MATCH_MP th (REAL_DIFF_CONV t)) in REAL_DIFF_CONV;; (* ------------------------------------------------------------------------- *) (* Hence a tactic. *) (* ------------------------------------------------------------------------- *) let REAL_DIFF_TAC = let pth = MESON[] `(f has_real_derivative f') net ==> f' = g' ==> (f has_real_derivative g') net` in W(fun (asl,w) -> let th = MATCH_MP pth (REAL_DIFF_CONV w) in MATCH_MP_TAC(repeat (GEN_REWRITE_RULE I [IMP_IMP]) (DISCH_ALL th)));; let REAL_DIFFERENTIABLE_TAC = let DISCH_FIRST th = DISCH (hd(hyp th)) th in GEN_REWRITE_TAC I [real_differentiable] THEN W(fun (asl,w) -> let th = REAL_DIFF_CONV(snd(dest_exists w)) in let f' = rand(rator(concl th)) in EXISTS_TAC f' THEN (if hyp th = [] then MATCH_ACCEPT_TAC th else let th' = repeat (GEN_REWRITE_RULE I [IMP_IMP] o DISCH_FIRST) (DISCH_FIRST th) in MATCH_MP_TAC th'));; (* ------------------------------------------------------------------------- *) (* Analytic results for real power function. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_RPOW = 
prove (`!x y. &0 < x ==> ((\x. x rpow y) has_real_derivative y * x rpow (y - &1)) (atreal x)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_TRANSFORM_ATREAL THEN EXISTS_TAC `\x. exp(y * log x)` THEN EXISTS_TAC `x:real` THEN ASM_SIMP_TAC[rpow; REAL_ARITH `&0 < x ==> (abs(y - x) < x <=> &0 < y /\ y < &2 * x)`] THEN REAL_DIFF_TAC THEN ASM_SIMP_TAC[REAL_SUB_RDISTRIB; REAL_EXP_SUB; REAL_MUL_LID; EXP_LOG] THEN REAL_ARITH_TAC);;
add_real_differentiation_theorems (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM] (GEN `y:real` (MATCH_MP HAS_REAL_DERIVATIVE_CHAIN (SPEC `y:real` (ONCE_REWRITE_RULE[SWAP_FORALL_THM] HAS_REAL_DERIVATIVE_RPOW))))));;
let REAL_DIFFERENTIABLE_AT_RPOW = 
prove (`!x y. ~(x = &0) ==> (\x. x rpow y) real_differentiable atreal x`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_ARITH `~(x = &0) <=> &0 < x \/ &0 < --x`] THEN STRIP_TAC THEN MATCH_MP_TAC REAL_DIFFERENTIABLE_TRANSFORM_ATREAL THEN REWRITE_TAC[] THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN EXISTS_TAC `abs x` THENL [EXISTS_TAC `\x. exp(y * log x)` THEN ASM_SIMP_TAC[REAL_ARITH `&0 < x ==> &0 < abs x`] THEN CONJ_TAC THENL [X_GEN_TAC `z:real` THEN DISCH_TAC THEN SUBGOAL_THEN `&0 < z` (fun th -> REWRITE_TAC[rpow; th]) THEN ASM_REAL_ARITH_TAC; REAL_DIFFERENTIABLE_TAC THEN ASM_REAL_ARITH_TAC]; ASM_CASES_TAC `?m n. ODD m /\ ODD n /\ abs y = &m / &n` THENL [EXISTS_TAC `\x. --(exp(y * log(--x)))`; EXISTS_TAC `\x. exp(y * log(--x))`] THEN (ASM_SIMP_TAC[REAL_ARITH `&0 < --x ==> &0 < abs x`] THEN CONJ_TAC THENL [X_GEN_TAC `z:real` THEN DISCH_TAC THEN SUBGOAL_THEN `~(&0 < z) /\ ~(z = &0)` (fun th -> ASM_REWRITE_TAC[rpow; th]) THEN ASM_REAL_ARITH_TAC; REAL_DIFFERENTIABLE_TAC THEN ASM_REAL_ARITH_TAC])]);;
let REAL_CONTINUOUS_AT_RPOW = 
prove (`!x y. (x = &0 ==> &0 <= y) ==> (\x. x rpow y) real_continuous (atreal x)`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `y = &0` THEN ASM_REWRITE_TAC[RPOW_POW; real_pow; REAL_CONTINUOUS_CONST] THEN ASM_CASES_TAC `x = &0` THENL [ASM_REWRITE_TAC[real_continuous_atreal; RPOW_ZERO] THEN REWRITE_TAC[REAL_SUB_RZERO; REAL_ABS_RPOW] THEN STRIP_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `e rpow inv(y)` THEN ASM_SIMP_TAC[RPOW_POS_LT] THEN X_GEN_TAC `z:real` THEN DISCH_TAC THEN MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `e rpow inv y rpow y` THEN CONJ_TAC THENL [MATCH_MP_TAC RPOW_LT2 THEN ASM_REAL_ARITH_TAC; ASM_SIMP_TAC[RPOW_RPOW; REAL_LT_IMP_LE; REAL_MUL_LINV] THEN REWRITE_TAC[RPOW_POW; REAL_POW_1; REAL_LE_REFL]]; ASM_SIMP_TAC[REAL_DIFFERENTIABLE_IMP_CONTINUOUS_ATREAL; REAL_DIFFERENTIABLE_AT_RPOW]]);;
let REAL_CONTINUOUS_WITHIN_RPOW = 
prove (`!s x y. (x = &0 ==> &0 <= y) ==> (\x. x rpow y) real_continuous (atreal x within s)`,
let REAL_CONTINUOUS_ON_RPOW = 
prove (`!s y. (&0 IN s ==> &0 <= y) ==> (\x. x rpow y) real_continuous_on s`,
REWRITE_TAC[REAL_CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_WITHIN_RPOW THEN ASM_MESON_TAC[]);;
let REALLIM_RPOW = 
prove (`!net f l n. (f ---> l) net /\ (l = &0 ==> &0 <= n) ==> ((\x. f x rpow n) ---> l rpow n) net`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC (REWRITE_RULE[] (ISPEC `\x. x rpow n` REALLIM_REAL_CONTINUOUS_FUNCTION)) THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_CONTINUOUS_AT_RPOW THEN ASM_REWRITE_TAC[]);;
let REALLIM_NULL_POW_EQ = 
prove (`!net f n. ~(n = 0) ==> (((\x. f x pow n) ---> &0) net <=> (f ---> &0) net)`,
REPEAT STRIP_TAC THEN EQ_TAC THEN ASM_SIMP_TAC[REALLIM_NULL_POW] THEN DISCH_THEN(MP_TAC o ISPEC `(\x. x rpow (inv(&n))) o abs` o MATCH_MP(REWRITE_RULE[IMP_CONJ_ALT] REALLIM_REAL_CONTINUOUS_FUNCTION)) THEN REWRITE_TAC[o_THM] THEN ASM_REWRITE_TAC[RPOW_ZERO; REAL_INV_EQ_0; REAL_OF_NUM_EQ; REAL_ABS_NUM] THEN SIMP_TAC[GSYM RPOW_POW; RPOW_RPOW; REAL_ABS_POS; REAL_ABS_RPOW] THEN ASM_SIMP_TAC[REAL_MUL_RINV; REAL_OF_NUM_EQ] THEN REWRITE_TAC[REALLIM_NULL_ABS; RPOW_POW; REAL_POW_1] THEN DISCH_THEN MATCH_MP_TAC THEN ONCE_REWRITE_TAC[GSYM WITHINREAL_UNIV] THEN MATCH_MP_TAC REAL_CONTINUOUS_WITHINREAL_COMPOSE THEN CONJ_TAC THENL [GEN_REWRITE_TAC LAND_CONV [GSYM ETA_AX] THEN MATCH_MP_TAC REAL_CONTINUOUS_ABS THEN REWRITE_TAC[REAL_CONTINUOUS_WITHIN_ID]; MATCH_MP_TAC REAL_CONTINUOUS_WITHIN_RPOW THEN REWRITE_TAC[REAL_LE_INV_EQ; REAL_POS]]);;
let LIM_NULL_COMPLEX_POW_EQ = 
prove (`!net f n. ~(n = 0) ==> (((\x. f x pow n) --> Cx(&0)) net <=> (f --> Cx(&0)) net)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM COMPLEX_VEC_0] THEN ONCE_REWRITE_TAC[LIM_NULL_NORM] THEN REWRITE_TAC[COMPLEX_NORM_POW; REAL_TENDSTO; o_DEF; LIFT_DROP] THEN ASM_SIMP_TAC[REALLIM_NULL_POW_EQ; DROP_VEC]);;
(* ------------------------------------------------------------------------- *) (* Intermediate Value Theorem. *) (* ------------------------------------------------------------------------- *)
let REAL_IVT_INCREASING = 
prove (`!f a b y. a <= b /\ f real_continuous_on real_interval[a,b] /\ f a <= y /\ y <= f b ==> ?x. x IN real_interval [a,b] /\ f x = y`,
REWRITE_TAC[REAL_CONTINUOUS_ON; IMAGE_LIFT_REAL_INTERVAL] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `lift a`; `lift b`; `y:real`; `1`] IVT_INCREASING_COMPONENT_ON_1) THEN ASM_REWRITE_TAC[GSYM drop; o_THM; LIFT_DROP; DIMINDEX_1; LE_REFL] THEN REWRITE_TAC[GSYM IMAGE_LIFT_REAL_INTERVAL; EXISTS_IN_IMAGE; LIFT_DROP]);;
let REAL_IVT_DECREASING = 
prove (`!f a b y. a <= b /\ f real_continuous_on real_interval[a,b] /\ f b <= y /\ y <= f a ==> ?x. x IN real_interval [a,b] /\ f x = y`,
REWRITE_TAC[REAL_CONTINUOUS_ON; IMAGE_LIFT_REAL_INTERVAL] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `lift a`; `lift b`; `y:real`; `1`] IVT_DECREASING_COMPONENT_ON_1) THEN ASM_REWRITE_TAC[GSYM drop; o_THM; LIFT_DROP; DIMINDEX_1; LE_REFL] THEN REWRITE_TAC[GSYM IMAGE_LIFT_REAL_INTERVAL; EXISTS_IN_IMAGE; LIFT_DROP]);;
let IS_REALINTERVAL_CONTINUOUS_IMAGE = 
prove (`!s. f real_continuous_on s /\ is_realinterval s ==> is_realinterval(IMAGE f s)`,
GEN_TAC THEN REWRITE_TAC[REAL_CONTINUOUS_ON; IS_REALINTERVAL_CONNECTED] THEN DISCH_THEN(MP_TAC o MATCH_MP CONNECTED_CONTINUOUS_IMAGE) THEN REWRITE_TAC[IMAGE_o; REWRITE_RULE[IMAGE_o] IMAGE_LIFT_DROP]);;
(* ------------------------------------------------------------------------- *) (* Zeroness (or sign at boundary) of derivative at local extremum. *) (* ------------------------------------------------------------------------- *)
let REAL_DERIVATIVE_POS_LEFT_MINIMUM = 
prove (`!f f' a b e. a < b /\ &0 < e /\ (f has_real_derivative f') (atreal a within real_interval[a,b]) /\ (!x. x IN real_interval[a,b] /\ abs(x - a) < e ==> f a <= f x) ==> &0 <= f'`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `\x:real^1. f' % x`; `lift a`; `interval[lift a,lift b]`; `e:real`] DROP_DIFFERENTIAL_POS_AT_MINIMUM) THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL; CONVEX_INTERVAL; IN_INTER; IMP_CONJ] THEN ASM_REWRITE_TAC[GSYM IMAGE_LIFT_REAL_INTERVAL; IMAGE_EQ_EMPTY; GSYM HAS_REAL_FRECHET_DERIVATIVE_WITHIN] THEN ASM_SIMP_TAC[FORALL_IN_IMAGE; o_THM; LIFT_DROP; IN_BALL; DIST_LIFT; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ANTS_TAC THENL [ASM_MESON_TAC[REAL_ABS_SUB]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `b:real`) THEN ASM_SIMP_TAC[ENDS_IN_REAL_INTERVAL; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ASM_SIMP_TAC[DROP_CMUL; DROP_SUB; LIFT_DROP; REAL_LE_MUL_EQ; REAL_SUB_LT]);;
let REAL_DERIVATIVE_NEG_LEFT_MAXIMUM = 
prove (`!f f' a b e. a < b /\ &0 < e /\ (f has_real_derivative f') (atreal a within real_interval[a,b]) /\ (!x. x IN real_interval[a,b] /\ abs(x - a) < e ==> f x <= f a) ==> f' <= &0`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `\x:real^1. f' % x`; `lift a`; `interval[lift a,lift b]`; `e:real`] DROP_DIFFERENTIAL_NEG_AT_MAXIMUM) THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL; CONVEX_INTERVAL; IN_INTER; IMP_CONJ] THEN ASM_REWRITE_TAC[GSYM IMAGE_LIFT_REAL_INTERVAL; IMAGE_EQ_EMPTY; GSYM HAS_REAL_FRECHET_DERIVATIVE_WITHIN] THEN ASM_SIMP_TAC[FORALL_IN_IMAGE; o_THM; LIFT_DROP; IN_BALL; DIST_LIFT; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ANTS_TAC THENL [ASM_MESON_TAC[REAL_ABS_SUB]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `b:real`) THEN ASM_SIMP_TAC[ENDS_IN_REAL_INTERVAL; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ASM_SIMP_TAC[DROP_CMUL; DROP_SUB; LIFT_DROP; REAL_LE_MUL_EQ; REAL_SUB_LT; REAL_ARITH `f * ba <= &0 <=> &0 <= --f * ba`] THEN REAL_ARITH_TAC);;
let REAL_DERIVATIVE_POS_RIGHT_MAXIMUM = 
prove (`!f f' a b e. a < b /\ &0 < e /\ (f has_real_derivative f') (atreal b within real_interval[a,b]) /\ (!x. x IN real_interval[a,b] /\ abs(x - b) < e ==> f x <= f b) ==> &0 <= f'`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `\x:real^1. f' % x`; `lift b`; `interval[lift a,lift b]`; `e:real`] DROP_DIFFERENTIAL_NEG_AT_MAXIMUM) THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL; CONVEX_INTERVAL; IN_INTER; IMP_CONJ] THEN ASM_REWRITE_TAC[GSYM IMAGE_LIFT_REAL_INTERVAL; IMAGE_EQ_EMPTY; GSYM HAS_REAL_FRECHET_DERIVATIVE_WITHIN] THEN ASM_SIMP_TAC[FORALL_IN_IMAGE; o_THM; LIFT_DROP; IN_BALL; DIST_LIFT; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ANTS_TAC THENL [ASM_MESON_TAC[REAL_ABS_SUB]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `a:real`) THEN ASM_SIMP_TAC[ENDS_IN_REAL_INTERVAL; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ASM_SIMP_TAC[DROP_CMUL; DROP_SUB; LIFT_DROP; REAL_LE_MUL_EQ; REAL_SUB_LT; REAL_ARITH `f * (a - b) <= &0 <=> &0 <= f * (b - a)`]);;
let REAL_DERIVATIVE_NEG_RIGHT_MINIMUM = 
prove (`!f f' a b e. a < b /\ &0 < e /\ (f has_real_derivative f') (atreal b within real_interval[a,b]) /\ (!x. x IN real_interval[a,b] /\ abs(x - b) < e ==> f b <= f x) ==> f' <= &0`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `\x:real^1. f' % x`; `lift b`; `interval[lift a,lift b]`; `e:real`] DROP_DIFFERENTIAL_POS_AT_MINIMUM) THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL; CONVEX_INTERVAL; IN_INTER; IMP_CONJ] THEN ASM_REWRITE_TAC[GSYM IMAGE_LIFT_REAL_INTERVAL; IMAGE_EQ_EMPTY; GSYM HAS_REAL_FRECHET_DERIVATIVE_WITHIN] THEN ASM_SIMP_TAC[FORALL_IN_IMAGE; o_THM; LIFT_DROP; IN_BALL; DIST_LIFT; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ANTS_TAC THENL [ASM_MESON_TAC[REAL_ABS_SUB]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `a:real`) THEN ASM_SIMP_TAC[ENDS_IN_REAL_INTERVAL; REAL_INTERVAL_NE_EMPTY; REAL_LT_IMP_LE] THEN ASM_SIMP_TAC[DROP_CMUL; DROP_SUB; LIFT_DROP] THEN ONCE_REWRITE_TAC[REAL_ARITH `&0 <= f * (a - b) <=> &0 <= --f * (b - a)`] THEN ASM_SIMP_TAC[REAL_LE_MUL_EQ; REAL_SUB_LT] THEN REAL_ARITH_TAC);;
let REAL_DERIVATIVE_ZERO_MAXMIN = 
prove (`!f f' x s. x IN s /\ real_open s /\ (f has_real_derivative f') (atreal x) /\ ((!y. y IN s ==> f y <= f x) \/ (!y. y IN s ==> f x <= f y)) ==> f' = &0`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `\x:real^1. f' % x`; `lift x`; `IMAGE lift s`] DIFFERENTIAL_ZERO_MAXMIN) THEN ASM_REWRITE_TAC[GSYM HAS_REAL_FRECHET_DERIVATIVE_AT; GSYM REAL_OPEN] THEN ASM_SIMP_TAC[FUN_IN_IMAGE; FORALL_IN_IMAGE] THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP] THEN DISCH_THEN(MP_TAC o C AP_THM `vec 1:real^1`) THEN REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_VEC; REAL_MUL_RID]);;
(* ------------------------------------------------------------------------- *) (* Rolle and Mean Value Theorem. *) (* ------------------------------------------------------------------------- *)
let REAL_ROLLE = 
prove (`!f f' a b. a < b /\ f a = f b /\ f real_continuous_on real_interval[a,b] /\ (!x. x IN real_interval(a,b) ==> (f has_real_derivative f'(x)) (atreal x)) ==> ?x. x IN real_interval(a,b) /\ f'(x) = &0`,
REWRITE_TAC[REAL_INTERVAL_INTERVAL; FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN REWRITE_TAC[REAL_CONTINUOUS_ON; HAS_REAL_VECTOR_DERIVATIVE_AT] THEN REWRITE_TAC[GSYM IMAGE_o; IMAGE_LIFT_DROP; has_vector_derivative] THEN REWRITE_TAC[LIFT_DROP] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `\x:real^1 h:real^1. f'(drop x) % h`; `lift a`; `lift b`] ROLLE) THEN ASM_REWRITE_TAC[o_THM; LIFT_DROP] THEN ANTS_TAC THENL [X_GEN_TAC `t:real^1` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `t:real^1`) THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM; FORALL_LIFT; LIFT_DROP; GSYM LIFT_CMUL] THEN REWRITE_TAC[REAL_MUL_AC]; MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^1` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o C AP_THM `lift(&1)`) THEN REWRITE_TAC[GSYM LIFT_CMUL; GSYM LIFT_NUM; LIFT_EQ; REAL_MUL_RID]]);;
let REAL_MVT = 
prove (`!f f' a b. a < b /\ f real_continuous_on real_interval[a,b] /\ (!x. x IN real_interval(a,b) ==> (f has_real_derivative f'(x)) (atreal x)) ==> ?x. x IN real_interval(a,b) /\ f(b) - f(a) = f'(x) * (b - a)`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`\x:real. f(x) - (f b - f a) / (b - a) * x`; `(\x. f'(x) - (f b - f a) / (b - a)):real->real`; `a:real`; `b:real`] REAL_ROLLE) THEN ASM_SIMP_TAC[REAL_FIELD `a < b ==> (fx - fba / (b - a) = &0 <=> fba = fx * (b - a))`] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_SIMP_TAC[REAL_CONTINUOUS_ON_SUB; REAL_CONTINUOUS_ON_LMUL; REAL_CONTINUOUS_ON_ID] THEN CONJ_TAC THENL [UNDISCH_TAC `a < b` THEN CONV_TAC REAL_FIELD; ALL_TAC] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_SUB THEN ASM_SIMP_TAC[] THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_MUL_RID] THEN ASM_SIMP_TAC[HAS_REAL_DERIVATIVE_LMUL_ATREAL; HAS_REAL_DERIVATIVE_ID]);;
let REAL_MVT_SIMPLE = 
prove (`!f f' a b. a < b /\ (!x. x IN real_interval[a,b] ==> (f has_real_derivative f'(x)) (atreal x within real_interval[a,b])) ==> ?x. x IN real_interval(a,b) /\ f(b) - f(a) = f'(x) * (b - a)`,
MP_TAC REAL_MVT THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [MATCH_MP_TAC REAL_DIFFERENTIABLE_ON_IMP_REAL_CONTINUOUS_ON THEN ASM_MESON_TAC[real_differentiable_on; real_differentiable]; ASM_MESON_TAC[HAS_REAL_DERIVATIVE_WITHIN_REAL_OPEN; REAL_OPEN_REAL_INTERVAL; REAL_INTERVAL_OPEN_SUBSET_CLOSED; HAS_REAL_DERIVATIVE_WITHIN_SUBSET; SUBSET]]);;
let REAL_MVT_VERY_SIMPLE = 
prove (`!f f' a b. a <= b /\ (!x. x IN real_interval[a,b] ==> (f has_real_derivative f'(x)) (atreal x within real_interval[a,b])) ==> ?x. x IN real_interval[a,b] /\ f(b) - f(a) = f'(x) * (b - a)`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `b:real = a` THENL [ASM_REWRITE_TAC[REAL_SUB_REFL; REAL_MUL_RZERO] THEN REWRITE_TAC[REAL_INTERVAL_SING; IN_SING; EXISTS_REFL]; ASM_REWRITE_TAC[REAL_LE_LT] THEN DISCH_THEN(MP_TAC o MATCH_MP REAL_MVT_SIMPLE) THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[REWRITE_RULE[SUBSET] REAL_INTERVAL_OPEN_SUBSET_CLOSED]]);;
let REAL_ROLLE_SIMPLE = 
prove (`!f f' a b. a < b /\ f a = f b /\ (!x. x IN real_interval[a,b] ==> (f has_real_derivative f'(x)) (atreal x within real_interval[a,b])) ==> ?x. x IN real_interval(a,b) /\ f'(x) = &0`,
MP_TAC REAL_MVT_SIMPLE THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[REAL_RING `a - a = b * (c - d) <=> b = &0 \/ c = d`] THEN ASM_MESON_TAC[REAL_LT_REFL]);;
(* ------------------------------------------------------------------------- *) (* Cauchy MVT and l'Hospital's rule. *) (* ------------------------------------------------------------------------- *)
let REAL_MVT_CAUCHY = 
prove (`!f g f' g' a b. a < b /\ f real_continuous_on real_interval[a,b] /\ g real_continuous_on real_interval[a,b] /\ (!x. x IN real_interval(a,b) ==> (f has_real_derivative f' x) (atreal x) /\ (g has_real_derivative g' x) (atreal x)) ==> ?x. x IN real_interval(a,b) /\ (f b - f a) * g'(x) = (g b - g a) * f'(x)`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`\x. (f:real->real)(x) * (g(b:real) - g(a)) - g(x) * (f(b) - f(a))`; `\x. (f':real->real)(x) * (g(b:real) - g(a)) - g'(x) * (f(b) - f(a))`; `a:real`; `b:real`] REAL_MVT) THEN ASM_SIMP_TAC[REAL_CONTINUOUS_ON_SUB; REAL_CONTINUOUS_ON_RMUL; HAS_REAL_DERIVATIVE_SUB; HAS_REAL_DERIVATIVE_RMUL_ATREAL] THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN UNDISCH_TAC `a < b` THEN CONV_TAC REAL_FIELD);;
let LHOSPITAL = 
prove (`!f g f' g' c l d. &0 < d /\ (!x. &0 < abs(x - c) /\ abs(x - c) < d ==> (f has_real_derivative f'(x)) (atreal x) /\ (g has_real_derivative g'(x)) (atreal x) /\ ~(g'(x) = &0)) /\ (f ---> &0) (atreal c) /\ (g ---> &0) (atreal c) /\ ((\x. f'(x) / g'(x)) ---> l) (atreal c) ==> ((\x. f(x) / g(x)) ---> l) (atreal c)`,
SUBGOAL_THEN `!f g f' g' c l d. &0 < d /\ (!x. &0 < abs(x - c) /\ abs(x - c) < d ==> (f has_real_derivative f'(x)) (atreal x) /\ (g has_real_derivative g'(x)) (atreal x) /\ ~(g'(x) = &0)) /\ f(c) = &0 /\ g(c) = &0 /\ (f ---> &0) (atreal c) /\ (g ---> &0) (atreal c) /\ ((\x. f'(x) / g'(x)) ---> l) (atreal c) ==> ((\x. f(x) / g(x)) ---> l) (atreal c)` ASSUME_TAC THENL [REWRITE_TAC[TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN REWRITE_TAC[FORALL_AND_THM] THEN REPEAT STRIP_TAC THEN SUBGOAL_THEN `(!x. abs(x - c) < d ==> f real_continuous atreal x) /\ (!x. abs(x - c) < d ==> g real_continuous atreal x)` STRIP_ASSUME_TAC THENL [REWRITE_TAC[AND_FORALL_THM] THEN X_GEN_TAC `x:real` THEN DISJ_CASES_TAC(REAL_ARITH `x = c \/ &0 < abs(x - c)`) THENL [ASM_REWRITE_TAC[REAL_CONTINUOUS_ATREAL]; ALL_TAC] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_DIFFERENTIABLE_IMP_CONTINUOUS_ATREAL THEN REWRITE_TAC[real_differentiable] THEN ASM_MESON_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `!x. &0 < abs(x - c) /\ abs(x - c) < d ==> ~(g x = &0)` STRIP_ASSUME_TAC THENL [REPEAT STRIP_TAC THEN SUBGOAL_THEN `c < x \/ x < c` DISJ_CASES_TAC THENL [ASM_REAL_ARITH_TAC; MP_TAC(ISPECL [`g:real->real`; `g':real->real`; `c:real`; `x:real`] REAL_ROLLE); MP_TAC(ISPECL [`g:real->real`; `g':real->real`; `x:real`; `c:real`] REAL_ROLLE)] THEN ASM_REWRITE_TAC[NOT_IMP; NOT_EXISTS_THM] THEN (REPEAT CONJ_TAC THENL [REWRITE_TAC[REAL_CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN REWRITE_TAC[IN_REAL_INTERVAL] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_ATREAL_WITHINREAL; REWRITE_TAC[IN_REAL_INTERVAL] THEN REPEAT STRIP_TAC; X_GEN_TAC `y:real` THEN REWRITE_TAC[IN_REAL_INTERVAL] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN REWRITE_TAC[]] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC); ALL_TAC] THEN UNDISCH_TAC `((\x. f' x / g' x) ---> l) (atreal c)` THEN REWRITE_TAC[REALLIM_ATREAL] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `min d k:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN X_GEN_TAC `x:real` THEN STRIP_TAC THEN SUBGOAL_THEN `?y. &0 < abs(y - c) /\ abs(y - c) < abs(x - c) /\ (f:real->real) x / g x = f' y / g' y` STRIP_ASSUME_TAC THENL [ALL_TAC; ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[REAL_LT_TRANS]] THEN SUBGOAL_THEN `c < x \/ x < c` DISJ_CASES_TAC THENL [ASM_REAL_ARITH_TAC; MP_TAC(ISPECL [`f:real->real`; `g:real->real`; `f':real->real`; `g':real->real`; `c:real`; `x:real`] REAL_MVT_CAUCHY); MP_TAC(ISPECL [`f:real->real`; `g:real->real`; `f':real->real`; `g':real->real`; `x:real`; `c:real`] REAL_MVT_CAUCHY)] THEN (ASM_REWRITE_TAC[IN_REAL_INTERVAL] THEN ANTS_TAC THENL [REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL [CONJ_TAC THEN REWRITE_TAC[REAL_CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN REWRITE_TAC[IN_REAL_INTERVAL] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONTINUOUS_ATREAL_WITHINREAL; REPEAT STRIP_TAC] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[REAL_SUB_RZERO] THEN GEN_TAC THEN STRIP_TAC THEN REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN MATCH_MP_TAC(REAL_FIELD `f * g' = g * f' /\ ~(g = &0) /\ ~(g' = &0) ==> f / g = f' / g'`) THEN CONJ_TAC THENL [ASM_REAL_ARITH_TAC; CONJ_TAC] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC]); REPEAT GEN_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`\x:real. if x = c then &0 else f(x)`; `\x:real. if x = c then &0 else g(x)`; `f':real->real`; `g':real->real`; `c:real`; `l:real`; `d:real`]) THEN REWRITE_TAC[] THEN MATCH_MP_TAC MONO_IMP THEN CONJ_TAC THEN REPEAT(MATCH_MP_TAC MONO_AND THEN CONJ_TAC) THEN TRY(SIMP_TAC[REALLIM_ATREAL;REAL_ARITH `&0 < abs(x - c) ==> ~(x = c)`] THEN NO_TAC) THEN DISCH_TAC THEN X_GEN_TAC `x:real` THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `x:real`) THEN ASM_REWRITE_TAC[] THEN REPEAT(MATCH_MP_TAC MONO_AND THEN CONJ_TAC) THEN REWRITE_TAC[] THEN MATCH_MP_TAC(REWRITE_RULE[TAUT `a /\ b /\ c ==> d <=> a /\ b ==> c ==> d`] HAS_REAL_DERIVATIVE_TRANSFORM_ATREAL) THEN EXISTS_TAC `abs(x - c)` THEN ASM_REAL_ARITH_TAC]);;
(* ------------------------------------------------------------------------- *) (* Darboux's theorem (intermediate value property for derivatives). *) (* ------------------------------------------------------------------------- *)
let REAL_DERIVATIVE_IVT_INCREASING = 
prove (`!f f' a b. a <= b /\ (!x. x IN real_interval[a,b] ==> (f has_real_derivative f'(x)) (atreal x within real_interval[a,b])) ==> !t. f'(a) <= t /\ t <= f'(b) ==> ?x. x IN real_interval[a,b] /\ f' x = t`,
REPEAT GEN_TAC THEN STRIP_TAC THEN GEN_TAC THEN ASM_CASES_TAC `(f':real->real) a = t` THENL [ASM_MESON_TAC[ENDS_IN_REAL_INTERVAL; REAL_INTERVAL_NE_EMPTY]; ALL_TAC] THEN ASM_CASES_TAC `(f':real->real) b = t` THENL [ASM_MESON_TAC[ENDS_IN_REAL_INTERVAL; REAL_INTERVAL_NE_EMPTY]; ALL_TAC] THEN ASM_CASES_TAC `b:real = a` THEN ASM_REWRITE_TAC[REAL_LE_ANTISYM] THEN SUBGOAL_THEN `a < b` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN ASM_REWRITE_TAC[REAL_LE_LT] THEN STRIP_TAC THEN MP_TAC(ISPECL [`\x:real. f x - t * x`; `real_interval[a,b]`] REAL_CONTINUOUS_ATTAINS_INF) THEN ASM_REWRITE_TAC[REAL_INTERVAL_NE_EMPTY; REAL_COMPACT_INTERVAL] THEN ANTS_TAC THENL [MATCH_MP_TAC REAL_DIFFERENTIABLE_ON_IMP_REAL_CONTINUOUS_ON THEN MATCH_MP_TAC REAL_DIFFERENTIABLE_ON_SUB THEN SIMP_TAC[REAL_DIFFERENTIABLE_ON_MUL; REAL_DIFFERENTIABLE_ON_ID; REAL_DIFFERENTIABLE_ON_CONST] THEN ASM_MESON_TAC[real_differentiable_on]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN MP_TAC(SPECL [`\x:real. f x - t * x`; `(f':real->real) x - t:real`; `x:real`; `real_interval(a,b)`] REAL_DERIVATIVE_ZERO_MAXMIN) THEN ASM_REWRITE_TAC[REAL_SUB_0] THEN DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[REAL_OPEN_REAL_INTERVAL] THEN ASM_SIMP_TAC[REAL_OPEN_CLOSED_INTERVAL; IN_DIFF] THEN ASM_CASES_TAC `x:real = a` THENL [FIRST_X_ASSUM SUBST_ALL_TAC THEN MP_TAC(ISPECL[`\x:real. f x - t * x`; `(f':real->real) a - t:real`; `a:real`; `b:real`; `&1`] REAL_DERIVATIVE_POS_LEFT_MINIMUM) THEN ASM_SIMP_TAC[REAL_LT_01; REAL_SUB_LE] THEN MATCH_MP_TAC(TAUT `~q /\ p ==> (p ==> q) ==> r`) THEN ASM_REWRITE_TAC[REAL_NOT_LE] THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_SUB THEN CONJ_TAC THENL [ALL_TAC; REAL_DIFF_TAC THEN REWRITE_TAC[REAL_MUL_RID]] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY]; ALL_TAC] THEN ASM_CASES_TAC `x:real = b` THENL [FIRST_X_ASSUM SUBST_ALL_TAC THEN MP_TAC(ISPECL[`\x:real. f x - t * x`; `(f':real->real) b - t:real`; `a:real`; `b:real`; `&1`] REAL_DERIVATIVE_NEG_RIGHT_MINIMUM) THEN ASM_SIMP_TAC[REAL_LT_01; REAL_SUB_LE] THEN MATCH_MP_TAC(TAUT `~q /\ p ==> (p ==> q) ==> r`) THEN ASM_REWRITE_TAC[REAL_NOT_LE; REAL_SUB_LT] THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_SUB THEN CONJ_TAC THENL [ALL_TAC; REAL_DIFF_TAC THEN REWRITE_TAC[REAL_MUL_RID]] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY]; ALL_TAC] THEN ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_SUB THEN CONJ_TAC THENL [ALL_TAC; REAL_DIFF_TAC THEN REWRITE_TAC[REAL_MUL_RID]] THEN SUBGOAL_THEN `(f has_real_derivative f' x) (atreal x within real_interval(a,b))` MP_TAC THENL [MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_SUBSET THEN EXISTS_TAC `real_interval[a,b]` THEN ASM_SIMP_TAC[REAL_INTERVAL_OPEN_SUBSET_CLOSED]; MATCH_MP_TAC EQ_IMP THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_REAL_OPEN THEN REWRITE_TAC[REAL_OPEN_REAL_INTERVAL] THEN ASM_REWRITE_TAC[REAL_OPEN_CLOSED_INTERVAL] THEN ASM SET_TAC[]]);;
let REAL_DERIVATIVE_IVT_DECREASING = 
prove (`!f f' a b t. a <= b /\ (!x. x IN real_interval[a,b] ==> (f has_real_derivative f'(x)) (atreal x within real_interval[a,b])) ==> !t. f'(b) <= t /\ t <= f'(a) ==> ?x. x IN real_interval[a,b] /\ f' x = t`,
REPEAT STRIP_TAC THEN MP_TAC(SPECL [`\x. --((f:real->real) x)`; `\x. --((f':real->real) x)`; `a:real`; `b:real`] REAL_DERIVATIVE_IVT_INCREASING) THEN ASM_SIMP_TAC[HAS_REAL_DERIVATIVE_NEG] THEN DISCH_THEN(MP_TAC o SPEC `--t:real`) THEN ASM_REWRITE_TAC[REAL_LE_NEG2; REAL_EQ_NEG2]);;
(* ------------------------------------------------------------------------- *) (* Continuity and differentiability of inverse functions. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_INVERSE_BASIC = 
prove (`!f g f' t y. (f has_real_derivative f') (atreal (g y)) /\ ~(f' = &0) /\ g real_continuous atreal y /\ real_open t /\ y IN t /\ (!z. z IN t ==> f (g z) = z) ==> (g has_real_derivative inv(f')) (atreal y)`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_AT; REAL_OPEN; REAL_CONTINUOUS_CONTINUOUS_ATREAL] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_DERIVATIVE_INVERSE_BASIC THEN MAP_EVERY EXISTS_TAC [`lift o f o drop`; `\x:real^1. f' % x`; `IMAGE lift t`] THEN ASM_REWRITE_TAC[o_THM; LIFT_DROP; LIFT_IN_IMAGE_LIFT] THEN ASM_SIMP_TAC[FORALL_IN_IMAGE; LIFT_DROP; LINEAR_COMPOSE_CMUL; LINEAR_ID] THEN REWRITE_TAC[FUN_EQ_THM; I_THM; o_THM; VECTOR_MUL_ASSOC] THEN ASM_SIMP_TAC[REAL_MUL_LINV; VECTOR_MUL_LID]);;
let HAS_REAL_DERIVATIVE_INVERSE_STRONG = 
prove (`!f g f' s x. real_open s /\ x IN s /\ f real_continuous_on s /\ (!x. x IN s ==> g (f x) = x) /\ (f has_real_derivative f') (atreal x) /\ ~(f' = &0) ==> (g has_real_derivative inv(f')) (atreal (f x))`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_AT; REAL_OPEN; REAL_CONTINUOUS_ON] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPEC `lift o f o drop` HAS_DERIVATIVE_INVERSE_STRONG) THEN REWRITE_TAC[FORALL_LIFT; o_THM; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN MAP_EVERY EXISTS_TAC [`\x:real^1. f' % x`; `IMAGE lift s`] THEN ASM_REWRITE_TAC[o_THM; LIFT_DROP; LIFT_IN_IMAGE_LIFT] THEN ASM_SIMP_TAC[FUN_EQ_THM; I_THM; o_THM; VECTOR_MUL_ASSOC] THEN ASM_SIMP_TAC[REAL_MUL_RINV; VECTOR_MUL_LID]);;
let HAS_REAL_DERIVATIVE_INVERSE_STRONG_X = 
prove (`!f g f' s y. real_open s /\ (g y) IN s /\ f real_continuous_on s /\ (!x. x IN s ==> (g(f(x)) = x)) /\ (f has_real_derivative f') (atreal (g y)) /\ ~(f' = &0) /\ f(g y) = y ==> (g has_real_derivative inv(f')) (atreal y)`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_AT; REAL_OPEN; REAL_CONTINUOUS_ON] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPEC `lift o f o drop` HAS_DERIVATIVE_INVERSE_STRONG_X) THEN REWRITE_TAC[FORALL_LIFT; o_THM; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN MAP_EVERY EXISTS_TAC [`\x:real^1. f' % x`; `IMAGE lift s`] THEN ASM_REWRITE_TAC[o_THM; LIFT_DROP; LIFT_IN_IMAGE_LIFT] THEN ASM_SIMP_TAC[FUN_EQ_THM; I_THM; o_THM; VECTOR_MUL_ASSOC] THEN ASM_SIMP_TAC[REAL_MUL_RINV; VECTOR_MUL_LID]);;
(* ------------------------------------------------------------------------- *) (* Real differentiation of sequences and series. *) (* ------------------------------------------------------------------------- *)
let HAS_REAL_DERIVATIVE_SEQUENCE = 
prove (`!s f f' g'. is_realinterval s /\ (!n x. x IN s ==> (f n has_real_derivative f' n x) (atreal x within s)) /\ (!e. &0 < e ==> ?N. !n x. n >= N /\ x IN s ==> abs(f' n x - g' x) <= e) /\ (?x l. x IN s /\ ((\n. f n x) ---> l) sequentially) ==> ?g. !x. x IN s ==> ((\n. f n x) ---> g x) sequentially /\ (g has_real_derivative g' x) (atreal x within s)`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; IS_REALINTERVAL_CONVEX; TENDSTO_REAL] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`IMAGE lift s`; `\n:num. lift o f n o drop`; `\n:num x:real^1 h:real^1. f' n (drop x) % h`; `\x:real^1 h:real^1. g' (drop x) % h`] HAS_DERIVATIVE_SEQUENCE) THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE; LIFT_DROP] THEN ANTS_TAC THENL [REWRITE_TAC[IMP_CONJ; RIGHT_EXISTS_AND_THM; RIGHT_FORALL_IMP_THM; EXISTS_IN_IMAGE; FORALL_IN_IMAGE] THEN REWRITE_TAC[EXISTS_LIFT; o_THM; LIFT_DROP] THEN RULE_ASSUM_TAC(REWRITE_RULE[o_DEF]) THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN REWRITE_TAC[GSYM VECTOR_SUB_RDISTRIB; NORM_MUL] THEN ASM_MESON_TAC[REAL_LE_RMUL; NORM_POS_LE]; REWRITE_TAC[o_DEF; LIFT_DROP] THEN DISCH_THEN(X_CHOOSE_TAC `g:real^1->real^1`) THEN EXISTS_TAC `drop o g o lift` THEN RULE_ASSUM_TAC(REWRITE_RULE[ETA_AX]) THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX]]);;
let HAS_REAL_DERIVATIVE_SERIES = 
prove (`!s f f' g' k. is_realinterval s /\ (!n x. x IN s ==> (f n has_real_derivative f' n x) (atreal x within s)) /\ (!e. &0 < e ==> ?N. !n x. n >= N /\ x IN s ==> abs(sum (k INTER (0..n)) (\i. f' i x) - g' x) <= e) /\ (?x l. x IN s /\ ((\n. f n x) real_sums l) k) ==> ?g. !x. x IN s ==> ((\n. f n x) real_sums g x) k /\ (g has_real_derivative g' x) (atreal x within s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_sums] THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_SEQUENCE THEN EXISTS_TAC `\n:num x:real. sum(k INTER (0..n)) (\n. f' n x):real` THEN ASM_SIMP_TAC[ETA_AX; FINITE_INTER_NUMSEG; HAS_REAL_DERIVATIVE_SUM]);;
let REAL_DIFFERENTIABLE_BOUND = 
prove (`!f f' s B. is_realinterval s /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s) /\ abs(f' x) <= B) ==> !x y. x IN s /\ y IN s ==> abs(f x - f y) <= B * abs(x - y)`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; IS_REALINTERVAL_CONVEX; o_DEF] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`lift o f o drop`; `\x h:real^1. f' (drop x) % h`; `IMAGE lift s`; `B:real`] DIFFERENTIABLE_BOUND) THEN ASM_SIMP_TAC[o_DEF; FORALL_IN_IMAGE; LIFT_DROP] THEN ANTS_TAC THENL [X_GEN_TAC `v:real` THEN DISCH_TAC THEN MP_TAC(ISPEC `\h:real^1. f' (v:real) % h` ONORM) THEN SIMP_TAC[LINEAR_COMPOSE_CMUL; LINEAR_ID] THEN DISCH_THEN(MATCH_MP_TAC o CONJUNCT2) THEN ASM_SIMP_TAC[NORM_MUL; REAL_LE_RMUL; NORM_POS_LE]; SIMP_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE; LIFT_DROP] THEN ASM_SIMP_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; GSYM LIFT_SUB; NORM_LIFT]]);;
let REAL_TAYLOR_MVT_POS = 
prove (`!f a x n. a < x /\ (!i t. t IN real_interval[a,x] /\ i <= n ==> ((f i) has_real_derivative f (i + 1) t) (atreal t within real_interval[a,x])) ==> ?t. t IN real_interval(a,x) /\ f 0 x = sum (0..n) (\i. f i a * (x - a) pow i / &(FACT i)) + f (n + 1) t * (x - a) pow (n + 1) / &(FACT(n + 1))`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `?B. sum (0..n) (\i. f i a * (x - a) pow i / &(FACT i)) + B * (x - a) pow (n + 1) = f 0 x` STRIP_ASSUME_TAC THENL [MATCH_MP_TAC(MESON[] `a + (y - a) / x * x:real = y ==> ?b. a + b * x = y`) THEN MATCH_MP_TAC(REAL_FIELD `~(x = &0) ==> a + (y - a) / x * x = y`) THEN ASM_REWRITE_TAC[REAL_POW_EQ_0; REAL_SUB_0] THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN MP_TAC(SPECL [`\t. sum(0..n) (\i. f i t * (x - t) pow i / &(FACT i)) + B * (x - t) pow (n + 1)`; `\t. (f (n + 1) t * (x - t) pow n / &(FACT n)) - B * &(n + 1) * (x - t) pow n`; `a:real`; `x:real`] REAL_ROLLE_SIMPLE) THEN ASM_REWRITE_TAC[] THEN ANTS_TAC THENL [CONJ_TAC THENL [SIMP_TAC[SUM_CLAUSES_LEFT; LE_0] THEN REWRITE_TAC[GSYM ADD1; real_pow; REAL_SUB_REFL; REAL_POW_ZERO; REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_ADD_RID] THEN CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[NOT_SUC; REAL_MUL_RZERO; REAL_DIV_1; REAL_MUL_RID] THEN REWRITE_TAC[REAL_ARITH `x = (x + y) + &0 <=> y = &0`] THEN MATCH_MP_TAC SUM_EQ_0_NUMSEG THEN SIMP_TAC[ARITH; ARITH_RULE `1 <= i ==> ~(i = 0)`] THEN REWRITE_TAC[real_div; REAL_MUL_LZERO; REAL_MUL_RZERO]; ALL_TAC] THEN X_GEN_TAC `t:real` THEN DISCH_TAC THEN REWRITE_TAC[real_sub] THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_ADD THEN CONJ_TAC THENL [ALL_TAC; REAL_DIFF_TAC THEN REWRITE_TAC[ADD_SUB] THEN CONV_TAC REAL_RING] THEN REWRITE_TAC[GSYM real_sub] THEN MATCH_MP_TAC(MESON[] `!g'. f' = g' /\ (f has_real_derivative g') net ==> (f has_real_derivative f') net`) THEN EXISTS_TAC `sum (0..n) (\i. f i t * --(&i * (x - t) pow (i - 1)) / &(FACT i) + f (i + 1) t * (x - t) pow i / &(FACT i))` THEN REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; MATCH_MP_TAC HAS_REAL_DERIVATIVE_SUM THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN X_GEN_TAC `m:num` THEN STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_MUL_WITHIN THEN ASM_SIMP_TAC[ETA_AX] THEN REAL_DIFF_TAC THEN REAL_ARITH_TAC] THEN SIMP_TAC[SUM_CLAUSES_LEFT; LE_0; ARITH; FACT; REAL_DIV_1; real_pow; REAL_MUL_LZERO; REAL_NEG_0; REAL_MUL_RZERO; REAL_MUL_RID; REAL_ADD_LID] THEN ASM_CASES_TAC `n = 0` THENL [ASM_REWRITE_TAC[SUM_CLAUSES_NUMSEG; ARITH; FACT] THEN REAL_ARITH_TAC; ALL_TAC] THEN ASM_SIMP_TAC[SPECL [`f:num->real`; `1`] SUM_OFFSET_0; LE_1] THEN REWRITE_TAC[ADD_SUB] THEN REWRITE_TAC[GSYM ADD1; FACT; GSYM REAL_OF_NUM_MUL; GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_SUC] THEN REWRITE_TAC[real_div; REAL_INV_MUL] THEN REWRITE_TAC[REAL_ARITH `--(n * x) * (inv n * inv y):real = --(n / n) * x / y`] THEN REWRITE_TAC[REAL_FIELD `--((&n + &1) / (&n + &1)) * x = --x`] THEN REWRITE_TAC[GSYM REAL_INV_MUL; REAL_OF_NUM_MUL; REAL_OF_NUM_SUC] THEN REWRITE_TAC[GSYM(CONJUNCT2 FACT)] THEN REWRITE_TAC[REAL_ARITH `a * --b + c:real = c - a * b`] THEN REWRITE_TAC[ADD1; GSYM real_div; SUM_DIFFS_ALT; LE_0] THEN ASM_SIMP_TAC[ARITH_RULE `~(n = 0) ==> n - 1 + 1 = n`; FACT] THEN REWRITE_TAC[ADD_CLAUSES] THEN REAL_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [GSYM th]) THEN REWRITE_TAC[REAL_EQ_ADD_LCANCEL] THEN REWRITE_TAC[REAL_ARITH `a * b / c:real = a / c * b`] THEN AP_THM_TAC THEN AP_TERM_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH `a * x / f - B * k * x = &0 ==> (B * k - a / f) * x = &0`)) THEN REWRITE_TAC[REAL_ENTIRE; REAL_POW_EQ_0; REAL_SUB_0] THEN ASM_CASES_TAC `x:real = t` THENL [ASM_MESON_TAC[IN_REAL_INTERVAL; REAL_LT_REFL]; ALL_TAC] THEN ASM_REWRITE_TAC[GSYM ADD1; FACT] THEN REWRITE_TAC[GSYM REAL_OF_NUM_MUL; GSYM REAL_OF_NUM_ADD; ADD1] THEN SUBGOAL_THEN `~(&(FACT n) = &0)` MP_TAC THENL [REWRITE_TAC[REAL_OF_NUM_EQ; FACT_NZ]; CONV_TAC REAL_FIELD]);;
let REAL_TAYLOR_MVT_NEG = 
prove (`!f a x n. x < a /\ (!i t. t IN real_interval[x,a] /\ i <= n ==> ((f i) has_real_derivative f (i + 1) t) (atreal t within real_interval[x,a])) ==> ?t. t IN real_interval(x,a) /\ f 0 x = sum (0..n) (\i. f i a * (x - a) pow i / &(FACT i)) + f (n + 1) t * (x - a) pow (n + 1) / &(FACT(n + 1))`,
REWRITE_TAC[IN_REAL_INTERVAL] THEN REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[MESON[REAL_NEG_NEG] `(?x:real. P x) <=> (?x. P(--x))`] THEN MP_TAC(SPECL [`\n x. (-- &1) pow n * (f:num->real->real) n (--x)`; `--a:real`; ` --x:real`; `n:num`] REAL_TAYLOR_MVT_POS) THEN REWRITE_TAC[REAL_NEG_NEG] THEN ONCE_REWRITE_TAC[REAL_ARITH `(x * y) * z / w:real = y * (x * z) / w`] THEN REWRITE_TAC[GSYM REAL_POW_MUL] THEN REWRITE_TAC[REAL_ARITH `-- &1 * (--x - --a) = x - a`] THEN REWRITE_TAC[IN_REAL_INTERVAL; real_pow; REAL_MUL_LID] THEN REWRITE_TAC[REAL_ARITH `--a < t /\ t < --x <=> x < --t /\ --t < a`] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[REAL_LT_NEG2] THEN MAP_EVERY X_GEN_TAC [`m:num`; `t:real`] THEN STRIP_TAC THEN REWRITE_TAC[REAL_POW_ADD; GSYM REAL_MUL_ASSOC] THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_LMUL_WITHIN THEN ONCE_REWRITE_TAC[REAL_ARITH `y pow 1 * x:real = x * y`] THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC REAL_DIFF_CHAIN_WITHIN THEN CONJ_TAC THENL [GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM ETA_AX] THEN REAL_DIFF_TAC THEN REFL_TAC; ALL_TAC] THEN SUBGOAL_THEN `IMAGE (--) (real_interval[--a,--x]) = real_interval[x,a]` SUBST1_TAC THENL [REWRITE_TAC[EXTENSION; IN_IMAGE; IN_REAL_INTERVAL] THEN REWRITE_TAC[REAL_ARITH `x:real = --y <=> --x = y`; UNWIND_THM1] THEN REAL_ARITH_TAC; FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC]);;
let REAL_TAYLOR = 
prove (`!f n s B. is_realinterval s /\ (!i x. x IN s /\ i <= n ==> ((f i) has_real_derivative f (i + 1) x) (atreal x within s)) /\ (!x. x IN s ==> abs(f (n + 1) x) <= B) ==> !w z. w IN s /\ z IN s ==> abs(f 0 z - sum (0..n) (\i. f i w * (z - w) pow i / &(FACT i))) <= B * abs(z - w) pow (n + 1) / &(FACT(n + 1))`,
REPEAT STRIP_TAC THEN REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC (REAL_ARITH `w = z \/ w < z \/ z < w`) THENL [ASM_SIMP_TAC[SUM_CLAUSES_LEFT; LE_0; REAL_SUB_REFL; REAL_POW_ZERO; REAL_ABS_0; ARITH; ADD_EQ_0; real_div] THEN REWRITE_TAC[REAL_MUL_LZERO; FACT; REAL_INV_1; REAL_MUL_RZERO] THEN MATCH_MP_TAC(REAL_ARITH `y = &0 ==> abs(x - (x * &1 * &1 + y)) <= &0`) THEN MATCH_MP_TAC SUM_EQ_0_NUMSEG THEN SIMP_TAC[ARITH; LE_1; REAL_MUL_RZERO; REAL_MUL_LZERO]; MP_TAC(ISPECL [`f:num->real->real`; `w:real`; `z:real`; `n:num`] REAL_TAYLOR_MVT_POS) THEN ASM_REWRITE_TAC[] THEN SUBGOAL_THEN `real_interval[w,z] SUBSET s` ASSUME_TAC THENL [SIMP_TAC[SUBSET; IN_REAL_INTERVAL] THEN ASM_MESON_TAC[is_realinterval]; ALL_TAC]; MP_TAC(ISPECL [`f:num->real->real`; `w:real`; `z:real`; `n:num`] REAL_TAYLOR_MVT_NEG) THEN ASM_REWRITE_TAC[] THEN SUBGOAL_THEN `real_interval[z,w] SUBSET s` ASSUME_TAC THENL [SIMP_TAC[SUBSET; IN_REAL_INTERVAL] THEN ASM_MESON_TAC[is_realinterval]; ALL_TAC]] THEN (ANTS_TAC THENL [MAP_EVERY X_GEN_TAC [`m:num`; `t:real`] THEN STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_SUBSET THEN EXISTS_TAC `s:real->bool` THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `t:real` (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN REWRITE_TAC[REAL_ADD_SUB; REAL_ABS_MUL; REAL_ABS_DIV] THEN REWRITE_TAC[REAL_ABS_POW; REAL_ABS_NUM] THEN MATCH_MP_TAC REAL_LE_RMUL THEN SIMP_TAC[REAL_LE_DIV; REAL_POS; REAL_POW_LE; REAL_ABS_POS] THEN ASM_MESON_TAC[REAL_INTERVAL_OPEN_SUBSET_CLOSED; SUBSET]));;
(* ------------------------------------------------------------------------- *) (* Comparing sums and "integrals" via real antiderivatives. *) (* ------------------------------------------------------------------------- *)
let REAL_SUM_INTEGRAL_UBOUND_INCREASING = 
prove (`!f g m n. m <= n /\ (!x. x IN real_interval[&m,&n + &1] ==> (g has_real_derivative f(x)) (atreal x within real_interval[&m,&n + &1])) /\ (!x y. &m <= x /\ x <= y /\ y <= &n + &1 ==> f x <= f y) ==> sum(m..n) (\k. f(&k)) <= g(&n + &1) - g(&m)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(m..n) (\k. g(&(k + 1)) - g(&k))` THEN CONJ_TAC THENL [ALL_TAC; ASM_SIMP_TAC[SUM_DIFFS_ALT; REAL_OF_NUM_ADD; REAL_LE_REFL]] THEN MATCH_MP_TAC SUM_LE_NUMSEG THEN X_GEN_TAC `k:num` THEN STRIP_TAC THEN MP_TAC(ISPECL [`g:real->real`; `f:real->real`; `&k`; `&(k + 1)`] REAL_MVT_SIMPLE) THEN ASM_REWRITE_TAC[REAL_OF_NUM_LT; ARITH_RULE `k < k + 1`] THEN ASM_REWRITE_TAC[GSYM REAL_OF_NUM_ADD; REAL_ADD_SUB] THEN ANTS_TAC THENL [REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_SUBSET THEN EXISTS_TAC `real_interval[&m,&n + &1]` THEN CONJ_TAC THENL [FIRST_X_ASSUM MATCH_MP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_REAL_INTERVAL]); REWRITE_TAC[SUBSET] THEN GEN_TAC] THEN REWRITE_TAC[IN_REAL_INTERVAL] THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC; DISCH_THEN(X_CHOOSE_THEN `t:real` (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN REWRITE_TAC[REAL_MUL_RID] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_REAL_INTERVAL]) THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC]);;
let REAL_SUM_INTEGRAL_UBOUND_DECREASING = 
prove (`!f g m n. m <= n /\ (!x. x IN real_interval[&m - &1,&n] ==> (g has_real_derivative f(x)) (atreal x within real_interval[&m - &1,&n])) /\ (!x y. &m - &1 <= x /\ x <= y /\ y <= &n ==> f y <= f x) ==> sum(m..n) (\k. f(&k)) <= g(&n) - g(&m - &1)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(m..n) (\k. g(&(k + 1) - &1) - g(&k - &1))` THEN CONJ_TAC THENL [ALL_TAC; ASM_REWRITE_TAC[SUM_DIFFS_ALT] THEN ASM_REWRITE_TAC[GSYM REAL_OF_NUM_ADD; REAL_ARITH `(x + &1) - &1 = x`] THEN REWRITE_TAC[REAL_LE_REFL]] THEN MATCH_MP_TAC SUM_LE_NUMSEG THEN X_GEN_TAC `k:num` THEN STRIP_TAC THEN MP_TAC(ISPECL [`g:real->real`; `f:real->real`; `&k - &1`; `&k`] REAL_MVT_SIMPLE) THEN ASM_REWRITE_TAC[REAL_ARITH `k - &1 < k`] THEN ANTS_TAC THENL [REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_SUBSET THEN EXISTS_TAC `real_interval[&m - &1,&n]` THEN CONJ_TAC THENL [FIRST_X_ASSUM MATCH_MP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_REAL_INTERVAL]); REWRITE_TAC[SUBSET] THEN GEN_TAC] THEN REWRITE_TAC[IN_REAL_INTERVAL] THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC; REWRITE_TAC[GSYM REAL_OF_NUM_ADD; REAL_ARITH `(a + &1) - &1 = a`] THEN DISCH_THEN(X_CHOOSE_THEN `t:real` (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN REWRITE_TAC[REAL_ARITH `a * (x - (x - &1)) = a`] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_REAL_INTERVAL]) THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC]);;
let REAL_SUM_INTEGRAL_LBOUND_INCREASING = 
prove (`!f g m n. m <= n /\ (!x. x IN real_interval[&m - &1,&n] ==> (g has_real_derivative f(x)) (atreal x within real_interval[&m - &1,&n])) /\ (!x y. &m - &1 <= x /\ x <= y /\ y <= &n ==> f x <= f y) ==> g(&n) - g(&m - &1) <= sum(m..n) (\k. f(&k))`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`\z. --((f:real->real) z)`; `\z. --((g:real->real) z)`; `m:num`; `n:num`] REAL_SUM_INTEGRAL_UBOUND_DECREASING) THEN REWRITE_TAC[RE_NEG; RE_SUB; SUM_NEG; REAL_LE_NEG2; REAL_ARITH `--x - --y:real = --(x - y)`] THEN ASM_SIMP_TAC[HAS_REAL_DERIVATIVE_NEG]);;
let REAL_SUM_INTEGRAL_LBOUND_DECREASING = 
prove (`!f g m n. m <= n /\ (!x. x IN real_interval[&m,&n + &1] ==> (g has_real_derivative f(x)) (atreal x within real_interval[&m,&n + &1])) /\ (!x y. &m <= x /\ x <= y /\ y <= &n + &1 ==> f y <= f x) ==> g(&n + &1) - g(&m) <= sum(m..n) (\k. f(&k))`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`\z. --((f:real->real) z)`; `\z. --((g:real->real) z)`; `m:num`; `n:num`] REAL_SUM_INTEGRAL_UBOUND_INCREASING) THEN REWRITE_TAC[RE_NEG; RE_SUB; SUM_NEG; REAL_LE_NEG2; REAL_ARITH `--x - --y:real = --(x - y)`] THEN ASM_SIMP_TAC[HAS_REAL_DERIVATIVE_NEG]);;
let REAL_SUM_INTEGRAL_BOUNDS_INCREASING = 
prove (`!f g m n. m <= n /\ (!x. x IN real_interval[&m - &1,&n + &1] ==> (g has_real_derivative f x) (atreal x within real_interval[&m - &1,&n + &1])) /\ (!x y. &m - &1 <= x /\ x <= y /\ y <= &n + &1 ==> f x <= f y) ==> g(&n) - g(&m - &1) <= sum(m..n) (\k. f(&k)) /\ sum (m..n) (\k. f(&k)) <= g(&n + &1) - g(&m)`,
REPEAT STRIP_TAC THENL [MATCH_MP_TAC REAL_SUM_INTEGRAL_LBOUND_INCREASING; MATCH_MP_TAC REAL_SUM_INTEGRAL_UBOUND_INCREASING] THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN TRY(MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_SUBSET THEN EXISTS_TAC `real_interval[&m - &1,&n + &1]` THEN CONJ_TAC) THEN TRY(FIRST_X_ASSUM MATCH_MP_TAC) THEN TRY(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_REAL_INTERVAL])) THEN REWRITE_TAC[SUBSET; IN_REAL_INTERVAL] THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC);;
let REAL_SUM_INTEGRAL_BOUNDS_DECREASING = 
prove (`!f g m n. m <= n /\ (!x. x IN real_interval[&m - &1,&n + &1] ==> (g has_real_derivative f(x)) (atreal x within real_interval[&m - &1,&n + &1])) /\ (!x y. &m - &1 <= x /\ x <= y /\ y <= &n + &1 ==> f y <= f x) ==> g(&n + &1) - g(&m) <= sum(m..n) (\k. f(&k)) /\ sum(m..n) (\k. f(&k)) <= g(&n) - g(&m - &1)`,
REPEAT STRIP_TAC THENL [MATCH_MP_TAC REAL_SUM_INTEGRAL_LBOUND_DECREASING; MATCH_MP_TAC REAL_SUM_INTEGRAL_UBOUND_DECREASING] THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN TRY(MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_SUBSET THEN EXISTS_TAC `real_interval[&m - &1,&n + &1]` THEN CONJ_TAC) THEN TRY(FIRST_X_ASSUM MATCH_MP_TAC) THEN TRY(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_REAL_INTERVAL])) THEN REWRITE_TAC[SUBSET; IN_REAL_INTERVAL] THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Relating different kinds of real limits. *) (* ------------------------------------------------------------------------- *)
let LIM_POSINFINITY_SEQUENTIALLY = 
prove (`!f l. (f --> l) at_posinfinity ==> ((\n. f(&n)) --> l) sequentially`,
REPEAT GEN_TAC THEN REWRITE_TAC[LIM_AT_POSINFINITY; LIM_SEQUENTIALLY] 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_TAC `B:real`) THEN MP_TAC(ISPEC `B:real` REAL_ARCH_SIMPLE) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC);;
let REALLIM_POSINFINITY_SEQUENTIALLY = 
prove (`!f l. (f ---> l) at_posinfinity ==> ((\n. f(&n)) ---> l) sequentially`,
REPEAT GEN_TAC THEN REWRITE_TAC[TENDSTO_REAL] THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_POSINFINITY_SEQUENTIALLY) THEN REWRITE_TAC[o_DEF]);;
let LIM_ZERO_POSINFINITY = 
prove (`!f l. ((\x. f(&1 / x)) --> l) (atreal (&0)) ==> (f --> l) at_posinfinity`,
REPEAT GEN_TAC THEN REWRITE_TAC[LIM_ATREAL; LIM_AT_POSINFINITY] 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 REWRITE_TAC[dist; REAL_SUB_RZERO; real_ge] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `&2 / d` THEN X_GEN_TAC `z:real` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `inv(z):real`) THEN REWRITE_TAC[real_div; REAL_MUL_LINV; REAL_INV_INV] THEN REWRITE_TAC[REAL_MUL_LID] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[REAL_ABS_INV; REAL_LT_INV_EQ] THEN CONJ_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH `a <= z ==> &0 < a ==> &0 < abs z`)); GEN_REWRITE_TAC RAND_CONV [GSYM REAL_INV_INV] THEN MATCH_MP_TAC REAL_LT_INV2 THEN ASM_REWRITE_TAC[REAL_LT_INV_EQ] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH `&2 / d <= z ==> &0 < &2 / d ==> inv d < abs z`))] THEN ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH]);;
let LIM_ZERO_NEGINFINITY = 
prove (`!f l. ((\x. f(&1 / x)) --> l) (atreal (&0)) ==> (f --> l) at_neginfinity`,
REPEAT GEN_TAC THEN REWRITE_TAC[LIM_ATREAL; LIM_AT_NEGINFINITY] 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 REWRITE_TAC[dist; REAL_SUB_RZERO; real_ge] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `--(&2 / d)` THEN X_GEN_TAC `z:real` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `inv(z):real`) THEN REWRITE_TAC[real_div; REAL_MUL_LINV; REAL_INV_INV] THEN REWRITE_TAC[REAL_MUL_LID] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[REAL_ABS_INV; REAL_LT_INV_EQ] THEN CONJ_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH `z <= --a ==> &0 < a ==> &0 < abs z`)); GEN_REWRITE_TAC RAND_CONV [GSYM REAL_INV_INV] THEN MATCH_MP_TAC REAL_LT_INV2 THEN ASM_REWRITE_TAC[REAL_LT_INV_EQ] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH `z <= --(&2 / d) ==> &0 < &2 / d ==> inv d < abs z`))] THEN ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH]);;
let REALLIM_ZERO_POSINFINITY = 
prove (`!f l. ((\x. f(&1 / x)) ---> l) (atreal (&0)) ==> (f ---> l) at_posinfinity`,
REPEAT GEN_TAC THEN REWRITE_TAC[TENDSTO_REAL] THEN REWRITE_TAC[o_DEF; LIM_ZERO_POSINFINITY]);;
let REALLIM_ZERO_NEGINFINITY = 
prove (`!f l. ((\x. f(&1 / x)) ---> l) (atreal (&0)) ==> (f ---> l) at_neginfinity`,
REPEAT GEN_TAC THEN REWRITE_TAC[TENDSTO_REAL] THEN REWRITE_TAC[o_DEF; LIM_ZERO_NEGINFINITY]);;
(* ------------------------------------------------------------------------- *) (* Real segments (bidirectional intervals). *) (* ------------------------------------------------------------------------- *)
let closed_real_segment = define
 `closed_real_segment[a,b] = {(&1 - u) * a + u * b | &0 <= u /\ u <= &1}`;;
let open_real_segment = new_definition
 `open_real_segment(a,b) = closed_real_segment[a,b] DIFF {a,b}`;;
make_overloadable "real_segment" `:A`;; overload_interface("real_segment",`open_real_segment`);; overload_interface("real_segment",`closed_real_segment`);;
let real_segment = 
prove (`real_segment[a,b] = {(&1 - u) * a + u * b | &0 <= u /\ u <= &1} /\ real_segment(a,b) = real_segment[a,b] DIFF {a,b}`,
let REAL_SEGMENT_SEGMENT = 
prove (`(!a b. real_segment[a,b] = IMAGE drop (segment[lift a,lift b])) /\ (!a b. real_segment(a,b) = IMAGE drop (segment(lift a,lift b)))`,
REWRITE_TAC[segment; real_segment] THEN SIMP_TAC[IMAGE_DIFF_INJ; DROP_EQ; IMAGE_CLAUSES; LIFT_DROP] THEN ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN REWRITE_TAC[GSYM IMAGE_o; o_DEF; DROP_ADD; DROP_CMUL; LIFT_DROP]);;
let SEGMENT_REAL_SEGMENT = 
prove (`(!a b. segment[a,b] = IMAGE lift (real_segment[drop a,drop b])) /\ (!a b. segment(a,b) = IMAGE lift (real_segment(drop a,drop b)))`,
REWRITE_TAC[REAL_SEGMENT_SEGMENT; GSYM IMAGE_o] THEN REWRITE_TAC[o_DEF; IMAGE_ID; LIFT_DROP]);;
let IMAGE_LIFT_REAL_SEGMENT = 
prove (`(!a b. IMAGE lift (real_segment[a,b]) = segment[lift a,lift b]) /\ (!a b. IMAGE lift (real_segment(a,b)) = segment(lift a,lift b))`,
let REAL_SEGMENT_INTERVAL = 
prove (`(!a b. real_segment[a,b] = if a <= b then real_interval[a,b] else real_interval[b,a]) /\ (!a b. real_segment(a,b) = if a <= b then real_interval(a,b) else real_interval(b,a))`,
REWRITE_TAC[REAL_SEGMENT_SEGMENT; SEGMENT_1; LIFT_DROP] THEN REWRITE_TAC[REAL_INTERVAL_INTERVAL] THEN CONJ_TAC THEN REPEAT GEN_TAC THEN COND_CASES_TAC THEN REWRITE_TAC[]);;
let REAL_CONTINUOUS_INJECTIVE_IFF_MONOTONIC = 
prove (`!f s. f real_continuous_on s /\ is_realinterval s ==> ((!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) <=> (!x y. x IN s /\ y IN s /\ x < y ==> f x < f y) \/ (!x y. x IN s /\ y IN s /\ x < y ==> f y < f x))`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_CONTINUOUS_ON; IS_REALINTERVAL_IS_INTERVAL] THEN DISCH_THEN(MP_TAC o MATCH_MP CONTINUOUS_INJECTIVE_IFF_MONOTONIC) THEN REWRITE_TAC[FORALL_LIFT; LIFT_IN_IMAGE_LIFT; o_THM; LIFT_DROP; LIFT_EQ]);;
(* ------------------------------------------------------------------------- *) (* Convex real->real functions. *) (* ------------------------------------------------------------------------- *) parse_as_infix ("real_convex_on",(12,"right"));;
let real_convex_on = new_definition
  `(f:real->real) real_convex_on s <=>
        !x y u v. x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ (u + v = &1)
                  ==> f(u * x + v * y) <= u * f(x) + v * f(y)`;;
let REAL_CONVEX_ON = 
prove (`!f s. f real_convex_on s <=> (f o drop) convex_on (IMAGE lift s)`,
REWRITE_TAC[real_convex_on; convex_on] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[o_THM; LIFT_DROP; DROP_ADD; DROP_CMUL]);;
let REAL_CONVEX_ON_SUBSET = 
prove (`!f s t. f real_convex_on t /\ s SUBSET t ==> f real_convex_on s`,
REWRITE_TAC[REAL_CONVEX_ON] THEN MESON_TAC[CONVEX_ON_SUBSET; IMAGE_SUBSET]);;
let REAL_CONVEX_ADD = 
prove (`!s f g. f real_convex_on s /\ g real_convex_on s ==> (\x. f(x) + g(x)) real_convex_on s`,
REWRITE_TAC[REAL_CONVEX_ON; o_DEF; CONVEX_ADD]);;
let REAL_CONVEX_LMUL = 
prove (`!s c f. &0 <= c /\ f real_convex_on s ==> (\x. c * f(x)) real_convex_on s`,
REPEAT GEN_TAC THEN REWRITE_TAC[REAL_CONVEX_ON; o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP CONVEX_CMUL) THEN REWRITE_TAC[]);;
let REAL_CONVEX_RMUL = 
prove (`!s c f. &0 <= c /\ f real_convex_on s ==> (\x. f(x) * c) real_convex_on s`,
ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REAL_CONVEX_LMUL]);;
let REAL_CONVEX_LOWER = 
prove (`!f s x y. f real_convex_on s /\ x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ u + v = &1 ==> f(u * x + v * y) <= max (f(x)) (f(y))`,
REWRITE_TAC[REAL_CONVEX_ON] THEN REWRITE_TAC[FORALL_DROP; GSYM IN_IMAGE_LIFT_DROP] THEN REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CONVEX_LOWER) THEN REWRITE_TAC[o_THM; DROP_ADD; DROP_CMUL]);;
let REAL_CONVEX_LOCAL_GLOBAL_MINIMUM = 
prove (`!f s t x. f real_convex_on s /\ x IN t /\ real_open t /\ t SUBSET s /\ (!y. y IN t ==> f(x) <= f(y)) ==> !y. y IN s ==> f(x) <= f(y)`,
REWRITE_TAC[REAL_CONVEX_ON; REAL_OPEN] THEN REWRITE_TAC[FORALL_DROP; GSYM IN_IMAGE_LIFT_DROP] THEN REWRITE_TAC[FORALL_IN_IMAGE; LIFT_DROP] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN MP_TAC(ISPECL [`(f:real->real) o drop`; `IMAGE lift s`; `IMAGE lift t`; `x:real^1`] CONVEX_LOCAL_GLOBAL_MINIMUM) THEN ASM_SIMP_TAC[FORALL_IN_IMAGE; LIFT_DROP; o_THM; IMAGE_SUBSET]);;
let REAL_CONVEX_DISTANCE = 
prove (`!s a. (\x. abs(a - x)) real_convex_on s`,
REWRITE_TAC[REAL_CONVEX_ON; o_DEF; FORALL_DROP; GSYM DROP_SUB] THEN REWRITE_TAC[drop; GSYM NORM_REAL; GSYM dist; CONVEX_DISTANCE]);;
let REAL_CONVEX_ON_JENSEN = 
prove (`!f s. is_realinterval s ==> (f real_convex_on s <=> !k u x. (!i:num. 1 <= i /\ i <= k ==> &0 <= u(i) /\ x(i) IN s) /\ (sum (1..k) u = &1) ==> f(sum (1..k) (\i. u(i) * x(i))) <= sum (1..k) (\i. u(i) * f(x(i))))`,
REWRITE_TAC[IS_REALINTERVAL_CONVEX; REAL_CONVEX_ON] THEN SIMP_TAC[CONVEX_ON_JENSEN] THEN REPEAT STRIP_TAC THEN SIMP_TAC[o_DEF; DROP_VSUM; FINITE_NUMSEG] THEN AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN X_GEN_TAC `k:num` THEN REWRITE_TAC[] THEN AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN X_GEN_TAC `u:num->real` THEN REWRITE_TAC[] THEN EQ_TAC THEN DISCH_TAC THENL [X_GEN_TAC `x:num->real` THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `lift o (x:num->real)`) THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP; IN_IMAGE_LIFT_DROP] THEN REWRITE_TAC[DROP_CMUL; LIFT_DROP]; X_GEN_TAC `x:num->real^1` THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `drop o (x:num->real^1)`) THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP; IN_IMAGE_LIFT_DROP] THEN ASM_REWRITE_TAC[DROP_CMUL; LIFT_DROP; GSYM IN_IMAGE_LIFT_DROP]]);;
let REAL_CONVEX_ON_CONTINUOUS = 
prove (`!f s. real_open s /\ f real_convex_on s ==> f real_continuous_on s`,
let REAL_CONVEX_ON_LEFT_SECANT_MUL = 
prove (`!f s. f real_convex_on s <=> !a b x. a IN s /\ b IN s /\ x IN real_segment[a,b] ==> (f x - f a) * abs(b - a) <= (f b - f a) * abs(x - a)`,
REWRITE_TAC[REAL_CONVEX_ON; CONVEX_ON_LEFT_SECANT_MUL] THEN REWRITE_TAC[REAL_SEGMENT_SEGMENT] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[o_DEF; LIFT_DROP] THEN REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB; LIFT_DROP]);;
let REAL_CONVEX_ON_RIGHT_SEQUENT_MUL = 
prove (`!f s. f real_convex_on s <=> !a b x. a IN s /\ b IN s /\ x IN real_segment[a,b] ==> (f b - f a) * abs(b - x) <= (f b - f x) * abs(b - a)`,
REWRITE_TAC[REAL_CONVEX_ON; CONVEX_ON_RIGHT_SECANT_MUL] THEN REWRITE_TAC[REAL_SEGMENT_SEGMENT] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[o_DEF; LIFT_DROP] THEN REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB; LIFT_DROP]);;
let REAL_CONVEX_ON_LEFT_SECANT = 
prove (`!f s. f real_convex_on s <=> !a b x. a IN s /\ b IN s /\ x IN real_segment(a,b) ==> (f x - f a) / abs(x - a) <= (f b - f a) / abs(b - a)`,
REWRITE_TAC[REAL_CONVEX_ON; CONVEX_ON_LEFT_SECANT] THEN REWRITE_TAC[REAL_SEGMENT_SEGMENT] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[o_DEF; LIFT_DROP] THEN REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB; LIFT_DROP]);;
let REAL_CONVEX_ON_RIGHT_SEQUENT = 
prove (`!f s. f real_convex_on s <=> !a b x. a IN s /\ b IN s /\ x IN real_segment(a,b) ==> (f b - f a) / abs(b - a) <= (f b - f x) / abs(b - x)`,
REWRITE_TAC[REAL_CONVEX_ON; CONVEX_ON_RIGHT_SECANT] THEN REWRITE_TAC[REAL_SEGMENT_SEGMENT] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[o_DEF; LIFT_DROP] THEN REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB; LIFT_DROP]);;
let REAL_CONVEX_ON_DERIVATIVE_SECANT_IMP = 
prove (`!f f' s x y. f real_convex_on s /\ real_segment[x,y] SUBSET s /\ (f has_real_derivative f') (atreal x within s) ==> f' * (y - x) <= f y - f x`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; REAL_CONVEX_ON; REAL_SEGMENT_SEGMENT] THEN REWRITE_TAC[SUBSET; IN_IMAGE_LIFT_DROP] THEN REPEAT GEN_TAC THEN REWRITE_TAC[FORALL_DROP] THEN REWRITE_TAC[LIFT_DROP] THEN REWRITE_TAC[GSYM IN_IMAGE_LIFT_DROP; GSYM SUBSET] THEN ONCE_REWRITE_TAC[GSYM(REWRITE_CONV[LIFT_DROP] `\x. lift(drop(f % x))`)] THEN REWRITE_TAC[GSYM o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP CONVEX_ON_DERIVATIVE_SECANT_IMP) THEN REWRITE_TAC[o_THM; DROP_CMUL; DROP_SUB; LIFT_DROP]);;
let REAL_CONVEX_ON_SECANT_DERIVATIVE_IMP = 
prove (`!f f' s x y. f real_convex_on s /\ real_segment[x,y] SUBSET s /\ (f has_real_derivative f') (atreal y within s) ==> f y - f x <= f' * (y - x)`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; REAL_CONVEX_ON; REAL_SEGMENT_SEGMENT] THEN REWRITE_TAC[SUBSET; IN_IMAGE_LIFT_DROP] THEN REPEAT GEN_TAC THEN REWRITE_TAC[FORALL_DROP] THEN REWRITE_TAC[LIFT_DROP] THEN REWRITE_TAC[GSYM IN_IMAGE_LIFT_DROP; GSYM SUBSET] THEN ONCE_REWRITE_TAC[GSYM(REWRITE_CONV[LIFT_DROP] `\x. lift(drop(f % x))`)] THEN REWRITE_TAC[GSYM o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP CONVEX_ON_SECANT_DERIVATIVE_IMP) THEN REWRITE_TAC[o_THM; DROP_CMUL; DROP_SUB; LIFT_DROP]);;
let REAL_CONVEX_ON_DERIVATIVES_IMP = 
prove (`!f f'x f'y s x y. f real_convex_on s /\ real_segment[x,y] SUBSET s /\ (f has_real_derivative f'x) (atreal x within s) /\ (f has_real_derivative f'y) (atreal y within s) ==> f'x * (y - x) <= f'y * (y - x)`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; REAL_CONVEX_ON; REAL_SEGMENT_SEGMENT] THEN REWRITE_TAC[SUBSET; IN_IMAGE_LIFT_DROP] THEN REPEAT GEN_TAC THEN REWRITE_TAC[FORALL_DROP] THEN REWRITE_TAC[LIFT_DROP] THEN REWRITE_TAC[GSYM IN_IMAGE_LIFT_DROP; GSYM SUBSET] THEN ONCE_REWRITE_TAC[GSYM(REWRITE_CONV[LIFT_DROP] `\x. lift(drop(f % x))`)] THEN REWRITE_TAC[GSYM o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP CONVEX_ON_DERIVATIVES_IMP) THEN REWRITE_TAC[o_THM; DROP_CMUL; DROP_SUB; LIFT_DROP]);;
let REAL_CONVEX_ON_DERIVATIVE_INCREASING_IMP = 
prove (`!f f'x f'y s x y. f real_convex_on s /\ real_interval[x,y] SUBSET s /\ (f has_real_derivative f'x) (atreal x within s) /\ (f has_real_derivative f'y) (atreal y within s) /\ x < y ==> f'x <= f'y`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`f:real->real`; `f'x:real`; `f'y:real`; `s:real->bool`; `x:real`; `y:real`] REAL_CONVEX_ON_DERIVATIVES_IMP) THEN ASM_REWRITE_TAC[REAL_SEGMENT_INTERVAL] THEN ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LE_RMUL_EQ; REAL_SUB_LT]);;
let REAL_CONVEX_ON_DERIVATIVE_SECANT = 
prove (`!f f' s. is_realinterval s /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s)) ==> (f real_convex_on s <=> !x y. x IN s /\ y IN s ==> f'(x) * (y - x) <= f y - f x)`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; REAL_CONVEX_ON; IS_REALINTERVAL_CONVEX] THEN REPEAT GEN_TAC THEN REWRITE_TAC[FORALL_DROP; GSYM IN_IMAGE_LIFT_DROP; LIFT_DROP] THEN ONCE_REWRITE_TAC[GSYM(REWRITE_CONV[LIFT_DROP; o_DEF] `lift o (\x. drop(f % x))`)] THEN DISCH_THEN(SUBST1_TAC o MATCH_MP CONVEX_ON_DERIVATIVE_SECANT) THEN REWRITE_TAC[DROP_CMUL; DROP_SUB; o_THM]);;
let REAL_CONVEX_ON_SECANT_DERIVATIVE = 
prove (`!f f' s. is_realinterval s /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s)) ==> (f real_convex_on s <=> !x y. x IN s /\ y IN s ==> f y - f x <= f'(y) * (y - x))`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; REAL_CONVEX_ON; IS_REALINTERVAL_CONVEX] THEN REPEAT GEN_TAC THEN REWRITE_TAC[FORALL_DROP; GSYM IN_IMAGE_LIFT_DROP; LIFT_DROP] THEN ONCE_REWRITE_TAC[GSYM(REWRITE_CONV[LIFT_DROP; o_DEF] `lift o (\x. drop(f % x))`)] THEN DISCH_THEN(SUBST1_TAC o MATCH_MP CONVEX_ON_SECANT_DERIVATIVE) THEN REWRITE_TAC[DROP_CMUL; DROP_SUB; o_THM]);;
let REAL_CONVEX_ON_DERIVATIVES = 
prove (`!f f' s. is_realinterval s /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s)) ==> (f real_convex_on s <=> !x y. x IN s /\ y IN s ==> f'(x) * (y - x) <= f'(y) * (y - x))`,
REWRITE_TAC[HAS_REAL_FRECHET_DERIVATIVE_WITHIN; REAL_CONVEX_ON; IS_REALINTERVAL_CONVEX] THEN REPEAT GEN_TAC THEN REWRITE_TAC[FORALL_DROP; GSYM IN_IMAGE_LIFT_DROP; LIFT_DROP] THEN ONCE_REWRITE_TAC[GSYM(REWRITE_CONV[LIFT_DROP; o_DEF] `lift o (\x. drop(f % x))`)] THEN DISCH_THEN(SUBST1_TAC o MATCH_MP CONVEX_ON_DERIVATIVES) THEN REWRITE_TAC[DROP_CMUL; DROP_SUB; o_THM]);;
let REAL_CONVEX_ON_DERIVATIVE_INCREASING = 
prove (`!f f' s. is_realinterval s /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s)) ==> (f real_convex_on s <=> !x y. x IN s /\ y IN s /\ x <= y ==> f'(x) <= f'(y))`,
REPEAT GEN_TAC THEN DISCH_TAC THEN FIRST_ASSUM(SUBST1_TAC o MATCH_MP REAL_CONVEX_ON_DERIVATIVES) THEN EQ_TAC THEN DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`x:real`; `y:real`] THEN STRIP_TAC THENL [FIRST_X_ASSUM(MP_TAC o SPECL [`x:real`; `y:real`]) THEN ASM_CASES_TAC `x:real = y` THEN ASM_REWRITE_TAC[REAL_LE_REFL] THEN ASM_SIMP_TAC[REAL_LE_RMUL_EQ; REAL_SUB_LT; REAL_LT_LE]; DISJ_CASES_TAC(REAL_ARITH `x <= y \/ y <= x`) THENL [FIRST_X_ASSUM(MP_TAC o SPECL [`x:real`; `y:real`]); FIRST_X_ASSUM(MP_TAC o SPECL [`y:real`; `x:real`])] THEN ASM_CASES_TAC `x:real = y` THEN ASM_REWRITE_TAC[REAL_LE_REFL] THEN ASM_SIMP_TAC[REAL_LE_RMUL_EQ; REAL_SUB_LT; REAL_LT_LE] THEN ONCE_REWRITE_TAC[REAL_ARITH `a * (y - x) <= b * (y - x) <=> b * (x - y) <= a * (x - y)`] THEN ASM_SIMP_TAC[REAL_LE_RMUL_EQ; REAL_SUB_LT; REAL_LT_LE]]);;
let HAS_REAL_DERIVATIVE_INCREASING_IMP = 
prove (`!f f' s a b. is_realinterval s /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s)) /\ (!x. x IN s ==> &0 <= f'(x)) /\ a IN s /\ b IN s /\ a <= b ==> f(a) <= f(b)`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `real_interval[a,b] SUBSET s` ASSUME_TAC THENL [REWRITE_TAC[SUBSET; IN_REAL_INTERVAL] THEN REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [is_realinterval]) THEN MAP_EVERY EXISTS_TAC [`a:real`; `b:real`] THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN MP_TAC(ISPECL [`f:real->real`; `f':real->real`; `a:real`; `b:real`] REAL_MVT_VERY_SIMPLE) THEN ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN X_GEN_TAC `z:real` THEN DISCH_TAC THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_WITHIN_SUBSET THEN EXISTS_TAC `s:real->bool` THEN ASM SET_TAC[]; DISCH_THEN(X_CHOOSE_THEN `z:real` MP_TAC) THEN STRIP_TAC THEN GEN_REWRITE_TAC I [GSYM REAL_SUB_LE] THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_MUL THEN CONJ_TAC THENL [ASM SET_TAC[]; ASM_REAL_ARITH_TAC]]);;
let HAS_REAL_DERIVATIVE_INCREASING = 
prove (`!f f' s. is_realinterval s /\ ~(?a. s = {a}) /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s)) ==> ((!x. x IN s ==> &0 <= f'(x)) <=> (!x y. x IN s /\ y IN s /\ x <= y ==> f(x) <= f(y)))`,
REWRITE_TAC[NOT_EXISTS_THM] THEN REPEAT STRIP_TAC THEN EQ_TAC THENL [ASM_MESON_TAC[HAS_REAL_DERIVATIVE_INCREASING_IMP]; ALL_TAC] THEN DISCH_TAC THEN X_GEN_TAC `x:real` THEN DISCH_TAC THEN MATCH_MP_TAC(ISPEC `atreal x within s` REALLIM_LBOUND) THEN EXISTS_TAC `\y:real. (f y - f x) / (y - x)` THEN ASM_SIMP_TAC[GSYM HAS_REAL_DERIVATIVE_WITHINREAL] THEN ASM_SIMP_TAC[TRIVIAL_LIMIT_WITHIN_REALINTERVAL] THEN REWRITE_TAC[EVENTUALLY_WITHINREAL] THEN EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN X_GEN_TAC `y:real` THEN REWRITE_TAC[REAL_ARITH `&0 < abs(y - x) <=> ~(y = x)`] THEN STRIP_TAC THEN FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH `~(y:real = x) ==> x < y \/ y < x`)) THENL [ALL_TAC; ONCE_REWRITE_TAC[GSYM REAL_NEG_SUB] THEN REWRITE_TAC[real_div; REAL_INV_NEG; REAL_MUL_LNEG; REAL_MUL_RNEG] THEN REWRITE_TAC[REAL_NEG_NEG; GSYM real_div]] THEN MATCH_MP_TAC REAL_LE_DIV THEN ASM_SIMP_TAC[REAL_SUB_LE; REAL_LT_IMP_LE]);;
let REAL_CONVEX_ON_SECOND_DERIVATIVE = 
prove (`!f f' f'' s. is_realinterval s /\ ~(?a. s = {a}) /\ (!x. x IN s ==> (f has_real_derivative f'(x)) (atreal x within s)) /\ (!x. x IN s ==> (f' has_real_derivative f''(x)) (atreal x within s)) ==> (f real_convex_on s <=> !x. x IN s ==> &0 <= f''(x))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `!x y. x IN s /\ y IN s /\ x <= y ==> (f':real->real)(x) <= f'(y)` THEN CONJ_TAC THENL [MATCH_MP_TAC REAL_CONVEX_ON_DERIVATIVE_INCREASING; CONV_TAC SYM_CONV THEN MATCH_MP_TAC HAS_REAL_DERIVATIVE_INCREASING] THEN ASM_REWRITE_TAC[]);;
let REAL_CONVEX_ON_ASYM = 
prove (`!s f. f real_convex_on s <=> !x y u v. x IN s /\ y IN s /\ x < y /\ &0 <= u /\ &0 <= v /\ u + v = &1 ==> f (u * x + v * y) <= u * f x + v * f y`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_convex_on] THEN EQ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_WLOG_LT THEN SIMP_TAC[GSYM REAL_ADD_RDISTRIB; REAL_MUL_LID; REAL_LE_REFL] THEN ASM_MESON_TAC[REAL_ADD_SYM]);;
let REAL_CONVEX_ON_EXP = 
prove (`!s. exp real_convex_on s`,
GEN_TAC THEN MATCH_MP_TAC REAL_CONVEX_ON_SUBSET THEN EXISTS_TAC `(:real)` THEN REWRITE_TAC[SUBSET_UNIV] THEN MP_TAC(ISPECL [`exp`; `exp`; `exp`; `(:real)`] REAL_CONVEX_ON_SECOND_DERIVATIVE) THEN SIMP_TAC[HAS_REAL_DERIVATIVE_EXP; REAL_EXP_POS_LE; HAS_REAL_DERIVATIVE_ATREAL_WITHIN; IS_REALINTERVAL_UNIV] THEN DISCH_THEN MATCH_MP_TAC THEN MATCH_MP_TAC(SET_RULE `&0 IN s /\ &1 IN s /\ ~(&1 = &0) ==> ~(?a. s = {a})`) THEN REWRITE_TAC[IN_UNIV] THEN REAL_ARITH_TAC);;
let REAL_CONVEX_ON_RPOW = 
prove (`!s t. s SUBSET {x | &0 <= x} /\ &1 <= t ==> (\x. x rpow t) real_convex_on s`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONVEX_ON_SUBSET THEN EXISTS_TAC `{x | &0 <= x}` THEN ASM_REWRITE_TAC[] THEN SUBGOAL_THEN `(\x. x rpow t) real_convex_on {x | &0 < x}` MP_TAC THENL [MP_TAC(ISPECL [`\x. x rpow t`; `\x. t * x rpow (t - &1)`; `\x. t * (t - &1) * x rpow (t - &2)`; `{x | &0 < x}`] REAL_CONVEX_ON_SECOND_DERIVATIVE) THEN ASM_REWRITE_TAC[IN_ELIM_THM] THEN ANTS_TAC THENL [REPEAT CONJ_TAC THENL [REWRITE_TAC[is_realinterval; IN_ELIM_THM] THEN REAL_ARITH_TAC; MATCH_MP_TAC(SET_RULE `&1 IN s /\ &2 IN s /\ ~(&1 = &2) ==> ~(?a. s = {a})`) THEN REWRITE_TAC[IN_ELIM_THM] THEN REAL_ARITH_TAC; REPEAT STRIP_TAC THEN REAL_DIFF_TAC THEN ASM_REAL_ARITH_TAC; REPEAT STRIP_TAC THEN REAL_DIFF_TAC THEN ASM_REWRITE_TAC[REAL_ARITH `t - &1 - &1 = t - &2`] THEN ASM_REAL_ARITH_TAC]; DISCH_THEN SUBST1_TAC THEN REPEAT STRIP_TAC THEN REPEAT(MATCH_MP_TAC REAL_LE_MUL THEN CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN MATCH_MP_TAC RPOW_POS_LE THEN ASM_SIMP_TAC[REAL_LT_IMP_LE]]; REWRITE_TAC[REAL_CONVEX_ON_ASYM] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `x:real` THEN REWRITE_TAC[IN_ELIM_THM] THEN ASM_CASES_TAC `x = &0` THENL [DISCH_THEN(K ALL_TAC) THEN ASM_REWRITE_TAC[REAL_MUL_RZERO] THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC[RPOW_ZERO; REAL_ARITH `&1 <= t ==> ~(t = &0)`] THEN REWRITE_TAC[REAL_MUL_RZERO; REAL_ADD_LID] THEN ASM_CASES_TAC `v = &0` THEN ASM_SIMP_TAC[RPOW_ZERO; REAL_ARITH `&1 <= t ==> ~(t = &0)`; REAL_MUL_LZERO; REAL_LE_REFL] THEN ASM_SIMP_TAC[RPOW_MUL; REAL_LT_LE] THEN MATCH_MP_TAC REAL_LE_RMUL THEN ASM_SIMP_TAC[RPOW_POS_LE; REAL_LT_IMP_LE] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `exp(&1 * log v)` THEN CONJ_TAC THENL [ASM_SIMP_TAC[rpow; REAL_LT_LE; REAL_EXP_MONO_LE] THEN ONCE_REWRITE_TAC[REAL_ARITH `a * l <= b * l <=> --l * b <= --l * a`] THEN MATCH_MP_TAC REAL_LE_LMUL THEN ASM_REWRITE_TAC[] THEN ASM_SIMP_TAC[GSYM LOG_INV; REAL_LT_LE] THEN MATCH_MP_TAC LOG_POS THEN MATCH_MP_TAC REAL_INV_1_LE THEN ASM_REAL_ARITH_TAC; ASM_SIMP_TAC[REAL_MUL_LID; EXP_LOG; REAL_LT_LE; REAL_LE_REFL]]; ASM_MESON_TAC[REAL_LT_LE; REAL_LET_TRANS]]]);;
(* ------------------------------------------------------------------------- *) (* A couple of simple bounds that it's convenient to get this way. *) (* ------------------------------------------------------------------------- *)
let REAL_LE_X_SINH = 
prove (`!x. &0 <= x ==> x <= (exp x - inv(exp x)) / &2`,
SUBGOAL_THEN `!a b. a <= b ==> exp a - inv(exp a) - &2 * a <= exp b - inv(exp b) - &2 * b` (MP_TAC o SPEC `&0`) THENL [MP_TAC(ISPECL [`\x. exp x - exp(--x) - &2 * x`; `\x. exp x + exp(--x) - &2`; `(:real)`] HAS_REAL_DERIVATIVE_INCREASING) THEN REWRITE_TAC[IN_ELIM_THM; IS_REALINTERVAL_UNIV; IN_UNIV] THEN ANTS_TAC THENL [CONJ_TAC THENL [SET_TAC[REAL_ARITH `~(&1 = &0)`]; ALL_TAC] THEN GEN_TAC THEN REAL_DIFF_TAC THEN REAL_ARITH_TAC; SIMP_TAC[REAL_EXP_NEG] THEN DISCH_THEN(fun th -> SIMP_TAC[GSYM th]) THEN X_GEN_TAC `x:real` THEN SIMP_TAC[REAL_EXP_NZ; REAL_FIELD `~(e = &0) ==> e + inv e - &2 = (e - &1) pow 2 / e`] THEN SIMP_TAC[REAL_EXP_POS_LE; REAL_LE_DIV; REAL_LE_POW_2]]; MATCH_MP_TAC MONO_FORALL THEN REWRITE_TAC[REAL_EXP_0] THEN REAL_ARITH_TAC]);;
let REAL_LE_ABS_SINH = 
prove (`!x. abs x <= abs((exp x - inv(exp x)) / &2)`,
GEN_TAC THEN ASM_CASES_TAC `&0 <= x` THENL [MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ x <= y ==> abs x <= abs y`) THEN ASM_SIMP_TAC[REAL_LE_X_SINH]; MATCH_MP_TAC(REAL_ARITH `~(&0 <= x) /\ --x <= --y ==> abs x <= abs y`) THEN ASM_REWRITE_TAC[REAL_ARITH `--((a - b) / &2) = (b - a) / &2`] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `(exp(--x) - inv(exp(--x))) / &2` THEN ASM_SIMP_TAC[REAL_LE_X_SINH; REAL_ARITH `~(&0 <= x) ==> &0 <= --x`] THEN REWRITE_TAC[REAL_EXP_NEG; REAL_INV_INV] THEN REAL_ARITH_TAC]);;
(* ------------------------------------------------------------------------- *) (* Integrals of real->real functions; measures of real sets. *) (* ------------------------------------------------------------------------- *) parse_as_infix("has_real_integral",(12,"right"));; parse_as_infix("real_integrable_on",(12,"right"));; parse_as_infix("absolutely_real_integrable_on",(12,"right"));; parse_as_infix("has_real_measure",(12,"right"));;
let has_real_integral = new_definition
 `(f has_real_integral y) s <=>
        ((lift o f o drop) has_integral (lift y)) (IMAGE lift s)`;;
let real_integrable_on = new_definition
 `f real_integrable_on i <=> ?y. (f has_real_integral y) i`;;
let real_integral = new_definition
 `real_integral i f = @y. (f has_real_integral y) i`;;
let real_negligible = new_definition
 `real_negligible s <=> negligible (IMAGE lift s)`;;
let absolutely_real_integrable_on = new_definition
 `f absolutely_real_integrable_on s <=>
        f real_integrable_on s /\ (\x. abs(f x)) real_integrable_on s`;;
let has_real_measure = new_definition
 `s has_real_measure m <=> ((\x. &1) has_real_integral m) s`;;
let real_measurable = new_definition
 `real_measurable s <=> ?m. s has_real_measure m`;;
let real_measure = new_definition
 `real_measure s = @m. s has_real_measure m`;;
let HAS_REAL_INTEGRAL = 
prove (`(f has_real_integral y) (real_interval[a,b]) <=> ((lift o f o drop) has_integral (lift y)) (interval[lift a,lift b])`,
let REAL_INTEGRABLE_INTEGRAL = 
prove (`!f i. f real_integrable_on i ==> (f has_real_integral (real_integral i f)) i`,
REPEAT GEN_TAC THEN REWRITE_TAC[real_integrable_on; real_integral] THEN CONV_TAC(RAND_CONV SELECT_CONV) THEN REWRITE_TAC[]);;
let HAS_REAL_INTEGRAL_INTEGRABLE = 
prove (`!f i s. (f has_real_integral i) s ==> f real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[]);;
let HAS_REAL_INTEGRAL_INTEGRAL = 
prove (`!f s. f real_integrable_on s <=> (f has_real_integral (real_integral s f)) s`,
let HAS_REAL_INTEGRAL_UNIQUE = 
prove (`!f i k1 k2. (f has_real_integral k1) i /\ (f has_real_integral k2) i ==> k1 = k2`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_integral] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_INTEGRAL_UNIQUE) THEN REWRITE_TAC[LIFT_EQ]);;
let REAL_INTEGRAL_UNIQUE = 
prove (`!f y k. (f has_real_integral y) k ==> real_integral k f = y`,
REPEAT STRIP_TAC THEN REWRITE_TAC[real_integral] THEN MATCH_MP_TAC SELECT_UNIQUE THEN ASM_MESON_TAC[HAS_REAL_INTEGRAL_UNIQUE]);;
let HAS_REAL_INTEGRAL_INTEGRABLE_INTEGRAL = 
prove (`!f i s. (f has_real_integral i) s <=> f real_integrable_on s /\ real_integral s f = i`,
let REAL_INTEGRAL_EQ_HAS_INTEGRAL = 
prove (`!s f y. f real_integrable_on s ==> (real_integral s f = y <=> (f has_real_integral y) s)`,
let REAL_INTEGRABLE_ON = 
prove (`f real_integrable_on s <=> (lift o f o drop) integrable_on (IMAGE lift s)`,
let ABSOLUTELY_REAL_INTEGRABLE_ON = 
prove (`f absolutely_real_integrable_on s <=> (lift o f o drop) absolutely_integrable_on (IMAGE lift s)`,
let REAL_INTEGRAL = 
prove (`f real_integrable_on s ==> real_integral s f = drop(integral (IMAGE lift s) (lift o f o drop))`,
REWRITE_TAC[REAL_INTEGRABLE_ON] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN REWRITE_TAC[has_real_integral; LIFT_DROP] THEN ASM_REWRITE_TAC[GSYM HAS_INTEGRAL_INTEGRAL]);;
let HAS_REAL_INTEGRAL_IS_0 = 
prove (`!f s. (!x. x IN s ==> f(x) = &0) ==> (f has_real_integral &0) s`,
REPEAT STRIP_TAC THEN REWRITE_TAC[has_real_integral; LIFT_NUM] THEN MATCH_MP_TAC HAS_INTEGRAL_IS_0 THEN ASM_REWRITE_TAC[LIFT_EQ; FORALL_IN_IMAGE; o_THM; LIFT_DROP; GSYM LIFT_NUM]);;
let HAS_REAL_INTEGRAL_0 = 
prove (`!s. ((\x. &0) has_real_integral &0) s`,
let HAS_REAL_INTEGRAL_0_EQ = 
prove (`!i s. ((\x. &0) has_real_integral i) s <=> i = &0`,
let HAS_REAL_INTEGRAL_LINEAR = 
prove (`!f:real->real y s h:real->real. (f has_real_integral y) s /\ linear(lift o h o drop) ==> ((h o f) has_real_integral h(y)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_integral] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_INTEGRAL_LINEAR) THEN REWRITE_TAC[o_DEF; LIFT_DROP]);;
let HAS_REAL_INTEGRAL_LMUL = 
prove (`!(f:real->real) k s c. (f has_real_integral k) s ==> ((\x. c * f(x)) has_real_integral (c * k)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_integral] THEN DISCH_THEN(MP_TAC o SPEC `c:real` o MATCH_MP HAS_INTEGRAL_CMUL) THEN REWRITE_TAC[GSYM LIFT_CMUL; o_DEF]);;
let HAS_REAL_INTEGRAL_RMUL = 
prove (`!(f:real->real) k s c. (f has_real_integral k) s ==> ((\x. f(x) * c) has_real_integral (k * c)) s`,
ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[HAS_REAL_INTEGRAL_LMUL]);;
let HAS_REAL_INTEGRAL_NEG = 
prove (`!f k s. (f has_real_integral k) s ==> ((\x. --(f x)) has_real_integral (--k)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_integral] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_INTEGRAL_NEG) THEN REWRITE_TAC[o_DEF; LIFT_NEG]);;
let HAS_REAL_INTEGRAL_ADD = 
prove (`!f:real->real g k l s. (f has_real_integral k) s /\ (g has_real_integral l) s ==> ((\x. f(x) + g(x)) has_real_integral (k + l)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_integral] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_INTEGRAL_ADD) THEN REWRITE_TAC[o_DEF; LIFT_ADD]);;
let HAS_REAL_INTEGRAL_SUB = 
prove (`!f:real->real g k l s. (f has_real_integral k) s /\ (g has_real_integral l) s ==> ((\x. f(x) - g(x)) has_real_integral (k - l)) s`,
REPEAT GEN_TAC THEN REWRITE_TAC[has_real_integral] THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_INTEGRAL_SUB) THEN REWRITE_TAC[o_DEF; LIFT_SUB]);;
let REAL_INTEGRAL_0 = 
prove (`!s. real_integral s (\x. &0) = &0`,
let REAL_INTEGRAL_ADD = 
prove (`!f:real->real g s. f real_integrable_on s /\ g real_integrable_on s ==> real_integral s (\x. f x + g x) = real_integral s f + real_integral s g`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_ADD THEN ASM_SIMP_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let REAL_INTEGRAL_LMUL = 
prove (`!f:real->real c s. f real_integrable_on s ==> real_integral s (\x. c * f(x)) = c * real_integral s f`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_LMUL THEN ASM_SIMP_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let REAL_INTEGRAL_RMUL = 
prove (`!f:real->real c s. f real_integrable_on s ==> real_integral s (\x. f(x) * c) = real_integral s f * c`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_RMUL THEN ASM_SIMP_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let REAL_INTEGRAL_NEG = 
prove (`!f:real->real s. f real_integrable_on s ==> real_integral s (\x. --f(x)) = --real_integral s f`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_NEG THEN ASM_SIMP_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let REAL_INTEGRAL_SUB = 
prove (`!f:real->real g s. f real_integrable_on s /\ g real_integrable_on s ==> real_integral s (\x. f x - g x) = real_integral s f - real_integral s g`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_SUB THEN ASM_SIMP_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let REAL_INTEGRABLE_0 = 
prove (`!s. (\x. &0) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_0]);;
let REAL_INTEGRABLE_ADD = 
prove (`!f:real->real g s. f real_integrable_on s /\ g real_integrable_on s ==> (\x. f x + g x) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_ADD]);;
let REAL_INTEGRABLE_LMUL = 
prove (`!f:real->real c s. f real_integrable_on s ==> (\x. c * f(x)) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_LMUL]);;
let REAL_INTEGRABLE_RMUL = 
prove (`!f:real->real c s. f real_integrable_on s ==> (\x. f(x) * c) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_RMUL]);;
let REAL_INTEGRABLE_NEG = 
prove (`!f:real->real s. f real_integrable_on s ==> (\x. --f(x)) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_NEG]);;
let REAL_INTEGRABLE_SUB = 
prove (`!f:real->real g s. f real_integrable_on s /\ g real_integrable_on s ==> (\x. f x - g x) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_SUB]);;
let REAL_INTEGRABLE_LINEAR = 
prove (`!f h s. f real_integrable_on s /\ linear(lift o h o drop) ==> (h o f) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_LINEAR]);;
let REAL_INTEGRAL_LINEAR = 
prove (`!f:real->real s h:real->real. f real_integrable_on s /\ linear(lift o h o drop) ==> real_integral s (h o f) = h(real_integral s f)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_UNIQUE THEN MAP_EVERY EXISTS_TAC [`(h:real->real) o (f:real->real)`; `s:real->bool`] THEN CONJ_TAC THENL [ALL_TAC; MATCH_MP_TAC HAS_REAL_INTEGRAL_LINEAR] THEN ASM_SIMP_TAC[GSYM HAS_REAL_INTEGRAL_INTEGRAL; REAL_INTEGRABLE_LINEAR]);;
let HAS_REAL_INTEGRAL_SUM = 
prove (`!f:A->real->real s t. FINITE t /\ (!a. a IN t ==> ((f a) has_real_integral (i a)) s) ==> ((\x. sum t (\a. f a x)) has_real_integral (sum t i)) s`,
GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[SUM_CLAUSES; HAS_REAL_INTEGRAL_0; IN_INSERT] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_ADD THEN ASM_REWRITE_TAC[ETA_AX] THEN CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[]);;
let REAL_INTEGRAL_SUM = 
prove (`!f:A->real->real s t. FINITE t /\ (!a. a IN t ==> (f a) real_integrable_on s) ==> real_integral s (\x. sum t (\a. f a x)) = sum t (\a. real_integral s (f a))`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_SUM THEN ASM_SIMP_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let REAL_INTEGRABLE_SUM = 
prove (`!f:A->real->real s t. FINITE t /\ (!a. a IN t ==> (f a) real_integrable_on s) ==> (\x. sum t (\a. f a x)) real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_SUM]);;
let HAS_REAL_INTEGRAL_EQ = 
prove (`!f:real->real g k s. (!x. x IN s ==> (f(x) = g(x))) /\ (f has_real_integral k) s ==> (g has_real_integral k) s`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o MATCH_MP HAS_REAL_INTEGRAL_IS_0) MP_TAC) THEN REWRITE_TAC[IMP_IMP] THEN DISCH_THEN (MP_TAC o MATCH_MP HAS_REAL_INTEGRAL_SUB) THEN SIMP_TAC[REAL_ARITH `x - (x - y:real) = y`; ETA_AX; REAL_SUB_RZERO]);;
let REAL_INTEGRABLE_EQ = 
prove (`!f:real->real g s. (!x. x IN s ==> (f(x) = g(x))) /\ f real_integrable_on s ==> g real_integrable_on s`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_EQ]);;
let HAS_REAL_INTEGRAL_EQ_EQ = 
prove (`!f:real->real g k s. (!x. x IN s ==> (f(x) = g(x))) ==> ((f has_real_integral k) s <=> (g has_real_integral k) s)`,
MESON_TAC[HAS_REAL_INTEGRAL_EQ]);;
let HAS_REAL_INTEGRAL_NULL = 
prove (`!f:real->real a b. b <= a ==> (f has_real_integral &0) (real_interval[a,b])`,
REPEAT STRIP_TAC THEN REWRITE_TAC[has_real_integral; REAL_INTERVAL_INTERVAL] THEN REWRITE_TAC[GSYM IMAGE_o; o_DEF; LIFT_DROP; LIFT_NUM] THEN REWRITE_TAC[SET_RULE `IMAGE (\x. x) s = s`] THEN MATCH_MP_TAC HAS_INTEGRAL_NULL THEN ASM_REWRITE_TAC[CONTENT_EQ_0_1; LIFT_DROP]);;
let HAS_REAL_INTEGRAL_NULL_EQ = 
prove (`!f a b i. b <= a ==> ((f has_real_integral i) (real_interval[a,b]) <=> i = &0)`,
let REAL_INTEGRAL_NULL = 
prove (`!f a b. b <= a ==> real_integral(real_interval[a,b]) f = &0`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN ASM_MESON_TAC[HAS_REAL_INTEGRAL_NULL]);;
let REAL_INTEGRABLE_ON_NULL = 
prove (`!f a b. b <= a ==> f real_integrable_on real_interval[a,b]`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_NULL]);;
let HAS_REAL_INTEGRAL_EMPTY = 
prove (`!f. (f has_real_integral &0) {}`,
GEN_TAC THEN REWRITE_TAC[EMPTY_AS_REAL_INTERVAL] THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_NULL THEN REWRITE_TAC[REAL_POS]);;
let HAS_REAL_INTEGRAL_EMPTY_EQ = 
prove (`!f i. (f has_real_integral i) {} <=> i = &0`,
let REAL_INTEGRABLE_ON_EMPTY = 
prove (`!f. f real_integrable_on {}`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_EMPTY]);;
let REAL_INTEGRAL_EMPTY = 
prove (`!f. real_integral {} f = &0`,
let HAS_REAL_INTEGRAL_REFL = 
prove (`!f a. (f has_real_integral &0) (real_interval[a,a])`,
REPEAT GEN_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_NULL THEN REWRITE_TAC[REAL_LE_REFL]);;
let REAL_INTEGRABLE_ON_REFL = 
prove (`!f a. f real_integrable_on real_interval[a,a]`,
REWRITE_TAC[real_integrable_on] THEN MESON_TAC[HAS_REAL_INTEGRAL_REFL]);;
let REAL_INTEGRAL_REFL = 
prove (`!f a. real_integral (real_interval[a,a]) f = &0`,
let HAS_REAL_INTEGRAL_CONST = 
prove (`!a b c. a <= b ==> ((\x. c) has_real_integral (c * (b - a))) (real_interval[a,b])`,
REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[has_real_integral; IMAGE_LIFT_REAL_INTERVAL] THEN MP_TAC(ISPECL [`lift a`; `lift b`; `lift c`] HAS_INTEGRAL_CONST) THEN ASM_SIMP_TAC[o_DEF; CONTENT_1; LIFT_DROP; LIFT_CMUL]);;
let REAL_INTEGRABLE_CONST = 
prove (`!a b c. (\x. c) real_integrable_on real_interval[a,b]`,
let REAL_INTEGRAL_CONST = 
prove (`!a b c. a <= b ==> real_integral (real_interval [a,b]) (\x. c) = c * (b - a)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INTEGRAL_UNIQUE THEN ASM_SIMP_TAC[HAS_REAL_INTEGRAL_CONST]);;
let HAS_REAL_INTEGRAL_BOUND = 
prove (`!f:real->real a b i B. &0 <= B /\ a <= b /\ (f has_real_integral i) (real_interval[a,b]) /\ (!x. x IN real_interval[a,b] ==> abs(f x) <= B) ==> abs i <= B * (b - a)`,
REWRITE_TAC[HAS_REAL_INTEGRAL; REAL_INTERVAL_INTERVAL; GSYM NORM_LIFT] THEN REWRITE_TAC[FORALL_IN_IMAGE; LIFT_DROP] THEN REPEAT STRIP_TAC THEN GEN_REWRITE_TAC (RAND_CONV o RAND_CONV o BINOP_CONV) [GSYM LIFT_DROP] THEN ASM_SIMP_TAC[GSYM CONTENT_1; LIFT_DROP] THEN MATCH_MP_TAC HAS_INTEGRAL_BOUND THEN EXISTS_TAC `lift o f o drop` THEN ASM_REWRITE_TAC[o_THM]);;
let HAS_REAL_INTEGRAL_LE = 
prove (`!f g s i j. (f has_real_integral i) s /\ (g has_real_integral j) s /\ (!x. x IN s ==> f x <= g x) ==> i <= j`,
REWRITE_TAC[has_real_integral] THEN REPEAT STRIP_TAC THEN GEN_REWRITE_TAC BINOP_CONV [GSYM LIFT_DROP] THEN REWRITE_TAC[drop] THEN MATCH_MP_TAC (ISPECL [`lift o f o drop`; `lift o g o drop`; `IMAGE lift s`] HAS_INTEGRAL_COMPONENT_LE) THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE; DIMINDEX_1; LE_REFL; o_THM; LIFT_DROP; GSYM drop]);;
let REAL_INTEGRAL_LE = 
prove (`!f:real->real g:real->real s. f real_integrable_on s /\ g real_integrable_on s /\ (!x. x IN s ==> f x <= g x) ==> real_integral s f <= real_integral s g`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_LE THEN ASM_MESON_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let HAS_REAL_INTEGRAL_POS = 
prove (`!f:real->real s i. (f has_real_integral i) s /\ (!x. x IN s ==> &0 <= f x) ==> &0 <= i`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`(\x. &0):real->real`; `f:real->real`; `s:real->bool`; `&0:real`; `i:real`] HAS_REAL_INTEGRAL_LE) THEN ASM_SIMP_TAC[HAS_REAL_INTEGRAL_0]);;
let REAL_INTEGRAL_POS = 
prove (`!f:real->real s. f real_integrable_on s /\ (!x. x IN s ==> &0 <= f x) ==> &0 <= real_integral s f`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_POS THEN ASM_MESON_TAC[REAL_INTEGRABLE_INTEGRAL]);;
let HAS_REAL_INTEGRAL_ISNEG = 
prove (`!f:real->real s i. (f has_real_integral i) s /\ (!x. x IN s ==> f x <= &0) ==> i <= &0`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`f:real->real`; `(\x. &0):real->real`; `s:real->bool`; `i:real`; `&0:real`; ] HAS_REAL_INTEGRAL_LE) THEN ASM_SIMP_TAC[HAS_REAL_INTEGRAL_0]);;
let HAS_REAL_INTEGRAL_LBOUND = 
prove (`!f:real->real a b i. a <= b /\ (f has_real_integral i) (real_interval[a,b]) /\ (!x. x IN real_interval[a,b] ==> B <= f(x)) ==> B * (b - a) <= i`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`(\x. B):real->real`; `f:real->real`; `real_interval[a,b]`; `B * (b - a):real`; `i:real`] HAS_REAL_INTEGRAL_LE) THEN ASM_SIMP_TAC[HAS_REAL_INTEGRAL_CONST]);;
let HAS_REAL_INTEGRAL_UBOUND = 
prove (`!f:real->real a b i. a <= b /\ (f has_real_integral i) (real_interval[a,b]) /\ (!x. x IN real_interval[a,b] ==> f(x) <= B) ==> i <= B * (b - a)`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`f:real->real`; `(\x. B):real->real`; `real_interval[a,b]`; `i:real`; `B * (b - a):real`] HAS_REAL_INTEGRAL_LE) THEN ASM_SIMP_TAC[HAS_REAL_INTEGRAL_CONST]);;
let REAL_INTEGRAL_LBOUND = 
prove (`!f:real->real a b. a <= b /\ f real_integrable_on real_interval[a,b] /\ (!x. x IN real_interval[a,b] ==> B <= f(x)) ==> B * (b - a) <= real_integral(real_interval[a,b]) f`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_LBOUND THEN EXISTS_TAC `f:real->real` THEN ASM_REWRITE_TAC[GSYM HAS_REAL_INTEGRAL_INTEGRAL]);;
let REAL_INTEGRAL_UBOUND = 
prove (`!f:real->real a b. a <= b /\ f real_integrable_on real_interval[a,b] /\ (!x. x IN real_interval[a,b] ==> f(x) <= B) ==> real_integral(real_interval[a,b]) f <= B * (b - a)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_UBOUND THEN EXISTS_TAC `f:real->real` THEN ASM_REWRITE_TAC[GSYM HAS_REAL_INTEGRAL_INTEGRAL]);;
let REAL_INTEGRABLE_UNIFORM_LIMIT = 
prove (`!f a b. (!e. &0 < e ==> ?g. (!x. x IN real_interval[a,b] ==> abs(f x - g x) <= e) /\ g real_integrable_on real_interval[a,b] ) ==> f real_integrable_on real_interval[a,b]`,
REWRITE_TAC[real_integrable_on; HAS_REAL_INTEGRAL; GSYM EXISTS_LIFT] THEN REWRITE_TAC[GSYM integrable_on] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC INTEGRABLE_UNIFORM_LIMIT 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 `g:real->real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `lift o g o drop` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM IMAGE_LIFT_REAL_INTERVAL; FORALL_IN_IMAGE] THEN ASM_SIMP_TAC[o_THM; LIFT_DROP; GSYM LIFT_SUB; NORM_LIFT]);;
let HAS_REAL_INTEGRAL_NEGLIGIBLE = 
prove (`!f s t. real_negligible s /\ (!x. x IN (t DIFF s) ==> f x = &0) ==> (f has_real_integral (&0)) t`,
REWRITE_TAC[has_real_integral; real_negligible; LIFT_NUM] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_INTEGRAL_NEGLIGIBLE THEN EXISTS_TAC `IMAGE lift s` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[o_THM; IN_DIFF; IMP_CONJ; FORALL_IN_IMAGE] THEN REWRITE_TAC[LIFT_IN_IMAGE_LIFT; LIFT_DROP] THEN ASM SET_TAC[LIFT_NUM]);;
let HAS_REAL_INTEGRAL_SPIKE = 
prove (`!f g s t y. real_negligible s /\ (!x. x IN (t DIFF s) ==> g x = f x) /\ (f has_real_integral y) t ==> (g has_real_integral y) t`,
REWRITE_TAC[has_real_integral; real_negligible] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_INTEGRAL_SPIKE THEN MAP_EVERY EXISTS_TAC [`lift o f o drop`; `IMAGE lift s`] THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[o_THM; IN_DIFF; IMP_CONJ; FORALL_IN_IMAGE] THEN REWRITE_TAC[LIFT_IN_IMAGE_LIFT; LIFT_DROP] THEN ASM SET_TAC[LIFT_NUM]);;
let HAS_REAL_INTEGRAL_SPIKE_EQ = 
prove (`!f g s t y. real_negligible s /\ (!x. x IN (t DIFF s) ==> g x = f x) ==> ((f has_real_integral y) t <=> (g has_real_integral y) t)`,
REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_SPIKE THENL [EXISTS_TAC `f:real->real`; EXISTS_TAC `g:real->real`] THEN EXISTS_TAC `s:real->bool` THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[REAL_ABS_SUB]);;
let REAL_INTEGRABLE_SPIKE = 
prove (`!f g s t. real_negligible s /\ (!x. x IN (t DIFF s) ==> g x = f x) ==> f real_integrable_on t ==> g real_integrable_on t`,
REPEAT GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[real_integrable_on] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MP_TAC(SPEC_ALL HAS_REAL_INTEGRAL_SPIKE) THEN ASM_REWRITE_TAC[]);;
let REAL_INTEGRAL_SPIKE = 
prove (`!f:real->real g s t. real_negligible s /\ (!x. x IN (t DIFF s) ==> g x = f x) ==> real_integral t f = real_integral t g`,
REPEAT STRIP_TAC THEN REWRITE_TAC[real_integral] THEN AP_TERM_TAC THEN ABS_TAC THEN MATCH_MP_TAC HAS_REAL_INTEGRAL_SPIKE_EQ THEN ASM_MESON_TAC[]);;
let REAL_NEGLIGIBLE_SUBSET = 
prove (`!s:real->bool t:real->bool. real_negligible s /\ t SUBSET s ==> real_negligible t`,
REWRITE_TAC[real_negligible] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC NEGLIGIBLE_SUBSET THEN EXISTS_TAC `IMAGE lift s` THEN ASM_SIMP_TAC[IMAGE_SUBSET]);;
let REAL_NEGLIGIBLE_DIFF = 
prove (`!s t:real->bool. real_negligible s ==> real_negligible(s DIFF t)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_NEGLIGIBLE_SUBSET THEN EXISTS_TAC `s:real->bool` THEN ASM_REWRITE_TAC[SUBSET_DIFF]);;
let REAL_NEGLIGIBLE_INTER = 
prove (`!s t. real_negligible s \/ real_negligible t ==> real_negligible(s INTER t)`,
let REAL_NEGLIGIBLE_UNION = 
prove (`!s t:real->bool. real_negligible s /\ real_negligible t ==> real_negligible (s UNION t)`,
let REAL_NEGLIGIBLE_UNION_EQ = 
prove (`!s t:real->bool. real_negligible (s UNION t) <=> real_negligible s /\ real_negligible t`,
let REAL_NEGLIGIBLE_SING = 
prove (`!a:real. real_negligible {a}`,
let REAL_NEGLIGIBLE_INSERT = 
prove (`!a:real s. real_negligible(a INSERT s) <=> real_negligible s`,
let REAL_NEGLIGIBLE_EMPTY = 
prove (`real_negligible {}`,
let REAL_NEGLIGIBLE_FINITE = 
prove (`!s. FINITE s ==> real_negligible s`,