Update from HH master
authorCezary Kaliszyk <cek@colo12-c703.uibk.ac.at>
Fri, 30 Aug 2013 09:32:28 +0000 (11:32 +0200)
committerCezary Kaliszyk <cek@colo12-c703.uibk.ac.at>
Fri, 30 Aug 2013 09:32:28 +0000 (11:32 +0200)
27 files changed:
Multivariate/canal.ml [new file with mode: 0644]
Multivariate/cauchy.ml [new file with mode: 0644]
Multivariate/clifford.ml [new file with mode: 0644]
Multivariate/complex_database.ml [new file with mode: 0644]
Multivariate/complexes.ml [new file with mode: 0644]
Multivariate/convex.ml [new file with mode: 0644]
Multivariate/cross.ml [new file with mode: 0644]
Multivariate/derivatives.ml [new file with mode: 0644]
Multivariate/determinants.ml [new file with mode: 0644]
Multivariate/dimension.ml [new file with mode: 0644]
Multivariate/flyspeck.ml [new file with mode: 0644]
Multivariate/geom.ml [new file with mode: 0644]
Multivariate/integration.ml [new file with mode: 0644]
Multivariate/make_complex.ml [new file with mode: 0644]
Multivariate/measure.ml [new file with mode: 0644]
Multivariate/misc.ml [new file with mode: 0644]
Multivariate/multivariate_database.ml [new file with mode: 0644]
Multivariate/paths.ml [new file with mode: 0644]
Multivariate/polytope.ml [new file with mode: 0644]
Multivariate/realanalysis.ml [new file with mode: 0644]
Multivariate/tarski.ml [new file with mode: 0644]
Multivariate/topology.ml [new file with mode: 0644]
Multivariate/transcendentals.ml [new file with mode: 0644]
Multivariate/vectors.ml [new file with mode: 0644]
Multivariate/wlog.ml [new file with mode: 0644]
Multivariate/wlog_examples.ml [new file with mode: 0644]
make.ml [new file with mode: 0644]

diff --git a/Multivariate/canal.ml b/Multivariate/canal.ml
new file mode 100644 (file)
index 0000000..f09184f
--- /dev/null
@@ -0,0 +1,3207 @@
+(* ========================================================================= *)
+(* Complex analysis.                                                         *)
+(*                                                                           *)
+(*              (c) Copyright, John Harrison 1998-2008                       *)
+(* (c) Copyright, Marco Maggesi, Graziano Gentili and Gianni Ciolli, 2008.   *)
+(*              (c) Copyright, Valentina Bruno 2010                          *)
+(* ========================================================================= *)
+
+needs "Library/floor.ml";;
+needs "Library/iter.ml";;
+needs "Multivariate/complexes.ml";;
+
+prioritize_complex();;
+
+(* ------------------------------------------------------------------------- *)
+(* Some toplogical facts formulated for the complex numbers.                 *)
+(* ------------------------------------------------------------------------- *)
+
+let CLOSED_HALFSPACE_RE_GE = prove
+ (`!b. closed {z | Re(z) >= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`Cx(&1)`; `b:real`] CLOSED_HALFSPACE_GE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[RE_CX; IM_CX; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CLOSED_HALFSPACE_RE_LE = prove
+ (`!b. closed {z | Re(z) <= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`Cx(&1)`; `b:real`] CLOSED_HALFSPACE_LE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[RE_CX; IM_CX; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CLOSED_HALFSPACE_RE_EQ = prove
+ (`!b. closed {z | Re(z) = b}`,
+  GEN_TAC THEN REWRITE_TAC[REAL_ARITH `x = y <=> x >= y /\ x <= y`] THEN
+  REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
+  SIMP_TAC[CLOSED_INTER; CLOSED_HALFSPACE_RE_GE; CLOSED_HALFSPACE_RE_LE]);;
+
+let OPEN_HALFSPACE_RE_GT = prove
+ (`!b. open {z | Re(z) > b}`,
+  REWRITE_TAC[OPEN_CLOSED; CLOSED_HALFSPACE_RE_LE;
+              REAL_ARITH `x > y <=> ~(x <= y)`;
+              SET_RULE `UNIV DIFF {x | ~p x} = {x | p x}`]);;
+
+let OPEN_HALFSPACE_RE_LT = prove
+ (`!b. open {z | Re(z) < b}`,
+  REWRITE_TAC[OPEN_CLOSED; CLOSED_HALFSPACE_RE_GE;
+              REAL_ARITH `x < y <=> ~(x >= y)`;
+              SET_RULE `UNIV DIFF {x | ~p x} = {x | p x}`]);;
+
+let CLOSED_HALFSPACE_IM_GE = prove
+ (`!b. closed {z | Im(z) >= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`ii`; `b:real`] CLOSED_HALFSPACE_GE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CLOSED_HALFSPACE_IM_LE = prove
+ (`!b. closed {z | Im(z) <= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`ii`; `b:real`] CLOSED_HALFSPACE_LE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CLOSED_HALFSPACE_IM_EQ = prove
+ (`!b. closed {z | Im(z) = b}`,
+  GEN_TAC THEN REWRITE_TAC[REAL_ARITH `x = y <=> x >= y /\ x <= y`] THEN
+  REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
+  SIMP_TAC[CLOSED_INTER; CLOSED_HALFSPACE_IM_GE; CLOSED_HALFSPACE_IM_LE]);;
+
+let OPEN_HALFSPACE_IM_GT = prove
+ (`!b. open {z | Im(z) > b}`,
+  REWRITE_TAC[OPEN_CLOSED; CLOSED_HALFSPACE_IM_LE;
+              REAL_ARITH `x > y <=> ~(x <= y)`;
+              SET_RULE `UNIV DIFF {x | ~p x} = {x | p x}`]);;
+
+let OPEN_HALFSPACE_IM_LT = prove
+ (`!b. open {z | Im(z) < b}`,
+  REWRITE_TAC[OPEN_CLOSED; CLOSED_HALFSPACE_IM_GE;
+              REAL_ARITH `x < y <=> ~(x >= y)`;
+              SET_RULE `UNIV DIFF {x | ~p x} = {x | p x}`]);;
+
+let CONVEX_HALFSPACE_RE_GE = prove
+ (`!b. convex {z | Re(z) >= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`Cx(&1)`; `b:real`] CONVEX_HALFSPACE_GE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CONVEX_HALFSPACE_RE_GT = prove
+ (`!b. convex {z | Re(z) > b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`Cx(&1)`; `b:real`] CONVEX_HALFSPACE_GT) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CONVEX_HALFSPACE_RE_LE = prove
+ (`!b. convex {z | Re(z) <= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`Cx(&1)`; `b:real`] CONVEX_HALFSPACE_LE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CONVEX_HALFSPACE_RE_LT = prove
+ (`!b. convex {z | Re(z) < b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`Cx(&1)`; `b:real`] CONVEX_HALFSPACE_LT) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CONVEX_HALFSPACE_IM_GE = prove
+ (`!b. convex {z | Im(z) >= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`ii`; `b:real`] CONVEX_HALFSPACE_GE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CONVEX_HALFSPACE_IM_GT = prove
+ (`!b. convex {z | Im(z) > b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`ii`; `b:real`] CONVEX_HALFSPACE_GT) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CONVEX_HALFSPACE_IM_LE = prove
+ (`!b. convex {z | Im(z) <= b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`ii`; `b:real`] CONVEX_HALFSPACE_LE) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let CONVEX_HALFSPACE_IM_LT = prove
+ (`!b. convex {z | Im(z) < b}`,
+  GEN_TAC THEN MP_TAC(ISPECL [`ii`; `b:real`] CONVEX_HALFSPACE_LT) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+  REWRITE_TAC[EXTENSION; dot; SUM_2; DIMINDEX_2; GSYM RE_DEF; GSYM IM_DEF] THEN
+  REWRITE_TAC[ii; RE_CX; IM_CX; RE; IM; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
+
+let COMPLEX_IN_BALL_0 = prove
+ (`!v r. v IN ball(Cx(&0),r) <=> norm v < r`,
+  REWRITE_TAC [GSYM COMPLEX_VEC_0; IN_BALL_0]);;
+
+let COMPLEX_IN_CBALL_0 = prove
+ (`!v r. v IN cball(Cx(&0),r) <=> norm v <= r`,
+  REWRITE_TAC [GSYM COMPLEX_VEC_0; IN_CBALL_0]);;
+
+let COMPLEX_IN_SPHERE_0 = prove
+ (`!v r. v IN sphere(Cx(&0),r) <=> norm v = r`,
+  REWRITE_TAC [GSYM COMPLEX_VEC_0; IN_SPHERE_0]);;
+
+let IN_BALL_RE = prove
+ (`!x z e. x IN ball(z,e) ==> abs(Re(x) - Re(z)) < e`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[IN_BALL; dist] THEN
+  MP_TAC(SPEC `z - x:complex` COMPLEX_NORM_GE_RE_IM) THEN
+  REWRITE_TAC[RE_SUB] THEN REAL_ARITH_TAC);;
+
+let IN_BALL_IM = prove
+ (`!x z e. x IN ball(z,e) ==> abs(Im(x) - Im(z)) < e`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[IN_BALL; dist] THEN
+  MP_TAC(SPEC `z - x:complex` COMPLEX_NORM_GE_RE_IM) THEN
+  REWRITE_TAC[IM_SUB] THEN REAL_ARITH_TAC);;
+
+let IN_CBALL_RE = prove
+ (`!x z e. x IN cball(z,e) ==> abs(Re(x) - Re(z)) <= e`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[IN_CBALL; dist] THEN
+  MP_TAC(SPEC `z - x:complex` COMPLEX_NORM_GE_RE_IM) THEN
+  REWRITE_TAC[RE_SUB] THEN REAL_ARITH_TAC);;
+
+let IN_CBALL_IM = prove
+ (`!x z e. x IN cball(z,e) ==> abs(Im(x) - Im(z)) <= e`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[IN_CBALL; dist] THEN
+  MP_TAC(SPEC `z - x:complex` COMPLEX_NORM_GE_RE_IM) THEN
+  REWRITE_TAC[IM_SUB] THEN REAL_ARITH_TAC);;
+
+let CLOSED_REAL_SET = prove
+ (`closed {z | real z}`,
+  REWRITE_TAC[CLOSED_HALFSPACE_IM_EQ; real]);;
+
+let CLOSED_REAL = prove
+ (`closed real`,
+  GEN_REWRITE_TAC RAND_CONV [SET_RULE `s = {x | s x}`] THEN
+  REWRITE_TAC[CLOSED_REAL_SET]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Complex-specific uniform limit composition theorems.                      *)
+(* ------------------------------------------------------------------------- *)
+
+let UNIFORM_LIM_COMPLEX_MUL = prove
+ (`!net:(A)net P f g l m b1 b2.
+        eventually (\x. !n. P n ==> norm(l n) <= b1) net /\
+        eventually (\x. !n. P n ==> norm(m n) <= b2) net /\
+        (!e. &0 < e
+             ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
+        (!e. &0 < e
+             ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
+        ==> !e. &0 < e
+                ==> eventually
+                     (\x. !n. P n
+                              ==> norm(f n x * g n x - l n * m n) < e)
+                     net`,
+  REPEAT GEN_TAC THEN
+  DISCH_THEN(MP_TAC o CONJ BILINEAR_COMPLEX_MUL) THEN
+  REWRITE_TAC[UNIFORM_LIM_BILINEAR]);;
+
+let UNIFORM_LIM_COMPLEX_INV = prove
+ (`!net:(A)net P f l b.
+        (!e. &0 < e
+             ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
+        &0 < b /\ eventually (\x. !n. P n ==> b <= norm(l n)) net
+        ==> !e. &0 < e
+                ==> eventually
+                    (\x. !n. P n ==> norm(inv(f n x) - inv(l n)) < e) net`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC EVENTUALLY_MONO THEN
+  EXISTS_TAC
+   `\x. !n. P n ==> b <= norm(l n) /\
+                    b / &2 <= norm((f:B->A->complex) n x) /\
+                    norm(f n x - l n) < e * b pow 2 / &2` THEN
+  REWRITE_TAC[TAUT `(p ==> q /\ r) <=> (p ==> q) /\ (p ==> r)`] THEN
+  REWRITE_TAC[FORALL_AND_THM] THEN CONJ_TAC THENL
+   [X_GEN_TAC `x:A` THEN STRIP_TAC THEN X_GEN_TAC `n:B` THEN DISCH_TAC THEN
+    REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `n:B`) THEN ASM_REWRITE_TAC[]) THEN
+    REPEAT DISCH_TAC THEN
+    SUBGOAL_THEN `~((f:B->A->complex) n x = Cx(&0)) /\ ~(l n = Cx(&0))`
+    STRIP_ASSUME_TAC THENL
+     [CONJ_TAC THEN DISCH_THEN SUBST_ALL_TAC THEN
+      RULE_ASSUM_TAC(REWRITE_RULE[COMPLEX_NORM_CX]) THEN ASM_REAL_ARITH_TAC;
+      ALL_TAC] THEN
+    ASM_SIMP_TAC[COMPLEX_FIELD
+     `~(x = Cx(&0)) /\ ~(y = Cx(&0))
+      ==> inv x - inv y = (y - x) / (x * y)`] THEN
+    ASM_SIMP_TAC[COMPLEX_NORM_DIV; REAL_LT_LDIV_EQ; COMPLEX_NORM_NZ;
+                 COMPLEX_ENTIRE] THEN
+    ONCE_REWRITE_TAC[NORM_SUB] THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+        REAL_LTE_TRANS)) THEN
+    ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_ARITH `b pow 2 / &2 = b / &2 * b`] THEN
+    REWRITE_TAC[COMPLEX_NORM_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN
+    ASM_REAL_ARITH_TAC;
+    ASM_REWRITE_TAC[EVENTUALLY_AND] THEN CONJ_TAC THENL
+     [FIRST_X_ASSUM(MP_TAC o SPEC `b / &2`) THEN
+      ASM_REWRITE_TAC[REAL_HALF] THEN
+      FIRST_X_ASSUM(fun th -> MP_TAC th THEN REWRITE_TAC[IMP_IMP] THEN
+        GEN_REWRITE_TAC LAND_CONV [GSYM EVENTUALLY_AND]) THEN
+      MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
+      REWRITE_TAC[] THEN
+      ASM_MESON_TAC[NORM_ARITH
+       `b <= norm l /\ norm(f - l) < b / &2 ==> b / &2 <= norm f`];
+      FIRST_X_ASSUM MATCH_MP_TAC THEN
+      ASM_SIMP_TAC[REAL_HALF; REAL_POW_LT; REAL_LT_MUL]]]);;
+
+let UNIFORM_LIM_COMPLEX_DIV = prove
+ (`!net:(A)net P f g l m b1 b2.
+        eventually (\x. !n. P n ==> norm(l n) <= b1) net /\
+        &0 < b2 /\ eventually (\x. !n. P n ==> b2 <= norm(m n)) net /\
+        (!e. &0 < e
+             ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
+        (!e. &0 < e
+             ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
+        ==> !e. &0 < e
+                ==> eventually
+                     (\x. !n. P n
+                              ==> norm(f n x / g n x - l n / m n) < e)
+                     net`,
+  REPEAT GEN_TAC THEN DISCH_TAC THEN
+  REWRITE_TAC[complex_div] THEN MATCH_MP_TAC UNIFORM_LIM_COMPLEX_MUL THEN
+  MAP_EVERY EXISTS_TAC [`b1:real`; `inv(b2):real`] THEN
+  ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+   [FIRST_X_ASSUM(CONJUNCTS_THEN2 ASSUME_TAC
+     (MP_TAC o CONJUNCT1) o CONJUNCT2) THEN
+    MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
+    GEN_TAC THEN REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN
+    REPEAT STRIP_TAC THEN REWRITE_TAC[COMPLEX_NORM_INV] THEN
+    MATCH_MP_TAC REAL_LE_INV2 THEN ASM_SIMP_TAC[];
+    MATCH_MP_TAC UNIFORM_LIM_COMPLEX_INV THEN
+    EXISTS_TAC `b2:real` THEN ASM_REWRITE_TAC[]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* The usual non-uniform versions.                                           *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_COMPLEX_MUL = prove
+ (`!net:(A)net f g l m.
+         (f --> l) net /\ (g --> m) net ==> ((\x. f x * g x) --> l * m) net`,
+  SIMP_TAC[LIM_BILINEAR; BILINEAR_COMPLEX_MUL]);;
+
+let LIM_COMPLEX_INV = prove
+ (`!net:(A)net f g l m.
+         (f --> l) net /\ ~(l = Cx(&0)) ==> ((\x. inv(f x)) --> inv(l)) net`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL
+   [`net:(A)net`; `\x:one. T`;
+    `\n:one. (f:A->complex)`;
+    `\n:one. (l:complex)`;
+    `norm(l:complex)`] UNIFORM_LIM_COMPLEX_INV) THEN
+  ASM_REWRITE_TAC[REAL_LE_REFL; EVENTUALLY_TRUE] THEN
+  ASM_REWRITE_TAC[GSYM dist; GSYM tendsto; COMPLEX_NORM_NZ]);;
+
+let LIM_COMPLEX_DIV = prove
+ (`!net:(A)net f g l m.
+         (f --> l) net /\ (g --> m) net /\ ~(m = Cx(&0))
+         ==> ((\x. f x / g x) --> l / m) net`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[complex_div] THEN
+  MATCH_MP_TAC LIM_COMPLEX_MUL THEN ASM_SIMP_TAC[LIM_COMPLEX_INV]);;
+
+let LIM_COMPLEX_POW = prove
+ (`!net:(A)net f l n.
+         (f --> l) net ==> ((\x. f(x) pow n) --> l pow n) net`,
+  REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
+  INDUCT_TAC THEN ASM_SIMP_TAC[LIM_COMPLEX_MUL; complex_pow; LIM_CONST]);;
+
+let LIM_COMPLEX_LMUL = prove
+ (`!f l c. (f --> l) net ==> ((\x. c * f x) --> c * l) net`,
+  SIMP_TAC[LIM_COMPLEX_MUL; LIM_CONST]);;
+
+let LIM_COMPLEX_RMUL = prove
+ (`!f l c. (f --> l) net ==> ((\x. f x * c) --> l * c) net`,
+  SIMP_TAC[LIM_COMPLEX_MUL; LIM_CONST]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Special cases of null limits.                                             *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_NULL_COMPLEX_NEG = prove
+ (`!net f. (f --> Cx(&0)) net ==> ((\x. --(f x)) --> Cx(&0)) net`,
+  REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_NEG) THEN
+  REWRITE_TAC[COMPLEX_NEG_0]);;
+
+let LIM_NULL_COMPLEX_ADD = prove
+ (`!net f g. (f --> Cx(&0)) net /\ (g --> Cx(&0)) net
+             ==> ((\x. f x + g x) --> Cx(&0)) net`,
+  REPEAT GEN_TAC THEN
+  DISCH_THEN(MP_TAC o MATCH_MP LIM_ADD) THEN
+  REWRITE_TAC[COMPLEX_ADD_LID]);;
+
+let LIM_NULL_COMPLEX_SUB = prove
+ (`!net f g. (f --> Cx(&0)) net /\ (g --> Cx(&0)) net
+             ==> ((\x. f x - g x) --> Cx(&0)) net`,
+  REPEAT GEN_TAC THEN
+  DISCH_THEN(MP_TAC o MATCH_MP LIM_SUB) THEN
+  REWRITE_TAC[COMPLEX_SUB_REFL]);;
+
+let LIM_NULL_COMPLEX_MUL = prove
+ (`!net f g. (f --> Cx(&0)) net /\ (g --> Cx(&0)) net
+             ==> ((\x. f x * g x) --> Cx(&0)) net`,
+  REPEAT GEN_TAC THEN
+  DISCH_THEN(MP_TAC o MATCH_MP LIM_COMPLEX_MUL) THEN
+  REWRITE_TAC[COMPLEX_MUL_LZERO]);;
+
+let LIM_NULL_COMPLEX_LMUL = prove
+ (`!net f c. (f --> Cx(&0)) net ==> ((\x. c * f x) --> Cx(&0)) net`,
+  REPEAT STRIP_TAC THEN SUBST1_TAC(COMPLEX_RING `Cx(&0) = c * Cx(&0)`) THEN
+  ASM_SIMP_TAC[LIM_COMPLEX_LMUL]);;
+
+let LIM_NULL_COMPLEX_RMUL = prove
+ (`!net f c. (f --> Cx(&0)) net ==> ((\x. f x * c) --> Cx(&0)) net`,
+  REPEAT STRIP_TAC THEN SUBST1_TAC(COMPLEX_RING `Cx(&0) = Cx(&0) * c`) THEN
+  ASM_SIMP_TAC[LIM_COMPLEX_RMUL]);;
+
+let LIM_NULL_COMPLEX_POW = prove
+ (`!net f n. (f --> Cx(&0)) net /\ ~(n = 0)
+             ==> ((\x. (f x) pow n) --> Cx(&0)) net`,
+  REPEAT STRIP_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `n:num` o MATCH_MP LIM_COMPLEX_POW) THEN
+  ASM_REWRITE_TAC[COMPLEX_POW_ZERO]);;
+
+let LIM_NULL_COMPLEX_BOUND = prove
+ (`!f g. eventually (\n. norm (f n) <= norm (g n)) net /\ (g --> Cx(&0)) net
+         ==> (f --> Cx(&0)) net`,
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; LIM_TRANSFORM_BOUND]);;
+
+let SUMS_COMPLEX_0 = prove
+ (`!f s. (!n. n IN s ==> f n = Cx(&0)) ==> (f sums Cx(&0)) s`,
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; SUMS_0]);;
+
+let LIM_NULL_COMPLEX_RMUL_BOUNDED = prove
+ (`!f g. (f --> Cx(&0)) net /\
+         eventually (\a. f a = Cx(&0) \/ norm(g a) <= B) net
+         ==> ((\z. f(z) * g(z)) --> Cx(&0)) net`,
+  REWRITE_TAC[GSYM COMPLEX_VEC_0] THEN
+  ONCE_REWRITE_TAC[LIM_NULL_NORM] THEN
+  REWRITE_TAC[LIFT_CMUL; COMPLEX_NORM_MUL] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_NULL_VMUL_BOUNDED THEN
+  EXISTS_TAC `B:real` THEN
+  ASM_REWRITE_TAC[o_DEF; NORM_LIFT; REAL_ABS_NORM; NORM_EQ_0]);;
+
+let LIM_NULL_COMPLEX_LMUL_BOUNDED = prove
+ (`!f g. eventually (\a. norm(f a) <= B \/ g a = Cx(&0)) net /\
+         (g --> Cx(&0)) net
+         ==> ((\z. f(z) * g(z)) --> Cx(&0)) net`,
+  ONCE_REWRITE_TAC[DISJ_SYM; COMPLEX_MUL_SYM] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC LIM_NULL_COMPLEX_RMUL_BOUNDED THEN ASM_REWRITE_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Bound results for real and imaginary components of limits.                *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_RE_UBOUND = prove
+ (`!net:(A)net f l b.
+        ~(trivial_limit net) /\ (f --> l) net /\
+        eventually (\x. Re(f x) <= b) net
+        ==> Re(l) <= b`,
+  REWRITE_TAC[RE_DEF] THEN REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`net:(A)net`; `f:A->complex`; `l:complex`; `b:real`; `1`]
+                LIM_COMPONENT_UBOUND) THEN
+  ASM_REWRITE_TAC[DIMINDEX_2; ARITH]);;
+
+let LIM_RE_LBOUND = prove
+ (`!net:(A)net f l b.
+        ~(trivial_limit net) /\ (f --> l) net /\
+        eventually (\x. b <= Re(f x)) net
+        ==> b <= Re(l)`,
+  REWRITE_TAC[RE_DEF] THEN REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`net:(A)net`; `f:A->complex`; `l:complex`; `b:real`; `1`]
+                LIM_COMPONENT_LBOUND) THEN
+  ASM_REWRITE_TAC[DIMINDEX_2; ARITH]);;
+
+let LIM_IM_UBOUND = prove
+ (`!net:(A)net f l b.
+        ~(trivial_limit net) /\ (f --> l) net /\
+        eventually (\x. Im(f x) <= b) net
+        ==> Im(l) <= b`,
+  REWRITE_TAC[IM_DEF] THEN REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`net:(A)net`; `f:A->complex`; `l:complex`; `b:real`; `2`]
+                LIM_COMPONENT_UBOUND) THEN
+  ASM_REWRITE_TAC[DIMINDEX_2; ARITH]);;
+
+let LIM_IM_LBOUND = prove
+ (`!net:(A)net f l b.
+        ~(trivial_limit net) /\ (f --> l) net /\
+        eventually (\x. b <= Im(f x)) net
+        ==> b <= Im(l)`,
+  REWRITE_TAC[IM_DEF] THEN REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`net:(A)net`; `f:A->complex`; `l:complex`; `b:real`; `2`]
+                LIM_COMPONENT_LBOUND) THEN
+  ASM_REWRITE_TAC[DIMINDEX_2; ARITH]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Left and right multiplication of series.                                  *)
+(* ------------------------------------------------------------------------- *)
+
+let SERIES_COMPLEX_LMUL = prove
+ (`!f l c s. (f sums l) s ==> ((\x. c * f x) sums c * l) s`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC SERIES_LINEAR THEN
+  ASM_REWRITE_TAC[] THEN GEN_REWRITE_TAC RAND_CONV [GSYM ETA_AX] THEN
+  REWRITE_TAC[LINEAR_COMPLEX_MUL]);;
+
+let SERIES_COMPLEX_RMUL = prove
+ (`!f l c s. (f sums l) s ==> ((\x. f x * c) sums l * c) s`,
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN REWRITE_TAC[SERIES_COMPLEX_LMUL]);;
+
+let SERIES_COMPLEX_DIV = prove
+ (`!f l c s. (f sums l) s ==> ((\x. f x / c) sums (l / c)) s`,
+  REWRITE_TAC[complex_div; SERIES_COMPLEX_RMUL]);;
+
+let SUMMABLE_COMPLEX_LMUL = prove
+ (`!f c s. summable s f ==> summable s (\x. c * f x)`,
+  REWRITE_TAC[summable] THEN MESON_TAC[SERIES_COMPLEX_LMUL]);;
+
+let SUMMABLE_COMPLEX_RMUL = prove
+ (`!f c s. summable s f ==> summable s (\x. f x * c)`,
+  REWRITE_TAC[summable] THEN MESON_TAC[SERIES_COMPLEX_RMUL]);;
+
+let SUMMABLE_COMPLEX_DIV = prove
+ (`!f c s. summable s f ==> summable s (\x. f x / c)`,
+  REWRITE_TAC[summable] THEN MESON_TAC[SERIES_COMPLEX_DIV]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Complex-specific continuity closures.                                     *)
+(* ------------------------------------------------------------------------- *)
+
+let CONTINUOUS_COMPLEX_MUL = prove
+ (`!net f g.
+    f continuous net /\ g continuous net ==> (\x. f(x) * g(x)) continuous net`,
+  SIMP_TAC[continuous; LIM_COMPLEX_MUL]);;
+
+let CONTINUOUS_COMPLEX_INV = prove
+ (`!net f.
+    f continuous net /\ ~(f(netlimit net) = Cx(&0))
+    ==> (\x. inv(f x)) continuous net`,
+  SIMP_TAC[continuous; LIM_COMPLEX_INV]);;
+
+let CONTINUOUS_COMPLEX_DIV = prove
+ (`!net f g.
+    f continuous net /\ g continuous net /\ ~(g(netlimit net) = Cx(&0))
+    ==> (\x. f(x) / g(x)) continuous net`,
+  SIMP_TAC[continuous; LIM_COMPLEX_DIV]);;
+
+let CONTINUOUS_COMPLEX_POW = prove
+ (`!net f n. f continuous net ==> (\x. f(x) pow n) continuous net`,
+  SIMP_TAC[continuous; LIM_COMPLEX_POW]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Write away the netlimit, which is otherwise a bit tedious.                *)
+(* ------------------------------------------------------------------------- *)
+
+let CONTINUOUS_COMPLEX_INV_WITHIN = prove
+ (`!f s a.
+    f continuous (at a within s) /\ ~(f a = Cx(&0))
+    ==> (\x. inv(f x)) continuous (at a within s)`,
+  MESON_TAC[CONTINUOUS_COMPLEX_INV; CONTINUOUS_TRIVIAL_LIMIT;
+            NETLIMIT_WITHIN]);;
+
+let CONTINUOUS_COMPLEX_INV_AT = prove
+ (`!f a.
+    f continuous (at a) /\ ~(f a = Cx(&0))
+    ==> (\x. inv(f x)) continuous (at a)`,
+  SIMP_TAC[CONTINUOUS_COMPLEX_INV; NETLIMIT_AT]);;
+
+let CONTINUOUS_COMPLEX_DIV_WITHIN = prove
+ (`!f g s a.
+    f continuous (at a within s) /\ g continuous (at a within s) /\
+    ~(g a = Cx(&0))
+    ==> (\x. f x / g x) continuous (at a within s)`,
+  MESON_TAC[CONTINUOUS_COMPLEX_DIV; CONTINUOUS_TRIVIAL_LIMIT;
+            NETLIMIT_WITHIN]);;
+
+let CONTINUOUS_COMPLEX_DIV_AT = prove
+ (`!f g a.
+    f continuous at a /\ g continuous at a /\ ~(g a = Cx(&0))
+    ==> (\x. f x / g x) continuous at a`,
+  SIMP_TAC[CONTINUOUS_COMPLEX_DIV; NETLIMIT_AT]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Also prove "on" variants as needed.                                       *)
+(* ------------------------------------------------------------------------- *)
+
+let CONTINUOUS_ON_COMPLEX_MUL = prove
+ (`!f g s. f continuous_on s /\ g continuous_on s
+           ==> (\x. f(x) * g(x)) continuous_on s`,
+  REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
+  SIMP_TAC[CONTINUOUS_COMPLEX_MUL]);;
+
+let CONTINUOUS_ON_COMPLEX_LMUL = prove
+ (`!f:real^N->complex s. f continuous_on s ==> (\x. c * f(x)) continuous_on s`,
+  REWRITE_TAC[CONTINUOUS_ON] THEN SIMP_TAC[LIM_COMPLEX_MUL; LIM_CONST]);;
+
+let CONTINUOUS_ON_COMPLEX_RMUL = prove
+ (`!f:real^N->complex s. f continuous_on s ==> (\x. f(x) * c) continuous_on s`,
+  REWRITE_TAC[CONTINUOUS_ON] THEN SIMP_TAC[LIM_COMPLEX_MUL; LIM_CONST]);;
+
+let CONTINUOUS_ON_COMPLEX_INV = prove
+ (`!f:real^N->complex.
+        f continuous_on s /\
+        (!x. x IN s ==> ~(f x = Cx(&0)))
+        ==> (\x. inv(f x)) continuous_on s`,
+  SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
+           CONTINUOUS_COMPLEX_INV_WITHIN]);;
+
+let CONTINUOUS_ON_COMPLEX_DIV = prove
+ (`!f g s. f continuous_on s /\ g continuous_on s /\
+           (!x. x IN s ==> ~(g x = Cx(&0)))
+           ==> (\x. f(x) / g(x)) continuous_on s`,
+  REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
+  SIMP_TAC[CONTINUOUS_COMPLEX_DIV_WITHIN]);;
+
+let CONTINUOUS_ON_COMPLEX_POW = prove
+ (`!f n s. f continuous_on s ==> (\x. f(x) pow n) continuous_on s`,
+  SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_COMPLEX_POW]);;
+
+(* ------------------------------------------------------------------------- *)
+(* And also uniform versions.                                                *)
+(* ------------------------------------------------------------------------- *)
+
+let UNIFORMLY_CONTINUOUS_ON_COMPLEX_MUL = prove
+ (`!f g s:real^N->bool.
+        f uniformly_continuous_on s /\ g uniformly_continuous_on s /\
+        bounded(IMAGE f s) /\ bounded(IMAGE g s)
+        ==> (\x. f(x) * g(x)) uniformly_continuous_on s`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL
+   [`f:real^N->complex`; `g:real^N->complex`;
+    `( * ):complex->complex->complex`; `s:real^N->bool`]
+    BILINEAR_UNIFORMLY_CONTINUOUS_ON_COMPOSE) THEN
+  ASM_REWRITE_TAC[BILINEAR_COMPLEX_MUL]);;
+
+let UNIFORMLY_CONTINUOUS_ON_COMPLEX_LMUL = prove
+ (`!f c s:real^N->bool.
+      f uniformly_continuous_on s ==> (\x. c * f x) uniformly_continuous_on s`,
+  REPEAT GEN_TAC THEN
+  DISCH_THEN(MP_TAC o ISPEC `\x:complex. c * x` o MATCH_MP
+   (REWRITE_RULE[IMP_CONJ] UNIFORMLY_CONTINUOUS_ON_COMPOSE)) THEN
+  ASM_SIMP_TAC[o_DEF; LINEAR_COMPLEX_MUL; LINEAR_UNIFORMLY_CONTINUOUS_ON]);;
+
+let UNIFORMLY_CONTINUOUS_ON_COMPLEX_RMUL = prove
+ (`!f c s:real^N->bool.
+      f uniformly_continuous_on s ==> (\x. f x * c) uniformly_continuous_on s`,
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_COMPLEX_LMUL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Continuity prover (not just for complex numbers but with more for them).  *)
+(* ------------------------------------------------------------------------- *)
+
+let CONTINUOUS_TAC =
+  let ETA_THM = prove
+   (`f continuous net <=> (\x. f x) continuous net`,
+    REWRITE_TAC[ETA_AX]) in
+  let ETA_TWEAK =
+    GEN_REWRITE_RULE (LAND_CONV o ONCE_DEPTH_CONV) [ETA_THM] o SPEC_ALL in
+  let tac_base =
+    MATCH_ACCEPT_TAC CONTINUOUS_CONST ORELSE
+    MATCH_ACCEPT_TAC CONTINUOUS_AT_ID ORELSE
+    MATCH_ACCEPT_TAC CONTINUOUS_WITHIN_ID
+  and tac_1 =
+    MATCH_MP_TAC(ETA_TWEAK CONTINUOUS_CMUL) ORELSE
+    MATCH_MP_TAC(ETA_TWEAK CONTINUOUS_NEG) ORELSE
+    MATCH_MP_TAC(ETA_TWEAK CONTINUOUS_COMPLEX_POW)
+  and tac_2 =
+    MATCH_MP_TAC(ETA_TWEAK CONTINUOUS_ADD) ORELSE
+    MATCH_MP_TAC(ETA_TWEAK CONTINUOUS_SUB) ORELSE
+    MATCH_MP_TAC(ETA_TWEAK CONTINUOUS_COMPLEX_MUL)
+  and tac_1' = MATCH_MP_TAC (ETA_TWEAK CONTINUOUS_COMPLEX_INV)
+  and tac_2' = MATCH_MP_TAC (ETA_TWEAK CONTINUOUS_COMPLEX_DIV) in
+  let rec CONTINUOUS_TAC gl =
+   (tac_base ORELSE
+    (tac_1 THEN CONTINUOUS_TAC) ORELSE
+    (tac_2 THEN CONJ_TAC THEN CONTINUOUS_TAC) ORELSE
+    (tac_1' THEN CONJ_TAC THENL
+     [CONTINUOUS_TAC; REWRITE_TAC[NETLIMIT_AT; NETLIMIT_WITHIN]]) ORELSE
+    (tac_2' THEN REPEAT CONJ_TAC THENL
+     [CONTINUOUS_TAC; CONTINUOUS_TAC;
+      REWRITE_TAC[NETLIMIT_AT; NETLIMIT_WITHIN]]) ORELSE
+    ALL_TAC) gl in
+  CONTINUOUS_TAC;;
+
+(* ------------------------------------------------------------------------- *)
+(* Hence a limit calculator                                                  *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_CONTINUOUS = prove
+ (`!net f l. f continuous net /\ f(netlimit net) = l ==> (f --> l) net`,
+  MESON_TAC[continuous]);;
+
+let LIM_TAC =
+  MATCH_MP_TAC LIM_CONTINUOUS THEN CONJ_TAC THENL
+   [CONTINUOUS_TAC; REWRITE_TAC[NETLIMIT_AT; NETLIMIT_WITHIN]];;
+
+(* ------------------------------------------------------------------------- *)
+(* Continuity of the norm.                                                   *)
+(* ------------------------------------------------------------------------- *)
+
+let CONTINUOUS_AT_CX_NORM = prove
+ (`!z:real^N. (\z. Cx(norm z)) continuous at z`,
+  REWRITE_TAC[continuous_at; dist; GSYM CX_SUB; COMPLEX_NORM_CX] THEN
+  MESON_TAC[NORM_ARITH `norm(a - b:real^N) < d ==> abs(norm a - norm b) < d`]);;
+
+let CONTINUOUS_WITHIN_CX_NORM = prove
+ (`!z:real^N s. (\z. Cx(norm z)) continuous (at z within s)`,
+  SIMP_TAC[CONTINUOUS_AT_CX_NORM; CONTINUOUS_AT_WITHIN]);;
+
+let CONTINUOUS_ON_CX_NORM = prove
+ (`!s. (\z. Cx(norm z)) continuous_on s`,
+  SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_WITHIN_CX_NORM]);;
+
+let CONTINUOUS_AT_CX_DOT = prove
+ (`!c z:real^N. (\z. Cx(c dot z)) continuous at z`,
+  REPEAT GEN_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
+  REWRITE_TAC[linear; DOT_RADD; DOT_RMUL; CX_ADD; COMPLEX_CMUL; CX_MUL]);;
+
+let CONTINUOUS_WITHIN_CX_DOT = prove
+ (`!c z:real^N s. (\z. Cx(c dot z)) continuous (at z within s)`,
+  SIMP_TAC[CONTINUOUS_AT_CX_DOT; CONTINUOUS_AT_WITHIN]);;
+
+let CONTINUOUS_ON_CX_DOT = prove
+ (`!s c:real^N. (\z. Cx(c dot z)) continuous_on s`,
+  SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_WITHIN_CX_DOT]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Continuity switching range between complex and real^1                     *)
+(* ------------------------------------------------------------------------- *)
+
+let CONTINUOUS_CX_DROP = prove
+ (`!net f. f continuous net ==> (\x. Cx(drop(f x))) continuous net`,
+  REWRITE_TAC[continuous; tendsto] THEN
+  REWRITE_TAC[dist; GSYM CX_SUB; COMPLEX_NORM_CX; GSYM DROP_SUB] THEN
+  REWRITE_TAC[GSYM ABS_DROP]);;
+
+let CONTINUOUS_ON_CX_DROP = prove
+ (`!f s. f continuous_on s ==> (\x. Cx(drop(f x))) continuous_on s`,
+  SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_CX_DROP]);;
+
+let CONTINUOUS_CX_LIFT = prove
+ (`!f. (\x. Cx(f x)) continuous net <=> (\x. lift(f x)) continuous net`,
+  REWRITE_TAC[continuous; LIM; dist; GSYM CX_SUB; GSYM LIFT_SUB] THEN
+  REWRITE_TAC[COMPLEX_NORM_CX; NORM_LIFT]);;
+
+let CONTINUOUS_ON_CX_LIFT = prove
+ (`!f s. (\x. Cx(f x)) continuous_on s <=> (\x. lift(f x)) continuous_on s`,
+  REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_CX_LIFT]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Linearity and continuity of the components.                               *)
+(* ------------------------------------------------------------------------- *)
+
+let LINEAR_CX_RE = prove
+ (`linear(Cx o Re)`,
+  SIMP_TAC[linear; o_THM; COMPLEX_CMUL; RE_ADD; RE_MUL_CX; CX_MUL; CX_ADD]);;
+
+let CONTINUOUS_AT_CX_RE = prove
+ (`!z. (Cx o Re) continuous at z`,
+  SIMP_TAC[LINEAR_CONTINUOUS_AT; LINEAR_CX_RE]);;
+
+let CONTINUOUS_ON_CX_RE = prove
+ (`!s. (Cx o Re) continuous_on s`,
+  SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_CX_RE]);;
+
+let LINEAR_CX_IM = prove
+ (`linear(Cx o Im)`,
+  SIMP_TAC[linear; o_THM; COMPLEX_CMUL; IM_ADD; IM_MUL_CX; CX_MUL; CX_ADD]);;
+
+let CONTINUOUS_AT_CX_IM = prove
+ (`!z. (Cx o Im) continuous at z`,
+  SIMP_TAC[LINEAR_CONTINUOUS_AT; LINEAR_CX_IM]);;
+
+let CONTINUOUS_ON_CX_IM = prove
+ (`!s. (Cx o Im) continuous_on s`,
+  SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_CX_IM]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Complex differentiability.                                                *)
+(* ------------------------------------------------------------------------- *)
+
+parse_as_infix ("has_complex_derivative",(12,"right"));;
+parse_as_infix ("complex_differentiable",(12,"right"));;
+parse_as_infix ("holomorphic_on",(12,"right"));;
+
+let has_complex_derivative = new_definition
+ `(f has_complex_derivative f') net <=> (f has_derivative (\x. f' * x)) net`;;
+
+let complex_differentiable = new_definition
+ `f complex_differentiable net <=> ?f'. (f has_complex_derivative f') net`;;
+
+let complex_derivative = new_definition
+ `complex_derivative f x = @f'. (f has_complex_derivative f') (at x)`;;
+
+let higher_complex_derivative = define
+ `higher_complex_derivative 0 f = f /\
+  (!n. higher_complex_derivative (SUC n) f =
+                complex_derivative (higher_complex_derivative n f))`;;
+
+let holomorphic_on = new_definition
+ `f holomorphic_on s <=>
+     !x. x IN s ==> ?f'. (f has_complex_derivative f') (at x within s)`;;
+
+let HOLOMORPHIC_ON_DIFFERENTIABLE = prove
+ (`!f s. f holomorphic_on s <=>
+         !x. x IN s ==> f complex_differentiable (at x within s)`,
+  REWRITE_TAC[holomorphic_on; complex_differentiable]);;
+
+let HOLOMORPHIC_ON_OPEN = prove
+ (`!f s. open s
+         ==> (f holomorphic_on s <=>
+              !x. x IN s ==> ?f'. (f has_complex_derivative f') (at x))`,
+  REWRITE_TAC[holomorphic_on; has_complex_derivative] THEN
+  REWRITE_TAC[has_derivative_at; has_derivative_within] THEN
+  SIMP_TAC[LIM_WITHIN_OPEN]);;
+
+let HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_WITHIN = prove
+ (`!f s x. f holomorphic_on s /\ x IN s
+           ==> f complex_differentiable (at x within s)`,
+  MESON_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE]);;
+
+let HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_AT = prove
+ (`!f s x. f holomorphic_on s /\ open s /\ x IN s
+           ==> f complex_differentiable (at x)`,
+  MESON_TAC[HOLOMORPHIC_ON_OPEN; complex_differentiable]);;
+
+let HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT = prove
+ (`!f f' x. (f has_complex_derivative f') (at x) ==> f continuous at x`,
+  REWRITE_TAC[has_complex_derivative] THEN
+  MESON_TAC[differentiable; DIFFERENTIABLE_IMP_CONTINUOUS_AT]);;
+
+let HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_WITHIN = prove
+ (`!f f' x s. (f has_complex_derivative f') (at x within s)
+              ==> f continuous (at x within s)`,
+  REWRITE_TAC[has_complex_derivative] THEN
+  MESON_TAC[differentiable; DIFFERENTIABLE_IMP_CONTINUOUS_WITHIN]);;
+
+let COMPLEX_DIFFERENTIABLE_IMP_CONTINUOUS_AT = prove
+ (`!f x. f complex_differentiable at x ==> f continuous at x`,
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT; complex_differentiable]);;
+
+let HOLOMORPHIC_ON_IMP_CONTINUOUS_ON = prove
+ (`!f s. f holomorphic_on s ==> f continuous_on s`,
+  REWRITE_TAC[holomorphic_on; CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
+  REWRITE_TAC[has_complex_derivative] THEN
+  MESON_TAC[DIFFERENTIABLE_IMP_CONTINUOUS_WITHIN; differentiable]);;
+
+let HOLOMORPHIC_ON_SUBSET = prove
+ (`!f s t. f holomorphic_on s /\ t SUBSET s ==> f holomorphic_on t`,
+  REWRITE_TAC[holomorphic_on; has_complex_derivative] THEN
+  MESON_TAC[SUBSET; HAS_DERIVATIVE_WITHIN_SUBSET]);;
+
+let HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET = prove
+ (`!f s t x. (f has_complex_derivative f') (at x within s) /\ t SUBSET s
+             ==> (f has_complex_derivative f') (at x within t)`,
+  REWRITE_TAC[has_complex_derivative; HAS_DERIVATIVE_WITHIN_SUBSET]);;
+
+let COMPLEX_DIFFERENTIABLE_WITHIN_SUBSET = prove
+ (`!f s t. f complex_differentiable (at x within s) /\ t SUBSET s
+           ==> f complex_differentiable (at x within t)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET]);;
+
+let HAS_COMPLEX_DERIVATIVE_AT_WITHIN = prove
+ (`!f f' x s. (f has_complex_derivative f') (at x)
+              ==> (f has_complex_derivative f') (at x within s)`,
+  REWRITE_TAC[has_complex_derivative; HAS_DERIVATIVE_AT_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN = prove
+ (`!f f' a s.
+         a IN s /\ open s
+         ==> ((f has_complex_derivative f') (at a within s) <=>
+              (f has_complex_derivative f') (at a))`,
+  REWRITE_TAC[has_complex_derivative; HAS_DERIVATIVE_WITHIN_OPEN]);;
+
+let COMPLEX_DIFFERENTIABLE_AT_WITHIN = prove
+ (`!f s z. f complex_differentiable (at z)
+           ==> f complex_differentiable (at z within s)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN = prove
+ (`!f f' g x s d.
+       &0 < d /\ x IN s /\
+       (!x'. x' IN s /\ dist (x',x) < d ==> f x' = g x') /\
+       (f has_complex_derivative f') (at x within s)
+       ==> (g has_complex_derivative f') (at x within s)`,
+  REWRITE_TAC[has_complex_derivative] THEN
+  MESON_TAC[HAS_DERIVATIVE_TRANSFORM_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN_OPEN = prove
+  (`!f g f' s z. open s /\ z IN s /\ (!w. w IN s ==> f w = g w) /\
+                 (f has_complex_derivative f') (at z)
+                 ==> (g has_complex_derivative f') (at z)`,
+   REWRITE_TAC [has_complex_derivative] THEN
+   ASM_MESON_TAC [HAS_DERIVATIVE_TRANSFORM_WITHIN_OPEN]);;
+
+let HAS_COMPLEX_DERIVATIVE_TRANSFORM_AT = prove
+ (`!f f' g x d.
+       &0 < d /\ (!x'. dist (x',x) < d ==> f x' = g x') /\
+       (f has_complex_derivative f') (at x)
+       ==> (g has_complex_derivative f') (at x)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN; IN_UNIV]);;
+
+let HAS_COMPLEX_DERIVATIVE_ZERO_CONSTANT = prove
+ (`!f s.
+        convex s /\
+        (!x. x IN s ==> (f has_complex_derivative Cx(&0)) (at x within s))
+        ==> ?c. !x. x IN s ==> f(x) = c`,
+  REWRITE_TAC[has_complex_derivative; COMPLEX_MUL_LZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_DERIVATIVE_ZERO_CONSTANT]);;
+
+let HAS_COMPLEX_DERIVATIVE_ZERO_UNIQUE = prove
+ (`!f s c a.
+        convex s /\ a IN s /\ f a = c /\
+        (!x. x IN s ==> (f has_complex_derivative Cx(&0)) (at x within s))
+        ==> !x. x IN s ==> f(x) = c`,
+  REWRITE_TAC[has_complex_derivative; COMPLEX_MUL_LZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_DERIVATIVE_ZERO_UNIQUE]);;
+
+let HAS_COMPLEX_DERIVATIVE_ZERO_CONNECTED_CONSTANT = prove
+ (`!f s.
+        open s /\ connected s /\
+        (!x. x IN s ==> (f has_complex_derivative Cx(&0)) (at x))
+        ==> ?c. !x. x IN s ==> f(x) = c`,
+  REWRITE_TAC[has_complex_derivative; COMPLEX_MUL_LZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_DERIVATIVE_ZERO_CONNECTED_CONSTANT]);;
+
+let HAS_COMPLEX_DERIVATIVE_ZERO_CONNECTED_UNIQUE = prove
+ (`!f s c a.
+        open s /\ connected s /\ a IN s /\ f a = c /\
+        (!x. x IN s ==> (f has_complex_derivative Cx(&0)) (at x))
+        ==> !x. x IN s ==> f(x) = c`,
+  REWRITE_TAC[has_complex_derivative; COMPLEX_MUL_LZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_DERIVATIVE_ZERO_CONNECTED_UNIQUE]);;
+
+let COMPLEX_DIFF_CHAIN_WITHIN = prove
+ (`!f g f' g' x s.
+        (f has_complex_derivative f') (at x within s) /\
+        (g has_complex_derivative g') (at (f x) within (IMAGE f s))
+        ==> ((g o f) has_complex_derivative (g' * f'))(at x within s)`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[has_complex_derivative] THEN
+  DISCH_THEN(MP_TAC o MATCH_MP DIFF_CHAIN_WITHIN) THEN
+  REWRITE_TAC[o_DEF; COMPLEX_MUL_ASSOC]);;
+
+let COMPLEX_DIFF_CHAIN_AT = prove
+ (`!f g f' g' x.
+        (f has_complex_derivative f') (at x) /\
+        (g has_complex_derivative g') (at (f x))
+        ==> ((g o f) has_complex_derivative (g' * f')) (at x)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  ASM_MESON_TAC[COMPLEX_DIFF_CHAIN_WITHIN; SUBSET_UNIV;
+                HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET]);;
+
+let HAS_COMPLEX_DERIVATIVE_CHAIN = prove
+ (`!P f g.
+        (!x. P x ==> (g has_complex_derivative g'(x)) (at x))
+        ==> (!x s. (f has_complex_derivative f') (at x within s) /\ P(f x)
+                   ==> ((\x. g(f x)) has_complex_derivative f' * g'(f x))
+                       (at x within s)) /\
+            (!x. (f has_complex_derivative f') (at x) /\ P(f x)
+                 ==> ((\x. g(f x)) has_complex_derivative f' * g'(f x))
+                     (at x))`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM o_DEF] THEN
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  ASM_MESON_TAC[COMPLEX_DIFF_CHAIN_WITHIN; COMPLEX_DIFF_CHAIN_AT;
+                HAS_COMPLEX_DERIVATIVE_AT_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_CHAIN_UNIV = prove
+ (`!f g. (!x. (g has_complex_derivative g'(x)) (at x))
+         ==> (!x s. (f has_complex_derivative f') (at x within s)
+                    ==> ((\x. g(f x)) has_complex_derivative f' * g'(f x))
+                        (at x within s)) /\
+             (!x. (f has_complex_derivative f') (at x)
+                  ==> ((\x. g(f x)) has_complex_derivative f' * g'(f x))
+                      (at x))`,
+  MP_TAC(SPEC `\x:complex. T` HAS_COMPLEX_DERIVATIVE_CHAIN) THEN SIMP_TAC[]);;
+
+let COMPLEX_DERIVATIVE_UNIQUE_AT = prove
+ (`!f z f' f''.
+        (f has_complex_derivative f') (at z) /\
+        (f has_complex_derivative f'') (at z)
+        ==> f' = f''`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[has_complex_derivative] THEN
+  DISCH_THEN(MP_TAC o MATCH_MP FRECHET_DERIVATIVE_UNIQUE_AT) THEN
+  DISCH_THEN(MP_TAC o C AP_THM `Cx(&1)`) THEN
+  REWRITE_TAC[COMPLEX_MUL_RID]);;
+
+let HIGHER_COMPLEX_DERIVATIVE_1 = prove
+ (`!f z. higher_complex_derivative 1 f z = complex_derivative f z`,
+  REWRITE_TAC[num_CONV `1`; higher_complex_derivative]);;
+
+(* ------------------------------------------------------------------------- *)
+(* A more direct characterization.                                           *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_COMPLEX_DERIVATIVE_WITHIN = prove
+ (`!f s a. (f has_complex_derivative f') (at a within s) <=>
+           ((\x. (f(x) - f(a)) / (x - a)) --> f') (at a within s)`,
+  REWRITE_TAC[has_complex_derivative; has_derivative_within] THEN
+  REPEAT GEN_TAC THEN REWRITE_TAC[LINEAR_COMPLEX_MUL] THEN
+  GEN_REWRITE_TAC RAND_CONV [LIM_NULL] THEN
+  REWRITE_TAC[LIM_WITHIN; dist; VECTOR_SUB_RZERO; NORM_MUL] THEN
+  REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN SIMP_TAC[COMPLEX_FIELD
+  `~(x:complex = a) ==> y / (x - a) - z = inv(x - a) * (y - z * (x - a))`] THEN
+  REWRITE_TAC[REAL_ABS_INV; COMPLEX_NORM_MUL; REAL_ABS_NORM;
+         COMPLEX_NORM_INV; VECTOR_ARITH `a:complex - (b + c) = a - b - c`]);;
+
+let HAS_COMPLEX_DERIVATIVE_AT = prove
+ (`!f a. (f has_complex_derivative f') (at a) <=>
+         ((\x. (f(x) - f(a)) / (x - a)) --> f') (at a)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Arithmetical combining theorems.                                          *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_DERIVATIVE_COMPLEX_CMUL = prove
+ (`!net c. ((\x. c * x) has_derivative (\x. c * x)) net`,
+  REPEAT GEN_TAC THEN MATCH_MP_TAC HAS_DERIVATIVE_LINEAR THEN
+  REWRITE_TAC[LINEAR_COMPLEX_MUL]);;
+
+let HAS_COMPLEX_DERIVATIVE_LINEAR = prove
+ (`!net c. ((\x. c * x) has_complex_derivative c) net`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[has_complex_derivative] THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_LINEAR THEN
+  REWRITE_TAC[linear; COMPLEX_CMUL] THEN CONV_TAC COMPLEX_RING);;
+
+let HAS_COMPLEX_DERIVATIVE_LMUL_WITHIN = prove
+ (`!f f' c x s.
+        (f has_complex_derivative f') (at x within s)
+        ==> ((\x. c * f(x)) has_complex_derivative (c * f')) (at x within s)`,
+  REPEAT GEN_TAC THEN
+  MP_TAC(ISPECL [`at ((f:complex->complex) x) within (IMAGE f s)`; `c:complex`]
+    HAS_COMPLEX_DERIVATIVE_LINEAR) THEN
+  ONCE_REWRITE_TAC[TAUT `a ==> b ==> c <=> b /\ a ==> c`] THEN
+  DISCH_THEN(MP_TAC o MATCH_MP COMPLEX_DIFF_CHAIN_WITHIN) THEN
+  REWRITE_TAC[o_DEF]);;
+
+let HAS_COMPLEX_DERIVATIVE_LMUL_AT = prove
+ (`!f f' c x.
+        (f has_complex_derivative f') (at x)
+        ==> ((\x. c * f(x)) has_complex_derivative (c * f')) (at x)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_LMUL_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_RMUL_WITHIN = prove
+ (`!f f' c x s.
+        (f has_complex_derivative f') (at x within s)
+        ==> ((\x. f(x) * c) has_complex_derivative (f' * c)) (at x within s)`,
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_LMUL_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_RMUL_AT = prove
+ (`!f f' c x.
+        (f has_complex_derivative f') (at x)
+        ==> ((\x. f(x) * c) has_complex_derivative (f' * c)) (at x)`,
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_LMUL_AT]);;
+
+let HAS_COMPLEX_DERIVATIVE_CDIV_WITHIN = prove
+ (`!f f' c x s.
+        (f has_complex_derivative f') (at x within s)
+        ==> ((\x. f(x) / c) has_complex_derivative (f' / c)) (at x within s)`,
+  SIMP_TAC[complex_div; HAS_COMPLEX_DERIVATIVE_RMUL_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_CDIV_AT = prove
+ (`!f f' c x s.
+        (f has_complex_derivative f') (at x)
+        ==> ((\x. f(x) / c) has_complex_derivative (f' / c)) (at x)`,
+  SIMP_TAC[complex_div; HAS_COMPLEX_DERIVATIVE_RMUL_AT]);;
+
+let HAS_COMPLEX_DERIVATIVE_ID = prove
+ (`!net. ((\x. x) has_complex_derivative Cx(&1)) net`,
+  REWRITE_TAC[has_complex_derivative; HAS_DERIVATIVE_ID; COMPLEX_MUL_LID]);;
+
+let HAS_COMPLEX_DERIVATIVE_CONST = prove
+ (`!c net. ((\x. c) has_complex_derivative Cx(&0)) net`,
+  REWRITE_TAC[has_complex_derivative; COMPLEX_MUL_LZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_DERIVATIVE_CONST]);;
+
+let HAS_COMPLEX_DERIVATIVE_NEG = prove
+ (`!f f' net. (f has_complex_derivative f') net
+            ==> ((\x. --(f(x))) has_complex_derivative (--f')) net`,
+  SIMP_TAC[has_complex_derivative; COMPLEX_MUL_LNEG; HAS_DERIVATIVE_NEG]);;
+
+let HAS_COMPLEX_DERIVATIVE_ADD = prove
+ (`!f f' g g' net.
+        (f has_complex_derivative f') net /\ (g has_complex_derivative g') net
+        ==> ((\x. f(x) + g(x)) has_complex_derivative (f' + g')) net`,
+  SIMP_TAC[has_complex_derivative; COMPLEX_ADD_RDISTRIB; HAS_DERIVATIVE_ADD]);;
+
+let HAS_COMPLEX_DERIVATIVE_SUB = prove
+ (`!f f' g g' net.
+        (f has_complex_derivative f') net /\ (g has_complex_derivative g') net
+        ==> ((\x. f(x) - g(x)) has_complex_derivative (f' - g')) net`,
+  SIMP_TAC[has_complex_derivative; COMPLEX_SUB_RDISTRIB; HAS_DERIVATIVE_SUB]);;
+
+let HAS_COMPLEX_DERIVATIVE_MUL_WITHIN = prove
+ (`!f f' g g' x s.
+        (f has_complex_derivative f') (at x within s) /\
+        (g has_complex_derivative g') (at x within s)
+        ==> ((\x. f(x) * g(x)) has_complex_derivative
+             (f(x) * g' + f' * g(x))) (at x within s)`,
+  REPEAT GEN_TAC THEN SIMP_TAC[has_complex_derivative] THEN
+  DISCH_THEN(MP_TAC o C CONJ BILINEAR_COMPLEX_MUL) THEN
+  REWRITE_TAC[GSYM CONJ_ASSOC] THEN
+  DISCH_THEN(MP_TAC o MATCH_MP HAS_DERIVATIVE_BILINEAR_WITHIN) THEN
+  MATCH_MP_TAC EQ_IMP THEN
+  AP_THM_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN
+  CONV_TAC COMPLEX_RING);;
+
+let HAS_COMPLEX_DERIVATIVE_MUL_AT = prove
+ (`!f f' g g' x.
+        (f has_complex_derivative f') (at x) /\
+        (g has_complex_derivative g') (at x)
+        ==> ((\x. f(x) * g(x)) has_complex_derivative
+             (f(x) * g' + f' * g(x))) (at x)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_MUL_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_POW_WITHIN = prove
+ (`!f f' x s n. (f has_complex_derivative f') (at x within s)
+                ==> ((\x. f(x) pow n) has_complex_derivative
+                     (Cx(&n) * f(x) pow (n - 1) * f')) (at x within s)`,
+  REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
+  INDUCT_TAC THEN REWRITE_TAC[complex_pow] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_CONST; COMPLEX_MUL_LZERO] THEN
+  POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN
+  DISCH_THEN(MP_TAC o MATCH_MP HAS_COMPLEX_DERIVATIVE_MUL_WITHIN) THEN
+  REWRITE_TAC[SUC_SUB1] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN
+  BINOP_TAC THEN REWRITE_TAC[COMPLEX_MUL_AC; GSYM REAL_OF_NUM_SUC] THEN
+  SPEC_TAC(`n:num`,`n:num`) THEN REWRITE_TAC[CX_ADD] THEN INDUCT_TAC THEN
+  CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[SUC_SUB1; complex_pow] THEN
+  CONV_TAC COMPLEX_FIELD);;
+
+let HAS_COMPLEX_DERIVATIVE_POW_AT = prove
+ (`!f f' x n. (f has_complex_derivative f') (at x)
+              ==> ((\x. f(x) pow n) has_complex_derivative
+                   (Cx(&n) * f(x) pow (n - 1) * f')) (at x)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_POW_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_INV_BASIC = prove
+ (`!x. ~(x = Cx(&0))
+         ==> ((inv) has_complex_derivative (--inv(x pow 2))) (at x)`,
+  REPEAT STRIP_TAC THEN
+  REWRITE_TAC[has_complex_derivative; has_derivative_at] THEN
+  REWRITE_TAC[LINEAR_COMPLEX_MUL; COMPLEX_VEC_0] THEN
+  MATCH_MP_TAC LIM_TRANSFORM_AWAY_AT THEN
+  MAP_EVERY EXISTS_TAC
+   [`\y. inv(norm(y - x)) % inv(x pow 2 * y) * (y - x) pow 2`; `Cx(&0)`] THEN
+  ASM_REWRITE_TAC[COMPLEX_CMUL] THEN CONJ_TAC THENL
+   [POP_ASSUM MP_TAC THEN CONV_TAC COMPLEX_FIELD; ALL_TAC] THEN
+  SUBGOAL_THEN `((\y. inv(x pow 2 * y) * (y - x)) --> Cx(&0)) (at x)`
+  MP_TAC THENL
+   [LIM_TAC THEN POP_ASSUM MP_TAC THEN CONV_TAC COMPLEX_FIELD; ALL_TAC] THEN
+  MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[LIM_AT] THEN
+  REWRITE_TAC[dist; COMPLEX_SUB_RZERO] THEN
+  REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_INV; COMPLEX_NORM_POW] THEN
+  REWRITE_TAC[COMPLEX_NORM_CX; REAL_ABS_INV; REAL_ABS_NORM] THEN
+  REPLICATE_TAC 2 (AP_TERM_TAC THEN ABS_TAC THEN AP_TERM_TAC) THEN
+  AP_TERM_TAC THEN ABS_TAC THEN
+  MATCH_MP_TAC(MESON[]
+   `(p ==> x = y) ==> ((p ==> x < e) <=> (p ==> y < e))`) THEN
+  MAP_EVERY ABBREV_TAC
+   [`n = norm(x' - x:complex)`;
+    `m = inv (norm(x:complex) pow 2 * norm(x':complex))`] THEN
+  CONV_TAC REAL_FIELD);;
+
+let HAS_COMPLEX_DERIVATIVE_INV_WITHIN = prove
+ (`!f f' x s. (f has_complex_derivative f') (at x within s) /\
+              ~(f x = Cx(&0))
+              ==> ((\x. inv(f(x))) has_complex_derivative (--f' / f(x) pow 2))
+                  (at x within s)`,
+  REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN
+  ASM_SIMP_TAC[COMPLEX_FIELD
+   `~(g = Cx(&0)) ==> --f / g pow 2 = --inv(g pow 2) * f`] THEN
+  MATCH_MP_TAC COMPLEX_DIFF_CHAIN_WITHIN THEN ASM_REWRITE_TAC[] THEN
+  MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN
+  ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_INV_BASIC]);;
+
+let HAS_COMPLEX_DERIVATIVE_INV_AT = prove
+ (`!f f' x. (f has_complex_derivative f') (at x) /\
+            ~(f x = Cx(&0))
+            ==> ((\x. inv(f(x))) has_complex_derivative (--f' / f(x) pow 2))
+                (at x)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_INV_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_DIV_WITHIN = prove
+ (`!f f' g g' x s.
+        (f has_complex_derivative f') (at x within s) /\
+        (g has_complex_derivative g') (at x within s) /\
+        ~(g(x) = Cx(&0))
+        ==> ((\x. f(x) / g(x)) has_complex_derivative
+             (f' * g(x) - f(x) * g') / g(x) pow 2) (at 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_COMPLEX_DERIVATIVE_INV_WITHIN) THEN
+  UNDISCH_TAC `(f has_complex_derivative f') (at x within s)` THEN
+  REWRITE_TAC[IMP_IMP] THEN
+  DISCH_THEN(MP_TAC o MATCH_MP HAS_COMPLEX_DERIVATIVE_MUL_WITHIN) THEN
+  REWRITE_TAC[GSYM complex_div] THEN MATCH_MP_TAC EQ_IMP THEN
+  AP_THM_TAC THEN AP_TERM_TAC THEN
+  POP_ASSUM MP_TAC THEN CONV_TAC COMPLEX_FIELD);;
+
+let HAS_COMPLEX_DERIVATIVE_DIV_AT = prove
+ (`!f f' g g' x.
+        (f has_complex_derivative f') (at x) /\
+        (g has_complex_derivative g') (at x) /\
+        ~(g(x) = Cx(&0))
+        ==> ((\x. f(x) / g(x)) has_complex_derivative
+             (f' * g(x) - f(x) * g') / g(x) pow 2) (at x)`,
+  ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
+  REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_DIV_WITHIN]);;
+
+let HAS_COMPLEX_DERIVATIVE_VSUM = prove
+ (`!f net s.
+         FINITE s /\ (!a. a IN s ==> (f a has_complex_derivative f' a) net)
+         ==> ((\x. vsum s (\a. f a x)) has_complex_derivative (vsum s f'))
+             net`,
+  SIMP_TAC[GSYM VSUM_COMPLEX_RMUL; has_complex_derivative] THEN
+  REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP HAS_DERIVATIVE_VSUM) THEN
+  REWRITE_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Same thing just for complex differentiability.                            *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_DIFFERENTIABLE_LINEAR = prove
+ (`(\z. c * z) complex_differentiable p`,
+  REWRITE_TAC [complex_differentiable] THEN
+  MESON_TAC [HAS_COMPLEX_DERIVATIVE_LINEAR]);;
+
+let COMPLEX_DIFFERENTIABLE_CONST = prove
+ (`!c net. (\z. c) complex_differentiable net`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_CONST]);;
+
+let COMPLEX_DIFFERENTIABLE_ID = prove
+ (`!net. (\z. z) complex_differentiable net`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_ID]);;
+
+let COMPLEX_DIFFERENTIABLE_NEG = prove
+ (`!f net.
+        f complex_differentiable net
+        ==> (\z. --(f z)) complex_differentiable net`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_NEG]);;
+
+let COMPLEX_DIFFERENTIABLE_ADD = prove
+ (`!f g net.
+        f complex_differentiable net /\
+        g complex_differentiable net
+        ==> (\z. f z + g z) complex_differentiable net`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_ADD]);;
+
+let COMPLEX_DIFFERENTIABLE_SUB = prove
+ (`!f g net.
+        f complex_differentiable net /\
+        g complex_differentiable net
+        ==> (\z. f z - g z) complex_differentiable net`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_SUB]);;
+
+let COMPLEX_DIFFERENTIABLE_INV_WITHIN = prove
+ (`!f z s.
+        f complex_differentiable (at z within s) /\ ~(f z = Cx(&0))
+        ==> (\z. inv(f z)) complex_differentiable (at z within s)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_INV_WITHIN]);;
+
+let COMPLEX_DIFFERENTIABLE_MUL_WITHIN = prove
+ (`!f g z s.
+        f complex_differentiable (at z within s) /\
+        g complex_differentiable (at z within s)
+        ==> (\z. f z * g z) complex_differentiable (at z within s)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_MUL_WITHIN]);;
+
+let COMPLEX_DIFFERENTIABLE_DIV_WITHIN = prove
+ (`!f g z s.
+        f complex_differentiable (at z within s) /\
+        g complex_differentiable (at z within s) /\
+        ~(g z = Cx(&0))
+        ==> (\z. f z / g z) complex_differentiable (at z within s)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_DIV_WITHIN]);;
+
+let COMPLEX_DIFFERENTIABLE_POW_WITHIN = prove
+ (`!f n z s.
+        f complex_differentiable (at z within s)
+        ==> (\z. f z pow n) complex_differentiable (at z within s)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_POW_WITHIN]);;
+
+let COMPLEX_DIFFERENTIABLE_TRANSFORM_WITHIN = prove
+ (`!f g x s d.
+        &0 < d /\
+        x IN s /\
+        (!x'. x' IN s /\ dist (x',x) < d ==> f x' = g x') /\
+        f complex_differentiable (at x within s)
+        ==> g complex_differentiable (at x within s)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN]);;
+
+let HOLOMORPHIC_TRANSFORM = prove
+ (`!f g s. (!x. x IN s ==> f x = g x) /\ f holomorphic_on s
+           ==> g holomorphic_on s`,
+  REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  REWRITE_TAC[holomorphic_on; GSYM complex_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 COMPLEX_DIFFERENTIABLE_TRANSFORM_WITHIN THEN
+  MAP_EVERY EXISTS_TAC [`f:complex->complex`; `&1`] THEN
+  ASM_SIMP_TAC[REAL_LT_01]);;
+
+let HOLOMORPHIC_EQ = prove
+ (`!f g s. (!x. x IN s ==> f x = g x)
+           ==> (f holomorphic_on s <=> g holomorphic_on s)`,
+  MESON_TAC[HOLOMORPHIC_TRANSFORM]);;
+
+let COMPLEX_DIFFERENTIABLE_INV_AT = prove
+ (`!f z.
+        f complex_differentiable at z /\ ~(f z = Cx(&0))
+        ==> (\z. inv(f z)) complex_differentiable at z`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_INV_AT]);;
+
+let COMPLEX_DIFFERENTIABLE_MUL_AT = prove
+ (`!f g z.
+        f complex_differentiable at z /\
+        g complex_differentiable at z
+        ==> (\z. f z * g z) complex_differentiable at z`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_MUL_AT]);;
+
+let COMPLEX_DIFFERENTIABLE_DIV_AT = prove
+ (`!f g z.
+        f complex_differentiable at z /\
+        g complex_differentiable at z /\
+        ~(g z = Cx(&0))
+        ==> (\z. f z / g z) complex_differentiable at z`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_DIV_AT]);;
+
+let COMPLEX_DIFFERENTIABLE_POW_AT = prove
+ (`!f n z.
+        f complex_differentiable at z
+        ==> (\z. f z pow n) complex_differentiable at z`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_POW_AT]);;
+
+let COMPLEX_DIFFERENTIABLE_TRANSFORM_AT = prove
+ (`!f g x d.
+        &0 < d /\
+        (!x'. dist (x',x) < d ==> f x' = g x') /\
+        f complex_differentiable at x
+        ==> g complex_differentiable at x`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_TRANSFORM_AT]);;
+
+let COMPLEX_DIFFERENTIABLE_COMPOSE_WITHIN = prove
+ (`!f g x s.
+         f complex_differentiable (at x within s) /\
+         g complex_differentiable (at (f x) within IMAGE f s)
+         ==> (g o f) complex_differentiable (at x within s)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[COMPLEX_DIFF_CHAIN_WITHIN]);;
+
+let COMPLEX_DIFFERENTIABLE_COMPOSE_AT = prove
+ (`!f g x s.
+         f complex_differentiable (at x) /\
+         g complex_differentiable (at (f x))
+         ==> (g o f) complex_differentiable (at x)`,
+  REWRITE_TAC[complex_differentiable] THEN
+  MESON_TAC[COMPLEX_DIFF_CHAIN_AT]);;
+
+let COMPLEX_DIFFERENTIABLE_WITHIN_OPEN = prove
+ (`!f a s.
+        a IN s /\ open s
+        ==> (f complex_differentiable at a within s <=>
+             f complex_differentiable at a)`,
+  SIMP_TAC[complex_differentiable; HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Same again for being holomorphic on a set.                                *)
+(* ------------------------------------------------------------------------- *)
+
+let HOLOMORPHIC_ON_LINEAR = prove
+ (`!s c. (\w. c * w) holomorphic_on s`,
+  REWRITE_TAC [holomorphic_on] THEN
+  MESON_TAC [HAS_COMPLEX_DERIVATIVE_LINEAR]);;
+
+let HOLOMORPHIC_ON_CONST = prove
+ (`!c s. (\z. c) holomorphic_on s`,
+  REWRITE_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_CONST]);;
+
+let HOLOMORPHIC_ON_ID = prove
+ (`!s. (\z. z) holomorphic_on s`,
+  REWRITE_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_ID]);;
+
+let HOLOMORPHIC_ON_COMPOSE = prove
+ (`!f g s. f holomorphic_on s /\ g holomorphic_on (IMAGE f s)
+           ==> (g o f) holomorphic_on s`,
+  SIMP_TAC[holomorphic_on; GSYM complex_differentiable; FORALL_IN_IMAGE] THEN
+  MESON_TAC[COMPLEX_DIFFERENTIABLE_COMPOSE_WITHIN]);;
+
+let HOLOMORPHIC_ON_NEG = prove
+ (`!f s. f holomorphic_on s ==> (\z. --(f z)) holomorphic_on s`,
+  SIMP_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_NEG]);;
+
+let HOLOMORPHIC_ON_ADD = prove
+ (`!f g s.
+        f holomorphic_on s /\ g holomorphic_on s
+        ==> (\z. f z + g z) holomorphic_on s`,
+  SIMP_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_ADD]);;
+
+let HOLOMORPHIC_ON_SUB = prove
+ (`!f g s.
+        f holomorphic_on s /\ g holomorphic_on s
+        ==> (\z. f z - g z) holomorphic_on s`,
+  SIMP_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_SUB]);;
+
+let HOLOMORPHIC_ON_MUL = prove
+ (`!f g s.
+        f holomorphic_on s /\ g holomorphic_on s
+        ==> (\z. f z * g z) holomorphic_on s`,
+  SIMP_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_MUL_WITHIN]);;
+
+let HOLOMORPHIC_ON_INV = prove
+ (`!f s. f holomorphic_on s /\ (!z. z IN s ==> ~(f z = Cx(&0)))
+         ==> (\z. inv(f z)) holomorphic_on s`,
+  SIMP_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_INV_WITHIN]);;
+
+let HOLOMORPHIC_ON_DIV = prove
+ (`!f g s.
+        f holomorphic_on s /\ g holomorphic_on s /\
+        (!z. z IN s ==> ~(g z = Cx(&0)))
+        ==> (\z. f z / g z) holomorphic_on s`,
+  SIMP_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_DIV_WITHIN]);;
+
+let HOLOMORPHIC_ON_POW = prove
+ (`!f s n. f holomorphic_on s ==> (\z. (f z) pow n) holomorphic_on s`,
+  SIMP_TAC[HOLOMORPHIC_ON_DIFFERENTIABLE; COMPLEX_DIFFERENTIABLE_POW_WITHIN]);;
+
+let HOLOMORPHIC_ON_VSUM = prove
+ (`!f s k. FINITE k /\ (!a. a IN k ==> (f a) holomorphic_on s)
+           ==> (\x. vsum k (\a. f a x)) holomorphic_on s`,
+  GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
+  MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[VSUM_CLAUSES] THEN
+  SIMP_TAC[HOLOMORPHIC_ON_CONST; IN_INSERT; NOT_IN_EMPTY] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HOLOMORPHIC_ON_ADD THEN
+  ASM_SIMP_TAC[ETA_AX]);;
+
+let HOLOMORPHIC_ON_COMPOSE_GEN = prove
+ (`!f g s t. f holomorphic_on s /\ g holomorphic_on t /\
+             (!z. z IN s ==> f z IN t)
+             ==>  g o f holomorphic_on s`,
+  REWRITE_TAC [holomorphic_on] THEN REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN `IMAGE (f:complex->complex) s SUBSET t` MP_TAC THENL
+   [ASM SET_TAC []; ASM_MESON_TAC [HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET;
+                                   COMPLEX_DIFF_CHAIN_WITHIN]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Same again for the actual derivative function.                            *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_COMPLEX_DERIVATIVE_DERIVATIVE = prove
+ (`!f f' x. (f has_complex_derivative f') (at x)
+                ==> complex_derivative f x = f'`,
+  REWRITE_TAC[complex_derivative] THEN
+  MESON_TAC[COMPLEX_DERIVATIVE_UNIQUE_AT]);;
+
+let HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE = prove
+ (`!f x. (f has_complex_derivative (complex_derivative f x)) (at x) <=>
+         f complex_differentiable at x`,
+  REWRITE_TAC[complex_differentiable; complex_derivative] THEN MESON_TAC[]);;
+
+let COMPLEX_DIFFERENTIABLE_COMPOSE = prove
+ (`!f g z. f complex_differentiable at z /\ g complex_differentiable at (f z)
+          ==> (g o f) complex_differentiable at z`,
+  REWRITE_TAC [complex_differentiable] THEN
+  MESON_TAC [COMPLEX_DIFF_CHAIN_AT]);;
+
+let COMPLEX_DERIVATIVE_CHAIN = prove
+ (`!f g z. f complex_differentiable at z /\ g complex_differentiable at (f z)
+           ==> complex_derivative (g o f) z =
+               complex_derivative g (f z) * complex_derivative f z`,
+  MESON_TAC [HAS_COMPLEX_DERIVATIVE_DERIVATIVE; COMPLEX_DIFF_CHAIN_AT;
+             HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE]);;
+
+let COMPLEX_DERIVATIVE_LINEAR = prove
+ (`!c. complex_derivative (\w. c * w) = \z. c`,
+  REWRITE_TAC [FUN_EQ_THM] THEN REPEAT GEN_TAC THEN
+  MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_DERIVATIVE THEN
+  REWRITE_TAC [HAS_COMPLEX_DERIVATIVE_LINEAR]);;
+
+let COMPLEX_DERIVATIVE_ID = prove
+ (`complex_derivative (\w.w) = \z. Cx(&1)`,
+  REWRITE_TAC [FUN_EQ_THM] THEN
+  MESON_TAC [HAS_COMPLEX_DERIVATIVE_DERIVATIVE; HAS_COMPLEX_DERIVATIVE_ID]);;
+
+let COMPLEX_DERIVATIVE_CONST = prove
+ (`!c. complex_derivative (\w.c) = \z. Cx(&0)`,
+  REWRITE_TAC [FUN_EQ_THM] THEN
+  MESON_TAC [HAS_COMPLEX_DERIVATIVE_DERIVATIVE;
+             HAS_COMPLEX_DERIVATIVE_CONST]);;
+
+let COMPLEX_DERIVATIVE_ADD = prove
+ (`!f g z. f complex_differentiable at z /\ g complex_differentiable at z
+           ==> complex_derivative (\w. f w + g w) z =
+               complex_derivative f z + complex_derivative g z`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_DERIVATIVE THEN
+  ASM_SIMP_TAC [HAS_COMPLEX_DERIVATIVE_ADD;
+                HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE]);;
+
+let COMPLEX_DERIVATIVE_SUB = prove
+ (`!f g z. f complex_differentiable at z /\ g complex_differentiable at z
+           ==> complex_derivative (\w. f w - g w) z =
+               complex_derivative f z - complex_derivative g z`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_DERIVATIVE THEN
+  ASM_SIMP_TAC [HAS_COMPLEX_DERIVATIVE_SUB;
+                HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE]);;
+
+let COMPLEX_DERIVATIVE_MUL = prove
+ (`!f g z. f complex_differentiable at z /\ g complex_differentiable at z
+           ==> complex_derivative (\w. f w * g w) z =
+               f z * complex_derivative g z + complex_derivative f z * g z`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_DERIVATIVE THEN
+  ASM_SIMP_TAC [HAS_COMPLEX_DERIVATIVE_MUL_AT;
+                HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE]);;
+
+let COMPLEX_DERIVATIVE_LMUL = prove
+ (`!f c z. f complex_differentiable at z
+             ==> complex_derivative (\w. c * f w) z =
+                 c * complex_derivative f z`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_DERIVATIVE THEN
+  ASM_SIMP_TAC [HAS_COMPLEX_DERIVATIVE_LMUL_AT;
+                HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE]);;
+
+let COMPLEX_DERIVATIVE_RMUL = prove
+ (`!f c z. f complex_differentiable at z
+           ==> complex_derivative (\w. f w * c) z =
+               complex_derivative f z * c`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_DERIVATIVE THEN
+  ASM_SIMP_TAC [HAS_COMPLEX_DERIVATIVE_RMUL_AT;
+                HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE]);;
+
+let COMPLEX_DERIVATIVE_TRANSFORM_WITHIN_OPEN = prove
+ (`!f g s z. open s /\ f holomorphic_on s /\ g holomorphic_on s /\ z IN s /\
+             (!w. w IN s ==> f w = g w)
+             ==> complex_derivative f z = complex_derivative g z`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC COMPLEX_DERIVATIVE_UNIQUE_AT THEN
+  ASM_MESON_TAC[HAS_COMPLEX_DERIVATIVE_TRANSFORM_WITHIN_OPEN;
+                HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_AT;
+                HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE]);;
+
+let COMPLEX_DERIVATIVE_COMPOSE_LINEAR = prove
+ (`!f c z. f complex_differentiable at (c * z)
+           ==> complex_derivative (\w. f (c * w)) z =
+               c * complex_derivative f (c * z)`,
+  SIMP_TAC
+    [COMPLEX_MUL_SYM; REWRITE_RULE [o_DEF; COMPLEX_DIFFERENTIABLE_ID;
+                   COMPLEX_DIFFERENTIABLE_LINEAR;
+                   COMPLEX_DERIVATIVE_LINEAR]
+     (SPECL [`\w:complex. c * w`] COMPLEX_DERIVATIVE_CHAIN)]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Caratheodory characterization.                                            *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_COMPLEX_DERIVATIVE_CARATHEODORY_AT = prove
+ (`!f f' z.
+        (f has_complex_derivative f') (at z) <=>
+        ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\
+            g continuous at z /\ g(z) = f'`,
+  REPEAT GEN_TAC THEN
+  REWRITE_TAC[COMPLEX_RING `w' - z':complex = a <=> w' = z' + a`] THEN
+  SIMP_TAC[GSYM FUN_EQ_THM; HAS_COMPLEX_DERIVATIVE_AT; CONTINUOUS_AT] THEN
+  EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THENL
+   [EXISTS_TAC `\w. if w = z then f':complex else (f(w) - f(z)) / (w - z)` THEN
+    ASM_SIMP_TAC[FUN_EQ_THM; COND_RAND; COND_RATOR; COMPLEX_SUB_REFL] THEN
+    CONV_TAC COMPLEX_FIELD;
+    FIRST_X_ASSUM SUBST_ALL_TAC THEN FIRST_X_ASSUM SUBST1_TAC THEN
+    ASM_SIMP_TAC[COMPLEX_RING `(z + a) - (z + b * (w - w)):complex = a`] THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
+      LIM_TRANSFORM)) THEN
+    SIMP_TAC[LIM_CONST; COMPLEX_VEC_0; COMPLEX_FIELD
+     `~(w = z) ==> x - (x * (w - z)) / (w - z) = Cx(&0)`]]);;
+
+let HAS_COMPLEX_DERIVATIVE_CARATHEODORY_WITHIN = prove
+ (`!f f' z s.
+        (f has_complex_derivative f') (at z within s) <=>
+        ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\
+            g continuous (at z within s) /\ g(z) = f'`,
+  REPEAT GEN_TAC THEN
+  REWRITE_TAC[COMPLEX_RING `w' - z':complex = a <=> w' = z' + a`] THEN
+  SIMP_TAC[GSYM FUN_EQ_THM; HAS_COMPLEX_DERIVATIVE_WITHIN;
+           CONTINUOUS_WITHIN] THEN
+  EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THENL
+   [EXISTS_TAC `\w. if w = z then f':complex else (f(w) - f(z)) / (w - z)` THEN
+    ASM_SIMP_TAC[FUN_EQ_THM; COND_RAND; COND_RATOR; COMPLEX_SUB_REFL] THEN
+    CONV_TAC COMPLEX_FIELD;
+    FIRST_X_ASSUM SUBST_ALL_TAC THEN FIRST_X_ASSUM SUBST1_TAC THEN
+    ASM_SIMP_TAC[COMPLEX_RING `(z + a) - (z + b * (w - w)):complex = a`] THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
+      LIM_TRANSFORM)) THEN
+    SIMP_TAC[LIM_CONST; COMPLEX_VEC_0; COMPLEX_FIELD
+     `~(w = z) ==> x - (x * (w - z)) / (w - z) = Cx(&0)`]]);;
+
+let COMPLEX_DIFFERENTIABLE_CARATHEODORY_AT = prove
+ (`!f z. f complex_differentiable at z <=>
+         ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\ g continuous at z`,
+  SIMP_TAC[complex_differentiable; HAS_COMPLEX_DERIVATIVE_CARATHEODORY_AT] THEN
+  MESON_TAC[]);;
+
+let COMPLEX_DIFFERENTIABLE_CARATHEODORY_WITHIN = prove
+ (`!f z s.
+      f complex_differentiable (at z within s) <=>
+      ?g. (!w. f(w) - f(z) = g(w) * (w - z)) /\ g continuous (at z within s)`,
+  SIMP_TAC[complex_differentiable;
+           HAS_COMPLEX_DERIVATIVE_CARATHEODORY_WITHIN] THEN
+  MESON_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* A slightly stronger, more traditional notion of analyticity on a set.     *)
+(* ------------------------------------------------------------------------- *)
+
+parse_as_infix ("analytic_on",(12,"right"));;
+
+let analytic_on = new_definition
+ `f analytic_on s <=>
+      !x. x IN s ==> ?e. &0 < e /\ f holomorphic_on ball(x,e)`;;
+
+let ANALYTIC_IMP_HOLOMORPHIC = prove
+ (`!f s. f analytic_on s ==> f holomorphic_on s`,
+  REWRITE_TAC[analytic_on; holomorphic_on] THEN
+  SIMP_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL] THEN
+  MESON_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN; CENTRE_IN_BALL]);;
+
+let ANALYTIC_ON_OPEN = prove
+ (`!f s. open s ==> (f analytic_on s <=> f holomorphic_on s)`,
+  REPEAT STRIP_TAC THEN EQ_TAC THEN REWRITE_TAC[ANALYTIC_IMP_HOLOMORPHIC] THEN
+  REWRITE_TAC[analytic_on; holomorphic_on] THEN
+  ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL] THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
+  REWRITE_TAC[SUBSET] THEN MESON_TAC[CENTRE_IN_BALL]);;
+
+let ANALYTIC_ON_IMP_DIFFERENTIABLE_AT = prove
+ (`!f s x. f analytic_on s /\ x IN s ==> f complex_differentiable (at x)`,
+  SIMP_TAC[analytic_on; HOLOMORPHIC_ON_OPEN; OPEN_BALL;
+           complex_differentiable] THEN
+  MESON_TAC[CENTRE_IN_BALL]);;
+
+let ANALYTIC_ON_SUBSET = prove
+ (`!f s t. f analytic_on s /\ t SUBSET s ==> f analytic_on t`,
+  REWRITE_TAC[analytic_on; SUBSET] THEN MESON_TAC[]);;
+
+let ANALYTIC_ON_UNION = prove
+ (`!f s t. f analytic_on (s UNION t) <=> f analytic_on s /\ f analytic_on t`,
+  REWRITE_TAC [analytic_on; IN_UNION] THEN MESON_TAC[]);;
+
+let ANALYTIC_ON_UNIONS = prove
+ (`!f s. f analytic_on (UNIONS s) <=> (!t. t IN s ==> f analytic_on t)`,
+  REWRITE_TAC [analytic_on; IN_UNIONS] THEN MESON_TAC[]);;
+
+let ANALYTIC_ON_HOLOMORPHIC = prove
+ (`!f s. f analytic_on s <=> ?t. open t /\ s SUBSET t /\ f holomorphic_on t`,
+  REPEAT GEN_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
+  EXISTS_TAC `?t. open t /\ s SUBSET t /\ f analytic_on t` THEN CONJ_TAC THENL
+   [EQ_TAC THENL
+    [DISCH_TAC THEN EXISTS_TAC `UNIONS {u | open u /\ f analytic_on u}` THEN
+     SIMP_TAC [IN_ELIM_THM; OPEN_UNIONS; ANALYTIC_ON_UNIONS] THEN
+     REWRITE_TAC [SUBSET; IN_UNIONS; IN_ELIM_THM] THEN
+     ASM_MESON_TAC [analytic_on; ANALYTIC_ON_OPEN; OPEN_BALL; CENTRE_IN_BALL];
+     MESON_TAC [ANALYTIC_ON_SUBSET]];
+    MESON_TAC [ANALYTIC_ON_OPEN]]);;
+
+let ANALYTIC_ON_LINEAR = prove
+ (`!s c. (\w. c * w) analytic_on s`,
+  REPEAT GEN_TAC THEN
+  REWRITE_TAC [ANALYTIC_ON_HOLOMORPHIC; HOLOMORPHIC_ON_LINEAR] THEN
+  EXISTS_TAC `(:complex)` THEN REWRITE_TAC [OPEN_UNIV; SUBSET_UNIV]);;
+
+let ANALYTIC_ON_CONST = prove
+ (`!c s. (\z. c) analytic_on s`,
+  REWRITE_TAC[analytic_on; HOLOMORPHIC_ON_CONST] THEN MESON_TAC[REAL_LT_01]);;
+
+let ANALYTIC_ON_ID = prove
+ (`!s. (\z. z) analytic_on s`,
+  REWRITE_TAC[analytic_on; HOLOMORPHIC_ON_ID] THEN MESON_TAC[REAL_LT_01]);;
+
+let ANALYTIC_ON_COMPOSE = prove
+ (`!f g s. f analytic_on s /\ g analytic_on (IMAGE f s)
+           ==> (g o f) analytic_on s`,
+  REWRITE_TAC[analytic_on; FORALL_IN_IMAGE] THEN REPEAT GEN_TAC THEN
+  DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "f") (LABEL_TAC "g")) THEN
+  X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+  REMOVE_THEN "f" (MP_TAC o SPEC `z:complex`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
+  FIRST_ASSUM(MP_TAC o MATCH_MP HOLOMORPHIC_ON_IMP_CONTINUOUS_ON) THEN
+  SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT; OPEN_BALL] THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN
+  ASM_REWRITE_TAC[CENTRE_IN_BALL; CONTINUOUS_AT_BALL] THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `z:complex`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
+  DISCH_THEN(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:real) k` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
+  MATCH_MP_TAC HOLOMORPHIC_ON_COMPOSE THEN
+  CONJ_TAC THEN MATCH_MP_TAC HOLOMORPHIC_ON_SUBSET THENL
+   [EXISTS_TAC `ball(z:complex,d)`;
+    EXISTS_TAC `ball((f:complex->complex) z,e)`] THEN
+  ASM_REWRITE_TAC[BALL_MIN_INTER; INTER_SUBSET] THEN ASM SET_TAC[]);;
+
+let ANALYTIC_ON_COMPOSE_GEN = prove
+ (`!f g s t. f analytic_on s /\ g analytic_on t /\ (!z. z IN s ==> f z IN t)
+             ==> g o f analytic_on s`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC ANALYTIC_ON_COMPOSE THEN
+  ASM_REWRITE_TAC[] THEN MATCH_MP_TAC ANALYTIC_ON_SUBSET THEN ASM SET_TAC[]);;
+
+let ANALYTIC_ON_NEG = prove
+ (`!f s. f analytic_on s ==> (\z. --(f z)) analytic_on s`,
+  SIMP_TAC[analytic_on] THEN MESON_TAC[HOLOMORPHIC_ON_NEG]);;
+
+let ANALYTIC_ON_ADD = prove
+ (`!f g s.
+        f analytic_on s /\ g analytic_on s ==> (\z. f z + g z) analytic_on s`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[analytic_on] THEN
+  REWRITE_TAC[AND_FORALL_THM] 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_THEN(CONJUNCTS_THEN2
+   (X_CHOOSE_TAC `d:real`) (X_CHOOSE_TAC `e:real`)) THEN
+  EXISTS_TAC `min (d:real) e` THEN
+  ASM_REWRITE_TAC[REAL_LT_MIN; BALL_MIN_INTER; IN_INTER] THEN
+  MATCH_MP_TAC HOLOMORPHIC_ON_ADD THEN
+  ASM_MESON_TAC[HOLOMORPHIC_ON_SUBSET; INTER_SUBSET]);;
+
+let ANALYTIC_ON_SUB = prove
+ (`!f g s.
+        f analytic_on s /\ g analytic_on s ==> (\z. f z - g z) analytic_on s`,
+  SIMP_TAC[complex_sub; ANALYTIC_ON_ADD; ANALYTIC_ON_NEG]);;
+
+let ANALYTIC_ON_MUL = prove
+ (`!f g s.
+        f analytic_on s /\ g analytic_on s ==> (\z. f z * g z) analytic_on s`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[analytic_on] THEN
+  REWRITE_TAC[AND_FORALL_THM] 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_THEN(CONJUNCTS_THEN2
+   (X_CHOOSE_TAC `d:real`) (X_CHOOSE_TAC `e:real`)) THEN
+  EXISTS_TAC `min (d:real) e` THEN
+  ASM_REWRITE_TAC[REAL_LT_MIN; BALL_MIN_INTER; IN_INTER] THEN
+  MATCH_MP_TAC HOLOMORPHIC_ON_MUL THEN
+  ASM_MESON_TAC[HOLOMORPHIC_ON_SUBSET; INTER_SUBSET]);;
+
+let ANALYTIC_ON_INV = prove
+ (`!f s. f analytic_on s /\ (!z. z IN s ==> ~(f z = Cx(&0)))
+         ==> (\z. inv(f z)) analytic_on s`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[analytic_on] THEN
+  X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [analytic_on]) THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
+  SUBGOAL_THEN `?e. &0 < e /\ !y:complex. dist(z,y) < e ==> ~(f y = Cx(&0))`
+  MP_TAC THENL
+   [MATCH_MP_TAC CONTINUOUS_ON_OPEN_AVOID THEN
+    EXISTS_TAC `ball(z:complex,d)` THEN
+    ASM_SIMP_TAC[HOLOMORPHIC_ON_IMP_CONTINUOUS_ON; CENTRE_IN_BALL; OPEN_BALL];
+    REWRITE_TAC[GSYM IN_BALL] THEN
+    DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
+    EXISTS_TAC `min (d:real) e` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
+    MATCH_MP_TAC HOLOMORPHIC_ON_INV THEN
+    ASM_SIMP_TAC[BALL_MIN_INTER; IN_INTER] THEN
+    ASM_MESON_TAC[HOLOMORPHIC_ON_SUBSET; INTER_SUBSET]]);;
+
+let ANALYTIC_ON_DIV = prove
+ (`!f g s.
+        f analytic_on s /\ g analytic_on s /\
+        (!z. z IN s ==> ~(g z = Cx(&0)))
+        ==> (\z. f z / g z) analytic_on s`,
+  SIMP_TAC[complex_div; ANALYTIC_ON_MUL; ANALYTIC_ON_INV]);;
+
+let ANALYTIC_ON_POW = prove
+ (`!f s n. f analytic_on s ==> (\z. (f z) pow n) analytic_on s`,
+  REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN REPEAT GEN_TAC THEN
+  DISCH_TAC THEN INDUCT_TAC THEN REWRITE_TAC[complex_pow] THEN
+  ASM_SIMP_TAC[ANALYTIC_ON_CONST; ANALYTIC_ON_MUL]);;
+
+let ANALYTIC_ON_VSUM = prove
+ (`!f s k. FINITE k /\ (!a. a IN k ==> (f a) analytic_on s)
+           ==> (\x. vsum k (\a. f a x)) analytic_on s`,
+  GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
+  MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[VSUM_CLAUSES] THEN
+  SIMP_TAC[ANALYTIC_ON_CONST; IN_INSERT; NOT_IN_EMPTY] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC ANALYTIC_ON_ADD THEN
+  ASM_SIMP_TAC[ETA_AX]);;
+
+(* ------------------------------------------------------------------------- *)
+(* The case of analyticity at a point.                                       *)
+(* ------------------------------------------------------------------------- *)
+
+let ANALYTIC_AT_BALL = prove
+ (`!f z. f analytic_on {z} <=> ?e. &0<e /\ f holomorphic_on ball (z,e)`,
+  REWRITE_TAC [analytic_on; IN_SING] THEN MESON_TAC []);;
+
+let ANALYTIC_AT = prove
+ (`!f z. f analytic_on {z} <=> ?s. open s /\ z IN s /\ f holomorphic_on s`,
+  REWRITE_TAC [ANALYTIC_ON_HOLOMORPHIC; SING_SUBSET]);;
+
+let ANALYTIC_ON_ANALYTIC_AT = prove
+ (`!f s. f analytic_on s <=> !z. z IN s ==> f analytic_on {z}`,
+  REWRITE_TAC [ANALYTIC_AT_BALL; analytic_on]);;
+
+let ANALYTIC_AT_TWO = prove
+ (`!f g z. f analytic_on {z} /\ g analytic_on {z} <=>
+    ?s. open s /\ z IN s /\ f holomorphic_on s /\ g holomorphic_on s`,
+  REWRITE_TAC [ANALYTIC_AT] THEN
+  MESON_TAC [HOLOMORPHIC_ON_SUBSET; OPEN_INTER; INTER_SUBSET; IN_INTER]);;
+
+let ANALYTIC_AT_ADD = prove
+ (`!f g z. f analytic_on {z} /\ g analytic_on {z}
+     ==> (\w. f w + g w) analytic_on {z}`,
+  REWRITE_TAC [ANALYTIC_AT_TWO] THEN REWRITE_TAC [ANALYTIC_AT] THEN
+  MESON_TAC [HOLOMORPHIC_ON_ADD]);;
+
+let ANALYTIC_AT_SUB = prove
+ (`!f g z. f analytic_on {z} /\ g analytic_on {z}
+     ==> (\w. f w - g w) analytic_on {z}`,
+  REWRITE_TAC [ANALYTIC_AT_TWO] THEN REWRITE_TAC [ANALYTIC_AT] THEN
+  MESON_TAC [HOLOMORPHIC_ON_SUB]);;
+
+let ANALYTIC_AT_MUL = prove
+ (`!f g z. f analytic_on {z} /\ g analytic_on {z}
+
+     ==> (\w. f w * g w) analytic_on {z}`,
+  REWRITE_TAC [ANALYTIC_AT_TWO] THEN REWRITE_TAC [ANALYTIC_AT] THEN
+  MESON_TAC [HOLOMORPHIC_ON_MUL]);;
+
+let ANALYTIC_AT_POW = prove
+ (`!f n z. f analytic_on {z}
+     ==> (\w. f w pow n) analytic_on {z}`,
+  REWRITE_TAC [ANALYTIC_AT] THEN MESON_TAC [HOLOMORPHIC_ON_POW]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Combining theorems for derivative with analytic_at {z} hypotheses.        *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_DERIVATIVE_ADD_AT = prove
+ (`!f g z. f analytic_on {z} /\ g analytic_on {z}
+     ==> complex_derivative (\w. f w + g w) z =
+           complex_derivative f z + complex_derivative g z`,
+  REWRITE_TAC [ANALYTIC_AT_TWO] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC COMPLEX_DERIVATIVE_ADD THEN
+  ASM_MESON_TAC [HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_AT]);;
+
+let COMPLEX_DERIVATIVE_SUB_AT = prove
+ (`!f g z. f analytic_on {z} /\ g analytic_on {z}
+     ==> complex_derivative (\w. f w - g w) z =
+           complex_derivative f z - complex_derivative g z`,
+  REWRITE_TAC [ANALYTIC_AT_TWO] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC COMPLEX_DERIVATIVE_SUB THEN
+  ASM_MESON_TAC [HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_AT]);;
+
+let COMPLEX_DERIVATIVE_MUL_AT = prove
+ (`!f g z. f analytic_on {z} /\ g analytic_on {z}
+     ==> complex_derivative (\w. f w * g w) z =
+           f z * complex_derivative g z + complex_derivative f z * g z`,
+  REWRITE_TAC [ANALYTIC_AT_TWO] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC COMPLEX_DERIVATIVE_MUL THEN
+  ASM_MESON_TAC [HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_AT]);;
+
+let COMPLEX_DERIVATIVE_LMUL_AT = prove
+ (`!f c z. f analytic_on {z}
+    ==> complex_derivative (\w. c * f w) z = c * complex_derivative f z`,
+  REWRITE_TAC [ANALYTIC_AT] THEN
+  MESON_TAC [HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_AT; COMPLEX_DERIVATIVE_LMUL]);;
+
+let COMPLEX_DERIVATIVE_RMUL_AT = prove
+ (`!f c z. f analytic_on {z}
+    ==> complex_derivative (\w. f w * c) z = complex_derivative f z * c`,
+  REWRITE_TAC [ANALYTIC_AT] THEN
+  MESON_TAC [HOLOMORPHIC_ON_IMP_DIFFERENTIABLE_AT; COMPLEX_DERIVATIVE_RMUL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* A composition lemma for functions of mixed type.                          *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_VECTOR_DERIVATIVE_REAL_COMPLEX = prove
+ (`(f has_complex_derivative f') (at(Cx(drop a)))
+   ==> ((\x. f(Cx(drop x))) has_vector_derivative f') (at a)`,
+  REWRITE_TAC[has_complex_derivative; has_vector_derivative] THEN
+  REWRITE_TAC[COMPLEX_CMUL] THEN MP_TAC(ISPECL
+   [`\x. Cx(drop x)`; `f:complex->complex`;
+    `\x. Cx(drop x)`; `\x:complex. f' * x`; `a:real^1`] DIFF_CHAIN_AT) THEN
+  REWRITE_TAC[o_DEF; COMPLEX_MUL_SYM; IMP_CONJ] THEN
+  DISCH_THEN MATCH_MP_TAC THEN MATCH_MP_TAC HAS_DERIVATIVE_LINEAR THEN
+  REWRITE_TAC[linear; DROP_ADD; DROP_CMUL; CX_ADD; CX_MUL; COMPLEX_CMUL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Complex differentiation of sequences and series.                          *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_COMPLEX_DERIVATIVE_SEQUENCE = prove
+ (`!s f f' g'.
+         convex s /\
+         (!n x. x IN s
+                ==> (f n has_complex_derivative f' n x) (at x within s)) /\
+         (!e. &0 < e
+              ==> ?N. !n x. n >= N /\ x IN s ==> norm (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_complex_derivative g' x) (at x within s)`,
+  REWRITE_TAC[has_complex_derivative] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_SEQUENCE THEN
+  EXISTS_TAC `\n x h:complex. (f':num->complex->complex) n x * h` THEN
+  ASM_SIMP_TAC[] THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
+  REWRITE_TAC[GSYM COMPLEX_SUB_RDISTRIB; COMPLEX_NORM_MUL] THEN
+  ASM_MESON_TAC[REAL_LE_RMUL; NORM_POS_LE]);;
+
+let HAS_COMPLEX_DERIVATIVE_SERIES = prove
+ (`!s f f' g' k.
+         convex s /\
+         (!n x. x IN s
+                ==> (f n has_complex_derivative f' n x) (at x within s)) /\
+         (!e. &0 < e
+              ==> ?N. !n x. n >= N /\ x IN s
+                            ==> norm(vsum (k INTER (0..n)) (\i. f' i x) - g' x)
+                                    <= e) /\
+         (?x l. x IN s /\ ((\n. f n x) sums l) k)
+         ==> ?g. !x. x IN s
+                     ==> ((\n. f n x) sums g x) k /\
+                         (g has_complex_derivative g' x) (at x within s)`,
+  REWRITE_TAC[has_complex_derivative] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_SERIES THEN
+  EXISTS_TAC `\n x h:complex. (f':num->complex->complex) n x * h` THEN
+  ASM_SIMP_TAC[] THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
+  SIMP_TAC[GSYM COMPLEX_SUB_RDISTRIB; VSUM_COMPLEX_RMUL; FINITE_NUMSEG;
+           FINITE_INTER; COMPLEX_NORM_MUL] THEN
+  ASM_MESON_TAC[REAL_LE_RMUL; NORM_POS_LE]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Bound theorem.                                                            *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_DIFFERENTIABLE_BOUND = prove
+ (`!f f' s B.
+        convex s /\
+        (!x. x IN s ==> (f has_complex_derivative f'(x)) (at x within s) /\
+                        norm(f' x) <= B)
+        ==> !x y. x IN s /\ y IN s ==> norm(f x - f y) <= B * norm(x - y)`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[has_complex_derivative] THEN
+  STRIP_TAC THEN MATCH_MP_TAC DIFFERENTIABLE_BOUND THEN
+  EXISTS_TAC `\x:complex h. f' x * h` THEN ASM_SIMP_TAC[] THEN
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPEC `\h. (f':complex->complex) x * h` ONORM) THEN
+  REWRITE_TAC[LINEAR_COMPLEX_MUL] THEN
+  DISCH_THEN(MATCH_MP_TAC o CONJUNCT2) THEN
+  GEN_TAC THEN REWRITE_TAC[COMPLEX_NORM_MUL] THEN
+  ASM_MESON_TAC[REAL_LE_RMUL; NORM_POS_LE]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Inverse function theorem for complex derivatives.                         *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_COMPLEX_DERIVATIVE_INVERSE_BASIC = prove
+ (`!f g f' t y.
+        (f has_complex_derivative f') (at (g y)) /\
+        ~(f' = Cx(&0)) /\
+        g continuous at y /\
+        open t /\
+        y IN t /\
+        (!z. z IN t ==> f (g z) = z)
+        ==> (g has_complex_derivative inv(f')) (at y)`,
+  REWRITE_TAC[has_complex_derivative] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_INVERSE_BASIC THEN
+  MAP_EVERY EXISTS_TAC
+   [`f:complex->complex`; `\x:complex. f' * x`; `t:complex->bool`] THEN
+  ASM_REWRITE_TAC[LINEAR_COMPLEX_MUL; FUN_EQ_THM; o_THM; I_THM] THEN
+  UNDISCH_TAC `~(f' = Cx(&0))` THEN CONV_TAC COMPLEX_FIELD);;
+
+let HAS_COMPLEX_DERIVATIVE_INVERSE_STRONG = prove
+ (`!f g f' s x.
+         open s /\
+         x IN s /\
+         f continuous_on s /\
+         (!x. x IN s ==> g (f x) = x) /\
+         (f has_complex_derivative f') (at x) /\
+         ~(f' = Cx(&0))
+         ==> (g has_complex_derivative inv(f')) (at (f x))`,
+  REWRITE_TAC[has_complex_derivative] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_INVERSE_STRONG THEN
+  MAP_EVERY EXISTS_TAC [`\x:complex. f' * x`; `s:complex->bool`] THEN
+  ASM_REWRITE_TAC[] THEN ASM_SIMP_TAC[FUN_EQ_THM; o_THM; I_THM] THEN
+  UNDISCH_TAC `~(f' = Cx(&0))` THEN CONV_TAC COMPLEX_FIELD);;
+
+let HAS_COMPLEX_DERIVATIVE_INVERSE_STRONG_X = prove
+ (`!f g f' s y.
+        open s /\ (g y) IN s /\ f continuous_on s /\
+        (!x. x IN s ==> (g(f(x)) = x)) /\
+        (f has_complex_derivative f') (at (g y)) /\ ~(f' = Cx(&0)) /\
+        f(g y) = y
+        ==> (g has_complex_derivative inv(f')) (at y)`,
+  REWRITE_TAC[has_complex_derivative] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_INVERSE_STRONG_X THEN MAP_EVERY EXISTS_TAC
+   [`f:complex->complex`; `\x:complex. f' * x`; `s:complex->bool`] THEN
+  ASM_REWRITE_TAC[] THEN ASM_SIMP_TAC[FUN_EQ_THM; o_THM; I_THM] THEN
+  UNDISCH_TAC `~(f' = Cx(&0))` THEN CONV_TAC COMPLEX_FIELD);;
+
+(* ------------------------------------------------------------------------- *)
+(* Cauchy-Riemann condition and relation to conformal.                       *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_BASIS = prove
+ (`basis 1 = Cx(&1) /\ basis 2 = ii`,
+  SIMP_TAC[CART_EQ; FORALL_2; BASIS_COMPONENT; DIMINDEX_2; ARITH] THEN
+  REWRITE_TAC[GSYM RE_DEF; GSYM IM_DEF; RE_CX; IM_CX] THEN
+  REWRITE_TAC[ii] THEN SIMPLE_COMPLEX_ARITH_TAC);;
+
+let COMPLEX_DIFFERENTIABLE_IMP_DIFFERENTIABLE = prove
+ (`!net f. f complex_differentiable net ==> f differentiable net`,
+  SIMP_TAC[complex_differentiable; differentiable; has_complex_derivative] THEN
+  MESON_TAC[]);;
+
+let CAUCHY_RIEMANN = prove
+ (`!f z. f complex_differentiable at z <=>
+         f differentiable at z  /\
+         (jacobian f (at z))$1$1 = (jacobian f (at z))$2$2 /\
+         (jacobian f (at z))$1$2 = --((jacobian f (at z))$2$1)`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[complex_differentiable] THEN EQ_TAC THENL
+   [REWRITE_TAC[has_complex_derivative] THEN
+    DISCH_THEN(X_CHOOSE_THEN `f':complex` ASSUME_TAC) THEN
+    CONJ_TAC THENL [ASM_MESON_TAC[differentiable]; ALL_TAC] THEN
+    REWRITE_TAC[jacobian] THEN
+    FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP FRECHET_DERIVATIVE_AT) THEN
+    SIMP_TAC[matrix; LAMBDA_BETA; DIMINDEX_2; ARITH] THEN
+    REWRITE_TAC[COMPLEX_BASIS; GSYM RE_DEF; GSYM IM_DEF; ii] THEN
+    SIMPLE_COMPLEX_ARITH_TAC;
+    STRIP_TAC THEN EXISTS_TAC
+     `complex(jacobian (f:complex->complex) (at z)$1$1,
+              jacobian f (at z)$2$1)` THEN
+    REWRITE_TAC[has_complex_derivative] THEN
+    FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [JACOBIAN_WORKS]) THEN
+    MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN
+    ASM_SIMP_TAC[CART_EQ; matrix_vector_mul; DIMINDEX_2; SUM_2; ARITH;
+                 FORALL_2; FUN_EQ_THM; LAMBDA_BETA] THEN
+    REWRITE_TAC[GSYM RE_DEF; GSYM IM_DEF; IM; RE; complex_mul] THEN
+    REAL_ARITH_TAC]);;
+
+let COMPLEX_DERIVATIVE_JACOBIAN = prove
+ (`!f z.
+        f complex_differentiable (at z)
+        ==> complex_derivative f z =
+            complex(jacobian f (at z)$1$1,jacobian f (at z)$2$1)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC COMPLEX_DERIVATIVE_UNIQUE_AT THEN
+  MAP_EVERY EXISTS_TAC [`f:complex->complex`; `z:complex`] THEN
+  ASM_REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_DIFFERENTIABLE] THEN
+  REWRITE_TAC[has_complex_derivative] THEN
+  FIRST_ASSUM(STRIP_ASSUME_TAC o GEN_REWRITE_RULE I [CAUCHY_RIEMANN]) THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [JACOBIAN_WORKS]) THEN
+  MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN
+  ASM_SIMP_TAC[CART_EQ; matrix_vector_mul; DIMINDEX_2; SUM_2; ARITH;
+               FORALL_2; FUN_EQ_THM; LAMBDA_BETA] THEN
+  REWRITE_TAC[GSYM RE_DEF; GSYM IM_DEF; IM; RE; complex_mul] THEN
+  REAL_ARITH_TAC);;
+
+let COMPLEX_DIFFERENTIABLE_EQ_CONFORMAL = prove
+ (`!f z.
+      f complex_differentiable at z /\ ~(complex_derivative f z = Cx(&0)) <=>
+      f differentiable at z  /\
+      ?a. ~(a = &0) /\ rotation_matrix (a %% jacobian f (at z))`,
+  REPEAT GEN_TAC THEN EQ_TAC THENL
+   [DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+    ASM_SIMP_TAC[COMPLEX_DIFFERENTIABLE_IMP_DIFFERENTIABLE;
+                 COMPLEX_DERIVATIVE_JACOBIAN] THEN
+    REWRITE_TAC[GSYM COMPLEX_VEC_0; GSYM DOT_EQ_0] THEN
+    REWRITE_TAC[DOT_2; GSYM RE_DEF; GSYM IM_DEF; RE; IM; GSYM REAL_POW_2] THEN
+    REWRITE_TAC[RE_DEF; IM_DEF; ROTATION_MATRIX_2] THEN
+    RULE_ASSUM_TAC(REWRITE_RULE[CAUCHY_RIEMANN]) THEN
+    ASM_REWRITE_TAC[MATRIX_CMUL_COMPONENT] THEN DISCH_TAC THEN
+    REWRITE_TAC[REAL_MUL_RNEG; GSYM REAL_ADD_LDISTRIB;
+                REAL_ARITH `(a * x:real) pow 2 = a pow 2 * x pow 2`] THEN
+    EXISTS_TAC
+     `inv(sqrt(jacobian (f:complex->complex) (at z)$2$2 pow 2 +
+               jacobian f (at z)$2$1 pow 2))` THEN
+    MATCH_MP_TAC(REAL_FIELD
+     `x pow 2 = y /\ ~(y = &0)
+      ==> ~(inv x = &0) /\ inv(x) pow 2 * y = &1`) THEN
+    ASM_SIMP_TAC[SQRT_POW_2; REAL_LE_ADD; REAL_LE_POW_2];
+    REWRITE_TAC[ROTATION_MATRIX_2; MATRIX_CMUL_COMPONENT] THEN
+    DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+    DISCH_THEN(X_CHOOSE_THEN `a:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
+    ASM_REWRITE_TAC[GSYM REAL_MUL_RNEG; REAL_EQ_MUL_LCANCEL] THEN
+    STRIP_TAC THEN MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN
+    CONJ_TAC THENL [ASM_REWRITE_TAC[CAUCHY_RIEMANN]; DISCH_TAC] THEN
+    ASM_SIMP_TAC[COMPLEX_DERIVATIVE_JACOBIAN] THEN
+    REWRITE_TAC[GSYM COMPLEX_VEC_0; GSYM DOT_EQ_0] THEN
+    REWRITE_TAC[DOT_2; GSYM RE_DEF; GSYM IM_DEF; RE; IM; GSYM REAL_POW_2] THEN
+    FIRST_X_ASSUM(MP_TAC o MATCH_MP
+     (REAL_RING `(a * x) pow 2 + (a * y) pow 2 = &1
+                 ==> ~(x pow 2 + y pow 2 = &0)`)) THEN
+    ASM_REWRITE_TAC[RE_DEF; IM_DEF]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Differentiation conversion.                                               *)
+(* ------------------------------------------------------------------------- *)
+
+let complex_differentiation_theorems = ref [];;
+
+let add_complex_differentiation_theorems =
+  let ETA_THM = prove
+   (`(f has_complex_derivative f') net <=>
+     ((\x. f x) has_complex_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 -> complex_differentiation_theorems :=
+              !complex_differentiation_theorems @ map ETA_TWEAK l;;
+
+add_complex_differentiation_theorems
+ [HAS_COMPLEX_DERIVATIVE_LMUL_WITHIN; HAS_COMPLEX_DERIVATIVE_LMUL_AT;
+  HAS_COMPLEX_DERIVATIVE_RMUL_WITHIN; HAS_COMPLEX_DERIVATIVE_RMUL_AT;
+  HAS_COMPLEX_DERIVATIVE_CDIV_WITHIN; HAS_COMPLEX_DERIVATIVE_CDIV_AT;
+  HAS_COMPLEX_DERIVATIVE_ID;
+  HAS_COMPLEX_DERIVATIVE_CONST;
+  HAS_COMPLEX_DERIVATIVE_NEG;
+  HAS_COMPLEX_DERIVATIVE_ADD;
+  HAS_COMPLEX_DERIVATIVE_SUB;
+  HAS_COMPLEX_DERIVATIVE_MUL_WITHIN; HAS_COMPLEX_DERIVATIVE_MUL_AT;
+  HAS_COMPLEX_DERIVATIVE_DIV_WITHIN; HAS_COMPLEX_DERIVATIVE_DIV_AT;
+  HAS_COMPLEX_DERIVATIVE_POW_WITHIN; HAS_COMPLEX_DERIVATIVE_POW_AT;
+  HAS_COMPLEX_DERIVATIVE_INV_WITHIN; HAS_COMPLEX_DERIVATIVE_INV_AT];;
+
+let rec COMPLEX_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_complex_derivative f') net`) in
+  let rec COMPLEX_DIFF_CONV tm =
+    try tryfind (fun th -> PART_MATCH partfn th (partfn tm))
+                (!complex_differentiation_theorems)
+    with Failure _ ->
+        let ith = tryfind (fun th ->
+         PART_MATCH (partfn o repeat (snd o dest_imp)) th (partfn tm))
+                    (!complex_differentiation_theorems) in
+        COMPLEX_DIFF_ELIM ith
+  and COMPLEX_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 COMPLEX_DIFF_ELIM (MATCH_MP th (COMPLEX_DIFF_CONV t)) in
+  COMPLEX_DIFF_CONV;;
+
+(* ------------------------------------------------------------------------- *)
+(* Hence a tactic.                                                           *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_DIFF_TAC =
+  let pth = MESON[]
+   `(f has_complex_derivative f') net
+    ==> f' = g'
+        ==> (f has_complex_derivative g') net` in
+  W(fun (asl,w) -> let th = MATCH_MP pth (COMPLEX_DIFF_CONV w) in
+       MATCH_MP_TAC(repeat (GEN_REWRITE_RULE I [IMP_IMP]) (DISCH_ALL th)));;
+
+let COMPLEX_DIFFERENTIABLE_TAC =
+  let DISCH_FIRST th = DISCH (hd(hyp th)) th in
+  GEN_REWRITE_TAC I [complex_differentiable] THEN
+  W(fun (asl,w) ->
+        let th = COMPLEX_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'));;
+
+(* ------------------------------------------------------------------------- *)
+(* A kind of complex Taylor theorem.                                         *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_TAYLOR = prove
+ (`!f n s B.
+    convex s /\
+    (!i x. x IN s /\ i <= n
+           ==> ((f i) has_complex_derivative f (i + 1) x) (at x within s)) /\
+    (!x. x IN s ==> norm(f (n + 1) x) <= B)
+    ==> !w z. w IN s /\ z IN s
+              ==> norm(f 0 z -
+                       vsum (0..n) (\i. f i w * (z - w) pow i / Cx(&(FACT i))))
+                  <= B * norm(z - w) pow (n + 1) / &(FACT n)`,
+  let lemma = prove
+   (`!f:num->real^N.
+          vsum (0..n) f = f 0 - f (n + 1) + vsum (0..n) (\i. f (i + 1))`,
+    REWRITE_TAC[GSYM(REWRITE_CONV[o_DEF] `(f:num->real^N) o (\i. i + 1)`)] THEN
+    ASM_SIMP_TAC[GSYM VSUM_IMAGE; EQ_ADD_RCANCEL; FINITE_NUMSEG] THEN
+    REWRITE_TAC[GSYM NUMSEG_OFFSET_IMAGE] THEN
+    SIMP_TAC[VSUM_CLAUSES_LEFT; LE_0] THEN
+    REWRITE_TAC[VSUM_CLAUSES_NUMSEG; GSYM ADD1] THEN
+    REWRITE_TAC[ARITH; ARITH_RULE `1 <= SUC n`] THEN VECTOR_ARITH_TAC) in
+  REPEAT STRIP_TAC THEN MP_TAC(SPECL
+   [`(\w. vsum (0..n) (\i. f i w * (z - w) pow i / Cx(&(FACT i))))`;
+    `\w. (f:num->complex->complex) (n + 1) w *
+         (z - w) pow n / Cx(&(FACT n))`; `segment[w:complex,z]`;
+    `B * norm(z - w:complex) pow n / &(FACT n)`]
+   COMPLEX_DIFFERENTIABLE_BOUND) THEN
+  ANTS_TAC THENL
+   [ASM_REWRITE_TAC[CONVEX_SEGMENT] THEN X_GEN_TAC `u:complex` THEN
+    DISCH_TAC THEN SUBGOAL_THEN `(u:complex) IN s` ASSUME_TAC THENL
+     [ASM_MESON_TAC[CONVEX_CONTAINS_SEGMENT; SUBSET]; ALL_TAC] THEN
+    CONJ_TAC THENL
+     [ALL_TAC;
+      REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_DIV; COMPLEX_NORM_CX;
+                  COMPLEX_NORM_POW; REAL_ABS_NUM] THEN
+      MATCH_MP_TAC REAL_LE_MUL2 THEN
+      ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE; REAL_POS; REAL_POW_LE] THEN
+      ASM_SIMP_TAC[REAL_LE_DIV2_EQ; REAL_OF_NUM_LT; FACT_LT] THEN
+      MATCH_MP_TAC REAL_POW_LE2 THEN REWRITE_TAC[NORM_POS_LE] THEN
+      ASM_MESON_TAC[SEGMENT_BOUND; NORM_SUB]] THEN
+    MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET THEN
+    EXISTS_TAC `s:complex->bool` THEN CONJ_TAC THENL
+     [ALL_TAC; ASM_MESON_TAC[CONVEX_CONTAINS_SEGMENT]] THEN
+    SUBGOAL_THEN
+     `((\u. vsum (0..n) (\i. f i u * (z - u) pow i / Cx (&(FACT i))))
+       has_complex_derivative
+       vsum (0..n) (\i. f i u * (-- Cx(&i) * (z - u) pow (i - 1)) /
+                                Cx(&(FACT i)) +
+                        f (i + 1) u * (z - u) pow i / Cx (&(FACT i))))
+      (at u within s)`
+    MP_TAC THENL
+     [MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_VSUM THEN
+      REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN REPEAT STRIP_TAC THEN
+      MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_MUL_WITHIN THEN
+      ASM_SIMP_TAC[ETA_AX] THEN W(MP_TAC o COMPLEX_DIFF_CONV o snd) THEN
+      MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN
+      REWRITE_TAC[complex_div] THEN CONV_TAC COMPLEX_RING;
+      ALL_TAC] THEN
+    ASM_SIMP_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN
+    AP_TERM_TAC THEN REWRITE_TAC[VSUM_ADD_NUMSEG] THEN
+    GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [lemma] THEN
+    REWRITE_TAC[GSYM VSUM_ADD_NUMSEG; GSYM COMPLEX_ADD_ASSOC] THEN
+    REWRITE_TAC[ADD_SUB] THEN REWRITE_TAC[GSYM ADD1; FACT] THEN
+    REWRITE_TAC[GSYM REAL_OF_NUM_SUC; GSYM REAL_OF_NUM_MUL; CX_MUL] THEN
+    REWRITE_TAC[complex_div; COMPLEX_INV_MUL; GSYM COMPLEX_MUL_ASSOC] THEN
+    REWRITE_TAC[COMPLEX_RING
+      `--a * b * inv a * c:complex = --(a * inv a) * b * c`] THEN
+    SIMP_TAC[COMPLEX_MUL_RINV; CX_INJ; REAL_ARITH `~(&n + &1 = &0)`] THEN
+    REWRITE_TAC[COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG; COMPLEX_MUL_LID] THEN
+    REWRITE_TAC[COMPLEX_ADD_LINV; GSYM COMPLEX_VEC_0; VSUM_0] THEN
+    REWRITE_TAC[COMPLEX_VEC_0; COMPLEX_ADD_RID] THEN
+    REWRITE_TAC[COMPLEX_MUL_LZERO; COMPLEX_MUL_RZERO; COMPLEX_NEG_0] THEN
+    CONV_TAC COMPLEX_RING;
+    ALL_TAC] THEN
+  DISCH_THEN(MP_TAC o SPECL [`z:complex`; `w:complex`]) THEN ANTS_TAC THEN
+  ASM_REWRITE_TAC[ENDS_IN_SEGMENT] THEN MATCH_MP_TAC EQ_IMP THEN
+  BINOP_TAC THENL
+   [ALL_TAC;
+    REWRITE_TAC[REAL_POW_ADD; real_div; REAL_POW_1] THEN REAL_ARITH_TAC] THEN
+  AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
+  SIMP_TAC[VSUM_CLAUSES_LEFT; LE_0; complex_pow; FACT; COMPLEX_DIV_1] THEN
+  REWRITE_TAC[SIMPLE_COMPLEX_ARITH `x * Cx(&1) + y = x <=> y = Cx(&0)`] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0] THEN MATCH_MP_TAC VSUM_EQ_0 THEN
+  INDUCT_TAC THEN
+  ASM_REWRITE_TAC[complex_pow; complex_div; COMPLEX_MUL_LZERO;
+                  COMPLEX_MUL_RZERO; COMPLEX_SUB_REFL; COMPLEX_VEC_0] THEN
+  REWRITE_TAC[IN_NUMSEG] THEN ARITH_TAC);;
+
+(* ------------------------------------------------------------------------- *)
+(* The simplest special case.                                                *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_MVT = prove
+ (`!f f' s B.
+        convex s /\
+        (!z. z IN s ==> (f has_complex_derivative f' z) (at z within s)) /\
+        (!z. z IN s ==> norm (f' z) <= B)
+        ==> !w z. w IN s /\ z IN s ==> norm (f z - f w) <= B * norm (z - w)`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(SPECL [`(\n. if n = 0 then f else f'):num->complex->complex`;
+                `0`; `s:complex->bool`; `B:real`] COMPLEX_TAYLOR) THEN
+  SIMP_TAC[NUMSEG_SING; VSUM_SING; LE; ARITH] THEN
+  REWRITE_TAC[complex_pow; REAL_POW_1; FACT; REAL_DIV_1] THEN
+  ASM_SIMP_TAC[COMPLEX_DIV_1; COMPLEX_MUL_RID]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Something more like the traditional MVT for real components.              *)
+(* Could, perhaps should, sharpen this to derivatives inside the segment.    *)
+(* ------------------------------------------------------------------------- *)
+
+let COMPLEX_MVT_LINE = prove
+ (`!f f' w z.
+        (!u. u IN segment[w,z]
+             ==> (f has_complex_derivative f'(u)) (at u))
+        ==> ?u. u IN segment[w,z] /\ Re(f z) - Re(f w) = Re(f'(u) * (z - w))`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL
+   [`(lift o Re) o (f:complex->complex) o
+     (\t. (&1 - drop t) % w + drop t % z)`;
+    `\u. (lift o Re) o
+         (\h. (f':complex->complex)((&1 - drop u) % w + drop u % z) * h) o
+         (\t. drop t % (z - w))`;
+    `vec 0:real^1`; `vec 1:real^1`]
+        MVT_VERY_SIMPLE) THEN
+  ANTS_TAC THENL
+   [REWRITE_TAC[DROP_VEC; REAL_POS] THEN
+    X_GEN_TAC `t:real^1` THEN STRIP_TAC THEN
+    MATCH_MP_TAC HAS_DERIVATIVE_AT_WITHIN THEN
+    MATCH_MP_TAC DIFF_CHAIN_AT THEN CONJ_TAC THENL
+     [ALL_TAC;
+      MATCH_MP_TAC HAS_DERIVATIVE_LINEAR THEN
+      REWRITE_TAC[linear; LIFT_ADD; RE_ADD; LIFT_CMUL; RE_CMUL; o_DEF]] THEN
+    MATCH_MP_TAC DIFF_CHAIN_AT THEN CONJ_TAC THENL
+     [REWRITE_TAC[VECTOR_ARITH `(&1 - t) % w + t % z = w + t % (z - w)`] THEN
+      GEN_REWRITE_TAC (RATOR_CONV o RAND_CONV o ABS_CONV)
+        [GSYM VECTOR_ADD_LID] THEN
+      MATCH_MP_TAC HAS_DERIVATIVE_ADD THEN
+      REWRITE_TAC[HAS_DERIVATIVE_CONST] THEN
+      MATCH_MP_TAC HAS_DERIVATIVE_LINEAR THEN
+      REWRITE_TAC[linear; DROP_ADD; DROP_CMUL] THEN
+      CONJ_TAC THEN VECTOR_ARITH_TAC;
+      ALL_TAC] THEN
+    REWRITE_TAC[GSYM has_complex_derivative] THEN
+    FIRST_X_ASSUM MATCH_MP_TAC;
+    REWRITE_TAC[o_THM; GSYM LIFT_SUB; LIFT_EQ; DROP_VEC; VECTOR_SUB_RZERO] THEN
+    CONV_TAC REAL_RAT_REDUCE_CONV THEN
+    REWRITE_TAC[VECTOR_MUL_LID; VECTOR_MUL_LZERO] THEN
+    REWRITE_TAC[VECTOR_ADD_LID; VECTOR_ADD_RID] THEN
+    DISCH_THEN(X_CHOOSE_THEN `t:real^1` STRIP_ASSUME_TAC) THEN
+    EXISTS_TAC `(&1 - drop t) % w + drop t % z:complex`] THEN
+  ASM_REWRITE_TAC[segment; IN_ELIM_THM] THEN
+  EXISTS_TAC `drop t` THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN
+  REWRITE_TAC[DROP_VEC]);;
+
+let COMPLEX_TAYLOR_MVT = prove
+ (`!f w z n.
+    (!i x. x IN segment[w,z] /\ i <= n
+           ==> ((f i) has_complex_derivative f (i + 1) x) (at x))
+    ==> ?u. u IN segment[w,z] /\
+            Re(f 0 z) =
+            Re(vsum (0..n) (\i. f i w * (z - w) pow i / Cx(&(FACT i))) +
+               (f (n + 1) u * (z - u) pow n / Cx (&(FACT n))) * (z - w))`,
+  let lemma = prove
+   (`!f:num->real^N.
+          vsum (0..n) f = f 0 - f (n + 1) + vsum (0..n) (\i. f (i + 1))`,
+    REWRITE_TAC[GSYM(REWRITE_CONV[o_DEF] `(f:num->real^N) o (\i. i + 1)`)] THEN
+    ASM_SIMP_TAC[GSYM VSUM_IMAGE; EQ_ADD_RCANCEL; FINITE_NUMSEG] THEN
+    REWRITE_TAC[GSYM NUMSEG_OFFSET_IMAGE] THEN
+    SIMP_TAC[VSUM_CLAUSES_LEFT; LE_0] THEN
+    REWRITE_TAC[VSUM_CLAUSES_NUMSEG; GSYM ADD1] THEN
+    REWRITE_TAC[ARITH; ARITH_RULE `1 <= SUC n`] THEN VECTOR_ARITH_TAC) in
+  REPEAT STRIP_TAC THEN MP_TAC(SPECL
+   [`(\w. vsum (0..n) (\i. f i w * (z - w) pow i / Cx(&(FACT i))))`;
+    `\w. (f:num->complex->complex) (n + 1) w *
+         (z - w) pow n / Cx(&(FACT n))`;
+    `w:complex`; `z:complex`]
+    COMPLEX_MVT_LINE) THEN
+  ANTS_TAC THENL
+   [ASM_REWRITE_TAC[CONVEX_SEGMENT] THEN X_GEN_TAC `u:complex` THEN
+    DISCH_TAC THEN
+    SUBGOAL_THEN
+     `((\u. vsum (0..n) (\i. f i u * (z - u) pow i / Cx (&(FACT i))))
+       has_complex_derivative
+       vsum (0..n) (\i. f i u * (-- Cx(&i) * (z - u) pow (i - 1)) /
+                                Cx(&(FACT i)) +
+                        f (i + 1) u * (z - u) pow i / Cx (&(FACT i))))
+      (at u)`
+    MP_TAC THENL
+     [MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_VSUM THEN
+      REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN REPEAT STRIP_TAC THEN
+      MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_MUL_AT THEN
+      ASM_SIMP_TAC[ETA_AX] THEN W(MP_TAC o COMPLEX_DIFF_CONV o snd) THEN
+      MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN
+      REWRITE_TAC[complex_div] THEN CONV_TAC COMPLEX_RING;
+      ALL_TAC] THEN
+    ASM_SIMP_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN
+    AP_TERM_TAC THEN REWRITE_TAC[VSUM_ADD_NUMSEG] THEN
+    GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [lemma] THEN
+    REWRITE_TAC[GSYM VSUM_ADD_NUMSEG; GSYM COMPLEX_ADD_ASSOC] THEN
+    REWRITE_TAC[ADD_SUB] THEN REWRITE_TAC[GSYM ADD1; FACT] THEN
+    REWRITE_TAC[GSYM REAL_OF_NUM_SUC; GSYM REAL_OF_NUM_MUL; CX_MUL] THEN
+    REWRITE_TAC[complex_div; COMPLEX_INV_MUL; GSYM COMPLEX_MUL_ASSOC] THEN
+    REWRITE_TAC[COMPLEX_RING
+      `--a * b * inv a * c:complex = --(a * inv a) * b * c`] THEN
+    SIMP_TAC[COMPLEX_MUL_RINV; CX_INJ; REAL_ARITH `~(&n + &1 = &0)`] THEN
+    REWRITE_TAC[COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG; COMPLEX_MUL_LID] THEN
+    REWRITE_TAC[COMPLEX_ADD_LINV; GSYM COMPLEX_VEC_0; VSUM_0] THEN
+    REWRITE_TAC[COMPLEX_VEC_0; COMPLEX_ADD_RID] THEN
+    REWRITE_TAC[COMPLEX_MUL_LZERO; COMPLEX_MUL_RZERO; COMPLEX_NEG_0] THEN
+    CONV_TAC COMPLEX_RING;
+    ALL_TAC] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:complex` THEN
+  MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[RE_ADD] THEN
+  REWRITE_TAC[ONCE_REWRITE_RULE[REAL_ADD_SYM] REAL_EQ_SUB_RADD] THEN
+  DISCH_THEN(SUBST1_TAC o SYM) THEN
+  SIMP_TAC[VSUM_CLAUSES_LEFT; LE_0; complex_pow; FACT; COMPLEX_DIV_1] THEN
+  REWRITE_TAC[COMPLEX_MUL_RID; RE_ADD] THEN
+  MATCH_MP_TAC(REAL_ARITH `Re x = &0 ==> y = y + Re x`) THEN
+  SIMP_TAC[RE_VSUM; FINITE_NUMSEG] THEN
+  MATCH_MP_TAC SUM_EQ_0_NUMSEG THEN
+  INDUCT_TAC THEN REWRITE_TAC[ARITH] THEN
+  REWRITE_TAC[COMPLEX_SUB_REFL; complex_pow; complex_div] THEN
+  REWRITE_TAC[COMPLEX_MUL_LZERO; COMPLEX_MUL_RZERO; RE_CX]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Further useful properties of complex conjugation.                         *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_CNJ = prove
+ (`!net f l. ((\x. cnj(f x)) --> cnj l) net <=> (f --> l) net`,
+  REWRITE_TAC[LIM; dist; GSYM CNJ_SUB; COMPLEX_NORM_CNJ]);;
+
+let SUMS_CNJ = prove
+ (`!net f l. ((\x. cnj(f x)) sums cnj l) net <=> (f sums l) net`,
+  SIMP_TAC[sums; LIM_CNJ; GSYM CNJ_VSUM; FINITE_INTER_NUMSEG]);;
+
+let CONTINUOUS_WITHIN_CNJ = prove
+ (`!s z. cnj continuous (at z within s)`,
+  SIMP_TAC[LINEAR_CONTINUOUS_WITHIN; LINEAR_CNJ]);;
+
+let CONTINUOUS_AT_CNJ = prove
+ (`!z. cnj continuous (at z)`,
+  SIMP_TAC[LINEAR_CONTINUOUS_AT; LINEAR_CNJ]);;
+
+let CONTINUOUS_ON_CNJ = prove
+ (`!s. cnj continuous_on s`,
+  SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_CNJ]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Some limit theorems about real part of real series etc.                   *)
+(* ------------------------------------------------------------------------- *)
+
+let REAL_LIM = prove
+ (`!net:(A)net f l.
+        (f --> l) net /\ ~(trivial_limit net) /\
+        (?b. (?a. netord net a b) /\ !a. netord net a b ==> real(f a))
+        ==> real l`,
+  REWRITE_TAC[IM_DEF; real] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC LIM_COMPONENT_EQ THEN
+  REWRITE_TAC[eventually; DIMINDEX_2; ARITH] THEN ASM_MESON_TAC[]);;
+
+let REAL_LIM_SEQUENTIALLY = prove
+ (`!f l. (f --> l) sequentially /\ (?N. !n. n >= N ==> real(f n))
+         ==> real l`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC(ISPEC `sequentially` REAL_LIM) THEN
+  REWRITE_TAC[SEQUENTIALLY; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
+  ASM_MESON_TAC[GE_REFL]);;
+
+let REAL_SERIES = prove
+ (`!f l s. (f sums l) s /\ (!n. real(f n)) ==> real l`,
+  REWRITE_TAC[sums] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC REAL_LIM_SEQUENTIALLY THEN
+  EXISTS_TAC `\n. vsum(s INTER (0..n)) f :complex` THEN
+  ASM_SIMP_TAC[REAL_VSUM; FINITE_INTER; FINITE_NUMSEG]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Often convenient to use comparison with real limit of complex type.       *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_NULL_COMPARISON_COMPLEX = prove
+ (`!net:(A)net f g.
+        eventually (\x. norm(f x) <= norm(g x)) net /\
+        (g --> Cx(&0)) net
+        ==> (f --> Cx(&0)) net`,
+  REWRITE_TAC[GSYM COMPLEX_VEC_0] THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC(ISPEC `net:(A)net` LIM_NULL_COMPARISON) THEN
+  EXISTS_TAC `norm o (g:A->complex)` THEN
+  ASM_REWRITE_TAC[o_THM; GSYM LIM_NULL_NORM]);;
+
+let LIM_NULL_COMPARISON_COMPLEX_RE = prove
+ (`!net:(A)net f g.
+        eventually (\x. norm(f x) <= Re(g x)) net /\
+        (g --> Cx(&0)) net
+        ==> (f --> Cx(&0)) net`,
+  REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC(ISPEC `net:(A)net` LIM_NULL_COMPARISON_COMPLEX) THEN
+  EXISTS_TAC `g:A->complex` THEN ASM_REWRITE_TAC[] THEN
+  FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP
+   (REWRITE_RULE[IMP_CONJ_ALT] EVENTUALLY_MONO)) THEN
+  REWRITE_TAC[] THEN
+  MESON_TAC[COMPLEX_NORM_GE_RE_IM; REAL_ABS_LE; REAL_LE_TRANS]);;
+
+let SERIES_COMPARISON_COMPLEX = prove
+ (`!f:num->real^N g s.
+        summable s g /\
+        (!n. n IN s ==> real(g n) /\ &0 <= Re(g n)) /\
+        (?N. !n. n >= N /\ n IN s ==> norm(f n) <= norm(g n))
+        ==> summable s f`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[summable] THEN
+  DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
+  MATCH_MP_TAC SERIES_COMPARISON THEN
+  EXISTS_TAC `\n. norm((g:num->complex) n)` THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM(X_CHOOSE_THEN `l:complex` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `lift(Re l)` THEN MATCH_MP_TAC SUMS_EQ THEN
+  EXISTS_TAC `\i:num. lift(Re(g i))` THEN
+  ASM_SIMP_TAC[REAL_NORM_POS; o_DEF] THEN
+  REWRITE_TAC[RE_DEF] THEN MATCH_MP_TAC SERIES_COMPONENT THEN
+  ASM_REWRITE_TAC[DIMINDEX_2; ARITH]);;
+
+let SERIES_COMPARISON_UNIFORM_COMPLEX = prove
+ (`!f:A->num->real^N g P s.
+        summable s g /\
+        (!n. n IN s ==> real(g n) /\ &0 <= Re(g n)) /\
+        (?N. !n x. N <= n /\ n IN s /\ P x ==> norm(f x n) <= norm(g n))
+        ==> ?l. !e. &0 < e
+                    ==> ?N. !n x. N <= n /\ P x
+                                  ==> dist(vsum(s INTER (0..n)) (f x),l x) <
+                                       e`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[summable] THEN
+  DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
+  MATCH_MP_TAC SERIES_COMPARISON_UNIFORM THEN
+  EXISTS_TAC `\n. norm((g:num->complex) n)` THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM(X_CHOOSE_THEN `l:complex` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `lift(Re l)` THEN MATCH_MP_TAC SUMS_EQ THEN
+  EXISTS_TAC `\i:num. lift(Re(g i))` THEN
+  ASM_SIMP_TAC[REAL_NORM_POS; o_DEF] THEN
+  REWRITE_TAC[RE_DEF] THEN MATCH_MP_TAC SERIES_COMPONENT THEN
+  ASM_REWRITE_TAC[DIMINDEX_2; ARITH]);;
+
+let SUMMABLE_SUBSET_COMPLEX = prove
+ (`!x s t. (!n. n IN s ==> real(x n) /\ &0 <= Re(x n)) /\
+           summable s x /\ t SUBSET s
+           ==> summable t x`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMMABLE_SUBSET THEN
+  EXISTS_TAC `s:num->bool` THEN ASM_REWRITE_TAC[] THEN
+  MATCH_MP_TAC SERIES_COMPARISON_COMPLEX THEN
+  EXISTS_TAC `x:num->complex` THEN ASM_REWRITE_TAC[] THEN
+  MESON_TAC[REAL_LE_REFL; NORM_0; NORM_POS_LE]);;
+
+let SERIES_ABSCONV_IMP_CONV = prove
+ (`!x:num->real^N k. summable k (\n. Cx(norm(x n))) ==> summable k x`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC SERIES_COMPARISON_COMPLEX THEN
+  EXISTS_TAC `\n:num. Cx(norm(x n:real^N))` THEN
+  ASM_REWRITE_TAC[REAL_CX; RE_CX; NORM_POS_LE; COMPLEX_NORM_CX] THEN
+  REWRITE_TAC[REAL_ABS_NORM; REAL_LE_REFL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Complex-valued geometric series.                                          *)
+(* ------------------------------------------------------------------------- *)
+
+let SUMS_GP = prove
+ (`!n z. norm(z) < &1
+         ==> ((\k. z pow k) sums (z pow n / (Cx(&1) - z))) (from n)`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[SERIES_FROM; VSUM_GP] THEN
+  ASM_CASES_TAC `z = Cx(&1)` THENL
+   [ASM_MESON_TAC[COMPLEX_NORM_NUM; REAL_LT_REFL]; ALL_TAC] THEN
+  MATCH_MP_TAC LIM_TRANSFORM_EVENTUALLY THEN
+  EXISTS_TAC `\m. (z pow n - z pow SUC m) / (Cx (&1) - z)` THEN CONJ_TAC THENL
+   [ASM_REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
+    EXISTS_TAC `n:num` THEN SIMP_TAC[GSYM NOT_LE];
+    MATCH_MP_TAC LIM_COMPLEX_DIV THEN
+    ASM_REWRITE_TAC[COMPLEX_SUB_0; LIM_CONST] THEN
+    GEN_REWRITE_TAC (RATOR_CONV o RAND_CONV) [GSYM COMPLEX_SUB_RZERO] THEN
+    MATCH_MP_TAC LIM_SUB THEN REWRITE_TAC[LIM_CONST] THEN
+    REWRITE_TAC[LIM_SEQUENTIALLY; GSYM COMPLEX_VEC_0] THEN
+    REWRITE_TAC[NORM_ARITH `dist(x,vec 0) = norm x`] THEN
+    X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+    MP_TAC(SPECL [`norm(z:complex)`; `e:real`] REAL_ARCH_POW_INV) THEN
+    ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN
+    X_GEN_TAC `n:num` THEN DISCH_TAC THEN X_GEN_TAC `m:num` THEN DISCH_TAC THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
+     `x < e ==> y <= x ==> y < e`)) THEN
+    REWRITE_TAC[COMPLEX_NORM_POW] THEN MATCH_MP_TAC REAL_POW_MONO_INV THEN
+    ASM_SIMP_TAC[NORM_POS_LE; REAL_LT_IMP_LE] THEN
+    UNDISCH_TAC `n:num <= m` THEN ARITH_TAC]);;
+
+let SUMMABLE_GP = prove
+ (`!z k. norm(z) < &1 ==> summable k (\n. z pow n)`,
+  REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC SUMMABLE_SUBSET THEN EXISTS_TAC `(:num)` THEN
+  REWRITE_TAC[SUBSET_UNIV] THEN
+  MATCH_MP_TAC SERIES_COMPARISON_COMPLEX THEN
+  EXISTS_TAC `\n. Cx(norm(z:complex) pow n)` THEN
+  REWRITE_TAC[REAL_CX; RE_CX; COMPLEX_NORM_CX] THEN
+  SIMP_TAC[REAL_POW_LE; NORM_POS_LE] THEN CONJ_TAC THENL
+   [REWRITE_TAC[summable; GSYM FROM_0; CX_POW] THEN
+    EXISTS_TAC `Cx(norm z) pow 0 / (Cx(&1) - Cx(norm(z:complex)))` THEN
+    MATCH_MP_TAC SUMS_GP THEN
+    ASM_REWRITE_TAC[COMPLEX_NORM_CX; REAL_ABS_NORM];
+    EXISTS_TAC `0` THEN REPEAT STRIP_TAC THEN
+    COND_CASES_TAC THEN
+    ASM_SIMP_TAC[REAL_ABS_POW; REAL_ABS_NORM; REAL_LE_REFL; NORM_POS_LE;
+                 COMPLEX_NORM_POW; NORM_0; REAL_ABS_POS; REAL_POW_LE]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Complex version (the usual one) of Dirichlet convergence test.            *)
+(* ------------------------------------------------------------------------- *)
+
+let SERIES_DIRICHLET_COMPLEX_GEN = prove
+ (`!f g N k m p l.
+        bounded {vsum (m..n) f | n IN (:num)} /\
+        summable (from p) (\n. Cx(norm(g(n + 1) - g(n)))) /\
+        ((\n. vsum(1..n) f * g(n + 1)) --> l) sequentially
+        ==> summable (from k) (\n. f(n) * g(n))`,
+  REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  MATCH_MP_TAC SERIES_DIRICHLET_BILINEAR THEN
+  MAP_EVERY EXISTS_TAC [`m:num`; `p:num`; `l:complex`] THEN
+  ASM_REWRITE_TAC[BILINEAR_COMPLEX_MUL] THEN
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [summable]) THEN
+  REWRITE_TAC[summable; SERIES_CAUCHY] THEN
+  SIMP_TAC[GSYM(REWRITE_RULE[o_DEF] LIFT_SUM); FINITE_NUMSEG; FINITE_INTER;
+           VSUM_CX; NORM_LIFT; COMPLEX_NORM_CX]);;
+
+let SERIES_DIRICHLET_COMPLEX = prove
+ (`!f g N k m.
+        bounded {vsum (m..n) f | n IN (:num)} /\
+        (!n. real(g n)) /\
+        (!n. N <= n ==> Re(g(n + 1)) <= Re(g n)) /\
+        (g --> Cx(&0)) sequentially
+        ==> summable (from k) (\n. f(n) * g(n))`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`f:num->complex`; `\n:num. Re(g n)`; `N:num`; `k:num`;
+                 `m:num`] SERIES_DIRICHLET) THEN
+  ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
+   [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
+    REWRITE_TAC[LIM_SEQUENTIALLY; o_THM; dist; VECTOR_SUB_RZERO] THEN
+    REWRITE_TAC[COMPLEX_SUB_RZERO; NORM_LIFT] THEN
+    MESON_TAC[COMPLEX_NORM_GE_RE_IM; REAL_LET_TRANS];
+    MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
+    REWRITE_TAC[COMPLEX_CMUL; FUN_EQ_THM] THEN
+    ASM_MESON_TAC[REAL; COMPLEX_MUL_SYM]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Versions with explicit bounds are sometimes useful.                       *)
+(* ------------------------------------------------------------------------- *)
+
+let SERIES_DIRICHLET_COMPLEX_VERY_EXPLICIT = prove
+ (`!f g B p.
+        &0 < B /\ 1 <= p /\
+        (!m n. p <= m ==> norm(vsum(m..n) f) <= B) /\
+        (!n. p <= n ==> real(g n) /\ &0 <= Re(g n)) /\
+        (!n. p <= n ==> Re(g(n + 1)) <= Re(g n))
+        ==> !m n. p <= m
+                  ==> norm(vsum(m..n) (\k. f k * g k)) <= &2 * B * norm(g m)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN
+  EXISTS_TAC
+   `norm(vsum(m..n) (\k. (vsum(p..k) f - vsum(p..(k-1)) f) * g k))` THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC REAL_EQ_IMP_LE THEN AP_TERM_TAC THEN
+    MATCH_MP_TAC VSUM_EQ_NUMSEG THEN X_GEN_TAC `k:num` THEN STRIP_TAC THEN
+    REWRITE_TAC[] THEN AP_THM_TAC THEN AP_TERM_TAC THEN
+    SUBGOAL_THEN `p:num <= k`
+     (fun th -> SIMP_TAC[GSYM(MATCH_MP NUMSEG_RREC th)])
+    THENL [ASM_ARITH_TAC; ALL_TAC] THEN
+    SIMP_TAC[VSUM_CLAUSES; FINITE_NUMSEG; IN_NUMSEG] THEN
+    COND_CASES_TAC THENL [ASM_ARITH_TAC; VECTOR_ARITH_TAC];
+    ALL_TAC] THEN
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  REWRITE_TAC[MATCH_MP BILINEAR_VSUM_PARTIAL_PRE BILINEAR_COMPLEX_MUL] THEN
+  COND_CASES_TAC THEN
+  ASM_SIMP_TAC[NORM_0; REAL_LE_MUL; REAL_POS; REAL_LT_IMP_LE; NORM_POS_LE] THEN
+  MATCH_MP_TAC(NORM_ARITH
+   `norm(c) <= e - norm(a) - norm(b) ==> norm(a - b - c) <= e`) THEN
+  MATCH_MP_TAC REAL_LE_TRANS THEN
+  EXISTS_TAC `sum (m..n) (\k. norm(g(k + 1) - g(k)) * B)` THEN CONJ_TAC THENL
+   [MATCH_MP_TAC VSUM_NORM_LE THEN REWRITE_TAC[IN_NUMSEG; FINITE_NUMSEG] THEN
+    X_GEN_TAC `k:num` THEN STRIP_TAC THEN REWRITE_TAC[COMPLEX_NORM_MUL] THEN
+    MATCH_MP_TAC REAL_LE_MUL2 THEN
+    ASM_SIMP_TAC[REAL_LE_REFL; LE_REFL; NORM_POS_LE];
+    ALL_TAC] THEN
+  MATCH_MP_TAC REAL_LE_TRANS THEN
+  EXISTS_TAC `sum(m..n) (\k. Re(g(k)) - Re(g(k + 1))) * B` THEN CONJ_TAC THENL
+   [ASM_SIMP_TAC[SUM_RMUL; REAL_LE_RMUL_EQ] THEN
+    MATCH_MP_TAC REAL_EQ_IMP_LE THEN MATCH_MP_TAC SUM_EQ_NUMSEG THEN
+    X_GEN_TAC `i:num` THEN STRIP_TAC THEN
+    SUBGOAL_THEN `p <= i /\ p <= i + 1` ASSUME_TAC THENL
+     [ASM_ARITH_TAC; ALL_TAC] THEN
+    ASM_SIMP_TAC[REAL_NORM; REAL_SUB; RE_SUB] THEN
+    ASM_SIMP_TAC[REAL_ARITH `abs(x - y) = y - x <=> x <= y`];
+    ALL_TAC] THEN
+  ASM_REWRITE_TAC[SUM_DIFFS; COMPLEX_NORM_MUL] THEN
+  MATCH_MP_TAC(REAL_ARITH
+   `w * n1 <= w * B /\ z * n2 <= z * B /\ &0 <= B * (&2 * y - (x + w + z))
+    ==> x * B <= &2 * B * y - w * n1 - z * n2`) THEN
+  REPEAT(CONJ_TAC THENL
+   [MATCH_MP_TAC REAL_LE_LMUL THEN
+    ASM_SIMP_TAC[NORM_POS_LE; LE_REFL]; ALL_TAC]) THEN
+  MATCH_MP_TAC REAL_LE_MUL THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN
+  SUBGOAL_THEN
+   `p <= m /\ p <= m + 1 /\ p <= n /\ p <= n + 1`
+  STRIP_ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
+  ASM_SIMP_TAC[REAL_NORM; real_abs] THEN REAL_ARITH_TAC);;
+
+let SERIES_DIRICHLET_COMPLEX_EXPLICIT = prove
+ (`!f g p q.
+           1 <= p /\
+           bounded {vsum (q..n) f | n IN (:num)} /\
+           (!n. p <= n ==> real(g n) /\ &0 <= Re(g n)) /\
+           (!n. p <= n ==> Re(g(n + 1)) <= Re(g n))
+           ==> ?B. &0 < B /\
+                   !m n. p <= m
+                         ==> norm(vsum(m..n) (\k. f k * g k))
+                                 <= B * norm(g m)`,
+  REWRITE_TAC[FORALL_AND_THM] THEN REPEAT STRIP_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o MATCH_MP BOUNDED_PARTIAL_SUMS) THEN
+  SIMP_TAC[BOUNDED_POS; IN_ELIM_THM; IN_UNIV; LEFT_IMP_EXISTS_THM] THEN
+  REWRITE_TAC[MESON[] `(!x a b. x = f a b ==> p a b) <=> (!a b. p a b)`] THEN
+  X_GEN_TAC `B:real` THEN STRIP_TAC THEN EXISTS_TAC `&2 * B` THEN
+  ASM_SIMP_TAC[GSYM REAL_MUL_ASSOC; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN
+  MATCH_MP_TAC SERIES_DIRICHLET_COMPLEX_VERY_EXPLICIT THEN
+  ASM_SIMP_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Relations among convergence and absolute convergence for power series.    *)
+(* ------------------------------------------------------------------------- *)
+
+let ABEL_LEMMA = prove
+ (`!a M r r0.
+        &0 <= r /\ r < r0 /\
+        (!n. n IN k ==> norm(a n) * r0 pow n <= M)
+        ==> summable k (\n. Cx(norm(a(n)) * r pow n))`,
+  REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN `&0 < r0` ASSUME_TAC THENL
+   [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
+  ASM_CASES_TAC `k:num->bool = {}` THEN ASM_REWRITE_TAC[SUMMABLE_TRIVIAL] THEN
+  SUBGOAL_THEN `&0 <= M` ASSUME_TAC THENL
+   [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
+    DISCH_THEN(X_CHOOSE_TAC `i:num`) THEN
+    FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN ASM_REWRITE_TAC[] THEN
+    MATCH_MP_TAC(REAL_ARITH `&0 <= x ==> x <= y ==> &0 <= y`) THEN
+    MATCH_MP_TAC REAL_LE_MUL THEN
+    ASM_SIMP_TAC[NORM_POS_LE; REAL_POW_LE; REAL_LT_IMP_LE];
+    ALL_TAC] THEN
+  MATCH_MP_TAC SERIES_COMPARISON_COMPLEX THEN
+  EXISTS_TAC `\n. Cx(M * (r / r0) pow n)` THEN REPEAT CONJ_TAC THENL
+   [REWRITE_TAC[CX_MUL; CX_POW] THEN MATCH_MP_TAC SUMMABLE_COMPLEX_LMUL THEN
+    MATCH_MP_TAC SUMMABLE_GP THEN REWRITE_TAC[COMPLEX_NORM_CX] THEN
+    ASM_SIMP_TAC[REAL_ABS_DIV; real_abs; REAL_LT_IMP_LE] THEN
+    ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_MUL_LID];
+    REWRITE_TAC[REAL_CX; RE_CX] THEN
+    REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[] THEN
+    ASM_SIMP_TAC[REAL_LE_DIV; REAL_POW_LE; REAL_LT_IMP_LE];
+    EXISTS_TAC `0` THEN REWRITE_TAC[COMPLEX_NORM_CX] THEN REPEAT STRIP_TAC THEN
+    REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_POW; REAL_ABS_NORM; REAL_ABS_DIV] THEN
+    ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE; REAL_POW_DIV] THEN
+    REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN
+    ASM_SIMP_TAC[GSYM real_div; REAL_LE_RDIV_EQ; REAL_POW_LT] THEN
+    ONCE_REWRITE_TAC[REAL_ARITH `(a * b) * c:real = (a * c) * b`] THEN
+    ASM_SIMP_TAC[REAL_LE_RMUL; REAL_POW_LE; REAL_LT_IMP_LE]]);;
+
+let POWER_SERIES_CONV_IMP_ABSCONV = prove
+ (`!a k w z.
+        summable k (\n. a(n) * z pow n) /\ norm(w) < norm(z)
+        ==> summable k (\n. Cx(norm(a(n) * w pow n)))`,
+  REPEAT STRIP_TAC THEN
+  REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_POW] THEN
+  MATCH_MP_TAC ABEL_LEMMA THEN
+  FIRST_ASSUM(MP_TAC o MATCH_MP SUMMABLE_IMP_BOUNDED) THEN
+  REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `B:real` THEN STRIP_TAC THEN
+  EXISTS_TAC `norm(z:complex)` THEN REWRITE_TAC[NORM_POS_LE] THEN
+  ASM_REWRITE_TAC[GSYM COMPLEX_NORM_POW; GSYM COMPLEX_NORM_MUL]);;
+
+let POWER_SERIES_CONV_IMP_ABSCONV_WEAK = prove
+ (`!a k w z.
+        summable k (\n. a(n) * z pow n) /\ norm(w) < norm(z)
+        ==> summable k (\n. Cx(norm(a(n))) * w pow n)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC SERIES_COMPARISON_COMPLEX THEN
+  EXISTS_TAC `\n. Cx(norm(a(n) * w pow n))` THEN CONJ_TAC THENL
+   [MATCH_MP_TAC POWER_SERIES_CONV_IMP_ABSCONV THEN
+    EXISTS_TAC `z:complex` THEN ASM_REWRITE_TAC[];
+    ALL_TAC] THEN
+  REWRITE_TAC[REAL_CX; RE_CX; NORM_POS_LE] THEN
+  REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_CX; REAL_ABS_NORM;
+              REAL_ABS_MUL; REAL_LE_REFL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Comparing sums and "integrals" via complex antiderivatives.               *)
+(* ------------------------------------------------------------------------- *)
+
+let SUM_INTEGRAL_UBOUND_INCREASING = prove
+ (`!f g m n.
+      m <= n /\
+      (!x. x IN segment[Cx(&m),Cx(&n + &1)]
+           ==> (g has_complex_derivative f(x)) (at x)) /\
+      (!x y. &m <= x /\ x <= y /\ y <= &n + &1 ==> Re(f(Cx x)) <= Re(f(Cx y)))
+      ==> sum(m..n) (\k. Re(f(Cx(&k)))) <= Re(g(Cx(&n + &1)) - g(Cx(&m)))`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN
+  EXISTS_TAC `--sum(m..n) (\k. Re(g(Cx(&k))) - Re(g(Cx(&(k + 1)))))` THEN
+  CONJ_TAC THENL
+   [ALL_TAC;
+    ASM_REWRITE_TAC[SUM_DIFFS; RE_SUB; REAL_NEG_SUB; REAL_OF_NUM_ADD] THEN
+    REWRITE_TAC[REAL_LE_REFL]] THEN
+  REWRITE_TAC[GSYM SUM_NEG] THEN MATCH_MP_TAC SUM_LE_NUMSEG THEN
+  REWRITE_TAC[REAL_NEG_SUB] THEN X_GEN_TAC `r:num` THEN STRIP_TAC THEN
+  MP_TAC(ISPECL [`g:complex->complex`; `f:complex->complex`;
+                 `Cx(&r)`; `Cx(&r + &1)`] COMPLEX_MVT_LINE) THEN
+  ANTS_TAC THENL
+   [X_GEN_TAC `u:complex` THEN STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    UNDISCH_TAC `u IN segment[Cx(&r),Cx(&r + &1)]` THEN
+    REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+    SPEC_TAC(`u:complex`,`u:complex`) THEN REWRITE_TAC[GSYM SUBSET] THEN
+    MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_CONVEX_HULL] THEN
+    REWRITE_TAC[SUBSET; IN_INSERT; NOT_IN_EMPTY; GSYM SEGMENT_CONVEX_HULL] THEN
+    REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[IN_SEGMENT_CX] THEN
+    REWRITE_TAC[REAL_OF_NUM_ADD; REAL_OF_NUM_LE] THEN
+    ASM_ARITH_TAC;
+    REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN DISCH_THEN(X_CHOOSE_THEN `u:complex`
+     (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN
+    REWRITE_TAC[CX_ADD; COMPLEX_RING `y * ((x + Cx(&1)) - x) = y`] THEN
+    SUBGOAL_THEN `?y. u = Cx y` (CHOOSE_THEN SUBST_ALL_TAC) THENL
+     [ASM_MESON_TAC[REAL_SEGMENT; REAL_CX; REAL]; ALL_TAC] THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT_CX]) THEN
+    REPEAT(FIRST_X_ASSUM
+     (MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_OF_NUM_LE])) THEN
+    REAL_ARITH_TAC]);;
+
+let SUM_INTEGRAL_UBOUND_DECREASING = prove
+ (`!f g m n.
+      m <= n /\
+      (!x. x IN segment[Cx(&m - &1),Cx(&n)]
+           ==> (g has_complex_derivative f(x)) (at x)) /\
+      (!x y. &m - &1 <= x /\ x <= y /\ y <= &n ==> Re(f(Cx y)) <= Re(f(Cx x)))
+      ==> sum(m..n) (\k. Re(f(Cx(&k)))) <= Re(g(Cx(&n)) - g(Cx(&m - &1)))`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
+   `--sum(m..n) (\k. Re(g(Cx(&(k) - &1))) - Re(g(Cx(&(k+1) - &1))))` THEN
+  CONJ_TAC THENL
+   [ALL_TAC;
+    ASM_REWRITE_TAC[SUM_DIFFS; REAL_NEG_SUB] THEN
+    REWRITE_TAC[GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_SUB] THEN
+    REWRITE_TAC[RE_SUB; REAL_ARITH `(x + &1) - &1 = x`; REAL_LE_REFL]] THEN
+  REWRITE_TAC[GSYM SUM_NEG] THEN MATCH_MP_TAC SUM_LE_NUMSEG THEN
+  REWRITE_TAC[REAL_NEG_SUB] THEN X_GEN_TAC `r:num` THEN STRIP_TAC THEN
+  REWRITE_TAC[GSYM REAL_OF_NUM_ADD; REAL_ARITH `(x + &1) - &1 = x`] THEN
+  MP_TAC(ISPECL [`g:complex->complex`; `f:complex->complex`;
+                 `Cx(&r - &1)`; `Cx(&r)`] COMPLEX_MVT_LINE) THEN
+  ANTS_TAC THENL
+   [X_GEN_TAC `u:complex` THEN STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    UNDISCH_TAC `u IN segment[Cx(&r - &1),Cx(&r)]` THEN
+    REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+    SPEC_TAC(`u:complex`,`u:complex`) THEN REWRITE_TAC[GSYM SUBSET] THEN
+    MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_CONVEX_HULL] THEN
+    REWRITE_TAC[SUBSET; IN_INSERT; NOT_IN_EMPTY; GSYM SEGMENT_CONVEX_HULL] THEN
+    REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[IN_SEGMENT_CX] THEN
+    REPEAT(POP_ASSUM MP_TAC) THEN
+    REWRITE_TAC[GSYM REAL_OF_NUM_LE] THEN REAL_ARITH_TAC;
+    REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN DISCH_THEN(X_CHOOSE_THEN `u:complex`
+     (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN
+    REWRITE_TAC[CX_SUB; COMPLEX_RING `y * (x - (x - Cx(&1))) = y`] THEN
+    SUBGOAL_THEN `?y. u = Cx y` (CHOOSE_THEN SUBST_ALL_TAC) THENL
+     [ASM_MESON_TAC[REAL_SEGMENT; REAL_CX; REAL]; ALL_TAC] THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT_CX]) THEN
+    REPEAT(FIRST_X_ASSUM
+     (MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_OF_NUM_LE])) THEN
+    REAL_ARITH_TAC]);;
+
+let SUM_INTEGRAL_LBOUND_INCREASING = prove
+ (`!f g m n.
+      m <= n /\
+      (!x. x IN segment[Cx(&m - &1),Cx(&n)]
+           ==> (g has_complex_derivative f(x)) (at x)) /\
+      (!x y. &m - &1 <= x /\ x <= y /\ y <= &n ==> Re(f(Cx x)) <= Re(f(Cx y)))
+      ==> Re(g(Cx(&n)) - g(Cx(&m - &1))) <= sum(m..n) (\k. Re(f(Cx(&k))))`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`\z. --((f:complex->complex) z)`;
+                 `\z. --((g:complex->complex) z)`;
+                 `m:num`; `n:num`] 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_COMPLEX_DERIVATIVE_NEG]);;
+
+let SUM_INTEGRAL_LBOUND_DECREASING = prove
+ (`!f g m n.
+      m <= n /\
+      (!x. x IN segment[Cx(&m),Cx(&n + &1)]
+           ==> (g has_complex_derivative f(x)) (at x)) /\
+      (!x y. &m <= x /\ x <= y /\ y <= &n + &1 ==> Re(f(Cx y)) <= Re(f(Cx x)))
+      ==> Re(g(Cx(&n + &1)) - g(Cx(&m))) <= sum(m..n) (\k. Re(f(Cx(&k))))`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`\z. --((f:complex->complex) z)`;
+                 `\z. --((g:complex->complex) z)`;
+                 `m:num`; `n:num`] 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_COMPLEX_DERIVATIVE_NEG]);;
+
+let SUM_INTEGRAL_BOUNDS_INCREASING = prove
+ (`!f g m n.
+         m <= n /\
+         (!x. x IN segment[Cx(&m - &1),Cx (&n + &1)]
+              ==> (g has_complex_derivative f x) (at x)) /\
+         (!x y.
+              &m - &1 <= x /\ x <= y /\ y <= &n + &1
+              ==> Re(f(Cx x)) <= Re(f(Cx y)))
+         ==> Re(g(Cx(&n)) - g(Cx(&m - &1))) <= sum(m..n) (\k. Re(f(Cx(&k)))) /\
+             sum (m..n) (\k. Re(f(Cx(&k)))) <= Re(g(Cx(&n + &1)) - g(Cx(&m)))`,
+  REPEAT STRIP_TAC THENL
+   [MATCH_MP_TAC SUM_INTEGRAL_LBOUND_INCREASING;
+    MATCH_MP_TAC SUM_INTEGRAL_UBOUND_INCREASING] THEN
+  REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[IN_SEGMENT_CX_GEN; GSYM REAL_OF_NUM_LE]) THEN
+  REWRITE_TAC[IN_SEGMENT_CX_GEN] THEN ASM_REAL_ARITH_TAC);;
+
+let SUM_INTEGRAL_BOUNDS_DECREASING = prove
+ (`!f g m n.
+      m <= n /\
+      (!x. x IN segment[Cx(&m - &1),Cx(&n + &1)]
+           ==> (g has_complex_derivative f(x)) (at x)) /\
+      (!x y. &m - &1 <= x /\ x <= y /\ y <= &n + &1
+             ==> Re(f(Cx y)) <= Re(f(Cx x)))
+      ==> Re(g(Cx(&n + &1)) - g(Cx(&m))) <= sum(m..n) (\k. Re(f(Cx(&k)))) /\
+          sum(m..n) (\k. Re(f(Cx(&k)))) <= Re(g(Cx(&n)) - g(Cx(&m - &1)))`,
+  REPEAT STRIP_TAC THENL
+   [MATCH_MP_TAC SUM_INTEGRAL_LBOUND_DECREASING;
+    MATCH_MP_TAC SUM_INTEGRAL_UBOUND_DECREASING] THEN
+  REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[IN_SEGMENT_CX_GEN; GSYM REAL_OF_NUM_LE]) THEN
+  REWRITE_TAC[IN_SEGMENT_CX_GEN] THEN ASM_REAL_ARITH_TAC);;
+
+(* ------------------------------------------------------------------------- *)
+(* Relating different kinds of complex limits.                               *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_INFINITY_SEQUENTIALLY_COMPLEX = prove
+ (`!f l. (f --> l) at_infinity ==> ((\n. f(Cx(&n))) --> l) sequentially`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[LIM_AT_INFINITY; 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
+  REWRITE_TAC[COMPLEX_NORM_CX] THEN
+  REPEAT(POP_ASSUM MP_TAC) THEN
+  REWRITE_TAC[GSYM REAL_OF_NUM_LE] THEN REAL_ARITH_TAC);;
+
+let LIM_ZERO_INFINITY_COMPLEX = prove
+ (`!f l. ((\x. f(Cx(&1) / x)) --> l) (at (Cx(&0))) ==> (f --> l) at_infinity`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[LIM_AT; LIM_AT_INFINITY] 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; COMPLEX_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:complex` THEN DISCH_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `inv(z):complex`) THEN
+  REWRITE_TAC[complex_div; COMPLEX_MUL_LINV; COMPLEX_INV_INV] THEN
+  REWRITE_TAC[COMPLEX_MUL_LID] THEN DISCH_THEN MATCH_MP_TAC THEN
+  ASM_REWRITE_TAC[COMPLEX_NORM_INV; REAL_LT_INV_EQ] THEN CONJ_TAC THENL
+   [UNDISCH_TAC `&2 / d <= norm(z:complex)` THEN
+    ASM_CASES_TAC `z = Cx(&0)` THEN ASM_REWRITE_TAC[COMPLEX_NORM_NZ] THEN
+    REWRITE_TAC[COMPLEX_NORM_0; REAL_NOT_LE] THEN
+    ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH];
+    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
+    MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&2 / d` THEN
+    ASM_REWRITE_TAC[] THEN REWRITE_TAC[real_div] THEN
+    ASM_REWRITE_TAC[REAL_LT_INV_EQ; REAL_ARITH `x < &2 * x <=> &0 < x`]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Transforming complex limits to real ones.                                 *)
+(* ------------------------------------------------------------------------- *)
+
+let LIM_COMPLEX_REAL = prove
+ (`!f g l m.
+         eventually (\n. Re(g n) = f n) sequentially /\
+         Re m = l /\
+         (g --> m) sequentially
+         ==> !e. &0 < e ==> ?N. !n. N <= n ==> abs(f n - l) < e`,
+  REPEAT GEN_TAC THEN
+  REWRITE_TAC[EVENTUALLY_SEQUENTIALLY; LIM_SEQUENTIALLY] THEN
+  DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `N1:num`)
+   (CONJUNCTS_THEN2 (SUBST1_TAC o SYM) ASSUME_TAC)) THEN
+  X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[dist] THEN
+  DISCH_THEN(X_CHOOSE_TAC `N0:num`) THEN EXISTS_TAC `N0 + N1:num` THEN
+  X_GEN_TAC `n:num` THEN DISCH_THEN(STRIP_ASSUME_TAC o MATCH_MP (ARITH_RULE
+   `N0 + N1:num <= n ==> N0 <= n /\ N1 <= n`)) THEN
+  UNDISCH_THEN `!n. N0 <= n ==> norm ((g:num->complex) n - m) < e`
+   (MP_TAC o SPEC `n:num`) THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `n:num`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(SUBST1_TAC o SYM) THEN REWRITE_TAC[GSYM RE_SUB] THEN
+  MATCH_MP_TAC(REAL_ARITH `x <= y ==> y < e ==> x < e`) THEN
+  REWRITE_TAC[COMPLEX_NORM_GE_RE_IM]);;
+
+let LIM_COMPLEX_REAL_0 = prove
+ (`!f g. eventually (\n. Re(g n) = f n) sequentially /\
+         (g --> Cx(&0)) sequentially
+         ==> !e. &0 < e ==> ?N. !n. N <= n ==> abs(f n) < e`,
+  MP_TAC LIM_COMPLEX_REAL THEN
+  REPLICATE_TAC 2 (MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
+  DISCH_THEN(MP_TAC o SPECL [`&0`; `Cx(&0)`]) THEN
+  REWRITE_TAC[RE_CX; REAL_SUB_RZERO]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Uniform convergence of power series in a "Stolz angle".                   *)
+(* ------------------------------------------------------------------------- *)
+
+let POWER_SERIES_UNIFORM_CONVERGENCE_STOLZ_1 = prove
+ (`!M a s e.
+        summable s a /\ &0 < M /\ &0 < e
+        ==> eventually
+             (\n. !z. norm(Cx(&1) - z) <= M * (&1 - norm z)
+                      ==> norm(vsum (s INTER (0..n)) (\i. a i * z pow i) -
+                               infsum s (\i. a i * z pow i)) < e)
+             sequentially`,
+  let lemma = prove
+   (`!M w z. &0 < M /\ norm(w - z) <= M * (norm w - norm z) /\ ~(z = w)
+             ==> norm(z) < norm(w)`,
+    REPEAT STRIP_TAC THEN REWRITE_TAC[REAL_LT_LE] THEN CONJ_TAC THENL
+     [ASM_MESON_TAC[REAL_LE_MUL_EQ; REAL_SUB_LE; NORM_POS_LE; REAL_LE_TRANS];
+      DISCH_THEN SUBST_ALL_TAC THEN
+      ASM_MESON_TAC[REAL_SUB_REFL; REAL_MUL_RZERO;NORM_LE_0; VECTOR_SUB_EQ]])
+  and lemma1 = prove
+   (`!m n. m < n
+           ==> vsum (m..n) (\i. a i * z pow i) =
+               (Cx(&1) - z) * vsum(m..n-1) (\i. vsum (m..i) a * z pow i) +
+               vsum(m..n) a * z pow n`,
+    GEN_TAC THEN INDUCT_TAC THEN REWRITE_TAC[NOT_SUC; SUC_SUB1] THEN
+    SIMP_TAC[VSUM_CLAUSES_NUMSEG; LT; LT_IMP_LE] THEN STRIP_TAC THENL
+     [ASM_REWRITE_TAC[VSUM_SING_NUMSEG; complex_pow] THEN CONV_TAC COMPLEX_RING;
+      ASM_SIMP_TAC[] THEN UNDISCH_TAC `m:num < n` THEN
+      POP_ASSUM(K ALL_TAC)] THEN
+    SPEC_TAC(`n:num`,`n:num`) THEN
+    INDUCT_TAC THEN REWRITE_TAC[CONJUNCT1 LT] THEN POP_ASSUM(K ALL_TAC) THEN
+    SIMP_TAC[SUC_SUB1; VSUM_CLAUSES_NUMSEG; LT_IMP_LE] THEN
+    ASM_REWRITE_TAC[VSUM_SING_NUMSEG; complex_pow] THEN
+    CONV_TAC COMPLEX_RING) in
+  SUBGOAL_THEN
+   `!M a e.
+        summable (:num) a /\ &0 < M /\ &0 < e
+        ==> eventually
+             (\n. !z. norm(Cx(&1) - z) <= M * (&1 - norm z)
+                      ==> norm(vsum (0..n) (\i. a i * z pow i) -
+                               infsum (:num) (\i. a i * z pow i)) < e)
+             sequentially`
+  ASSUME_TAC THENL
+   [ALL_TAC;
+    REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o ISPECL
+     [`M:real`; `\i:num. if i IN s then a i else Cx(&0)`; `e:real`]) THEN
+    REWRITE_TAC[COND_RAND; COND_RATOR; COMPLEX_MUL_LZERO] THEN
+    ASM_REWRITE_TAC[GSYM COMPLEX_VEC_0; GSYM VSUM_RESTRICT_SET;
+                    INFSUM_RESTRICT; SUMMABLE_RESTRICT] THEN
+    REWRITE_TAC[SET_RULE `{i | i IN t /\ i IN s} = s INTER t`]] THEN
+  REPEAT STRIP_TAC THEN
+  ONCE_REWRITE_TAC[MESON[]
+   `(!z. P z) <=> P (Cx(&1)) /\ (!z. ~(z = Cx(&1)) ==> P z)`] THEN
+  REWRITE_TAC[EVENTUALLY_AND] THEN CONJ_TAC THENL
+   [REWRITE_TAC[COMPLEX_NORM_CX; REAL_ABS_NUM; COMPLEX_SUB_REFL;
+                REAL_SUB_REFL; REAL_MUL_RZERO; REAL_LE_REFL] THEN
+    UNDISCH_TAC `&0 < e` THEN SPEC_TAC(`e:real`,`e:real`) THEN
+    REWRITE_TAC[GSYM tendsto; COMPLEX_POW_ONE; COMPLEX_MUL_RID; GSYM dist;
+                ETA_AX] THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM SUMS_INFSUM]) THEN
+    REWRITE_TAC[sums; INTER_UNIV];
+    ALL_TAC] THEN
+  REWRITE_TAC[IMP_IMP; EVENTUALLY_SEQUENTIALLY] THEN
+  REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; GSYM dist] THEN
+  UNDISCH_TAC `&0 < e` THEN SPEC_TAC(`e:real`,`e:real`) THEN
+  MATCH_MP_TAC UNIFORMLY_CAUCHY_IMP_UNIFORMLY_CONVERGENT THEN
+  REWRITE_TAC[GSYM LIM_SEQUENTIALLY] THEN CONJ_TAC THENL
+   [X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+    REWRITE_TAC[MESON[] `(!m n z. P m /\ P n /\ Q z ==> R m n z) <=>
+                         (!z. Q z ==> !m n. P m /\ P n ==> R m n z)`] THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM SUMS_INFSUM]) THEN
+    REWRITE_TAC[sums] THEN
+    DISCH_THEN(MP_TAC o MATCH_MP CONVERGENT_IMP_CAUCHY) THEN
+    REWRITE_TAC[cauchy; GSYM dist] THEN
+    DISCH_THEN(MP_TAC o SPEC `min (e / &2) (e / &2 / M)`) THEN
+    ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_DIV; REAL_HALF; GE; INTER_UNIV] THEN
+    REWRITE_TAC[GSYM REAL_LT_MIN] THEN
+    ONCE_REWRITE_TAC[SEQUENCE_CAUCHY_WLOG] THEN
+    SUBGOAL_THEN
+     `!f:num->complex m n. m <= n
+              ==> dist(vsum (0..m) f,vsum (0..n) f) = norm(vsum (m+1..n) f)`
+     (fun th -> SIMP_TAC[th])
+    THENL
+     [REPEAT STRIP_TAC THEN
+      MATCH_MP_TAC(NORM_ARITH `a + c = b ==> dist(a,b) = norm c`) THEN
+      MATCH_MP_TAC VSUM_COMBINE_R THEN ASM_ARITH_TAC;
+      ALL_TAC] THEN
+    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
+    REWRITE_TAC[REAL_LT_MIN] THEN STRIP_TAC THEN
+    X_GEN_TAC `z:complex` THEN REWRITE_TAC[dist] THEN STRIP_TAC THEN
+    SUBGOAL_THEN `norm(z:complex) < &1` ASSUME_TAC THENL
+     [UNDISCH_TAC `~(z = Cx(&1))` THEN
+      ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
+      REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN DISCH_TAC THEN
+      FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (NORM_ARITH
+       `norm(a - b) <= M ==> &0 <= --M ==> b = a`)) THEN
+      REWRITE_TAC[GSYM REAL_MUL_RNEG; REAL_NEG_SUB] THEN
+      MATCH_MP_TAC REAL_LE_MUL THEN ASM_REAL_ARITH_TAC;
+      ALL_TAC] THEN
+    MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
+    ASM_CASES_TAC `m + 1 < n` THENL
+     [ASM_SIMP_TAC[lemma1] THEN
+      MATCH_MP_TAC(NORM_ARITH
+       `norm(a) < e / &2 /\ norm(b) < e / &2 ==> norm(a + b) < e`) THEN
+      REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_POW] THEN CONJ_TAC THENL
+       [MATCH_MP_TAC REAL_LET_TRANS THEN
+        EXISTS_TAC `(M * (&1 - norm(z:complex))) *
+                    sum (m+1..n-1) (\i. e / &2 / M * norm(z) pow i)` THEN
+        CONJ_TAC THENL
+         [MATCH_MP_TAC REAL_LE_MUL2 THEN ASM_REWRITE_TAC[NORM_POS_LE] THEN
+          MATCH_MP_TAC VSUM_NORM_LE THEN
+          REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
+          X_GEN_TAC `p:num` THEN STRIP_TAC THEN
+          ASM_SIMP_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_POW] THEN
+          MATCH_MP_TAC REAL_LE_RMUL THEN
+          SIMP_TAC[REAL_POW_LE; NORM_POS_LE] THEN
+          MATCH_MP_TAC(REAL_ARITH
+            `x < e / &2 /\ x < e / &2 / M ==> x <= e / &2 / M`) THEN
+          FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC;
+          REWRITE_TAC[SUM_LMUL] THEN
+          REWRITE_TAC[REAL_ARITH
+           `(M * z1) * e / &2 / M * s < e / &2 <=>
+            e * (M / M) * s * z1 < e * &1`] THEN
+          ASM_SIMP_TAC[REAL_LT_LMUL_EQ] THEN
+          ASM_SIMP_TAC[REAL_DIV_REFL; REAL_LT_IMP_NZ; REAL_MUL_LID] THEN
+          ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_SUB_LT] THEN
+          REWRITE_TAC[SUM_GP] THEN
+          COND_CASES_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
+          COND_CASES_TAC THENL
+           [UNDISCH_TAC `norm(Cx(&1) - z) <= M * (&1 - norm z)` THEN
+            ASM_REWRITE_TAC[REAL_SUB_REFL; REAL_MUL_RZERO] THEN
+            ASM_REWRITE_TAC[NORM_ARITH `norm(x - y:complex) <= &0 <=> x = y`];
+            ALL_TAC] THEN
+          ASM_SIMP_TAC[REAL_LT_DIV2_EQ; REAL_SUB_LT] THEN
+          MATCH_MP_TAC(REAL_ARITH
+           `&0 <= y /\ x < &1 ==> x - y < &1`) THEN
+          ASM_SIMP_TAC[REAL_POW_LE; NORM_POS_LE] THEN
+          MATCH_MP_TAC REAL_POW_1_LT THEN
+          ASM_REWRITE_TAC[NORM_POS_LE] THEN ARITH_TAC];
+        GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN
+        MATCH_MP_TAC REAL_LT_MUL2 THEN SIMP_TAC[NORM_POS_LE; REAL_POW_LE] THEN
+        CONJ_TAC THENL
+         [MATCH_MP_TAC(REAL_ARITH
+            `x < e / &2 /\ x < e / &2 / M ==> x < e / &2`) THEN
+          FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC;
+          MATCH_MP_TAC REAL_POW_1_LT THEN
+          ASM_REWRITE_TAC[NORM_POS_LE] THEN ASM_ARITH_TAC]];
+      ASM_CASES_TAC `(m+1)..n = {}` THENL
+       [ASM_REWRITE_TAC[VSUM_CLAUSES; NORM_0]; ALL_TAC] THEN
+      RULE_ASSUM_TAC(REWRITE_RULE[NUMSEG_EMPTY]) THEN
+      SUBGOAL_THEN `m + 1 = n` SUBST1_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
+      REWRITE_TAC[VSUM_SING_NUMSEG] THEN
+      REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_POW] THEN
+      GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN
+      MATCH_MP_TAC REAL_LT_MUL2 THEN SIMP_TAC[NORM_POS_LE; REAL_POW_LE] THEN
+      CONJ_TAC THENL
+       [FIRST_X_ASSUM(MP_TAC o SPECL [`m:num`; `n:num`]) THEN
+        SUBGOAL_THEN `m + 1 = n` SUBST1_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
+        ANTS_TAC THENL [ASM_ARITH_TAC; REWRITE_TAC[VSUM_SING_NUMSEG]] THEN
+        ASM_REAL_ARITH_TAC;
+        MATCH_MP_TAC REAL_POW_1_LT THEN
+        ASM_REWRITE_TAC[NORM_POS_LE] THEN ASM_ARITH_TAC]];
+    X_GEN_TAC `z:complex` THEN REWRITE_TAC[dist] THEN STRIP_TAC THEN
+    MP_TAC(ISPECL [`M:real`; `Cx(&1)`; `z:complex`] lemma) THEN
+    ASM_REWRITE_TAC[COMPLEX_NORM_CX; REAL_ABS_NUM] THEN DISCH_TAC THEN
+    SUBGOAL_THEN `summable (:num) (\i. a i * z pow i)` MP_TAC THENL
+     [MATCH_MP_TAC SERIES_ABSCONV_IMP_CONV THEN
+      REWRITE_TAC[] THEN MATCH_MP_TAC POWER_SERIES_CONV_IMP_ABSCONV THEN
+      EXISTS_TAC `Cx(&1)` THEN
+      REWRITE_TAC[COMPLEX_POW_ONE; COMPLEX_NORM_CX] THEN
+      ASM_REWRITE_TAC[REAL_ABS_NUM; COMPLEX_MUL_RID; ETA_AX];
+      REWRITE_TAC[GSYM SUMS_INFSUM] THEN
+      REWRITE_TAC[sums; INTER_UNIV]]]);;
+
+let POWER_SERIES_UNIFORM_CONVERGENCE_STOLZ = prove
+ (`!M a w s e.
+        summable s (\i. a i * w pow i) /\ &0 < M /\ &0 < e
+        ==> eventually
+             (\n. !z. norm(w - z) <= M * (norm w - norm z)
+                      ==> norm(vsum (s INTER (0..n)) (\i. a i * z pow i) -
+                               infsum s (\i. a i * z pow i)) < e)
+             sequentially`,
+  REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `w = Cx(&0)` THENL
+   [ASM_REWRITE_TAC[COMPLEX_SUB_LZERO; REAL_SUB_LZERO; COMPLEX_NORM_0] THEN
+    REWRITE_TAC[NORM_NEG; REAL_ARITH
+      `n <= M * --n <=> &0 <= --n * (&1 + M)`] THEN
+    ASM_SIMP_TAC[REAL_LE_MUL_EQ; REAL_ARITH `&0 < M ==> &0 < &1 + M`] THEN
+    REWRITE_TAC[NORM_ARITH `&0 <= --norm z <=> z = vec 0`] THEN
+    REWRITE_TAC[EVENTUALLY_SEQUENTIALLY; FORALL_UNWIND_THM2] THEN
+    EXISTS_TAC `1` THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
+    REWRITE_TAC[COMPLEX_VEC_0; COMPLEX_POW_ZERO] THEN
+    REWRITE_TAC[COND_RATOR; COND_RAND; COMPLEX_MUL_RZERO; COMPLEX_MUL_RID] THEN
+    MATCH_MP_TAC(NORM_ARITH `x = y /\ &0 < e ==> norm(y - x) < e`) THEN
+    ASM_REWRITE_TAC[] THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
+    REWRITE_TAC[sums] THEN MATCH_MP_TAC LIM_EVENTUALLY THEN
+    REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `1` THEN
+    X_GEN_TAC `m:num` THEN DISCH_TAC THEN
+    SIMP_TAC[GSYM COMPLEX_VEC_0; VSUM_DELTA] THEN
+    REWRITE_TAC[IN_INTER; LE_0; IN_NUMSEG];
+    FIRST_ASSUM(MP_TAC o MATCH_MP POWER_SERIES_UNIFORM_CONVERGENCE_STOLZ_1) THEN
+    MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
+    X_GEN_TAC `n:num` THEN REWRITE_TAC[] THEN DISCH_TAC THEN
+    X_GEN_TAC `z:complex` THEN STRIP_TAC THEN
+    FIRST_X_ASSUM(MP_TAC o SPEC `z / w:complex`) THEN
+    ASM_SIMP_TAC[GSYM COMPLEX_MUL_ASSOC; GSYM COMPLEX_POW_MUL] THEN
+    ASM_SIMP_TAC[COMPLEX_DIV_LMUL] THEN DISCH_THEN MATCH_MP_TAC THEN
+    MATCH_MP_TAC REAL_LE_RCANCEL_IMP THEN EXISTS_TAC `norm(w:complex)` THEN
+    ASM_REWRITE_TAC[COMPLEX_NORM_NZ; GSYM COMPLEX_NORM_MUL] THEN
+    ASM_SIMP_TAC[COMPLEX_FIELD
+     `~(w = Cx(&0)) ==> (Cx(&1) - z / w) * w = w - z`] THEN
+    REWRITE_TAC[GSYM REAL_MUL_ASSOC; REAL_SUB_RDISTRIB] THEN
+    REWRITE_TAC[GSYM COMPLEX_NORM_MUL; REAL_MUL_LID] THEN
+    ASM_SIMP_TAC[COMPLEX_DIV_RMUL]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Hence continuity and the Abel limit theorem.                              *)
+(* ------------------------------------------------------------------------- *)
+
+let ABEL_POWER_SERIES_CONTINUOUS = prove
+ (`!M s a.
+        summable s a /\ &0 < M
+        ==> (\z. infsum s (\i. a i * z pow i)) continuous_on
+            {z | norm(Cx(&1) - z) <= M * (&1 - norm z)}`,
+  REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC(ISPEC `sequentially` CONTINUOUS_UNIFORM_LIMIT) THEN
+  EXISTS_TAC `\n z. vsum (s INTER (0..n)) (\i. a i * z pow i)` THEN
+  ASM_SIMP_TAC[POWER_SERIES_UNIFORM_CONVERGENCE_STOLZ_1; IN_ELIM_THM;
+               TRIVIAL_LIMIT_SEQUENTIALLY] THEN
+  MATCH_MP_TAC ALWAYS_EVENTUALLY THEN X_GEN_TAC `n:num` THEN
+  REWRITE_TAC[] THEN MATCH_MP_TAC CONTINUOUS_ON_VSUM THEN
+  SIMP_TAC[CONTINUOUS_ON_COMPLEX_MUL; CONTINUOUS_ON_COMPLEX_POW;
+           CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST; FINITE_INTER;
+           FINITE_NUMSEG]);;
+
+let ABEL_LIMIT_THEOREM = prove
+ (`!M s a.
+        summable s a /\ &0 < M
+        ==> (!z. norm(z) < &1 ==> summable s (\i. a i * z pow i)) /\
+            ((\z. infsum s (\i. a i * z pow i)) --> infsum s a)
+            (at (Cx(&1)) within {z | norm(Cx(&1) - z) <= M * (&1 - norm z)})`,
+  GEN_TAC THEN ASM_CASES_TAC `&0 < M` THEN ASM_REWRITE_TAC[] THEN
+  SUBGOAL_THEN
+   `!a. summable (:num) a
+        ==> (!z. norm(z) < &1 ==> summable (:num) (\i. a i * z pow i)) /\
+            ((\z. infsum (:num) (\i. a i * z pow i))
+              --> infsum (:num) a)
+            (at (Cx(&1)) within {z | norm(Cx(&1) - z) <= M * (&1 - norm z)})`
+  ASSUME_TAC THENL
+   [ALL_TAC;
+    REPEAT GEN_TAC THEN STRIP_TAC THEN
+    FIRST_X_ASSUM(MP_TAC o SPEC
+     `(\n. if n IN s then a n else vec 0):num->complex`) THEN
+    REWRITE_TAC[COND_RAND; COND_RATOR; COMPLEX_VEC_0; COMPLEX_MUL_LZERO] THEN
+    REWRITE_TAC[GSYM COMPLEX_VEC_0] THEN
+    ASM_REWRITE_TAC[SUMMABLE_RESTRICT; INFSUM_RESTRICT]] THEN
+  GEN_TAC THEN STRIP_TAC THEN CONJ_TAC THENL
+   [X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+    MATCH_MP_TAC SERIES_ABSCONV_IMP_CONV THEN
+    REWRITE_TAC[] THEN MATCH_MP_TAC POWER_SERIES_CONV_IMP_ABSCONV THEN
+    EXISTS_TAC `Cx(&1)` THEN REWRITE_TAC[COMPLEX_POW_ONE; COMPLEX_NORM_CX] THEN
+    ASM_REWRITE_TAC[REAL_ABS_NUM; COMPLEX_MUL_RID; ETA_AX];
+    MP_TAC(ISPECL [`M:real`; `(:num)`; `a:num->complex`]
+       ABEL_POWER_SERIES_CONTINUOUS) THEN
+    ASM_REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
+    DISCH_THEN(MP_TAC o SPEC `Cx(&1)`) THEN
+    REWRITE_TAC[IN_ELIM_THM; CONTINUOUS_WITHIN] THEN
+    REWRITE_TAC[COMPLEX_SUB_REFL; COMPLEX_NORM_CX; COMPLEX_POW_ONE;
+                COMPLEX_MUL_RID; ETA_AX; REAL_ABS_NUM; REAL_SUB_REFL;
+                REAL_LE_REFL; REAL_MUL_RZERO]]);;
diff --git a/Multivariate/cauchy.ml b/Multivariate/cauchy.ml
new file mode 100644 (file)
index 0000000..81be303
--- /dev/null
@@ -0,0 +1,16641 @@
+(* ========================================================================= *)
+(* Complex path integrals and Cauchy's theorem.                              *)
+(*                                                                           *)
+(*              (c) Copyright, John Harrison 1998-2008                       *)
+(* (c) Copyright, Gianni Ciolli, Graziano Gentili, Marco Maggesi 2008-2009.  *)
+(*              (c) Copyright, Valentina Bruno 2010                          *)
+(* ========================================================================= *)
+
+needs "Library/binomial.ml";;
+needs "Library/iter.ml";;
+needs "Multivariate/realanalysis.ml";;
+
+prioritize_complex();;
+
+(* ------------------------------------------------------------------------- *)
+(* A couple of extra tactics used in some proofs below.                      *)
+(* ------------------------------------------------------------------------- *)
+
+let ASSERT_TAC tm =
+  SUBGOAL_THEN tm STRIP_ASSUME_TAC;;
+
+let EQ_TRANS_TAC tm =
+  MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC tm THEN CONJ_TAC;;
+
+(* ------------------------------------------------------------------------- *)
+(* Piecewise differentiability on a 1-D interval. The definition doesn't     *)
+(* tie it to real^1 but it's not obviously that useful elsewhere.            *)
+(* ------------------------------------------------------------------------- *)
+
+parse_as_infix("piecewise_differentiable_on",(12,"right"));;
+
+let piecewise_differentiable_on = new_definition
+ `f piecewise_differentiable_on i <=>
+        f continuous_on i /\
+        (?s. FINITE s /\ !x. x IN (i DIFF s) ==> f differentiable at x)`;;
+
+let PIECEWISE_DIFFERENTIABLE_ON_IMP_CONTINUOUS_ON = prove
+ (`!f s. f piecewise_differentiable_on s ==> f continuous_on s`,
+  SIMP_TAC[piecewise_differentiable_on]);;
+
+let PIECEWISE_DIFFERENTIABLE_ON_SUBSET = prove
+ (`!f s t.
+        f piecewise_differentiable_on s /\ t SUBSET s
+        ==> f piecewise_differentiable_on t`,
+  REWRITE_TAC[piecewise_differentiable_on] THEN
+  MESON_TAC[SUBSET; IN_DIFF; CONTINUOUS_ON_SUBSET]);;
+
+let DIFFERENTIABLE_ON_IMP_PIECEWISE_DIFFERENTIABLE = prove
+ (`!f:real^1->real^N a b.
+        f differentiable_on interval[a,b]
+        ==> f piecewise_differentiable_on interval[a,b]`,
+  SIMP_TAC[piecewise_differentiable_on;
+           DIFFERENTIABLE_IMP_CONTINUOUS_ON] THEN
+  REPEAT STRIP_TAC THEN EXISTS_TAC `{a,b}:real^1->bool` THEN
+  ASM_REWRITE_TAC[FINITE_INSERT; FINITE_RULES] THEN
+  REWRITE_TAC[GSYM OPEN_CLOSED_INTERVAL_1] THEN
+  SIMP_TAC[GSYM DIFFERENTIABLE_ON_EQ_DIFFERENTIABLE_AT; OPEN_INTERVAL] THEN
+  MATCH_MP_TAC DIFFERENTIABLE_ON_SUBSET THEN
+  EXISTS_TAC `interval[a:real^1,b]` THEN
+  ASM_REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED]);;
+
+let DIFFERENTIABLE_IMP_PIECEWISE_DIFFERENTIABLE = prove
+ (`!f s. (!x. x IN s ==> f differentiable (at x))
+         ==> f piecewise_differentiable_on s`,
+  SIMP_TAC[piecewise_differentiable_on; DIFFERENTIABLE_IMP_CONTINUOUS_AT;
+           CONTINUOUS_AT_IMP_CONTINUOUS_ON; IN_DIFF] THEN
+  MESON_TAC[FINITE_RULES]);;
+
+let PIECEWISE_DIFFERENTIABLE_COMPOSE = prove
+ (`!f:real^M->real^N g:real^N->real^P s.
+        f piecewise_differentiable_on s /\
+        g piecewise_differentiable_on (IMAGE f s) /\
+        (!b. FINITE {x | x IN s /\ f(x) = b})
+        ==> (g o f) piecewise_differentiable_on s`,
+  REPEAT GEN_TAC THEN
+  SIMP_TAC[piecewise_differentiable_on; CONTINUOUS_ON_COMPOSE] THEN
+  DISCH_THEN(CONJUNCTS_THEN2
+   (CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `ks:real^M->bool`
+                                STRIP_ASSUME_TAC))
+   (CONJUNCTS_THEN2
+     (CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `kt:real^N->bool`
+                                  STRIP_ASSUME_TAC))
+     ASSUME_TAC)) THEN
+  EXISTS_TAC
+    `ks UNION
+     UNIONS(IMAGE (\b. {x | x IN s /\ (f:real^M->real^N) x = b}) kt)` THEN
+  ASM_SIMP_TAC[FINITE_UNION; FINITE_UNIONS; FINITE_IMAGE] THEN
+  REWRITE_TAC[UNIONS_IMAGE; FORALL_IN_IMAGE; IN_DIFF; IN_UNION] THEN
+  ASM_REWRITE_TAC[IN_ELIM_THM; DE_MORGAN_THM] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC DIFFERENTIABLE_CHAIN_AT THEN
+  CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM SET_TAC[]);;
+
+let PIECEWISE_DIFFERENTIABLE_AFFINE = prove
+ (`!f:real^M->real^N s m c.
+        f piecewise_differentiable_on (IMAGE (\x. m % x + c) s)
+        ==> (f o (\x. m % x + c)) piecewise_differentiable_on s`,
+  REPEAT STRIP_TAC THEN ASM_CASES_TAC `m = &0` THENL
+   [ASM_REWRITE_TAC[o_DEF; VECTOR_MUL_LZERO] THEN
+    MATCH_MP_TAC DIFFERENTIABLE_IMP_PIECEWISE_DIFFERENTIABLE THEN
+    SIMP_TAC[DIFFERENTIABLE_CONST];
+    MATCH_MP_TAC PIECEWISE_DIFFERENTIABLE_COMPOSE THEN
+    ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+     [MATCH_MP_TAC DIFFERENTIABLE_IMP_PIECEWISE_DIFFERENTIABLE THEN
+      SIMP_TAC[DIFFERENTIABLE_ADD; DIFFERENTIABLE_CMUL; DIFFERENTIABLE_CONST;
+               DIFFERENTIABLE_ID];
+      X_GEN_TAC `b:real^M` THEN ASM_SIMP_TAC[VECTOR_AFFINITY_EQ] THEN
+      MATCH_MP_TAC FINITE_SUBSET THEN
+      EXISTS_TAC `{inv m % b + --(inv m % c):real^M}` THEN
+      SIMP_TAC[FINITE_RULES] THEN SET_TAC[]]]);;
+
+let PIECEWISE_DIFFERENTIABLE_CASES = prove
+ (`!f g:real^1->real^N a b c.
+        drop a <= drop c /\ drop c <= drop b /\ f c = g c /\
+        f piecewise_differentiable_on interval[a,c] /\
+        g piecewise_differentiable_on interval[c,b]
+        ==> (\x. if drop x <= drop c then f(x) else g(x))
+            piecewise_differentiable_on interval[a,b]`,
+  REPEAT GEN_TAC THEN
+  REPLICATE_TAC 3 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
+  REWRITE_TAC[piecewise_differentiable_on] THEN
+  DISCH_THEN(CONJUNCTS_THEN2
+   (CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `s:real^1->bool`
+                                STRIP_ASSUME_TAC))
+   (CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `t:real^1->bool`
+                                STRIP_ASSUME_TAC))) THEN
+  CONJ_TAC THENL
+   [SUBGOAL_THEN `interval[a:real^1,b] = interval[a,c] UNION interval[c,b]`
+    SUBST1_TAC THENL
+     [REWRITE_TAC[EXTENSION; IN_UNION; IN_INTERVAL_1] THEN
+      ASM_REAL_ARITH_TAC;
+      ALL_TAC] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_CASES THEN
+    ASM_REWRITE_TAC[CLOSED_INTERVAL; IN_INTERVAL_1] THEN
+    ASM_MESON_TAC[REAL_LE_ANTISYM; DROP_EQ];
+    ALL_TAC] THEN
+  EXISTS_TAC `(c:real^1) INSERT s UNION t` THEN
+  ASM_REWRITE_TAC[FINITE_INSERT; FINITE_UNION] THEN
+  REWRITE_TAC[DE_MORGAN_THM; IN_DIFF; IN_INTERVAL_1; IN_INSERT; IN_UNION] THEN
+  X_GEN_TAC `x:real^1` THEN STRIP_TAC THEN
+  DISJ_CASES_TAC(REAL_ARITH `drop x <= drop c \/ drop c <= drop x`) THEN
+  MATCH_MP_TAC DIFFERENTIABLE_TRANSFORM_AT THENL
+   [EXISTS_TAC `f:real^1->real^N`; EXISTS_TAC `g:real^1->real^N`] THEN
+  EXISTS_TAC `dist(x:real^1,c)` THEN ASM_REWRITE_TAC[GSYM DIST_NZ] THEN
+  (CONJ_TAC THENL
+    [GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
+     REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB] THEN
+     ASM_REAL_ARITH_TAC;
+     FIRST_X_ASSUM MATCH_MP_TAC THEN
+     ASM_REWRITE_TAC[IN_INTERVAL_1; IN_DIFF]]));;
+
+let PIECEWISE_DIFFERENTIABLE_NEG = prove
+ (`!f:real^M->real^N s.
+        f piecewise_differentiable_on s
+        ==> (\x. --(f x)) piecewise_differentiable_on s`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[piecewise_differentiable_on] THEN
+  MATCH_MP_TAC MONO_AND THEN SIMP_TAC[CONTINUOUS_ON_NEG] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[DIFFERENTIABLE_NEG]);;
+
+let PIECEWISE_DIFFERENTIABLE_ADD = prove
+ (`!f g:real^M->real^N s.
+        f piecewise_differentiable_on s /\
+        g piecewise_differentiable_on s
+        ==> (\x. f x + g x) piecewise_differentiable_on s`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[piecewise_differentiable_on] THEN
+  DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
+  ASM_SIMP_TAC[CONTINUOUS_ON_ADD] THEN
+  FIRST_X_ASSUM(X_CHOOSE_THEN `t:real^M->bool` STRIP_ASSUME_TAC) THEN
+  FIRST_X_ASSUM(X_CHOOSE_THEN `u:real^M->bool` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `t UNION u :real^M->bool` THEN
+  ASM_SIMP_TAC[FINITE_UNION; DIFFERENTIABLE_ADD; IN_INTER;
+               SET_RULE `s DIFF (t UNION u) = (s DIFF t) INTER (s DIFF u)`]);;
+
+let PIECEWISE_DIFFERENTIABLE_SUB = prove
+ (`!f g:real^M->real^N s.
+        f piecewise_differentiable_on s /\
+        g piecewise_differentiable_on s
+        ==> (\x. f x - g x) piecewise_differentiable_on s`,
+  SIMP_TAC[VECTOR_SUB; PIECEWISE_DIFFERENTIABLE_ADD;
+           PIECEWISE_DIFFERENTIABLE_NEG]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Valid paths, and their start and finish.                                  *)
+(* ------------------------------------------------------------------------- *)
+
+let valid_path = new_definition
+ `valid_path (f:real^1->complex) <=>
+     f piecewise_differentiable_on interval[vec 0,vec 1]`;;
+
+let closed_path = new_definition
+ `closed_path g <=> pathstart g = pathfinish g`;;
+
+let VALID_PATH_COMPOSE = prove
+ (`!f g. valid_path g /\ f differentiable_on (path_image g)
+         ==> valid_path (f o g)`,
+  REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
+  REWRITE_TAC[valid_path; piecewise_differentiable_on] THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC
+   (X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC)) THEN
+  ASM_SIMP_TAC[CONTINUOUS_ON_COMPOSE; DIFFERENTIABLE_IMP_CONTINUOUS_ON] THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
+    ASM_MESON_TAC[DIFFERENTIABLE_IMP_CONTINUOUS_ON; path_image];
+    EXISTS_TAC `{vec 0:real^1,vec 1} UNION s` THEN
+    ASM_REWRITE_TAC[FINITE_UNION; FINITE_INSERT; FINITE_EMPTY] THEN
+    REWRITE_TAC[SET_RULE `s DIFF (t UNION u) = (s DIFF t) DIFF u`] THEN
+    REWRITE_TAC[GSYM OPEN_CLOSED_INTERVAL_1] THEN
+    X_GEN_TAC `t:real^1` THEN STRIP_TAC THEN
+    SUBGOAL_THEN
+     `((f:complex->complex) o (g:real^1->complex))
+      differentiable (at t within (interval(vec 0,vec 1) DIFF s))`
+    MP_TAC THENL
+     [MATCH_MP_TAC DIFFERENTIABLE_CHAIN_WITHIN THEN CONJ_TAC THENL
+       [MATCH_MP_TAC DIFFERENTIABLE_AT_WITHIN THEN
+        FIRST_X_ASSUM MATCH_MP_TAC;
+        FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [differentiable_on]) THEN
+        DISCH_THEN(MP_TAC o SPEC `(g:real^1->complex) t`) THEN
+        ANTS_TAC THENL
+         [REWRITE_TAC[path_image; IN_IMAGE] THEN EXISTS_TAC `t:real^1`;
+          MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT]
+            DIFFERENTIABLE_WITHIN_SUBSET) THEN
+          REWRITE_TAC[path_image] THEN MATCH_MP_TAC IMAGE_SUBSET]] THEN
+      MP_TAC(ISPECL [`vec 0:real^1`; `vec 1:real^1`]
+        INTERVAL_OPEN_SUBSET_CLOSED) THEN ASM SET_TAC[];
+      ASM_SIMP_TAC[DIFFERENTIABLE_WITHIN_OPEN; OPEN_DIFF; OPEN_INTERVAL;
+                   FINITE_IMP_CLOSED]]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* In particular, all results for paths apply.                               *)
+(* ------------------------------------------------------------------------- *)
+
+let VALID_PATH_IMP_PATH = prove
+ (`!g. valid_path g ==> path g`,
+  SIMP_TAC[valid_path; path; piecewise_differentiable_on]);;
+
+let CONNECTED_VALID_PATH_IMAGE = prove
+ (`!g. valid_path g ==> connected(path_image g)`,
+  MESON_TAC[CONNECTED_PATH_IMAGE; VALID_PATH_IMP_PATH]);;
+
+let COMPACT_VALID_PATH_IMAGE = prove
+ (`!g. valid_path g ==> compact(path_image g)`,
+  MESON_TAC[COMPACT_PATH_IMAGE; VALID_PATH_IMP_PATH]);;
+
+let BOUNDED_VALID_PATH_IMAGE = prove
+ (`!g. valid_path g ==> bounded(path_image g)`,
+  MESON_TAC[BOUNDED_PATH_IMAGE; VALID_PATH_IMP_PATH]);;
+
+let CLOSED_VALID_PATH_IMAGE = prove
+ (`!g. valid_path g ==> closed(path_image g)`,
+  MESON_TAC[CLOSED_PATH_IMAGE; VALID_PATH_IMP_PATH]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Theorems about rectifiable valid paths.                                   *)
+(* ------------------------------------------------------------------------- *)
+
+let RECTIFIABLE_VALID_PATH = prove
+ (`!g. valid_path g
+       ==> (rectifiable_path g <=>
+              (\t. vector_derivative g (at t)) absolutely_integrable_on
+              interval [vec 0,vec 1])`,
+  REWRITE_TAC[valid_path; piecewise_differentiable_on; GSYM path] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC RECTIFIABLE_PATH_DIFFERENTIABLE THEN
+  ASM_MESON_TAC[FINITE_IMP_COUNTABLE]);;
+
+let PATH_LENGTH_VALID_PATH = prove
+ (`!g. valid_path g /\ rectifiable_path g
+       ==> path_length g =
+                 drop(integral (interval[vec 0,vec 1])
+                               (\t. lift(norm(vector_derivative g (at t)))))`,
+  REWRITE_TAC[valid_path; piecewise_differentiable_on; GSYM path] THEN
+
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_LENGTH_DIFFERENTIABLE THEN
+  ASM_MESON_TAC[FINITE_IMP_COUNTABLE]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Negligibility of valid_path image                                         *)
+(* ------------------------------------------------------------------------- *)
+
+let NEGLIGIBLE_VALID_PATH_IMAGE = prove
+ (`!g. valid_path g ==> negligible(path_image g)`,
+  REWRITE_TAC[piecewise_differentiable_on; piecewise_differentiable_on;
+              valid_path; path_image] THEN
+  GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  DISCH_THEN(X_CHOOSE_THEN `k:real^1->bool` STRIP_ASSUME_TAC) THEN
+  MATCH_MP_TAC NEGLIGIBLE_SUBSET THEN
+  EXISTS_TAC `IMAGE (g:real^1->real^2)
+                    (k UNION (interval [vec 0,vec 1] DIFF k))` THEN
+  CONJ_TAC THENL [REWRITE_TAC[IMAGE_UNION]; SET_TAC[]] THEN
+  ASM_SIMP_TAC[NEGLIGIBLE_UNION_EQ; NEGLIGIBLE_FINITE; FINITE_IMAGE] THEN
+  MATCH_MP_TAC NEGLIGIBLE_DIFFERENTIABLE_IMAGE_LOWDIM THEN
+  REWRITE_TAC[DIMINDEX_1; DIMINDEX_2; ARITH] THEN
+  ASM_SIMP_TAC[DIFFERENTIABLE_AT_IMP_DIFFERENTIABLE_ON]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Integrals along a path (= piecewise differentiable function on [0,1]).    *)
+(* ------------------------------------------------------------------------- *)
+
+parse_as_infix("has_path_integral",(12,"right"));;
+parse_as_infix("path_integrable_on",(12,"right"));;
+
+let has_path_integral = define
+  `(f has_path_integral i) (g) <=>
+       ((\x. f(g(x)) * vector_derivative g (at x within interval[vec 0,vec 1]))
+        has_integral i)
+       (interval[vec 0,vec 1])`;;
+
+let path_integral = new_definition
+ `path_integral g f = @i. (f has_path_integral i) (g)`;;
+
+let path_integrable_on = new_definition
+ `f path_integrable_on g <=> ?i. (f has_path_integral i) g`;;
+
+let PATH_INTEGRAL_UNIQUE = prove
+ (`!f g i. (f has_path_integral i) (g) ==> path_integral(g) f = i`,
+  REWRITE_TAC[path_integral; has_path_integral; GSYM integral] THEN
+  MESON_TAC[INTEGRAL_UNIQUE]);;
+
+let HAS_PATH_INTEGRAL_INTEGRAL = prove
+ (`!f i. f path_integrable_on i
+         ==> (f has_path_integral (path_integral i f)) i`,
+  REWRITE_TAC[path_integral; path_integrable_on] THEN
+  MESON_TAC[PATH_INTEGRAL_UNIQUE]);;
+
+let HAS_PATH_INTEGRAL_UNIQUE = prove
+ (`!f i j g. (f has_path_integral i) g /\
+             (f has_path_integral j) g
+             ==> i = j`,
+  REWRITE_TAC[has_path_integral] THEN MESON_TAC[HAS_INTEGRAL_UNIQUE]);;
+
+let HAS_PATH_INTEGRAL_INTEGRABLE = prove
+ (`!f g i. (f has_path_integral i) g ==> f path_integrable_on g`,
+  REWRITE_TAC[path_integrable_on] THEN MESON_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Show that we can forget about the localized derivative.                   *)
+(* ------------------------------------------------------------------------- *)
+
+let VECTOR_DERIVATIVE_WITHIN_INTERIOR = prove
+ (`!a b x.
+        x IN interior(interval[a,b])
+        ==> vector_derivative f (at x within interval[a,b]) =
+            vector_derivative f (at x)`,
+  SIMP_TAC[vector_derivative; has_vector_derivative; has_derivative;
+           LIM_WITHIN_INTERIOR; NETLIMIT_WITHIN_INTERIOR; NETLIMIT_AT]);;
+
+let HAS_INTEGRAL_LOCALIZED_VECTOR_DERIVATIVE = prove
+ (`((\x. f' (g x) * vector_derivative g (at x within interval [a,b]))
+    has_integral i) (interval [a,b]) <=>
+    ((\x. f' (g x) * vector_derivative g (at x))
+     has_integral i) (interval [a,b])`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_INTEGRAL_SPIKE_EQ THEN
+  EXISTS_TAC `{a:real^1,b}` THEN
+  REWRITE_TAC[NEGLIGIBLE_INSERT; NEGLIGIBLE_EMPTY] THEN
+  SUBGOAL_THEN `interval[a:real^1,b] DIFF {a,b} = interior(interval[a,b])`
+   (fun th -> SIMP_TAC[th; VECTOR_DERIVATIVE_WITHIN_INTERIOR]) THEN
+  REWRITE_TAC[INTERIOR_CLOSED_INTERVAL] THEN
+  REWRITE_TAC[EXTENSION; IN_DIFF; IN_INTERVAL; IN_INSERT; NOT_IN_EMPTY] THEN
+  REWRITE_TAC[DIMINDEX_1; FORALL_1; GSYM drop; GSYM DROP_EQ] THEN
+  REAL_ARITH_TAC);;
+
+let HAS_PATH_INTEGRAL = prove
+ (`(f has_path_integral i) g <=>
+        ((\x. f (g x) * vector_derivative g (at x)) has_integral i)
+        (interval[vec 0,vec 1])`,
+  SIMP_TAC[HAS_INTEGRAL_LOCALIZED_VECTOR_DERIVATIVE; has_path_integral]);;
+
+let PATH_INTEGRABLE_ON = prove
+ (`f path_integrable_on g <=>
+        (\t. f(g t) * vector_derivative g (at t))
+            integrable_on interval[vec 0,vec 1]`,
+  REWRITE_TAC[path_integrable_on; HAS_PATH_INTEGRAL; GSYM integrable_on]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Reversing a path.                                                         *)
+(* ------------------------------------------------------------------------- *)
+
+let VALID_PATH_REVERSEPATH = prove
+ (`!g. valid_path(reversepath g) <=> valid_path g`,
+  SUBGOAL_THEN `!g. valid_path g ==> valid_path(reversepath g)`
+   (fun th -> MESON_TAC[th; REVERSEPATH_REVERSEPATH]) THEN GEN_TAC THEN
+  SIMP_TAC[valid_path; piecewise_differentiable_on; GSYM path;
+           PATH_REVERSEPATH] THEN
+  DISCH_THEN(CONJUNCTS_THEN2 (K ALL_TAC) MP_TAC) THEN
+  REWRITE_TAC[IN_DIFF] THEN
+  DISCH_THEN(X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `IMAGE (\x:real^1. vec 1 - x) s` THEN
+  ASM_SIMP_TAC[FINITE_IMAGE; reversepath] THEN
+  REPEAT STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
+  MATCH_MP_TAC DIFFERENTIABLE_CHAIN_AT THEN
+  SIMP_TAC[DIFFERENTIABLE_SUB; DIFFERENTIABLE_CONST; DIFFERENTIABLE_ID] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
+   [UNDISCH_TAC `(x:real^1) IN interval[vec 0,vec 1]` THEN
+    REWRITE_TAC[IN_INTERVAL_1; DROP_SUB; DROP_VEC] THEN REAL_ARITH_TAC;
+    DISCH_THEN(MP_TAC o ISPEC `\x:real^1. vec 1 - x` o
+     MATCH_MP FUN_IN_IMAGE) THEN
+    UNDISCH_TAC `~((x:real^1) IN IMAGE (\x. vec 1 - x) s)` THEN
+    REWRITE_TAC[VECTOR_ARITH `vec 1 - (vec 1 - x):real^1 = x`]]);;
+
+let HAS_PATH_INTEGRAL_REVERSEPATH = prove
+ (`!f g i. valid_path g /\ (f has_path_integral i) g
+           ==> (f has_path_integral (--i)) (reversepath g)`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[HAS_PATH_INTEGRAL] THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  DISCH_THEN(MP_TAC o C CONJ (REAL_ARITH `~(-- &1 = &0)`)) THEN
+  DISCH_THEN(MP_TAC o MATCH_MP HAS_INTEGRAL_AFFINITY) THEN
+  DISCH_THEN(MP_TAC o SPEC `vec 1:real^1`) THEN
+  REWRITE_TAC[IMAGE_AFFINITY_INTERVAL; INTERVAL_EQ_EMPTY_1; DROP_VEC] THEN
+  CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  REWRITE_TAC[VECTOR_ARITH `x + --x:real^1 = vec 0`] THEN
+  REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID; VECTOR_MUL_LNEG] THEN
+  REWRITE_TAC[VECTOR_MUL_LID; VECTOR_NEG_NEG; REAL_POW_ONE] THEN
+  REWRITE_TAC[reversepath; VECTOR_ARITH `-- x + a:real^N = a - x`] THEN
+  REWRITE_TAC[REAL_INV_1; VECTOR_MUL_LID] THEN
+  DISCH_THEN(MP_TAC o MATCH_MP HAS_INTEGRAL_NEG) THEN
+  REWRITE_TAC[VECTOR_SUB_RZERO] THEN
+  MATCH_MP_TAC(REWRITE_RULE [TAUT `a /\ b /\ c ==> d <=> a /\ b ==> c ==> d`]
+                HAS_INTEGRAL_SPIKE_FINITE) THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [valid_path]) THEN
+  REWRITE_TAC[piecewise_differentiable_on] THEN
+  DISCH_THEN(X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC o CONJUNCT2) THEN
+  EXISTS_TAC `IMAGE (\x:real^1. vec 1 - x) s` THEN
+  ASM_SIMP_TAC[FINITE_IMAGE] THEN X_GEN_TAC `x:real^1` THEN STRIP_TAC THEN
+  ASM_REWRITE_TAC[GSYM COMPLEX_MUL_RNEG] THEN
+  AP_TERM_TAC THEN MATCH_MP_TAC VECTOR_DERIVATIVE_AT THEN
+  GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM o_DEF] THEN
+  ONCE_REWRITE_TAC[VECTOR_ARITH `--x = --(&1) % x`] THEN
+  REWRITE_TAC[GSYM DROP_VEC; GSYM DROP_NEG] THEN
+  MATCH_MP_TAC VECTOR_DIFF_CHAIN_AT THEN REWRITE_TAC[] THEN
+  ONCE_REWRITE_TAC[VECTOR_ARITH `--x:real^N = vec 0 - x`] THEN
+  SIMP_TAC[HAS_VECTOR_DERIVATIVE_SUB; HAS_VECTOR_DERIVATIVE_CONST;
+           HAS_VECTOR_DERIVATIVE_ID] THEN
+  REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_DIFF]) THEN
+  REWRITE_TAC[IN_DIFF] THEN MATCH_MP_TAC MONO_AND THEN
+  REWRITE_TAC[CONTRAPOS_THM; IN_DIFF; IN_INTERVAL_1; DROP_SUB; DROP_VEC] THEN
+  CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[IN_IMAGE] THEN
+  MESON_TAC[VECTOR_ARITH `vec 1 - (vec 1 - x):real^1 = x`]);;
+
+let PATH_INTEGRABLE_REVERSEPATH = prove
+ (`!f g. valid_path g /\ f path_integrable_on g
+         ==> f path_integrable_on (reversepath g)`,
+  REWRITE_TAC[path_integrable_on] THEN
+  MESON_TAC[HAS_PATH_INTEGRAL_REVERSEPATH]);;
+
+let PATH_INTEGRABLE_REVERSEPATH_EQ = prove
+ (`!f g. valid_path g
+         ==> (f path_integrable_on (reversepath g) <=>
+              f path_integrable_on g)`,
+  MESON_TAC[PATH_INTEGRABLE_REVERSEPATH; VALID_PATH_REVERSEPATH;
+            REVERSEPATH_REVERSEPATH]);;
+
+let PATH_INTEGRAL_REVERSEPATH = prove
+ (`!f g. valid_path g /\ f path_integrable_on g
+         ==> path_integral (reversepath g) f = --(path_integral g f)`,
+  MESON_TAC[PATH_INTEGRAL_UNIQUE; HAS_PATH_INTEGRAL_REVERSEPATH;
+            HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Joining two paths together.                                               *)
+(* ------------------------------------------------------------------------- *)
+
+let VALID_PATH_JOIN_EQ = prove
+ (`!g1 g2.
+        pathfinish g1 = pathstart g2
+        ==> (valid_path(g1 ++ g2) <=> valid_path g1 /\ valid_path g2)`,
+  REWRITE_TAC[valid_path; piecewise_differentiable_on; GSYM path] THEN
+  ASM_SIMP_TAC[PATH_JOIN] THEN REPEAT STRIP_TAC THEN
+  ASM_CASES_TAC `path(g1:real^1->complex)` THEN ASM_REWRITE_TAC[] THEN
+  ASM_CASES_TAC `path(g2:real^1->complex)` THEN ASM_REWRITE_TAC[] THEN
+  EQ_TAC THENL
+   [DISCH_THEN(X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC) THEN
+    CONJ_TAC THENL
+     [EXISTS_TAC `(vec 0) INSERT (vec 1) INSERT
+                  {x:real^1 | ((&1 / &2) % x) IN s}` THEN
+      CONJ_TAC THENL
+       [REWRITE_TAC[FINITE_INSERT] THEN MATCH_MP_TAC FINITE_IMAGE_INJ THEN
+        ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC;
+        ALL_TAC] THEN
+      X_GEN_TAC `x:real^1` THEN
+      FIRST_X_ASSUM(MP_TAC o SPEC `(&1 / &2) % x:real^1`) THEN
+      REWRITE_TAC[IN_DIFF; IN_ELIM_THM; IN_INTERVAL_1; DROP_CMUL; DROP_VEC;
+                  IN_INSERT; DE_MORGAN_THM; GSYM DROP_EQ; NOT_EXISTS_THM] THEN
+      DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ANTS_TAC THENL
+       [ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
+        ALL_TAC] THEN
+      DISCH_TAC THEN
+      SUBGOAL_THEN
+       `(g1:real^1->complex) = (\x. g1 (&2 % x)) o (\x. &1 / &2 % x)`
+      SUBST1_TAC THENL
+       [REWRITE_TAC[FUN_EQ_THM; o_THM] THEN GEN_TAC THEN AP_TERM_TAC THEN
+        VECTOR_ARITH_TAC;
+        ALL_TAC] THEN
+      MATCH_MP_TAC DIFFERENTIABLE_CHAIN_AT THEN
+      SIMP_TAC[DIFFERENTIABLE_CMUL; DIFFERENTIABLE_ID] THEN
+      MATCH_MP_TAC DIFFERENTIABLE_TRANSFORM_AT THEN
+      EXISTS_TAC `(g1 ++ g2):real^1->complex` THEN
+      EXISTS_TAC `dist(&1 / &2 % x:real^1,lift(&1 / &2))` THEN
+      ASM_REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB; DROP_CMUL;
+                      LIFT_DROP] THEN
+      REWRITE_TAC[joinpaths] THEN
+      REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+      ASM_REAL_ARITH_TAC;
+
+      EXISTS_TAC `(vec 0) INSERT (vec 1) INSERT
+                  {x:real^1 | ((&1 / &2) % (x + vec 1)) IN s}` THEN
+      CONJ_TAC THENL
+       [REWRITE_TAC[FINITE_INSERT] THEN MATCH_MP_TAC FINITE_IMAGE_INJ THEN
+        ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC;
+        ALL_TAC] THEN
+      X_GEN_TAC `x:real^1` THEN
+      FIRST_X_ASSUM(MP_TAC o SPEC `(&1 / &2) % (x + vec 1):real^1`) THEN
+      REWRITE_TAC[IN_DIFF; IN_ELIM_THM; IN_INTERVAL_1; DROP_CMUL; DROP_VEC;
+       DROP_ADD; IN_INSERT; DE_MORGAN_THM; GSYM DROP_EQ; NOT_EXISTS_THM] THEN
+      DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ANTS_TAC THENL
+       [ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
+        ALL_TAC] THEN
+      DISCH_TAC THEN
+      SUBGOAL_THEN
+       `(g2:real^1->complex) =
+        (\x. g2 (&2 % x - vec 1)) o (\x. &1 / &2 % (x + vec 1))`
+      SUBST1_TAC THENL
+       [REWRITE_TAC[FUN_EQ_THM; o_THM] THEN GEN_TAC THEN AP_TERM_TAC THEN
+        VECTOR_ARITH_TAC;
+        ALL_TAC] THEN
+      MATCH_MP_TAC DIFFERENTIABLE_CHAIN_AT THEN
+      SIMP_TAC[DIFFERENTIABLE_CMUL; DIFFERENTIABLE_ADD;
+               DIFFERENTIABLE_CONST; DIFFERENTIABLE_ID] THEN
+      MATCH_MP_TAC DIFFERENTIABLE_TRANSFORM_AT THEN
+      EXISTS_TAC `(g1 ++ g2):real^1->complex` THEN
+      EXISTS_TAC `dist(&1 / &2 % (x + vec 1):real^1,lift(&1 / &2))` THEN
+      ASM_REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB; DROP_CMUL;
+                      DROP_ADD; DROP_VEC; LIFT_DROP] THEN
+      REWRITE_TAC[joinpaths] THEN
+      REPEAT STRIP_TAC THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
+      ASM_REAL_ARITH_TAC];
+    ALL_TAC] THEN
+  DISCH_THEN(CONJUNCTS_THEN2
+   (X_CHOOSE_THEN `s1:real^1->bool` STRIP_ASSUME_TAC)
+   (X_CHOOSE_THEN `s2:real^1->bool` STRIP_ASSUME_TAC)) THEN
+  EXISTS_TAC `(&1 / &2 % vec 1:real^1) INSERT
+              {x:real^1 | (&2 % x) IN s1} UNION
+              {x:real^1 | (&2 % x - vec 1) IN s2}` THEN
+  CONJ_TAC THENL
+   [REWRITE_TAC[FINITE_INSERT; FINITE_UNION] THEN
+    CONJ_TAC THEN MATCH_MP_TAC FINITE_IMAGE_INJ THEN
+    ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC;
+    ALL_TAC] THEN
+  X_GEN_TAC `x:real^1` THEN
+  REWRITE_TAC[IN_INTERVAL_1; IN_DIFF; DROP_VEC; IN_INSERT; IN_ELIM_THM;
+              DE_MORGAN_THM; IN_UNION; GSYM DROP_EQ; DROP_CMUL] THEN
+  STRIP_TAC THEN
+  REWRITE_TAC[joinpaths] THEN ASM_CASES_TAC `drop x <= &1 / &2` THENL
+   [MATCH_MP_TAC DIFFERENTIABLE_TRANSFORM_AT THEN
+    EXISTS_TAC `\x. (g1:real^1->complex)(&2 % x)` THEN
+    EXISTS_TAC `abs(&1 / &2 - drop x)` THEN
+    REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB; DROP_CMUL;
+                    DROP_ADD; DROP_VEC; LIFT_DROP] THEN
+    CONJ_TAC THENL
+     [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
+    CONJ_TAC THENL
+     [GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
+      ASM_REAL_ARITH_TAC;
+      ALL_TAC];
+    MATCH_MP_TAC DIFFERENTIABLE_TRANSFORM_AT THEN
+    EXISTS_TAC `\x. (g2:real^1->complex)(&2 % x - vec 1)` THEN
+    EXISTS_TAC `abs(&1 / &2 - drop x)` THEN
+    REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB; DROP_CMUL;
+                    DROP_ADD; DROP_VEC; LIFT_DROP] THEN
+    CONJ_TAC THENL
+     [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
+    CONJ_TAC THENL
+     [GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
+      ASM_REAL_ARITH_TAC;
+      ALL_TAC]] THEN
+  GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
+  MATCH_MP_TAC DIFFERENTIABLE_CHAIN_AT THEN
+  SIMP_TAC[DIFFERENTIABLE_CMUL; DIFFERENTIABLE_SUB; DIFFERENTIABLE_CONST;
+           DIFFERENTIABLE_ID] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_SUB; IN_DIFF; DROP_VEC; DROP_CMUL] THEN
+  ASM_REAL_ARITH_TAC);;
+
+let VALID_PATH_JOIN = prove
+ (`!g1 g2.
+        valid_path g1 /\ valid_path g2 /\ pathfinish g1 = pathstart g2
+        ==> valid_path(g1 ++ g2)`,
+  MESON_TAC[VALID_PATH_JOIN_EQ]);;
+
+let HAS_PATH_INTEGRAL_JOIN = prove
+ (`!f g1 g2 i1 i2.
+        (f has_path_integral i1) g1 /\
+        (f has_path_integral i2) g2 /\
+        valid_path g1 /\ valid_path g2
+        ==> (f has_path_integral (i1 + i2)) (g1 ++ g2)`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[HAS_PATH_INTEGRAL; CONJ_ASSOC] THEN
+  REPLICATE_TAC 2 (DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
+  DISCH_THEN(CONJUNCTS_THEN
+   (MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] HAS_INTEGRAL_AFFINITY))) THEN
+  DISCH_THEN(ASSUME_TAC o SPECL [`&2`; `--(vec 1):real^1`]) THEN
+  DISCH_THEN(MP_TAC o SPECL [`&2`; `vec 0:real^1`]) THEN POP_ASSUM MP_TAC THEN
+  REWRITE_TAC[DIMINDEX_1] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  REWRITE_TAC[IMAGE_AFFINITY_INTERVAL] THEN
+  REWRITE_TAC[INTERVAL_EQ_EMPTY_1; DROP_VEC] THEN
+  CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  REWRITE_TAC[VECTOR_MUL_RNEG; VECTOR_NEG_NEG; VECTOR_MUL_RZERO;
+              VECTOR_ADD_LID; VECTOR_NEG_0; VECTOR_ADD_RID;
+              VECTOR_ARITH `&1 / &2 % x + &1 / &2 % x = x:real^N`] THEN
+  REWRITE_TAC[DROP_CMUL; DROP_ADD; DROP_NEG; DROP_VEC; VECTOR_MUL_ASSOC] THEN
+  REWRITE_TAC[VECTOR_ARITH `x % (a + b) + y % b = x % a + (x + y) % b`;
+              VECTOR_ARITH `x % a + y % (a + b) = (x + y) % a + y % b`] THEN
+  REWRITE_TAC[REAL_ARITH `(&1 - (&2 * x + --(&1))) * inv(&2) = &1 - x`;
+              REAL_ARITH `&1 - x + &2 * x + --(&1) = x`;
+              REAL_ARITH `&1 - &2 * x + (&2 * x) * inv(&2) = &1 - x`;
+              REAL_ARITH `(&2 * x) * inv(&2) = x`] THEN
+  REWRITE_TAC[VECTOR_ARITH `b - inv(&2) % (a + b) = inv(&2) % (b - a)`;
+              VECTOR_ARITH `inv(&2) % (a + b) - a = inv(&2) % (b - a)`] THEN
+  REPEAT(DISCH_THEN(MP_TAC o SPEC `&2` o MATCH_MP HAS_INTEGRAL_CMUL) THEN
+         REWRITE_TAC[COMPLEX_CMUL; SIMPLE_COMPLEX_ARITH
+          `Cx(&2) * Cx(&1 / &2) * j = j /\
+           Cx(&2) * (a * Cx(inv(&2)) * b) = a * b`] THEN DISCH_TAC) THEN
+  MATCH_MP_TAC HAS_INTEGRAL_COMBINE THEN
+  EXISTS_TAC `&1 / &2 % vec 1:real^1` THEN ASM_REWRITE_TAC[] THEN
+  REWRITE_TAC[DROP_CMUL; DROP_VEC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  CONJ_TAC THEN
+  FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE
+   [TAUT `a1 /\ a2 /\ b ==> c <=> b ==> a1 /\ a2 ==> c`]
+   HAS_INTEGRAL_SPIKE_FINITE)) THENL
+   [MP_TAC(REWRITE_RULE[valid_path] (ASSUME `valid_path g1`));
+    MP_TAC(REWRITE_RULE[valid_path] (ASSUME `valid_path g2`))] THEN
+  REWRITE_TAC[piecewise_differentiable_on] THEN
+  DISCH_THEN(MP_TAC o CONJUNCT2) THEN
+  DISCH_THEN(X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC) THENL
+   [EXISTS_TAC `((&1 / &2) % vec 1) INSERT {x:real^1 | (&2 % x) IN s}`;
+    EXISTS_TAC `((&1 / &2) % vec 1) INSERT
+                {x:real^1 | (&2 % x - vec 1) IN s}`] THEN
+  (CONJ_TAC THENL
+    [REWRITE_TAC[FINITE_INSERT] THEN MATCH_MP_TAC FINITE_IMAGE_INJ THEN
+     ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC;
+     ALL_TAC]) THEN
+  ASM_SIMP_TAC[FINITE_IMAGE; FINITE_INSERT; IN_DIFF; IN_INSERT; DE_MORGAN_THM;
+              joinpaths; IN_INTERVAL_1; DROP_VEC; DROP_CMUL; GSYM DROP_EQ] THEN
+  SIMP_TAC[REAL_LT_IMP_LE; REAL_MUL_RID; IN_ELIM_THM;
+         REAL_ARITH `&1 / &2 <= x /\ ~(x = &1 / &2) ==> ~(x <= &1 / &2)`] THEN
+  REWRITE_TAC[LIFT_CMUL; LIFT_SUB; LIFT_DROP; LIFT_NUM; GSYM VECTOR_SUB] THEN
+  X_GEN_TAC `x:real^1` THEN STRIP_TAC THEN
+  MATCH_MP_TAC(COMPLEX_RING `x = Cx(&2) * y ==> g * x = Cx(&2) * g * y`) THEN
+  MATCH_MP_TAC VECTOR_DERIVATIVE_AT THEN
+  MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_TRANSFORM_AT THENL
+   [EXISTS_TAC `(\x. g1(&2 % x)):real^1->complex`;
+    EXISTS_TAC `(\x. g2(&2 % x - vec 1)):real^1->complex`] THEN
+  EXISTS_TAC `abs(drop x - &1 / &2)` THEN
+  REWRITE_TAC[DIST_REAL; GSYM drop; GSYM REAL_ABS_NZ] THEN
+  ASM_SIMP_TAC[REAL_LT_IMP_NE; REAL_SUB_0] THEN
+  (CONJ_TAC THENL
+    [GEN_TAC THEN COND_CASES_TAC THEN REWRITE_TAC[] THEN
+     ASM_REAL_ARITH_TAC;
+     ALL_TAC]) THEN
+  GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM o_DEF] THEN
+  REWRITE_TAC[GSYM COMPLEX_CMUL] THEN
+  SUBST1_TAC(SYM(SPEC `2` DROP_VEC)) THEN
+  MATCH_MP_TAC VECTOR_DIFF_CHAIN_AT THEN
+  (CONJ_TAC THENL
+    [TRY(GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_SUB_RZERO] THEN
+         MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_SUB THEN
+         REWRITE_TAC[HAS_VECTOR_DERIVATIVE_CONST]) THEN
+     REWRITE_TAC[has_vector_derivative] THEN
+     MATCH_MP_TAC(MESON[HAS_DERIVATIVE_LINEAR]
+      `f = g /\ linear f ==> (f has_derivative g) net`) THEN
+     REWRITE_TAC[linear; FUN_EQ_THM; DROP_VEC] THEN
+     REWRITE_TAC[GSYM DROP_EQ; DROP_ADD; DROP_CMUL; DROP_VEC] THEN
+     REAL_ARITH_TAC;
+     REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN
+     FIRST_X_ASSUM MATCH_MP_TAC THEN
+     ASM_SIMP_TAC[IN_DIFF; IN_INTERVAL_1; DROP_SUB; DROP_CMUL; DROP_VEC] THEN
+     ASM_REAL_ARITH_TAC]));;
+
+let PATH_INTEGRABLE_JOIN = prove
+ (`!f g1 g2.
+        valid_path g1 /\ valid_path g2
+        ==> (f path_integrable_on (g1 ++ g2) <=>
+             f path_integrable_on g1 /\ f path_integrable_on g2)`,
+  REPEAT STRIP_TAC THEN EQ_TAC THENL
+   [ALL_TAC;
+    REWRITE_TAC[path_integrable_on] THEN
+    ASM_MESON_TAC[HAS_PATH_INTEGRAL_JOIN]] THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[valid_path]) THEN
+  REWRITE_TAC[PATH_INTEGRABLE_ON; joinpaths] THEN REPEAT STRIP_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o MATCH_MP
+   (REWRITE_RULE[IMP_CONJ] INTEGRABLE_ON_SUBINTERVAL))
+  THENL
+   [DISCH_THEN(MP_TAC o SPECL [`lift(&0)`; `lift(&1 / &2)`]);
+    DISCH_THEN(MP_TAC o SPECL [`lift(&1 / &2)`; `lift(&1)`])] THEN
+  REWRITE_TAC[SUBSET_INTERVAL_1; DROP_VEC; LIFT_DROP] THEN
+  CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  DISCH_THEN(MP_TAC o MATCH_MP
+   (REWRITE_RULE[IMP_CONJ] INTEGRABLE_AFFINITY))
+  THENL
+   [DISCH_THEN(MP_TAC o SPECL [`&1 / &2`; `vec 0:real^1`]);
+    DISCH_THEN(MP_TAC o SPECL [`&1 / &2`; `lift(&1 / &2)`])] THEN
+  REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  REWRITE_TAC[IMAGE_AFFINITY_INTERVAL; INTERVAL_EQ_EMPTY_1] THEN
+  REWRITE_TAC[LIFT_DROP; LIFT_NUM; VECTOR_MUL_RZERO; VECTOR_NEG_0;
+              GSYM LIFT_CMUL; VECTOR_ADD_RID; VECTOR_MUL_RNEG] THEN
+  CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[LIFT_NUM] THEN
+  REWRITE_TAC[VECTOR_ARITH `vec 2 + --vec 1:real^1 = vec 1`;
+              VECTOR_ARITH `vec 1 + --vec 1:real^1 = vec 0`] THEN
+  DISCH_THEN(MP_TAC o SPEC `&1 / &2` o MATCH_MP INTEGRABLE_CMUL) THEN
+  REWRITE_TAC[] THEN MATCH_MP_TAC INTEGRABLE_SPIKE_FINITE THEN
+  REWRITE_TAC[IN_DIFF; IN_INTERVAL_1; DROP_VEC; DROP_CMUL; DROP_ADD;
+              LIFT_DROP; COMPLEX_CMUL] THEN
+  REWRITE_TAC[COMPLEX_RING `a * b = Cx(&1 / &2) * x * y <=>
+                                x * y = a * Cx(&2) * b`]
+  THENL
+   [UNDISCH_TAC `(g1:real^1->complex) piecewise_differentiable_on
+                        interval[vec 0,vec 1]`;
+    UNDISCH_TAC `(g2:real^1->complex) piecewise_differentiable_on
+                        interval[vec 0,vec 1]`] THEN
+  REWRITE_TAC[piecewise_differentiable_on] THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  DISCH_THEN(X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `(vec 0:real^1) INSERT (vec 1) INSERT s` THEN
+  ASM_REWRITE_TAC[FINITE_INSERT; IN_INSERT; DE_MORGAN_THM] THEN
+  REWRITE_TAC[GSYM DROP_EQ; DROP_VEC] THEN X_GEN_TAC `t:real^1` THEN
+  STRIP_TAC THEN BINOP_TAC THENL
+   [AP_TERM_TAC THEN
+    ASM_SIMP_TAC[REAL_ARITH `x <= &1 ==> &1 / &2 * x <= &1 / &2`] THEN
+    AP_TERM_TAC THEN VECTOR_ARITH_TAC;
+    ALL_TAC;
+    AP_TERM_TAC THEN ASM_SIMP_TAC[REAL_ARITH
+     `&0 <= t /\ ~(t = &0) ==> ~(&1 / &2 * t + &1 / &2 <= &1 / &2)`] THEN
+    AP_TERM_TAC THEN
+    REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_ADD; DROP_SUB; LIFT_DROP] THEN
+    REWRITE_TAC[DROP_VEC] THEN REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  MATCH_MP_TAC VECTOR_DERIVATIVE_AT THEN
+  MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_TRANSFORM_AT THENL
+   [EXISTS_TAC `(\x. g1(&2 % x)):real^1->complex` THEN
+    EXISTS_TAC `abs(drop t - &1) / &2` THEN
+    ASM_SIMP_TAC[REAL_ARITH `&0 < abs x / &2 <=> ~(x = &0)`; REAL_SUB_0] THEN
+    REWRITE_TAC[DIST_REAL; GSYM drop; DROP_CMUL] THEN
+    CONJ_TAC THENL
+     [ASM_MESON_TAC[REAL_ARITH
+       `t <= &1 /\ ~(t = &1) /\ abs(x - &1 / &2 * t) < abs(t - &1) / &2
+        ==> x <= &1 / &2`];
+      ALL_TAC];
+    EXISTS_TAC `(\x. g2(&2 % x - vec 1)):real^1->complex` THEN
+    EXISTS_TAC `abs(drop t) / &2` THEN
+    ASM_SIMP_TAC[REAL_ARITH `&0 < abs x / &2 <=> ~(x = &0)`; REAL_SUB_0] THEN
+    REWRITE_TAC[DIST_REAL; GSYM drop; DROP_CMUL; DROP_ADD; LIFT_DROP] THEN
+    CONJ_TAC THENL
+     [ASM_MESON_TAC[REAL_ARITH
+       `&0 <= t /\ abs(x - (&1 / &2 * t + &1 / &2)) < abs(t) / &2
+        ==> ~(x <= &1 / &2)`];
+      ALL_TAC]] THEN
+  GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM o_DEF] THEN
+  REWRITE_TAC[GSYM COMPLEX_CMUL] THEN
+  SUBST1_TAC(SYM(SPEC `2` DROP_VEC)) THEN
+  MATCH_MP_TAC VECTOR_DIFF_CHAIN_AT THEN
+  (CONJ_TAC THENL
+    [TRY(GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_SUB_RZERO] THEN
+         MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_SUB THEN
+         REWRITE_TAC[HAS_VECTOR_DERIVATIVE_CONST]) THEN
+     REWRITE_TAC[has_vector_derivative] THEN
+     MATCH_MP_TAC(MESON[HAS_DERIVATIVE_LINEAR]
+      `f = g /\ linear f ==> (f has_derivative g) net`) THEN
+     REWRITE_TAC[linear; FUN_EQ_THM; DROP_VEC] THEN
+     REWRITE_TAC[GSYM DROP_EQ; DROP_ADD; DROP_CMUL; DROP_VEC] THEN
+     REAL_ARITH_TAC;
+     MATCH_MP_TAC(MESON[VECTOR_DERIVATIVE_WORKS]
+       `f differentiable (at t) /\ t' = t
+        ==> (f has_vector_derivative
+                  (vector_derivative f (at t))) (at t')`) THEN
+     CONJ_TAC THENL
+      [FIRST_X_ASSUM MATCH_MP_TAC THEN
+       ASM_REWRITE_TAC[IN_DIFF; IN_INTERVAL_1; DROP_VEC];
+       ALL_TAC] THEN
+     REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_ADD; DROP_SUB; LIFT_DROP;
+                 DROP_VEC] THEN
+     REAL_ARITH_TAC]));;
+
+let PATH_INTEGRAL_JOIN = prove
+ (`!f g1 g2:real^1->complex.
+        valid_path g1 /\ valid_path g2 /\
+        f path_integrable_on g1 /\ f path_integrable_on g2
+        ==> path_integral (g1 ++ g2) f =
+            path_integral g1 f + path_integral g2 f`,
+  MESON_TAC[PATH_INTEGRAL_UNIQUE; HAS_PATH_INTEGRAL_INTEGRAL;
+            HAS_PATH_INTEGRAL_JOIN]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Reparametrizing to shift the starting point of a (closed) path.           *)
+(* ------------------------------------------------------------------------- *)
+
+let VALID_PATH_SHIFTPATH = prove
+ (`!g a. valid_path g /\ pathfinish g = pathstart g /\
+         a IN interval[vec 0,vec 1]
+         ==> valid_path(shiftpath a g)`,
+  REWRITE_TAC[valid_path; shiftpath; DROP_ADD; GSYM DROP_VEC] THEN
+  REWRITE_TAC[REAL_ARITH `a + x <= y <=> x <= y - a`; GSYM DROP_SUB] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PIECEWISE_DIFFERENTIABLE_CASES THEN
+  REPLICATE_TAC 2 (CONJ_TAC THENL
+   [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN
+    REWRITE_TAC[DROP_SUB; DROP_VEC] THEN REAL_ARITH_TAC;
+    ALL_TAC]) THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish]) THEN
+  ASM_REWRITE_TAC[VECTOR_ARITH `a + vec 1 - a - vec 1:real^1 = vec 0`;
+                  VECTOR_ARITH `a + vec 1 - a:real^1 = vec 1`] THEN
+  CONJ_TAC THENL
+   [ONCE_REWRITE_TAC[VECTOR_ARITH `a + x:real^1 = &1 % x + a`];
+    ONCE_REWRITE_TAC[VECTOR_ARITH
+     `a + x - vec 1:real^1 = &1 % x + (a - vec 1)`]] THEN
+  GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
+  MATCH_MP_TAC PIECEWISE_DIFFERENTIABLE_AFFINE THEN
+  MATCH_MP_TAC PIECEWISE_DIFFERENTIABLE_ON_SUBSET THEN
+  EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN
+  REWRITE_TAC[IMAGE_AFFINITY_INTERVAL; REAL_POS; INTERVAL_EQ_EMPTY_1;
+              IN_INTERVAL_1; DROP_SUB; DROP_VEC] THEN
+  ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
+  REWRITE_TAC[EMPTY_SUBSET; SUBSET_INTERVAL_1; DROP_ADD; DROP_CMUL;
+              DROP_SUB; DROP_VEC] THEN
+  REAL_ARITH_TAC);;
+
+let HAS_PATH_INTEGRAL_SHIFTPATH = prove
+ (`!f g i a.
+        (f has_path_integral i) g /\ valid_path g /\
+        a IN interval[vec 0,vec 1]
+        ==> (f has_path_integral i) (shiftpath a g)`,
+  REWRITE_TAC[HAS_PATH_INTEGRAL; IN_INTERVAL_1; DROP_VEC] THEN
+  REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN
+   `i = integral (interval[a,vec 1])
+                 (\x. f ((g:real^1->real^2) x) * vector_derivative g (at x)) +
+        integral (interval[vec 0,a])
+                 (\x. f (g x) * vector_derivative g (at x))`
+  SUBST1_TAC THENL
+   [MATCH_MP_TAC(INST_TYPE [`:1`,`:M`; `:2`,`:N`] HAS_INTEGRAL_UNIQUE) THEN
+    MAP_EVERY EXISTS_TAC
+     [`\x. f ((g:real^1->real^2) x) * vector_derivative g (at x)`;
+      `interval[vec 0:real^1,vec 1]`] THEN
+    ONCE_REWRITE_TAC[COMPLEX_ADD_SYM] THEN ASM_REWRITE_TAC[] THEN
+    MATCH_MP_TAC HAS_INTEGRAL_COMBINE THEN EXISTS_TAC `a:real^1` THEN
+    ASM_REWRITE_TAC[DROP_VEC] THEN
+    CONJ_TAC THEN MATCH_MP_TAC INTEGRABLE_INTEGRAL THEN
+    MATCH_MP_TAC INTEGRABLE_SUBINTERVAL THEN
+    MAP_EVERY EXISTS_TAC [`vec 0:real^1`; `vec 1:real^1`] THEN
+    (CONJ_TAC THENL [ASM_MESON_TAC[integrable_on]; ALL_TAC]) THEN
+    REWRITE_TAC[DROP_SUB; DROP_VEC; SUBSET_INTERVAL_1] THEN
+    ASM_REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  MATCH_MP_TAC HAS_INTEGRAL_COMBINE THEN EXISTS_TAC `vec 1 - a:real^1` THEN
+  ASM_REWRITE_TAC[DROP_SUB; DROP_VEC; REAL_SUB_LE;
+                  REAL_ARITH `&1 - x <= &1 <=> &0 <= x`] THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [valid_path]) THEN
+  REWRITE_TAC[piecewise_differentiable_on] THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  DISCH_THEN(X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC) THEN
+  REWRITE_TAC[shiftpath] THEN CONJ_TAC THEN
+  MATCH_MP_TAC HAS_INTEGRAL_SPIKE_FINITE THENL
+   [EXISTS_TAC `\x. f(g(a + x)) * vector_derivative g (at(a + x))` THEN
+    EXISTS_TAC `(vec 1 - a) INSERT IMAGE (\x:real^1. x - a) s` THEN
+    ASM_SIMP_TAC[FINITE_IMAGE; FINITE_INSERT] THEN CONJ_TAC THENL
+     [X_GEN_TAC `x:real^1` THEN
+      REWRITE_TAC[IN_DIFF; IN_INTERVAL_1; IN_INSERT; IN_IMAGE; UNWIND_THM2;
+                  DROP_SUB; DROP_ADD; DROP_VEC; DE_MORGAN_THM;
+                  VECTOR_ARITH `x:real^1 = y - a <=> y = a + x`] THEN
+      REWRITE_TAC[GSYM DROP_EQ; DROP_ADD; DROP_VEC] THEN STRIP_TAC THEN
+      ASM_SIMP_TAC[REAL_ARITH `x <= &1 - a ==> a + x <= &1`] THEN
+      AP_TERM_TAC THEN MATCH_MP_TAC VECTOR_DERIVATIVE_AT THEN
+      MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_TRANSFORM_AT THEN
+      MAP_EVERY EXISTS_TAC
+       [`\x. (g:real^1->complex)(a + x)`; `dist(vec 1 - a:real^1,x)`] THEN
+      SIMP_TAC[CONJ_ASSOC; dist; NORM_REAL; GSYM drop; DROP_VEC; DROP_SUB] THEN
+      CONJ_TAC THENL
+       [REPEAT STRIP_TAC THEN REPEAT COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
+        ASM_REAL_ARITH_TAC;
+        ALL_TAC] THEN
+      GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM o_DEF] THEN
+      GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_MUL_LID] THEN
+      REWRITE_TAC[GSYM DROP_VEC] THEN MATCH_MP_TAC VECTOR_DIFF_CHAIN_AT THEN
+      SUBST1_TAC(VECTOR_ARITH `vec 1:real^1 = vec 0 + vec 1`) THEN
+      SIMP_TAC[HAS_VECTOR_DERIVATIVE_ADD; HAS_VECTOR_DERIVATIVE_CONST;
+               HAS_VECTOR_DERIVATIVE_ID] THEN
+      REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN
+      FIRST_X_ASSUM MATCH_MP_TAC THEN
+      ASM_REWRITE_TAC[IN_DIFF; IN_INTERVAL_1; DROP_VEC; DROP_ADD] THEN
+      ASM_REAL_ARITH_TAC;
+      ALL_TAC] THEN
+    SUBGOAL_THEN `(\x. f (g x) * vector_derivative g (at x)) integrable_on
+                  (interval [a,vec 1])`
+    MP_TAC THENL
+     [MATCH_MP_TAC INTEGRABLE_SUBINTERVAL THEN
+      MAP_EVERY EXISTS_TAC [`vec 0:real^1`; `vec 1:real^1`] THEN
+      CONJ_TAC THENL [ASM_MESON_TAC[integrable_on]; ALL_TAC] THEN
+      ASM_REWRITE_TAC[DROP_SUB; DROP_VEC; SUBSET_INTERVAL_1; REAL_LE_REFL];
+      ALL_TAC] THEN
+    DISCH_THEN(MP_TAC o C CONJ (REAL_ARITH `~(&1 = &0)`) o MATCH_MP
+      INTEGRABLE_INTEGRAL) THEN
+    DISCH_THEN(MP_TAC o SPEC `a:real^1` o MATCH_MP HAS_INTEGRAL_AFFINITY) THEN
+    REWRITE_TAC[IMAGE_AFFINITY_INTERVAL] THEN
+    REWRITE_TAC[VECTOR_ARITH `&1 % x + a:real^1 = a + x`] THEN
+    REWRITE_TAC[REAL_INV_1; REAL_POS; REAL_ABS_NUM; REAL_POW_ONE] THEN
+    ASM_REWRITE_TAC[INTERVAL_EQ_EMPTY_1; DROP_VEC; GSYM REAL_NOT_LE] THEN
+    REWRITE_TAC[VECTOR_MUL_LID; GSYM VECTOR_SUB; VECTOR_SUB_REFL];
+    EXISTS_TAC `\x. f(g(a + x - vec 1)) *
+                    vector_derivative g (at(a + x - vec 1))` THEN
+    EXISTS_TAC `(vec 1 - a) INSERT IMAGE (\x:real^1. x - a + vec 1) s` THEN
+    ASM_SIMP_TAC[FINITE_IMAGE; FINITE_INSERT] THEN CONJ_TAC THENL
+     [X_GEN_TAC `x:real^1` THEN
+      REWRITE_TAC[IN_DIFF; IN_INTERVAL_1; IN_INSERT; IN_IMAGE; UNWIND_THM2;
+                  DROP_SUB; DROP_ADD; DROP_VEC; DE_MORGAN_THM;
+                  VECTOR_ARITH `x:real^1 = y - a + z <=> y = a + (x - z)`] THEN
+      REWRITE_TAC[GSYM DROP_EQ; DROP_ADD; DROP_VEC; DROP_SUB] THEN
+      STRIP_TAC THEN
+      ASM_SIMP_TAC[REAL_ARITH
+       `&1 - a <= x /\ ~(x = &1 - a) ==> ~(a + x <= &1)`] THEN
+      AP_TERM_TAC THEN MATCH_MP_TAC VECTOR_DERIVATIVE_AT THEN
+      MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_TRANSFORM_AT THEN
+      MAP_EVERY EXISTS_TAC
+       [`\x. (g:real^1->complex)(a + x - vec 1)`;
+        `dist(vec 1 - a:real^1,x)`] THEN
+      SIMP_TAC[CONJ_ASSOC; dist; NORM_REAL; GSYM drop; DROP_VEC; DROP_SUB] THEN
+      CONJ_TAC THENL
+       [REPEAT STRIP_TAC THEN REPEAT COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
+        ASM_REAL_ARITH_TAC;
+        ALL_TAC] THEN
+      GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM o_DEF] THEN
+      GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_MUL_LID] THEN
+      REWRITE_TAC[GSYM DROP_VEC] THEN MATCH_MP_TAC VECTOR_DIFF_CHAIN_AT THEN
+      CONJ_TAC THENL
+       [GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_LID] THEN
+        ONCE_REWRITE_TAC[VECTOR_ARITH
+         `a + x - vec 1:real^1 = (a - vec 1) + x`] THEN
+        SIMP_TAC[HAS_VECTOR_DERIVATIVE_ADD; HAS_VECTOR_DERIVATIVE_CONST;
+                 HAS_VECTOR_DERIVATIVE_ID];
+        ALL_TAC] THEN
+      REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN
+      FIRST_X_ASSUM MATCH_MP_TAC THEN
+      ASM_SIMP_TAC[IN_DIFF; DROP_SUB; IN_INTERVAL_1; DROP_VEC; DROP_ADD] THEN
+      ASM_REAL_ARITH_TAC;
+      ALL_TAC] THEN
+    SUBGOAL_THEN `(\x. f (g x) * vector_derivative g (at x)) integrable_on
+                  (interval [vec 0,a])`
+    MP_TAC THENL
+     [MATCH_MP_TAC INTEGRABLE_SUBINTERVAL THEN
+      MAP_EVERY EXISTS_TAC [`vec 0:real^1`; `vec 1:real^1`] THEN
+      CONJ_TAC THENL [ASM_MESON_TAC[integrable_on]; ALL_TAC] THEN
+      ASM_REWRITE_TAC[DROP_SUB; DROP_VEC; SUBSET_INTERVAL_1; REAL_LE_REFL];
+      ALL_TAC] THEN
+    DISCH_THEN(MP_TAC o C CONJ (REAL_ARITH `~(&1 = &0)`) o MATCH_MP
+      INTEGRABLE_INTEGRAL) THEN
+    DISCH_THEN(MP_TAC o SPEC `a - vec 1:real^1` o
+      MATCH_MP HAS_INTEGRAL_AFFINITY) THEN
+    REWRITE_TAC[IMAGE_AFFINITY_INTERVAL] THEN
+    REWRITE_TAC[VECTOR_ARITH `&1 % x + a - vec 1:real^1 = a + x - vec 1`] THEN
+    REWRITE_TAC[REAL_INV_1; REAL_POS; REAL_ABS_NUM; REAL_POW_ONE] THEN
+    ASM_REWRITE_TAC[INTERVAL_EQ_EMPTY_1; DROP_VEC; GSYM REAL_NOT_LE] THEN
+    REWRITE_TAC[VECTOR_MUL_LID;
+                VECTOR_ARITH `vec 0 + --(a - vec 1):real^1 = vec 1 - a`;
+                VECTOR_ARITH `a + --(a - vec 1):real^1 = vec 1`]]);;
+
+let HAS_PATH_INTEGRAL_SHIFTPATH_EQ = prove
+ (`!f g i a.
+        valid_path g /\ pathfinish g = pathstart g /\
+        a IN interval[vec 0,vec 1]
+        ==> ((f has_path_integral i) (shiftpath a g) <=>
+             (f has_path_integral i) g)`,
+  REPEAT STRIP_TAC THEN EQ_TAC THEN STRIP_TAC THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_SHIFTPATH] THEN
+  SUBGOAL_THEN
+   `(f has_path_integral i) (shiftpath (vec 1 - a) (shiftpath a g))`
+  MP_TAC THENL
+   [MATCH_MP_TAC HAS_PATH_INTEGRAL_SHIFTPATH THEN
+    ASM_SIMP_TAC[VALID_PATH_SHIFTPATH] THEN REPEAT(POP_ASSUM MP_TAC) THEN
+    REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_SUB] THEN REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  REWRITE_TAC[HAS_PATH_INTEGRAL] THEN MATCH_MP_TAC EQ_IMP THEN
+  MATCH_MP_TAC HAS_INTEGRAL_SPIKE_FINITE_EQ THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [valid_path]) THEN
+  REWRITE_TAC[piecewise_differentiable_on] THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  DISCH_THEN(X_CHOOSE_THEN `s:real^1->bool` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `(s:real^1->bool) UNION {vec 0,vec 1}` THEN
+  ASM_SIMP_TAC[FINITE_UNION; FINITE_RULES] THEN
+  REWRITE_TAC[SET_RULE `s DIFF (t UNION u) = (s DIFF u) DIFF t`] THEN
+  REWRITE_TAC[GSYM OPEN_CLOSED_INTERVAL_1] THEN X_GEN_TAC `x:real^1` THEN
+  STRIP_TAC THEN   BINOP_TAC THEN CONV_TAC SYM_CONV THENL
+   [AP_TERM_TAC THEN MATCH_MP_TAC SHIFTPATH_SHIFTPATH THEN ASM_SIMP_TAC[] THEN
+    ASM_MESON_TAC[INTERVAL_OPEN_SUBSET_CLOSED; SUBSET; IN_DIFF];
+    ALL_TAC] THEN
+  MATCH_MP_TAC VECTOR_DERIVATIVE_AT THEN
+  MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_TRANSFORM_WITHIN_OPEN THEN
+  MAP_EVERY EXISTS_TAC
+   [`g:real^1->real^2`; `interval(vec 0,vec 1) DIFF s:real^1->bool`] THEN
+  ASM_SIMP_TAC[GSYM VECTOR_DERIVATIVE_WORKS; OPEN_DIFF; FINITE_IMP_CLOSED;
+               OPEN_INTERVAL] THEN
+  REPEAT STRIP_TAC THENL
+   [CONV_TAC SYM_CONV THEN MATCH_MP_TAC SHIFTPATH_SHIFTPATH;
+    FIRST_X_ASSUM MATCH_MP_TAC] THEN
+  ASM_MESON_TAC[INTERVAL_OPEN_SUBSET_CLOSED; SUBSET; IN_DIFF]);;
+
+let PATH_INTEGRAL_SHIFTPATH = prove
+ (`!f g a. valid_path g /\ pathfinish g = pathstart g /\
+           a IN interval[vec 0,vec 1]
+           ==> path_integral (shiftpath a g) f = path_integral g f`,
+  SIMP_TAC[path_integral; HAS_PATH_INTEGRAL_SHIFTPATH_EQ]);;
+
+(* ------------------------------------------------------------------------- *)
+(* More about straight-line paths.                                           *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_VECTOR_DERIVATIVE_LINEPATH_WITHIN = prove
+ (`!a b:complex x s.
+    (linepath(a,b) has_vector_derivative (b - a)) (at x within s)`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[linepath; has_vector_derivative] THEN
+  ONCE_REWRITE_TAC[VECTOR_ARITH `u % (b - a) = vec 0 + u % (b - a)`] THEN
+  REWRITE_TAC[VECTOR_ARITH `(&1 - u) % a + u % b = a + u % (b - a)`] THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_ADD THEN REWRITE_TAC[HAS_DERIVATIVE_CONST] THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_VMUL_DROP THEN REWRITE_TAC[HAS_DERIVATIVE_ID]);;
+
+let HAS_VECTOR_DERIVATIVE_LINEPATH_AT = prove
+ (`!a b:complex x.
+    (linepath(a,b) has_vector_derivative (b - a)) (at x)`,
+  MESON_TAC[WITHIN_UNIV; HAS_VECTOR_DERIVATIVE_LINEPATH_WITHIN]);;
+
+let VALID_PATH_LINEPATH = prove
+ (`!a b. valid_path(linepath(a,b))`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[valid_path] THEN
+  MATCH_MP_TAC DIFFERENTIABLE_ON_IMP_PIECEWISE_DIFFERENTIABLE THEN
+  REWRITE_TAC[differentiable_on; differentiable] THEN
+  MESON_TAC[HAS_VECTOR_DERIVATIVE_LINEPATH_WITHIN; has_vector_derivative]);;
+
+let VECTOR_DERIVATIVE_LINEPATH_WITHIN = prove
+ (`!a b x. x IN interval[vec 0,vec 1]
+           ==> vector_derivative (linepath(a,b))
+                (at x within interval[vec 0,vec 1]) = b - a`,
+  REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC VECTOR_DERIVATIVE_WITHIN_CLOSED_INTERVAL THEN
+  ASM_REWRITE_TAC[HAS_VECTOR_DERIVATIVE_LINEPATH_WITHIN] THEN
+  REWRITE_TAC[DROP_VEC; REAL_LT_01]);;
+
+let VECTOR_DERIVATIVE_LINEPATH_AT = prove
+ (`!a b x. vector_derivative (linepath(a,b)) (at x) = b - a`,
+  REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC VECTOR_DERIVATIVE_AT THEN
+  ASM_REWRITE_TAC[HAS_VECTOR_DERIVATIVE_LINEPATH_AT]);;
+
+let HAS_PATH_INTEGRAL_LINEPATH = prove
+ (`!f i a b. (f has_path_integral i) (linepath(a,b)) <=>
+             ((\x. f(linepath(a,b) x) * (b - a)) has_integral i)
+             (interval[vec 0,vec 1])`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[has_path_integral] THEN
+  MATCH_MP_TAC HAS_INTEGRAL_EQ_EQ THEN
+  SIMP_TAC[VECTOR_DERIVATIVE_LINEPATH_WITHIN]);;
+
+let LINEPATH_IN_PATH = prove
+ (`!x. x IN interval[vec 0,vec 1] ==> linepath(a,b) x IN segment[a,b]`,
+  REWRITE_TAC[segment; linepath; IN_ELIM_THM; IN_INTERVAL_1; DROP_VEC] THEN
+  MESON_TAC[]);;
+
+let RE_LINEPATH_CX = prove
+ (`!a b x. Re(linepath(Cx a,Cx b) x) = (&1 - drop x) * a + drop x * b`,
+  REWRITE_TAC[linepath; RE_ADD; COMPLEX_CMUL; RE_MUL_CX; RE_CX]);;
+
+let IM_LINEPATH_CX = prove
+ (`!a b x. Im(linepath(Cx a,Cx b) x) = &0`,
+  REWRITE_TAC[linepath; IM_ADD; COMPLEX_CMUL; IM_MUL_CX; IM_CX] THEN
+  REAL_ARITH_TAC);;
+
+let LINEPATH_CX = prove
+ (`!a b x. linepath(Cx a,Cx b) x = Cx((&1 - drop x) * a + drop x * b)`,
+  REWRITE_TAC[COMPLEX_EQ; RE_LINEPATH_CX; IM_LINEPATH_CX; RE_CX; IM_CX]);;
+
+let HAS_PATH_INTEGRAL_TRIVIAL = prove
+ (`!f a. (f has_path_integral (Cx(&0))) (linepath(a,a))`,
+  REWRITE_TAC[HAS_PATH_INTEGRAL_LINEPATH; COMPLEX_SUB_REFL;
+              COMPLEX_MUL_RZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_INTEGRAL_0]);;
+
+let PATH_INTEGRAL_TRIVIAL = prove
+ (`!f a. path_integral (linepath(a,a)) f = Cx(&0)`,
+  MESON_TAC[HAS_PATH_INTEGRAL_TRIVIAL; PATH_INTEGRAL_UNIQUE]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Relation to subpath construction.                                         *)
+(* ------------------------------------------------------------------------- *)
+
+let VALID_PATH_SUBPATH = prove
+ (`!g u v. valid_path g /\
+           u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1]
+           ==> valid_path(subpath u v g)`,
+  SIMP_TAC[valid_path; PATH_SUBPATH] THEN
+  REPEAT STRIP_TAC THEN REWRITE_TAC[subpath] THEN
+  ASM_CASES_TAC `v:real^1 = u` THENL
+   [MATCH_MP_TAC DIFFERENTIABLE_ON_IMP_PIECEWISE_DIFFERENTIABLE THEN
+    ASM_REWRITE_TAC[VECTOR_SUB_REFL; VECTOR_MUL_LZERO; DROP_VEC] THEN
+    REWRITE_TAC[DIFFERENTIABLE_ON_CONST];
+    MATCH_MP_TAC(REWRITE_RULE[o_DEF] PIECEWISE_DIFFERENTIABLE_COMPOSE) THEN
+    REPEAT CONJ_TAC THENL
+     [MATCH_MP_TAC DIFFERENTIABLE_ON_IMP_PIECEWISE_DIFFERENTIABLE THEN
+      MATCH_MP_TAC DIFFERENTIABLE_AT_IMP_DIFFERENTIABLE_ON THEN
+      REPEAT STRIP_TAC THEN MATCH_MP_TAC DIFFERENTIABLE_ADD THEN
+      REWRITE_TAC[DIFFERENTIABLE_CONST] THEN
+      MATCH_MP_TAC DIFFERENTIABLE_CMUL THEN REWRITE_TAC[DIFFERENTIABLE_ID];
+      MATCH_MP_TAC PIECEWISE_DIFFERENTIABLE_ON_SUBSET THEN
+      EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN ASM_REWRITE_TAC[] THEN
+      ONCE_REWRITE_TAC[VECTOR_ADD_SYM] THEN
+      REWRITE_TAC[IMAGE_AFFINITY_INTERVAL] THEN
+      REPEAT(COND_CASES_TAC THEN REWRITE_TAC[EMPTY_SUBSET]) THEN
+      REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1])) THEN
+      SIMP_TAC[SUBSET_INTERVAL_1; DROP_ADD; DROP_CMUL; DROP_SUB; DROP_VEC] THEN
+      REAL_ARITH_TAC;
+      REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_ADD; DROP_SUB] THEN
+      ASM_SIMP_TAC[DROP_EQ; REAL_FIELD `~(u:real = v) ==>
+        (u + (v - u) * x = b <=> x = (b - u) / (v - u))`] THEN
+      X_GEN_TAC `b:real^1` THEN MATCH_MP_TAC FINITE_SUBSET THEN
+      EXISTS_TAC `{lift((drop b - drop u) / (drop v - drop u))}` THEN
+      REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY; SUBSET; IN_ELIM_THM] THEN
+      SIMP_TAC[GSYM LIFT_EQ; LIFT_DROP; IN_SING]]]);;
+
+let HAS_PATH_INTEGRAL_SUBPATH_REFL = prove
+ (`!f g u. (f has_path_integral (Cx(&0))) (subpath u u g)`,
+  REWRITE_TAC[HAS_PATH_INTEGRAL; subpath; VECTOR_SUB_REFL] THEN
+  REWRITE_TAC[DROP_VEC; VECTOR_MUL_LZERO; VECTOR_DERIVATIVE_CONST_AT] THEN
+  REWRITE_TAC[COMPLEX_VEC_0; COMPLEX_MUL_RZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_INTEGRAL_0]);;
+
+let PATH_INTEGRABLE_SUBPATH_REFL = prove
+ (`!f g u. f path_integrable_on (subpath u u g)`,
+  REWRITE_TAC[path_integrable_on] THEN
+  MESON_TAC[HAS_PATH_INTEGRAL_SUBPATH_REFL]);;
+
+let PATH_INTEGRAL_SUBPATH_REFL = prove
+ (`!f g u. path_integral (subpath u u g) f = Cx(&0)`,
+  MESON_TAC[PATH_INTEGRAL_UNIQUE; HAS_PATH_INTEGRAL_SUBPATH_REFL]);;
+
+let HAS_PATH_INTEGRAL_SUBPATH = prove
+ (`!f g u v.
+        valid_path g /\ f path_integrable_on g /\
+        u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] /\
+        drop u <= drop v
+        ==> (f has_path_integral
+             integral (interval[u,v])
+                      (\x. f(g x) * vector_derivative g (at x)))
+            (subpath u v g)`,
+  REWRITE_TAC[path_integrable_on; HAS_PATH_INTEGRAL; subpath] THEN
+  REWRITE_TAC[GSYM integrable_on] THEN REPEAT STRIP_TAC THEN
+  ASM_CASES_TAC `v:real^1 = u` THENL
+   [ASM_REWRITE_TAC[INTEGRAL_REFL; VECTOR_SUB_REFL; DROP_VEC] THEN
+    REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_DERIVATIVE_CONST_AT] THEN
+    REWRITE_TAC[COMPLEX_VEC_0; COMPLEX_MUL_RZERO] THEN
+    REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_INTEGRAL_0];
+    SUBGOAL_THEN `drop u < drop v` ASSUME_TAC THENL
+     [ASM_REWRITE_TAC[REAL_LT_LE; DROP_EQ]; ALL_TAC]] THEN
+  FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^1`; `v:real^1`] o
+   MATCH_MP(REWRITE_RULE[IMP_CONJ] INTEGRABLE_ON_SUBINTERVAL)) THEN
+  ANTS_TAC THENL
+   [ASM_MESON_TAC[SUBSET_INTERVAL_1; IN_INTERVAL_1; REAL_LT_IMP_LE];
+    REWRITE_TAC[HAS_INTEGRAL_INTEGRAL]] THEN
+  DISCH_THEN(MP_TAC o SPECL [`drop(v - u)`; `u:real^1`] o
+   MATCH_MP(REWRITE_RULE[IMP_CONJ] HAS_INTEGRAL_AFFINITY)) THEN
+  ASM_SIMP_TAC[DROP_SUB; REAL_ARITH `u < v ==> ~(v - u = &0)`] THEN
+  REWRITE_TAC[IMAGE_AFFINITY_INTERVAL; INTERVAL_EQ_EMPTY_1; DROP_SUB] THEN
+  ASM_SIMP_TAC[REAL_LE_INV_EQ; REAL_ARITH `u < v ==> ~(v < u) /\ &0 <= v - u`;
+               VECTOR_ARITH `a % u + --(a % v):real^N = a % (u - v)`] THEN
+  REWRITE_TAC[VECTOR_SUB_REFL; VECTOR_MUL_RZERO] THEN
+  SUBGOAL_THEN `inv(drop v - drop u) % (v - u) = vec 1` SUBST1_TAC THENL
+   [REWRITE_TAC[GSYM DROP_EQ; DROP_VEC; DROP_CMUL; DROP_SUB] THEN
+    UNDISCH_TAC `drop u < drop v` THEN CONV_TAC REAL_FIELD;
+    ALL_TAC] THEN
+  DISCH_THEN(MP_TAC o SPEC `drop(v - u)` o MATCH_MP HAS_INTEGRAL_CMUL) THEN
+  ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE; REAL_SUB_LE] THEN
+  REWRITE_TAC[DIMINDEX_1; REAL_POW_1; VECTOR_MUL_ASSOC; DROP_SUB] THEN
+  ASM_SIMP_TAC[REAL_FIELD `u < v ==> (v - u) * inv(v - u) = &1`] THEN
+  REWRITE_TAC[VECTOR_MUL_LID] THEN
+  MATCH_MP_TAC(REWRITE_RULE[TAUT `a /\ b /\ c ==> d <=> a /\ b ==> c ==> d`]
+    HAS_INTEGRAL_SPIKE_FINITE) THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [valid_path]) THEN
+  REWRITE_TAC[piecewise_differentiable_on; IN_DIFF] THEN
+  DISCH_THEN(X_CHOOSE_THEN `k:real^1->bool` STRIP_ASSUME_TAC o CONJUNCT2) THEN
+  EXISTS_TAC `{t | ((drop v - drop u) % t + u) IN k}` THEN CONJ_TAC THENL
+   [MATCH_MP_TAC FINITE_IMAGE_INJ THEN
+    ASM_REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_SUB; DROP_ADD] THEN
+    UNDISCH_TAC `drop u < drop v` THEN CONV_TAC REAL_FIELD;
+    ALL_TAC] THEN
+  ASM_REWRITE_TAC[IN_DIFF; IN_ELIM_THM] THEN
+  X_GEN_TAC `t:real^1` THEN STRIP_TAC THEN REWRITE_TAC[COMPLEX_CMUL] THEN
+  ONCE_REWRITE_TAC[COMPLEX_RING `a * b * c:complex = b * a * c`] THEN
+  REWRITE_TAC[VECTOR_ARITH `x + a % y:real^N = a % y + x`] THEN
+  AP_TERM_TAC THEN REWRITE_TAC[GSYM COMPLEX_CMUL; GSYM DROP_SUB] THEN
+  MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_UNIQUE_AT THEN
+  MATCH_MP_TAC(REWRITE_RULE[o_DEF] VECTOR_DIFF_CHAIN_AT) THEN
+  REWRITE_TAC[DROP_SUB] THEN CONJ_TAC THENL
+   [SUBST1_TAC(VECTOR_ARITH `v - u:real^1 = (v - u) + vec 0`) THEN
+    MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_ADD THEN
+    REWRITE_TAC[HAS_VECTOR_DERIVATIVE_CONST] THEN
+    SUBST1_TAC(MESON[LIFT_DROP; LIFT_EQ_CMUL]
+     `v - u = drop(v - u) % vec 1`) THEN REWRITE_TAC[GSYM DROP_SUB] THEN
+    MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_CMUL THEN
+    REWRITE_TAC[HAS_VECTOR_DERIVATIVE_ID];
+    REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1] THEN
+    REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1])) THEN
+    REWRITE_TAC[DROP_ADD; DROP_SUB; DROP_CMUL; DROP_VEC] THEN
+    REPEAT STRIP_TAC THENL
+     [MATCH_MP_TAC REAL_LE_ADD THEN CONJ_TAC THEN
+      TRY(MATCH_MP_TAC REAL_LE_MUL) THEN ASM_REAL_ARITH_TAC;
+      MATCH_MP_TAC REAL_LE_TRANS THEN
+      EXISTS_TAC `(drop v - drop u) * &1 + drop u` THEN
+      ASM_SIMP_TAC[REAL_LE_RADD; REAL_LE_LMUL;
+                   REAL_SUB_LE; REAL_LT_IMP_LE] THEN
+      ASM_REAL_ARITH_TAC]]);;
+
+let PATH_INTEGRABLE_SUBPATH = prove
+ (`!f g u v.
+        valid_path g /\ f path_integrable_on g /\
+        u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1]
+        ==> f path_integrable_on (subpath u v g)`,
+  REPEAT STRIP_TAC THEN DISJ_CASES_TAC(REAL_ARITH
+   `drop u <= drop v \/ drop v <= drop u`)
+  THENL
+   [ASM_MESON_TAC[path_integrable_on; HAS_PATH_INTEGRAL_SUBPATH];
+    ONCE_REWRITE_TAC[GSYM REVERSEPATH_SUBPATH] THEN
+    MATCH_MP_TAC PATH_INTEGRABLE_REVERSEPATH THEN
+    ASM_SIMP_TAC[VALID_PATH_SUBPATH] THEN
+    ASM_MESON_TAC[path_integrable_on; HAS_PATH_INTEGRAL_SUBPATH]]);;
+
+let HAS_INTEGRAL_PATH_INTEGRAL_SUBPATH = prove
+ (`!f g u v.
+        valid_path g /\ f path_integrable_on g /\
+        u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] /\
+        drop u <= drop v
+        ==> (((\x. f(g x) * vector_derivative g (at x))) has_integral
+             path_integral (subpath u v g) f)
+            (interval[u,v])`,
+  REPEAT STRIP_TAC THEN
+  REWRITE_TAC[HAS_INTEGRAL_INTEGRABLE_INTEGRAL] THEN CONJ_TAC THENL
+   [MATCH_MP_TAC INTEGRABLE_ON_SUBINTERVAL THEN
+    EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN
+    ASM_REWRITE_TAC[GSYM PATH_INTEGRABLE_ON; SUBSET_INTERVAL_1] THEN
+    ASM_MESON_TAC[IN_INTERVAL_1];
+    CONV_TAC SYM_CONV THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+    ASM_SIMP_TAC[HAS_PATH_INTEGRAL_SUBPATH]]);;
+
+let PATH_INTEGRAL_SUBPATH_INTEGRAL = prove
+ (`!f g u v.
+        valid_path g /\ f path_integrable_on g /\
+        u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] /\
+        drop u <= drop v
+        ==> path_integral (subpath u v g) f =
+            integral (interval[u,v])
+                     (\x. f(g x) * vector_derivative g (at x))`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_SUBPATH]);;
+
+let PATH_INTEGRAL_SUBPATH_COMBINE = prove
+ (`!f g u v w.
+        valid_path g /\ f path_integrable_on g /\
+        u IN interval[vec 0,vec 1] /\
+        v IN interval[vec 0,vec 1] /\
+        w IN interval[vec 0,vec 1]
+        ==> path_integral (subpath u v g) f + path_integral (subpath v w g) f =
+            path_integral (subpath u w g) f`,
+  REPLICATE_TAC 3 GEN_TAC THEN
+  SUBGOAL_THEN
+   `!u v w.
+        drop u <= drop v /\ drop v <= drop w
+        ==> valid_path g /\ f path_integrable_on g /\
+            u IN interval[vec 0,vec 1] /\
+            v IN interval[vec 0,vec 1] /\
+            w IN interval[vec 0,vec 1]
+            ==> path_integral (subpath u v g) f +
+                path_integral (subpath v w g) f =
+                path_integral (subpath u w g) f`
+  ASSUME_TAC THENL
+   [ALL_TAC;
+    REPEAT STRIP_TAC THEN REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC
+     (REAL_ARITH `drop u <= drop v /\ drop v <= drop w \/
+                  drop u <= drop w /\ drop w <= drop v \/
+                  drop v <= drop u /\ drop u <= drop w \/
+                  drop v <= drop w /\ drop w <= drop u \/
+                  drop w <= drop u /\ drop u <= drop v \/
+                  drop w <= drop v /\ drop v <= drop u`) THEN
+    FIRST_ASSUM(ANTE_RES_THEN MP_TAC) THEN ASM_REWRITE_TAC[] THEN
+    REPEAT_TCL CONJUNCTS_THEN SUBST1_TAC (MESON[REVERSEPATH_SUBPATH]
+     `subpath v u (g:real^1->complex) = reversepath(subpath u v g) /\
+      subpath w u g = reversepath(subpath u w g) /\
+      subpath w v g = reversepath(subpath v w g)`) THEN
+    ASM_SIMP_TAC[PATH_INTEGRAL_REVERSEPATH; PATH_INTEGRABLE_SUBPATH;
+                 VALID_PATH_REVERSEPATH; VALID_PATH_SUBPATH] THEN
+    CONV_TAC COMPLEX_RING] THEN
+  REPEAT GEN_TAC THEN STRIP_TAC THEN
+  SUBGOAL_THEN `drop u <= drop w` ASSUME_TAC THENL
+   [ASM_REAL_ARITH_TAC; STRIP_TAC] THEN
+  ASM_SIMP_TAC[PATH_INTEGRAL_SUBPATH_INTEGRAL] THEN
+  MATCH_MP_TAC INTEGRAL_COMBINE THEN ASM_REWRITE_TAC[] THEN
+  MATCH_MP_TAC INTEGRABLE_ON_SUBINTERVAL THEN
+  EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN
+  ASM_REWRITE_TAC[GSYM PATH_INTEGRABLE_ON; SUBSET_INTERVAL_1] THEN
+  ASM_MESON_TAC[IN_INTERVAL_1]);;
+
+let PATH_INTEGRAL_INTEGRAL = prove
+ (`!f g. path_integral g f =
+         integral (interval [vec 0,vec 1])
+                  (\x. f (g x) * vector_derivative g (at x))`,
+  REWRITE_TAC[path_integral; integral; HAS_PATH_INTEGRAL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Easier to reason about segments via convex hulls.                         *)
+(* ------------------------------------------------------------------------- *)
+
+let SEGMENTS_SUBSET_CONVEX_HULL = prove
+ (`!a b c. segment[a,b] SUBSET (convex hull {a,b,c}) /\
+           segment[a,c] SUBSET (convex hull {a,b,c}) /\
+           segment[b,c] SUBSET (convex hull {a,b,c}) /\
+           segment[b,a] SUBSET (convex hull {a,b,c}) /\
+           segment[c,a] SUBSET (convex hull {a,b,c}) /\
+           segment[c,b] SUBSET (convex hull {a,b,c})`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+  MATCH_MP_TAC HULL_MONO THEN SET_TAC[]);;
+
+let MIDPOINTS_IN_CONVEX_HULL = prove
+ (`!x:real^N s. x IN convex hull s /\ y IN convex hull s
+         ==> midpoint(x,y) IN convex hull s`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[midpoint; VECTOR_ARITH
+    `inv(&2) % (x + y):real^N = (&1 - inv(&2)) % x + inv(&2) % y`] THEN
+  MATCH_MP_TAC IN_CONVEX_SET THEN
+  ASM_REWRITE_TAC[CONVEX_CONVEX_HULL] THEN REAL_ARITH_TAC);;
+
+let POINTS_IN_CONVEX_HULL = prove
+ (`!x s. x IN s ==> x IN convex hull s`,
+  MESON_TAC[SUBSET; HULL_SUBSET]);;
+
+let CONVEX_HULL_SUBSET = prove
+ (`(!x. x IN s ==> x IN convex hull t)
+   ==> (convex hull s) SUBSET (convex hull t)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_MINIMAL THEN
+  ASM_REWRITE_TAC[CONVEX_CONVEX_HULL; SUBSET]);;
+
+let NOT_IN_INTERIOR_CONVEX_HULL_3 = prove
+ (`!a b c:complex. ~(a IN interior(convex hull {a,b,c})) /\
+                   ~(b IN interior(convex hull {a,b,c})) /\
+                   ~(c IN interior(convex hull {a,b,c}))`,
+  REPEAT GEN_TAC THEN REPEAT CONJ_TAC THEN
+  MATCH_MP_TAC NOT_IN_INTERIOR_CONVEX_HULL THEN
+  ASM_SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY; IN_INSERT] THEN
+  REWRITE_TAC[DIMINDEX_2] THEN ARITH_TAC);;
+
+(* ------------------------------------------------------------------------- *)
+(* Cauchy's theorem where there's a primitive.                               *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRAL_PRIMITIVE_LEMMA = prove
+ (`!f f' g a b s.
+        ~(interval[a,b] = {}) /\
+        (!x. x IN s ==> (f has_complex_derivative f'(x)) (at x within s)) /\
+        g piecewise_differentiable_on interval[a,b] /\
+        (!x. x IN interval[a,b] ==> g(x) IN s)
+        ==> ((\x. f'(g x) * vector_derivative g (at x within interval[a,b]))
+             has_integral (f(g b) - f(g a))) (interval[a,b])`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[valid_path; piecewise_differentiable_on] THEN
+  REWRITE_TAC[INTERVAL_EQ_EMPTY_1; REAL_NOT_LT] THEN
+  DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
+  FIRST_X_ASSUM(X_CHOOSE_THEN `k:real^1->bool` STRIP_ASSUME_TAC) THEN
+  MATCH_MP_TAC FUNDAMENTAL_THEOREM_OF_CALCULUS_INTERIOR_STRONG THEN
+  EXISTS_TAC `k:real^1->bool` THEN ASM_REWRITE_TAC[DROP_VEC; REAL_POS] THEN
+  ASM_SIMP_TAC[FINITE_IMP_COUNTABLE; GSYM o_DEF] THEN CONJ_TAC THENL
+   [MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:complex->bool` THEN
+    ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
+    MATCH_MP_TAC HOLOMORPHIC_ON_IMP_CONTINUOUS_ON THEN
+    ASM_MESON_TAC[holomorphic_on];
+    ALL_TAC] THEN
+  X_GEN_TAC `x:real^1` THEN
+  REPEAT STRIP_TAC THEN REWRITE_TAC[has_vector_derivative; COMPLEX_CMUL] THEN
+  SUBGOAL_THEN `(f has_complex_derivative f'(g x))
+                (at (g x) within (IMAGE g (interval[a:real^1,b])))`
+  MP_TAC THENL
+   [MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET THEN
+    EXISTS_TAC `s:complex->bool` THEN
+    ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_MESON_TAC[INTERVAL_OPEN_SUBSET_CLOSED; SUBSET; IN_DIFF];
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+   `(g:real^1->complex) differentiable (at x within interval[a,b])`
+  MP_TAC THENL
+   [MATCH_MP_TAC DIFFERENTIABLE_AT_WITHIN THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_MESON_TAC[INTERVAL_OPEN_SUBSET_CLOSED; SUBSET; IN_DIFF];
+    ALL_TAC] THEN
+  GEN_REWRITE_TAC LAND_CONV [VECTOR_DERIVATIVE_WORKS] THEN
+  REWRITE_TAC[has_vector_derivative; IMP_IMP; has_complex_derivative] THEN
+  DISCH_THEN(MP_TAC o MATCH_MP DIFF_CHAIN_WITHIN) THEN
+  DISCH_THEN(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+    HAS_DERIVATIVE_WITHIN_SUBSET)) THEN
+  DISCH_THEN(MP_TAC o SPEC `interval(a:real^1,b)`) THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[IN_DIFF]) THEN
+  ASM_SIMP_TAC[INTERVAL_OPEN_SUBSET_CLOSED; OPEN_INTERVAL;
+               HAS_DERIVATIVE_WITHIN_OPEN] THEN
+  REWRITE_TAC[o_DEF; COMPLEX_CMUL] THEN REWRITE_TAC[COMPLEX_MUL_AC]);;
+
+let PATH_INTEGRAL_PRIMITIVE = prove
+ (`!f f' g s.
+        (!x. x IN s ==> (f has_complex_derivative f'(x)) (at x within s)) /\
+        valid_path g /\ (path_image g) SUBSET s
+        ==> (f' has_path_integral (f(pathfinish g) - f(pathstart g))) (g)`,
+  REWRITE_TAC[valid_path; path_image; pathfinish; pathstart] THEN
+  REWRITE_TAC[has_path_integral] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_PRIMITIVE_LEMMA THEN
+  ASM_REWRITE_TAC[INTERVAL_EQ_EMPTY_1; DROP_VEC; REAL_POS; REAL_NOT_LT] THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; FORALL_IN_IMAGE]) THEN
+  ASM_MESON_TAC[]);;
+
+let CAUCHY_THEOREM_PRIMITIVE = prove
+ (`!f f' g s.
+        (!x. x IN s ==> (f has_complex_derivative f'(x)) (at x within s)) /\
+        valid_path g /\ (path_image g) SUBSET s /\
+        pathfinish g = pathstart g
+        ==> (f' has_path_integral Cx(&0)) (g)`,
+  MESON_TAC[PATH_INTEGRAL_PRIMITIVE; COMPLEX_SUB_REFL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Existence of path integral for continuous function.                       *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRABLE_CONTINUOUS_LINEPATH = prove
+ (`!f a b. f continuous_on segment[a,b]
+           ==> f path_integrable_on (linepath(a,b))`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[path_integrable_on; has_path_integral] THEN
+  DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
+  REWRITE_TAC[GSYM integrable_on] THEN MATCH_MP_TAC INTEGRABLE_CONTINUOUS THEN
+  MATCH_MP_TAC CONTINUOUS_ON_EQ THEN
+  EXISTS_TAC `\x. f(linepath(a,b) x) * (b - a)` THEN
+  SIMP_TAC[VECTOR_DERIVATIVE_LINEPATH_WITHIN] THEN
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_LMUL THEN
+  GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
+  MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
+  ASM_REWRITE_TAC[GSYM path_image; ETA_AX; PATH_IMAGE_LINEPATH] THEN
+  REWRITE_TAC[CONTINUOUS_ON_LINEPATH]);;
+
+(* ------------------------------------------------------------------------- *)
+(* A complex-specific theorem for integrals.                                 *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_INTEGRAL_COMPLEX_CMUL = prove
+ (`!f y i c. (f has_integral y) i ==> ((\x. c * f(x)) has_integral (c * y)) i`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC
+   (REWRITE_RULE[o_DEF] HAS_INTEGRAL_LINEAR) THEN
+  ASM_REWRITE_TAC[linear; COMPLEX_CMUL] THEN CONV_TAC COMPLEX_RING);;
+
+(* ------------------------------------------------------------------------- *)
+(* Arithmetical combining theorems.                                          *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_PATH_INTEGRAL_CONST_LINEPATH = prove
+ (`!a b c. ((\x. c) has_path_integral (c * (b - a))) (linepath(a,b))`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[HAS_PATH_INTEGRAL_LINEPATH] THEN
+  MP_TAC(ISPECL [`vec 0:real^1`; `vec 1:real^1`; `c * (b - a):complex`]
+         HAS_INTEGRAL_CONST) THEN
+  REWRITE_TAC[CONTENT_UNIT; VECTOR_MUL_LID]);;
+
+let HAS_PATH_INTEGRAL_NEG = prove
+ (`!f i g. (f has_path_integral i) g
+           ==> ((\x. --(f x)) has_path_integral (--i)) g`,
+  REWRITE_TAC[has_path_integral; COMPLEX_MUL_LNEG; HAS_INTEGRAL_NEG]);;
+
+let HAS_PATH_INTEGRAL_ADD = prove
+ (`!f1 i1 f2 i2 g.
+        (f1 has_path_integral i1) g /\ (f2 has_path_integral i2) g
+        ==> ((\x. f1(x) + f2(x)) has_path_integral (i1 + i2)) g`,
+  REWRITE_TAC[has_path_integral; COMPLEX_ADD_RDISTRIB] THEN
+  SIMP_TAC[HAS_INTEGRAL_ADD]);;
+
+let HAS_PATH_INTEGRAL_SUB = prove
+ (`!f1 i1 f2 i2 g.
+        (f1 has_path_integral i1) g /\ (f2 has_path_integral i2) g
+         ==> ((\x. f1(x) - f2(x)) has_path_integral (i1 - i2)) g`,
+  REWRITE_TAC[has_path_integral; COMPLEX_SUB_RDISTRIB] THEN
+  SIMP_TAC[HAS_INTEGRAL_SUB]);;
+
+let HAS_PATH_INTEGRAL_COMPLEX_LMUL = prove
+ (`!f g i c. (f has_path_integral i) g
+             ==> ((\x. c * f x) has_path_integral (c * i)) g`,
+  REWRITE_TAC[has_path_integral; HAS_INTEGRAL_COMPLEX_CMUL;
+              GSYM COMPLEX_MUL_ASSOC]);;
+
+let HAS_PATH_INTEGRAL_COMPLEX_RMUL = prove
+ (`!f g i c. (f has_path_integral i) g
+             ==> ((\x. f x * c) has_path_integral (i * c)) g`,
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  REWRITE_TAC[HAS_PATH_INTEGRAL_COMPLEX_LMUL]);;
+
+let HAS_PATH_INTEGRAL_COMPLEX_DIV = prove
+ (`!f g i c. (f has_path_integral i) g
+             ==> ((\x. f x / c) has_path_integral (i / c)) g`,
+  REWRITE_TAC[complex_div; HAS_PATH_INTEGRAL_COMPLEX_RMUL]);;
+
+let HAS_PATH_INTEGRAL_EQ = prove
+ (`!f g p y.
+        (!x. x IN path_image p ==> f x = g x) /\
+        (f has_path_integral y) p
+        ==> (g has_path_integral y) p`,
+  REPEAT GEN_TAC THEN
+  REWRITE_TAC[path_image; IN_IMAGE; has_path_integral; IMP_CONJ] THEN
+  DISCH_TAC THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] HAS_INTEGRAL_EQ) THEN
+  ASM_SIMP_TAC[] THEN ASM_MESON_TAC[]);;
+
+let HAS_PATH_INTEGRAL_BOUND_LINEPATH = prove
+ (`!f i a b B.
+        (f has_path_integral i) (linepath(a,b)) /\
+        &0 <= B /\ (!x. x IN segment[a,b] ==> norm(f x) <= B)
+        ==> norm(i) <= B * norm(b - a)`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[has_path_integral] THEN STRIP_TAC THEN
+  GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN
+  REWRITE_TAC[GSYM CONTENT_UNIT_1] THEN MATCH_MP_TAC HAS_INTEGRAL_BOUND THEN
+  EXISTS_TAC `\x. f (linepath (a,b) x) *
+                    vector_derivative (linepath (a,b))
+                       (at x within interval [vec 0,vec 1])` THEN
+  ASM_SIMP_TAC[REAL_LE_MUL; NORM_POS_LE;
+               VECTOR_DERIVATIVE_LINEPATH_WITHIN] THEN
+  REPEAT STRIP_TAC THEN REWRITE_TAC[COMPLEX_NORM_MUL] THEN
+  MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  REWRITE_TAC[GSYM PATH_IMAGE_LINEPATH; path_image] THEN
+  ASM SET_TAC[]);;
+
+let HAS_PATH_INTEGRAL_BOUND_LINEPATH_STRONG = prove
+ (`!f i a b B k.
+        FINITE k /\
+        (f has_path_integral i) (linepath(a,b)) /\
+        &0 <= B /\ (!x. x IN segment[a,b] DIFF k ==> norm(f x) <= B)
+        ==> norm(i) <= B * norm(b - a)`,
+  REPEAT GEN_TAC THEN ASM_CASES_TAC `b:complex = a` THENL
+   [ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0; REAL_MUL_RZERO] THEN
+    STRIP_TAC THEN SUBGOAL_THEN `i = Cx(&0)`
+      (fun th -> REWRITE_TAC[th; COMPLEX_NORM_0; REAL_LE_REFL]) THEN
+    MATCH_MP_TAC HAS_PATH_INTEGRAL_UNIQUE THEN
+    ASM_MESON_TAC[HAS_PATH_INTEGRAL_TRIVIAL];
+    STRIP_TAC THEN MATCH_MP_TAC HAS_PATH_INTEGRAL_BOUND_LINEPATH THEN
+    EXISTS_TAC `\x. if x IN k then Cx(&0) else (f:complex->complex) x` THEN
+    ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+     [ALL_TAC; ASM SET_TAC[COMPLEX_NORM_0]] THEN
+    UNDISCH_TAC `(f has_path_integral i) (linepath (a,b))` THEN
+    MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[has_path_integral] THEN
+    MATCH_MP_TAC HAS_INTEGRAL_SPIKE_EQ THEN
+    EXISTS_TAC `{t | t IN interval[vec 0,vec 1] /\
+                     linepath(a:complex,b) t IN k}` THEN
+    CONJ_TAC THENL [MATCH_MP_TAC NEGLIGIBLE_FINITE; SET_TAC[]] THEN
+    MATCH_MP_TAC FINITE_FINITE_PREIMAGE_GENERAL THEN ASM_REWRITE_TAC[] THEN
+    X_GEN_TAC `c:complex` THEN DISCH_TAC THEN
+    MATCH_MP_TAC(MESON[FINITE_SING; FINITE_SUBSET]
+     `(?a. s SUBSET {a}) ==> FINITE s`) THEN
+    MATCH_MP_TAC(SET_RULE
+     `(!a b. a IN s /\ b IN s ==> a = b) ==> (?a. s SUBSET {a})`) THEN
+    MAP_EVERY X_GEN_TAC [`s:real^1`; `t:real^1`] THEN
+    REWRITE_TAC[IN_ELIM_THM] THEN STRIP_TAC THEN
+    FIRST_X_ASSUM(MP_TAC o SYM) THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
+    REWRITE_TAC[linepath; VECTOR_ARITH
+     `(&1 - s) % a + s % b:real^N = (&1 - t) % a + t % b <=>
+      (s - t) % (b - a) = vec 0`] THEN
+    ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ; REAL_SUB_0] THEN
+    REWRITE_TAC[DROP_EQ]]);;
+
+let HAS_PATH_INTEGRAL_0 = prove
+ (`!g. ((\x. Cx(&0)) has_path_integral Cx(&0)) g`,
+  REWRITE_TAC[has_path_integral; COMPLEX_MUL_LZERO] THEN
+  REWRITE_TAC[GSYM COMPLEX_VEC_0; HAS_INTEGRAL_0]);;
+
+let HAS_PATH_INTEGRAL_IS_0 = prove
+ (`!f g. (!z. z IN path_image g ==> f(z) = Cx(&0))
+         ==> (f has_path_integral Cx(&0)) g`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_PATH_INTEGRAL_EQ THEN
+  EXISTS_TAC `\z:complex. Cx(&0)` THEN
+  ASM_REWRITE_TAC[HAS_PATH_INTEGRAL_0] THEN ASM_MESON_TAC[]);;
+
+let HAS_PATH_INTEGRAL_VSUM = prove
+ (`!f p s. FINITE s /\ (!a. a IN s ==> (f a has_path_integral i a) p)
+           ==> ((\x. vsum s (\a. f a x)) has_path_integral vsum s i) p`,
+  GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
+  MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
+  SIMP_TAC[VSUM_CLAUSES; HAS_PATH_INTEGRAL_0; COMPLEX_VEC_0; IN_INSERT] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_PATH_INTEGRAL_ADD THEN
+  ASM_REWRITE_TAC[ETA_AX] THEN CONJ_TAC THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Same thing non-relationally.                                              *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRAL_CONST_LINEPATH = prove
+ (`!a b c. path_integral (linepath(a,b)) (\x. c) = c * (b - a)`,
+  REPEAT GEN_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  REWRITE_TAC[HAS_PATH_INTEGRAL_CONST_LINEPATH]);;
+
+let PATH_INTEGRAL_NEG = prove
+ (`!f g. f path_integrable_on g
+         ==> path_integral g (\x. --(f x)) = --(path_integral g f)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_NEG THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+let PATH_INTEGRAL_ADD = prove
+ (`!f1 f2 g.
+        f1 path_integrable_on g /\ f2 path_integrable_on g
+        ==> path_integral g (\x. f1(x) + f2(x)) =
+                path_integral g f1 + path_integral g f2`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_ADD THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+let PATH_INTEGRAL_SUB = prove
+ (`!f1 f2 g.
+        f1 path_integrable_on g /\ f2 path_integrable_on g
+        ==> path_integral g (\x. f1(x) - f2(x)) =
+                path_integral g f1 - path_integral g f2`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_SUB THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+let PATH_INTEGRAL_COMPLEX_LMUL = prove
+ (`!f g c.  f path_integrable_on g
+           ==> path_integral g (\x. c * f x) = c * path_integral g f`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_COMPLEX_LMUL THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+let PATH_INTEGRAL_COMPLEX_RMUL = prove
+ (`!f g c.  f path_integrable_on g
+           ==> path_integral g (\x. f x * c) = path_integral g f * c`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_COMPLEX_RMUL THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+let PATH_INTEGRAL_COMPLEX_DIV = prove
+ (`!f g c.  f path_integrable_on g
+           ==> path_integral g (\x. f x / c) = path_integral g f / c`,
+   REWRITE_TAC[complex_div; PATH_INTEGRAL_COMPLEX_RMUL]);;
+
+let PATH_INTEGRAL_EQ = prove
+ (`!f g p.
+        (!x. x IN path_image p ==> f x = g x)
+        ==> path_integral p f = path_integral p g`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[path_integral] THEN
+  AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN
+  ASM_MESON_TAC[HAS_PATH_INTEGRAL_EQ]);;
+
+let PATH_INTEGRAL_EQ_0 = prove
+ (`!f g. (!z. z IN path_image g ==> f(z) = Cx(&0))
+         ==> path_integral g f = Cx(&0)`,
+  MESON_TAC[HAS_PATH_INTEGRAL_IS_0; PATH_INTEGRAL_UNIQUE]);;
+
+let PATH_INTEGRAL_BOUND_LINEPATH = prove
+ (`!f a b.
+        f path_integrable_on (linepath(a,b)) /\
+        &0 <= B /\ (!x. x IN segment[a,b] ==> norm(f x) <= B)
+        ==> norm(path_integral (linepath(a,b)) f) <= B * norm(b - a)`,
+  REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_BOUND_LINEPATH THEN
+  EXISTS_TAC `f:complex->complex` THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+let PATH_INTEGRAL_0 = prove
+ (`!g. path_integral g (\x. Cx(&0)) = Cx(&0)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  REWRITE_TAC[HAS_PATH_INTEGRAL_0]);;
+
+let PATH_INTEGRAL_VSUM = prove
+ (`!f p s. FINITE s /\ (!a. a IN s ==> (f a) path_integrable_on p)
+           ==> path_integral p (\x. vsum s (\a. f a x)) =
+                vsum s (\a. path_integral p (f a))`,
+  REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_VSUM THEN
+  ASM_SIMP_TAC[HAS_PATH_INTEGRAL_INTEGRAL]);;
+
+let PATH_INTEGRABLE_EQ = prove
+ (`!f g p. (!x. x IN path_image p ==> f x = g x) /\ f path_integrable_on p
+           ==> g path_integrable_on p`,
+  REWRITE_TAC[path_integrable_on] THEN MESON_TAC[HAS_PATH_INTEGRAL_EQ]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Arithmetic theorems for path integrability.                               *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRABLE_NEG = prove
+ (`!f g. f path_integrable_on g
+           ==> (\x. --(f x)) path_integrable_on g`,
+  REWRITE_TAC[path_integrable_on] THEN MESON_TAC[HAS_PATH_INTEGRAL_NEG]);;
+
+let PATH_INTEGRABLE_ADD = prove
+ (`!f1 f2 g.
+        f1 path_integrable_on g /\ f2 path_integrable_on g
+        ==> (\x. f1(x) + f2(x)) path_integrable_on g`,
+  REWRITE_TAC[path_integrable_on] THEN MESON_TAC[HAS_PATH_INTEGRAL_ADD]);;
+
+let PATH_INTEGRABLE_SUB = prove
+ (`!f1 f2 g.
+        f1 path_integrable_on g /\ f2 path_integrable_on g
+        ==> (\x. f1(x) - f2(x)) path_integrable_on g`,
+  REWRITE_TAC[path_integrable_on] THEN MESON_TAC[HAS_PATH_INTEGRAL_SUB]);;
+
+let PATH_INTEGRABLE_COMPLEX_LMUL = prove
+ (`!f g c. f path_integrable_on g
+             ==> (\x. c * f x) path_integrable_on g`,
+  REWRITE_TAC[path_integrable_on] THEN
+  MESON_TAC[HAS_PATH_INTEGRAL_COMPLEX_LMUL]);;
+
+let PATH_INTEGRABLE_COMPLEX_RMUL = prove
+ (`!f g c. f path_integrable_on g
+             ==> (\x. f x * c) path_integrable_on g`,
+  ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+  REWRITE_TAC[PATH_INTEGRABLE_COMPLEX_LMUL]);;
+
+let PATH_INTEGRABLE_COMPLEX_DIV = prove
+ (`!f g c. f path_integrable_on g
+             ==> (\x. f x / c) path_integrable_on g`,
+  REWRITE_TAC[path_integrable_on] THEN
+  MESON_TAC[HAS_PATH_INTEGRAL_COMPLEX_DIV]);;
+
+let PATH_INTEGRABLE_VSUM = prove
+ (`!f g s. FINITE s /\ (!a. a IN s ==> f a path_integrable_on g)
+           ==> (\x. vsum s (\a. f a x)) path_integrable_on g`,
+  REWRITE_TAC[path_integrable_on] THEN
+  MESON_TAC[HAS_PATH_INTEGRAL_VSUM]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Considering a path integral "backwards".                                  *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_PATH_INTEGRAL_REVERSE_LINEPATH = prove
+ (`!f a b i.
+        (f has_path_integral i) (linepath(a,b))
+        ==> (f has_path_integral (--i)) (linepath(b,a))`,
+  MESON_TAC[REVERSEPATH_LINEPATH; VALID_PATH_LINEPATH;
+            HAS_PATH_INTEGRAL_REVERSEPATH]);;
+
+let PATH_INTEGRAL_REVERSE_LINEPATH = prove
+ (`!f a b.
+        f continuous_on (segment[a,b])
+        ==> path_integral(linepath(a,b)) f =
+            --(path_integral(linepath(b,a)) f)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_REVERSE_LINEPATH THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+  MATCH_MP_TAC PATH_INTEGRABLE_CONTINUOUS_LINEPATH THEN
+  ASM_MESON_TAC[SEGMENT_SYM]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Splitting a path integral in a flat way.                                  *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_PATH_INTEGRAL_SPLIT = prove
+ (`!f a b c i j k.
+        &0 <= k /\ k <= &1 /\ c - a = k % (b - a) /\
+        (f has_path_integral i) (linepath(a,c)) /\
+        (f has_path_integral j) (linepath(c,b))
+        ==> (f has_path_integral (i + j)) (linepath(a,b))`,
+  REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  ASM_CASES_TAC `k = &0` THENL
+   [ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_SUB_EQ] THEN
+    DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN ASM_REWRITE_TAC[] THEN
+    ASM_MESON_TAC[HAS_PATH_INTEGRAL_TRIVIAL; PATH_INTEGRAL_UNIQUE;
+                  COMPLEX_ADD_LID];
+    ALL_TAC] THEN
+  ASM_CASES_TAC `k = &1` THEN ASM_REWRITE_TAC[VECTOR_MUL_LID] THENL
+   [REWRITE_TAC[VECTOR_ARITH `c - a = b - a <=> c = b:real^N`] THEN
+    DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN ASM_REWRITE_TAC[] THEN
+    ASM_MESON_TAC[HAS_PATH_INTEGRAL_TRIVIAL; PATH_INTEGRAL_UNIQUE;
+                  COMPLEX_ADD_RID];
+    ALL_TAC] THEN
+  REWRITE_TAC[HAS_PATH_INTEGRAL_LINEPATH] THEN
+  REWRITE_TAC[linepath] THEN REPEAT GEN_TAC THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  DISCH_THEN(CONJUNCTS_THEN
+   (MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] HAS_INTEGRAL_AFFINITY))) THEN
+  DISCH_THEN(ASSUME_TAC o SPECL
+    [`inv(&1 - k):real`; `--(k / (&1 - k)) % vec 1:real^1`]) THEN
+  DISCH_THEN(MP_TAC o SPECL [`inv(k):real`; `vec 0:real^1`]) THEN
+  POP_ASSUM MP_TAC THEN ASM_REWRITE_TAC[REAL_INV_EQ_0; REAL_SUB_0] THEN
+  REWRITE_TAC[REAL_INV_INV; DIMINDEX_1; REAL_POW_1; REAL_ABS_INV] THEN
+  REWRITE_TAC[IMAGE_AFFINITY_INTERVAL] THEN
+  REWRITE_TAC[INTERVAL_EQ_EMPTY_1; DROP_VEC] THEN
+  ASM_REWRITE_TAC[REAL_SUB_LE; REAL_ARITH `~(&1 < &0)`] THEN
+  REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_NEG_0; VECTOR_ADD_RID] THEN
+  REWRITE_TAC[VECTOR_MUL_ASSOC; VECTOR_MUL_LNEG] THEN
+  ASM_SIMP_TAC[REAL_FIELD
+    `~(k = &1) ==> (&1 - k) * --(k / (&1 - k)) = --k`] THEN
+  REWRITE_TAC[VECTOR_ADD_LID; VECTOR_MUL_LNEG; VECTOR_NEG_NEG;
+              VECTOR_ARITH `(&1 - k) % x + k % x:real^1 = x`] THEN
+  REWRITE_TAC[DROP_ADD; DROP_CMUL; DROP_NEG; DROP_VEC; REAL_MUL_RID] THEN
+  FIRST_X_ASSUM(SUBST1_TAC o MATCH_MP (VECTOR_ARITH
+    `c - a = x ==> c = x + a`)) THEN
+  REWRITE_TAC[VECTOR_ARITH `b - (k % (b - a) + a) = (&1 - k) % (b - a)`] THEN
+  SUBGOAL_THEN
+   `!x. (&1 - (inv (&1 - k) * drop x + --(k / (&1 - k)))) % (k % (b - a) + a) +
+        (inv (&1 - k) * drop x + --(k / (&1 - k))) % b =
+        (&1 - drop x) % a + drop x % b`
+   (fun th -> REWRITE_TAC[th]) THENL
+   [REWRITE_TAC[VECTOR_ARITH
+     `x % (k % (b - a) + a) + y % b =
+      (x * (&1 - k)) % a + (y + x * k) % b`] THEN
+    GEN_TAC THEN BINOP_TAC THEN BINOP_TAC THEN REWRITE_TAC[] THEN
+    REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+   `!x. (&1 - inv k * drop x) % a + (inv k * drop x) % (k % (b - a) + a) =
+        (&1 - drop x) % a + drop x % b`
+   (fun th -> REWRITE_TAC[th]) THENL
+   [REWRITE_TAC[VECTOR_ARITH
+     `x % a + y % (k % (b - a) + a) =
+      (x + y * (&1 - k)) % a + (y * k) % b`] THEN
+    GEN_TAC THEN BINOP_TAC THEN BINOP_TAC THEN REWRITE_TAC[] THEN
+    REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
+    ALL_TAC] THEN
+  DISCH_TAC THEN
+  DISCH_THEN(MP_TAC o SPEC `inv(k:real)` o MATCH_MP HAS_INTEGRAL_CMUL) THEN
+  FIRST_ASSUM(MP_TAC o SPEC `inv(&1 - k)` o MATCH_MP HAS_INTEGRAL_CMUL) THEN
+  ASM_SIMP_TAC[REAL_ARITH `&0 <= k ==> abs k = k`;
+               REAL_ARITH `k <= &1 ==> abs(&1 - k) = &1 - k`] THEN
+  ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_SUB_0] THEN
+  REWRITE_TAC[IMP_IMP; VECTOR_MUL_LID] THEN
+  REWRITE_TAC[COMPLEX_CMUL] THEN
+  ONCE_REWRITE_TAC[COMPLEX_RING
+   `Cx(inv a) * b * Cx(a) * c = (Cx(inv a) * Cx a) * b * c`] THEN
+  ASM_SIMP_TAC[GSYM CX_MUL; REAL_MUL_LINV; REAL_SUB_0; COMPLEX_MUL_LID] THEN
+  STRIP_TAC THEN
+  MATCH_MP_TAC HAS_INTEGRAL_COMBINE THEN EXISTS_TAC `k % vec 1:real^1` THEN
+  ASM_REWRITE_TAC[DROP_CMUL; DROP_VEC; REAL_MUL_RID]);;
+
+let PATH_INTEGRAL_SPLIT = prove
+ (`!f a b c k.
+        &0 <= k /\ k <= &1 /\ c - a = k % (b - a) /\
+        f continuous_on (segment[a,b])
+        ==> path_integral(linepath(a,b)) f =
+            path_integral(linepath(a,c)) f +
+            path_integral(linepath(c,b)) f`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_SPLIT THEN
+  MAP_EVERY EXISTS_TAC [`c:complex`; `k:real`] THEN ASM_REWRITE_TAC[] THEN
+  CONJ_TAC THEN MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+  MATCH_MP_TAC PATH_INTEGRABLE_CONTINUOUS_LINEPATH THEN
+  MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+  EXISTS_TAC `segment[a:complex,b]` THEN ASM_REWRITE_TAC[] THEN
+  REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+  REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN REPEAT STRIP_TAC THEN
+  ASM_SIMP_TAC[POINTS_IN_CONVEX_HULL; IN_INSERT] THEN
+  FIRST_ASSUM(SUBST1_TAC o MATCH_MP (VECTOR_ARITH
+   `c - a = k % (b - a) ==> c = (&1 - k) % a + k % b`)) THEN
+  MATCH_MP_TAC IN_CONVEX_SET THEN
+  ASM_SIMP_TAC[CONVEX_CONVEX_HULL; POINTS_IN_CONVEX_HULL; IN_INSERT]);;
+
+let PATH_INTEGRAL_SPLIT_LINEPATH = prove
+ (`!f a b c.
+        f continuous_on segment[a,b] /\ c IN segment[a,b]
+        ==> path_integral(linepath (a,b)) f =
+            path_integral(linepath (a,c)) f +
+            path_integral(linepath (c,b)) f`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_SPLIT THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN
+  MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+  VECTOR_ARITH_TAC);;
+
+(* ------------------------------------------------------------------------- *)
+(* The special case of midpoints used in the main quadrisection.             *)
+(* ------------------------------------------------------------------------- *)
+
+let HAS_PATH_INTEGRAL_MIDPOINT = prove
+ (`!f a b i j.
+        (f has_path_integral i) (linepath(a,midpoint(a,b))) /\
+        (f has_path_integral j) (linepath(midpoint(a,b),b))
+        ==> (f has_path_integral (i + j)) (linepath(a,b))`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_PATH_INTEGRAL_SPLIT THEN
+  MAP_EVERY EXISTS_TAC [`midpoint(a:complex,b)`; `&1 / &2`] THEN
+  ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  REWRITE_TAC[midpoint] THEN VECTOR_ARITH_TAC);;
+
+let PATH_INTEGRAL_MIDPOINT = prove
+ (`!f a b.
+        f continuous_on (segment[a,b])
+        ==> path_integral(linepath(a,b)) f =
+            path_integral(linepath(a,midpoint(a,b))) f +
+            path_integral(linepath(midpoint(a,b),b)) f`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_SPLIT THEN
+  EXISTS_TAC `&1 / &2` THEN
+  ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
+  REWRITE_TAC[midpoint] THEN VECTOR_ARITH_TAC);;
+
+(* ------------------------------------------------------------------------- *)
+(* A couple of special case lemmas that are useful below.                    *)
+(* ------------------------------------------------------------------------- *)
+
+let TRIANGLE_LINEAR_HAS_CHAIN_INTEGRAL = prove
+ (`!a b c m d. ((\x. m * x + d) has_path_integral Cx(&0))
+         (linepath(a,b) ++ linepath(b,c) ++ linepath(c,a))`,
+  REPEAT GEN_TAC THEN MATCH_MP_TAC CAUCHY_THEOREM_PRIMITIVE THEN
+  MAP_EVERY EXISTS_TAC [`\x. m / Cx(&2) * x pow 2 + d * x`; `(:complex)`] THEN
+  SIMP_TAC[PATHSTART_JOIN; PATHFINISH_JOIN; PATHSTART_LINEPATH; SUBSET_UNIV;
+           PATHFINISH_LINEPATH; VALID_PATH_JOIN; VALID_PATH_LINEPATH] THEN
+  REPEAT STRIP_TAC THEN COMPLEX_DIFF_TAC THEN CONV_TAC NUM_REDUCE_CONV THEN
+  CONV_TAC COMPLEX_RING);;
+
+let HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL = prove
+ (`!f i a b c d.
+        (f has_path_integral i)
+        (linepath(a,b) ++ linepath(b,c) ++ linepath(c,d))
+        ==> path_integral (linepath(a,b)) f +
+            path_integral (linepath(b,c)) f +
+            path_integral (linepath(c,d)) f = i`,
+  REPEAT STRIP_TAC THEN
+  FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP PATH_INTEGRAL_UNIQUE) THEN
+  FIRST_X_ASSUM(MP_TAC o MATCH_MP HAS_PATH_INTEGRAL_INTEGRABLE) THEN
+  SIMP_TAC[PATH_INTEGRABLE_JOIN; VALID_PATH_LINEPATH; VALID_PATH_JOIN;
+           PATHSTART_JOIN; PATHFINISH_JOIN; PATHSTART_LINEPATH;
+           PATHFINISH_LINEPATH] THEN
+  STRIP_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+  REPEAT(MATCH_MP_TAC HAS_PATH_INTEGRAL_JOIN THEN
+         SIMP_TAC[VALID_PATH_LINEPATH; VALID_PATH_JOIN;
+                  PATHSTART_JOIN; PATHFINISH_JOIN; PATHSTART_LINEPATH;
+                  PATHFINISH_LINEPATH] THEN
+         CONJ_TAC) THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN ASM_REWRITE_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Reversing the order in a double path integral. The condition is           *)
+(* stronger than needed but it's often true in typical situations.           *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRAL_SWAP = prove
+ (`!f g h.
+    (\y. f (fstcart y) (sndcart y)) continuous_on
+    (path_image g PCROSS path_image h) /\
+    valid_path g /\ valid_path h /\
+    (\t. vector_derivative g (at t)) continuous_on interval[vec 0,vec 1] /\
+    (\t. vector_derivative h (at t)) continuous_on interval[vec 0,vec 1]
+    ==> path_integral g (\w. path_integral h (f w)) =
+        path_integral h (\z. path_integral g (\w. f w z))`,
+  REWRITE_TAC[PCROSS] THEN REPEAT STRIP_TAC THEN
+  ONCE_REWRITE_TAC[PATH_INTEGRAL_INTEGRAL] THEN MATCH_MP_TAC EQ_TRANS THEN
+  EXISTS_TAC
+   `integral (interval[vec 0,vec 1])
+             (\x. path_integral h
+                    (\y. f (g x) y * vector_derivative g (at x)))` THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC INTEGRAL_EQ THEN X_GEN_TAC `x:real^1` THEN
+    DISCH_TAC THEN REWRITE_TAC[] THEN
+    CONV_TAC SYM_CONV THEN MATCH_MP_TAC PATH_INTEGRAL_COMPLEX_RMUL THEN
+    REWRITE_TAC[PATH_INTEGRABLE_ON] THEN
+    MATCH_MP_TAC INTEGRABLE_CONTINUOUS THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_MUL THEN ASM_REWRITE_TAC[] THEN
+    SUBGOAL_THEN
+     `(\t:real^1. (f:complex->complex->complex) (g x) (h t)) =
+      (\y. f (fstcart y) (sndcart y)) o
+      (\t. pastecart (g(x:real^1)) (h t))`
+    SUBST1_TAC THENL
+     [REWRITE_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART];
+      ALL_TAC] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN CONJ_TAC THENL
+     [MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN
+      ASM_SIMP_TAC[CONTINUOUS_ON_CONST; GSYM path; VALID_PATH_IMP_PATH];
+      FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+         CONTINUOUS_ON_SUBSET)) THEN
+      REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_PASTECART_THM] THEN
+      ASM_SIMP_TAC[path_image; FUN_IN_IMAGE]];
+    ALL_TAC] THEN
+  MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC
+   `integral (interval[vec 0,vec 1])
+             (\y. path_integral g
+                    (\x. f x (h y) * vector_derivative h (at y)))` THEN
+  CONJ_TAC THENL
+   [ALL_TAC;
+    MATCH_MP_TAC INTEGRAL_EQ THEN X_GEN_TAC `y:real^1` THEN
+    DISCH_TAC THEN REWRITE_TAC[] THEN
+    MATCH_MP_TAC PATH_INTEGRAL_COMPLEX_RMUL THEN
+    REWRITE_TAC[PATH_INTEGRABLE_ON] THEN
+    MATCH_MP_TAC INTEGRABLE_CONTINUOUS THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_MUL THEN ASM_REWRITE_TAC[] THEN
+    SUBGOAL_THEN
+     `(\t:real^1. (f:complex->complex->complex) (g t) (h y)) =
+      (\z. f (fstcart z) (sndcart z)) o
+      (\t. pastecart (g t) (h(y:real^1)))`
+    SUBST1_TAC THENL
+     [REWRITE_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART];
+      ALL_TAC] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN CONJ_TAC THENL
+     [MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN
+      ASM_SIMP_TAC[CONTINUOUS_ON_CONST; GSYM path; VALID_PATH_IMP_PATH];
+      FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+         CONTINUOUS_ON_SUBSET)) THEN
+      REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_PASTECART_THM] THEN
+      ASM_SIMP_TAC[path_image; FUN_IN_IMAGE]]] THEN
+  REWRITE_TAC[PATH_INTEGRAL_INTEGRAL] THEN
+  W(MP_TAC o PART_MATCH (lhand o rand)
+     INTEGRAL_SWAP_CONTINUOUS o lhs o snd) THEN
+  REWRITE_TAC[] THEN ANTS_TAC THENL
+   [ALL_TAC;
+    DISCH_THEN(fun th -> GEN_REWRITE_TAC LAND_CONV [th]) THEN
+    REPEAT(MATCH_MP_TAC INTEGRAL_EQ THEN
+           REWRITE_TAC[] THEN REPEAT STRIP_TAC) THEN
+    REWRITE_TAC[COMPLEX_MUL_AC]] THEN
+  REPEAT(MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_MUL THEN CONJ_TAC) THENL
+   [ALL_TAC;
+    SUBGOAL_THEN
+     `(\z:real^(1,1)finite_sum. vector_derivative g (at (fstcart z))) =
+      (\t. vector_derivative (g:real^1->complex) (at t)) o fstcart`
+    SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
+    SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART] THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+        CONTINUOUS_ON_SUBSET)) THEN
+    SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_PASTECART_THM; PCROSS;
+             FORALL_PASTECART; GSYM PCROSS_INTERVAL; FSTCART_PASTECART];
+    SUBGOAL_THEN
+     `(\z:real^(1,1)finite_sum. vector_derivative h (at (sndcart z))) =
+      (\t. vector_derivative (h:real^1->complex) (at t)) o sndcart`
+    SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
+    SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_SNDCART] THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+        CONTINUOUS_ON_SUBSET)) THEN
+    SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_PASTECART_THM; PCROSS;
+          FORALL_PASTECART; GSYM PCROSS_INTERVAL; SNDCART_PASTECART]] THEN
+  SUBGOAL_THEN
+   `(\z. f (g (fstcart z)) (h (sndcart z))) =
+    (\y. (f:complex->complex->complex) (fstcart y) (sndcart y)) o
+    (\p. pastecart (g(fstcart p:real^1)) (h(sndcart p:real^1)))`
+  SUBST1_TAC THENL
+   [REWRITE_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART]; ALL_TAC] THEN
+  MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN CONJ_TAC THENL
+   [MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN
+    CONJ_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
+    SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART; LINEAR_SNDCART] THEN
+    REWRITE_TAC[GSYM PCROSS_INTERVAL; PCROSS; GSYM SIMPLE_IMAGE] THEN
+    REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART;
+                SET_RULE `{f x | x IN {g a b | P a /\ Q b}} =
+                          {f(g a b) | P a /\ Q b}`] THEN
+    REPEAT(FIRST_X_ASSUM(ASSUME_TAC o REWRITE_RULE[path] o
+        MATCH_MP VALID_PATH_IMP_PATH)) THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+      CONTINUOUS_ON_SUBSET)) THEN
+    SIMP_TAC[SUBSET; FORALL_IN_GSPEC];
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+      CONTINUOUS_ON_SUBSET)) THEN
+    REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_PASTECART_THM;
+                FORALL_PASTECART; GSYM PCROSS_INTERVAL; PCROSS;
+                path_image; FSTCART_PASTECART; SNDCART_PASTECART] THEN
+    SIMP_TAC[FUN_IN_IMAGE]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* The key quadrisection step.                                               *)
+(* ------------------------------------------------------------------------- *)
+
+let NORM_SUM_LEMMA = prove
+ (`norm(a + b + c + d:complex) >= e
+   ==> norm(a) >= e / &4 \/
+       norm(b) >= e / &4 \/
+       norm(c) >= e / &4 \/
+       norm(d) >= e / &4`,
+  NORM_ARITH_TAC);;
+
+let CAUCHY_THEOREM_QUADRISECTION = prove
+ (`!f a b c e K.
+        f continuous_on (convex hull {a,b,c}) /\
+        dist (a,b) <= K /\
+        dist (b,c) <= K /\
+        dist (c,a) <= K /\
+        norm(path_integral(linepath(a,b)) f +
+             path_integral(linepath(b,c)) f +
+             path_integral(linepath(c,a)) f) >= e * K pow 2
+        ==> ?a' b' c'. a' IN convex hull {a,b,c} /\
+                       b' IN convex hull {a,b,c} /\
+                       c' IN convex hull {a,b,c} /\
+                       dist(a',b') <= K / &2 /\
+                       dist(b',c') <= K / &2 /\
+                       dist(c',a') <= K / &2 /\
+                       norm(path_integral(linepath(a',b')) f +
+                            path_integral(linepath(b',c')) f +
+                            path_integral(linepath(c',a')) f)
+                        >= e * (K / &2) pow 2`,
+  REPEAT STRIP_TAC THEN MAP_EVERY ABBREV_TAC
+   [`a':complex = midpoint(b,c)`;
+    `b':complex = midpoint(c,a)`;
+    `c':complex = midpoint(a,b)`] THEN
+  SUBGOAL_THEN
+   `path_integral(linepath(a,b)) f +
+    path_integral(linepath(b,c)) f +
+    path_integral(linepath(c,a)) f =
+    (path_integral(linepath(a,c')) f +
+     path_integral(linepath(c',b')) f +
+     path_integral(linepath(b',a)) f) +
+    (path_integral(linepath(a',c')) f +
+     path_integral(linepath(c',b)) f +
+     path_integral(linepath(b,a')) f) +
+    (path_integral(linepath(a',c)) f +
+     path_integral(linepath(c,b')) f +
+     path_integral(linepath(b',a')) f) +
+    (path_integral(linepath(a',b')) f +
+     path_integral(linepath(b',c')) f +
+     path_integral(linepath(c',a')) f)`
+  SUBST_ALL_TAC THENL
+   [MP_TAC(SPEC `f:complex->complex` PATH_INTEGRAL_MIDPOINT) THEN DISCH_THEN
+     (fun th -> MP_TAC(SPECL [`a:complex`; `b:complex`] th) THEN
+                MP_TAC(SPECL [`b:complex`; `c:complex`] th) THEN
+                MP_TAC(SPECL [`c:complex`; `a:complex`] th)) THEN
+    MP_TAC(SPEC `f:complex->complex` PATH_INTEGRAL_REVERSE_LINEPATH) THEN DISCH_THEN
+     (fun th -> MP_TAC(SPECL [`a':complex`; `b':complex`] th) THEN
+                MP_TAC(SPECL [`b':complex`; `c':complex`] th) THEN
+                MP_TAC(SPECL [`c':complex`; `a':complex`] th)) THEN
+    ASM_REWRITE_TAC[] THEN
+    REPEAT(MATCH_MP_TAC(TAUT
+     `((a /\ c ==> b /\ d) ==> e) ==> (a ==> b) ==> (c ==> d) ==> e`)) THEN
+    ANTS_TAC THENL [ALL_TAC; CONV_TAC COMPLEX_RING] THEN
+    REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+    REPEAT CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+    EXISTS_TAC `convex hull {a:complex,b,c}` THEN ASM_REWRITE_TAC[] THEN
+    MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+    SIMP_TAC[IN_INSERT; NOT_IN_EMPTY;
+             TAUT `(a \/ b ==> c) <=> (a ==> c) /\ (b ==> c)`] THEN
+    MAP_EVERY EXPAND_TAC ["a'"; "b'"; "c'"] THEN
+    SIMP_TAC[MIDPOINTS_IN_CONVEX_HULL; POINTS_IN_CONVEX_HULL; IN_INSERT];
+    ALL_TAC] THEN
+  REWRITE_TAC[REAL_ARITH `e * (K / &2) pow 2 = (e * K pow 2) / &4`] THEN
+  FIRST_X_ASSUM(MP_TAC o MATCH_MP NORM_SUM_LEMMA) THEN STRIP_TAC THENL
+   [MAP_EVERY EXISTS_TAC [`a:complex`; `c':complex`; `b':complex`];
+    MAP_EVERY EXISTS_TAC [`a':complex`; `c':complex`; `b:complex`];
+    MAP_EVERY EXISTS_TAC [`a':complex`; `c:complex`; `b':complex`];
+    MAP_EVERY EXISTS_TAC [`a':complex`; `b':complex`; `c':complex`]] THEN
+  ASM_REWRITE_TAC[] THEN
+  MAP_EVERY EXPAND_TAC ["a'"; "b'"; "c'"] THEN
+  SIMP_TAC[MIDPOINTS_IN_CONVEX_HULL; POINTS_IN_CONVEX_HULL; IN_INSERT] THEN
+  REWRITE_TAC[midpoint; dist; GSYM VECTOR_SUB_LDISTRIB;
+              VECTOR_ARITH `a - inv(&2) % (a + b) = inv(&2) % (a - b)`;
+              VECTOR_ARITH `inv(&2) % (c + a) - a = inv(&2) % (c - a)`;
+              VECTOR_ARITH `(a + b) - (c + a) = b - c`;
+              VECTOR_ARITH `(b + c) - (c + a) = b - a`] THEN
+  SIMP_TAC[NORM_MUL; REAL_ARITH `abs(inv(&2)) * x <= k / &2 <=> x <= k`] THEN
+  ASM_REWRITE_TAC[GSYM dist] THEN ASM_MESON_TAC[DIST_SYM]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Yet at small enough scales this cannot be the case.                       *)
+(* ------------------------------------------------------------------------- *)
+
+let TRIANGLE_POINTS_CLOSER = prove
+ (`!a b c x y:real^N.
+        x IN convex hull {a,b,c} /\
+        y IN convex hull {a,b,c}
+        ==> norm(x - y) <= norm(a - b) \/
+            norm(x - y) <= norm(b - c) \/
+            norm(x - y) <= norm(c - a)`,
+  REPEAT STRIP_TAC THEN MP_TAC(ISPEC `{a:real^N,b,c}` SIMPLEX_EXTREMAL_LE) THEN
+  REWRITE_TAC[FINITE_INSERT; FINITE_RULES; NOT_INSERT_EMPTY] THEN
+  REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
+  REPEAT STRIP_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `y:real^N`]) THEN
+  ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN
+  ASM_MESON_TAC[NORM_POS_LE; REAL_LE_TRANS; NORM_SUB]);;
+
+let HOLOMORPHIC_POINT_SMALL_TRIANGLE = prove
+ (`!f s x e.
+        x IN s /\ f continuous_on s /\
+        f complex_differentiable (at x within s) /\
+        &0 < e
+        ==> ?k. &0 < k /\
+                !a b c. dist(a,b) <= k /\ dist(b,c) <= k /\ dist(c,a) <= k /\
+                        x IN convex hull {a,b,c} /\ convex hull {a,b,c} SUBSET s
+                        ==> norm(path_integral(linepath(a,b)) f +
+                                 path_integral(linepath(b,c)) f +
+                                 path_integral(linepath(c,a)) f)
+                            <= e * (dist(a,b) + dist(b,c) + dist(c,a)) pow 2`,
+  REPEAT STRIP_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [complex_differentiable]) THEN
+  DISCH_THEN(X_CHOOSE_THEN `f':complex` MP_TAC) THEN
+  GEN_REWRITE_TAC LAND_CONV [has_complex_derivative] THEN
+  REWRITE_TAC[HAS_DERIVATIVE_WITHIN_ALT] THEN
+  DISCH_THEN(MP_TAC o SPEC `e:real` o CONJUNCT2) THEN
+  ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
+  GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
+   [TAUT `a /\ b ==> c <=> b ==> a ==> c`] THEN
+  REWRITE_TAC[APPROACHABLE_LT_LE] THEN
+  ONCE_REWRITE_TAC[TAUT `b ==> a ==> c <=> a /\ b ==> c`] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN STRIP_TAC THEN
+  ASM_REWRITE_TAC[dist] THEN
+  MAP_EVERY X_GEN_TAC [`a:complex`; `b:complex`; `c:complex`] THEN
+  STRIP_TAC THEN
+  SUBGOAL_THEN
+   `path_integral (linepath(a,b)) f +
+    path_integral (linepath(b,c)) f +
+    path_integral (linepath(c,a)) f =
+    path_integral (linepath(a,b)) (\y. f y - f x - f' * (y - x)) +
+    path_integral (linepath(b,c)) (\y. f y - f x - f' * (y - x)) +
+    path_integral (linepath(c,a)) (\y. f y - f x - f' * (y - x))`
+  SUBST1_TAC THENL
+   [SUBGOAL_THEN
+     `path_integral (linepath(a,b)) (\y. f y - f x - f' * (y - x)) =
+      path_integral (linepath(a,b)) f -
+      path_integral (linepath(a,b)) (\y. f x + f' * (y - x)) /\
+      path_integral (linepath(b,c)) (\y. f y - f x - f' * (y - x)) =
+      path_integral (linepath(b,c)) f -
+      path_integral (linepath(b,c)) (\y. f x + f' * (y - x)) /\
+      path_integral (linepath(c,a)) (\y. f y - f x - f' * (y - x)) =
+      path_integral (linepath(c,a)) f -
+      path_integral (linepath(c,a)) (\y. f x + f' * (y - x))`
+    (REPEAT_TCL CONJUNCTS_THEN SUBST1_TAC) THENL
+     [REWRITE_TAC[SIMPLE_COMPLEX_ARITH `a - b - c = a - (b + c)`] THEN
+      REPEAT CONJ_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+      MATCH_MP_TAC HAS_PATH_INTEGRAL_SUB THEN
+      CONJ_TAC THEN MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+      MATCH_MP_TAC PATH_INTEGRABLE_CONTINUOUS_LINEPATH THEN
+      MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+      EXISTS_TAC `s:complex->bool` THEN
+      ASM_SIMP_TAC[CONTINUOUS_ON_ID; CONTINUOUS_ON_ADD; CONTINUOUS_ON_CONST;
+                   CONTINUOUS_ON_COMPLEX_MUL; CONTINUOUS_ON_SUB] THEN
+      MATCH_MP_TAC SUBSET_TRANS THEN
+      EXISTS_TAC `convex hull {a:complex,b,c}` THEN
+      ASM_REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+      MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+      REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN REPEAT STRIP_TAC THEN
+      ASM_SIMP_TAC[MIDPOINTS_IN_CONVEX_HULL; POINTS_IN_CONVEX_HULL; IN_INSERT];
+      ALL_TAC] THEN
+    REWRITE_TAC[COMPLEX_RING
+     `x + y + z = (x - x') + (y - y') + (z - z') <=>
+      x' + y' + z' = Cx(&0)`] THEN
+    MP_TAC(ISPECL [`a:complex`; `b:complex`; `c:complex`;
+                   `f':complex`; `f x - f' * x`]
+           TRIANGLE_LINEAR_HAS_CHAIN_INTEGRAL) THEN
+    REWRITE_TAC[COMPLEX_RING
+     `f' * x' + f x - f' * x = f x + f' * (x' - x)`] THEN
+    DISCH_THEN(MP_TAC o MATCH_MP HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL) THEN
+    REWRITE_TAC[];
+    ALL_TAC] THEN
+  ONCE_REWRITE_TAC[NORM_SUB] THEN MATCH_MP_TAC(REAL_ARITH
+   `&0 <= x * y /\ &0 <= x * z /\ &0 <= y * z /\
+    a <= (e * (x + y + z)) * x +
+         (e * (x + y + z)) * y +
+         (e * (x + y + z)) * z
+    ==> a <= e * (x + y + z) pow 2`) THEN
+  SIMP_TAC[REAL_LE_MUL; NORM_POS_LE] THEN
+  REPEAT(MATCH_MP_TAC NORM_TRIANGLE_LE THEN
+         MATCH_MP_TAC REAL_LE_ADD2 THEN CONJ_TAC) THEN
+  (MATCH_MP_TAC HAS_PATH_INTEGRAL_BOUND_LINEPATH THEN
+   EXISTS_TAC `\y:complex. f y - f x - f' * (y - x)` THEN
+   ASM_SIMP_TAC[REAL_LE_MUL; REAL_LE_ADD; REAL_LT_IMP_LE; NORM_POS_LE] THEN
+   CONJ_TAC THENL
+    [MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+     MATCH_MP_TAC PATH_INTEGRABLE_CONTINUOUS_LINEPATH THEN
+     MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:complex->bool` THEN
+     ASM_SIMP_TAC[CONTINUOUS_ON_SUB; ETA_AX; CONTINUOUS_ON_COMPLEX_MUL;
+                 CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
+     MATCH_MP_TAC SUBSET_TRANS THEN
+     EXISTS_TAC `convex hull {a:complex,b,c}` THEN
+     ASM_REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+     MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+     REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN REPEAT STRIP_TAC THEN
+     ASM_SIMP_TAC[MIDPOINTS_IN_CONVEX_HULL; POINTS_IN_CONVEX_HULL; IN_INSERT];
+     ALL_TAC] THEN
+   X_GEN_TAC `y:complex` THEN STRIP_TAC THEN
+   MATCH_MP_TAC REAL_LE_TRANS THEN
+   EXISTS_TAC `e * norm(y - x:complex)` THEN CONJ_TAC THENL
+    [FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
+      [MATCH_MP_TAC(SET_RULE `!t. y IN t /\ t SUBSET s ==> y IN s`) THEN
+       EXISTS_TAC `convex hull {a:complex,b,c}` THEN ASM_REWRITE_TAC[];
+       MATCH_MP_TAC(REAL_ARITH
+        `!n1 n2 n3. n1 <= d /\ n2 <= d /\ n3 <= d /\
+                    (n <= n1 \/ n <= n2 \/ n <= n3)
+                    ==> n <= d`) THEN
+       MAP_EVERY EXISTS_TAC
+        [`norm(a - b:complex)`; `norm(b - c:complex)`;
+         `norm(c - a:complex)`] THEN
+       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC TRIANGLE_POINTS_CLOSER];
+     ASM_SIMP_TAC[REAL_LE_LMUL_EQ] THEN
+     ONCE_REWRITE_TAC[NORM_SUB] THEN
+     MATCH_MP_TAC(REAL_ARITH
+      `(x <= a \/ x <= b \/ x <= c) /\ (&0 <= a /\ &0 <= b /\ &0 <= c)
+       ==> x <= a + b + c`) THEN
+     REWRITE_TAC[NORM_POS_LE] THEN MATCH_MP_TAC TRIANGLE_POINTS_CLOSER THEN
+     ASM_REWRITE_TAC[]] THEN
+    REPEAT CONJ_TAC THEN
+    FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
+     `x IN s ==> s SUBSET t ==> x IN t`)) THEN
+    REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+    REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN REPEAT STRIP_TAC THEN
+    ASM_SIMP_TAC[MIDPOINTS_IN_CONVEX_HULL; POINTS_IN_CONVEX_HULL;
+                 IN_INSERT]));;
+
+(* ------------------------------------------------------------------------- *)
+(* Hence the most basic theorem for a triangle.                              *)
+(* ------------------------------------------------------------------------- *)
+
+let CAUCHY_THEOREM_TRIANGLE = prove
+ (`!f a b c.
+        f holomorphic_on (convex hull {a,b,c})
+        ==> (f has_path_integral Cx(&0))
+            (linepath(a,b) ++ linepath(b,c) ++ linepath(c,a))`,
+  let lemma1 = prove
+   (`!P Q abc.
+          P abc 0 /\
+          (!abc:A n. P abc n ==> ?abc'. P abc' (SUC n) /\ Q abc' abc)
+          ==> ?ABC. ABC 0 = abc /\ !n. P (ABC n) n /\ Q (ABC(SUC n)) (ABC n)`,
+    REPEAT STRIP_TAC THEN
+    (MP_TAC o prove_recursive_functions_exist num_RECURSION)
+      `ABC 0 = abc:A /\
+       !n. ABC(SUC n) = @abc. P abc (SUC n) /\ Q abc (ABC n)` THEN
+    MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
+    STRIP_TAC THEN CONJ_TAC THENL [ASM_REWRITE_TAC[]; ALL_TAC] THEN
+    REWRITE_TAC[FORALL_AND_THM] THEN
+    MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
+     [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
+    DISCH_TAC THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]) in
+  let lemma3 = prove
+   (`!P Q a:A b:A c:A.
+          P a b c 0 /\
+          (!a b c n. P a b c n
+                     ==> ?a' b' c'. P a' b' c' (SUC n) /\ Q a' b' c' a b c)
+          ==> ?A B C. A 0 = a /\ B 0 = b /\ C 0 = c /\
+                      !n. P (A n) (B n) (C n) n /\
+                          Q (A(SUC n)) (B(SUC n)) (C(SUC n)) (A n) (B n) (C n)`,
+    REPEAT STRIP_TAC THEN
+    MP_TAC(ISPECL
+     [`\(a,b,c). (P:A->A->A->num->bool) a b c`;
+      `\(a,b,c) (a',b',c'). (Q:A->A->A->A->A->A->bool) a b c a' b' c'`;
+      `(a:A,b:A,c:A)`]
+          lemma1) THEN
+    REWRITE_TAC[FORALL_PAIR_THM; EXISTS_PAIR_THM] THEN
+    ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
+    DISCH_THEN(X_CHOOSE_THEN `ABC:num->A#A#A` STRIP_ASSUME_TAC) THEN
+    MAP_EVERY EXISTS_TAC
+     [`(\(a,b,c). a) o (ABC:num->A#A#A)`;
+      `(\(a,b,c). b) o (ABC:num->A#A#A)`;
+      `(\(a,b,c). c) o (ABC:num->A#A#A)`] THEN
+    REWRITE_TAC[o_THM] THEN
+    REPEAT(CONJ_TAC THENL [ASM_REWRITE_TAC[]; ALL_TAC]) THEN
+    X_GEN_TAC `n:num` THEN
+    FIRST_X_ASSUM(MP_TAC o SPEC `n:num`) THEN
+    SPEC_TAC(`(ABC:num->A#A#A) (SUC n)`,`y:A#A#A`) THEN
+    SPEC_TAC(`(ABC:num->A#A#A) n`,`x:A#A#A`) THEN
+    REWRITE_TAC[FORALL_PAIR_THM]) in
+  REPEAT STRIP_TAC THEN
+  STRIP_ASSUME_TAC(ISPECL [`a:complex`; `b:complex`; `c:complex`]
+                SEGMENTS_SUBSET_CONVEX_HULL) THEN
+  FIRST_ASSUM(ASSUME_TAC o MATCH_MP HOLOMORPHIC_ON_IMP_CONTINUOUS_ON) THEN
+  SUBGOAL_THEN
+   `f path_integrable_on (linepath(a,b) ++ linepath(b,c) ++ linepath(c,a))`
+  MP_TAC THENL
+   [SIMP_TAC[PATH_INTEGRABLE_JOIN; VALID_PATH_JOIN; VALID_PATH_LINEPATH;
+             PATHSTART_JOIN; PATHFINISH_JOIN; PATHSTART_LINEPATH;
+             PATHFINISH_LINEPATH] THEN
+    ASM_MESON_TAC[PATH_INTEGRABLE_CONTINUOUS_LINEPATH; CONTINUOUS_ON_SUBSET];
+    ALL_TAC] THEN
+  SIMP_TAC[path_integrable_on] THEN DISCH_THEN(X_CHOOSE_TAC `y:complex`) THEN
+  ASM_CASES_TAC `y = Cx(&0)` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
+  ABBREV_TAC
+   `K = &1 + max (dist(a:complex,b)) (max (dist(b,c)) (dist(c,a)))` THEN
+  SUBGOAL_THEN `&0 < K` ASSUME_TAC THENL
+   [EXPAND_TAC "K" THEN MATCH_MP_TAC(REAL_ARITH `&0 <= x ==> &0 < &1 + x`) THEN
+    REWRITE_TAC[REAL_LE_MAX; DIST_POS_LE];
+    ALL_TAC] THEN
+  ABBREV_TAC `e = norm(y:complex) / K pow 2` THEN
+  SUBGOAL_THEN `&0 < e` ASSUME_TAC THENL
+   [EXPAND_TAC "e" THEN
+    ASM_SIMP_TAC[REAL_LT_DIV; REAL_POW_LT; COMPLEX_NORM_NZ];
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+   `?A B C. A 0 = a /\ B 0 = b /\ C 0 = c /\
+            !n. (convex hull {A n,B n,C n} SUBSET convex hull {a,b,c} /\
+                 dist(A n,B n) <= K / &2 pow n /\
+                 dist(B n,C n) <= K / &2 pow n /\
+                 dist(C n,A n) <= K / &2 pow n /\
+                 norm(path_integral(linepath (A n,B n)) f +
+                      path_integral(linepath (B n,C n)) f +
+                      path_integral(linepath (C n,A n)) f) >=
+                 e * (K / &2 pow n) pow 2) /\
+                convex hull {A(SUC n),B(SUC n),C(SUC n)} SUBSET
+                convex hull {A n,B n,C n}`
+  MP_TAC THENL
+   [MATCH_MP_TAC lemma3 THEN CONJ_TAC THENL
+     [ASM_REWRITE_TAC[real_pow; REAL_DIV_1; CONJ_ASSOC; SUBSET_REFL] THEN
+      CONJ_TAC THENL [EXPAND_TAC "K" THEN REAL_ARITH_TAC; ALL_TAC] THEN
+      EXPAND_TAC "e" THEN
+      ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_LT_IMP_NZ; REAL_POW_LT] THEN
+      MATCH_MP_TAC(REAL_ARITH `x = y ==> x >= y`) THEN AP_TERM_TAC THEN
+      FIRST_ASSUM(SUBST1_TAC o SYM o
+        MATCH_MP HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL) THEN
+      REWRITE_TAC[];
+      ALL_TAC] THEN
+    MAP_EVERY X_GEN_TAC
+     [`a':complex`; `b':complex`; `c':complex`; `n:num`] THEN
+    REPEAT STRIP_TAC THEN
+    MP_TAC(SPECL [`f:complex->complex`; `a':complex`; `b':complex`;
+       `c':complex`; `e:real`; `K / &2 pow n`]
+       CAUCHY_THEOREM_QUADRISECTION) THEN
+    ASM_REWRITE_TAC[] THEN
+    ANTS_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ALL_TAC] THEN
+    REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN STRIP_TAC THEN
+    ASM_REWRITE_TAC[real_pow; REAL_FIELD `x / (&2 * y) = x / y / &2`] THEN
+    MATCH_MP_TAC(SET_RULE
+     `s SUBSET t /\ t SUBSET u ==> s SUBSET u /\ s SUBSET t`) THEN
+    ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+    ASM SET_TAC[];
+    ALL_TAC] THEN
+  REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC THEN
+  SUBGOAL_THEN
+   `?x:complex. !n:num. x IN convex hull {A n,B n,C n}`
+  STRIP_ASSUME_TAC THENL
+   [MATCH_MP_TAC BOUNDED_CLOSED_NEST THEN REPEAT CONJ_TAC THENL
+     [GEN_TAC THEN MATCH_MP_TAC COMPACT_IMP_CLOSED;
+      REWRITE_TAC[CONVEX_HULL_EQ_EMPTY; NOT_INSERT_EMPTY];
+      MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN ASM_REWRITE_TAC[] THEN
+      MESON_TAC[SUBSET_REFL; SUBSET_TRANS];
+      MATCH_MP_TAC COMPACT_IMP_BOUNDED] THEN
+    MATCH_MP_TAC FINITE_IMP_COMPACT_CONVEX_HULL THEN
+    REWRITE_TAC[FINITE_INSERT; FINITE_RULES];
+    ALL_TAC] THEN
+  MP_TAC(ISPECL [`f:complex->complex`; `convex hull {a:complex,b,c}`;
+                 `x:complex`; `e / &10`] HOLOMORPHIC_POINT_SMALL_TRIANGLE) THEN
+  ANTS_TAC THENL
+   [ASM_SIMP_TAC[HOLOMORPHIC_ON_IMP_CONTINUOUS_ON; complex_differentiable] THEN
+    ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
+    ASM_MESON_TAC[holomorphic_on; SUBSET];
+    ALL_TAC] THEN
+  DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
+  MP_TAC(SPEC `K:real / k` REAL_ARCH_POW2) THEN
+  ASM_SIMP_TAC[REAL_LT_LDIV_EQ] THEN
+  ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
+  SIMP_TAC[GSYM REAL_LT_LDIV_EQ; REAL_POW_LT; REAL_OF_NUM_LT; ARITH] THEN
+  DISCH_THEN(X_CHOOSE_TAC `n:num`) THEN FIRST_X_ASSUM(MP_TAC o SPECL
+   [`(A:num->complex) n`; `(B:num->complex) n`; `(C:num->complex) n`]) THEN
+  ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
+   [ASM_MESON_TAC[REAL_LE_TRANS; REAL_LT_IMP_LE]; ALL_TAC] THEN
+  ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_THEN(K ALL_TAC) THEN
+  REWRITE_TAC[REAL_NOT_LE] THEN
+  MATCH_MP_TAC REAL_LTE_TRANS THEN
+  EXISTS_TAC `e * (K / &2 pow n) pow 2` THEN
+  CONJ_TAC THENL [ALL_TAC; ASM_REWRITE_TAC[GSYM real_ge]] THEN
+  ASM_SIMP_TAC[real_div; GSYM REAL_MUL_ASSOC; REAL_LT_LMUL_EQ] THEN
+  MATCH_MP_TAC(REAL_ARITH
+   `&0 < x /\ y <= &9 * x ==> inv(&10) * y < x`) THEN
+  ASM_SIMP_TAC[REAL_POW_LT; REAL_LT_MUL; REAL_LT_INV_EQ;
+                REAL_OF_NUM_LT; ARITH] THEN
+  REWRITE_TAC[REAL_ARITH `&9 * x pow 2 = (&3 * x) pow 2`] THEN
+  MATCH_MP_TAC REAL_POW_LE2 THEN
+  SIMP_TAC[REAL_LE_ADD; DIST_POS_LE; GSYM real_div] THEN
+  MATCH_MP_TAC(REAL_ARITH
+   `x <= a /\ y <= a /\ z <= a ==> x + y + z <= &3 * a`) THEN
+  ASM_REWRITE_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Version needing function holomorphic in interior only.                    *)
+(* ------------------------------------------------------------------------- *)
+
+let CAUCHY_THEOREM_FLAT_LEMMA = prove
+ (`!f a b c k.
+        f continuous_on convex hull {a,b,c} /\ c - a = k % (b - a) /\ &0 <= k
+        ==> path_integral (linepath(a,b)) f +
+            path_integral (linepath(b,c)) f +
+            path_integral (linepath(c,a)) f = Cx(&0)`,
+  REPEAT STRIP_TAC THEN
+  STRIP_ASSUME_TAC(ISPECL [`a:complex`; `b:complex`; `c:complex`]
+                SEGMENTS_SUBSET_CONVEX_HULL) THEN
+  ASM_CASES_TAC `k <= &1` THENL
+   [MP_TAC(SPECL [`f:complex->complex`; `a:complex`; `b:complex`; `c:complex`;
+                  `k:real`] PATH_INTEGRAL_SPLIT) THEN
+    ASM_REWRITE_TAC[] THEN
+    ANTS_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ALL_TAC] THEN
+    DISCH_THEN SUBST1_TAC THEN MATCH_MP_TAC(COMPLEX_RING
+     `x = --b /\ y = --a ==> (x + y) + (a + b) = Cx(&0)`) THEN
+    CONJ_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_REVERSE_LINEPATH THEN
+    ASM_MESON_TAC[CONTINUOUS_ON_SUBSET];
+    MP_TAC(SPECL [`f:complex->complex`; `a:complex`; `c:complex`; `b:complex`;
+                  `inv k:real`] PATH_INTEGRAL_SPLIT) THEN
+    ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_LE_INV_EQ; REAL_MUL_LINV; REAL_INV_LE_1;
+      VECTOR_MUL_LID; REAL_ARITH `~(k <= &1) ==> ~(k = &0) /\ &1 <= k`] THEN
+    ANTS_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ALL_TAC] THEN
+    MATCH_MP_TAC(COMPLEX_RING
+     `ac = --ca ==> ac = ab + bc ==> ab + bc + ca = Cx(&0)`) THEN
+    MATCH_MP_TAC PATH_INTEGRAL_REVERSE_LINEPATH THEN
+    ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]]);;
+
+let CAUCHY_THEOREM_FLAT = prove
+ (`!f a b c k.
+        f continuous_on convex hull {a,b,c} /\ c - a = k % (b - a)
+        ==> path_integral (linepath(a,b)) f +
+            path_integral (linepath(b,c)) f +
+            path_integral (linepath(c,a)) f = Cx(&0)`,
+  REPEAT STRIP_TAC THEN ASM_CASES_TAC `&0 <= k` THENL
+   [ASM_MESON_TAC[CAUCHY_THEOREM_FLAT_LEMMA]; ALL_TAC] THEN
+  STRIP_ASSUME_TAC(ISPECL [`a:complex`; `b:complex`; `c:complex`]
+                SEGMENTS_SUBSET_CONVEX_HULL) THEN
+  MP_TAC(ISPECL [`f:complex->complex`; `b:complex`; `a:complex`; `c:complex`;
+                 `&1 - k`] CAUCHY_THEOREM_FLAT_LEMMA) THEN
+  ANTS_TAC THENL
+   [ASM_MESON_TAC[INSERT_AC; REAL_ARITH `~(&0 <= k) ==> &0 <= &1 - k`;
+         VECTOR_ARITH `b - a = k % (c - a) ==> (b - c) = (&1 - k) % (a - c)`];
+    ALL_TAC] THEN
+  MATCH_MP_TAC(COMPLEX_RING
+     `ab = --ba /\ ac = --ca /\ bc = --cb
+      ==> ba + ac + cb = Cx(&0) ==> ab + bc + ca = Cx(&0)`) THEN
+  REPEAT CONJ_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_REVERSE_LINEPATH THEN
+  ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]);;
+
+let CAUCHY_THEOREM_TRIANGLE_INTERIOR = prove
+ (`!f a b c.
+        f continuous_on (convex hull {a,b,c}) /\
+        f holomorphic_on interior (convex hull {a,b,c})
+        ==> (f has_path_integral Cx(&0))
+            (linepath(a,b) ++ linepath(b,c) ++ linepath(c,a))`,
+  REPEAT STRIP_TAC THEN
+  STRIP_ASSUME_TAC(ISPECL [`a:complex`; `b:complex`; `c:complex`]
+                SEGMENTS_SUBSET_CONVEX_HULL) THEN
+  SUBGOAL_THEN
+    `?B. &0 < B /\
+         !y. y IN IMAGE (f:complex->complex) (convex hull {a,b,c})
+             ==> norm(y) <= B`
+  MP_TAC THENL
+   [REWRITE_TAC[GSYM BOUNDED_POS] THEN MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
+    MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
+    ASM_SIMP_TAC[FINITE_IMP_COMPACT_CONVEX_HULL; FINITE_INSERT; FINITE_RULES];
+    REWRITE_TAC[FORALL_IN_IMAGE] THEN STRIP_TAC] THEN
+  SUBGOAL_THEN
+    `?C. &0 < C /\ !x:complex. x IN convex hull {a,b,c} ==> norm(x) <= C`
+  MP_TAC THENL
+   [REWRITE_TAC[GSYM BOUNDED_POS] THEN
+    MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
+    ASM_SIMP_TAC[FINITE_IMP_COMPACT_CONVEX_HULL; FINITE_INSERT; FINITE_RULES];
+    STRIP_TAC] THEN
+  SUBGOAL_THEN
+   `(f:complex->complex) uniformly_continuous_on (convex hull {a,b,c})`
+  MP_TAC THENL
+   [MATCH_MP_TAC COMPACT_UNIFORMLY_CONTINUOUS THEN
+    ASM_SIMP_TAC[FINITE_IMP_COMPACT_CONVEX_HULL; FINITE_RULES; FINITE_INSERT];
+    ALL_TAC] THEN
+  REWRITE_TAC[uniformly_continuous_on] THEN DISCH_TAC THEN
+  SUBGOAL_THEN
+   `f path_integrable_on
+    (linepath (a,b) ++ linepath(b,c) ++ linepath(c,a))`
+  MP_TAC THENL
+   [SIMP_TAC[PATH_INTEGRABLE_JOIN; VALID_PATH_JOIN; VALID_PATH_LINEPATH;
+             PATHSTART_JOIN; PATHFINISH_JOIN; PATHSTART_LINEPATH;
+             PATHFINISH_LINEPATH] THEN
+    ASM_MESON_TAC[PATH_INTEGRABLE_CONTINUOUS_LINEPATH; CONTINUOUS_ON_SUBSET];
+    ALL_TAC] THEN
+  SIMP_TAC[path_integrable_on] THEN DISCH_THEN(X_CHOOSE_TAC `y:complex`) THEN
+  ASM_CASES_TAC `y = Cx(&0)` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
+  UNDISCH_TAC `~(y = Cx(&0))` THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
+  DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[] THEN
+  FIRST_ASSUM(ASSUME_TAC o SYM o MATCH_MP
+     HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL) THEN
+  ASM_REWRITE_TAC[] THEN
+  ASM_CASES_TAC `c:complex = a` THENL
+   [MATCH_MP_TAC CAUCHY_THEOREM_FLAT THEN
+    EXISTS_TAC `&0` THEN ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_SUB_EQ];
+    ALL_TAC] THEN
+  ASM_CASES_TAC `b:complex = c` THENL
+   [ONCE_REWRITE_TAC[COMPLEX_RING `a + b + c:complex = c + a + b`] THEN
+    MATCH_MP_TAC CAUCHY_THEOREM_FLAT THEN
+    EXISTS_TAC `&0` THEN ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_SUB_EQ] THEN
+    ASM_MESON_TAC[INSERT_AC];
+    ALL_TAC] THEN
+  ASM_CASES_TAC `a:complex = b` THENL
+   [ONCE_REWRITE_TAC[COMPLEX_RING `a + b + c:complex = b + c + a`] THEN
+    MATCH_MP_TAC CAUCHY_THEOREM_FLAT THEN
+    EXISTS_TAC `&0` THEN ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_SUB_EQ] THEN
+    ASM_MESON_TAC[INSERT_AC];
+    ALL_TAC] THEN
+  ASM_CASES_TAC `interior(convex hull {a:complex,b,c}) = {}` THENL
+   [MATCH_MP_TAC CAUCHY_THEOREM_FLAT THEN
+    SUBGOAL_THEN `{a:complex,b,c} HAS_SIZE (dimindex(:2) + 1)`
+    MP_TAC THENL
+     [ASM_SIMP_TAC[HAS_SIZE; CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
+      ASM_REWRITE_TAC[DIMINDEX_2; ARITH; IN_INSERT; NOT_IN_EMPTY];
+      ALL_TAC] THEN
+    DISCH_THEN(MP_TAC o MATCH_MP INTERIOR_CONVEX_HULL_EQ_EMPTY) THEN
+    ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
+    SUBGOAL_THEN `collinear{a:complex,b,c}` MP_TAC THENL
+     [ASM_REWRITE_TAC[COLLINEAR_3_EQ_AFFINE_DEPENDENT]; ALL_TAC] THEN
+    ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {b,a,c}`] THEN
+    ONCE_REWRITE_TAC[COLLINEAR_3] THEN
+    ASM_REWRITE_TAC[COLLINEAR_LEMMA; VECTOR_SUB_EQ];
+    ALL_TAC] THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
+  DISCH_THEN(X_CHOOSE_TAC `d:complex`) THEN FIRST_X_ASSUM(MP_TAC o SYM) THEN
+  DISCH_TAC THEN
+  ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `y = Cx(&0)` THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `norm(y:complex) / &24 / C`) THEN
+  SUBGOAL_THEN `&0 < norm(y:complex) / &24 / C` ASSUME_TAC THENL
+   [ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; NORM_POS_LE; REAL_LTE_ADD;
+                 COMPLEX_NORM_NZ; COMPLEX_SUB_0];
+    ASM_REWRITE_TAC[dist]] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN ABBREV_TAC
+   `e = min (&1)
+            (min (d1 / (&4 * C))
+                 ((norm(y:complex) / &24 / C) / B))` THEN
+  SUBGOAL_THEN `&0 < e` ASSUME_TAC THENL
+   [EXPAND_TAC "e" THEN
+    ASM_SIMP_TAC[REAL_HALF; REAL_LT_MIN; REAL_LT_DIV; COMPLEX_NORM_NZ;
+                 REAL_LT_MUL; REAL_OF_NUM_LT; ARITH];
+    ALL_TAC] THEN
+  ABBREV_TAC `shrink = \x:complex. x - e % (x - d)` THEN
+  SUBGOAL_THEN `shrink (a:complex) IN interior(convex hull {a,b,c}) /\
+                shrink b IN interior(convex hull {a,b,c}) /\
+                shrink c IN interior(convex hull {a,b,c})`
+  STRIP_ASSUME_TAC THENL
+   [REPEAT CONJ_TAC THEN EXPAND_TAC "shrink" THEN
+    MATCH_MP_TAC IN_INTERIOR_CONVEX_SHRINK THEN
+    ASM_REWRITE_TAC[CONVEX_CONVEX_HULL] THEN
+    (CONJ_TAC THENL [ALL_TAC; EXPAND_TAC "e" THEN REAL_ARITH_TAC]) THEN
+    MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
+    REWRITE_TAC[IN_INSERT];
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+   `norm((path_integral(linepath(shrink a,shrink b)) f -
+          path_integral(linepath(a,b)) f) +
+         (path_integral(linepath(shrink b,shrink c)) f -
+          path_integral(linepath(b,c)) f) +
+         (path_integral(linepath(shrink c,shrink a)) f -
+          path_integral(linepath(c,a)) f)) <= norm(y:complex) / &2`
+  MP_TAC THENL
+   [ALL_TAC;
+    ASM_REWRITE_TAC[COMPLEX_RING
+     `(ab' - ab) + (bc' - bc) + (ca' - ca) =
+      (ab' + bc' + ca') - (ab + bc + ca)`] THEN
+    SUBGOAL_THEN
+     `(f has_path_integral (Cx(&0)))
+      (linepath (shrink a,shrink b) ++
+       linepath (shrink b,shrink c) ++
+       linepath (shrink c,shrink (a:complex)))`
+    MP_TAC THENL
+     [MATCH_MP_TAC CAUCHY_THEOREM_TRIANGLE THEN
+      MATCH_MP_TAC HOLOMORPHIC_ON_SUBSET THEN
+      EXISTS_TAC `interior(convex hull {a:complex,b,c})` THEN
+      ASM_REWRITE_TAC[] THEN MATCH_MP_TAC HULL_MINIMAL THEN
+      SIMP_TAC[CONVEX_INTERIOR; CONVEX_CONVEX_HULL] THEN
+      ASM SET_TAC[];
+      ALL_TAC] THEN
+    DISCH_THEN(MP_TAC o MATCH_MP HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL) THEN
+    SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC) THEN
+    REWRITE_TAC[COMPLEX_SUB_LZERO; NORM_NEG] THEN
+    MATCH_MP_TAC(REAL_ARITH `&0 <= y /\ ~(y = &0) ==> ~(y <= y / &2)`) THEN
+    ASM_REWRITE_TAC[COMPLEX_NORM_ZERO; NORM_POS_LE]] THEN
+  SUBGOAL_THEN
+   `!x y. x IN convex hull {a,b,c} /\ y IN convex hull {a,b,c}
+          ==> norm(x - y) <= &2 * C`
+  ASSUME_TAC THENL
+   [REPEAT STRIP_TAC THEN REWRITE_TAC[REAL_MUL_2; VECTOR_SUB] THEN
+    MATCH_MP_TAC NORM_TRIANGLE_LE THEN REWRITE_TAC[NORM_NEG] THEN
+    MATCH_MP_TAC REAL_LE_ADD2 THEN ASM_SIMP_TAC[];
+    ALL_TAC] THEN
+  REWRITE_TAC[REAL_ARITH `x / &2 = x / &6 + x / &6 + x / &6`] THEN
+  REPEAT(MATCH_MP_TAC NORM_TRIANGLE_LE THEN
+         MATCH_MP_TAC REAL_LE_ADD2 THEN CONJ_TAC) THEN
+  GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN
+  GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [GSYM CONTENT_UNIT_1] THEN
+  MATCH_MP_TAC HAS_INTEGRAL_BOUND THENL
+   [EXISTS_TAC `\x. f(linepath(shrink a,shrink b) x) *
+                    (shrink b - shrink a) -
+                    f(linepath(a,b) x) * (b - a)`;
+    EXISTS_TAC `\x. f(linepath(shrink b,shrink c) x) *
+                    (shrink c - shrink b) -
+                    f(linepath(b,c) x) * (c - b)`;
+    EXISTS_TAC `\x. f(linepath(shrink c,shrink a) x) *
+                    (shrink a - shrink c) -
+                    f(linepath(c,a) x) * (a - c)`] THEN
+  ASM_SIMP_TAC[COMPLEX_NORM_NZ; REAL_ARITH `&0 < x ==> &0 <= x / &6`] THEN
+  (CONJ_TAC THENL
+    [MATCH_MP_TAC HAS_INTEGRAL_SUB THEN
+     REWRITE_TAC[GSYM HAS_PATH_INTEGRAL_LINEPATH] THEN
+     CONJ_TAC THEN MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+     MATCH_MP_TAC PATH_INTEGRABLE_CONTINUOUS_LINEPATH THEN
+     MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+     EXISTS_TAC `convex hull {a:complex,b,c}` THEN
+     ASM_REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+     MATCH_MP_TAC HULL_MINIMAL THEN
+     REWRITE_TAC[CONVEX_CONVEX_HULL; SUBSET; IN_INSERT; NOT_IN_EMPTY] THEN
+     ASM_MESON_TAC[SUBSET; INTERIOR_SUBSET];
+     ALL_TAC] THEN
+   REPEAT STRIP_TAC THEN
+   ONCE_REWRITE_TAC[COMPLEX_RING
+    `f' * x' - f * x = f' * (x' - x) + x * (f' - f):complex`] THEN
+   MATCH_MP_TAC NORM_TRIANGLE_LE THEN REWRITE_TAC[COMPLEX_NORM_MUL] THEN
+   MATCH_MP_TAC REAL_LE_TRANS THEN
+   EXISTS_TAC `B * (norm(y:complex) / &24 / C / B) * &2 * C +
+               (&2 * C) * (norm y / &24 / C)` THEN
+   CONJ_TAC THENL
+    [ALL_TAC;
+     MATCH_MP_TAC REAL_EQ_IMP_LE THEN
+     MAP_EVERY UNDISCH_TAC [`&0 < B`; `&0 < C`] THEN CONV_TAC REAL_FIELD] THEN
+   MATCH_MP_TAC REAL_LE_ADD2 THEN CONJ_TAC THEN
+   MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[NORM_POS_LE] THENL
+    [CONJ_TAC THENL
+      [FIRST_X_ASSUM MATCH_MP_TAC THEN
+       W(fun (asl,w) ->
+         MP_TAC(PART_MATCH (lhand o rand) LINEPATH_IN_PATH (lhand w))) THEN
+       ASM_REWRITE_TAC[] THEN
+       W(fun (asl,w) -> SPEC_TAC(lhand(rand w),`x:complex`)) THEN
+       REWRITE_TAC[GSYM SUBSET; SEGMENT_CONVEX_HULL] THEN
+       MATCH_MP_TAC HULL_MINIMAL THEN
+       REWRITE_TAC[CONVEX_CONVEX_HULL; SUBSET; IN_INSERT; NOT_IN_EMPTY] THEN
+       ASM_MESON_TAC[SUBSET; INTERIOR_SUBSET];
+       ALL_TAC] THEN
+     EXPAND_TAC "shrink" THEN
+     REWRITE_TAC[VECTOR_ARITH `(b - e % (b - d)) - (a - e % (a - d)) -
+                           (b - a) = e % (a - b)`] THEN
+     REWRITE_TAC[NORM_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN
+     ASM_SIMP_TAC[NORM_POS_LE; REAL_ARITH `&0 < x ==> abs x = x`;
+                  REAL_ABS_POS] THEN
+     CONJ_TAC THENL [EXPAND_TAC "e" THEN REAL_ARITH_TAC; ALL_TAC] THEN
+     FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THEN
+     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
+     REWRITE_TAC[IN_INSERT];
+     ALL_TAC] THEN
+   CONJ_TAC THENL
+    [FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THEN
+     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
+     REWRITE_TAC[IN_INSERT];
+     ALL_TAC] THEN
+   MATCH_MP_TAC REAL_LT_IMP_LE THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+   CONJ_TAC THENL
+    [W(fun (asl,w) ->
+       MP_TAC(PART_MATCH (lhand o rand) LINEPATH_IN_PATH (lhand w))) THEN
+     ASM_MESON_TAC[SUBSET];
+     ALL_TAC] THEN
+   CONJ_TAC THENL
+    [W(fun (asl,w) ->
+       MP_TAC(PART_MATCH (lhand o rand) LINEPATH_IN_PATH (lhand w))) THEN
+     ASM_REWRITE_TAC[] THEN
+     W(fun (asl,w) -> SPEC_TAC(lhand(rand w),`x:complex`)) THEN
+     REWRITE_TAC[GSYM SUBSET; SEGMENT_CONVEX_HULL] THEN
+     MATCH_MP_TAC HULL_MINIMAL THEN
+     REWRITE_TAC[CONVEX_CONVEX_HULL; SUBSET; IN_INSERT; NOT_IN_EMPTY] THEN
+     ASM_MESON_TAC[SUBSET; INTERIOR_SUBSET];
+     ALL_TAC] THEN
+   REWRITE_TAC[linepath] THEN REWRITE_TAC[VECTOR_ARITH
+     `((&1 - x) % a' + x % b') - ((&1 - x) % a + x % b) =
+      (&1 - x) % (a' - a) + x % (b' - b)`] THEN
+   EXPAND_TAC "shrink" THEN REWRITE_TAC[VECTOR_ARITH `a - b - a = --b`] THEN
+   MATCH_MP_TAC NORM_TRIANGLE_LT THEN REWRITE_TAC[NORM_MUL; NORM_NEG] THEN
+   MATCH_MP_TAC REAL_CONVEX_BOUND_LT THEN ONCE_REWRITE_TAC[TAUT
+    `a /\ b /\ c /\ d /\ e <=> (c /\ d /\ e) /\ a /\ b`] THEN
+   CONJ_TAC THENL
+    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN
+     REWRITE_TAC[DROP_VEC] THEN REAL_ARITH_TAC;
+     ALL_TAC] THEN
+   CONJ_TAC THEN
+   MATCH_MP_TAC REAL_LET_TRANS THEN
+   EXISTS_TAC `e * &2 * C` THEN
+   ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_ARITH `&0 < x ==> abs x = x`] THEN
+   (CONJ_TAC THENL
+     [FIRST_X_ASSUM MATCH_MP_TAC THEN
+      ASM_MESON_TAC[SUBSET; INTERIOR_SUBSET; HULL_SUBSET; IN_INSERT];
+      ALL_TAC]) THEN
+   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN
+   EXPAND_TAC "e" THEN REWRITE_TAC[REAL_MIN_LT] THEN
+   DISJ2_TAC THEN DISJ1_TAC THEN
+   REWRITE_TAC[REAL_FIELD `d / (a * b) = inv(a:real) * d / b`] THEN
+   REWRITE_TAC[REAL_ARITH `inv(&4) * x < inv(&2) * x <=> &0 < x`] THEN
+   ASM_SIMP_TAC[REAL_LT_DIV]));;
+
+(* ------------------------------------------------------------------------- *)
+(* Version allowing finite number of exceptional points.                     *)
+(* ------------------------------------------------------------------------- *)
+
+let CAUCHY_THEOREM_TRIANGLE_COFINITE = prove
+ (`!f s a b c.
+        f continuous_on (convex hull {a,b,c}) /\
+        FINITE s /\
+        (!x. x IN interior(convex hull {a,b,c}) DIFF s
+             ==> f complex_differentiable (at x))
+        ==> (f has_path_integral Cx(&0))
+            (linepath (a,b) ++ linepath(b,c) ++ linepath(c,a))`,
+  GEN_TAC THEN GEN_TAC THEN WF_INDUCT_TAC `CARD(s:complex->bool)` THEN
+  REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:complex->bool = {}` THENL
+   [MATCH_MP_TAC CAUCHY_THEOREM_TRIANGLE_INTERIOR THEN
+    ASM_REWRITE_TAC[holomorphic_on] THEN X_GEN_TAC `z:complex` THEN
+    DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `z:complex`) THEN
+    ASM_REWRITE_TAC[complex_differentiable; IN_DIFF; NOT_IN_EMPTY] THEN
+    MESON_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN];
+    ALL_TAC] THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
+  DISCH_THEN(X_CHOOSE_TAC `d:complex`) THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `s DELETE (d:complex)`) THEN
+  ASM_SIMP_TAC[CARD_DELETE; CARD_EQ_0;
+                 ARITH_RULE `n - 1 < n <=> ~(n = 0)`] THEN
+  ASM_CASES_TAC `(d:complex) IN convex hull {a,b,c}` THENL
+   [ALL_TAC;
+    DISCH_THEN MATCH_MP_TAC THEN
+    ASM_REWRITE_TAC[FINITE_DELETE; IN_DIFF; IN_DELETE] THEN
+    REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_REWRITE_TAC[IN_DIFF] THEN ASM_MESON_TAC[INTERIOR_SUBSET; SUBSET]] THEN
+  DISCH_TAC THEN SUBGOAL_THEN
+   `(f has_path_integral Cx(&0))
+    (linepath(a,b) ++ linepath(b,d) ++ linepath(d,a)) /\
+    (f has_path_integral Cx(&0))
+    (linepath(b,c) ++ linepath(c,d) ++ linepath(d,b)) /\
+    (f has_path_integral Cx(&0))
+    (linepath(c,a) ++ linepath(a,d) ++ linepath(d,c))`
+  MP_TAC THENL
+   [RULE_ASSUM_TAC(REWRITE_RULE[IMP_IMP; RIGHT_IMP_FORALL_THM]) THEN
+    REPEAT CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_REWRITE_TAC[FINITE_DELETE] THEN
+    (CONJ_TAC THENL
+      [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+       EXISTS_TAC `convex hull {a:complex,b,c}` THEN ASM_REWRITE_TAC[] THEN
+       MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+       REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
+       REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+       MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
+       REWRITE_TAC[IN_INSERT];
+       ALL_TAC]) THEN
+    ASM_REWRITE_TAC[FINITE_DELETE; IN_DIFF; IN_DELETE] THEN
+    REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [DE_MORGAN_THM]) THEN
+    (ASM_CASES_TAC `x:complex = d` THEN ASM_REWRITE_TAC[] THENL
+      [ASM_MESON_TAC[NOT_IN_INTERIOR_CONVEX_HULL_3]; ALL_TAC]) THEN
+    DISCH_TAC THEN ASM_REWRITE_TAC[IN_DIFF] THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
+     `x IN interior s
+      ==> interior s SUBSET interior t ==> x IN interior t`)) THEN
+    MATCH_MP_TAC SUBSET_INTERIOR THEN
+    MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+    SIMP_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
+    REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+    MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN REWRITE_TAC[IN_INSERT];
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+   `f path_integrable_on
+    (linepath (a,b) ++ linepath(b,c) ++ linepath(c,a))`
+  MP_TAC THENL
+   [SIMP_TAC[PATH_INTEGRABLE_JOIN; VALID_PATH_JOIN; VALID_PATH_LINEPATH;
+             PATHSTART_JOIN; PATHFINISH_JOIN; PATHSTART_LINEPATH;
+             PATHFINISH_LINEPATH] THEN
+    STRIP_ASSUME_TAC(ISPECL [`a:complex`; `b:complex`; `c:complex`]
+                  SEGMENTS_SUBSET_CONVEX_HULL) THEN
+    ASM_MESON_TAC[PATH_INTEGRABLE_CONTINUOUS_LINEPATH; CONTINUOUS_ON_SUBSET];
+    ALL_TAC] THEN
+  REWRITE_TAC[path_integrable_on; LEFT_IMP_EXISTS_THM] THEN
+  X_GEN_TAC `y:complex` THEN
+  DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
+  REWRITE_TAC[IMP_IMP] THEN
+  DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN
+   (MP_TAC o MATCH_MP HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL)) THEN
+  ASM_CASES_TAC `y = Cx(&0)` THEN ASM_REWRITE_TAC[] THENL
+   [ASM_MESON_TAC[]; UNDISCH_TAC `~(y = Cx(&0))`] THEN
+  REWRITE_TAC[] THEN
+  SUBGOAL_THEN `(f:complex->complex) continuous_on segment[a,d] /\
+                f continuous_on segment[b,d] /\
+                f continuous_on segment[c,d]`
+  MP_TAC THENL
+   [ALL_TAC;
+    DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN (MP_TAC o MATCH_MP
+               PATH_INTEGRAL_REVERSE_LINEPATH)) THEN
+    CONV_TAC COMPLEX_RING] THEN
+  REPEAT CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+  EXISTS_TAC `convex hull {a:complex,b,c}` THEN
+  ASM_REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+  MATCH_MP_TAC CONVEX_HULL_SUBSET THEN
+  SIMP_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
+  REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+  MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN REWRITE_TAC[IN_INSERT]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Existence of a primitive.                                                 *)
+(* ------------------------------------------------------------------------- *)
+
+let STARLIKE_CONVEX_SUBSET = prove
+ (`!s a b c:real^N.
+        a IN s /\ segment[b,c] SUBSET s /\
+        (!x. x IN s ==> segment[a,x] SUBSET s)
+        ==> convex hull {a,b,c} SUBSET s`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`{b:real^N,c}`; `a:real^N`] CONVEX_HULL_INSERT) THEN
+  REWRITE_TAC[NOT_INSERT_EMPTY] THEN DISCH_THEN SUBST1_TAC THEN
+  REWRITE_TAC[SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
+  MAP_EVERY X_GEN_TAC [`x:real^N`; `u:real`; `v:real`; `d:real^N`] THEN
+  STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `d:real^N`) THEN ANTS_TAC THENL
+   [ASM_MESON_TAC[SUBSET; SEGMENT_CONVEX_HULL];
+    ASM_REWRITE_TAC[SUBSET] THEN DISCH_THEN MATCH_MP_TAC THEN
+    REWRITE_TAC[SEGMENT_CONVEX_HULL; CONVEX_HULL_2; IN_ELIM_THM] THEN
+    ASM_MESON_TAC[]]);;
+
+let TRIANGLE_PATH_INTEGRALS_STARLIKE_PRIMITIVE = prove
+ (`!f s a.
+      a IN s /\ open s /\ f continuous_on s /\
+      (!z. z IN s ==> segment[a,z] SUBSET s) /\
+      (!b c. segment[b,c] SUBSET s
+             ==> path_integral (linepath(a,b)) f +
+                 path_integral (linepath(b,c)) f +
+                 path_integral (linepath(c,a)) f = Cx(&0))
+      ==> ?g. !z. z IN s ==> (g has_complex_derivative f(z)) (at z)`,
+  REPEAT STRIP_TAC THEN
+  EXISTS_TAC `\x. path_integral (linepath(a,x)) f` THEN
+  X_GEN_TAC `x:complex` THEN STRIP_TAC THEN
+  REWRITE_TAC[has_complex_derivative] THEN
+  REWRITE_TAC[has_derivative_at; LINEAR_COMPLEX_MUL] THEN
+  MATCH_MP_TAC LIM_TRANSFORM THEN
+  EXISTS_TAC `\y. inv(norm(y - x)) % (path_integral(linepath(x,y)) f -
+                   f x * (y - x))` THEN
+  REWRITE_TAC[VECTOR_ARITH
+   `i % (x - a) - i % (y - (z + a)) = i % (x + z - y)`] THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC LIM_EVENTUALLY THEN REWRITE_TAC[EVENTUALLY_AT] THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
+    DISCH_THEN(MP_TAC o SPEC `x:complex`) THEN ASM_REWRITE_TAC[] THEN
+    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
+    STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+    X_GEN_TAC `y:complex` THEN REWRITE_TAC[dist] THEN STRIP_TAC THEN
+    REWRITE_TAC[VECTOR_MUL_EQ_0] THEN DISJ2_TAC THEN
+    MP_TAC(SPECL [`f:complex->complex`; `a:complex`; `y:complex`]
+         PATH_INTEGRAL_REVERSE_LINEPATH) THEN
+    ANTS_TAC THENL
+     [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+      EXISTS_TAC `s:complex->bool` THEN ASM_REWRITE_TAC[] THEN
+      FIRST_X_ASSUM MATCH_MP_TAC THEN
+      FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
+      ASM_REWRITE_TAC[IN_BALL; ONCE_REWRITE_RULE[NORM_SUB] dist];
+      REWRITE_TAC[COMPLEX_VEC_0] THEN MATCH_MP_TAC(COMPLEX_RING
+        `ax + xy + ya = Cx(&0) ==> ay = --ya ==> xy + ax - ay = Cx(&0)`) THEN
+      FIRST_X_ASSUM MATCH_MP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o
+       MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT] SUBSET_TRANS)) THEN
+      REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+      MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_BALL] THEN
+      REWRITE_TAC[SUBSET; IN_BALL; IN_INSERT; NOT_IN_EMPTY] THEN
+      REPEAT STRIP_TAC THEN
+      ASM_REWRITE_TAC[dist; NORM_0; VECTOR_SUB_REFL] THEN
+      ASM_MESON_TAC[NORM_SUB]];
+    REWRITE_TAC[LIM_AT] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+    SUBGOAL_THEN `(f:complex->complex) continuous at x` MP_TAC THENL
+     [MATCH_MP_TAC CONTINUOUS_ON_INTERIOR THEN ASM_MESON_TAC[INTERIOR_OPEN];
+      ALL_TAC] THEN
+    REWRITE_TAC[continuous_at; dist; VECTOR_SUB_RZERO] THEN
+    DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
+    DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
+    DISCH_THEN(MP_TAC o SPEC `x:complex`) THEN
+    ASM_REWRITE_TAC[SUBSET; IN_BALL; dist] THEN
+    DISCH_THEN(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC) THEN
+    EXISTS_TAC `min d1 d2` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
+    X_GEN_TAC `y:complex` THEN STRIP_TAC THEN
+    SUBGOAL_THEN `f path_integrable_on linepath(x,y)` MP_TAC THENL
+     [MATCH_MP_TAC PATH_INTEGRABLE_CONTINUOUS_LINEPATH THEN
+      MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:complex->bool` THEN
+      ASM_REWRITE_TAC[] THEN
+      MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `ball(x:complex,d2)` THEN
+      CONJ_TAC THENL
+       [REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+        MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_BALL] THEN
+        REWRITE_TAC[SUBSET; IN_BALL; IN_INSERT; NOT_IN_EMPTY] THEN
+        REPEAT STRIP_TAC THEN
+        ASM_REWRITE_TAC[dist; NORM_0; VECTOR_SUB_REFL] THEN
+        ASM_MESON_TAC[NORM_SUB];
+        ASM_REWRITE_TAC[SUBSET; IN_BALL; dist]];
+      ALL_TAC] THEN
+    REWRITE_TAC[path_integrable_on; LEFT_IMP_EXISTS_THM] THEN
+    X_GEN_TAC `z:complex` THEN
+    MP_TAC(SPECL [`x:complex`; `y:complex`; `(f:complex->complex) x`]
+                  HAS_PATH_INTEGRAL_CONST_LINEPATH) THEN
+    REWRITE_TAC[IMP_IMP] THEN
+    DISCH_THEN(fun th -> ASSUME_TAC(CONJUNCT2 th) THEN MP_TAC th) THEN
+    FIRST_ASSUM(SUBST1_TAC o MATCH_MP PATH_INTEGRAL_UNIQUE) THEN
+    DISCH_THEN(MP_TAC o MATCH_MP HAS_PATH_INTEGRAL_SUB) THEN
+    DISCH_THEN(MP_TAC o MATCH_MP HAS_PATH_INTEGRAL_NEG) THEN
+    REWRITE_TAC[COMPLEX_NEG_SUB] THEN STRIP_TAC THEN
+    MATCH_MP_TAC(REAL_ARITH `x <= e / &2 /\ &0 < e ==> x < e`) THEN
+    ASM_REWRITE_TAC[NORM_MUL; REAL_ABS_INV; REAL_ABS_NORM] THEN
+    ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
+    ASM_SIMP_TAC[REAL_LE_LDIV_EQ] THEN
+    MATCH_MP_TAC HAS_PATH_INTEGRAL_BOUND_LINEPATH THEN
+    EXISTS_TAC `\w. (f:complex->complex) w - f x` THEN
+    ASM_SIMP_TAC[REAL_ARITH `&0 < e ==> &0 <= e / &2`] THEN
+    X_GEN_TAC `w:complex` THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LT_IMP_LE THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_MESON_TAC[REAL_LET_TRANS; SEGMENT_BOUND]]);;
+
+let HOLOMORPHIC_STARLIKE_PRIMITIVE = prove
+ (`!f s k. open s /\ starlike s /\ FINITE k /\ f continuous_on s /\
+           (!x. x IN s DIFF k ==> f complex_differentiable at x)
+           ==> ?g. !x. x IN s ==> (g has_complex_derivative f(x)) (at x)`,
+  REPEAT STRIP_TAC THEN
+  FIRST_X_ASSUM(X_CHOOSE_THEN `a:complex` STRIP_ASSUME_TAC o
+        GEN_REWRITE_RULE I [starlike]) THEN
+  MATCH_MP_TAC TRIANGLE_PATH_INTEGRALS_STARLIKE_PRIMITIVE THEN
+  EXISTS_TAC `a:complex` THEN ASM_REWRITE_TAC[] THEN
+  MAP_EVERY X_GEN_TAC [`x:complex`; `y:complex`] THEN STRIP_TAC THEN
+  MATCH_MP_TAC HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL THEN
+  MATCH_MP_TAC CAUCHY_THEOREM_TRIANGLE_COFINITE THEN
+  EXISTS_TAC `k:complex->bool` THEN ASM_REWRITE_TAC[] THEN
+  SUBGOAL_THEN `convex hull {a:complex,x,y} SUBSET s` ASSUME_TAC THENL
+   [MATCH_MP_TAC STARLIKE_CONVEX_SUBSET THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN
+  CONJ_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ALL_TAC] THEN
+  REWRITE_TAC[IN_DIFF] THEN REPEAT STRIP_TAC THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN_DIFF] THEN
+  ASM_MESON_TAC[SUBSET; INTERIOR_SUBSET]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Cauchy's theorem for an open starlike set.                                *)
+(* ------------------------------------------------------------------------- *)
+
+let CAUCHY_THEOREM_STARLIKE = prove
+ (`!f s k g. open s /\ starlike s /\ FINITE k /\ f continuous_on s /\
+             (!x. x IN s DIFF k ==> f complex_differentiable at x) /\
+             valid_path g /\ (path_image g) SUBSET s /\
+             pathfinish g = pathstart g
+             ==> (f has_path_integral Cx(&0)) (g)`,
+  MESON_TAC[HOLOMORPHIC_STARLIKE_PRIMITIVE; CAUCHY_THEOREM_PRIMITIVE;
+            HAS_COMPLEX_DERIVATIVE_AT_WITHIN]);;
+
+let CAUCHY_THEOREM_STARLIKE_SIMPLE = prove
+ (`!f s g. open s /\ starlike s /\ f holomorphic_on s /\
+           valid_path g /\ (path_image g) SUBSET s /\
+           pathfinish g = pathstart g
+           ==> (f has_path_integral Cx(&0)) (g)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC CAUCHY_THEOREM_STARLIKE THEN
+  MAP_EVERY EXISTS_TAC [`s:complex->bool`; `{}:complex->bool`] THEN
+  ASM_SIMP_TAC[HOLOMORPHIC_ON_IMP_CONTINUOUS_ON; FINITE_RULES] THEN
+  REWRITE_TAC[IN_DIFF; NOT_IN_EMPTY; complex_differentiable] THEN
+  ASM_MESON_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; holomorphic_on]);;
+
+(* ------------------------------------------------------------------------- *)
+(* For a convex set we can avoid assuming openness and boundary analyticity. *)
+(* ------------------------------------------------------------------------- *)
+
+let TRIANGLE_PATH_INTEGRALS_CONVEX_PRIMITIVE = prove
+ (`!f s a.
+      a IN s /\ convex s /\ f continuous_on s /\
+      (!b c. b IN s /\ c IN s
+             ==> path_integral (linepath(a,b)) f +
+                 path_integral (linepath(b,c)) f +
+                 path_integral (linepath(c,a)) f = Cx(&0))
+      ==> ?g. !z. z IN s ==> (g has_complex_derivative f(z)) (at z within s)`,
+  REPEAT STRIP_TAC THEN
+  EXISTS_TAC `\x. path_integral (linepath(a,x)) f` THEN
+  X_GEN_TAC `x:complex` THEN STRIP_TAC THEN
+  REWRITE_TAC[has_complex_derivative] THEN
+  REWRITE_TAC[has_derivative_within; LINEAR_COMPLEX_MUL] THEN
+  MATCH_MP_TAC LIM_TRANSFORM THEN
+  EXISTS_TAC `\y. inv(norm(y - x)) % (path_integral(linepath(x,y)) f -
+                   f x * (y - x))` THEN
+  REWRITE_TAC[VECTOR_ARITH
+   `i % (x - a) - i % (y - (z + a)) = i % (x + z - y)`] THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC LIM_EVENTUALLY THEN REWRITE_TAC[EVENTUALLY_WITHIN] THEN
+    EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN
+    X_GEN_TAC `y:complex` THEN STRIP_TAC THEN
+    REWRITE_TAC[VECTOR_MUL_EQ_0] THEN DISJ2_TAC THEN
+    MP_TAC(SPECL [`f:complex->complex`; `a:complex`; `y:complex`]
+         PATH_INTEGRAL_REVERSE_LINEPATH) THEN
+    ANTS_TAC THENL
+     [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+      EXISTS_TAC `s:complex->bool` THEN ASM_REWRITE_TAC[] THEN
+      REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+      MATCH_MP_TAC HULL_MINIMAL THEN ASM SET_TAC[];
+      REWRITE_TAC[COMPLEX_VEC_0] THEN MATCH_MP_TAC(COMPLEX_RING
+        `ax + xy + ya = Cx(&0) ==> ay = --ya ==> xy + ax - ay = Cx(&0)`) THEN
+      ASM_SIMP_TAC[]];
+    REWRITE_TAC[LIM_WITHIN] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+    SUBGOAL_THEN
+     `(f:complex->complex) continuous (at x within s)` MP_TAC THENL
+     [ASM_MESON_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN]; ALL_TAC] THEN
+    REWRITE_TAC[continuous_within; dist; VECTOR_SUB_RZERO] THEN
+    DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
+    DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
+    EXISTS_TAC `d1:real` THEN ASM_REWRITE_TAC[] THEN
+    X_GEN_TAC `y:complex` THEN STRIP_TAC THEN
+    SUBGOAL_THEN `f path_integrable_on linepath(x,y)` MP_TAC THENL
+     [MATCH_MP_TAC PATH_INTEGRABLE_CONTINUOUS_LINEPATH THEN
+      MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:complex->bool` THEN
+      ASM_REWRITE_TAC[] THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+      MATCH_MP_TAC HULL_MINIMAL THEN ASM SET_TAC[];
+      ALL_TAC] THEN
+    REWRITE_TAC[path_integrable_on; LEFT_IMP_EXISTS_THM] THEN
+    X_GEN_TAC `z:complex` THEN
+    MP_TAC(SPECL [`x:complex`; `y:complex`; `(f:complex->complex) x`]
+                  HAS_PATH_INTEGRAL_CONST_LINEPATH) THEN
+    REWRITE_TAC[IMP_IMP] THEN
+    DISCH_THEN(fun th -> ASSUME_TAC(CONJUNCT2 th) THEN MP_TAC th) THEN
+    FIRST_ASSUM(SUBST1_TAC o MATCH_MP PATH_INTEGRAL_UNIQUE) THEN
+    DISCH_THEN(MP_TAC o MATCH_MP HAS_PATH_INTEGRAL_SUB) THEN
+    DISCH_THEN(MP_TAC o MATCH_MP HAS_PATH_INTEGRAL_NEG) THEN
+    REWRITE_TAC[COMPLEX_NEG_SUB] THEN STRIP_TAC THEN
+    MATCH_MP_TAC(REAL_ARITH `x <= e / &2 /\ &0 < e ==> x < e`) THEN
+    ASM_REWRITE_TAC[NORM_MUL; REAL_ABS_INV; REAL_ABS_NORM] THEN
+    ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
+    ASM_SIMP_TAC[REAL_LE_LDIV_EQ] THEN
+    MATCH_MP_TAC HAS_PATH_INTEGRAL_BOUND_LINEPATH THEN
+    EXISTS_TAC `\w. (f:complex->complex) w - f x` THEN
+    ASM_SIMP_TAC[REAL_ARITH `&0 < e ==> &0 <= e / &2`] THEN
+    X_GEN_TAC `w:complex` THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LT_IMP_LE THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
+     [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
+       `w IN t ==> t SUBSET s ==> w IN s`)) THEN
+      REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
+      MATCH_MP_TAC HULL_MINIMAL THEN ASM SET_TAC[];
+      ASM_MESON_TAC[REAL_LET_TRANS; SEGMENT_BOUND]]]);;
+
+let PATHINTEGRAL_CONVEX_PRIMITIVE = prove
+ (`!f s. convex s /\ f continuous_on s /\
+         (!a b c. a IN s /\ b IN s /\ c IN s
+                  ==>  (f has_path_integral Cx(&0))
+                       (linepath (a,b) ++ linepath(b,c) ++ linepath(c,a)))
+         ==> ?g. !x. x IN s
+                     ==> (g has_complex_derivative f(x)) (at x within s)`,
+  REPEAT STRIP_TAC THEN
+  ASM_CASES_TAC `s:complex->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
+  FIRST_X_ASSUM(X_CHOOSE_THEN `a:complex` STRIP_ASSUME_TAC o
+        GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
+  MATCH_MP_TAC TRIANGLE_PATH_INTEGRALS_CONVEX_PRIMITIVE THEN
+  EXISTS_TAC `a:complex` THEN ASM_REWRITE_TAC[] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC HAS_CHAIN_INTEGRAL_CHAIN_INTEGRAL THEN
+  ASM_SIMP_TAC[]);;
+
+let HOLOMORPHIC_CONVEX_PRIMITIVE = prove
+ (`!f s k. convex s /\ FINITE k /\ f continuous_on s /\
+           (!x. x IN interior(s) DIFF k ==> f complex_differentiable at x)
+           ==> ?g. !x. x IN s
+                       ==> (g has_complex_derivative f(x)) (at x within s)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATHINTEGRAL_CONVEX_PRIMITIVE THEN
+  ASM_REWRITE_TAC[] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC CAUCHY_THEOREM_TRIANGLE_COFINITE THEN
+  EXISTS_TAC `k:complex->bool` THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+   [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:complex->bool` THEN
+    ASM_REWRITE_TAC[];
+    X_GEN_TAC `w:complex` THEN
+    DISCH_THEN(fun th -> FIRST_X_ASSUM MATCH_MP_TAC THEN MP_TAC th) THEN
+    SPEC_TAC(`w:complex`,`w:complex`) THEN ASM_REWRITE_TAC[GSYM SUBSET] THEN
+    MATCH_MP_TAC(SET_RULE `s SUBSET t ==> (s DIFF k) SUBSET (t DIFF k)`) THEN
+    MATCH_MP_TAC SUBSET_INTERIOR] THEN
+  MATCH_MP_TAC HULL_MINIMAL THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
+
+let CAUCHY_THEOREM_CONVEX = prove
+ (`!f s k g. convex s /\ FINITE k /\ f continuous_on s /\
+             (!x. x IN interior(s) DIFF k ==> f complex_differentiable at x) /\
+             valid_path g /\ (path_image g) SUBSET s /\
+             pathfinish g = pathstart g
+             ==> (f has_path_integral Cx(&0)) (g)`,
+  MESON_TAC[HOLOMORPHIC_CONVEX_PRIMITIVE; CAUCHY_THEOREM_PRIMITIVE]);;
+
+let CAUCHY_THEOREM_CONVEX_SIMPLE = prove
+ (`!f s g. convex s /\ f holomorphic_on s /\
+           valid_path g /\ (path_image g) SUBSET s /\
+           pathfinish g = pathstart g
+           ==> (f has_path_integral Cx(&0)) (g)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC CAUCHY_THEOREM_CONVEX THEN
+  MAP_EVERY EXISTS_TAC [`s:complex->bool`; `{}:complex->bool`] THEN
+  ASM_SIMP_TAC[HOLOMORPHIC_ON_IMP_CONTINUOUS_ON; FINITE_RULES] THEN
+  REWRITE_TAC[IN_DIFF; NOT_IN_EMPTY; complex_differentiable] THEN
+  SUBGOAL_THEN `f holomorphic_on (interior s)` MP_TAC THENL
+   [ASM_MESON_TAC[HOLOMORPHIC_ON_SUBSET; INTERIOR_SUBSET]; ALL_TAC] THEN
+  MESON_TAC[holomorphic_on; HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN;
+            OPEN_INTERIOR]);;
+
+(* ------------------------------------------------------------------------- *)
+(* In particular for a disc.                                                 *)
+(* ------------------------------------------------------------------------- *)
+
+let CAUCHY_THEOREM_DISC = prove
+ (`!f g k a e.
+        FINITE k /\ f continuous_on cball(a,e) /\
+        (!x. x IN ball(a,e) DIFF k ==> f complex_differentiable at x) /\
+        valid_path g /\ (path_image g) SUBSET cball(a,e) /\
+        pathfinish g = pathstart g
+        ==> (f has_path_integral Cx(&0)) (g)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC CAUCHY_THEOREM_CONVEX THEN
+  MAP_EVERY EXISTS_TAC [`cball(a:complex,e)`; `k:complex->bool`] THEN
+  ASM_REWRITE_TAC[INTERIOR_CBALL; CONVEX_CBALL]);;
+
+let CAUCHY_THEOREM_DISC_SIMPLE = prove
+ (`!f g a e.
+        f holomorphic_on ball(a,e) /\
+        valid_path g /\ (path_image g) SUBSET ball(a,e) /\
+        pathfinish g = pathstart g
+        ==> (f has_path_integral Cx(&0)) (g)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC CAUCHY_THEOREM_CONVEX_SIMPLE THEN
+  EXISTS_TAC `ball(a:complex,e)` THEN ASM_REWRITE_TAC[CONVEX_BALL; OPEN_BALL]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Generalize integrability to local primitives.                             *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRAL_LOCAL_PRIMITIVE_LEMMA = prove
+ (`!f f' g s a b.
+        (!x. x IN s ==> (f has_complex_derivative f' x) (at x within s)) /\
+        g piecewise_differentiable_on interval[a,b] /\
+        (!x. x IN interval[a,b] ==> g(x) IN s)
+        ==> (\x. f' (g x) * vector_derivative g (at x within interval[a,b]))
+            integrable_on interval[a,b]`,
+  REPEAT STRIP_TAC THEN
+  ASM_CASES_TAC `interval[a:real^1,b] = {}` THENL
+   [ASM_REWRITE_TAC[INTEGRABLE_ON_EMPTY];
+    REWRITE_TAC[integrable_on] THEN
+    EXISTS_TAC `(f:complex->complex) (g(b:real^1)) - f(g a)` THEN
+    MATCH_MP_TAC PATH_INTEGRAL_PRIMITIVE_LEMMA THEN
+    ASM_MESON_TAC[]]);;
+
+let PATH_INTEGRAL_LOCAL_PRIMITIVE_ANY = prove
+ (`!f g s a b.
+    (!x. x IN s
+         ==> ?d h. &0 < d /\
+                   !y. norm(y - x) < d
+                       ==> (h has_complex_derivative f(y)) (at y within s)) /\
+    g piecewise_differentiable_on interval[a,b] /\
+    (!x. x IN interval[a,b] ==> g(x) IN s)
+    ==> (\x. f(g x) * vector_derivative g (at x)) integrable_on interval[a,b]`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC INTEGRABLE_ON_LITTLE_SUBINTERVALS THEN
+  X_GEN_TAC `x:real^1` THEN DISCH_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `(g:real^1->complex) x`) THEN
+  ASM_SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN
+  MAP_EVERY X_GEN_TAC [`d:real`; `h:complex->complex`] THEN STRIP_TAC THEN
+  FIRST_ASSUM(MP_TAC o MATCH_MP
+    PIECEWISE_DIFFERENTIABLE_ON_IMP_CONTINUOUS_ON) THEN
+  REWRITE_TAC[continuous_on] THEN DISCH_THEN(MP_TAC o SPEC `x:real^1`) THEN
+  ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `d:real`) THEN
+  ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
+  STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
+  SIMP_TAC[integrable_on; GSYM HAS_INTEGRAL_LOCALIZED_VECTOR_DERIVATIVE] THEN
+  REWRITE_TAC[GSYM integrable_on] THEN
+  MATCH_MP_TAC PATH_INTEGRAL_LOCAL_PRIMITIVE_LEMMA THEN
+  MAP_EVERY EXISTS_TAC
+   [`h:complex->complex`; `IMAGE (g:real^1->complex) (interval[u,v])`] THEN
+  REWRITE_TAC[FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THENL
+   [MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_WITHIN_SUBSET THEN
+    EXISTS_TAC `s:complex->bool` THEN
+    CONJ_TAC THENL [FIRST_X_ASSUM MATCH_MP_TAC; ASM SET_TAC[]] THEN
+    REWRITE_TAC[GSYM dist] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_MESON_TAC[SUBSET; IN_BALL; DIST_SYM];
+    ASM_MESON_TAC[PIECEWISE_DIFFERENTIABLE_ON_SUBSET];
+    ASM SET_TAC[]]);;
+
+let PATH_INTEGRAL_LOCAL_PRIMITIVE = prove
+ (`!f g s.
+        (!x. x IN s
+         ==> ?d h. &0 < d /\
+                   !y. norm(y - x) < d
+                       ==> (h has_complex_derivative f(y)) (at y within s)) /\
+        valid_path g /\ (path_image g) SUBSET s
+        ==> f path_integrable_on g`,
+  REWRITE_TAC[valid_path; path_image; SUBSET; FORALL_IN_IMAGE] THEN
+  REWRITE_TAC[path_integrable_on; has_path_integral] THEN
+  REWRITE_TAC[HAS_INTEGRAL_LOCALIZED_VECTOR_DERIVATIVE] THEN
+  REWRITE_TAC[GSYM integrable_on; PATH_INTEGRAL_LOCAL_PRIMITIVE_ANY]);;
+
+(* ------------------------------------------------------------------------- *)
+(* In particular if a function is holomorphic.                               *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRABLE_HOLOMORPHIC = prove
+ (`!f g s k.
+        open s /\ FINITE k /\
+        f continuous_on s /\
+        (!x. x IN s DIFF k ==> f complex_differentiable at x) /\
+        valid_path g /\ path_image g SUBSET s
+        ==> f path_integrable_on g`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRAL_LOCAL_PRIMITIVE THEN
+  EXISTS_TAC `s:complex->bool` THEN ASM_REWRITE_TAC[] THEN
+  X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN ASM_REWRITE_TAC[] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN STRIP_TAC THEN
+  MP_TAC(ISPECL [`f:complex->complex`; `ball(z:complex,d)`;
+                 `k:complex->bool`] HOLOMORPHIC_CONVEX_PRIMITIVE) THEN
+  ANTS_TAC THENL
+   [ASM_REWRITE_TAC[CONVEX_BALL; DIFF_EMPTY] THEN CONJ_TAC THENL
+     [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ALL_TAC] THEN
+    GEN_TAC THEN DISCH_THEN(fun th ->
+        FIRST_X_ASSUM MATCH_MP_TAC THEN MP_TAC th) THEN
+    SIMP_TAC[IN_DIFF] THEN ASM_MESON_TAC[INTERIOR_SUBSET; SUBSET];
+    MATCH_MP_TAC MONO_EXISTS THEN
+    SIMP_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL] THEN
+    ONCE_REWRITE_TAC[NORM_SUB] THEN REWRITE_TAC[IN_BALL; dist] THEN
+    ASM_MESON_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN]]);;
+
+let PATH_INTEGRABLE_HOLOMORPHIC_SIMPLE = prove
+ (`!f g s. open s /\ f holomorphic_on s /\ valid_path g /\ path_image g SUBSET s
+           ==> f path_integrable_on g`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRABLE_HOLOMORPHIC THEN
+  MAP_EVERY EXISTS_TAC [`s:complex->bool`; `{}:complex->bool`] THEN
+  ASM_SIMP_TAC[HOLOMORPHIC_ON_IMP_CONTINUOUS_ON; FINITE_RULES; DIFF_EMPTY] THEN
+  ASM_MESON_TAC[HOLOMORPHIC_ON_OPEN; complex_differentiable]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Key fact that path integral is the same for a "nearby" path. This is the  *)
+(* main lemma for the homotopy form of Cauchy's theorem and is also useful   *)
+(* if we want "without loss of generality" to assume some niceness of our    *)
+(* path (e.g. smoothness). It can also be used to define the integrals of    *)
+(* analytic functions over arbitrary continuous paths. This is just done for *)
+(* winding numbers now; I'm not sure if it's worth going further with that.  *)
+(* ------------------------------------------------------------------------- *)
+
+let PATH_INTEGRAL_NEARBY_ENDS,PATH_INTEGRAL_NEARBY_LOOP = (CONJ_PAIR o prove)
+ (`(!s p.
+      open s /\ path p /\ path_image p SUBSET s
+      ==> ?d. &0 < d /\
+              !g h. valid_path g /\ valid_path h /\
+                    (!t. t IN interval[vec 0,vec 1]
+                         ==> norm(g t - p t) < d /\ norm(h t - p t) < d) /\
+                    pathstart h = pathstart g /\ pathfinish h = pathfinish g
+                    ==> path_image g SUBSET s /\
+                        path_image h SUBSET s /\
+                        !f. f holomorphic_on s
+                            ==> path_integral h f = path_integral g f) /\
+   (!s p.
+      open s /\ path p /\ path_image p SUBSET s
+      ==> ?d. &0 < d /\
+              !g h. valid_path g /\ valid_path h /\
+                    (!t. t IN interval[vec 0,vec 1]
+                         ==> norm(g t - p t) < d /\ norm(h t - p t) < d) /\
+                    pathfinish g = pathstart g /\ pathfinish h = pathstart h
+                    ==> path_image g SUBSET s /\
+                        path_image h SUBSET s /\
+                        !f. f holomorphic_on s
+                            ==> path_integral h f = path_integral g f)`,
+  REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN
+  MAP_EVERY (fun t -> ASM_CASES_TAC t THEN ASM_REWRITE_TAC[])
+   [`open(s:complex->bool)`;
+    `path(p:real^1->complex)`;
+    `path_image(p:real^1->complex) SUBSET s`] THEN
+  REWRITE_TAC[RIGHT_IMP_EXISTS_THM] THEN
+  MATCH_MP_TAC(MESON[] `(?x. P x /\ Q x) ==> (?x. P x) /\ (?x. Q x)`) THEN
+  SUBGOAL_THEN
+   `!z. z IN path_image p ==> ?e. &0 < e /\ ball(z:complex,e) SUBSET s`
+  MP_TAC THENL
+   [ASM_MESON_TAC[OPEN_CONTAINS_BALL; SUBSET]; ALL_TAC] THEN
+  GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
+   [RIGHT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM; SKOLEM_THM] THEN
+  REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `ee:complex->real` THEN
+  DISCH_THEN(LABEL_TAC "*") THEN
+  FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_HEINE_BOREL o
+    MATCH_MP COMPACT_PATH_IMAGE) THEN
+  DISCH_THEN(MP_TAC o SPEC
+   `IMAGE (\z:complex. ball(z,ee z / &3)) (path_image p)`) THEN
+  ANTS_TAC THENL
+   [REWRITE_TAC[FORALL_IN_IMAGE; OPEN_BALL; SUBSET] THEN
+    X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+    REWRITE_TAC[UNIONS_IMAGE; IN_ELIM_THM] THEN EXISTS_TAC `z:complex` THEN
+    ASM_SIMP_TAC[CENTRE_IN_BALL; REAL_ARITH `&0 < e / &3 <=> &0 < e`];
+    ALL_TAC] THEN
+  REWRITE_TAC[path_image; GSYM IMAGE_o] THEN REWRITE_TAC[GSYM path_image] THEN
+  ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`] THEN
+  REWRITE_TAC[CONJ_ASSOC; FINITE_SUBSET_IMAGE] THEN
+  REWRITE_TAC[LEFT_AND_EXISTS_THM; MESON[]
+   `(?f s. (P s /\ f = g s) /\ Q f) <=> ?s. P s /\ Q(g s)`] THEN
+  REWRITE_TAC[UNIONS_IMAGE; LEFT_IMP_EXISTS_THM] THEN
+  X_GEN_TAC `k:real^1->bool` THEN
+  DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
+  GEN_REWRITE_TAC LAND_CONV [SUBSET] THEN REWRITE_TAC[IN_ELIM_THM; o_THM] THEN
+  ASM_CASES_TAC `k:real^1->bool = {}` THENL
+   [ASM_REWRITE_TAC[NOT_IN_EMPTY; GSYM NOT_EXISTS_THM; MEMBER_NOT_EMPTY] THEN
+    REWRITE_TAC[PATH_IMAGE_NONEMPTY];
+    DISCH_THEN(LABEL_TAC "+")] THEN
+  SUBGOAL_THEN
+    `!i:real^1. i IN k ==> &0 < ee((p i):complex)`
+  ASSUME_TAC THENL
+   [ASM_MESON_TAC[SUBSET; path_image; IN_IMAGE]; ALL_TAC] THEN
+  ABBREV_TAC `e = inf(IMAGE ((ee:complex->real) o (p:real^1->complex)) k)` THEN
+  MP_TAC(ISPEC `IMAGE ((ee:complex->real) o (p:real^1->complex)) k`
+    INF_FINITE) THEN
+  MP_TAC(ISPECL [`IMAGE ((ee:complex->real) o (p:real^1->complex)) k`; `&0`]
+    REAL_LT_INF_FINITE) THEN
+  ASM_SIMP_TAC[FINITE_IMAGE; IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
+  ASM_REWRITE_TAC[o_THM] THEN DISCH_TAC THEN
+  DISCH_THEN(ASSUME_TAC o CONJUNCT2) THEN
+  EXISTS_TAC `e / &3` THEN
+  MP_TAC(ISPECL [`p:real^1->complex`; `interval[vec 0:real^1,vec 1]`]
+        COMPACT_UNIFORMLY_CONTINUOUS) THEN REWRITE_TAC[COMPACT_INTERVAL] THEN
+  ANTS_TAC THENL [ASM_MESON_TAC[path]; ALL_TAC] THEN
+  REWRITE_TAC[uniformly_continuous_on] THEN
+  DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
+  ASM_REWRITE_TAC[REAL_ARITH `&0 < e / &3 <=> &0 < e`] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
+  REWRITE_TAC[RIGHT_IMP_FORALL_THM; AND_FORALL_THM] THEN
+  MAP_EVERY X_GEN_TAC [`g:real^1->complex`; `h:real^1->complex`] THEN
+  MAP_EVERY (fun t -> ASM_CASES_TAC t THEN ASM_REWRITE_TAC[])
+   [`!t. t IN interval[vec 0,vec 1]
+         ==> norm((g:real^1->complex) t - p t) < e / &3 /\
+             norm((h:real^1->complex) t - p t) < e / &3`;
+    `valid_path(g:real^1->complex)`; `valid_path(h:real^1->complex)`] THEN
+  MATCH_MP_TAC(TAUT
+   `q /\ (p1 \/ p2 ==> q ==> r) ==> (p1 ==> q /\ r) /\ (p2 ==> q /\ r)`) THEN
+  CONJ_TAC THENL
+   [CONJ_TAC THEN REWRITE_TAC[path_image; SUBSET; FORALL_IN_IMAGE] THEN
+    X_GEN_TAC `t:real^1` THEN DISCH_TAC THEN
+    REMOVE_THEN "+" (MP_TAC o SPEC `(p:real^1->complex) t`) THEN
+    ASM_SIMP_TAC[path_image; FUN_IN_IMAGE; IN_BALL] THEN
+    DISCH_THEN(X_CHOOSE_THEN `u:real^1` STRIP_ASSUME_TAC) THENL
+     [SUBGOAL_THEN `(g:real^1->complex) t IN ball(p(u:real^1),ee(p u))`
+      MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[path_image; IN_IMAGE; SUBSET]];
+      SUBGOAL_THEN `(h:real^1->complex) t IN ball(p(u:real^1),ee(p u))`
+      MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[path_image; IN_IMAGE; SUBSET]]] THEN
+    REWRITE_TAC[IN_BALL] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
+     (NORM_ARITH `dist(gu,gt) < eu / &3
+                  ==> norm(ht - gt) < e / &3 /\ e <= eu
+                  ==> dist(gu,ht) < eu`)) THEN
+    ASM_SIMP_TAC[];
+    DISCH_TAC THEN STRIP_TAC THEN
+    X_GEN_TAC `f:complex->complex` THEN DISCH_TAC] THEN
+  SUBGOAL_THEN
+   `?ff. !z. z IN path_image p
+             ==> &0 < ee z /\ ball(z,ee z) SUBSET s /\
+                 !w. w IN ball(z,ee z)
+                     ==> (ff z has_complex_derivative f w) (at w)`
+  MP_TAC THENL
+   [REWRITE_TAC[GSYM SKOLEM_THM; RIGHT_EXISTS_IMP_THM;
+                RIGHT_EXISTS_AND_THM] THEN
+    X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+    REMOVE_THEN "*" (MP_TAC o SPEC `z:complex`) THEN
+    ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
+    MP_TAC(ISPECL [`f:complex->complex`; `ball(z:complex,ee z)`;
+                   `{}:complex->bool`] HOLOMORPHIC_CONVEX_PRIMITIVE) THEN
+    SIMP_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL] THEN
+    DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[CONVEX_BALL; FINITE_EMPTY] THEN
+    SIMP_TAC[DIFF_EMPTY; INTERIOR_OPEN; OPEN_BALL] THEN
+    SUBGOAL_THEN `f holomorphic_on ball(z,ee z)` MP_TAC THENL
+     [MATCH_MP_TAC HOLOMORPHIC_ON_SUBSET THEN EXISTS_TAC `s:complex->bool` THEN
+      ASM_REWRITE_TAC[];
+      SIMP_TAC[HOLOMORPHIC_ON_IMP_CONTINUOUS_ON] THEN
+      SIMP_TAC[holomorphic_on; HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL;
+               complex_differentiable]];
+    REMOVE_THEN "*" (K ALL_TAC) THEN
+    DISCH_THEN(CHOOSE_THEN (LABEL_TAC "*"))] THEN
+  MP_TAC(ISPEC `d:real` REAL_ARCH_INV) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `N:num` STRIP_ASSUME_TAC) THEN
+  SUBGOAL_THEN
+   `!n. n <= N
+        ==> path_integral(subpath (vec 0) (&n / &N % vec 1) h) f -
+            path_integral(subpath (vec 0) (&n / &N % vec 1) g) f =
+            path_integral(linepath (g(&n / &N % vec 1),h(&n / &N % vec 1))) f -
+            path_integral(linepath (g(vec 0),h(vec 0))) f`
+  (MP_TAC o SPEC `N:num`) THENL
+   [ALL_TAC;
+    ASM_SIMP_TAC[LE_REFL; REAL_DIV_REFL; REAL_OF_NUM_EQ; VECTOR_MUL_LID] THEN
+    FIRST_X_ASSUM(DISJ_CASES_THEN MP_TAC) THEN
+    REWRITE_TAC[pathstart; pathfinish] THEN STRIP_TAC THEN
+    ASM_REWRITE_TAC[SUBPATH_TRIVIAL; PATH_INTEGRAL_TRIVIAL] THEN
+    CONV_TAC COMPLEX_RING] THEN
+  INDUCT_TAC THENL
+   [REWRITE_TAC[real_div; REAL_MUL_LZERO; VECTOR_MUL_LZERO] THEN
+    FIRST_X_ASSUM(DISJ_CASES_THEN MP_TAC) THEN
+    REWRITE_TAC[pathstart; pathfinish] THEN REPEAT STRIP_TAC THEN
+    ASM_REWRITE_TAC[PATH_INTEGRAL_TRIVIAL; PATH_INTEGRAL_SUBPATH_REFL] THEN
+    REWRITE_TAC[COMPLEX_SUB_REFL];
+    DISCH_TAC THEN FIRST_X_ASSUM(K ALL_TAC o check (is_disj o concl))] THEN
+  REMOVE_THEN "+" (MP_TAC o SPEC `(p:real^1->complex)(&n / &N % vec 1)`) THEN
+  REWRITE_TAC[IN_BALL] THEN ANTS_TAC THENL
+   [REWRITE_TAC[path_image] THEN MATCH_MP_TAC FUN_IN_IMAGE THEN
+    REWRITE_TAC[IN_INTERVAL_1; DROP_CMUL; DROP_VEC; REAL_MUL_RID] THEN
+    ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; LE_1] THEN
+    REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_LE] THEN ASM_ARITH_TAC;
+    DISCH_THEN(X_CHOOSE_THEN `t:real^1` STRIP_ASSUME_TAC)] THEN
+  MP_TAC(ISPECL
+   [`(ff:complex->complex->complex) (p(t:real^1))`; `f:complex->complex`;
+    `subpath (&n / &N % vec 1) (&(SUC n) / &N % vec 1) (g:real^1->complex) ++
+     linepath(g (&(SUC n) / &N % vec 1),h(&(SUC n) / &N % vec 1)) ++
+     subpath (&(SUC n) / &N % vec 1) (&n / &N % vec 1) h ++
+     linepath(h (&n / &N % vec 1),g (&n / &N % vec 1))`;
+    `ball((p:real^1->complex) t,ee(p t))`] CAUCHY_THEOREM_PRIMITIVE) THEN
+  ASM_SIMP_TAC[VALID_PATH_JOIN_EQ; PATHSTART_JOIN; PATHFINISH_JOIN;
+   PATHSTART_SUBPATH; PATHFINISH_SUBPATH; PATH_IMAGE_JOIN; PATHSTART_LINEPATH;
+   PATHFINISH_LINEPATH; VALID_PATH_LINEPATH; UNION_SUBSET] THEN
+  ONCE_REWRITE_TAC[IMP_CONJ] THEN ANTS_TAC THENL
+   [X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+    REMOVE_THEN "*" (MP_TAC o SPEC `(p:real^1->complex) t`) THEN ANTS_TAC THENL
+     [ASM_MESON_TAC[path_image; IN_IMAGE; SUBSET];
+      ASM_SIMP_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN; CENTRE_IN_BALL]];
+    ALL_TAC] THEN
+  MATCH_MP_TAC(TAUT `p /\ q /\ (p ==> r ==> s) ==> (p /\ q ==> r) ==> s`) THEN
+  CONJ_TAC THENL
+   [CONJ_TAC THEN MATCH_MP_TAC VALID_PATH_SUBPATH THEN ASM_REWRITE_TAC[] THEN
+    REWRITE_TAC[IN_INTERVAL_1; DROP_CMUL; DROP_VEC; REAL_MUL_RID] THEN
+    ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; LE_1] THEN
+    REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_LE] THEN ASM_ARITH_TAC;
+    ALL_TAC] THEN
+  CONJ_TAC THENL
+   [SUBGOAL_THEN `drop(&n / &N % vec 1) <= drop(&(SUC n) / &N % vec 1)`
+    ASSUME_TAC THENL
+     [ASM_SIMP_TAC[DROP_CMUL; DROP_VEC; REAL_MUL_RID; REAL_LE_DIV2_EQ;
+                   REAL_OF_NUM_LT; LE_1; REAL_OF_NUM_LE] THEN
+      ARITH_TAC;
+      ASM_SIMP_TAC[PATH_IMAGE_SUBPATH; PATH_IMAGE_LINEPATH] THEN
+      ONCE_REWRITE_TAC[GSYM REVERSEPATH_SUBPATH] THEN
+      ASM_SIMP_TAC[PATH_IMAGE_SUBPATH; PATH_IMAGE_REVERSEPATH]] THEN
+    MATCH_MP_TAC(TAUT
+     `(p /\ r) /\ (p /\ r ==> q /\ s) ==> p /\ q /\ r /\ s`) THEN
+    CONJ_TAC THENL
+     [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
+      REWRITE_TAC[AND_FORALL_THM; TAUT
+        `(p ==> q) /\ (p ==> r) <=> p ==> q /\ r`] THEN
+      X_GEN_TAC `u:real^1` THEN REWRITE_TAC[IN_INTERVAL_1] THEN
+      REWRITE_TAC[DROP_CMUL; DROP_VEC; REAL_MUL_RID] THEN STRIP_TAC THEN
+      REWRITE_TAC[IN_BALL] THEN
+      FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (NORM_ARITH
+       `!e pu. dist(pt,pn) < ee / &3
+               ==> dist(pn,pu) < e / &3 /\ e <= ee /\
+                   norm(gu - pu) < e / &3 /\ norm(hu - pu) < e / &3
+                   ==> dist(pt,gu) < ee /\ dist(pt,hu) < ee`)) THEN
+      MAP_EVERY EXISTS_TAC [`e:real`; `(p:real^1->complex) u`] THEN
+      ASM_SIMP_TAC[] THEN
+      SUBGOAL_THEN `(u:real^1) IN interval[vec 0,vec 1]` ASSUME_TAC THENL
+       [REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN CONJ_TAC THENL
+         [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
+           REAL_LE_TRANS)) THEN ASM_SIMP_TAC[REAL_LE_DIV; REAL_POS];
+          FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+           REAL_LE_TRANS)) THEN
+          ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; LE_1] THEN
+          ASM_REWRITE_TAC[REAL_MUL_LID; REAL_OF_NUM_LE]];
+        ASM_SIMP_TAC[] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+        ASM_REWRITE_TAC[] THEN
+        REWRITE_TAC[DIST_REAL; GSYM drop; IN_INTERVAL_1;
+                    DROP_VEC; DROP_CMUL; REAL_MUL_RID] THEN
+        ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_POS; REAL_LE_DIV;
+              REAL_OF_NUM_LT; LE_1; REAL_MUL_LID; REAL_OF_NUM_LE;
+              ARITH_RULE `SUC n <= N ==> n <= N`] THEN
+        FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
+         `u <= s ==> n <= u /\ s - n < d ==> abs(n - u) < d`)) THEN
+        ASM_REWRITE_TAC[] THEN
+        REWRITE_TAC[real_div; GSYM REAL_SUB_RDISTRIB] THEN
+        SIMP_TAC[REAL_OF_NUM_SUB; ARITH_RULE `n <= SUC n`] THEN
+        ASM_REWRITE_TAC[ARITH_RULE `SUC n - n = 1`; REAL_MUL_LID]];
+      GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [SUBSET] THEN
+      REWRITE_TAC[FORALL_IN_IMAGE] THEN STRIP_TAC THEN
+      REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN CONJ_TAC THEN
+      MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_BALL] THEN
+      REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET] THEN
+      CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+      REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_EQ_EMPTY_1; REAL_NOT_LT] THEN
+      REWRITE_TAC[DROP_VEC; DROP_CMUL; REAL_MUL_RID] THEN
+        ASM_SIMP_TAC[REAL_LE_DIV2_EQ; REAL_POS; REAL_LE_DIV;
+              REAL_OF_NUM_LT; LE_1; REAL_MUL_LID; REAL_OF_NUM_LE] THEN
+      ARITH_TAC];
+    STRIP_TAC THEN DISCH_THEN(fun th ->
+        MP_TAC(MATCH_MP PATH_INTEGRAL_UNIQUE th) THEN
+        MP_TAC(MATCH_MP HAS_PATH_INTEGRAL_INTEGRABLE th)) THEN
+    ASM_SIMP_TAC[PATH_INTEGRABLE_JOIN; VALID_PATH_JOIN_EQ; VALID_PATH_LINEPATH;
+      PATHSTART_SUBPATH; PATHFINISH_SUBPATH; PATHSTART_JOIN; PATHFINISH_JOIN;
+      PATHSTART_LINEPATH; PATHFINISH_LINEPATH; VALID_PATH_LINEPATH;
+      PATH_INTEGRAL_JOIN] THEN
+    STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o check(is_imp o concl)) THEN
+    ASM_SIMP_TAC[ARITH_RULE `SUC n <= N ==> n <= N`] THEN
+    MATCH_MP_TAC(COMPLEX_RING
+     `hn - he = hn' /\ gn + gd = gn' /\ hgn = --ghn
+      ==> hn - gn = ghn - gh0
+          ==> gd + ghn' + he + hgn = Cx(&0)
+              ==> hn' - gn' = ghn' - gh0`) THEN
+    REPEAT CONJ_TAC THENL
+     [ASM_SIMP_TAC[complex_sub; GSYM PATH_INTEGRAL_REVERSEPATH] THEN
+      REWRITE_TAC[REVERSEPATH_SUBPATH] THEN
+      MATCH_MP_TAC PATH_INTEGRAL_SUBPATH_COMBINE;
+      MATCH_MP_TAC PATH_INTEGRAL_SUBPATH_COMBINE;
+      GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
+       [GSYM REVERSEPATH_LINEPATH] THEN
+      MATCH_MP_TAC PATH_INTEGRAL_REVERSEPATH] THEN
+    ASM_REWRITE_TAC[VALID_PATH_LINEPATH] THEN
+    ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_CMUL; DROP_VEC; REAL_MUL_RID] THEN
+    ASM_SIMP_TAC[REAL_LE_DIV; REAL_POS; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; LE_1;
+                 REAL_MUL_LID; REAL_OF_NUM_LE] THEN
+    ASM_SIMP_TAC[ARITH_RULE `SUC n <= N ==> n <= N`] THEN
+    TRY(MATCH_MP_TAC PATH_INTEGRABLE_HOLOMORPHIC_SIMPLE THEN
+        EXISTS_TAC `s:complex->bool` THEN ASM_REWRITE_TAC[] THEN NO_TAC) THEN
+    ASM_MESON_TAC[PATH_INTEGRABLE_REVERSEPATH; VALID_PATH_LINEPATH;
+                  REVERSEPATH_LINEPATH]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Hence we can treat even non-rectifiable paths as having a "length"        *)
+(* for bounds on analytic functions in open sets.                            *)
+(* ------------------------------------------------------------------------- *)
+
+let VALID_PATH_VECTOR_POLYNOMIAL_FUNCTION = prove
+ (`!p:real^1->complex.
+     vector_polynomial_function p ==> valid_path p`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[valid_path] THEN
+  MATCH_MP_TAC DIFFERENTIABLE_ON_IMP_PIECEWISE_DIFFERENTIABLE THEN
+  MATCH_MP_TAC DIFFERENTIABLE_AT_IMP_DIFFERENTIABLE_ON THEN
+  REWRITE_TAC[VECTOR_DERIVATIVE_WORKS] THEN
+  REPEAT STRIP_TAC THEN REWRITE_TAC[vector_derivative] THEN
+  CONV_TAC SELECT_CONV THEN
+  ASM_MESON_TAC[HAS_VECTOR_DERIVATIVE_VECTOR_POLYNOMIAL_FUNCTION]);;
+
+let PATH_INTEGRAL_BOUND_EXISTS = prove
+ (`!s g. open s /\ valid_path g /\ path_image g SUBSET s
+         ==> ?L. &0 < L /\
+                 !f B. f holomorphic_on s /\ (!z. z IN s ==> norm(f z) <= B)
+                       ==> norm(path_integral g f) <= L * B`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`s:complex->bool`; `g:real^1->complex`]
+        PATH_INTEGRAL_NEARBY_ENDS) THEN
+  ASM_SIMP_TAC[VALID_PATH_IMP_PATH] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
+  DISCH_THEN(MP_TAC o SPEC `g:real^1->complex`) THEN
+  ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN
+  DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `d:real`]
+   PATH_APPROX_VECTOR_POLYNOMIAL_FUNCTION) THEN
+  ASM_SIMP_TAC[VALID_PATH_IMP_PATH] THEN
+  DISCH_THEN(X_CHOOSE_THEN `p:real^1->complex` STRIP_ASSUME_TAC) THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `p:real^1->complex`) THEN
+  ASM_SIMP_TAC[VALID_PATH_VECTOR_POLYNOMIAL_FUNCTION] THEN STRIP_TAC THEN
+  FIRST_ASSUM(X_CHOOSE_THEN `p':real^1->complex` STRIP_ASSUME_TAC o
+    MATCH_MP HAS_VECTOR_DERIVATIVE_VECTOR_POLYNOMIAL_FUNCTION) THEN
+  SUBGOAL_THEN `bounded(IMAGE (p':real^1->complex) (interval[vec 0,vec 1]))`
+  MP_TAC THENL
+   [MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
+    MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
+    REWRITE_TAC[COMPACT_INTERVAL] THEN
+    ASM_MESON_TAC[CONTINUOUS_VECTOR_POLYNOMIAL_FUNCTION;
+                  CONTINUOUS_AT_IMP_CONTINUOUS_ON];
+    REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE]] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `L:real` THEN STRIP_TAC THEN
+  ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN `f path_integrable_on p /\ valid_path p` STRIP_ASSUME_TAC THENL
+   [ASM_MESON_TAC[PATH_INTEGRABLE_HOLOMORPHIC_SIMPLE;
+                  VALID_PATH_VECTOR_POLYNOMIAL_FUNCTION];
+    ALL_TAC] THEN
+  MP_TAC(ISPECL [`f:complex->complex`; `p:real^1->complex`]
+        PATH_INTEGRAL_INTEGRAL) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN SUBST1_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
+   `drop(integral (interval[vec 0,vec 1]) (\x:real^1. lift(L * B)))` THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC INTEGRAL_NORM_BOUND_INTEGRAL THEN
+    ASM_REWRITE_TAC[INTEGRABLE_CONST; GSYM PATH_INTEGRABLE_ON] THEN
+    X_GEN_TAC `t:real^1` THEN DISCH_TAC THEN
+    ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
+    REWRITE_TAC[LIFT_DROP; COMPLEX_NORM_MUL] THEN
+    MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[NORM_POS_LE] THEN
+    CONJ_TAC THENL
+     [FIRST_X_ASSUM MATCH_MP_TAC THEN
+      ASM_MESON_TAC[path_image; SUBSET; IN_IMAGE];
+      ASM_MESON_TAC[HAS_VECTOR_DERIVATIVE_UNIQUE_AT]];
+    REWRITE_TAC[INTEGRAL_CONST; CONTENT_UNIT_1; VECTOR_MUL_LID] THEN
+    REWRITE_TAC[LIFT_DROP; REAL_LE_REFL]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Winding number.                                                           *)
+(* ------------------------------------------------------------------------- *)
+
+let winding_number = new_definition
+ `winding_number(g,z) =
+    @n. !e. &0 < e
+            ==> ?p. valid_path p /\ ~(z IN path_image p) /\
+                    pathstart p = pathstart g /\
+                    pathfinish p = pathfinish g /\
+                    (!t. t IN interval[vec 0,vec 1] ==> norm(g t - p t) < e) /\
+                    path_integral p (\w. Cx(&1) / (w - z)) =
+                    Cx(&2) * Cx(pi) * ii * n`;;
+
+let CX_2PII_NZ = prove
+ (`~(Cx(&2) * Cx(pi) * ii = Cx(&0))`,
+  SIMP_TAC[COMPLEX_ENTIRE; CX_PI_NZ; II_NZ; CX_INJ; REAL_OF_NUM_EQ; ARITH]);;
+
+let PATH_INTEGRABLE_INVERSEDIFF = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g)
+         ==> (\w. Cx(&1) / (w - z)) path_integrable_on g`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_INTEGRABLE_HOLOMORPHIC_SIMPLE THEN
+  EXISTS_TAC `(:complex) DELETE z` THEN
+  ASM_SIMP_TAC[OPEN_DELETE; OPEN_UNIV; HOLOMORPHIC_ON_OPEN; SET_RULE
+   `s SUBSET (UNIV DELETE x) <=> ~(x IN s)`] THEN
+  X_GEN_TAC `w:complex` THEN REWRITE_TAC[IN_UNIV; IN_DELETE] THEN
+  STRIP_TAC THEN
+  W(MP_TAC o DISCH_ALL o COMPLEX_DIFF_CONV o snd o dest_exists o snd) THEN
+  ASM_REWRITE_TAC[COMPLEX_SUB_0] THEN MESON_TAC[]);;
+
+let WINDING_NUMBER = prove
+ (`!g z e.
+        path g /\ ~(z IN path_image g) /\ &0 < e
+         ==> ?p. valid_path p /\ ~(z IN path_image p) /\
+                 pathstart p = pathstart g /\
+                 pathfinish p = pathfinish g /\
+                 (!t. t IN interval[vec 0,vec 1] ==> norm(g t - p t) < e) /\
+                 path_integral p (\w. Cx(&1) / (w - z)) =
+                 Cx(&2) * Cx(pi) * ii * winding_number(g,z)`,
+  REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
+  GEN_TAC THEN DISCH_TAC THEN GEN_TAC THEN DISCH_TAC THEN
+  REWRITE_TAC[winding_number] THEN CONV_TAC SELECT_CONV THEN
+  MP_TAC(ISPECL [`(:complex) DELETE z`; `g:real^1->complex`]
+        PATH_INTEGRAL_NEARBY_ENDS) THEN
+  ASM_SIMP_TAC[OPEN_DELETE; OPEN_UNIV] THEN
+  ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `d / &2`]
+    PATH_APPROX_VECTOR_POLYNOMIAL_FUNCTION) THEN
+  ASM_REWRITE_TAC[REAL_HALF] THEN
+  DISCH_THEN(X_CHOOSE_THEN `h:real^1->complex` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `Cx (&1) / (Cx (&2) * Cx pi * ii) *
+              path_integral h (\w. Cx (&1) / (w - z))` THEN
+  X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `min d e / &2`]
+    PATH_APPROX_VECTOR_POLYNOMIAL_FUNCTION) THEN
+  ASM_REWRITE_TAC[REAL_HALF; REAL_LT_MIN] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `p:real^1->complex` THEN
+  STRIP_TAC THEN
+  ASM_SIMP_TAC[VALID_PATH_VECTOR_POLYNOMIAL_FUNCTION; CX_2PII_NZ; COMPLEX_FIELD
+   `~(a * b * c = Cx(&0))
+    ==> a * b * c * Cx(&1) / (a * b * c) * z = z`] THEN
+  FIRST_X_ASSUM(MP_TAC o SPECL [`h:real^1->complex`; `p:real^1->complex`]) THEN
+  ANTS_TAC THENL
+   [ASM_SIMP_TAC[VALID_PATH_VECTOR_POLYNOMIAL_FUNCTION] THEN
+    ASM_MESON_TAC[NORM_ARITH
+     `norm(h - g) < d / &2 /\ norm(p - g) < min d e / &2
+      ==> norm(h - g) < d /\ norm(p - g) < d`];
+    ALL_TAC] THEN
+  REWRITE_TAC[SET_RULE `t SUBSET UNIV DELETE x <=> ~(x IN t)`] THEN
+  STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+   [ASM_MESON_TAC[NORM_SUB; REAL_ARITH `&0 < e /\ x < min d e / &2 ==> x < e`];
+    ALL_TAC] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  ASM_SIMP_TAC[OPEN_DELETE; OPEN_UNIV; HOLOMORPHIC_ON_OPEN] THEN
+  REWRITE_TAC[IN_DELETE; IN_UNIV; GSYM complex_differentiable] THEN
+  REPEAT STRIP_TAC THEN COMPLEX_DIFFERENTIABLE_TAC THEN
+  ASM_REWRITE_TAC[COMPLEX_SUB_0]);;
+
+let WINDING_NUMBER_UNIQUE = prove
+ (`!g z e n.
+        path g /\ ~(z IN path_image g) /\
+        (!e. &0 < e
+             ==> ?p. valid_path p /\ ~(z IN path_image p) /\
+                     pathstart p = pathstart g /\
+                     pathfinish p = pathfinish g /\
+                     (!t. t IN interval[vec 0,vec 1]
+                          ==> norm(g t - p t) < e) /\
+                     path_integral p (\w. Cx(&1) / (w - z)) =
+                     Cx(&2) * Cx(pi) * ii * n)
+        ==> winding_number(g,z) = n`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`(:complex) DELETE z`; `g:real^1->complex`]
+        PATH_INTEGRAL_NEARBY_ENDS) THEN
+  ASM_SIMP_TAC[OPEN_DELETE; OPEN_UNIV] THEN
+  ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
+  DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `p:real^1->complex` STRIP_ASSUME_TAC) THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`] WINDING_NUMBER) THEN
+  DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `q:real^1->complex` STRIP_ASSUME_TAC) THEN
+  FIRST_X_ASSUM(MP_TAC o SPECL [`p:real^1->complex`; `q:real^1->complex`]) THEN
+  ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN ASM_SIMP_TAC[] THEN
+  STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `\w. Cx(&1) / (w - z)`) THEN
+  ANTS_TAC THENL
+   [ASM_SIMP_TAC[OPEN_DELETE; OPEN_UNIV; HOLOMORPHIC_ON_OPEN] THEN
+    REWRITE_TAC[IN_DELETE; IN_UNIV; GSYM complex_differentiable] THEN
+    REPEAT STRIP_TAC THEN COMPLEX_DIFFERENTIABLE_TAC THEN
+    ASM_REWRITE_TAC[COMPLEX_SUB_0];
+    ASM_REWRITE_TAC[] THEN MP_TAC CX_2PII_NZ THEN
+    CONV_TAC COMPLEX_RING]);;
+
+let WINDING_NUMBER_UNIQUE_LOOP = prove
+ (`!g z e n.
+        path g /\ ~(z IN path_image g) /\ pathfinish g = pathstart g /\
+        (!e. &0 < e
+             ==> ?p. valid_path p /\ ~(z IN path_image p) /\
+                     pathfinish p = pathstart p /\
+                     (!t. t IN interval[vec 0,vec 1]
+                          ==> norm(g t - p t) < e) /\
+                     path_integral p (\w. Cx(&1) / (w - z)) =
+                     Cx(&2) * Cx(pi) * ii * n)
+        ==> winding_number(g,z) = n`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`(:complex) DELETE z`; `g:real^1->complex`]
+        PATH_INTEGRAL_NEARBY_LOOP) THEN
+  ASM_SIMP_TAC[OPEN_DELETE; OPEN_UNIV] THEN
+  ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
+  DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `p:real^1->complex` STRIP_ASSUME_TAC) THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`] WINDING_NUMBER) THEN
+  DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `q:real^1->complex` STRIP_ASSUME_TAC) THEN
+  FIRST_X_ASSUM(MP_TAC o SPECL [`p:real^1->complex`; `q:real^1->complex`]) THEN
+  ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN ASM_SIMP_TAC[] THEN
+  STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `\w. Cx(&1) / (w - z)`) THEN
+  ANTS_TAC THENL
+   [ASM_SIMP_TAC[OPEN_DELETE; OPEN_UNIV; HOLOMORPHIC_ON_OPEN] THEN
+    REWRITE_TAC[IN_DELETE; IN_UNIV; GSYM complex_differentiable] THEN
+    REPEAT STRIP_TAC THEN COMPLEX_DIFFERENTIABLE_TAC THEN
+    ASM_REWRITE_TAC[COMPLEX_SUB_0];
+    ASM_REWRITE_TAC[] THEN MP_TAC CX_2PII_NZ THEN
+    CONV_TAC COMPLEX_RING]);;
+
+let WINDING_NUMBER_VALID_PATH = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g)
+         ==> winding_number(g,z) =
+             Cx(&1) / (Cx(&2) * Cx(pi) * ii) *
+             path_integral g (\w. Cx(&1) / (w - z))`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC WINDING_NUMBER_UNIQUE THEN
+  ASM_SIMP_TAC[VALID_PATH_IMP_PATH] THEN
+  X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+  EXISTS_TAC `g:real^1->complex` THEN
+  ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN
+  MP_TAC CX_2PII_NZ THEN CONV_TAC COMPLEX_FIELD);;
+
+let HAS_PATH_INTEGRAL_WINDING_NUMBER = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g)
+         ==> ((\w. Cx(&1) / (w - z)) has_path_integral
+              (Cx(&2) * Cx(pi) * ii * winding_number(g,z))) g`,
+  REPEAT STRIP_TAC THEN ASM_SIMP_TAC[WINDING_NUMBER_VALID_PATH] THEN
+  ASM_SIMP_TAC[CX_2PII_NZ; COMPLEX_FIELD
+   `~(a * b * c = Cx(&0))
+    ==> a * b * c * Cx(&1) / (a * b * c) * z = z`] THEN
+  MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+  ASM_SIMP_TAC[PATH_INTEGRABLE_INVERSEDIFF]);;
+
+let WINDING_NUMBER_TRIVIAL = prove
+ (`!a z. ~(z = a) ==> winding_number(linepath(a,a),z) = Cx(&0)`,
+  SIMP_TAC[VALID_PATH_LINEPATH; PATH_INTEGRAL_TRIVIAL; COMPLEX_MUL_RZERO;
+           WINDING_NUMBER_VALID_PATH; PATH_IMAGE_LINEPATH; SEGMENT_REFL;
+           IN_SING]);;
+
+let WINDING_NUMBER_JOIN = prove
+ (`!g1 g2 z.
+        path g1 /\ path g2 /\ pathfinish g1 = pathstart g2 /\
+        ~(z IN path_image g1) /\ ~(z IN path_image g2)
+        ==> winding_number(g1 ++ g2,z) =
+            winding_number(g1,z) + winding_number(g2,z)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC WINDING_NUMBER_UNIQUE THEN
+  ASM_SIMP_TAC[PATH_JOIN; PATH_IMAGE_JOIN; IN_UNION] THEN
+  X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+  MP_TAC(ISPECL [`g2:real^1->complex`; `z:complex`; `e:real`]
+    WINDING_NUMBER) THEN
+  MP_TAC(ISPECL [`g1:real^1->complex`; `z:complex`; `e:real`]
+    WINDING_NUMBER) THEN
+  ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
+  X_GEN_TAC `p1:real^1->complex` THEN STRIP_TAC THEN
+  X_GEN_TAC `p2:real^1->complex` THEN STRIP_TAC THEN
+  EXISTS_TAC `p1 ++ p2:real^1->complex` THEN
+  ASM_SIMP_TAC[VALID_PATH_JOIN; PATHSTART_JOIN; PATHFINISH_JOIN] THEN
+  ASM_SIMP_TAC[PATH_IMAGE_JOIN; IN_UNION] THEN  CONJ_TAC THENL
+   [REWRITE_TAC[joinpaths; IN_INTERVAL_1; DROP_VEC] THEN REPEAT STRIP_TAC THEN
+    COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_CMUL; DROP_SUB] THEN
+    ASM_REAL_ARITH_TAC;
+    W(MP_TAC o PART_MATCH (lhs o rand) PATH_INTEGRAL_JOIN o lhand o snd) THEN
+    ASM_REWRITE_TAC[COMPLEX_ADD_LDISTRIB] THEN
+    DISCH_THEN MATCH_MP_TAC THEN
+    CONJ_TAC THEN MATCH_MP_TAC PATH_INTEGRABLE_INVERSEDIFF THEN
+    ASM_REWRITE_TAC[]]);;
+
+let WINDING_NUMBER_REVERSEPATH = prove
+ (`!g z. path g /\ ~(z IN path_image g)
+         ==> winding_number(reversepath g,z) = --(winding_number(g,z))`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC WINDING_NUMBER_UNIQUE THEN
+  ASM_SIMP_TAC[PATH_REVERSEPATH; PATH_IMAGE_REVERSEPATH] THEN
+  X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`; `e:real`]
+    WINDING_NUMBER) THEN
+  ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `p:real^1->complex` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `reversepath p:real^1->complex` THEN
+  ASM_SIMP_TAC[VALID_PATH_REVERSEPATH; PATH_IMAGE_REVERSEPATH;
+               PATHSTART_REVERSEPATH; PATHFINISH_REVERSEPATH;
+               PATH_INTEGRAL_REVERSEPATH; PATH_INTEGRABLE_INVERSEDIFF] THEN
+  REWRITE_TAC[COMPLEX_MUL_RNEG; reversepath; IN_INTERVAL_1; DROP_VEC] THEN
+  REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+  REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_SUB] THEN ASM_REAL_ARITH_TAC);;
+
+let WINDING_NUMBER_SHIFTPATH = prove
+ (`!g a z. path g /\ pathfinish g = pathstart g /\ ~(z IN path_image g) /\
+           a IN interval[vec 0,vec 1]
+           ==> winding_number(shiftpath a g,z) = winding_number(g,z)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC WINDING_NUMBER_UNIQUE_LOOP THEN
+  ASM_SIMP_TAC[PATH_SHIFTPATH; PATH_IMAGE_SHIFTPATH] THEN CONJ_TAC THENL
+   [RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1; DROP_VEC]) THEN
+    ASM_SIMP_TAC[PATHSTART_SHIFTPATH; PATHFINISH_SHIFTPATH];
+    ALL_TAC] THEN
+  X_GEN_TAC `e:real` THEN DISCH_TAC THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`; `e:real`]
+    WINDING_NUMBER) THEN ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `p:real^1->complex` STRIP_ASSUME_TAC) THEN
+  EXISTS_TAC `shiftpath a p:real^1->complex` THEN
+  ASM_SIMP_TAC[VALID_PATH_SHIFTPATH; PATH_IMAGE_SHIFTPATH;
+               PATH_INTEGRAL_SHIFTPATH; PATH_INTEGRABLE_INVERSEDIFF] THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1; DROP_VEC]) THEN
+  ASM_SIMP_TAC[PATHSTART_SHIFTPATH; PATHFINISH_SHIFTPATH] THEN
+  SIMP_TAC[COMPLEX_MUL_RNEG; shiftpath; IN_INTERVAL_1; DROP_ADD; DROP_VEC] THEN
+  REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_SUB; DROP_ADD] THEN
+  ASM_REAL_ARITH_TAC);;
+
+let WINDING_NUMBER_SPLIT_LINEPATH = prove
+ (`!a b c z.
+    c IN segment[a,b] /\ ~(z IN segment[a,b])
+    ==> winding_number(linepath(a,b),z) =
+        winding_number(linepath(a,c),z) +
+        winding_number(linepath(c,b),z)`,
+  REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN `~((z:complex) IN segment[a,c]) /\ ~(z IN segment[c,b])`
+  STRIP_ASSUME_TAC THENL
+   [CONJ_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
+     `~(z IN s) ==> t SUBSET s ==> ~(z IN t)`)) THEN
+    ASM_REWRITE_TAC[SUBSET_SEGMENT; ENDS_IN_SEGMENT];
+    ASM_SIMP_TAC[WINDING_NUMBER_VALID_PATH; PATH_IMAGE_LINEPATH;
+                 VALID_PATH_LINEPATH] THEN
+    REWRITE_TAC[GSYM COMPLEX_ADD_LDISTRIB] THEN AP_TERM_TAC THEN
+    MATCH_MP_TAC PATH_INTEGRAL_SPLIT_LINEPATH THEN
+    ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_DIV THEN
+    SIMP_TAC[CONTINUOUS_ON_CONST; CONTINUOUS_ON_SUB; CONTINUOUS_ON_ID] THEN
+    ASM_MESON_TAC[COMPLEX_SUB_0]]);;
+
+let WINDING_NUMBER_EQUAL = prove
+ (`!p q z. (!t. t IN interval[vec 0,vec 1] ==> p t = q t)
+           ==> winding_number(p,z) = winding_number(q,z)`,
+  REPEAT STRIP_TAC THEN SIMP_TAC[winding_number; PATH_INTEGRAL_INTEGRAL] THEN
+  AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
+  X_GEN_TAC `W:complex` THEN REWRITE_TAC[] THEN
+  AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
+  X_GEN_TAC `e:real` THEN REWRITE_TAC[] THEN
+  ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
+  AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
+  X_GEN_TAC `g:real^1->complex` THEN
+  ASM_SIMP_TAC[pathstart; pathfinish; ENDS_IN_UNIT_INTERVAL]);;
+
+let WINDING_NUMBER_OFFSET = prove
+ (`!p z. winding_number(p,z) = winding_number((\w. p w - z),Cx(&0))`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[winding_number; PATH_INTEGRAL_INTEGRAL] THEN
+  AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
+  X_GEN_TAC `W:complex` THEN REWRITE_TAC[] THEN
+  AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
+  X_GEN_TAC `e:real` THEN REWRITE_TAC[] THEN
+  ASM_CASES_TAC `&0 < e` THEN
+  ASM_REWRITE_TAC[path_image; valid_path; pathstart; pathfinish] THEN
+  EQ_TAC THEN
+  DISCH_THEN(X_CHOOSE_THEN `g:real^1->complex` STRIP_ASSUME_TAC) THENL
+   [EXISTS_TAC `\t. (g:real^1->complex) t - z`;
+    EXISTS_TAC `\t. (g:real^1->complex) t + z`] THEN
+  ASM_REWRITE_TAC[COMPLEX_RING `(p - z) - (g - z):complex = p - g`;
+                  COMPLEX_RING `p - (g + z):complex = p - z - g`;
+                  COMPLEX_RING `(p - z) + z:complex = p`;
+                  COMPLEX_SUB_RZERO] THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[IN_IMAGE]) THEN
+  ASM_SIMP_TAC[PIECEWISE_DIFFERENTIABLE_ADD; PIECEWISE_DIFFERENTIABLE_SUB;
+               DIFFERENTIABLE_ON_IMP_PIECEWISE_DIFFERENTIABLE;
+               DIFFERENTIABLE_ON_CONST; IN_IMAGE] THEN
+  ASM_REWRITE_TAC[COMPLEX_RING `Cx(&0) = w - z <=> z = w`;
+                  COMPLEX_RING `z = w + z <=> Cx(&0) = w`] THEN
+  FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [SYM th]) THEN
+  MATCH_MP_TAC INTEGRAL_EQ THEN X_GEN_TAC `t:real^1` THEN STRIP_TAC THEN
+  REWRITE_TAC[COMPLEX_RING `(w + z) - z = w - Cx(&0)`] THEN AP_TERM_TAC THEN
+  REWRITE_TAC[vector_derivative; has_vector_derivative; HAS_DERIVATIVE_AT;
+              COMPLEX_RING `(x - z) - (w - z):complex = x - w`;
+              COMPLEX_RING `(x + z) - (w + z):complex = x - w`]);;
+
+(* ------------------------------------------------------------------------- *)
+(* A combined theorem deducing several things piecewise.                     *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_JOIN_POS_COMBINED = prove
+ (`!g1 g2 z.
+       (valid_path g1 /\
+        ~(z IN path_image g1) /\
+        &0 < Re(winding_number(g1,z))) /\
+       (valid_path g2 /\
+        ~(z IN path_image g2) /\
+        &0 < Re(winding_number(g2,z))) /\
+       pathfinish g1 = pathstart g2
+       ==> valid_path(g1 ++ g2) /\
+           ~(z IN path_image(g1 ++ g2)) /\
+           &0 < Re(winding_number(g1 ++ g2,z))`,
+  REPEAT GEN_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[VALID_PATH_JOIN] THEN
+  ASM_SIMP_TAC[PATH_IMAGE_JOIN; VALID_PATH_IMP_PATH; IN_UNION] THEN
+  ASM_SIMP_TAC[WINDING_NUMBER_JOIN; VALID_PATH_IMP_PATH; RE_ADD] THEN
+  ASM_REAL_ARITH_TAC);;
+
+(* ------------------------------------------------------------------------- *)
+(* Useful sufficient conditions for the winding number to be positive etc.   *)
+(* ------------------------------------------------------------------------- *)
+
+let RE_WINDING_NUMBER = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g)
+         ==> Re(winding_number(g,z)) =
+             Im(path_integral g (\w. Cx(&1) / (w - z))) / (&2 * pi)`,
+  SIMP_TAC[WINDING_NUMBER_VALID_PATH; complex_div; COMPLEX_MUL_LID] THEN
+  REPEAT STRIP_TAC THEN REWRITE_TAC[COMPLEX_MUL_ASSOC; GSYM CX_MUL] THEN
+  REWRITE_TAC[COMPLEX_INV_MUL; GSYM CX_INV; COMPLEX_INV_II] THEN
+  REWRITE_TAC[COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG; RE_NEG] THEN
+  REWRITE_TAC[GSYM COMPLEX_MUL_ASSOC; RE_MUL_CX; RE_MUL_II] THEN
+  MP_TAC PI_POS THEN CONV_TAC REAL_FIELD);;
+
+let WINDING_NUMBER_POS_LE = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g) /\
+         (!x. x IN interval(vec 0,vec 1)
+              ==> &0 <= Im(vector_derivative g (at x) * cnj(g x - z)))
+         ==> &0 <= Re(winding_number(g,z))`,
+  REPEAT STRIP_TAC THEN ASM_SIMP_TAC[RE_WINDING_NUMBER] THEN
+  MATCH_MP_TAC REAL_LE_DIV THEN
+  SIMP_TAC[REAL_LE_MUL; REAL_POS; PI_POS; REAL_LT_IMP_LE; IM_DEF] THEN
+  MATCH_MP_TAC(INST_TYPE [`:1`,`:M`; `:2`,`:N`]
+    HAS_INTEGRAL_COMPONENT_POS) THEN
+  MAP_EVERY EXISTS_TAC
+   [`\x:real^1. if x IN interval(vec 0,vec 1)
+                then Cx(&1) / (g x - z) * vector_derivative g (at x)
+                else Cx(&0)`;
+    `interval[vec 0:real^1,vec 1]`] THEN
+  REWRITE_TAC[ARITH; DIMINDEX_2] THEN CONJ_TAC THENL
+   [MATCH_MP_TAC HAS_INTEGRAL_SPIKE_INTERIOR THEN
+    EXISTS_TAC `\x:real^1. Cx(&1) / (g x - z) * vector_derivative g (at x)` THEN
+    ASM_SIMP_TAC[] THEN REWRITE_TAC[GSYM HAS_PATH_INTEGRAL] THEN
+    MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+    ASM_SIMP_TAC[PATH_INTEGRABLE_INVERSEDIFF];
+    ALL_TAC] THEN
+  X_GEN_TAC `x:real^1` THEN DISCH_TAC THEN COND_CASES_TAC THEN
+  ASM_REWRITE_TAC[GSYM IM_DEF; IM_CX; REAL_LE_REFL] THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `x:real^1`) THEN
+  ASM_REWRITE_TAC[complex_div; COMPLEX_MUL_LID] THEN
+  REWRITE_TAC[complex_inv; complex_inv; complex_mul; RE; IM; cnj] THEN
+  REWRITE_TAC[real_div; REAL_RING
+   `(a * x) * b + (--c * x) * d:real = x * (a * b - c * d)`] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_MUL THEN
+  SIMP_TAC[REAL_POW_2; REAL_LE_INV_EQ; REAL_LE_ADD; REAL_LE_SQUARE] THEN
+  ASM_REAL_ARITH_TAC);;
+
+let WINDING_NUMBER_POS_LT_LEMMA = prove
+ (`!g z e. valid_path g /\ ~(z IN path_image g) /\ &0 < e /\
+           (!x. x IN interval(vec 0,vec 1)
+                ==> e <= Im(vector_derivative g (at x) / (g x - z)))
+           ==> &0 < Re(winding_number(g,z))`,
+  REPEAT STRIP_TAC THEN ASM_SIMP_TAC[RE_WINDING_NUMBER] THEN
+  MATCH_MP_TAC REAL_LT_DIV THEN
+  SIMP_TAC[REAL_LT_MUL; REAL_OF_NUM_LT; ARITH; PI_POS] THEN
+  MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `Im(ii * Cx e)` THEN
+  CONJ_TAC THENL
+   [ASM_REWRITE_TAC[COMPLEX_MUL_LNEG; IM_MUL_II; IM_NEG; RE_CX]; ALL_TAC] THEN
+  REWRITE_TAC[IM_DEF] THEN
+  MATCH_MP_TAC(ISPECL [`\x:real^1. ii * Cx e`;
+        `\x:real^1. if x IN interval(vec 0,vec 1)
+                    then Cx(&1) / (g x - z) * vector_derivative g (at x)
+                    else ii * Cx e`;
+        `interval[vec 0:real^1,vec 1]`; `ii * Cx e`;
+        `path_integral g (\w. Cx(&1) / (w - z))`; `2`]
+       HAS_INTEGRAL_COMPONENT_LE) THEN
+  REWRITE_TAC[DIMINDEX_2; ARITH] THEN REPEAT CONJ_TAC THENL
+   [GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_MUL_LID] THEN
+    ONCE_REWRITE_TAC[GSYM CONTENT_UNIT_1] THEN
+    REWRITE_TAC[HAS_INTEGRAL_CONST];
+    MATCH_MP_TAC HAS_INTEGRAL_SPIKE_INTERIOR THEN
+    EXISTS_TAC `\x:real^1. Cx(&1) / (g x - z) * vector_derivative g (at x)` THEN
+    ASM_SIMP_TAC[] THEN REWRITE_TAC[GSYM HAS_PATH_INTEGRAL] THEN
+    MATCH_MP_TAC HAS_PATH_INTEGRAL_INTEGRAL THEN
+    ASM_SIMP_TAC[PATH_INTEGRABLE_INVERSEDIFF];
+    X_GEN_TAC `x:real^1` THEN DISCH_TAC THEN COND_CASES_TAC THEN
+    ASM_REWRITE_TAC[GSYM IM_DEF; IM_CX; REAL_LE_REFL] THEN
+    REWRITE_TAC[IM_MUL_II; RE_CX] THEN
+    FIRST_X_ASSUM(MP_TAC o SPEC `x:real^1`) THEN
+    ASM_REWRITE_TAC[complex_div; COMPLEX_MUL_LID; COMPLEX_MUL_SYM]]);;
+
+let WINDING_NUMBER_POS_LT = prove
+ (`!g z e. valid_path g /\ ~(z IN path_image g) /\ &0 < e /\
+           (!x. x IN interval(vec 0,vec 1)
+                ==> e <= Im(vector_derivative g (at x) * cnj(g x - z)))
+           ==> &0 < Re(winding_number(g,z))`,
+  REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN `bounded (IMAGE (\w. w - z) (path_image g))` MP_TAC THENL
+   [REWRITE_TAC[path_image; GSYM IMAGE_o] THEN
+    MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
+    MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
+    REWRITE_TAC[COMPACT_INTERVAL] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
+    SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
+    MATCH_MP_TAC PIECEWISE_DIFFERENTIABLE_ON_IMP_CONTINUOUS_ON THEN
+    ASM_REWRITE_TAC[GSYM valid_path];
+    ALL_TAC] THEN
+  REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE] THEN
+  DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
+  MATCH_MP_TAC WINDING_NUMBER_POS_LT_LEMMA THEN
+  EXISTS_TAC `e:real / B pow 2` THEN
+  ASM_SIMP_TAC[REAL_LT_DIV; REAL_POW_LT] THEN
+  X_GEN_TAC `x:real^1` THEN DISCH_TAC THEN
+  ONCE_REWRITE_TAC[COMPLEX_DIV_CNJ] THEN
+  REWRITE_TAC[real_div; complex_div; GSYM CX_INV; GSYM CX_POW] THEN
+  REWRITE_TAC[IM_MUL_CX] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN
+  ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LE_INV_EQ; REAL_POW_LE] THEN
+  MATCH_MP_TAC REAL_LE_INV2 THEN CONJ_TAC THENL
+   [MATCH_MP_TAC REAL_POW_LT THEN REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
+    UNDISCH_TAC `~((z:complex) IN path_image g)`;
+    MATCH_MP_TAC REAL_POW_LE2 THEN REWRITE_TAC[NORM_POS_LE] THEN
+    FIRST_X_ASSUM MATCH_MP_TAC] THEN
+  REWRITE_TAC[path_image; IN_IMAGE] THEN
+  ASM_MESON_TAC[SUBSET; INTERVAL_OPEN_SUBSET_CLOSED]);;
+
+(* ------------------------------------------------------------------------- *)
+(* The winding number is an integer (proof from Ahlfors's book).             *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_AHLFORS_LEMMA = prove
+ (`!g a b.
+        g piecewise_differentiable_on interval [a,b] /\
+        drop a <= drop b /\ (!x. x IN interval [a,b] ==> ~(g x = z))
+        ==> (\x. vector_derivative g (at x within interval[a,b]) / (g(x) - z))
+            integrable_on interval[a,b] /\
+            cexp(--(integral (interval[a,b])
+                        (\x. vector_derivative g (at x within interval[a,b]) /
+                               (g(x) - z)))) *
+            (g(b) - z) = g(a) - z`,
+  let lemma = prove
+   (`!f g g' s x z.
+          (g has_vector_derivative g') (at x within s) /\
+          (f has_vector_derivative (g' / (g x - z))) (at x within s) /\
+          ~(g x = z)
+          ==> ((\x. cexp(--f x) * (g x - z)) has_vector_derivative Cx(&0))
+              (at x within s)`,
+    REPEAT STRIP_TAC THEN
+    SUBGOAL_THEN
+     `cexp(--f x) * (g' - Cx(&0)) +
+      (cexp(--f x) * --(g' / ((g:real^1->complex) x - z))) * (g x - z) = Cx(&0)`
+     (SUBST1_TAC o SYM)
+    THENL
+     [FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN
+      CONV_TAC COMPLEX_FIELD;
+      ALL_TAC] THEN
+    MATCH_MP_TAC(ISPEC `( * ):complex->complex->complex`
+      HAS_VECTOR_DERIVATIVE_BILINEAR_WITHIN) THEN
+    REWRITE_TAC[BILINEAR_COMPLEX_MUL; GSYM COMPLEX_VEC_0] THEN
+    ASM_SIMP_TAC[HAS_VECTOR_DERIVATIVE_SUB; ETA_AX;
+                 HAS_VECTOR_DERIVATIVE_CONST] THEN
+    GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM o_DEF] THEN
+    REWRITE_TAC[has_vector_derivative] THEN
+    SUBGOAL_THEN `!x y. (\z. drop z % (x * y :complex)) =
+                        (\w. x * w) o (\z. drop z % y)`
+     (fun th -> REWRITE_TAC[th])
+    THENL
+     [REWRITE_TAC[FUN_EQ_THM; o_THM; COMPLEX_CMUL] THEN
+      SIMPLE_COMPLEX_ARITH_TAC;
+      ALL_TAC] THEN
+    MATCH_MP_TAC DIFF_CHAIN_WITHIN THEN
+    REWRITE_TAC[GSYM has_complex_derivative; GSYM has_vector_derivative] THEN
+    SIMP_TAC[HAS_COMPLEX_DERIVATIVE_CEXP; HAS_COMPLEX_DERIVATIVE_AT_WITHIN] THEN
+    ASM_SIMP_TAC[HAS_VECTOR_DERIVATIVE_NEG]) in
+  REPEAT GEN_TAC THEN STRIP_TAC THEN
+  SUBGOAL_THEN
+   `!w. ~(w = z)
+        ==> ?h. !y. norm(y - w) < norm(w - z)
+                    ==> (h has_complex_derivative inv(y - z)) (at y)`
+   (LABEL_TAC "P")
+  THENL
+   [REPEAT STRIP_TAC THEN
+    MP_TAC(ISPECL [`\w:complex. inv(w - z)`;
+               `ball(w:complex,norm(w - z))`;
+               `{}:complex->bool`]
+              HOLOMORPHIC_CONVEX_PRIMITIVE) THEN
+    SIMP_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL; INTERIOR_OPEN] THEN
+    REWRITE_TAC[CONVEX_BALL; FINITE_RULES; DIFF_EMPTY] THEN ANTS_TAC THENL
+     [SUBGOAL_THEN `(\w. inv(w - z)) holomorphic_on ball(w:complex,norm(w - z))`
+       (fun th ->
+        MESON_TAC[HOLOMORPHIC_ON_OPEN; HOLOMORPHIC_ON_IMP_CONTINUOUS_ON;
+                  OPEN_BALL; complex_differentiable; th]) THEN
+      SIMP_TAC[HOLOMORPHIC_ON_OPEN; OPEN_BALL; IN_BALL] THEN
+      X_GEN_TAC `u:complex` THEN DISCH_TAC THEN
+      EXISTS_TAC `--Cx(&1) / (u - z) pow 2` THEN COMPLEX_DIFF_TAC THEN
+      REWRITE_TAC[COMPLEX_SUB_RZERO; COMPLEX_SUB_0] THEN
+      ASM_MESON_TAC[REAL_LT_REFL; dist];
+      ALL_TAC] THEN
+    REWRITE_TAC[IN_BALL; dist] THEN MESON_TAC[NORM_SUB];
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+   `!t. t IN interval[a,b]
+        ==> (\x. vector_derivative g (at x within interval[a,b]) / (g(x) - z))
+            integrable_on interval[a,t] /\
+            cexp(--(integral (interval[a,t])
+                         (\x. vector_derivative g (at x within interval[a,b]) /
+                              (g(x) - z)))) *
+            (g(t) - z) = g(a) - z`
+   (fun th -> MATCH_MP_TAC th THEN
+              ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL]) THEN
+  REWRITE_TAC[TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN
+  REWRITE_TAC[FORALL_AND_THM] THEN
+  MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
+   [REPEAT STRIP_TAC THEN MATCH_MP_TAC INTEGRABLE_SUBINTERVAL THEN
+    MAP_EVERY EXISTS_TAC [`a:real^1`; `b:real^1`] THEN
+    ASM_REWRITE_TAC[SUBSET_INTERVAL_1; REAL_LE_REFL] THEN
+    CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[IN_INTERVAL_1]] THEN
+    REWRITE_TAC[integrable_on; complex_div] THEN
+    ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN
+    REWRITE_TAC[HAS_INTEGRAL_LOCALIZED_VECTOR_DERIVATIVE] THEN
+    REWRITE_TAC[GSYM integrable_on] THEN
+    MATCH_MP_TAC PATH_INTEGRAL_LOCAL_PRIMITIVE_ANY THEN
+    EXISTS_TAC `(:complex) DELETE z` THEN
+    ASM_SIMP_TAC[IN_DELETE; IN_UNIV;
+                 DIFFERENTIABLE_ON_IMP_PIECEWISE_DIFFERENTIABLE] THEN
+    X_GEN_TAC `w:complex` THEN DISCH_TAC THEN
+    EXISTS_TAC `norm(w - z:complex)` THEN
+    ASM_REWRITE_TAC[COMPLEX_NORM_NZ; COMPLEX_SUB_0] THEN
+    ASM_MESON_TAC[HAS_COMPLEX_DERIVATIVE_AT_WITHIN];
+    ALL_TAC] THEN
+  DISCH_TAC THEN MATCH_MP_TAC HAS_DERIVATIVE_ZERO_UNIQUE_STRONG_INTERVAL THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [piecewise_differentiable_on]) THEN
+  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[IN_DIFF; FINITE_IMP_COUNTABLE] THEN
+  X_GEN_TAC `k:real^1->bool` THEN STRIP_TAC THEN
+  ASM_SIMP_TAC[CONVEX_INTERVAL; INTEGRAL_REFL] THEN
+  REWRITE_TAC[COMPLEX_VEC_0; COMPLEX_NEG_0; CEXP_0; COMPLEX_MUL_LID] THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_MUL THEN
+    ASM_SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; ETA_AX;
+                 PIECEWISE_DIFFERENTIABLE_ON_IMP_CONTINUOUS_ON] THEN
+    GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
+    REWRITE_TAC[CONTINUOUS_ON_CEXP] THEN
+    MATCH_MP_TAC CONTINUOUS_ON_NEG THEN
+    MATCH_MP_TAC INDEFINITE_INTEGRAL_CONTINUOUS_RIGHT THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL];
+    ALL_TAC] THEN
+  X_GEN_TAC `t:real^1` THEN DISCH_TAC THEN
+  MP_TAC(ISPECL [`\w:complex. inv(w - z)`;
+                 `ball((g:real^1->complex) t,dist(g t,z))`;
+                 `{}:complex->bool`]
+                HOLOMORPHIC_CONVEX_PRIMITIVE) THEN
+  SIMP_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL; INTERIOR_OPEN] THEN
+  REWRITE_TAC[CONVEX_BALL; FINITE_RULES; DIFF_EMPTY] THEN ANTS_TAC THENL
+   [SUBGOAL_THEN `(\w. inv(w - z)) holomorphic_on ball(g(t:real^1),dist(g t,z))`
+     (fun th ->
+      MESON_TAC[HOLOMORPHIC_ON_OPEN; HOLOMORPHIC_ON_IMP_CONTINUOUS_ON;
+                OPEN_BALL; complex_differentiable; th]) THEN
+    SIMP_TAC[HOLOMORPHIC_ON_OPEN; OPEN_BALL; IN_BALL] THEN
+    X_GEN_TAC `w:complex` THEN DISCH_TAC THEN
+    EXISTS_TAC `--Cx(&1) / (w - z) pow 2` THEN COMPLEX_DIFF_TAC THEN
+    REWRITE_TAC[COMPLEX_SUB_RZERO; COMPLEX_SUB_0] THEN
+    ASM_MESON_TAC[REAL_LT_REFL];
+    ALL_TAC] THEN
+  REWRITE_TAC[IN_BALL; dist] THEN
+  DISCH_THEN(X_CHOOSE_TAC `h:complex->complex`) THEN
+  SUBGOAL_THEN `(\h. Cx(&0)) = (\h. drop h % Cx(&0))` SUBST1_TAC THENL
+   [REWRITE_TAC[FUN_EQ_THM; GSYM COMPLEX_VEC_0; VECTOR_MUL_RZERO];
+    ALL_TAC] THEN
+  REWRITE_TAC[GSYM has_vector_derivative] THEN MATCH_MP_TAC lemma THEN
+  EXISTS_TAC `vector_derivative g (at t within interval[a,b]):complex` THEN
+  REPEAT CONJ_TAC THENL
+   [REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN
+    ASM_MESON_TAC[DIFFERENTIABLE_AT_WITHIN];
+    ALL_TAC;
+    ASM_MESON_TAC[]] THEN
+  REWRITE_TAC[has_vector_derivative] THEN
+  MATCH_MP_TAC HAS_DERIVATIVE_TRANSFORM_WITHIN THEN
+  ASM_REWRITE_TAC[GSYM has_vector_derivative] THEN
+  EXISTS_TAC `\u. integral (interval [a,t])
+                  (\x. vector_derivative g (at x within interval [a,b]) /
+                       ((g:real^1->complex) x - z)) + (h(g(u)) - h(g(t)))` THEN
+  REWRITE_TAC[LEFT_EXISTS_AND_THM; CONJ_ASSOC] THEN
+  REWRITE_TAC[GSYM CONJ_ASSOC] THEN CONJ_TAC THENL
+   [ALL_TAC;
+    ONCE_REWRITE_TAC[COMPLEX_RING `a + (b - c) = b + (a - c):complex`] THEN
+    GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_RID] THEN
+    MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_ADD THEN
+    REWRITE_TAC[HAS_VECTOR_DERIVATIVE_CONST] THEN
+    REWRITE_TAC[has_vector_derivative] THEN
+    SUBGOAL_THEN `!x y. (\h. drop h % x / y) =
+                        (\x. inv(y) * x) o (\h. drop h % x)`
+     (fun th -> REWRITE_TAC[th])
+    THENL
+     [REWRITE_TAC[FUN_EQ_THM; o_THM; COMPLEX_CMUL] THEN
+      SIMPLE_COMPLEX_ARITH_TAC;
+      ALL_TAC] THEN
+    GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM o_DEF] THEN
+    MATCH_MP_TAC DIFF_CHAIN_WITHIN THEN
+    REWRITE_TAC[GSYM has_complex_derivative; GSYM has_vector_derivative] THEN
+    REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN
+    CONJ_TAC THENL [ASM_MESON_TAC[DIFFERENTIABLE_AT_WITHIN]; ALL_TAC] THEN
+    MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN
+    FIRST_X_ASSUM MATCH_MP_TAC THEN
+    REWRITE_TAC[COMPLEX_SUB_REFL; COMPLEX_NORM_0; COMPLEX_NORM_NZ] THEN
+    ASM_SIMP_TAC[COMPLEX_SUB_0]] THEN
+  SUBGOAL_THEN
+   `?d. &0 < d /\
+        !y:real^1. y IN interval[a,b] /\ dist(y,t) < d
+                   ==> dist(g y:complex,g t) < norm(g t - z) /\ ~(y IN k)`
+  MP_TAC THENL
+   [SUBGOAL_THEN `(g:real^1->complex) continuous (at t within interval[a,b])`
+    MP_TAC THENL
+     [ASM_MESON_TAC[PIECEWISE_DIFFERENTIABLE_ON_IMP_CONTINUOUS_ON;
+                    CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN];
+      ALL_TAC] THEN
+    REWRITE_TAC[continuous_within] THEN
+    DISCH_THEN(MP_TAC o SPEC `norm((g:real^1->complex) t - z)`) THEN
+    ASM_SIMP_TAC[COMPLEX_NORM_NZ; COMPLEX_SUB_0] THEN
+    DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
+    FIRST_X_ASSUM(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC o
+      SPEC `t:real^1` o MATCH_MP FINITE_SET_AVOID) THEN
+    EXISTS_TAC `min d1 d2` THEN ASM_SIMP_TAC[REAL_LT_MIN] THEN
+    ASM_MESON_TAC[DIST_SYM; REAL_NOT_LE];
+    ALL_TAC] THEN
+  REWRITE_TAC[TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN
+  REWRITE_TAC[FORALL_AND_THM] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN STRIP_TAC THEN
+  ASM_REWRITE_TAC[] THEN X_GEN_TAC `u:real^1` THEN REWRITE_TAC[dist] THEN
+  STRIP_TAC THEN
+  DISJ_CASES_TAC(REAL_ARITH `drop t <= drop u \/ drop u <= drop t`) THENL
+   [SUBGOAL_THEN
+     `integral (interval [a,u])
+        (\x. vector_derivative g (at x within interval [a,b]) / (g x - z)) =
+      integral (interval [a,t])
+        (\x. vector_derivative g (at x within interval [a,b]) / (g x - z)) +
+      integral (interval [t,u])
+        (\x. vector_derivative g (at x within interval [a,b]) / (g x - z))`
+    SUBST1_TAC THENL
+     [CONV_TAC SYM_CONV THEN MATCH_MP_TAC INTEGRAL_COMBINE THEN
+      ASM_MESON_TAC[IN_INTERVAL_1];
+      ALL_TAC] THEN
+    SIMP_TAC[COMPLEX_RING `a + x = a + y <=> y:complex = x`];
+    SUBGOAL_THEN
+     `integral (interval [a,t])
+        (\x. vector_derivative g (at x within interval [a,b]) / (g x - z)) =
+      integral (interval [a,u])
+        (\x. vector_derivative g (at x within interval [a,b]) / (g x - z)) +
+      integral (interval [u,t])
+        (\x. vector_derivative g (at x within interval [a,b]) / (g x - z))`
+    SUBST1_TAC THENL
+     [CONV_TAC SYM_CONV THEN MATCH_MP_TAC INTEGRAL_COMBINE THEN
+      ASM_MESON_TAC[IN_INTERVAL_1];
+      ALL_TAC] THEN
+    SIMP_TAC[COMPLEX_RING `(a + x) + (w - z) = a <=> x:complex = z - w`]] THEN
+  (MATCH_MP_TAC INTEGRAL_UNIQUE THEN
+   MATCH_MP_TAC FUNDAMENTAL_THEOREM_OF_CALCULUS THEN
+   ASM_REWRITE_TAC[GSYM o_DEF] THEN X_GEN_TAC `x:real^1` THEN
+   REPEAT STRIP_TAC THEN REWRITE_TAC[has_vector_derivative; COMPLEX_CMUL] THEN
+   SUBGOAL_THEN `!x y. (\h. Cx(drop h) * x / y) =
+                       (\x. inv(y) * x) o (\h. drop h % x)`
+    (fun th -> REWRITE_TAC[th])
+   THENL
+    [REWRITE_TAC[FUN_EQ_THM; o_THM; COMPLEX_CMUL] THEN
+     SIMPLE_COMPLEX_ARITH_TAC;
+     ALL_TAC] THEN
+   MATCH_MP_TAC DIFF_CHAIN_WITHIN THEN
+   REWRITE_TAC[GSYM has_complex_derivative; GSYM has_vector_derivative] THEN
+   CONJ_TAC THENL
+    [MATCH_MP_TAC HAS_VECTOR_DERIVATIVE_WITHIN_SUBSET THEN
+     EXISTS_TAC `interval[a:real^1,b]` THEN
+     REWRITE_TAC[GSYM VECTOR_DERIVATIVE_WORKS] THEN CONJ_TAC THENL
+      [MATCH_MP_TAC DIFFERENTIABLE_AT_WITHIN THEN
+       FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
+        [ALL_TAC; FIRST_X_ASSUM MATCH_MP_TAC];
+       ALL_TAC] THEN
+     REPEAT(FIRST_X_ASSUM(MP_TAC o
+        check (fun t -> not(is_forall (concl t))))) THEN
+     REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB] THEN
+     REWRITE_TAC[SUBSET_INTERVAL_1; IN_INTERVAL_1; REAL_LE_REFL] THEN
+     REAL_ARITH_TAC;
+     ALL_TAC] THEN
+   MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN
+   FIRST_X_ASSUM MATCH_MP_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM dist] THEN
+   ONCE_REWRITE_TAC[DIST_SYM] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+   CONJ_TAC THENL [ASM_MESON_TAC[IN_INTERVAL_1; REAL_LE_TRANS]; ALL_TAC] THEN
+   REPEAT(FIRST_X_ASSUM(MP_TAC o
+      check (fun t -> not(is_forall (concl t))))) THEN
+   REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB] THEN
+   REWRITE_TAC[SUBSET_INTERVAL_1; IN_INTERVAL_1; REAL_LE_REFL] THEN
+   REAL_ARITH_TAC));;
+
+let WINDING_NUMBER_AHLFORS = prove
+ (`!g z a b.
+        g piecewise_differentiable_on interval [a,b] /\
+        drop a <= drop b /\ (!x. x IN interval [a,b] ==> ~(g x = z))
+        ==> (\x. vector_derivative g (at x) / (g(x) - z))
+            integrable_on interval[a,b] /\
+            cexp(--(integral (interval[a,b])
+                             (\x. vector_derivative g (at x) / (g(x) - z)))) *
+            (g(b) - z) = g(a) - z`,
+  REPEAT GEN_TAC THEN STRIP_TAC THEN
+  REWRITE_TAC[integrable_on; integral] THEN
+  REWRITE_TAC[ONCE_REWRITE_RULE[COMPLEX_MUL_SYM] complex_div] THEN
+  REWRITE_TAC[GSYM HAS_INTEGRAL_LOCALIZED_VECTOR_DERIVATIVE] THEN
+  ONCE_REWRITE_TAC[ONCE_REWRITE_RULE[COMPLEX_MUL_SYM](GSYM complex_div)] THEN
+  REWRITE_TAC[GSYM integral; GSYM integrable_on] THEN
+  MATCH_MP_TAC WINDING_NUMBER_AHLFORS_LEMMA THEN ASM_REWRITE_TAC[]);;
+
+let WINDING_NUMBER_AHLFORS_FULL = prove
+ (`!p z. path p /\ ~(z IN path_image p)
+         ==> pathfinish p - z =
+             cexp(Cx(&2) * Cx pi * ii * winding_number(p,z)) *
+             (pathstart p - z)`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`p:real^1->complex`; `z:complex`; `&1`] WINDING_NUMBER) THEN
+  ASM_REWRITE_TAC[REAL_LT_01; LEFT_IMP_EXISTS_THM] THEN
+  X_GEN_TAC `g:real^1->complex` THEN STRIP_TAC THEN
+  REPEAT(FIRST_X_ASSUM(SUBST_ALL_TAC o SYM)) THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[valid_path; path_image; IN_IMAGE;
+        NOT_EXISTS_THM]) THEN
+  MP_TAC(ISPECL
+   [`g:real^1->complex`; `z:complex`; `vec 0:real^1`; `vec 1:real^1`]
+   WINDING_NUMBER_AHLFORS) THEN
+  ASM_SIMP_TAC[DROP_VEC; REAL_POS; pathstart; pathfinish] THEN ANTS_TAC THENL
+   [ASM_MESON_TAC[]; DISCH_THEN(SUBST1_TAC o SYM o CONJUNCT2)] THEN
+  REWRITE_TAC[GSYM CEXP_ADD; COMPLEX_MUL_ASSOC; PATH_INTEGRAL_INTEGRAL] THEN
+  REWRITE_TAC[SIMPLE_COMPLEX_ARITH `Cx(&1) / z * w = w / z`] THEN
+  REWRITE_TAC[GSYM complex_sub; COMPLEX_SUB_REFL; CEXP_0; COMPLEX_MUL_LID]);;
+
+(* ------------------------------------------------------------------------- *)
+(* State in terms of complex integers. Note the useful equality version.     *)
+(* ------------------------------------------------------------------------- *)
+
+let complex_integer = new_definition
+ `complex_integer z <=> integer(Re z) /\ Im z = &0`;;
+
+let COMPLEX_INTEGER = prove
+ (`complex_integer z <=> ?n. integer n /\ z = Cx n`,
+  REWRITE_TAC[COMPLEX_EQ; RE_CX; IM_CX; complex_integer] THEN MESON_TAC[]);;
+
+let INTEGER_WINDING_NUMBER_EQ = prove
+ (`!g z. path g /\ ~(z IN path_image g)
+         ==> (complex_integer(winding_number(g,z)) <=>
+              pathfinish g = pathstart g)`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPEC `(:complex) DIFF path_image g` OPEN_CONTAINS_BALL) THEN
+  ASM_SIMP_TAC[GSYM closed; CLOSED_PATH_IMAGE; VALID_PATH_IMP_PATH] THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN
+  ASM_REWRITE_TAC[IN_DIFF; IN_UNIV; SUBSET; IN_BALL] THEN
+  DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`; `e:real`]
+    WINDING_NUMBER) THEN
+  ASM_REWRITE_TAC[] THEN
+  DISCH_THEN(X_CHOOSE_THEN `p:real^1->complex` STRIP_ASSUME_TAC) THEN
+  SUBGOAL_THEN
+   `complex_integer(winding_number(p,z)) <=>
+    pathfinish p = pathstart p`
+  MP_TAC THENL
+   [UNDISCH_THEN
+     `path_integral p (\w. Cx (&1) / (w - z)) =
+      Cx (&2) * Cx pi * ii * winding_number (g,z)` (K ALL_TAC) THEN
+    ASM_SIMP_TAC[WINDING_NUMBER_VALID_PATH];
+    ASM_SIMP_TAC[WINDING_NUMBER_VALID_PATH; CX_2PII_NZ; COMPLEX_FIELD
+     `~(a * b * c = Cx(&0))
+      ==> Cx(&1) / (a * b * c) * a * b * c * z = z`]] THEN
+  UNDISCH_THEN `pathstart p:complex = pathstart g` (SUBST_ALL_TAC o SYM) THEN
+  UNDISCH_THEN `pathfinish p:complex = pathfinish g` (SUBST_ALL_TAC o SYM) THEN
+  RULE_ASSUM_TAC(REWRITE_RULE[valid_path; path_image]) THEN
+  REWRITE_TAC[pathfinish; pathstart] THEN
+  MATCH_MP_TAC EQ_TRANS THEN
+  EXISTS_TAC `cexp(path_integral p (\w. Cx(&1) / (w - z))) = Cx(&1)` THEN
+  CONJ_TAC THENL
+   [REWRITE_TAC[CEXP_EQ_1; complex_integer] THEN
+    REWRITE_TAC[complex_div; COMPLEX_MUL_LID; COMPLEX_INV_MUL] THEN
+    SIMP_TAC[GSYM CX_INV; GSYM CX_MUL; COMPLEX_MUL_ASSOC; COMPLEX_INV_II] THEN
+    REWRITE_TAC[RE_MUL_CX; IM_MUL_CX; GSYM COMPLEX_MUL_ASSOC] THEN
+    REWRITE_TAC[COMPLEX_MUL_LNEG; RE_MUL_II; IM_MUL_II; RE_NEG; IM_NEG] THEN
+    REWRITE_TAC[REAL_NEGNEG; REAL_ENTIRE; REAL_INV_EQ_0; REAL_NEG_EQ_0] THEN
+    SIMP_TAC[REAL_OF_NUM_EQ; ARITH; REAL_LT_IMP_NZ; PI_POS] THEN
+    SIMP_TAC[PI_POS; REAL_FIELD
+     `&0 < p ==> (x = &2 * n * p <=> (inv(&2) * inv(p)) * x = n)`] THEN
+    MESON_TAC[];
+    MP_TAC(ISPECL [`p:real^1->complex`; `z:complex`;
+                   `vec 0:real^1`; `vec 1:real^1`]
+                  WINDING_NUMBER_AHLFORS) THEN
+    ASM_REWRITE_TAC[DROP_VEC; REAL_POS] THEN
+    ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
+    DISCH_THEN(MP_TAC o CONJUNCT2) THEN
+    REWRITE_TAC[ONCE_REWRITE_RULE[COMPLEX_MUL_SYM] complex_div] THEN
+    REWRITE_TAC[integral; GSYM HAS_INTEGRAL_LOCALIZED_VECTOR_DERIVATIVE] THEN
+    REWRITE_TAC[GSYM has_path_integral; GSYM path_integral] THEN
+    REWRITE_TAC[CEXP_NEG; COMPLEX_MUL_RID] THEN
+    MATCH_MP_TAC(COMPLEX_FIELD
+     `~(i = Cx(&0)) /\ ~(g0 = z)
+      ==> (inv i * (g1 - z) = g0 - z ==> (i = Cx(&1) <=> g1 = g0))`) THEN
+    REWRITE_TAC[CEXP_NZ] THEN
+    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [IN_IMAGE]) THEN
+    REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN MESON_TAC[REAL_POS; DROP_VEC]]);;
+
+let INTEGER_WINDING_NUMBER = prove
+ (`!g z. path g /\ pathfinish g = pathstart g /\ ~(z IN path_image g)
+         ==> complex_integer(winding_number(g,z))`,
+  MESON_TAC[INTEGER_WINDING_NUMBER_EQ]);;
+
+(* ------------------------------------------------------------------------- *)
+(* For |WN| >= 1 the path must contain points in every direction.            *)
+(* We can thus bound the WN of a path that doesn't meet some "cut".          *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_POS_MEETS = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g) /\
+         Re(winding_number(g,z)) >= &1
+         ==> !w. ~(w = z)
+                 ==> ?a. &0 < a /\ z + (Cx a * (w - z)) IN path_image g`,
+  REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN
+   `!t. t IN interval[vec 0,vec 1] ==> ~((g:real^1->complex) t = z)`
+  ASSUME_TAC THENL
+   [UNDISCH_TAC `~((z:complex) IN path_image g)` THEN
+    REWRITE_TAC[path_image; IN_IMAGE] THEN MESON_TAC[];
+    ALL_TAC] THEN
+  ABBREV_TAC `r:complex = (w - z) / (pathstart g - z)` THEN
+  STRIP_ASSUME_TAC(GSYM(SPEC `r:complex` ARG)) THEN
+  SUBGOAL_THEN
+   `?t. t IN interval[vec 0,vec 1] /\
+        Im(integral (interval[vec 0,t])
+                    (\x. vector_derivative g (at x) / (g x - z))) = Arg r`
+  STRIP_ASSUME_TAC THENL
+   [REWRITE_TAC[IM_DEF] THEN MATCH_MP_TAC IVT_INCREASING_COMPONENT_ON_1 THEN
+    ASM_SIMP_TAC[DIMINDEX_2; DROP_VEC; ARITH; INTEGRAL_REFL; REAL_POS;
+                 VEC_COMPONENT] THEN
+    CONJ_TAC THENL
+     [MATCH_MP_TAC INDEFINITE_INTEGRAL_CONTINUOUS_RIGHT THEN
+      REWRITE_TAC[ONCE_REWRITE_RULE[COMPLEX_MUL_SYM] complex_div] THEN
+      REWRITE_TAC[GSYM PATH_INTEGRABLE_ON] THEN
+      REWRITE_TAC[SIMPLE_COMPLEX_ARITH `inv z = Cx(&1) / z`] THEN
+      MATCH_MP_TAC PATH_INTEGRABLE_INVERSEDIFF THEN ASM_REWRITE_TAC[];
+      ALL_TAC] THEN
+    MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&2 * pi` THEN
+    ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN
+    UNDISCH_TAC `Re(winding_number (g,z)) >= &1` THEN
+    ASM_SIMP_TAC[WINDING_NUMBER_VALID_PATH; GSYM IM_DEF] THEN
+    REWRITE_TAC[path_integral; HAS_PATH_INTEGRAL; GSYM integral] THEN
+    SUBST1_TAC(COMPLEX_FIELD `ii = --inv ii`) THEN
+    REWRITE_TAC[complex_div; COMPLEX_INV_MUL; COMPLEX_INV_NEG] THEN
+    REWRITE_TAC[GSYM CX_INV; GSYM CX_MUL; COMPLEX_MUL_ASSOC] THEN
+    REWRITE_TAC[RE_MUL_CX; RE; COMPLEX_MUL_RNEG; RE_NEG; COMPLEX_MUL_LNEG;
+                COMPLEX_INV_INV; GSYM COMPLEX_MUL_ASSOC; RE_MUL_II] THEN
+    REWRITE_TAC[REAL_MUL_RNEG; REAL_NEGNEG] THEN
+    SIMP_TAC[REAL_ARITH `((&1 * inv(&2)) * p) * x >= &1 <=> &2 <= x * p`] THEN
+    SIMP_TAC[GSYM real_div; REAL_LE_RDIV_EQ; PI_POS] THEN
+    REWRITE_TAC[COMPLEX_MUL_LID; COMPLEX_MUL_AC];
+    ALL_TAC] THEN
+  MP_TAC(ISPECL
+   [`g:real^1->complex`; `z:complex`; `vec 0:real^1`; `t:real^1`]
+   WINDING_NUMBER_AHLFORS) THEN
+  ANTS_TAC THENL
+   [REPEAT CONJ_TAC THENL
+     [MATCH_MP_TAC PIECEWISE_DIFFERENTIABLE_ON_SUBSET THEN
+      EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN
+      RULE_ASSUM_TAC(REWRITE_RULE[valid_path]) THEN ASM_REWRITE_TAC[];
+      ALL_TAC;
+      GEN_TAC THEN
+      DISCH_THEN(fun th -> FIRST_ASSUM MATCH_MP_TAC THEN MP_TAC th)] THEN
+    UNDISCH_TAC `(t:real^1) IN interval[vec 0,vec 1]` THEN
+    REWRITE_TAC[SUBSET; IN_INTERVAL_1; DROP_VEC] THEN REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  DISCH_THEN(MP_TAC o CONJUNCT2) THEN REWRITE_TAC[CEXP_NEG] THEN
+  ABBREV_TAC `i = integral (interval [vec 0,t])
+    (\x. vector_derivative g (at x) / (g x - z))` THEN
+  SUBST1_TAC(SPEC `i:complex` COMPLEX_EXPAND) THEN
+  ASM_REWRITE_TAC[CEXP_ADD; COMPLEX_INV_MUL; GSYM CX_EXP] THEN
+  UNDISCH_TAC `Cx(norm r) * cexp(ii * Cx(Arg r)) = r` THEN
+  REWRITE_TAC[IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP (COMPLEX_FIELD
+   `x * e = r /\ (y * inv e) * w = z
+    ==> ~(e = Cx(&0)) ==> x * y * w = r * z`)) THEN
+  REWRITE_TAC[CEXP_NZ] THEN
+  EXPAND_TAC "r" THEN
+  GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o ONCE_DEPTH_CONV) [pathstart] THEN
+  SUBGOAL_THEN `~((g:real^1->complex)(vec 0) = z)` ASSUME_TAC THENL
+   [FIRST_ASSUM MATCH_MP_TAC THEN SIMP_TAC[IN_INTERVAL_1; DROP_VEC; REAL_POS];
+    ALL_TAC] THEN
+  ASM_SIMP_TAC[COMPLEX_DIV_RMUL; COMPLEX_SUB_0; GSYM CX_INV; GSYM CX_MUL;
+               COMPLEX_MUL_ASSOC; GSYM real_div] THEN
+  DISCH_TAC THEN
+  EXISTS_TAC `exp(Re i) / norm(r:complex)` THEN
+  SUBGOAL_THEN `~(r = Cx(&0))` ASSUME_TAC THENL
+   [EXPAND_TAC "r" THEN MATCH_MP_TAC(COMPLEX_FIELD
+   `~(x = Cx(&0)) /\ ~(y = Cx(&0)) ==> ~(x / y = Cx(&0))`) THEN
+    ASM_REWRITE_TAC[COMPLEX_SUB_0; pathstart];
+    ALL_TAC] THEN
+  ASM_SIMP_TAC[REAL_LT_DIV; REAL_EXP_POS_LT; COMPLEX_NORM_NZ] THEN
+  REWRITE_TAC[path_image; IN_IMAGE] THEN
+  EXISTS_TAC `t:real^1` THEN ASM_REWRITE_TAC[] THEN
+  MATCH_MP_TAC(COMPLEX_FIELD
+   `inv i * (gt - z) = wz /\ ~(i = Cx(&0)) ==> z + i * wz = gt`) THEN
+  ASM_REWRITE_TAC[GSYM CX_INV; REAL_INV_DIV; CX_INJ] THEN
+  MATCH_MP_TAC(REAL_FIELD `~(x = &0) /\ ~(y = &0) ==> ~(x / y = &0)`) THEN
+  ASM_REWRITE_TAC[REAL_EXP_NZ; COMPLEX_NORM_ZERO]);;
+
+let WINDING_NUMBER_BIG_MEETS = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g) /\
+         abs(Re(winding_number(g,z))) >= &1
+         ==> !w. ~(w = z)
+                 ==> ?a. &0 < a /\ z + (Cx a * (w - z)) IN path_image g`,
+  REPEAT GEN_TAC THEN REWRITE_TAC[real_abs] THEN COND_CASES_TAC THEN
+  ASM_SIMP_TAC[WINDING_NUMBER_POS_MEETS] THEN
+  REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
+  ASM_SIMP_TAC[GSYM RE_NEG; VALID_PATH_IMP_PATH;
+               GSYM WINDING_NUMBER_REVERSEPATH] THEN
+  DISCH_TAC THEN ONCE_REWRITE_TAC[GSYM PATH_IMAGE_REVERSEPATH] THEN
+  MATCH_MP_TAC WINDING_NUMBER_POS_MEETS THEN
+  ASM_SIMP_TAC[PATH_IMAGE_REVERSEPATH; VALID_PATH_REVERSEPATH]);;
+
+let WINDING_NUMBER_LT_1 = prove
+ (`!g w z. valid_path g /\ ~(z IN path_image g) /\ ~(w = z) /\
+           (!a. &0 < a ==> ~(z + (Cx a * (w - z)) IN path_image g))
+           ==> Re(winding_number(g,z)) < &1`,
+  REPEAT STRIP_TAC THEN
+  REWRITE_TAC[GSYM REAL_NOT_LE; GSYM real_ge] THEN
+  ASM_MESON_TAC[WINDING_NUMBER_POS_MEETS]);;
+
+(* ------------------------------------------------------------------------- *)
+(* One way of proving that WN=1 for a loop.                                  *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_EQ_1 = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g) /\ pathfinish g = pathstart g /\
+         &0 < Re(winding_number(g,z)) /\ Re(winding_number(g,z)) < &2
+         ==> winding_number(g,z) = Cx(&1)`,
+  REPEAT GEN_TAC THEN
+  REPLICATE_TAC 3 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
+  SUBGOAL_THEN `complex_integer(winding_number(g,z))` MP_TAC THENL
+   [ASM_SIMP_TAC[INTEGER_WINDING_NUMBER; VALID_PATH_IMP_PATH]; ALL_TAC] THEN
+  SIMP_TAC[complex_integer; COMPLEX_EQ; RE_CX; IM_CX] THEN
+  SIMP_TAC[REAL_LT_INTEGERS; INTEGER_CLOSED] THEN REAL_ARITH_TAC);;
+
+(* ------------------------------------------------------------------------- *)
+(* Continuity of winding number and invariance on connected sets.            *)
+(* ------------------------------------------------------------------------- *)
+
+let CONTINUOUS_AT_WINDING_NUMBER = prove
+ (`!g z. path g /\ ~(z IN path_image g)
+         ==> (\w. winding_number(g,w)) continuous (at z)`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPEC `(:complex) DIFF path_image g` OPEN_CONTAINS_CBALL) THEN
+  ASM_SIMP_TAC[GSYM closed; CLOSED_PATH_IMAGE] THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN
+  ASM_REWRITE_TAC[IN_DIFF; IN_UNIV; SUBSET; IN_CBALL] THEN
+  DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
+  MP_TAC(ISPECL [`(:complex) DIFF cball(z,e / &2)`; `g:real^1->complex`]
+        PATH_INTEGRAL_NEARBY_ENDS) THEN
+  ASM_SIMP_TAC[OPEN_DIFF; OPEN_UNIV; CLOSED_CBALL] THEN ANTS_TAC THENL
+   [REWRITE_TAC[SUBSET; IN_DIFF; IN_CBALL; SUBSET; IN_UNIV] THEN
+    GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
+    REWRITE_TAC[] THEN DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ASM_REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`; `min d e / &2`]
+    WINDING_NUMBER) THEN
+  ASM_REWRITE_TAC[REAL_HALF; REAL_LT_MIN] THEN
+  DISCH_THEN(X_CHOOSE_THEN `p:real^1->complex` STRIP_ASSUME_TAC) THEN
+  MATCH_MP_TAC CONTINUOUS_TRANSFORM_AT THEN
+  MAP_EVERY EXISTS_TAC [`\w. winding_number(p,w)`; `min d e / &2`] THEN
+  ASM_REWRITE_TAC[REAL_HALF; REAL_LT_MIN] THEN CONJ_TAC THENL
+   [X_GEN_TAC `w:complex` THEN DISCH_TAC THEN
+    MATCH_MP_TAC WINDING_NUMBER_UNIQUE THEN
+    ASM_SIMP_TAC[VALID_PATH_IMP_PATH] THEN
+    MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
+     [REWRITE_TAC[path_image; IN_IMAGE] THEN
+      DISCH_THEN(X_CHOOSE_THEN `t:real^1` STRIP_ASSUME_TAC) THEN
+      FIRST_X_ASSUM(MP_TAC o SPEC `(g:real^1->complex) t`) THEN
+      FIRST_X_ASSUM(MP_TAC o SPEC `t:real^1`) THEN
+      ASM_SIMP_TAC[path_image; FUN_IN_IMAGE] THEN
+      UNDISCH_TAC `dist (w:complex,z) < min d e / &2` THEN
+      ASM_REWRITE_TAC[] THEN CONV_TAC NORM_ARITH;
+      DISCH_TAC THEN X_GEN_TAC `k:real` THEN DISCH_TAC THEN
+      MP_TAC(ISPECL [`g:real^1->complex`; `w:complex`; `min k (min d e) / &2`]
+         WINDING_NUMBER) THEN
+      ASM_REWRITE_TAC[REAL_HALF; REAL_LT_MIN] THEN ANTS_TAC THENL
+       [FIRST_X_ASSUM MATCH_MP_TAC THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
+        ASM_REAL_ARITH_TAC;
+        ALL_TAC] THEN
+      DISCH_THEN(X_CHOOSE_THEN `q:real^1->complex` STRIP_ASSUME_TAC) THEN
+      EXISTS_TAC `p:real^1->complex` THEN ASM_REWRITE_TAC[] THEN
+      ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN
+      FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [SYM th]) THEN
+      CONV_TAC SYM_CONV THEN FIRST_X_ASSUM(MP_TAC o SPECL
+        [`p:real^1->complex`; `q:real^1->complex`]) THEN
+      ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
+       [X_GEN_TAC `t:real^1` THEN DISCH_TAC THEN
+        REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `t:real^1`)) THEN
+        ASM_REWRITE_TAC[] THEN CONV_TAC NORM_ARITH;
+        DISCH_THEN(MATCH_MP_TAC o last o CONJUNCTS)] THEN
+      MATCH_MP_TAC HOLOMORPHIC_ON_DIV THEN
+      SIMP_TAC[HOLOMORPHIC_ON_SUB; HOLOMORPHIC_ON_ID; HOLOMORPHIC_ON_CONST;
+               IN_DELETE; IN_UNIV; COMPLEX_SUB_0] THEN
+      ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN SIMP_TAC[IN_DIFF] THEN
+      REWRITE_TAC[IN_UNIV; IN_CBALL] THEN
+      ONCE_REWRITE_TAC[DIST_SYM] THEN ASM_REAL_ARITH_TAC];
+    UNDISCH_TAC `~((z:complex) IN path_image p)` THEN
+    UNDISCH_TAC `valid_path(p:real^1->complex)` THEN
+    POP_ASSUM_LIST(K ALL_TAC) THEN SPEC_TAC(`z:complex`,`z:complex`) THEN
+    SPEC_TAC(`p:real^1->complex`,`g:real^1->complex`)] THEN
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPEC `(:complex) DIFF path_image g` OPEN_CONTAINS_BALL) THEN
+  ASM_SIMP_TAC[GSYM closed; CLOSED_PATH_IMAGE; VALID_PATH_IMP_PATH] THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN
+  ASM_REWRITE_TAC[IN_DIFF; IN_UNIV; SUBSET; IN_BALL] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
+  MP_TAC(ISPECL [`(:complex) DIFF cball(z, &3 / &4 * d)`; `g:real^1->complex`]
+        PATH_INTEGRAL_BOUND_EXISTS) THEN
+  ASM_REWRITE_TAC[GSYM closed; CLOSED_CBALL; SUBSET; IN_DIFF;
+                  IN_CBALL; IN_UNIV; REAL_NOT_LE] THEN
+  ANTS_TAC THENL
+   [ASM_MESON_TAC[REAL_ARITH `&0 < d /\ ~(&3 / &4 * d < x) ==> x < d`];
+    ALL_TAC] THEN
+  DISCH_THEN(X_CHOOSE_THEN `L:real` STRIP_ASSUME_TAC) THEN
+  REWRITE_TAC[continuous_at] THEN X_GEN_TAC `e:real` THEN STRIP_TAC THEN
+  EXISTS_TAC `min (d / &4) (e / &2 * d pow 2 / L / &4)` THEN
+  ASM_SIMP_TAC[REAL_LT_MIN; REAL_POW_LT; REAL_LT_DIV; REAL_LT_MUL; REAL_HALF;
+               REAL_ARITH `&0 < x / &4 <=> &0 < x`] THEN
+  X_GEN_TAC `w:complex` THEN STRIP_TAC THEN
+  SUBGOAL_THEN `~((w:complex) IN path_image g)` ASSUME_TAC THENL
+   [FIRST_X_ASSUM MATCH_MP_TAC THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
+    ASM_REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  ASM_SIMP_TAC[dist; WINDING_NUMBER_VALID_PATH; GSYM COMPLEX_SUB_LDISTRIB] THEN
+  REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_DIV; COMPLEX_NORM_CX] THEN
+  REWRITE_TAC[REAL_ABS_NUM; COMPLEX_NORM_II; REAL_ABS_PI] THEN
+  REWRITE_TAC[real_div; REAL_MUL_LID; REAL_MUL_RID] THEN
+  MATCH_MP_TAC(REAL_ARITH
+    `inv p * x <= &1 * x /\ x < e ==> inv p * x < e`) THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
+    MATCH_MP_TAC REAL_INV_LE_1 THEN MP_TAC PI_APPROX_32 THEN REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  MATCH_MP_TAC(REAL_ARITH `!d. &0 < e /\ d = e / &2 /\ x <= d ==> x < e`) THEN
+  EXISTS_TAC `L * (e / &2 * d pow 2 / L / &4) * inv(d / &2) pow 2` THEN
+  ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+   [MAP_EVERY UNDISCH_TAC [`&0 < d`; `&0 < L`] THEN CONV_TAC REAL_FIELD;
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+   `path_integral g (\x. Cx(&1) / (x - w)) -
+    path_integral g (\x. Cx(&1) / (x - z)) =
+    path_integral g (\x. Cx(&1) / (x - w) - Cx(&1) / (x - z))`
+  SUBST1_TAC THENL
+   [CONV_TAC SYM_CONV THEN MATCH_MP_TAC PATH_INTEGRAL_SUB THEN
+    CONJ_TAC THEN MATCH_MP_TAC PATH_INTEGRABLE_INVERSEDIFF THEN
+    ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
+    ONCE_REWRITE_TAC[DIST_SYM] THEN ASM_REAL_ARITH_TAC;
+    ALL_TAC] THEN
+  FIRST_X_ASSUM MATCH_MP_TAC THEN
+  SIMP_TAC[HOLOMORPHIC_ON_OPEN; GSYM closed; CLOSED_CBALL] THEN
+  REWRITE_TAC[IN_UNIV; IN_DIFF; IN_CBALL; REAL_NOT_LE; AND_FORALL_THM] THEN
+  X_GEN_TAC `x:complex` THEN
+  REWRITE_TAC[TAUT `(a ==> b) /\ (a ==> c) <=> a ==> b /\ c`] THEN
+  DISCH_TAC THEN REWRITE_TAC[GSYM complex_differentiable] THEN
+  SUBGOAL_THEN `~(x:complex = w) /\ ~(x = z)` STRIP_ASSUME_TAC THENL
+   [CONJ_TAC THEN DISCH_THEN SUBST_ALL_TAC THEN
+    REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_NOT_LE])) THEN
+    CONV_TAC NORM_ARITH;
+    ALL_TAC] THEN
+  CONJ_TAC THENL
+   [MATCH_MP_TAC COMPLEX_DIFFERENTIABLE_SUB THEN
+    CONJ_TAC THEN MATCH_MP_TAC COMPLEX_DIFFERENTIABLE_DIV_AT THEN
+    ASM_SIMP_TAC[COMPLEX_SUB_0; COMPLEX_DIFFERENTIABLE_SUB;
+                 COMPLEX_DIFFERENTIABLE_ID; COMPLEX_DIFFERENTIABLE_CONST];
+    ALL_TAC] THEN
+  ASM_SIMP_TAC[COMPLEX_FIELD
+   `~(x = w) /\ ~(x = z)
+    ==> Cx(&1) / (x - w) - Cx(&1) / (x - z) =
+        (w - z) * inv((x - w) * (x - z))`] THEN
+  REWRITE_TAC[COMPLEX_NORM_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN
+  ASM_SIMP_TAC[NORM_POS_LE; GSYM dist; REAL_LT_IMP_LE] THEN
+  REWRITE_TAC[COMPLEX_NORM_INV; REAL_POW_INV] THEN
+  MATCH_MP_TAC REAL_LE_INV2 THEN
+  ASM_SIMP_TAC[REAL_POW_2; REAL_LT_MUL; REAL_HALF; COMPLEX_NORM_MUL] THEN
+  MATCH_MP_TAC REAL_LE_MUL2 THEN ASM_SIMP_TAC[REAL_HALF; REAL_LT_IMP_LE] THEN
+  REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_NOT_LE])) THEN
+  CONV_TAC NORM_ARITH);;
+
+let CONTINUOUS_ON_WINDING_NUMBER = prove
+ (`!g. path g
+       ==> (\w. winding_number(g,w)) continuous_on
+           ((:complex) DIFF path_image g)`,
+  SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT; GSYM closed;
+           OPEN_UNIV; CLOSED_PATH_IMAGE; VALID_PATH_IMP_PATH] THEN
+  SIMP_TAC[IN_DIFF; IN_UNIV; CONTINUOUS_AT_WINDING_NUMBER]);;
+
+let WINDING_NUMBER_CONSTANT = prove
+ (`!s g. path g /\ pathfinish g = pathstart g /\
+         connected s /\ s INTER path_image g = {}
+         ==> ?k. !z. z IN s ==> winding_number(g,z) = k`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_DISCRETE_RANGE_CONSTANT THEN
+  ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+   [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
+    EXISTS_TAC `(:complex) DIFF path_image g` THEN
+    ASM_SIMP_TAC[CONTINUOUS_ON_WINDING_NUMBER] THEN ASM SET_TAC[];
+    ALL_TAC] THEN
+  X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
+  EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN
+  X_GEN_TAC `w:complex` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
+  SUBGOAL_THEN
+   `complex_integer(winding_number(g,w)) /\
+    complex_integer(winding_number(g,z))`
+  MP_TAC THENL
+   [CONJ_TAC THEN MATCH_MP_TAC INTEGER_WINDING_NUMBER THEN
+    ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
+    REWRITE_TAC[COMPLEX_INTEGER] THEN STRIP_TAC THEN ASM_REWRITE_TAC[]] THEN
+  REWRITE_TAC[GSYM CX_SUB; CX_INJ; COMPLEX_NORM_CX] THEN
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_ABS_INTEGER_LEMMA THEN
+  ASM_SIMP_TAC[REAL_SUB_0; INTEGER_CLOSED]);;
+
+let WINDING_NUMBER_EQ = prove
+ (`!g s w z.
+        path g /\ pathfinish g = pathstart g /\
+        w IN s /\ z IN s /\ connected s /\ s INTER path_image g = {}
+        ==> winding_number(g,w) = winding_number(g,z)`,
+  MESON_TAC[WINDING_NUMBER_CONSTANT]);;
+
+let OPEN_WINDING_NUMBER_LEVELSETS = prove
+ (`!g k. path g /\ pathfinish g = pathstart g
+         ==> open {z | ~(z IN path_image g) /\ winding_number(g,z) = k}`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[open_def; IN_ELIM_THM] THEN
+  X_GEN_TAC `z:complex` THEN STRIP_TAC THEN
+  MP_TAC(ISPEC `(:complex) DIFF path_image g` OPEN_CONTAINS_BALL) THEN
+  ASM_SIMP_TAC[GSYM closed; CLOSED_PATH_IMAGE; VALID_PATH_IMP_PATH] THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN
+  ASM_REWRITE_TAC[IN_DIFF; IN_UNIV; SUBSET; IN_BALL] THEN
+  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
+  STRIP_TAC THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `w:complex` THEN
+  REPEAT STRIP_TAC THENL [ASM_MESON_TAC[DIST_SYM]; ALL_TAC] THEN
+  MP_TAC(ISPECL [`ball(z:complex,e)`; `g:real^1->complex`]
+        WINDING_NUMBER_CONSTANT) THEN
+  ASM_SIMP_TAC[CONNECTED_BALL; EXTENSION; IN_INTER; NOT_IN_EMPTY; IN_BALL] THEN
+  ASM_MESON_TAC[DIST_REFL; DIST_SYM]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Winding number is zero "outside" a curve, in various senses.              *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_ZERO_IN_OUTSIDE = prove
+ (`!g z. path g /\ pathfinish g = pathstart g /\ z IN outside(path_image g)
+         ==> winding_number(g,z) = Cx(&0)`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`path_image(g:real^1->complex)`; `Cx(&0)`]
+   BOUNDED_SUBSET_BALL) THEN ASM_SIMP_TAC[BOUNDED_PATH_IMAGE] THEN
+  DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
+  SUBGOAL_THEN `?w. ~(w IN ball(Cx(&0),B + &1))` STRIP_ASSUME_TAC THENL
+   [MATCH_MP_TAC(SET_RULE `~(s = UNIV) ==> ?z. ~(z IN s)`) THEN
+    MESON_TAC[BOUNDED_BALL; NOT_BOUNDED_UNIV];
+    ALL_TAC] THEN
+  MP_TAC(ISPECL [`Cx(&0)`; `B:real`; `B + &1`] SUBSET_BALL) THEN
+  REWRITE_TAC[REAL_ARITH `B <= B + &1`] THEN DISCH_TAC THEN
+  MP_TAC(ISPECL [`path_image(g:real^1->complex)`; `ball(Cx(&0),B + &1)`]
+        OUTSIDE_SUBSET_CONVEX) THEN
+  ASM_REWRITE_TAC[CONVEX_BALL] THEN
+  ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
+  REWRITE_TAC[SUBSET; IN_UNIV; IN_DIFF] THEN DISCH_TAC THEN
+  MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `winding_number(g,w)` THEN
+  CONJ_TAC THENL
+   [MP_TAC(ISPECL [`outside(path_image(g:real^1->complex))`;
+                   `g:real^1->complex`] WINDING_NUMBER_CONSTANT) THEN
+    ASM_SIMP_TAC[OUTSIDE_NO_OVERLAP; CONNECTED_OUTSIDE;
+                 DIMINDEX_2; LE_REFL; BOUNDED_PATH_IMAGE] THEN
+    ASM SET_TAC[];
+    MATCH_MP_TAC WINDING_NUMBER_UNIQUE THEN ASM_REWRITE_TAC[] THEN
+    MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
+     [ASM SET_TAC[]; DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC] THEN
+    MP_TAC(ISPECL [`g:real^1->complex`; `min e (&1)`]
+        PATH_APPROX_VECTOR_POLYNOMIAL_FUNCTION) THEN
+    ASM_REWRITE_TAC[REAL_LT_MIN; REAL_LT_01] THEN
+    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `p:real^1->complex` THEN
+    STRIP_TAC THEN ONCE_REWRITE_TAC[NORM_SUB] THEN
+    ASM_SIMP_TAC[VALID_PATH_VECTOR_POLYNOMIAL_FUNCTION] THEN CONJ_TAC THENL
+     [UNDISCH_TAC `~(w IN ball (Cx (&0),B + &1))` THEN
+      REWRITE_TAC[CONTRAPOS_THM; path_image; IN_BALL] THEN
+      SPEC_TAC(`w:complex`,`x:complex`) THEN REWRITE_TAC[FORALL_IN_IMAGE];
+      REWRITE_TAC[COMPLEX_MUL_RZERO] THEN
+      MATCH_MP_TAC PATH_INTEGRAL_UNIQUE THEN
+      MATCH_MP_TAC CAUCHY_THEOREM_CONVEX_SIMPLE THEN
+      EXISTS_TAC `ball(Cx(&0),B + &1)` THEN
+      ASM_SIMP_TAC[CONVEX_BALL; VALID_PATH_VECTOR_POLYNOMIAL_FUNCTION] THEN
+      CONJ_TAC THENL
+       [MATCH_MP_TAC HOLOMORPHIC_ON_DIV THEN
+        SIMP_TAC[HOLOMORPHIC_ON_SUB; HOLOMORPHIC_ON_ID; HOLOMORPHIC_ON_CONST;
+                 COMPLEX_SUB_0] THEN
+        ASM_MESON_TAC[];
+        REWRITE_TAC[path_image; SUBSET; FORALL_IN_IMAGE; IN_BALL]]] THEN
+      X_GEN_TAC `t:real^1` THEN DISCH_TAC THEN
+      REWRITE_TAC[dist; COMPLEX_SUB_LZERO; NORM_NEG] THEN
+      MATCH_MP_TAC(NORM_ARITH
+       `!g:real^1->complex. norm(p t - g t) < &1 /\ norm(g t) <= B
+                            ==> norm(p t) < B + &1`) THEN
+      EXISTS_TAC `g:real^1->complex` THEN
+      UNDISCH_TAC `path_image g SUBSET ball (Cx (&0),B)` THEN
+      ASM_SIMP_TAC[SUBSET; IN_BALL; path_image; FORALL_IN_IMAGE] THEN
+      ASM_SIMP_TAC[dist; COMPLEX_SUB_LZERO; NORM_NEG; REAL_LT_IMP_LE]]);;
+
+let WINDING_NUMBER_ZERO_OUTSIDE = prove
+ (`!g s z. path g /\ convex s /\ pathfinish g = pathstart g /\
+           ~(z IN s) /\ path_image g SUBSET s
+           ==> winding_number(g,z) = Cx(&0)`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC WINDING_NUMBER_ZERO_IN_OUTSIDE THEN
+  ASM_REWRITE_TAC[] THEN
+  MP_TAC(ISPECL [`path_image(g:real^1->complex)`; `s:complex->bool`]
+        OUTSIDE_SUBSET_CONVEX) THEN
+  ASM SET_TAC[]);;
+
+let WINDING_NUMBER_ZERO_ATINFINITY = prove
+ (`!g. path g /\ pathfinish g = pathstart g
+       ==> ?B. !z. B <= norm(z) ==> winding_number(g,z) = Cx(&0)`,
+  REPEAT STRIP_TAC THEN
+  SUBGOAL_THEN `bounded (path_image g :complex->bool)` MP_TAC THENL
+   [ASM_SIMP_TAC[BOUNDED_PATH_IMAGE]; ALL_TAC] THEN
+  REWRITE_TAC[bounded] THEN DISCH_THEN(X_CHOOSE_TAC `B:real`) THEN
+  EXISTS_TAC `B + &1` THEN REPEAT STRIP_TAC THEN
+  MATCH_MP_TAC WINDING_NUMBER_ZERO_OUTSIDE THEN
+  EXISTS_TAC `cball(Cx(&0),B)` THEN ASM_REWRITE_TAC[CONVEX_CBALL] THEN
+  REWRITE_TAC[SUBSET; IN_CBALL; dist; COMPLEX_SUB_LZERO; NORM_NEG] THEN
+  ASM_MESON_TAC[REAL_ARITH `~(B + &1 <= z /\ z <= B)`]);;
+
+let WINDING_NUMBER_ZERO_POINT = prove
+ (`!g s. path g /\ pathfinish g = pathstart g /\
+         open s /\ path_image g SUBSET s
+         ==> ?z. z IN s /\ winding_number(g,z) = Cx(&0)`,
+  REPEAT STRIP_TAC THEN
+  MP_TAC(ISPECL [`path_image g:complex->bool`; `s:complex->bool`]
+        OUTSIDE_COMPACT_IN_OPEN) THEN
+  ASM_SIMP_TAC[COMPACT_PATH_IMAGE] THEN ANTS_TAC THENL
+   [ASM_MESON_TAC[SUBSET_EMPTY; PATH_IMAGE_NONEMPTY]; ALL_TAC] THEN
+  REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN MATCH_MP_TAC MONO_EXISTS THEN
+  GEN_TAC THEN REWRITE_TAC[IN_INTER] THEN
+  ASM_SIMP_TAC[WINDING_NUMBER_ZERO_IN_OUTSIDE]);;
+
+(* ------------------------------------------------------------------------- *)
+(* If a path winds round a set, it winds rounds its inside.                  *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_AROUND_INSIDE = prove
+ (`!g s z.
+        path g /\ pathfinish g = pathstart g /\
+        closed s /\ connected s /\ s INTER path_image g = {} /\
+        z IN s /\ ~(winding_number(g,z) = Cx(&0))
+        ==> !w. w IN s UNION inside(s)
+                ==> winding_number(g,w) = winding_number(g,z)`,
+  MAP_EVERY X_GEN_TAC
+   [`g:real^1->complex`; `s:complex->bool`; `z0:complex`] THEN STRIP_TAC THEN
+  SUBGOAL_THEN `!z. z IN s ==> winding_number(g,z) = winding_number(g,z0)`
+  ASSUME_TAC THENL [ASM_MESON_TAC[WINDING_NUMBER_EQ]; ALL_TAC] THEN
+  ABBREV_TAC `k = winding_number (g,z0)` THEN
+  SUBGOAL_THEN `(s:complex->bool) SUBSET inside(path_image g)` ASSUME_TAC THENL
+   [REWRITE_TAC[SUBSET; INSIDE_OUTSIDE; IN_DIFF; IN_UNIV; IN_UNION] THEN
+    X_GEN_TAC `z:complex` THEN REPEAT STRIP_TAC THENL
+     [ASM SET_TAC[]; ASM_MESON_TAC[WINDING_NUMBER_ZERO_IN_OUTSIDE]];
+    ALL_TAC] THEN
+  X_GEN_TAC `z:complex` THEN REWRITE_TAC[IN_UNION] THEN
+  STRIP_TAC THEN ASM_SIMP_TAC[] THEN
+  MP_TAC(ISPECL [`s:complex->bool`;
+                 `path_image g:complex->bool`]
+        INSIDE_INSIDE_COMPACT_CONNECTED) THEN
+  ASM_SIMP_TAC[COMPACT_PATH_IMAGE; CONNECTED_PATH_IMAGE] THEN STRIP_TAC THEN
+  EXPAND_TAC "k" THEN MATCH_MP_TAC WINDING_NUMBER_EQ THEN
+  EXISTS_TAC `s UNION inside s :complex->bool` THEN
+  ASM_SIMP_TAC[CONNECTED_WITH_INSIDE; IN_UNION] THEN
+  MP_TAC(ISPEC `path_image g :complex->bool` INSIDE_NO_OVERLAP) THEN
+  ASM SET_TAC[]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Bounding a WN by 1/2 for a path and point in opposite halfspaces.         *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_SUBPATH_CONTINUOUS = prove
+ (`!g z. valid_path g /\ ~(z IN path_image g)
+         ==> (\a. winding_number(subpath (vec 0) a g,z)) continuous_on
+             interval[vec 0,vec 1]`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THEN EXISTS_TAC
+    `\a. Cx(&1) / (Cx(&2) * Cx pi * ii) *
+         integral (interval[vec 0,a])
+                  (\t. Cx(&1) / (g t - z) * vector_derivative g (at t))` THEN
+  CONJ_TAC THENL
+   [X_GEN_TAC `a:real^1` THEN DISCH_TAC THEN REWRITE_TAC[] THEN
+    MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC
+     `Cx(&1) / (Cx(&2) * Cx pi * ii) *
+      path_integral (subpath (vec 0) a g) (\w. Cx (&1) / (w - z))` THEN
+    CONJ_TAC THENL
+     [AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
+      MATCH_MP_TAC PATH_INTEGRAL_SUBPATH_INTEGRAL THEN
+      ASM_SIMP_TAC[ENDS_IN_UNIT_INTERVAL; PATH_INTEGRABLE_INVERSEDIFF] THEN
+      ASM_MESON_TAC[IN_INTERVAL_1];
+      REPEAT STRIP_TAC THEN REWRITE_TAC[] THEN CONV_TAC SYM_CONV THEN
+      MATCH_MP_TAC WINDING_NUMBER_VALID_PATH THEN
+      ASM_MESON_TAC[VALID_PATH_SUBPATH; SUBSET; VALID_PATH_IMP_PATH;
+                 ENDS_IN_UNIT_INTERVAL; PATH_IMAGE_SUBPATH_SUBSET]];
+    MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_LMUL THEN
+    MATCH_MP_TAC INDEFINITE_INTEGRAL_CONTINUOUS_RIGHT THEN
+    REWRITE_TAC[GSYM PATH_INTEGRABLE_ON] THEN
+    ASM_SIMP_TAC[PATH_INTEGRABLE_INVERSEDIFF]]);;
+
+let WINDING_NUMBER_IVT_POS = prove
+ (`!g z w.
+        valid_path g /\ ~(z IN path_image g) /\
+        &0 <= w /\ w <= Re(winding_number(g,z))
+        ==> ?t. t IN interval[vec 0,vec 1] /\
+                Re(winding_number(subpath (vec 0) t g,z)) = w`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[RE_DEF] THEN
+  MATCH_MP_TAC IVT_INCREASING_COMPONENT_ON_1 THEN
+  ASM_SIMP_TAC[WINDING_NUMBER_SUBPATH_CONTINUOUS] THEN
+  ASM_REWRITE_TAC[SUBPATH_TRIVIAL; GSYM RE_DEF; DIMINDEX_2; ARITH] THEN
+  REWRITE_TAC[DROP_VEC; REAL_POS; SUBPATH_REFL] THEN
+  MP_TAC(ISPECL [`(g:real^1->complex) (vec 0)`; `z:complex`]
+        WINDING_NUMBER_TRIVIAL) THEN
+  ASM_MESON_TAC[pathstart; PATHSTART_IN_PATH_IMAGE; RE_CX]);;
+
+let WINDING_NUMBER_IVT_NEG = prove
+ (`!g z w.
+        valid_path g /\ ~(z IN path_image g) /\
+        Re(winding_number(g,z)) <= w /\ w <= &0
+        ==> ?t. t IN interval[vec 0,vec 1] /\
+                Re(winding_number(subpath (vec 0) t g,z)) = w`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[RE_DEF] THEN
+  MATCH_MP_TAC IVT_DECREASING_COMPONENT_ON_1 THEN
+  ASM_SIMP_TAC[WINDING_NUMBER_SUBPATH_CONTINUOUS] THEN
+  ASM_REWRITE_TAC[SUBPATH_TRIVIAL; GSYM RE_DEF; DIMINDEX_2; ARITH] THEN
+  REWRITE_TAC[DROP_VEC; REAL_POS; SUBPATH_REFL] THEN
+  MP_TAC(ISPECL [`(g:real^1->complex) (vec 0)`; `z:complex`]
+        WINDING_NUMBER_TRIVIAL) THEN
+  ASM_MESON_TAC[pathstart; PATHSTART_IN_PATH_IMAGE; RE_CX]);;
+
+let WINDING_NUMBER_IVT_ABS = prove
+ (`!g z w.
+        valid_path g /\ ~(z IN path_image g) /\
+        &0 <= w /\ w <= abs(Re(winding_number(g,z)))
+        ==> ?t. t IN interval[vec 0,vec 1] /\
+                abs(Re(winding_number(subpath (vec 0) t g,z))) = w`,
+  REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 <= Re(winding_number(g,z))` THEN
+  ASM_REWRITE_TAC[real_abs] THEN REWRITE_TAC[GSYM real_abs] THEN
+  REPEAT STRIP_TAC THENL
+   [MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`; `w:real`]
+        WINDING_NUMBER_IVT_POS);
+    MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`; `--w:real`]
+        WINDING_NUMBER_IVT_NEG)] THEN
+  (ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
+  MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN ASM_REAL_ARITH_TAC);;
+
+let WINDING_NUMBER_LT_HALF = prove
+ (`!g z a b.
+        valid_path g /\ a dot z <= b /\ path_image g SUBSET {w | a dot w > b}
+        ==> abs(Re(winding_number(g,z))) < &1 / &2`,
+  let lemma = prove
+   (`!g z a b.
+          valid_path g /\ ~(z IN path_image g) /\
+          a dot z <= b /\ path_image g SUBSET {w | a dot w > b}
+          ==> Re(winding_number(g,z)) < &1 / &2`,
+    REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LE] THEN STRIP_TAC THEN
+    MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`; `&1 / &2`]
+      WINDING_NUMBER_IVT_POS) THEN
+    CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
+    X_GEN_TAC `t:real^1` THEN STRIP_TAC THEN
+    MP_TAC(ISPECL [`subpath (vec 0) t (g:real^1->complex)`; `z:complex`]
+          WINDING_NUMBER_AHLFORS_FULL) THEN
+    ASM_SIMP_TAC[VALID_PATH_SUBPATH; VALID_PATH_IMP_PATH;
+                 ENDS_IN_UNIT_INTERVAL; NOT_IMP] THEN
+    CONJ_TAC THENL
+     [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
+       `~(z IN t) ==> s SUBSET t ==> ~(z IN s)`)) THEN
+      ASM_SIMP_TAC[PATH_IMAGE_SUBPATH_SUBSET; ENDS_IN_UNIT_INTERVAL;
+                   VALID_PATH_IMP_PATH];
+      ASM_REWRITE_TAC[EULER; RE_MUL_CX; RE_MUL_II; IM_MUL_CX; IM_MUL_II] THEN
+      REWRITE_TAC[REAL_ARITH `&2 * pi * &1 / &2 = pi`; SIN_PI; COS_PI] THEN
+      REWRITE_TAC[COMPLEX_MUL_RZERO; COMPLEX_ADD_RID] THEN
+      REWRITE_TAC[PATHSTART_SUBPATH; PATHFINISH_SUBPATH] THEN
+      REWRITE_TAC[COMPLEX_MUL_ASSOC; GSYM CX_MUL] THEN
+      REWRITE_TAC[REAL_MUL_RNEG; REAL_MUL_RID; GSYM COMPLEX_CMUL] THEN
+      DISCH_TAC THEN
+      SUBGOAL_THEN `&0 < a dot ((g:real^1->complex) t - z) /\
+                    &0 < a dot (g(vec 0) - z)`
+      MP_TAC THENL
+       [REWRITE_TAC[DOT_RSUB; REAL_SUB_LT] THEN CONJ_TAC THEN
+        MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `b:real` THEN
+        ASM_REWRITE_TAC[GSYM real_gt] THEN
+        FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
+         `g SUBSET {z | a dot z > b} ==> t IN g ==> a dot t > b`)) THEN
+        REWRITE_TAC[path_image] THEN MATCH_MP_TAC FUN_IN_IMAGE THEN
+        ASM_REWRITE_TAC[ENDS_IN_UNIT_INTERVAL];
+        ASM_REWRITE_TAC[DOT_RMUL] THEN
+        DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
+        ASM_SIMP_TAC[REAL_LT_MUL_EQ] THEN
+        MATCH_MP_TAC(REAL_ARITH `&0 < x ==> ~(&0 < -- x)`) THEN
+        REWRITE_TAC[REAL_EXP_POS_LT]]]) in
+  REPEAT STRIP_TAC THEN
+  FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
+  DISCH_THEN(MP_TAC o SPEC `z:complex`) THEN
+  ASM_REWRITE_TAC[IN_ELIM_THM; REAL_ARITH `a:real > b <=> ~(a <= b)`] THEN
+  DISCH_TAC THEN MATCH_MP_TAC(REAL_ARITH `x < a /\ --x < a ==> abs x < a`) THEN
+  CONJ_TAC THENL [ASM_MESON_TAC[lemma]; ALL_TAC] THEN
+  MP_TAC(ISPECL [`reversepath g:real^1->complex`; `z:complex`;
+                 `a:complex`; `b:real`] lemma) THEN
+  ASM_SIMP_TAC[VALID_PATH_REVERSEPATH; PATH_IMAGE_REVERSEPATH;
+               WINDING_NUMBER_REVERSEPATH; VALID_PATH_IMP_PATH; RE_NEG] THEN
+  REAL_ARITH_TAC);;
+
+let WINDING_NUMBER_LE_HALF = prove
+ (`!g z a b.
+        valid_path g /\ ~(z IN path_image g) /\
+        ~(a = vec 0) /\ a dot z <= b /\ path_image g SUBSET {w | a dot w >= b}
+        ==> abs(Re(winding_number(g,z))) <= &1 / &2`,
+  REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
+  MP_TAC(ISPECL [`g:real^1->complex`; `z:complex`]
+   CONTINUOUS_AT_WINDING_NUMBER) THEN
+  ASM_SIMP_TAC[VALID_PATH_IMP_PATH; continuous_at] THEN
+  DISCH_THEN(MP_TAC o SPEC `abs(Re(winding_number(g,z))) - &1 / &2`) THEN
+  ASM_REWRITE_TAC[REAL_SUB_LT] THEN
+  DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
+  FIRST_X_ASSUM(MP_TAC o SPEC `z - d / &2 / norm(a) % a:complex`) THEN
+  REWRITE_TAC[NORM_ARITH `dist(z - d:complex,z) = norm d`] THEN
+  ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL;
+               NORM_EQ_0; NOT_IMP] THEN
+  CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
+  MATCH_MP_TAC(NORM_ARITH
+    `abs(Re w' - Re w) <= norm(w' - w) /\ abs(Re w') < &1 / &2
+     ==> ~(dist(w',w) < abs(Re w) - &1 / &2)`) THEN
+  REWRITE_TAC[GSYM RE_SUB] THEN CONJ_TAC THENL
+   [SIMP_TAC[COMPONENT_LE_NORM; RE_DEF; DIMINDEX_2; ARITH]; ALL_TAC] THEN
+  MATCH_MP_TAC WINDING_NUMBER_LT_HALF THEN EXISTS_TAC `a:complex` THEN
+  EXISTS_TAC `b - d / &3 * norm(a:complex)` THEN
+  ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
+   [REWRITE_TAC[DOT_RSUB; DOT_RMUL; GSYM NORM_POW_2] THEN
+    ASM_SIMP_TAC[NORM_EQ_0; REAL_FIELD
+     `~(a = &0) ==> x / a * a pow 2 = x * a`] THEN
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
+     `a:real <= b ==> d <= e ==> a - e <= b - d`)) THEN
+    MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
+    ASM_REAL_ARITH_TAC;
+    FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
+        SUBSET_TRANS)) THEN
+    REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN MATCH_MP_TAC(REAL_ARITH
+     `&0 < e ==> !x. a dot x >= b ==> a dot x > b - e`) THEN
+    MATCH_MP_TAC REAL_LT_MUL THEN ASM_SIMP_TAC[NORM_POS_LT] THEN
+    ASM_REAL_ARITH_TAC]);;
+
+let WINDING_NUMBER_LT_HALF_LINEPATH = prove
+ (`!a b z.
+        ~(z IN segment[a,b])
+        ==> abs(Re(winding_number(linepath(a,b),z))) < &1 / &2`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC WINDING_NUMBER_LT_HALF THEN
+  MP_TAC(ISPECL [`segment[a:complex,b]`; `z:complex`]
+        SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
+  ASM_REWRITE_TAC[CONVEX_SEGMENT; CLOSED_SEGMENT] THEN
+  REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
+  SIMP_TAC[VALID_PATH_LINEPATH; PATH_IMAGE_LINEPATH; SUBSET; IN_ELIM_THM;
+           REAL_LT_IMP_LE]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Positivity of WN for a linepath.                                          *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_LINEPATH_POS_LT = prove
+ (`!a b z. &0 < Im((b - a) * cnj(b - z))
+           ==> &0 < Re(winding_number(linepath(a,b),z))`,
+  REPEAT STRIP_TAC THEN MATCH_MP_TAC WINDING_NUMBER_POS_LT THEN
+  EXISTS_TAC `Im((b - a) * cnj(b - z))` THEN
+  ASM_REWRITE_TAC[VALID_PATH_LINEPATH; VECTOR_DERIVATIVE_LINEPATH_AT] THEN
+  CONJ_TAC THENL
+   [POP_ASSUM MP_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
+    SPEC_TAC(`z:complex`,`z:complex`) THEN
+    REWRITE_TAC[path_image; FORALL_IN_IMAGE; linepath] THEN
+    REWRITE_TAC[VECTOR_ARITH
+     `b - ((&1 - x) % a + x % b) = (&1 - x) % (b - a)`] THEN
+    REWRITE_TAC[COMPLEX_CMUL; CNJ_MUL; CNJ_CX] THEN
+    REWRITE_TAC[COMPLEX_RING `a * Cx x * cnj a = Cx x * a * cnj a`] THEN
+    SIMP_TAC[COMPLEX_MUL_CNJ; GSYM CX_POW; GSYM CX_MUL; IM_CX; REAL_LT_REFL];
+    ALL_TAC] THEN
+  SUBGOAL_THEN
+    `segment[a,b] SUBSET
+      {y | Im((b - a) * cnj(b - z)) <= Im((b - a) * cnj(y - z))}`
+  MP_TAC THENL
+   [REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC HULL_MINIMAL THEN
+    CONJ_TAC THENL
+     [REWRITE_TAC[SET_RULE `{a,b} SUBSET {y | P y} <=> P a /\ P b`] THEN
+      POP_ASSUM MP_TAC THEN
+      REWRITE_TAC[cnj; complex_mul; RE; IM; RE_SUB; IM_SUB] THEN
+      REAL_ARITH_TAC;
+      ALL_TAC] THEN
+    REWRITE_TAC[COMPLEX_SUB_LDISTRIB; IM_SUB; CNJ_SUB; REAL_LE_SUB_LADD] THEN
+    REWRITE_TAC[CONVEX_ALT; cnj; complex_mul; RE; IM; RE_SUB; IM_SUB] THEN
+    REWRITE_TAC[IN_ELIM_THM; IM_ADD; RE_ADD; IM_CMUL; RE_CMUL] THEN
+    REWRITE_TAC[REAL_NEG_ADD; REAL_NEG_RMUL] THEN
+    ONCE_REWRITE_TAC[REAL_ARITH
+     `e <= ab * ((&1 - u) * x + u * y) + ab' * ((&1 - u) * x' + u * y') <=>
+      (&1 - u) * e + u * e <=
+        (&1 - u) * (ab * x + ab' * x') + u * (ab * y + ab' * y')`] THEN
+    REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_ADD2 THEN
+    CONJ_TAC THEN MATCH_MP_TAC REAL_LE_LMUL THEN ASM_REWRITE_TAC[] THEN
+    ASM_REAL_ARITH_TAC;
+    REWRITE_TAC[GSYM PATH_IMAGE_LINEPATH] THEN
+    REWRITE_TAC[SUBSET; path_image; FORALL_IN_IMAGE; IN_ELIM_THM] THEN
+    ASM_MESON_TAC[SUBSET; INTERVAL_OPEN_SUBSET_CLOSED]]);;
+
+(* ------------------------------------------------------------------------- *)
+(* Winding number for a triangle.                                            *)
+(* ------------------------------------------------------------------------- *)
+
+let WINDING_NUMBER_TRIANGLE = prove
+ (`!a b c z.
+        z IN interior(convex hull {a,b,c})
+        ==> winding_number(linepath(a,b) ++ linepath(b,c) ++ linepath(c,a),z) =
+            if &0 < Im((b - a) * cnj (b - z)) then Cx(&1) else --Cx(&1)`,
+  let lemma1 = prove
+   (`!a b c. vec 0 IN interior(convex hull {a,b,c})
+             ==> ~(Im(a / b) <= &0 /\ &0 <= Im(b / c))`,
+    REPEAT GEN_TAC THEN
+    ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN SIMP_TAC[] THEN
+    GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o ONCE_DEPTH_CONV)
+     [GSYM COMPLEX_INV_DIV] THEN
+    REWRITE_TAC[IM_COMPLEX_INV_GE_0] THEN
+    GEOM_BASIS_MULTIPLE_TAC 1 `b:complex` THEN
+    REWRITE_TAC[COMPLEX_CMUL; COMPLEX_BASIS; GSYM CX_MUL; REAL_MUL_RID] THEN
+    X_GEN_TAC `x:real` THEN GEN_REWRITE_TAC LAND_CONV [REAL_LE_LT] THEN
+    REWRITE_TAC[IM_DIV_CX] THEN ASM_CASES_TAC `x = &0` THEN
+    ASM_REWRITE_TAC[NOT_IN_INTERIOR_CONVEX_HULL_3; COMPLEX_VEC_0] THEN
+    DISCH_TAC THEN REPEAT GEN_TAC THEN
+    ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_MUL_LZERO] THEN STRIP_TAC THEN
+    MATCH_MP_TAC(SET_RULE
+     `!s. ~(x IN s) /\ t SUBSET s ==> ~(x IN t)`) THEN
+    EXISTS_TAC `interior {z | Im z <= &0}` THEN CONJ_TAC THENL
+     [REWRITE_TAC[IM_DEF; INTERIOR_HALFSPACE_COMPONENT_LE] THEN
+      REWRITE_TAC[GSYM COMPLEX_VEC_0; IN_ELIM_THM; VEC_COMPONENT] THEN
+      REAL_ARITH_TAC;
+      MATCH_MP_TAC SUBSET_INTERIOR THEN MATCH_MP_TAC HULL_MINIMAL THEN
+      REWRITE_TAC[CONVEX_HALFSPACE_IM_LE] THEN
+      ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET; IN_ELIM_THM] THEN
+      REWRITE_TAC[IM_CX; REAL_LE_REFL]]) in
+  let lemma2 = prove
+   (`z IN interior(convex hull {a,b,c})
+     ==>  &0 < Im((b - a) * cnj (b - z)) /\
+          &0 < Im((c - b) * cnj (c - z)) /\
+          &0 < Im((a - c) * cnj (a - z)) \/
+          Im((b - a) * cnj (b - z)) < &0 /\
+          &0 < Im((b - c) * cnj (b - z)) /\
+          &0 < Im((a - b) * cnj (a - z)) /\
+          &0 < Im((c - a) * cnj (c - z))`,
+    GEOM_ORIGIN_TAC `z:complex` THEN
+    REWRITE_TAC[VECTOR_SUB_RZERO; COMPLEX_SUB_RDISTRIB] THEN
+    REWRITE_TAC[COMPLEX_MUL_CNJ; IM_SUB; GSYM CX_POW; IM_CX] THEN
+    REWRITE_TAC[REAL_ARITH `&0 < &0 - x <=> x < &0`;
+                REAL_ARITH `&0 - x < &0 <=> &0 < x`] THEN
+    REWRITE_TAC[GSYM IM_COMPLEX_DIV_GT_0; GSYM IM_COMPLEX_DIV_LT_0] THEN
+    REPEAT STRIP_TAC THEN
+    GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [GSYM COMPLEX_INV_DIV] THEN
+    REWRITE_TAC[IM_COMPLEX_INV_LT_0; IM_COMPLEX_INV_GT_0] THEN
+    GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o LAND_CONV o RAND_CONV)
+     [GSYM COMPLEX_INV_DIV] THEN
+    REWRITE_TAC[IM_COMPLEX_INV_LT_0] THEN
+    MP_TAC(ISPECL [`a:complex`; `b:complex`; `c:complex`] lemma1) THEN
+    MP_TAC(ISPECL [`b:complex`; `c:complex`; `a:complex`] lemma1) THEN
+    MP_TAC(ISPECL [`c:complex`; `a:complex`; `b:complex`] lemma1) THEN
+    POP_ASSUM MP_TAC THEN SIMP_TAC[INSERT_AC] THEN REAL_ARITH_TAC) in
+  let lemma3 = prove
+   (`!a b c z.
+          z IN interior(convex hull {a,b,c}) /\
+          &0 < Im((b - a) * cnj (b - z)) /\
+          &0 < Im((c - b) * cnj (c - z)) /\
+          &0 < Im((a - c) * cnj (a - z))
+          ==> winding_number
+               (linepath(a,b) ++ linepath(b,c) ++ linepath(c,a),z) = Cx(&1)`,
+    REPEAT STRIP_TAC THEN
+    MATCH_MP_TAC WINDING_NUMBER_EQ_1 THEN
+    REWRITE_TAC[PATHSTA