Update from HH
[hl193./.git] / Multivariate / transcendentals.ml
1 (* ========================================================================= *)
2 (* Complex transcendentals and their real counterparts.                      *)
3 (*                                                                           *)
4 (*              (c) Copyright, John Harrison 1998-2008                       *)
5 (* ========================================================================= *)
6
7 needs "Multivariate/determinants.ml";;
8 needs "Multivariate/canal.ml";;
9
10 prioritize_complex();;
11
12 (* ------------------------------------------------------------------------- *)
13 (* The complex exponential function.                                         *)
14 (* ------------------------------------------------------------------------- *)
15
16 let cexp = new_definition
17  `cexp z = infsum (from 0) (\n. z pow n / Cx(&(FACT n)))`;;
18
19 let CEXP_0 = prove
20  (`cexp(Cx(&0)) = Cx(&1)`,
21   REWRITE_TAC[cexp] THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
22   MP_TAC(ISPECL [`\i. Cx(&0) pow i / Cx(&(FACT i))`; `{0}`; `from 0`]
23          SERIES_FINITE_SUPPORT) THEN
24   SIMP_TAC[FROM_0; INTER_UNIV; FINITE_INSERT; FINITE_RULES] THEN ANTS_TAC THENL
25    [INDUCT_TAC THEN REWRITE_TAC[IN_SING; NOT_SUC] THEN
26     REWRITE_TAC[complex_div; complex_pow; COMPLEX_MUL_LZERO; COMPLEX_VEC_0];
27     REWRITE_TAC[VSUM_SING; FACT; COMPLEX_DIV_1; complex_pow]]);;
28
29 let CEXP_CONVERGES_UNIFORMLY_CAUCHY = prove
30  (`!R e. &0 < e /\ &0 < R
31          ==> ?N. !m n z. m >= N /\ norm(z) <= R
32                          ==> norm(vsum(m..n) (\i. z pow i / Cx(&(FACT i))))
33                                      < e`,
34   REPEAT STRIP_TAC THEN
35   MP_TAC(ISPECL [`&1 / &2`; `\i. Cx(R) pow i / Cx(&(FACT i))`;
36                  `from 0`] SERIES_RATIO) THEN
37   REWRITE_TAC[SERIES_CAUCHY; LEFT_FORALL_IMP_THM] THEN
38   MP_TAC(SPEC `&2 * norm(Cx(R))` REAL_ARCH_SIMPLE) THEN
39   REWRITE_TAC[COMPLEX_NORM_CX; COMPLEX_NORM_DIV; COMPLEX_NORM_POW] THEN
40   CONV_TAC REAL_RAT_REDUCE_CONV THEN
41   MATCH_MP_TAC(TAUT `(a ==> b) /\ (c ==> d) ==> a ==> (b ==> c) ==> d`) THEN
42   CONJ_TAC THENL
43    [MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN DISCH_TAC THEN
44     X_GEN_TAC `n:num` THEN REWRITE_TAC[GE] THEN DISCH_TAC THEN
45     SIMP_TAC[FACT; real_pow; GSYM REAL_OF_NUM_MUL; real_div; REAL_INV_MUL] THEN
46     REWRITE_TAC[REAL_ARITH
47      `(z * zn) * (is * ik) <= (&1 * inv(&2)) * zn * ik <=>
48       &0 <= (&1 - (&2 * z) * is) * zn * ik`] THEN
49     MATCH_MP_TAC REAL_LE_MUL THEN
50     SIMP_TAC[REAL_LE_MUL; REAL_POS; REAL_POW_LE; REAL_SUB_LE;
51              REAL_LE_INV_EQ; REAL_ABS_POS] THEN
52     ASM_SIMP_TAC[GSYM real_div; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; LT_0] THEN
53     REPEAT(POP_ASSUM MP_TAC) THEN
54     REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM REAL_OF_NUM_SUC] THEN
55     REAL_ARITH_TAC;
56     DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
57     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
58     REWRITE_TAC[FROM_0; INTER_UNIV] THEN
59     REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
60     DISCH_THEN(fun th -> REPEAT STRIP_TAC THEN MP_TAC th) THEN
61     ASM_SIMP_TAC[GSYM CX_DIV; GSYM CX_POW; VSUM_CX_NUMSEG; COMPLEX_NORM_CX] THEN
62     MATCH_MP_TAC(REAL_ARITH `x <= y ==> y < e ==> x < e`) THEN
63     SUBGOAL_THEN `abs (sum (m..n) (\i. R pow i / &(FACT i))) =
64                   sum (m..n) (\i. R pow i / &(FACT i))`
65     SUBST1_TAC THENL
66      [REWRITE_TAC[REAL_ABS_REFL] THEN MATCH_MP_TAC SUM_POS_LE_NUMSEG THEN
67       ASM_SIMP_TAC[REAL_LT_IMP_LE;REAL_LT_DIV; REAL_OF_NUM_LT;
68                    FACT_LT; REAL_POW_LT];
69       ALL_TAC] THEN
70     MATCH_MP_TAC VSUM_NORM_LE THEN REWRITE_TAC[IN_NUMSEG; FINITE_NUMSEG] THEN
71     X_GEN_TAC `i:num` THEN
72     REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_POW; COMPLEX_NORM_CX] THEN
73     SIMP_TAC[REAL_ABS_NUM; REAL_LE_DIV2_EQ; REAL_OF_NUM_LT; FACT_LT] THEN
74     ASM_SIMP_TAC[REAL_POW_LE2; NORM_POS_LE]]);;
75
76 let CEXP_CONVERGES = prove
77  (`!z. ((\n. z pow n / Cx(&(FACT n))) sums cexp(z)) (from 0)`,
78   GEN_TAC THEN REWRITE_TAC[cexp; SUMS_INFSUM; summable; SERIES_CAUCHY] THEN
79   REWRITE_TAC[FROM_0; INTER_UNIV] THEN
80   MP_TAC(SPEC `norm(z:complex) + &1` CEXP_CONVERGES_UNIFORMLY_CAUCHY) THEN
81   SIMP_TAC[REAL_ARITH `&0 <= x ==> &0 < x + &1`; NORM_POS_LE] THEN
82   MESON_TAC[REAL_ARITH `x <= x + &1`]);;
83
84 let CEXP_CONVERGES_UNIQUE = prove
85  (`!w z. ((\n. z pow n / Cx(&(FACT n))) sums w) (from 0) <=> w = cexp(z)`,
86   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CEXP_CONVERGES] THEN
87   DISCH_THEN(MP_TAC o C CONJ (SPEC `z:complex` CEXP_CONVERGES)) THEN
88   REWRITE_TAC[SERIES_UNIQUE]);;
89
90 let CEXP_CONVERGES_UNIFORMLY = prove
91  (`!R e. &0 < R /\ &0 < e
92          ==> ?N. !n z. n >= N /\ norm(z) < R
93                        ==> norm(vsum(0..n) (\i. z pow i / Cx(&(FACT i))) -
94                                 cexp(z)) <= e`,
95   REPEAT STRIP_TAC THEN
96   MP_TAC(SPECL [`R:real`; `e / &2`] CEXP_CONVERGES_UNIFORMLY_CAUCHY) THEN
97   ASM_REWRITE_TAC[REAL_HALF] THEN MATCH_MP_TAC MONO_EXISTS THEN
98   X_GEN_TAC `N:num` THEN DISCH_TAC THEN
99   MAP_EVERY X_GEN_TAC [`n:num`; `z:complex`] THEN STRIP_TAC THEN
100   MP_TAC(SPEC `z:complex` CEXP_CONVERGES) THEN
101   REWRITE_TAC[sums; LIM_SEQUENTIALLY; FROM_0; INTER_UNIV; dist] THEN
102   DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
103   DISCH_THEN(X_CHOOSE_THEN `M:num` (MP_TAC o SPEC `n + M + 1`)) THEN
104   FIRST_X_ASSUM(MP_TAC o SPECL [`n + 1`; `n + M + 1`; `z:complex`]) THEN
105   ASM_SIMP_TAC[ARITH_RULE `(n >= N ==> n + 1 >= N) /\ M <= n + M + 1`] THEN
106   ASM_SIMP_TAC[REAL_LT_IMP_LE; VSUM_ADD_SPLIT; LE_0] THEN
107   CONV_TAC(ONCE_DEPTH_CONV(ALPHA_CONV `i:num`)) THEN NORM_ARITH_TAC);;
108
109 let HAS_COMPLEX_DERIVATIVE_CEXP = prove
110  (`!z. (cexp has_complex_derivative cexp(z)) (at z)`,
111   REPEAT GEN_TAC THEN MP_TAC(ISPECL
112    [`ball(Cx(&0),norm(z:complex) + &1)`;
113     `\n z. z pow n / Cx(&(FACT n))`;
114     `\n z. if n = 0 then Cx(&0) else z pow (n-1) / Cx(&(FACT(n-1)))`;
115     `cexp:complex->complex`;
116     `(from 0)`]
117    HAS_COMPLEX_DERIVATIVE_SERIES) THEN
118   REWRITE_TAC[CONVEX_BALL; OPEN_BALL; IN_BALL; dist] THEN
119   SIMP_TAC[HAS_COMPLEX_DERIVATIVE_WITHIN_OPEN; OPEN_BALL; IN_BALL;
120            dist; COMPLEX_SUB_LZERO; COMPLEX_SUB_RZERO; NORM_NEG] THEN
121   ANTS_TAC THEN REPEAT CONJ_TAC THENL
122    [X_GEN_TAC `n:num` THEN REPEAT STRIP_TAC THEN COMPLEX_DIFF_TAC THEN
123     SPEC_TAC(`n:num`,`n:num`) THEN INDUCT_TAC THEN
124     REWRITE_TAC[ARITH; complex_div; COMPLEX_MUL_LZERO] THEN
125     MP_TAC(SPECL [`&n + &1`; `&0`] CX_INJ) THEN
126     REWRITE_TAC[NOT_SUC; SUC_SUB1; GSYM REAL_OF_NUM_SUC; FACT;
127          CX_ADD; CX_MUL; GSYM REAL_OF_NUM_MUL; COMPLEX_INV_MUL] THEN
128     REWRITE_TAC[REAL_ARITH `~(&n + &1 = &0)`] THEN
129     ABBREV_TAC `a = inv(Cx(&(FACT n)))` THEN CONV_TAC COMPLEX_FIELD;
130     REPEAT STRIP_TAC THEN
131     MP_TAC(SPECL [`norm(z:complex) + &1`; `e:real`]
132        CEXP_CONVERGES_UNIFORMLY) THEN
133     ASM_SIMP_TAC[NORM_POS_LE; REAL_ARITH `&0 <= x ==> &0 < x + &1`] THEN
134     DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN EXISTS_TAC `N + 1` THEN
135     MAP_EVERY X_GEN_TAC [`n:num`; `w:complex`] THEN STRIP_TAC THEN
136     FIRST_X_ASSUM(MP_TAC o SPECL [`n - 1`; `w:complex`]) THEN
137     ASM_SIMP_TAC[ARITH_RULE `n >= m + 1 ==> n - 1 >= m`] THEN
138     REWRITE_TAC[FROM_0; INTER_UNIV] THEN MATCH_MP_TAC EQ_IMP THEN
139     AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
140     AP_THM_TAC THEN AP_TERM_TAC THEN
141     SUBGOAL_THEN `0..n = 0 INSERT (IMAGE SUC (0..n-1))` SUBST1_TAC THENL
142      [REWRITE_TAC[EXTENSION; IN_INSERT; IN_IMAGE; IN_NUMSEG] THEN
143       INDUCT_TAC THEN REWRITE_TAC[LE_0; NOT_SUC; SUC_INJ; UNWIND_THM1] THEN
144       UNDISCH_TAC `n >= N + 1` THEN ARITH_TAC;
145       ALL_TAC] THEN
146     SIMP_TAC[VSUM_CLAUSES; FINITE_IMAGE; FINITE_NUMSEG] THEN
147     REWRITE_TAC[IN_IMAGE; NOT_SUC; COMPLEX_ADD_LID] THEN
148     SIMP_TAC[VSUM_IMAGE; FINITE_NUMSEG; SUC_INJ] THEN
149     MATCH_MP_TAC VSUM_EQ THEN SIMP_TAC[IN_NUMSEG; NOT_SUC; o_THM; SUC_SUB1];
150     MAP_EVERY EXISTS_TAC [`Cx(&0)`; `cexp(Cx(&0))`] THEN
151     REWRITE_TAC[CEXP_CONVERGES; COMPLEX_NORM_0] THEN
152     SIMP_TAC[REAL_ARITH `&0 <= z ==> &0 < z + &1`; NORM_POS_LE];
153     DISCH_THEN(X_CHOOSE_THEN `g:complex->complex` MP_TAC) THEN
154     REWRITE_TAC[CEXP_CONVERGES_UNIQUE] THEN STRIP_TAC THEN
155     MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_TRANSFORM_AT THEN
156     MAP_EVERY EXISTS_TAC [`g:complex->complex`; `&1`] THEN
157     REWRITE_TAC[REAL_LT_01] THEN CONJ_TAC THENL
158      [ALL_TAC;
159       FIRST_X_ASSUM(MP_TAC o SPEC `z:complex`) THEN
160       ANTS_TAC THENL [REAL_ARITH_TAC; SIMP_TAC[]]] THEN
161     POP_ASSUM MP_TAC THEN MATCH_MP_TAC MONO_FORALL THEN
162     X_GEN_TAC `w:complex` THEN MATCH_MP_TAC MONO_IMP THEN SIMP_TAC[] THEN
163     NORM_ARITH_TAC]);;
164
165 let COMPLEX_DIFFERENTIABLE_AT_CEXP = prove
166  (`!z. cexp complex_differentiable at z`,
167   REWRITE_TAC[complex_differentiable] THEN
168   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CEXP]);;
169
170 let COMPLEX_DIFFERENTIABLE_WITHIN_CEXP = prove
171  (`!s z. cexp complex_differentiable (at z within s)`,
172   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
173             COMPLEX_DIFFERENTIABLE_AT_CEXP]);;
174
175 let CONTINUOUS_AT_CEXP = prove
176  (`!z. cexp continuous at z`,
177   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CEXP;
178             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
179
180 let CONTINUOUS_WITHIN_CEXP = prove
181  (`!s z. cexp continuous (at z within s)`,
182   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CEXP]);;
183
184 let CONTINUOUS_ON_CEXP = prove
185  (`!s. cexp continuous_on s`,
186   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CEXP]);;
187
188 let HOLOMORPHIC_ON_CEXP = prove
189  (`!s. cexp holomorphic_on s`,
190   REWRITE_TAC [holomorphic_on] THEN
191   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CEXP]);;
192
193 (* ------------------------------------------------------------------------- *)
194 (* Add it to the database.                                                   *)
195 (* ------------------------------------------------------------------------- *)
196
197 add_complex_differentiation_theorems
198  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
199    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN_UNIV
200              HAS_COMPLEX_DERIVATIVE_CEXP)));;
201
202 (* ------------------------------------------------------------------------- *)
203 (* Hence the main results.                                                   *)
204 (* ------------------------------------------------------------------------- *)
205
206 let CEXP_ADD_MUL = prove
207  (`!w z. cexp(w + z) * cexp(--z) = cexp(w)`,
208   GEN_TAC THEN
209   ONCE_REWRITE_TAC[SET_RULE `(!x. P x) <=> (!x. x IN UNIV ==> P x)`] THEN
210   MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_ZERO_UNIQUE THEN
211   EXISTS_TAC `Cx(&0)` THEN REWRITE_TAC[OPEN_UNIV; CONVEX_UNIV; IN_UNIV] THEN
212   REWRITE_TAC[COMPLEX_ADD_RID; COMPLEX_NEG_0; CEXP_0; COMPLEX_MUL_RID] THEN
213   GEN_TAC THEN COMPLEX_DIFF_TAC THEN CONV_TAC COMPLEX_RING);;
214
215 let CEXP_NEG_RMUL = prove
216  (`!z. cexp(z) * cexp(--z) = Cx(&1)`,
217   MP_TAC(SPEC `Cx(&0)` CEXP_ADD_MUL) THEN MATCH_MP_TAC MONO_FORALL THEN
218   SIMP_TAC[COMPLEX_ADD_LID; CEXP_0]);;
219
220 let CEXP_NEG_LMUL = prove
221  (`!z. cexp(--z) * cexp(z) = Cx(&1)`,
222   ONCE_REWRITE_TAC[COMPLEX_MUL_SYM] THEN REWRITE_TAC[CEXP_NEG_RMUL]);;
223
224 let CEXP_NEG = prove
225  (`!z. cexp(--z) = inv(cexp z)`,
226   MP_TAC CEXP_NEG_LMUL THEN MATCH_MP_TAC MONO_FORALL THEN
227   CONV_TAC COMPLEX_FIELD);;
228
229 let CEXP_ADD = prove
230  (`!w z. cexp(w + z) = cexp(w) * cexp(z)`,
231   REPEAT GEN_TAC THEN
232   MP_TAC(SPECL [`w:complex`; `z:complex`] CEXP_ADD_MUL) THEN
233   MP_TAC(SPEC `z:complex` CEXP_NEG_LMUL) THEN CONV_TAC COMPLEX_FIELD);;
234
235 let CEXP_SUB = prove
236  (`!w z. cexp(w - z) = cexp(w) / cexp(z)`,
237   REPEAT GEN_TAC THEN
238   REWRITE_TAC[complex_sub; complex_div; CEXP_ADD; CEXP_NEG]);;
239
240 let CEXP_NZ = prove
241  (`!z. ~(cexp(z) = Cx(&0))`,
242   MP_TAC CEXP_NEG_LMUL THEN MATCH_MP_TAC MONO_FORALL THEN
243   CONV_TAC COMPLEX_FIELD);;
244
245 let CEXP_N = prove
246  (`!n x. cexp(Cx(&n) * x) = cexp(x) pow n`,
247   INDUCT_TAC THEN REWRITE_TAC[GSYM REAL_OF_NUM_SUC; CX_ADD] THEN
248   REWRITE_TAC[COMPLEX_MUL_LZERO; complex_pow; CEXP_0] THEN
249   ASM_REWRITE_TAC[COMPLEX_ADD_RDISTRIB; CEXP_ADD; COMPLEX_MUL_LID] THEN
250   REWRITE_TAC[COMPLEX_MUL_AC]);;
251
252 let CEXP_VSUM = prove
253  (`!f s. FINITE s ==> cexp(vsum s f) = cproduct s (\x. cexp(f x))`,
254   GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
255   SIMP_TAC[VSUM_CLAUSES; CPRODUCT_CLAUSES; CEXP_ADD; COMPLEX_VEC_0; CEXP_0]);;
256
257 let LIM_CEXP_MINUS_1 = prove
258  (`((\z. (cexp(z) - Cx(&1)) / z) --> Cx(&1)) (at (Cx(&0)))`,
259   MP_TAC(COMPLEX_DIFF_CONV
260       `((\z. cexp(z) - Cx(&1)) has_complex_derivative f') (at(Cx(&0)))`) THEN
261   REWRITE_TAC[HAS_COMPLEX_DERIVATIVE_AT; CEXP_0; COMPLEX_SUB_REFL] THEN
262   REWRITE_TAC[COMPLEX_MUL_LID; COMPLEX_SUB_RZERO]);;
263
264 (* ------------------------------------------------------------------------- *)
265 (* Crude bounds on complex exponential function, usable to get tighter ones. *)
266 (* ------------------------------------------------------------------------- *)
267
268 let CEXP_BOUND_BLEMMA = prove
269  (`!B. (!z. norm(z) <= &1 / &2 ==> norm(cexp z) <= B)
270        ==> !z. norm(z) <= &1 / &2 ==> norm(cexp z) <= &1 + B / &2`,
271   REPEAT STRIP_TAC THEN
272   MP_TAC(ISPECL [`cexp`; `cexp`; `cball(Cx(&0),&1 / &2)`; `B:real`]
273                 COMPLEX_DIFFERENTIABLE_BOUND) THEN
274   ASM_SIMP_TAC[CONVEX_CBALL; IN_CBALL; dist; COMPLEX_SUB_LZERO; NORM_NEG;
275     HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CEXP] THEN
276   DISCH_THEN(MP_TAC o SPECL [`z:complex`; `Cx(&0)`]) THEN
277   REWRITE_TAC[COMPLEX_NORM_0; CEXP_0; COMPLEX_SUB_RZERO] THEN
278   CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
279   MATCH_MP_TAC(NORM_ARITH
280    `norm(y) = &1 /\ d <= e ==> norm(x - y) <= d ==> norm(x) <= &1 + e`) THEN
281   REWRITE_TAC[COMPLEX_NORM_CX; real_div; REAL_ABS_NUM] THEN
282   MATCH_MP_TAC REAL_LE_LMUL THEN FIRST_X_ASSUM(MP_TAC o SPEC `Cx(&0)`) THEN
283   REWRITE_TAC[COMPLEX_NORM_CX] THEN POP_ASSUM MP_TAC THEN
284   NORM_ARITH_TAC);;
285
286 let CEXP_BOUND_HALF = prove
287  (`!z. norm(z) <= &1 / &2 ==> norm(cexp z) <= &2`,
288   REPEAT STRIP_TAC THEN
289   MP_TAC(ISPECL [`IMAGE cexp (cball(Cx(&0),&1 / &2))`; `Cx(&0)`]
290     DISTANCE_ATTAINS_SUP) THEN
291   SIMP_TAC[COMPACT_CONTINUOUS_IMAGE; COMPACT_CBALL; CONTINUOUS_ON_CEXP;
292            IMAGE_EQ_EMPTY; CBALL_EQ_EMPTY; FORALL_IN_IMAGE; EXISTS_IN_IMAGE;
293            IN_CBALL; dist; COMPLEX_SUB_LZERO; NORM_NEG] THEN
294   CONV_TAC REAL_RAT_REDUCE_CONV THEN
295   DISCH_THEN(X_CHOOSE_THEN `w:complex` STRIP_ASSUME_TAC) THEN
296   FIRST_ASSUM(MP_TAC o SPEC `w:complex` o MATCH_MP CEXP_BOUND_BLEMMA) THEN
297   FIRST_X_ASSUM(MP_TAC o SPEC `z:complex`) THEN
298   ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
299
300 let CEXP_BOUND_LEMMA = prove
301  (`!z. norm(z) <= &1 / &2 ==> norm(cexp z) <= &1 + &2 * norm(z)`,
302   REPEAT STRIP_TAC THEN
303   MP_TAC(ISPECL [`cexp`; `cexp`; `cball(Cx(&0),&1 / &2)`; `&2`]
304                 COMPLEX_DIFFERENTIABLE_BOUND) THEN
305   ASM_SIMP_TAC[CONVEX_CBALL; IN_CBALL; dist; COMPLEX_SUB_LZERO; NORM_NEG;
306                HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CEXP;
307                CEXP_BOUND_HALF] THEN
308   DISCH_THEN(MP_TAC o SPECL [`z:complex`; `Cx(&0)`]) THEN
309   REWRITE_TAC[COMPLEX_NORM_0; CEXP_0; COMPLEX_SUB_RZERO] THEN
310   CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
311   MATCH_MP_TAC(NORM_ARITH
312    `norm(y) = &1 ==> norm(x - y) <= d ==> norm(x) <= &1 + d`) THEN
313   REWRITE_TAC[COMPLEX_NORM_CX; REAL_ABS_NUM]);;
314
315 (* ------------------------------------------------------------------------- *)
316 (* Complex trig functions.                                                   *)
317 (* ------------------------------------------------------------------------- *)
318
319 let ccos = new_definition
320   `ccos z = (cexp(ii * z) + cexp(--ii * z)) / Cx(&2)`;;
321
322 let csin = new_definition
323   `csin z = (cexp(ii * z) - cexp(--ii * z)) / (Cx(&2) * ii)`;;
324
325 let CSIN_0 = prove
326  (`csin(Cx(&0)) = Cx(&0)`,
327   REWRITE_TAC[csin; COMPLEX_MUL_RZERO; COMPLEX_SUB_REFL] THEN
328   CONV_TAC COMPLEX_FIELD);;
329
330 let CCOS_0 = prove
331  (`ccos(Cx(&0)) = Cx(&1)`,
332   REWRITE_TAC[ccos; COMPLEX_MUL_RZERO; CEXP_0] THEN
333   CONV_TAC COMPLEX_FIELD);;
334
335 let CSIN_CIRCLE = prove
336  (`!z. csin(z) pow 2 + ccos(z) pow 2 = Cx(&1)`,
337   GEN_TAC THEN REWRITE_TAC[csin; ccos] THEN
338   MP_TAC(SPEC `ii * z` CEXP_NEG_LMUL) THEN
339   REWRITE_TAC[COMPLEX_MUL_LNEG] THEN
340   CONV_TAC COMPLEX_FIELD);;
341
342 let CSIN_ADD = prove
343  (`!w z. csin(w + z) = csin(w) * ccos(z) + ccos(w) * csin(z)`,
344   REPEAT GEN_TAC THEN
345   REWRITE_TAC[csin; ccos; COMPLEX_ADD_LDISTRIB; CEXP_ADD] THEN
346   CONV_TAC COMPLEX_FIELD);;
347
348 let CCOS_ADD = prove
349  (`!w z. ccos(w + z) = ccos(w) * ccos(z) - csin(w) * csin(z)`,
350   REPEAT GEN_TAC THEN
351   REWRITE_TAC[csin; ccos; COMPLEX_ADD_LDISTRIB; CEXP_ADD] THEN
352   CONV_TAC COMPLEX_FIELD);;
353
354 let CSIN_NEG = prove
355  (`!z. csin(--z) = --(csin(z))`,
356   REWRITE_TAC[csin; COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG; COMPLEX_NEG_NEG] THEN
357   CONV_TAC COMPLEX_FIELD);;
358
359 let CCOS_NEG = prove
360  (`!z. ccos(--z) = ccos(z)`,
361   REWRITE_TAC[ccos; COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG; COMPLEX_NEG_NEG] THEN
362   CONV_TAC COMPLEX_FIELD);;
363
364 let CSIN_DOUBLE = prove
365  (`!z. csin(Cx(&2) * z) = Cx(&2) * csin(z) * ccos(z)`,
366   REWRITE_TAC[COMPLEX_RING `Cx(&2) * x = x + x`; CSIN_ADD] THEN
367   CONV_TAC COMPLEX_RING);;
368
369 let CCOS_DOUBLE = prove
370  (`!z. ccos(Cx(&2) * z) = (ccos(z) pow 2) - (csin(z) pow 2)`,
371   REWRITE_TAC[COMPLEX_RING `Cx(&2) * x = x + x`; CCOS_ADD] THEN
372   CONV_TAC COMPLEX_RING);;
373
374 let CSIN_SUB = prove
375  (`!w z. csin(w - z) = csin(w) * ccos(z) - ccos(w) * csin(z)`,
376   REWRITE_TAC[complex_sub; COMPLEX_MUL_RNEG; CSIN_ADD; CSIN_NEG; CCOS_NEG]);;
377
378 let CCOS_SUB = prove
379  (`!w z. ccos(w - z) = ccos(w) * ccos(z) + csin(w) * csin(z)`,
380   REWRITE_TAC[complex_sub; CCOS_ADD; CSIN_NEG; CCOS_NEG;
381               COMPLEX_MUL_RNEG; COMPLEX_NEG_NEG]);;
382
383 let COMPLEX_MUL_CSIN_CSIN = prove
384  (`!w z. csin(w) * csin(z) = (ccos(w - z) - ccos(w + z)) / Cx(&2)`,
385   REWRITE_TAC[CCOS_ADD; CCOS_SUB] THEN CONV_TAC COMPLEX_RING);;
386
387 let COMPLEX_MUL_CSIN_CCOS = prove
388  (`!w z. csin(w) * ccos(z) = (csin(w + z) + csin(w - z)) / Cx(&2)`,
389   REWRITE_TAC[CSIN_ADD; CSIN_SUB] THEN CONV_TAC COMPLEX_RING);;
390
391 let COMPLEX_MUL_CCOS_CSIN = prove
392  (`!w z. ccos(w) * csin(z) = (csin(w + z) - csin(w - z)) / Cx(&2)`,
393   REWRITE_TAC[CSIN_ADD; CSIN_SUB] THEN CONV_TAC COMPLEX_RING);;
394
395 let COMPLEX_MUL_CCOS_CCOS = prove
396  (`!w z. ccos(w) * ccos(z) = (ccos(w - z) + ccos(w + z)) / Cx(&2)`,
397   REWRITE_TAC[CCOS_ADD; CCOS_SUB] THEN CONV_TAC COMPLEX_RING);;
398
399 let COMPLEX_ADD_CSIN = prove
400  (`!w z. csin(w) + csin(z) =
401          Cx(&2) * csin((w + z) / Cx(&2)) * ccos((w - z) / Cx(&2))`,
402   SIMP_TAC[COMPLEX_MUL_CSIN_CCOS; COMPLEX_RING `Cx(&2) * x / Cx(&2) = x`] THEN
403   REPEAT GEN_TAC THEN BINOP_TAC THEN AP_TERM_TAC THEN CONV_TAC COMPLEX_RING);;
404
405 let COMPLEX_SUB_CSIN = prove
406  (`!w z. csin(w) - csin(z) =
407          Cx(&2) * csin((w - z) / Cx(&2)) * ccos((w + z) / Cx(&2))`,
408   SIMP_TAC[COMPLEX_MUL_CSIN_CCOS; COMPLEX_RING `Cx(&2) * x / Cx(&2) = x`] THEN
409   REPEAT GEN_TAC THEN REWRITE_TAC[complex_sub; GSYM CSIN_NEG] THEN
410   BINOP_TAC THEN AP_TERM_TAC THEN CONV_TAC COMPLEX_RING);;
411
412 let COMPLEX_ADD_CCOS = prove
413  (`!w z. ccos(w) + ccos(z) =
414          Cx(&2) * ccos((w + z) / Cx(&2)) * ccos((w - z) / Cx(&2))`,
415   SIMP_TAC[COMPLEX_MUL_CCOS_CCOS; COMPLEX_RING `Cx(&2) * x / Cx(&2) = x`] THEN
416   REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [COMPLEX_ADD_SYM] THEN
417   BINOP_TAC THEN AP_TERM_TAC THEN CONV_TAC COMPLEX_RING);;
418
419 let COMPLEX_SUB_CCOS = prove
420  (`!w z. ccos(w) - ccos(z) =
421          Cx(&2) * csin((w + z) / Cx(&2)) * csin((z - w) / Cx(&2))`,
422   SIMP_TAC[COMPLEX_MUL_CSIN_CSIN; COMPLEX_RING `Cx(&2) * x / Cx(&2) = x`] THEN
423   REPEAT GEN_TAC THEN BINOP_TAC THEN AP_TERM_TAC THEN CONV_TAC COMPLEX_RING);;
424
425 let CCOS_DOUBLE_CCOS = prove
426  (`!z. ccos(Cx(&2) * z) = Cx(&2) * ccos z pow 2 - Cx(&1)`,
427   GEN_TAC THEN REWRITE_TAC[COMPLEX_RING `Cx(&2) * x = x + x`; CCOS_ADD] THEN
428   MP_TAC(SPEC `z:complex` CSIN_CIRCLE) THEN CONV_TAC COMPLEX_RING);;
429
430 let CCOS_DOUBLE_CSIN = prove
431  (`!z. ccos(Cx(&2) * z) = Cx(&1) - Cx(&2) * csin z pow 2`,
432   GEN_TAC THEN REWRITE_TAC[COMPLEX_RING `Cx(&2) * x = x + x`; CCOS_ADD] THEN
433   MP_TAC(SPEC `z:complex` CSIN_CIRCLE) THEN CONV_TAC COMPLEX_RING);;
434
435 (* ------------------------------------------------------------------------- *)
436 (* Euler and de Moivre formulas.                                             *)
437 (* ------------------------------------------------------------------------- *)
438
439 let CEXP_EULER = prove
440  (`!z. cexp(ii * z) = ccos(z) + ii * csin(z)`,
441   REWRITE_TAC[ccos; csin] THEN CONV_TAC COMPLEX_FIELD);;
442
443 let DEMOIVRE = prove
444  (`!z n. (ccos z + ii * csin z) pow n =
445          ccos(Cx(&n) * z) + ii * csin(Cx(&n) * z)`,
446   REWRITE_TAC[GSYM CEXP_EULER; GSYM CEXP_N] THEN
447   REWRITE_TAC[COMPLEX_MUL_AC]);;
448
449 (* ------------------------------------------------------------------------- *)
450 (* Real exponential function. Same names as old Library/transc.ml.           *)
451 (* ------------------------------------------------------------------------- *)
452
453 let exp = new_definition `exp(x) = Re(cexp(Cx x))`;;
454
455 let CNJ_CEXP = prove
456  (`!z. cnj(cexp z) = cexp(cnj z)`,
457   GEN_TAC THEN MATCH_MP_TAC SERIES_UNIQUE THEN
458   MAP_EVERY EXISTS_TAC [`\n. cnj(z pow n / Cx(&(FACT n)))`; `from 0`] THEN
459   CONJ_TAC THENL
460    [REWRITE_TAC[SUMS_CNJ; CEXP_CONVERGES];
461     REWRITE_TAC[CNJ_DIV; CNJ_CX; CNJ_POW; CEXP_CONVERGES]]);;
462
463 let REAL_EXP = prove
464  (`!z. real z ==> real(cexp z)`,
465   SIMP_TAC[REAL_CNJ; CNJ_CEXP]);;
466
467 let CX_EXP = prove
468  (`!x. Cx(exp x) = cexp(Cx x)`,
469   REWRITE_TAC[exp] THEN MESON_TAC[REAL; REAL_CX; REAL_EXP]);;
470
471 let REAL_EXP_ADD = prove
472  (`!x y. exp(x + y) = exp(x) * exp(y)`,
473   REWRITE_TAC[GSYM CX_INJ; CX_MUL; CX_EXP; CX_ADD; CEXP_ADD]);;
474
475 let REAL_EXP_0 = prove
476  (`exp(&0) = &1`,
477   REWRITE_TAC[GSYM CX_INJ; CX_EXP; CEXP_0]);;
478
479 let REAL_EXP_ADD_MUL = prove
480  (`!x y. exp(x + y) * exp(--x) = exp(y)`,
481   ONCE_REWRITE_TAC[REAL_ADD_SYM] THEN
482   REWRITE_TAC[GSYM CX_INJ; CX_MUL; CX_EXP; CX_ADD; CX_NEG; CEXP_ADD_MUL]);;
483
484 let REAL_EXP_NEG_MUL = prove
485  (`!x. exp(x) * exp(--x) = &1`,
486   REWRITE_TAC[GSYM CX_INJ; CX_MUL; CX_EXP; CX_NEG; CEXP_NEG_RMUL]);;
487
488 let REAL_EXP_NEG_MUL2 = prove
489  (`!x. exp(--x) * exp(x) = &1`,
490   REWRITE_TAC[GSYM CX_INJ; CX_MUL; CX_EXP; CX_NEG; CEXP_NEG_LMUL]);;
491
492 let REAL_EXP_NEG = prove
493  (`!x. exp(--x) = inv(exp(x))`,
494   REWRITE_TAC[GSYM CX_INJ; CX_INV; CX_EXP; CX_NEG; CEXP_NEG]);;
495
496 let REAL_EXP_N = prove
497  (`!n x. exp(&n * x) = exp(x) pow n`,
498   REWRITE_TAC[GSYM CX_INJ; CX_EXP; CX_POW; CX_MUL; CEXP_N]);;
499
500 let REAL_EXP_SUB = prove
501  (`!x y. exp(x - y) = exp(x) / exp(y)`,
502   REWRITE_TAC[GSYM CX_INJ; CX_SUB; CX_DIV; CX_EXP; CEXP_SUB]);;
503
504 let REAL_EXP_NZ = prove
505  (`!x. ~(exp(x) = &0)`,
506   REWRITE_TAC[GSYM CX_INJ; CX_EXP; CEXP_NZ]);;
507
508 let REAL_EXP_POS_LE = prove
509  (`!x. &0 <= exp(x)`,
510   GEN_TAC THEN SUBST1_TAC(REAL_ARITH `x = x / &2 + x / &2`) THEN
511   REWRITE_TAC[REAL_EXP_ADD; REAL_LE_SQUARE]);;
512
513 let REAL_EXP_POS_LT = prove
514  (`!x. &0 < exp(x)`,
515   REWRITE_TAC[REAL_LT_LE; REAL_EXP_NZ; REAL_EXP_POS_LE]);;
516
517 let REAL_EXP_LE_X = prove
518  (`!x. &1 + x <= exp(x)`,
519   GEN_TAC THEN ASM_CASES_TAC `&1 + x < &0` THENL
520    [MP_TAC(SPEC `x:real` REAL_EXP_POS_LT) THEN ASM_REAL_ARITH_TAC;
521     ALL_TAC] THEN
522   REWRITE_TAC[exp; RE_DEF] THEN
523   MATCH_MP_TAC(MATCH_MP
524    (ONCE_REWRITE_RULE[TAUT `a /\ b /\ c ==> d <=> b ==> a /\ c ==> d`]
525         LIM_COMPONENT_LBOUND)
526    (REWRITE_RULE[sums] (SPEC `Cx x` CEXP_CONVERGES))) THEN
527   SIMP_TAC[DIMINDEX_2; ARITH; TRIVIAL_LIMIT_SEQUENTIALLY;
528            VSUM_COMPONENT; EVENTUALLY_SEQUENTIALLY; FROM_0; INTER_UNIV] THEN
529   REWRITE_TAC[GSYM CX_DIV; GSYM RE_DEF; RE_CX; GSYM CX_POW] THEN
530   EXISTS_TAC `1` THEN SIMP_TAC[SUM_CLAUSES_LEFT; LE_0; ADD_CLAUSES] THEN
531   CONV_TAC NUM_REDUCE_CONV THEN
532   SIMP_TAC[real_pow; REAL_POW_1; REAL_DIV_1; REAL_LE_ADDR; REAL_ADD_ASSOC] THEN
533   SUBGOAL_THEN
534    `!n. &0 <= sum(2*1..2*n+1) (\k. x pow k / &(FACT k))`
535   ASSUME_TAC THENL
536    [GEN_TAC THEN REWRITE_TAC[SUM_PAIR] THEN
537     MATCH_MP_TAC SUM_POS_LE_NUMSEG THEN X_GEN_TAC `k:num` THEN STRIP_TAC THEN
538     REWRITE_TAC[GSYM ADD1; real_pow; FACT; GSYM REAL_OF_NUM_MUL] THEN
539     ASM_SIMP_TAC[REAL_OF_NUM_EQ; FACT_NZ; NOT_SUC; REAL_FIELD
540      `~(k = &0) /\ ~(f = &0)
541       ==> p / f + (x * p) / (k * f) = p / f * (&1 + x / k)`] THEN
542     MATCH_MP_TAC REAL_LE_MUL THEN CONJ_TAC THENL
543      [ALL_TAC;
544       REWRITE_TAC[REAL_ARITH `&0 <= a + b <=> --a <= b`] THEN
545       ASM_SIMP_TAC[REAL_LE_RDIV_EQ; LT_0; REAL_OF_NUM_LT] THEN
546       REWRITE_TAC[GSYM REAL_OF_NUM_SUC] THEN ASM_REAL_ARITH_TAC];
547     RULE_ASSUM_TAC(REWRITE_RULE[MULT_CLAUSES]) THEN
548     X_GEN_TAC `n:num` THEN DISCH_TAC THEN
549     MP_TAC(SPEC `n - 1` EVEN_OR_ODD) THEN
550     ASM_SIMP_TAC[EVEN_EXISTS; ODD_EXISTS;
551                  ARITH_RULE `1 <= n ==> (n - 1 = d <=> n = SUC d)`] THEN
552     STRIP_TAC THENL [ASM_MESON_TAC[ADD1]; ALL_TAC] THEN
553     ASM_REWRITE_TAC[ARITH_RULE `SUC(2 * n) = 2 * n + 1`] THEN
554     ASM_REWRITE_TAC[SUM_CLAUSES_NUMSEG] THEN
555     COND_CASES_TAC THENL [ALL_TAC; ASM_ARITH_TAC] THEN
556     MATCH_MP_TAC REAL_LE_ADD THEN
557     ASM_REWRITE_TAC[ARITH_RULE `SUC(2 * m + 1) = 2 * (m + 1)`]] THEN
558   MATCH_MP_TAC REAL_LE_DIV THEN REWRITE_TAC[REAL_POS] THEN
559   ASM_SIMP_TAC[GSYM REAL_POW_POW; REAL_POW_LE; REAL_LE_POW_2]);;
560
561 let REAL_EXP_LT_1 = prove
562  (`!x. &0 < x ==> &1 < exp(x)`,
563   MP_TAC REAL_EXP_LE_X THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
564
565 let REAL_EXP_MONO_IMP = prove
566  (`!x y. x < y ==> exp(x) < exp(y)`,
567   REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_SUB_LT] THEN
568   DISCH_THEN(MP_TAC o MATCH_MP REAL_EXP_LT_1) THEN
569   SIMP_TAC[REAL_EXP_SUB; REAL_LT_RDIV_EQ; REAL_EXP_POS_LT; REAL_MUL_LID]);;
570
571 let REAL_EXP_MONO_LT = prove
572  (`!x y. exp(x) < exp(y) <=> x < y`,
573   REPEAT GEN_TAC THEN MATCH_MP_TAC(REAL_ARITH
574    `(x < y ==> f < g) /\ (x = y ==> f = g) /\ (y < x ==> g < f)
575     ==> (f < g <=> x < y)`) THEN
576   SIMP_TAC[REAL_EXP_MONO_IMP]);;
577
578 let REAL_EXP_MONO_LE = prove
579  (`!x y. exp(x) <= exp(y) <=> x <= y`,
580   REWRITE_TAC[GSYM REAL_NOT_LT; REAL_EXP_MONO_LT]);;
581
582 let REAL_EXP_INJ = prove
583  (`!x y. (exp(x) = exp(y)) <=> (x = y)`,
584   REWRITE_TAC[GSYM REAL_LE_ANTISYM; REAL_EXP_MONO_LE]);;
585
586 let REAL_EXP_EQ_1 = prove
587  (`!x. exp(x) = &1 <=> x = &0`,
588   ONCE_REWRITE_TAC[GSYM REAL_EXP_0] THEN REWRITE_TAC[REAL_EXP_INJ]);;
589
590 let REAL_ABS_EXP = prove
591  (`!x. abs(exp x) = exp x`,
592   REWRITE_TAC[real_abs; REAL_EXP_POS_LE]);;
593
594 let REAL_EXP_SUM = prove
595  (`!f s. FINITE s ==> exp(sum s f) = product s (\x. exp(f x))`,
596   GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
597   SIMP_TAC[SUM_CLAUSES; PRODUCT_CLAUSES; REAL_EXP_ADD; REAL_EXP_0]);;
598
599 let REAL_EXP_BOUND_LEMMA = prove
600  (`!x. &0 <= x /\ x <= inv(&2) ==> exp(x) <= &1 + &2 * x`,
601   REPEAT STRIP_TAC THEN MP_TAC(SPEC `Cx x` CEXP_BOUND_LEMMA) THEN
602   REWRITE_TAC[GSYM CX_EXP; COMPLEX_NORM_CX; RE_CX] THEN
603   ASM_REAL_ARITH_TAC);;
604
605 (* ------------------------------------------------------------------------- *)
606 (* Real trig functions, their reality,  derivatives of complex versions.     *)
607 (* ------------------------------------------------------------------------- *)
608
609 let sin = new_definition `sin(x) = Re(csin(Cx x))`;;
610
611 let cos = new_definition `cos(x) = Re(ccos(Cx x))`;;
612
613 let CNJ_CSIN = prove
614  (`!z. cnj(csin z) = csin(cnj z)`,
615   REWRITE_TAC[csin; CNJ_DIV; CNJ_SUB; CNJ_MUL; CNJ_CX; CNJ_CEXP;
616               CNJ_NEG; CNJ_II; COMPLEX_NEG_NEG] THEN
617   CONV_TAC COMPLEX_FIELD);;
618
619 let CNJ_CCOS = prove
620  (`!z. cnj(ccos z) = ccos(cnj z)`,
621   REWRITE_TAC[ccos; CNJ_DIV; CNJ_ADD; CNJ_MUL; CNJ_CX; CNJ_CEXP;
622               CNJ_NEG; CNJ_II; COMPLEX_NEG_NEG; COMPLEX_ADD_AC]);;
623
624 let REAL_SIN = prove
625  (`!z. real z ==> real(csin z)`,
626   SIMP_TAC[REAL_CNJ; CNJ_CSIN]);;
627
628 let REAL_COS = prove
629  (`!z. real z ==> real(ccos z)`,
630   SIMP_TAC[REAL_CNJ; CNJ_CCOS]);;
631
632 let CX_SIN = prove
633  (`!x. Cx(sin x) = csin(Cx x)`,
634   REWRITE_TAC[sin] THEN MESON_TAC[REAL; REAL_CX; REAL_SIN]);;
635
636 let CX_COS = prove
637  (`!x. Cx(cos x) = ccos(Cx x)`,
638   REWRITE_TAC[cos] THEN MESON_TAC[REAL; REAL_CX; REAL_COS]);;
639
640 let HAS_COMPLEX_DERIVATIVE_CSIN = prove
641  (`!z. (csin has_complex_derivative ccos z) (at z)`,
642   GEN_TAC THEN GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM ETA_AX] THEN
643   REWRITE_TAC[csin; ccos] THEN COMPLEX_DIFF_TAC THEN
644   CONV_TAC COMPLEX_FIELD);;
645
646 let COMPLEX_DIFFERENTIABLE_AT_CSIN = prove
647  (`!z. csin complex_differentiable at z`,
648   REWRITE_TAC[complex_differentiable] THEN
649   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CSIN]);;
650
651 let COMPLEX_DIFFERENTIABLE_WITHIN_CSIN = prove
652  (`!s z. csin complex_differentiable (at z within s)`,
653   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
654             COMPLEX_DIFFERENTIABLE_AT_CSIN]);;
655
656 add_complex_differentiation_theorems
657  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
658    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN_UNIV
659              HAS_COMPLEX_DERIVATIVE_CSIN)));;
660
661 let HAS_COMPLEX_DERIVATIVE_CCOS = prove
662  (`!z. (ccos has_complex_derivative --csin z) (at z)`,
663   GEN_TAC THEN GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM ETA_AX] THEN
664   REWRITE_TAC[csin; ccos] THEN COMPLEX_DIFF_TAC THEN
665   CONV_TAC COMPLEX_FIELD);;
666
667 let COMPLEX_DIFFERENTIABLE_AT_CCOS = prove
668  (`!z. ccos complex_differentiable at z`,
669   REWRITE_TAC[complex_differentiable] THEN
670   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CCOS]);;
671
672 let COMPLEX_DIFFERENTIABLE_WITHIN_CCOS = prove
673  (`!s z. ccos complex_differentiable (at z within s)`,
674   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
675             COMPLEX_DIFFERENTIABLE_AT_CCOS]);;
676
677 add_complex_differentiation_theorems
678  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
679    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN_UNIV
680              HAS_COMPLEX_DERIVATIVE_CCOS)));;
681
682 let CONTINUOUS_AT_CSIN = prove
683  (`!z. csin continuous at z`,
684   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CSIN;
685             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
686
687 let CONTINUOUS_WITHIN_CSIN = prove
688  (`!s z. csin continuous (at z within s)`,
689   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CSIN]);;
690
691 let CONTINUOUS_ON_CSIN = prove
692  (`!s. csin continuous_on s`,
693   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CSIN]);;
694
695 let HOLOMORPHIC_ON_CSIN = prove
696  (`!s. csin holomorphic_on s`,
697   REWRITE_TAC [holomorphic_on] THEN
698   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CSIN]);;
699
700 let CONTINUOUS_AT_CCOS = prove
701  (`!z. ccos continuous at z`,
702   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CCOS;
703             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
704
705 let CONTINUOUS_WITHIN_CCOS = prove
706  (`!s z. ccos continuous (at z within s)`,
707   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CCOS]);;
708
709 let CONTINUOUS_ON_CCOS = prove
710  (`!s. ccos continuous_on s`,
711   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CCOS]);;
712
713 let HOLOMORPHIC_ON_CCOS = prove
714  (`!s. ccos holomorphic_on s`,
715   REWRITE_TAC [holomorphic_on] THEN
716   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CCOS]);;
717
718 (* ------------------------------------------------------------------------- *)
719 (* Slew of theorems for compatibility with old transc.ml file.               *)
720 (* ------------------------------------------------------------------------- *)
721
722 let SIN_0 = prove
723  (`sin(&0) = &0`,
724   REWRITE_TAC[GSYM CX_INJ; CX_SIN; CSIN_0]);;
725
726 let COS_0 = prove
727  (`cos(&0) = &1`,
728   REWRITE_TAC[GSYM CX_INJ; CX_COS; CCOS_0]);;
729
730 let SIN_CIRCLE = prove
731  (`!x. (sin(x) pow 2) + (cos(x) pow 2) = &1`,
732   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_POW; CSIN_CIRCLE]);;
733
734 let SIN_ADD = prove
735  (`!x y. sin(x + y) = sin(x) * cos(y) + cos(x) * sin(y)`,
736   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_MUL; CSIN_ADD]);;
737
738 let COS_ADD = prove
739  (`!x y. cos(x + y) = cos(x) * cos(y) - sin(x) * sin(y)`,
740   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CCOS_ADD]);;
741
742 let SIN_NEG = prove
743  (`!x. sin(--x) = --(sin(x))`,
744   REWRITE_TAC[GSYM CX_INJ; CX_SIN; CX_NEG; CSIN_NEG]);;
745
746 let COS_NEG = prove
747  (`!x. cos(--x) = cos(x)`,
748   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_NEG; CCOS_NEG]);;
749
750 let SIN_DOUBLE = prove
751  (`!x. sin(&2 * x) = &2 * sin(x) * cos(x)`,
752   REWRITE_TAC[GSYM CX_INJ; CX_SIN; CX_COS; CX_MUL; CSIN_DOUBLE]);;
753
754 let COS_DOUBLE = prove
755  (`!x. cos(&2 * x) = (cos(x) pow 2) - (sin(x) pow 2)`,
756   SIMP_TAC[GSYM CX_INJ; CX_SIN; CX_COS; CX_SUB; CX_MUL; CX_POW; CCOS_DOUBLE]);;
757
758 let COS_DOUBLE_COS = prove
759  (`!x. cos(&2 * x) = &2 * cos(x) pow 2 - &1`,
760   MP_TAC SIN_CIRCLE THEN MATCH_MP_TAC MONO_FORALL THEN
761   REWRITE_TAC[COS_DOUBLE] THEN REAL_ARITH_TAC);;
762
763 let (SIN_BOUND,COS_BOUND) = (CONJ_PAIR o prove)
764  (`(!x. abs(sin x) <= &1) /\ (!x. abs(cos x) <= &1)`,
765   CONJ_TAC THEN GEN_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_ABS_NUM] THEN
766   ONCE_REWRITE_TAC[REAL_LE_SQUARE_ABS] THEN
767   MP_TAC(SPEC `x:real` SIN_CIRCLE) THEN
768   MAP_EVERY (MP_TAC o C SPEC REAL_LE_SQUARE) [`sin x`; `cos x`] THEN
769   REAL_ARITH_TAC);;
770
771 let SIN_BOUNDS = prove
772  (`!x. --(&1) <= sin(x) /\ sin(x) <= &1`,
773   MP_TAC SIN_BOUND THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
774
775 let COS_BOUNDS = prove
776  (`!x. --(&1) <= cos(x) /\ cos(x) <= &1`,
777   MP_TAC COS_BOUND THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
778
779 let COS_ABS = prove
780  (`!x. cos(abs x) = cos(x)`,
781   REWRITE_TAC[real_abs] THEN MESON_TAC[COS_NEG]);;
782
783 let SIN_SUB = prove
784  (`!w z. sin(w - z) = sin(w) * cos(z) - cos(w) * sin(z)`,
785   REWRITE_TAC[GSYM CX_INJ; CX_SIN; CX_COS; CX_SUB; CX_MUL; CSIN_SUB]);;
786
787 let COS_SUB = prove
788  (`!w z. cos(w - z) = cos(w) * cos(z) + sin(w) * sin(z)`,
789   REWRITE_TAC[GSYM CX_INJ; CX_SIN; CX_COS; CX_SUB; CX_ADD; CX_MUL; CCOS_SUB]);;
790
791 let REAL_MUL_SIN_SIN = prove
792  (`!x y. sin(x) * sin(y) = (cos(x - y) - cos(x + y)) / &2`,
793   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
794   REWRITE_TAC[COMPLEX_MUL_CSIN_CSIN]);;
795
796 let REAL_MUL_SIN_COS = prove
797  (`!x y. sin(x) * cos(y) = (sin(x + y) + sin(x - y)) / &2`,
798   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
799   REWRITE_TAC[COMPLEX_MUL_CSIN_CCOS]);;
800
801 let REAL_MUL_COS_SIN = prove
802  (`!x y. cos(x) * sin(y) = (sin(x + y) - sin(x - y)) / &2`,
803   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
804   REWRITE_TAC[COMPLEX_MUL_CCOS_CSIN]);;
805
806 let REAL_MUL_COS_COS = prove
807  (`!x y. cos(x) * cos(y) = (cos(x - y) + cos(x + y)) / &2`,
808   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
809   REWRITE_TAC[COMPLEX_MUL_CCOS_CCOS]);;
810
811 let REAL_ADD_SIN = prove
812  (`!x y. sin(x) + sin(y) = &2 * sin((x + y) / &2) * cos((x - y) / &2)`,
813   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
814   REWRITE_TAC[COMPLEX_ADD_CSIN]);;
815
816 let REAL_SUB_SIN = prove
817  (`!x y. sin(x) - sin(y) = &2 * sin((x - y) / &2) * cos((x + y) / &2)`,
818   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
819   REWRITE_TAC[COMPLEX_SUB_CSIN]);;
820
821 let REAL_ADD_COS = prove
822  (`!x y. cos(x) + cos(y) = &2 * cos((x + y) / &2) * cos((x - y) / &2)`,
823   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
824   REWRITE_TAC[COMPLEX_ADD_CCOS]);;
825
826 let REAL_SUB_COS = prove
827  (`!x y. cos(x) - cos(y) = &2 * sin((x + y) / &2) * sin((y - x) / &2)`,
828   REWRITE_TAC[GSYM CX_INJ; CX_COS; CX_SIN; CX_ADD; CX_SUB; CX_MUL; CX_DIV] THEN
829   REWRITE_TAC[COMPLEX_SUB_CCOS]);;
830
831 let COS_DOUBLE_SIN = prove
832  (`!x. cos(&2 * x) = &1 - &2 * sin x pow 2`,
833   GEN_TAC THEN REWRITE_TAC[REAL_RING `&2 * x = x + x`; COS_ADD] THEN
834   MP_TAC(SPEC `x:real` SIN_CIRCLE) THEN CONV_TAC REAL_RING);;
835
836 (* ------------------------------------------------------------------------- *)
837 (* Get a nice real/imaginary separation in Euler's formula.                  *)
838 (* ------------------------------------------------------------------------- *)
839
840 let EULER = prove
841  (`!z. cexp(z) = Cx(exp(Re z)) * (Cx(cos(Im z)) + ii * Cx(sin(Im z)))`,
842   GEN_TAC THEN GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [COMPLEX_EXPAND] THEN
843   REWRITE_TAC[CEXP_ADD; CEXP_EULER; GSYM CX_SIN; GSYM CX_COS; GSYM CX_EXP]);;
844
845 let RE_CEXP = prove
846  (`!z. Re(cexp z) = exp(Re z) * cos(Im z)`,
847   REWRITE_TAC[EULER; RE_ADD; RE_MUL_CX; RE_MUL_II; IM_CX; RE_CX] THEN
848   REAL_ARITH_TAC);;
849
850 let IM_CEXP = prove
851  (`!z. Im(cexp z) = exp(Re z) * sin(Im z)`,
852   REWRITE_TAC[EULER; IM_ADD; IM_MUL_CX; IM_MUL_II; IM_CX; RE_CX] THEN
853   REAL_ARITH_TAC);;
854
855 let RE_CSIN = prove
856  (`!z. Re(csin z) = (exp(Im z) + exp(--(Im z))) / &2 * sin(Re z)`,
857   GEN_TAC THEN REWRITE_TAC[csin] THEN
858   SIMP_TAC[COMPLEX_FIELD `x / (Cx(&2) * ii) = ii * --(x / Cx(&2))`] THEN
859   REWRITE_TAC[IM_MUL_II; IM_DIV_CX; RE_NEG; IM_SUB; IM_CEXP;
860               RE_MUL_II; COMPLEX_MUL_LNEG; IM_NEG] THEN
861   REWRITE_TAC[REAL_NEG_NEG; SIN_NEG] THEN CONV_TAC REAL_RING);;
862
863 let IM_CSIN = prove
864  (`!z. Im(csin z) = (exp(Im z) - exp(--(Im z))) / &2 * cos(Re z)`,
865   GEN_TAC THEN REWRITE_TAC[csin] THEN
866   SIMP_TAC[COMPLEX_FIELD `x / (Cx(&2) * ii) = ii * --(x / Cx(&2))`] THEN
867   REWRITE_TAC[IM_MUL_II; RE_DIV_CX; RE_NEG; RE_SUB; RE_CEXP;
868               RE_MUL_II; COMPLEX_MUL_LNEG; IM_NEG] THEN
869   REWRITE_TAC[REAL_NEG_NEG; COS_NEG] THEN CONV_TAC REAL_RING);;
870
871 let RE_CCOS = prove
872  (`!z. Re(ccos z) = (exp(Im z) + exp(--(Im z))) / &2 * cos(Re z)`,
873   GEN_TAC THEN REWRITE_TAC[ccos] THEN
874   REWRITE_TAC[RE_DIV_CX; RE_ADD; RE_CEXP; COMPLEX_MUL_LNEG;
875               RE_MUL_II; IM_MUL_II; RE_NEG; IM_NEG; COS_NEG] THEN
876   REWRITE_TAC[REAL_NEG_NEG] THEN CONV_TAC REAL_RING);;
877
878 let IM_CCOS = prove
879  (`!z. Im(ccos z) = (exp(--(Im z)) - exp(Im z)) / &2 * sin(Re z)`,
880   GEN_TAC THEN REWRITE_TAC[ccos] THEN
881   REWRITE_TAC[IM_DIV_CX; IM_ADD; IM_CEXP; COMPLEX_MUL_LNEG;
882               RE_MUL_II; IM_MUL_II; RE_NEG; IM_NEG; SIN_NEG] THEN
883   REWRITE_TAC[REAL_NEG_NEG] THEN CONV_TAC REAL_RING);;
884
885 (* ------------------------------------------------------------------------- *)
886 (* Some special intermediate value theorems over the reals.                  *)
887 (* ------------------------------------------------------------------------- *)
888
889 let IVT_INCREASING_RE = prove
890  (`!f a b y.
891         a <= b /\
892         (!x. a <= x /\ x <= b ==> f continuous at (Cx x)) /\
893         Re(f(Cx a)) <= y /\ y <= Re(f(Cx b))
894         ==> ?x. a <= x /\ x <= b /\ Re(f(Cx x)) = y`,
895   REPEAT STRIP_TAC THEN
896   MP_TAC(ISPECL [`(f:complex->complex) o Cx o drop`;
897                  `lift a`; `lift b`; `y:real`; `1`]
898         IVT_INCREASING_COMPONENT_1) THEN
899   REWRITE_TAC[EXISTS_DROP; GSYM drop; LIFT_DROP; o_THM; GSYM RE_DEF] THEN
900   ASM_REWRITE_TAC[IN_INTERVAL_1; GSYM CONJ_ASSOC; LIFT_DROP] THEN
901   DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[DIMINDEX_2; ARITH] THEN
902   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
903   ASM_SIMP_TAC[o_THM] THEN REWRITE_TAC[continuous_at; o_THM] THEN
904   REWRITE_TAC[dist; GSYM CX_SUB; GSYM DROP_SUB; COMPLEX_NORM_CX] THEN
905   REWRITE_TAC[GSYM ABS_DROP] THEN MESON_TAC[]);;
906
907 let IVT_DECREASING_RE = prove
908  (`!f a b y.
909         a <= b /\
910         (!x. a <= x /\ x <= b ==> f continuous at (Cx x)) /\
911         Re(f(Cx b)) <= y /\ y <= Re(f(Cx a))
912         ==> ?x. a <= x /\ x <= b /\ Re(f(Cx x)) = y`,
913   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EQ_NEG2] THEN
914   REWRITE_TAC[GSYM RE_NEG] THEN MATCH_MP_TAC IVT_INCREASING_RE THEN
915   ASM_SIMP_TAC[CONTINUOUS_NEG; RE_NEG; REAL_LE_NEG2]);;
916
917 let IVT_INCREASING_IM = prove
918  (`!f a b y.
919         a <= b /\
920         (!x. a <= x /\ x <= b ==> f continuous at (Cx x)) /\
921         Im(f(Cx a)) <= y /\ y <= Im(f(Cx b))
922         ==> ?x. a <= x /\ x <= b /\ Im(f(Cx x)) = y`,
923   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EQ_NEG2] THEN
924   REWRITE_TAC[SYM(CONJUNCT2(SPEC_ALL RE_MUL_II))] THEN
925   MATCH_MP_TAC IVT_DECREASING_RE THEN
926   ASM_SIMP_TAC[CONTINUOUS_COMPLEX_MUL; ETA_AX; CONTINUOUS_CONST] THEN
927   ASM_REWRITE_TAC[RE_MUL_II; REAL_LE_NEG2]);;
928
929 let IVT_DECREASING_IM = prove
930  (`!f a b y.
931         a <= b /\
932         (!x. a <= x /\ x <= b ==> f continuous at (Cx x)) /\
933         Im(f(Cx b)) <= y /\ y <= Im(f(Cx a))
934         ==> ?x. a <= x /\ x <= b /\ Im(f(Cx x)) = y`,
935   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EQ_NEG2] THEN
936   REWRITE_TAC[GSYM IM_NEG] THEN MATCH_MP_TAC IVT_INCREASING_IM THEN
937   ASM_SIMP_TAC[CONTINUOUS_NEG; IM_NEG; REAL_LE_NEG2]);;
938
939 (* ------------------------------------------------------------------------- *)
940 (* Some minimal properties of real logs help to define complex logs.         *)
941 (* ------------------------------------------------------------------------- *)
942
943 let log_def = new_definition
944  `log y = @x. exp(x) = y`;;
945
946 let EXP_LOG = prove
947  (`!x. &0 < x ==> exp(log x) = x`,
948   REPEAT STRIP_TAC THEN REWRITE_TAC[log_def] THEN CONV_TAC SELECT_CONV THEN
949   SUBGOAL_THEN `?y. --inv(x) <= y /\ y <= x /\ Re(cexp(Cx y)) = x`
950   MP_TAC THENL [ALL_TAC; MESON_TAC[CX_EXP; RE_CX]] THEN
951   MATCH_MP_TAC IVT_INCREASING_RE THEN
952   SIMP_TAC[GSYM CX_EXP; RE_CX; CONTINUOUS_AT_CEXP] THEN REPEAT CONJ_TAC THENL
953    [MATCH_MP_TAC(REAL_ARITH `&0 < x /\ &0 < y ==> --y <= x`) THEN
954     ASM_SIMP_TAC[REAL_LT_INV_EQ];
955     ONCE_REWRITE_TAC[GSYM REAL_INV_INV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
956     ASM_REWRITE_TAC[REAL_EXP_NEG; REAL_INV_INV; REAL_LT_INV_EQ];
957     ALL_TAC] THEN
958   MATCH_MP_TAC(REAL_ARITH `&1 + x <= y ==> x <= y`) THEN
959   ASM_SIMP_TAC[REAL_EXP_LE_X; REAL_LE_INV_EQ; REAL_LT_IMP_LE]);;
960
961 let LOG_EXP = prove
962  (`!x. log(exp x) = x`,
963   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EXP_INJ] THEN
964   SIMP_TAC[EXP_LOG; REAL_EXP_POS_LT]);;
965
966 let REAL_EXP_LOG = prove
967  (`!x. (exp(log x) = x) <=> &0 < x`,
968   MESON_TAC[EXP_LOG; REAL_EXP_POS_LT]);;
969
970 let LOG_MUL = prove
971  (`!x y. &0 < x /\ &0 < y ==> (log(x * y) = log(x) + log(y))`,
972   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EXP_INJ] THEN
973   ASM_SIMP_TAC[REAL_EXP_ADD; REAL_LT_MUL; EXP_LOG]);;
974
975 let LOG_INJ = prove
976  (`!x y. &0 < x /\ &0 < y ==> (log(x) = log(y) <=> x = y)`,
977   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_EXP_INJ] THEN
978   ASM_SIMP_TAC[EXP_LOG]);;
979
980 let LOG_1 = prove
981  (`log(&1) = &0`,
982   ONCE_REWRITE_TAC[GSYM REAL_EXP_INJ] THEN
983   REWRITE_TAC[REAL_EXP_0; REAL_EXP_LOG; REAL_LT_01]);;
984
985 let LOG_INV = prove
986  (`!x. &0 < x ==> (log(inv x) = --(log x))`,
987   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EXP_INJ] THEN
988   ASM_SIMP_TAC[REAL_EXP_NEG; EXP_LOG; REAL_LT_INV_EQ]);;
989
990 let LOG_DIV = prove
991  (`!x y. &0 < x /\ &0 < y ==> log(x / y) = log(x) - log(y)`,
992   SIMP_TAC[real_div; real_sub; LOG_MUL; LOG_INV; REAL_LT_INV_EQ]);;
993
994 let LOG_MONO_LT = prove
995  (`!x y. &0 < x /\ &0 < y ==> (log(x) < log(y) <=> x < y)`,
996   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_EXP_MONO_LT] THEN
997   ASM_SIMP_TAC[EXP_LOG]);;
998
999 let LOG_MONO_LT_IMP = prove
1000  (`!x y. &0 < x /\ x < y ==> log(x) < log(y)`,
1001   MESON_TAC[LOG_MONO_LT; REAL_LT_TRANS]);;
1002
1003 let LOG_MONO_LT_REV = prove
1004  (`!x y. &0 < x /\ &0 < y /\ log x < log y ==> x < y`,
1005   MESON_TAC[LOG_MONO_LT]);;
1006
1007 let LOG_MONO_LE = prove
1008  (`!x y. &0 < x /\ &0 < y ==> (log(x) <= log(y) <=> x <= y)`,
1009   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM REAL_EXP_MONO_LE] THEN
1010   ASM_SIMP_TAC[EXP_LOG]);;
1011
1012 let LOG_MONO_LE_IMP = prove
1013  (`!x y. &0 < x /\ x <= y ==> log(x) <= log(y)`,
1014   MESON_TAC[LOG_MONO_LE; REAL_LT_IMP_LE; REAL_LTE_TRANS]);;
1015
1016 let LOG_MONO_LE_REV = prove
1017  (`!x y. &0 < x /\ &0 < y /\ log x <= log y ==> x <= y`,
1018   MESON_TAC[LOG_MONO_LE]);;
1019
1020 let LOG_POW = prove
1021  (`!n x. &0 < x ==> (log(x pow n) = &n * log(x))`,
1022   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EXP_INJ] THEN
1023   ASM_SIMP_TAC[REAL_EXP_N; EXP_LOG; REAL_POW_LT]);;
1024
1025 let LOG_LE_STRONG = prove
1026  (`!x. &0 < &1 + x ==> log(&1 + x) <= x`,
1027   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EXP_MONO_LE] THEN
1028   ASM_SIMP_TAC[EXP_LOG; REAL_EXP_LE_X]);;
1029
1030 let LOG_LE = prove
1031  (`!x. &0 <= x ==> log(&1 + x) <= x`,
1032   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EXP_MONO_LE] THEN
1033   ASM_SIMP_TAC[EXP_LOG; REAL_ARITH `&0 <= x ==> &0 < &1 + x`; REAL_EXP_LE_X]);;
1034
1035 let LOG_LT_X = prove
1036  (`!x. &0 < x ==> log(x) < x`,
1037   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EXP_MONO_LT] THEN
1038   ASM_SIMP_TAC[EXP_LOG] THEN MP_TAC(SPEC `x:real` REAL_EXP_LE_X) THEN
1039   POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
1040
1041 let LOG_POS = prove
1042  (`!x. &1 <= x ==> &0 <= log(x)`,
1043   REWRITE_TAC[GSYM LOG_1] THEN
1044   SIMP_TAC[LOG_MONO_LE; ARITH_RULE `&1 <= x ==> &0 < x`; REAL_LT_01]);;
1045
1046 let LOG_POS_LT = prove
1047  (`!x. &1 < x ==> &0 < log(x)`,
1048   REWRITE_TAC[GSYM LOG_1] THEN
1049   SIMP_TAC[LOG_MONO_LT; ARITH_RULE `&1 < x ==> &0 < x`; REAL_LT_01]);;
1050
1051 let LOG_PRODUCT = prove
1052  (`!f:A->real s.
1053         FINITE s /\ (!x. x IN s ==> &0 < f x)
1054         ==> log(product s f) = sum s (\x. log(f x))`,
1055   GEN_TAC THEN REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
1056   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
1057   SIMP_TAC[PRODUCT_CLAUSES; SUM_CLAUSES; LOG_1; FORALL_IN_INSERT; LOG_MUL;
1058            PRODUCT_POS_LT]);;
1059
1060 (* ------------------------------------------------------------------------- *)
1061 (* Deduce periodicity just from derivative and zero values.                  *)
1062 (* ------------------------------------------------------------------------- *)
1063
1064 let SIN_NEARZERO = prove
1065  (`?x. &0 < x /\ !y. &0 < y /\ y <= x ==> &0 < sin(y)`,
1066   MP_TAC(SPEC `&1 / &2` (CONJUNCT2
1067    (REWRITE_RULE[has_complex_derivative; HAS_DERIVATIVE_AT_ALT]
1068     (ISPEC `Cx(&0)` HAS_COMPLEX_DERIVATIVE_CSIN)))) THEN
1069   CONV_TAC REAL_RAT_REDUCE_CONV THEN
1070   REWRITE_TAC[CSIN_0; COMPLEX_SUB_RZERO; CCOS_0; COMPLEX_MUL_LZERO;
1071               COMPLEX_MUL_LID] THEN
1072   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
1073   EXISTS_TAC `d / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
1074   X_GEN_TAC `y:real` THEN STRIP_TAC THEN
1075   FIRST_X_ASSUM(MP_TAC o SPEC `Cx y`) THEN
1076   ASM_REWRITE_TAC[GSYM CX_SIN; COMPLEX_NORM_CX; GSYM CX_SUB] THEN
1077   ASM_REAL_ARITH_TAC);;
1078
1079 let SIN_NONTRIVIAL = prove
1080  (`?x. &0 < x /\ ~(sin x = &0)`,
1081   MESON_TAC[REAL_LE_REFL; REAL_LT_REFL; SIN_NEARZERO]);;
1082
1083 let COS_NONTRIVIAL = prove
1084  (`?x. &0 < x /\ ~(cos x = &1)`,
1085   MP_TAC SIN_NONTRIVIAL THEN MATCH_MP_TAC MONO_EXISTS THEN
1086   MP_TAC SIN_CIRCLE THEN MATCH_MP_TAC MONO_FORALL THEN
1087   CONV_TAC REAL_FIELD);;
1088
1089 let COS_DOUBLE_BOUND = prove
1090  (`!x. &0 <= cos x ==> &2 * (&1 - cos x) <= &1 - cos(&2 * x)`,
1091   REWRITE_TAC[COS_DOUBLE_COS] THEN REWRITE_TAC[REAL_ARITH
1092    `&2 * (&1 - a) <= &1 - (&2 * b - &1) <=> b <= &1 * a`] THEN
1093   SIMP_TAC[REAL_POW_2; REAL_LE_RMUL; COS_BOUNDS]);;
1094
1095 let COS_GOESNEGATIVE_LEMMA = prove
1096  (`!x. cos(x) < &1 ==> ?n. cos(&2 pow n * x) < &0`,
1097   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC(TAUT `(~p ==> p) ==> p`) THEN
1098   REWRITE_TAC[NOT_EXISTS_THM; REAL_NOT_LT] THEN DISCH_TAC THEN
1099   SUBGOAL_THEN `!n.  &2  pow n * (&1 - cos x) <= &1 - cos(&2 pow n * x)`
1100   ASSUME_TAC THENL
1101    [INDUCT_TAC THEN REWRITE_TAC[real_pow; REAL_MUL_LID; REAL_LE_REFL] THEN
1102     MATCH_MP_TAC REAL_LE_TRANS THEN
1103     EXISTS_TAC `&2 * (&1 - cos(&2 pow n * x))` THEN
1104     ASM_SIMP_TAC[GSYM REAL_MUL_ASSOC; REAL_LE_LMUL; REAL_POS; COS_DOUBLE_BOUND];
1105     MP_TAC(ISPEC `&1 / (&1 - cos(x))` REAL_ARCH_POW2) THEN
1106     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_SUB_LT] THEN
1107     DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN
1108     REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `n:num`)) THEN REAL_ARITH_TAC]);;
1109
1110 let COS_GOESNEGATIVE = prove
1111  (`?x. &0 < x /\ cos(x) < &0`,
1112   X_CHOOSE_TAC `x:real` COS_NONTRIVIAL THEN
1113   MP_TAC(SPEC `x:real` COS_GOESNEGATIVE_LEMMA) THEN ANTS_TAC THENL
1114    [MP_TAC(SPEC `x:real` COS_BOUNDS) THEN
1115     ASM_REAL_ARITH_TAC;
1116     ASM_MESON_TAC[REAL_LT_MUL; REAL_POW_LT; REAL_ARITH `&0 < &2`]]);;
1117
1118 let COS_HASZERO = prove
1119  (`?x. &0 < x /\ cos(x) = &0`,
1120   X_CHOOSE_THEN `z:real` STRIP_ASSUME_TAC COS_GOESNEGATIVE THEN
1121   SUBGOAL_THEN `?x. &0 <= x /\ x <= z /\ Re(ccos(Cx x)) = &0` MP_TAC THENL
1122    [MATCH_MP_TAC IVT_DECREASING_RE THEN
1123     ASM_SIMP_TAC[GSYM CX_COS; RE_CX; REAL_LT_IMP_LE; COS_0; REAL_POS] THEN
1124     MESON_TAC[HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT;
1125               HAS_COMPLEX_DERIVATIVE_CCOS];
1126     MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[GSYM CX_COS; RE_CX] THEN
1127     MESON_TAC[COS_0; REAL_LE_LT; REAL_ARITH `~(&1 = &0)`]]);;
1128
1129 let SIN_HASZERO = prove
1130  (`?x. &0 < x /\ sin(x) = &0`,
1131   X_CHOOSE_THEN `x:real` STRIP_ASSUME_TAC COS_HASZERO THEN
1132   EXISTS_TAC `&2 * x` THEN ASM_SIMP_TAC[SIN_DOUBLE] THEN
1133   ASM_REAL_ARITH_TAC);;
1134
1135 let SIN_HASZERO_MINIMAL = prove
1136  (`?p. &0 < p /\ sin p = &0 /\ !x. &0 < x /\ x < p ==> ~(sin x = &0)`,
1137   X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC SIN_NEARZERO THEN
1138   MP_TAC(ISPECL
1139     [`{z | z IN IMAGE Cx {x | x >= e} /\ csin z IN {Cx(&0)}}`; `Cx(&0)`]
1140     DISTANCE_ATTAINS_INF) THEN
1141   ANTS_TAC THENL
1142    [ALL_TAC;
1143     REWRITE_TAC[IN_ELIM_THM; GSYM CONJ_ASSOC; IMP_CONJ] THEN
1144     REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
1145     REWRITE_TAC[IN_ELIM_THM; IN_SING; real_ge; GSYM CX_COS; CX_INJ] THEN
1146     REWRITE_TAC[dist; GSYM CX_SUB; GSYM CX_SIN; CX_INJ; COMPLEX_NORM_CX] THEN
1147     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
1148     REWRITE_TAC[REAL_ARITH `abs(&0 - x) = abs x`] THEN
1149     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
1150      [ALL_TAC;
1151       X_GEN_TAC `x:real` THEN
1152       REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `x:real`))] THEN
1153     ASM_REAL_ARITH_TAC] THEN
1154   X_CHOOSE_TAC `a:real` SIN_HASZERO THEN CONJ_TAC THENL
1155    [ALL_TAC;
1156     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `Cx a` THEN
1157     ASM_REWRITE_TAC[IN_SING; IN_IMAGE; IN_ELIM_THM; GSYM CX_SIN] THEN
1158     ASM_MESON_TAC[REAL_ARITH `x >= w \/ x <= w`; REAL_LT_REFL]] THEN
1159   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN
1160   REWRITE_TAC[CONTINUOUS_ON_CSIN; CLOSED_SING] THEN
1161   SUBGOAL_THEN
1162    `IMAGE Cx {x | x >= e} = {z | Im(z) = &0} INTER {z | Re(z) >= e}`
1163    (fun th -> SIMP_TAC[th; CLOSED_INTER; CLOSED_HALFSPACE_IM_EQ;
1164                            CLOSED_HALFSPACE_RE_GE]) THEN
1165   REWRITE_TAC[EXTENSION; IN_IMAGE; IN_INTER; IN_ELIM_THM] THEN
1166   REWRITE_TAC[FORALL_COMPLEX; COMPLEX_EQ; RE; IM; RE_CX; IM_CX] THEN
1167   MESON_TAC[]);;
1168
1169 let pi = new_definition
1170  `pi = @p. &0 < p /\ sin(p) = &0 /\ !x. &0 < x /\ x < p ==> ~(sin(x) = &0)`;;
1171
1172 let PI_WORKS = prove
1173  (`&0 < pi /\ sin(pi) = &0 /\ !x. &0 < x /\ x < pi ==> ~(sin x = &0)`,
1174   REWRITE_TAC[pi] THEN CONV_TAC SELECT_CONV THEN
1175   REWRITE_TAC[SIN_HASZERO_MINIMAL]);;
1176
1177 (* ------------------------------------------------------------------------- *)
1178 (* Now more relatively easy consequences.                                    *)
1179 (* ------------------------------------------------------------------------- *)
1180
1181 let PI_POS = prove
1182  (`&0 < pi`,
1183   REWRITE_TAC[PI_WORKS]);;
1184
1185 let PI_POS_LE = prove
1186  (`&0 <= pi`,
1187   REWRITE_TAC[REAL_LE_LT; PI_POS]);;
1188
1189 let PI_NZ = prove
1190  (`~(pi = &0)`,
1191   SIMP_TAC[PI_POS; REAL_LT_IMP_NZ]);;
1192
1193 let REAL_ABS_PI = prove
1194  (`abs pi = pi`,
1195   REWRITE_TAC[real_abs; PI_POS_LE]);;
1196
1197 let SIN_PI = prove
1198  (`sin(pi) = &0`,
1199   REWRITE_TAC[PI_WORKS]);;
1200
1201 let SIN_POS_PI = prove
1202  (`!x. &0 < x /\ x < pi ==> &0 < sin(x)`,
1203   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_NOT_LE] THEN DISCH_TAC THEN
1204   X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC SIN_NEARZERO THEN
1205   MP_TAC(ISPECL [`csin`; `e:real`; `x:real`; `&0`] IVT_DECREASING_RE) THEN
1206   ASM_SIMP_TAC[NOT_IMP; CONTINUOUS_AT_CSIN; GSYM CX_SIN; RE_CX; SIN_0] THEN
1207   ASM_MESON_TAC[REAL_LE_TOTAL; REAL_LET_ANTISYM; PI_WORKS; REAL_LET_TRANS;
1208                 REAL_LTE_TRANS]);;
1209
1210 let COS_PI2 = prove
1211  (`cos(pi / &2) = &0`,
1212   MP_TAC(SYM(SPEC `pi / &2` SIN_DOUBLE)) THEN
1213   REWRITE_TAC[REAL_HALF; SIN_PI; REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH] THEN
1214   MATCH_MP_TAC(REAL_ARITH `&0 < y ==> y = &0 \/ z = &0 ==> z = &0`) THEN
1215   MATCH_MP_TAC SIN_POS_PI THEN MP_TAC PI_POS THEN REAL_ARITH_TAC);;
1216
1217 let COS_PI = prove
1218  (`cos(pi) = -- &1`,
1219   ONCE_REWRITE_TAC[REAL_ARITH `pi = &2 * pi / &2`] THEN
1220   REWRITE_TAC[COS_DOUBLE_COS; COS_PI2] THEN REAL_ARITH_TAC);;
1221
1222 let SIN_PI2 = prove
1223  (`sin(pi / &2) = &1`,
1224   MP_TAC(SPEC `pi / &2` SIN_CIRCLE) THEN
1225   REWRITE_TAC[COS_PI2; REAL_POW_2; REAL_ADD_RID; REAL_MUL_LZERO] THEN
1226   REWRITE_TAC[REAL_RING `x * x = &1 <=> x = &1 \/ x = -- &1`] THEN
1227   MP_TAC(SPEC `pi / &2` SIN_POS_PI) THEN MP_TAC PI_POS THEN REAL_ARITH_TAC);;
1228
1229 let SIN_COS = prove
1230  (`!x. sin(x) = cos(pi / &2 - x)`,
1231   REWRITE_TAC[COS_SUB; COS_PI2; SIN_PI2] THEN REAL_ARITH_TAC);;
1232
1233 let COS_SIN = prove
1234  (`!x. cos(x) = sin(pi / &2 - x)`,
1235   REWRITE_TAC[SIN_SUB; COS_PI2; SIN_PI2] THEN REAL_ARITH_TAC);;
1236
1237 let SIN_PERIODIC_PI = prove
1238  (`!x. sin(x + pi) = --(sin(x))`,
1239   REWRITE_TAC[SIN_ADD; SIN_PI; COS_PI] THEN REAL_ARITH_TAC);;
1240
1241 let COS_PERIODIC_PI = prove
1242  (`!x. cos(x + pi) = --(cos(x))`,
1243   REWRITE_TAC[COS_ADD; SIN_PI; COS_PI] THEN REAL_ARITH_TAC);;
1244
1245 let SIN_PERIODIC = prove
1246  (`!x. sin(x + &2 * pi) = sin(x)`,
1247   REWRITE_TAC[REAL_MUL_2; REAL_ADD_ASSOC; SIN_PERIODIC_PI; REAL_NEG_NEG]);;
1248
1249 let COS_PERIODIC = prove
1250  (`!x. cos(x + &2 * pi) = cos(x)`,
1251   REWRITE_TAC[REAL_MUL_2; REAL_ADD_ASSOC; COS_PERIODIC_PI; REAL_NEG_NEG]);;
1252
1253 let SIN_NPI = prove
1254  (`!n. sin(&n * pi) = &0`,
1255   INDUCT_TAC THEN
1256   ASM_REWRITE_TAC[GSYM REAL_OF_NUM_SUC; REAL_MUL_LID; REAL_ADD_RDISTRIB;
1257                   REAL_NEG_0; SIN_PERIODIC_PI; REAL_MUL_LZERO; SIN_0]);;
1258
1259 let COS_NPI = prove
1260  (`!n. cos(&n * pi) = --(&1) pow n`,
1261   INDUCT_TAC THEN
1262   ASM_REWRITE_TAC[real_pow; REAL_MUL_LZERO; COS_0; COS_PERIODIC_PI;
1263     REAL_MUL_LID; REAL_MUL_LNEG; GSYM REAL_OF_NUM_SUC; REAL_ADD_RDISTRIB]);;
1264
1265 let COS_POS_PI2 = prove
1266  (`!x. &0 < x /\ x < pi / &2 ==> &0 < cos(x)`,
1267   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_NOT_LE] THEN DISCH_TAC THEN
1268   MP_TAC(ISPECL [`ccos`; `&0`; `x:real`; `&0`] IVT_DECREASING_RE) THEN
1269   ASM_SIMP_TAC[CONTINUOUS_AT_CCOS; REAL_LT_IMP_LE; GSYM CX_COS; RE_CX] THEN
1270   REWRITE_TAC[COS_0; REAL_POS] THEN DISCH_THEN(X_CHOOSE_TAC `y:real`) THEN
1271   MP_TAC(SPEC `y:real` SIN_DOUBLE) THEN ASM_REWRITE_TAC[REAL_MUL_RZERO] THEN
1272   MATCH_MP_TAC(last(CONJUNCTS PI_WORKS)) THEN REPEAT(POP_ASSUM MP_TAC) THEN
1273   ASM_CASES_TAC `y = &0` THEN ASM_REWRITE_TAC[COS_0] THEN
1274   POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
1275
1276 let SIN_POS_PI2 = prove
1277  (`!x. &0 < x /\ x < pi / &2 ==> &0 < sin(x)`,
1278   REPEAT STRIP_TAC THEN MATCH_MP_TAC SIN_POS_PI THEN
1279   ASM_REAL_ARITH_TAC);;
1280
1281 let COS_POS_PI = prove
1282  (`!x. --(pi / &2) < x /\ x < pi / &2 ==> &0 < cos(x)`,
1283   GEN_TAC THEN MP_TAC(SPEC `abs x` COS_POS_PI2) THEN REWRITE_TAC[COS_ABS] THEN
1284   ASM_CASES_TAC `x = &0` THEN ASM_REWRITE_TAC[COS_0] THEN
1285   POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
1286
1287 let COS_POS_PI_LE = prove
1288  (`!x. --(pi / &2) <= x /\ x <= pi / &2 ==> &0 <= cos(x)`,
1289   REWRITE_TAC[REAL_LE_LT] THEN MESON_TAC[COS_PI2; COS_NEG; COS_POS_PI]);;
1290
1291 let SIN_POS_PI_LE = prove
1292  (`!x. &0 <= x /\ x <= pi ==> &0 <= sin(x)`,
1293   REWRITE_TAC[REAL_LE_LT] THEN MESON_TAC[SIN_0; SIN_PI; SIN_POS_PI]);;
1294
1295 let SIN_PIMUL_EQ_0 = prove
1296  (`!n. sin(n * pi) = &0 <=> integer(n)`,
1297   SUBGOAL_THEN `!n. integer n ==> sin(n * pi) = &0 /\ ~(cos(n * pi) = &0)`
1298   ASSUME_TAC THENL
1299    [REWRITE_TAC[INTEGER_CASES] THEN GEN_TAC THEN STRIP_TAC THEN CONJ_TAC THEN
1300     ASM_SIMP_TAC[REAL_MUL_LNEG; COS_NPI; SIN_NPI;
1301                  SIN_NEG; COS_NEG; REAL_POW_EQ_0] THEN REAL_ARITH_TAC;
1302     ALL_TAC] THEN
1303   GEN_TAC THEN EQ_TAC THEN ASM_SIMP_TAC[] THEN
1304   SUBST1_TAC(last(CONJUNCTS(SPEC `n:real` FLOOR_FRAC))) THEN
1305   ASM_SIMP_TAC[REAL_ADD_RDISTRIB; FLOOR; SIN_ADD; REAL_MUL_LZERO] THEN
1306   ASM_SIMP_TAC[REAL_ADD_LID; REAL_ENTIRE; FLOOR] THEN
1307   DISCH_TAC THEN MP_TAC(SPEC `frac n * pi` SIN_POS_PI) THEN
1308   ASM_SIMP_TAC[REAL_LT_REFL; GSYM REAL_LT_RDIV_EQ; GSYM REAL_LT_LDIV_EQ;
1309                PI_POS; REAL_DIV_REFL; REAL_LT_IMP_NZ] THEN
1310   MP_TAC(SPEC `n:real` FLOOR_FRAC) THEN ASM_CASES_TAC `frac n = &0` THEN
1311   ASM_REWRITE_TAC[FLOOR; REAL_ADD_RID] THEN
1312   ASM_REAL_ARITH_TAC);;
1313
1314 let SIN_EQ_0 = prove
1315  (`!x. sin(x) = &0 <=> ?n. integer n /\ x = n * pi`,
1316   GEN_TAC THEN MP_TAC(SPEC `x / pi` SIN_PIMUL_EQ_0) THEN
1317   SIMP_TAC[REAL_DIV_RMUL; REAL_LT_IMP_NZ; GSYM REAL_EQ_LDIV_EQ; PI_POS] THEN
1318   ONCE_REWRITE_TAC[CONJ_SYM] THEN REWRITE_TAC[UNWIND_THM1]);;
1319
1320 let COS_EQ_0 = prove
1321  (`!x. cos(x) = &0 <=> ?n. integer n /\ x = (n + &1 / &2) * pi`,
1322   GEN_TAC THEN REWRITE_TAC[COS_SIN; SIN_EQ_0] THEN
1323   EQ_TAC THEN DISCH_THEN(X_CHOOSE_THEN `n:real` STRIP_ASSUME_TAC) THEN
1324   EXISTS_TAC `--n:real` THEN ASM_REWRITE_TAC[INTEGER_NEG] THEN
1325   ASM_REAL_ARITH_TAC);;
1326
1327 let SIN_ZERO_PI = prove
1328  (`!x. sin(x) = &0 <=> (?n. x = &n * pi) \/ (?n. x = --(&n * pi))`,
1329   REWRITE_TAC[SIN_EQ_0; INTEGER_CASES] THEN MESON_TAC[REAL_MUL_LNEG]);;
1330
1331 let COS_ZERO_PI = prove
1332  (`!x. cos(x) = &0 <=>
1333        (?n. x = (&n + &1 / &2) * pi) \/ (?n. x = --((&n + &1 / &2) * pi))`,
1334   GEN_TAC THEN REWRITE_TAC[COS_EQ_0; INTEGER_CASES; RIGHT_OR_DISTRIB] THEN
1335   REWRITE_TAC[EXISTS_OR_THM; LEFT_AND_EXISTS_THM] THEN
1336   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN SIMP_TAC[UNWIND_THM2] THEN EQ_TAC THEN
1337   DISCH_THEN(DISJ_CASES_THEN (X_CHOOSE_THEN `n:num` SUBST1_TAC)) THENL
1338    [DISJ1_TAC THEN EXISTS_TAC `n:num`;
1339     ASM_CASES_TAC `n = 0` THENL
1340      [DISJ1_TAC THEN EXISTS_TAC `0`;
1341       DISJ2_TAC THEN EXISTS_TAC `n - 1`];
1342     DISJ1_TAC THEN EXISTS_TAC `n:num`;
1343     DISJ2_TAC THEN EXISTS_TAC `n + 1`] THEN
1344   ASM_SIMP_TAC[GSYM REAL_OF_NUM_SUB; GSYM REAL_OF_NUM_ADD;
1345                ARITH_RULE `1 <= n <=> ~(n = 0)`] THEN
1346   REAL_ARITH_TAC);;
1347
1348 let SIN_ZERO = prove
1349  (`!x. (sin(x) = &0) <=> (?n. EVEN n /\ x = &n * (pi / &2)) \/
1350                          (?n. EVEN n /\ x = --(&n * (pi / &2)))`,
1351   REWRITE_TAC[SIN_ZERO_PI; EVEN_EXISTS; LEFT_AND_EXISTS_THM] THEN
1352   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2] THEN
1353   SIMP_TAC[GSYM REAL_OF_NUM_MUL; REAL_ARITH `(&2 * x) * y / &2 = x * y`]);;
1354
1355 let COS_ZERO = prove
1356  (`!x. cos(x) = &0 <=> (?n. ~EVEN n /\ (x = &n * (pi / &2))) \/
1357                        (?n. ~EVEN n /\ (x = --(&n * (pi / &2))))`,
1358   REWRITE_TAC[COS_ZERO_PI; NOT_EVEN; ODD_EXISTS; LEFT_AND_EXISTS_THM] THEN
1359   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2] THEN
1360   SIMP_TAC[GSYM REAL_OF_NUM_MUL; GSYM REAL_OF_NUM_SUC;
1361            REAL_ARITH `(&2 * x + &1) * y / &2 = (x + &1 / &2) * y`]);;
1362
1363 let COS_ONE_2PI = prove
1364  (`!x. (cos(x) = &1) <=> (?n. x = &n * &2 * pi) \/ (?n. x = --(&n * &2 * pi))`,
1365   GEN_TAC THEN EQ_TAC THEN DISCH_TAC THENL
1366    [FIRST_ASSUM(MP_TAC o SPEC `sin(x)` o MATCH_MP (REAL_RING
1367      `c = &1 ==> !s. s pow 2 + c pow 2 = &1 ==> s = &0`)) THEN
1368     REWRITE_TAC[SIN_ZERO_PI; SIN_CIRCLE] THEN
1369     DISCH_THEN(DISJ_CASES_THEN(X_CHOOSE_THEN `n:num` SUBST_ALL_TAC)) THEN
1370     POP_ASSUM MP_TAC THEN REWRITE_TAC[COS_NEG; COS_NPI; REAL_POW_NEG] THEN
1371     COND_CASES_TAC THEN REWRITE_TAC[REAL_POW_ONE] THEN
1372     CONV_TAC REAL_RAT_REDUCE_CONV THEN
1373     FIRST_X_ASSUM(MP_TAC o REWRITE_RULE[EVEN_EXISTS]) THEN
1374     REWRITE_TAC[OR_EXISTS_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
1375     SIMP_TAC[GSYM REAL_OF_NUM_MUL] THEN REAL_ARITH_TAC;
1376     FIRST_X_ASSUM (DISJ_CASES_THEN CHOOSE_TAC) THEN
1377     ASM_REWRITE_TAC[COS_NEG; REAL_MUL_ASSOC; REAL_OF_NUM_MUL; COS_NPI;
1378                     REAL_POW_NEG; EVEN_MULT; ARITH; REAL_POW_ONE]]);;
1379
1380 let SIN_COS_SQRT = prove
1381  (`!x. &0 <= sin(x) ==> (sin(x) = sqrt(&1 - (cos(x) pow 2)))`,
1382   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC SQRT_UNIQUE THEN
1383   ASM_REWRITE_TAC[SIN_CIRCLE; REAL_EQ_SUB_LADD]);;
1384
1385 let SIN_EQ_0_PI = prove
1386  (`!x. --pi < x /\ x < pi /\ sin(x) = &0 ==> x = &0`,
1387   GEN_TAC THEN REWRITE_TAC[SIN_EQ_0; CONJ_ASSOC] THEN
1388   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC
1389    (X_CHOOSE_THEN `n:real` STRIP_ASSUME_TAC)) THEN
1390   ASM_REWRITE_TAC[REAL_ARITH
1391    `--p < n * p /\ n * p < p <=> -- &1 * p < n * p /\ n * p < &1 * p`] THEN
1392   SIMP_TAC[REAL_ENTIRE; REAL_LT_IMP_NZ; REAL_LT_RMUL_EQ; PI_POS] THEN
1393   MP_TAC(SPEC `n:real` REAL_ABS_INTEGER_LEMMA) THEN
1394   ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
1395
1396 let COS_TREBLE_COS = prove
1397  (`!x. cos(&3 * x) = &4 * cos(x) pow 3 - &3 * cos x`,
1398   GEN_TAC THEN REWRITE_TAC[COS_ADD; REAL_ARITH `&3 * x = &2 * x + x`] THEN
1399   REWRITE_TAC[SIN_DOUBLE; COS_DOUBLE_COS] THEN
1400   MP_TAC(SPEC `x:real` SIN_CIRCLE) THEN CONV_TAC REAL_RING);;
1401
1402 let COS_PI6 = prove
1403  (`cos(pi / &6) = sqrt(&3) / &2`,
1404   MP_TAC(ISPEC `pi / &6` COS_TREBLE_COS) THEN
1405   REWRITE_TAC[REAL_ARITH `&3 * x / &6 = x / &2`; COS_PI2] THEN
1406   REWRITE_TAC[REAL_RING `&0 = &4 * c pow 3 - &3 * c <=>
1407                          c = &0 \/ (&2 * c) pow 2 = &3`] THEN
1408   SUBGOAL_THEN `&0 < cos(pi / &6)` ASSUME_TAC THENL
1409    [MATCH_MP_TAC COS_POS_PI THEN MP_TAC PI_POS THEN REAL_ARITH_TAC;
1410     DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
1411      [ASM_MESON_TAC[REAL_LT_REFL]; ALL_TAC] THEN
1412     DISCH_THEN(MP_TAC o AP_TERM `sqrt`) THEN
1413     ASM_SIMP_TAC[POW_2_SQRT; REAL_LE_MUL; REAL_LT_IMP_LE; REAL_POS] THEN
1414     REAL_ARITH_TAC]);;
1415
1416 let SIN_PI6 = prove
1417  (`sin(pi / &6) = &1 / &2`,
1418   MP_TAC(SPEC `pi / &6` SIN_CIRCLE) THEN REWRITE_TAC[COS_PI6] THEN
1419   SIMP_TAC[REAL_POW_DIV; SQRT_POW_2; REAL_POS] THEN MATCH_MP_TAC(REAL_FIELD
1420    `~(s + &1 / &2 = &0) ==> s pow 2 + &3 / &2 pow 2 = &1 ==> s = &1 / &2`) THEN
1421   MATCH_MP_TAC(REAL_ARITH `&0 < x ==> ~(x + &1 / &2 = &0)`) THEN
1422   MATCH_MP_TAC SIN_POS_PI THEN MP_TAC PI_POS THEN REAL_ARITH_TAC);;
1423
1424 let SIN_POS_PI_REV = prove
1425  (`!x. &0 <= x /\ x <= &2 * pi /\ &0 < sin x ==> &0 < x /\ x < pi`,
1426   GEN_TAC THEN ASM_CASES_TAC `x = &0` THEN
1427   ASM_REWRITE_TAC[SIN_0; REAL_LT_REFL] THEN
1428   ASM_CASES_TAC `x = pi` THEN
1429   ASM_REWRITE_TAC[SIN_PI; REAL_LT_REFL] THEN
1430   ASM_CASES_TAC `x = &2 * pi` THEN
1431   ASM_REWRITE_TAC[SIN_NPI; REAL_LT_REFL] THEN
1432   REPEAT STRIP_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
1433   REWRITE_TAC[GSYM REAL_NOT_LE] THEN DISCH_TAC THEN
1434   SUBGOAL_THEN `&0 < sin(&2 * pi - x)` MP_TAC THENL
1435    [MATCH_MP_TAC SIN_POS_PI THEN ASM_REAL_ARITH_TAC;
1436     REWRITE_TAC[SIN_SUB; SIN_NPI; COS_NPI] THEN ASM_REAL_ARITH_TAC]);;
1437
1438 (* ------------------------------------------------------------------------- *)
1439 (* Prove totality of trigs.                                                  *)
1440 (* ------------------------------------------------------------------------- *)
1441
1442 let SIN_TOTAL_POS = prove
1443  (`!y. &0 <= y /\ y <= &1
1444        ==> ?x. &0 <= x /\ x <= pi / &2 /\ sin(x) = y`,
1445   REPEAT STRIP_TAC THEN
1446   MP_TAC(SPECL [`csin`; `&0`; `pi / &2`; `y:real`] IVT_INCREASING_RE) THEN
1447   ASM_REWRITE_TAC[GSYM CX_SIN; RE_CX; SIN_0; SIN_PI2] THEN
1448   SIMP_TAC[CONTINUOUS_AT_CSIN; PI_POS; REAL_ARITH `&0 < x ==> &0 <= x / &2`]);;
1449
1450 let SINCOS_TOTAL_PI2 = prove
1451  (`!x y. &0 <= x /\ &0 <= y /\ x pow 2 + y pow 2 = &1
1452          ==> ?t. &0 <= t /\ t <= pi / &2 /\ x = cos t /\ y = sin t`,
1453   REPEAT STRIP_TAC THEN MP_TAC(SPEC `y:real` SIN_TOTAL_POS) THEN ANTS_TAC THENL
1454    [ASM_REWRITE_TAC[] THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
1455      `x pow 2 + y pow 2 = &1
1456       ==> (&1 < y ==> &1 pow 2 < y pow 2) /\ &0 <= x * x
1457           ==> y <= &1`)) THEN
1458     SIMP_TAC[REAL_LE_SQUARE; REAL_POW_LT2; REAL_POS; ARITH];
1459     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real` THEN
1460     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1461     SUBGOAL_THEN `x = cos t \/ x = --(cos t)` MP_TAC THENL
1462      [MP_TAC(SPEC `t:real` SIN_CIRCLE);
1463       MP_TAC(SPEC `t:real` COS_POS_PI_LE)] THEN
1464     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD]);;
1465
1466 let SINCOS_TOTAL_PI = prove
1467  (`!x y. &0 <= y /\ x pow 2 + y pow 2 = &1
1468          ==> ?t. &0 <= t /\ t <= pi /\ x = cos t /\ y = sin t`,
1469   REPEAT STRIP_TAC THEN DISJ_CASES_TAC(REAL_ARITH `&0 <= x \/ &0 <= --x`) THENL
1470    [MP_TAC(SPECL [`x:real`; `y:real`] SINCOS_TOTAL_PI2);
1471     MP_TAC(SPECL [`--x:real`; `y:real`] SINCOS_TOTAL_PI2)] THEN
1472   ASM_REWRITE_TAC[REAL_POW_NEG; ARITH] THEN
1473   DISCH_THEN(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THENL
1474    [EXISTS_TAC `t:real`; EXISTS_TAC `pi - t`] THEN
1475   ASM_REWRITE_TAC[SIN_SUB; COS_SUB; SIN_PI; COS_PI] THEN
1476   ASM_REAL_ARITH_TAC);;
1477
1478 let SINCOS_TOTAL_2PI = prove
1479  (`!x y. x pow 2 + y pow 2 = &1
1480          ==> ?t. &0 <= t /\ t < &2 * pi /\ x = cos t /\ y = sin t`,
1481   REPEAT STRIP_TAC THEN ASM_CASES_TAC `x = &1 /\ y = &0` THENL
1482    [EXISTS_TAC `&0` THEN ASM_REWRITE_TAC[SIN_0; COS_0] THEN
1483     MP_TAC PI_POS THEN REAL_ARITH_TAC;
1484     ALL_TAC] THEN
1485   DISJ_CASES_TAC(REAL_ARITH `&0 <= y \/ &0 <= --y`) THENL
1486    [MP_TAC(SPECL [`x:real`; `y:real`] SINCOS_TOTAL_PI);
1487     MP_TAC(SPECL [`x:real`; `--y:real`] SINCOS_TOTAL_PI)] THEN
1488   ASM_REWRITE_TAC[REAL_POW_NEG; ARITH] THEN
1489   DISCH_THEN(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THENL
1490    [EXISTS_TAC `t:real`; EXISTS_TAC `&2 * pi - t`] THEN
1491   ASM_REWRITE_TAC[SIN_SUB; COS_SUB; SIN_NPI; COS_NPI] THENL
1492    [MP_TAC PI_POS THEN ASM_REAL_ARITH_TAC;
1493     ALL_TAC] THEN
1494   REPEAT(POP_ASSUM MP_TAC) THEN ASM_CASES_TAC `t = &0` THEN
1495   ASM_REWRITE_TAC[SIN_0; COS_0] THEN POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
1496
1497 let CIRCLE_SINCOS = prove
1498  (`!x y. x pow 2 + y pow 2 = &1 ==> ?t. x = cos(t) /\ y = sin(t)`,
1499   MESON_TAC[SINCOS_TOTAL_2PI]);;
1500
1501 (* ------------------------------------------------------------------------- *)
1502 (* Polar representation.                                                     *)
1503 (* ------------------------------------------------------------------------- *)
1504
1505 let CX_PI_NZ = prove
1506  (`~(Cx pi = Cx(&0))`,
1507   SIMP_TAC[CX_INJ; REAL_LT_IMP_NZ; PI_POS]);;
1508
1509 let COMPLEX_UNIMODULAR_POLAR = prove
1510  (`!z. (norm z = &1) ==> ?x. z = complex(cos(x),sin(x))`,
1511   GEN_TAC THEN
1512   DISCH_THEN(MP_TAC o C AP_THM `2` o AP_TERM `(pow):real->num->real`) THEN
1513   REWRITE_TAC[complex_norm] THEN
1514   SIMP_TAC[REAL_POW_2; REWRITE_RULE[REAL_POW_2] SQRT_POW_2;
1515            REAL_LE_SQUARE; REAL_LE_ADD] THEN
1516   REWRITE_TAC[GSYM REAL_POW_2; REAL_MUL_LID] THEN
1517   DISCH_THEN(X_CHOOSE_TAC `t:real` o MATCH_MP CIRCLE_SINCOS) THEN
1518   EXISTS_TAC `t:real` THEN ASM_REWRITE_TAC[COMPLEX_EQ; RE; IM]);;
1519
1520 let SIN_INTEGER_2PI = prove
1521  (`!n. integer n ==> sin((&2 * pi) * n) = &0`,
1522   REWRITE_TAC[SIN_EQ_0; REAL_ARITH `(&2 * pi) * n = (&2 * n) * pi`] THEN
1523   MESON_TAC[INTEGER_CLOSED]);;
1524
1525 let SIN_INTEGER_PI = prove
1526  (`!n. integer n ==> sin (n * pi) = &0`,
1527   REWRITE_TAC[INTEGER_CASES] THEN REPEAT STRIP_TAC THEN
1528   ASM_REWRITE_TAC[REAL_MUL_LNEG; SIN_NPI; SIN_NEG; REAL_NEG_0]);;
1529
1530 let COS_INTEGER_2PI = prove
1531  (`!n. integer n ==> cos((&2 * pi) * n) = &1`,
1532   REWRITE_TAC[INTEGER_CASES; REAL_ARITH `(&2 * pi) * n = (&2 * n) * pi`] THEN
1533   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[REAL_MUL_RNEG; REAL_OF_NUM_MUL] THEN
1534   SIMP_TAC[COS_NEG; COS_NPI; REAL_POW_NEG; REAL_MUL_LNEG;
1535            ARITH; EVEN_MULT; REAL_POW_ONE]);;
1536
1537 let SINCOS_PRINCIPAL_VALUE = prove
1538  (`!x. ?y. (--pi < y /\ y <= pi) /\ (sin(y) = sin(x) /\ cos(y) = cos(x))`,
1539   GEN_TAC THEN EXISTS_TAC `pi - (&2 * pi) * frac((pi - x) / (&2 * pi))` THEN
1540   CONJ_TAC THENL
1541    [SIMP_TAC[REAL_ARITH `--p < p - x <=> x < (&2 * p) * &1`;
1542              REAL_ARITH `p - x <= p <=> (&2 * p) * &0 <= x`;
1543              REAL_LT_LMUL_EQ; REAL_LE_LMUL_EQ; REAL_LT_MUL;
1544              PI_POS; REAL_OF_NUM_LT; ARITH; FLOOR_FRAC];
1545    REWRITE_TAC[FRAC_FLOOR; REAL_SUB_LDISTRIB] THEN
1546    SIMP_TAC[REAL_DIV_LMUL; REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH; REAL_LT_IMP_NZ;
1547     PI_POS; REAL_ARITH `a - (a - b - c):real = b + c`; SIN_ADD; COS_ADD] THEN
1548    SIMP_TAC[FLOOR_FRAC; SIN_INTEGER_2PI; COS_INTEGER_2PI] THEN
1549    CONV_TAC REAL_RING]);;
1550
1551 let CEXP_COMPLEX = prove
1552  (`!r t. cexp(complex(r,t)) = Cx(exp r) * complex(cos t,sin t)`,
1553   REPEAT GEN_TAC THEN
1554   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [COMPLEX_EXPAND] THEN
1555   REWRITE_TAC[RE; IM; CEXP_ADD; CEXP_EULER; CX_EXP] THEN
1556   REWRITE_TAC[COMPLEX_TRAD; CX_SIN; CX_COS]);;
1557
1558 let NORM_COSSIN = prove
1559  (`!t. norm(complex(cos t,sin t)) = &1`,
1560   REWRITE_TAC[complex_norm; RE; IM] THEN ONCE_REWRITE_TAC[REAL_ADD_SYM] THEN
1561   REWRITE_TAC[SIN_CIRCLE; SQRT_1]);;
1562
1563 let NORM_CEXP = prove
1564  (`!z. norm(cexp z) = exp(Re z)`,
1565   REWRITE_TAC[FORALL_COMPLEX; CEXP_COMPLEX; COMPLEX_NORM_MUL] THEN
1566   REWRITE_TAC[NORM_COSSIN; RE; COMPLEX_NORM_CX] THEN
1567   MP_TAC REAL_EXP_POS_LT THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
1568
1569 let NORM_CEXP_II = prove
1570  (`!t. norm (cexp (ii * Cx t)) = &1`,
1571   REWRITE_TAC [NORM_CEXP; RE_MUL_II; IM_CX; REAL_NEG_0; REAL_EXP_0]);;
1572
1573 let NORM_CEXP_IMAGINARY = prove
1574  (`!z. norm(cexp z) = &1 ==> Re(z) = &0`,
1575   REWRITE_TAC[NORM_CEXP; REAL_EXP_EQ_1]);;
1576
1577 let CEXP_EQ_1 = prove
1578  (`!z. cexp z = Cx(&1) <=> Re(z) = &0 /\ ?n. integer n /\ Im(z) = &2 * n * pi`,
1579   REWRITE_TAC[FORALL_COMPLEX; CEXP_COMPLEX; RE; IM] THEN
1580   MAP_EVERY X_GEN_TAC [`x:real`; `y:real`] THEN EQ_TAC THENL
1581    [DISCH_TAC THEN FIRST_ASSUM(MP_TAC o AP_TERM `norm:complex->real`) THEN
1582     SIMP_TAC[COMPLEX_NORM_MUL; CX_EXP; NORM_CEXP; RE_CX; COMPLEX_NORM_CX] THEN
1583     REWRITE_TAC[NORM_COSSIN; REAL_ABS_NUM; REAL_ABS_EXP; REAL_MUL_RID] THEN
1584     REWRITE_TAC[REAL_EXP_EQ_1] THEN DISCH_THEN SUBST_ALL_TAC THEN
1585     POP_ASSUM MP_TAC THEN REWRITE_TAC[REAL_EXP_0; COMPLEX_MUL_LID] THEN
1586     REWRITE_TAC[COMPLEX_EQ; RE; IM; RE_CX; IM_CX] THEN STRIP_TAC THEN
1587     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SIN_EQ_0]) THEN
1588     DISCH_THEN(X_CHOOSE_THEN `m:real`
1589      (CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
1590     EXISTS_TAC `m / &2` THEN CONJ_TAC THENL [ALL_TAC; REAL_ARITH_TAC] THEN
1591     ONCE_REWRITE_TAC[GSYM INTEGER_ABS] THEN
1592     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE LAND_CONV [GSYM COS_ABS]) THEN
1593     REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_DIV; REAL_ABS_NUM] THEN
1594     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [integer]) THEN
1595     DISCH_THEN(X_CHOOSE_THEN `n:num` SUBST_ALL_TAC) THEN
1596     SIMP_TAC[real_abs; PI_POS; REAL_LT_IMP_LE; COS_NPI] THEN
1597     REWRITE_TAC[REAL_POW_NEG; REAL_POW_ONE] THEN
1598     COND_CASES_TAC THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
1599     FIRST_X_ASSUM(CHOOSE_THEN SUBST1_TAC o REWRITE_RULE[EVEN_EXISTS]) THEN
1600     REWRITE_TAC[GSYM REAL_OF_NUM_MUL; REAL_ARITH `(&2 * x) / &2 = x`] THEN
1601     REWRITE_TAC[INTEGER_CLOSED];
1602     DISCH_THEN(CONJUNCTS_THEN2 SUBST1_TAC (X_CHOOSE_TAC `n:real`)) THEN
1603     ASM_SIMP_TAC[REAL_EXP_0; COMPLEX_MUL_LID] THEN
1604     ONCE_REWRITE_TAC[REAL_ARITH `&2 * x * y = (&2 * y) * x`] THEN
1605     ASM_SIMP_TAC[SIN_INTEGER_2PI; COS_INTEGER_2PI] THEN
1606     SIMPLE_COMPLEX_ARITH_TAC]);;
1607
1608 let CEXP_EQ = prove
1609  (`!w z. cexp w = cexp z <=> ?n. integer n /\ w = z + Cx(&2 * n * pi) * ii`,
1610   SIMP_TAC[CEXP_NZ; COMPLEX_FIELD
1611    `~(z = Cx(&0)) ==> (w = z <=> w / z = Cx(&1))`] THEN
1612   REWRITE_TAC[GSYM CEXP_SUB; CEXP_EQ_1; RE_SUB; IM_SUB; REAL_SUB_0] THEN
1613   SIMP_TAC[COMPLEX_EQ; RE_ADD; IM_ADD; RE_MUL_II; IM_MUL_II; RE_CX; IM_CX] THEN
1614   REWRITE_TAC[REAL_NEG_0; REAL_ADD_RID; REAL_EQ_SUB_RADD] THEN
1615   MESON_TAC[REAL_ADD_SYM]);;
1616
1617 let COMPLEX_EQ_CEXP = prove
1618  (`!w z. abs(Im w - Im z) < &2 * pi /\ cexp w = cexp z ==> w = z`,
1619   SIMP_TAC[CEXP_NZ; GSYM CEXP_SUB; CEXP_EQ_1; COMPLEX_FIELD
1620    `~(a = Cx(&0)) /\ ~(b = Cx(&0)) ==> (a = b <=> a / b = Cx(&1))`] THEN
1621   REPEAT GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
1622   FIRST_X_ASSUM(X_CHOOSE_THEN `n:real` STRIP_ASSUME_TAC) THEN
1623   UNDISCH_TAC `abs(Im w - Im z) < &2 * pi` THEN
1624   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
1625   ASM_REWRITE_TAC[GSYM IM_SUB; REAL_ABS_MUL; REAL_ABS_PI; REAL_ABS_NUM] THEN
1626   SIMP_TAC[REAL_MUL_ASSOC; REAL_LT_RMUL_EQ; PI_POS] THEN
1627   MATCH_MP_TAC(REAL_ARITH `&1 <= x ==> ~(&2 * x < &2)`) THEN
1628   MATCH_MP_TAC REAL_ABS_INTEGER_LEMMA THEN ASM_REWRITE_TAC[] THEN
1629   DISCH_THEN SUBST_ALL_TAC THEN UNDISCH_TAC `~(w:complex = z)` THEN
1630   REWRITE_TAC[] THEN ONCE_REWRITE_TAC[GSYM COMPLEX_SUB_0] THEN
1631   ASM_REWRITE_TAC[COMPLEX_EQ; RE_CX; IM_CX; REAL_MUL_LZERO; REAL_MUL_RZERO]);;
1632
1633 let CEXP_INTEGER_2PI = prove
1634  (`!n. integer n ==> cexp(Cx(&2 * n * pi) * ii) = Cx(&1)`,
1635   REWRITE_TAC[CEXP_EQ_1; IM_MUL_II; RE_MUL_II; RE_CX; IM_CX] THEN
1636   REWRITE_TAC[REAL_NEG_0] THEN MESON_TAC[]);;
1637
1638 let SIN_COS_EQ = prove
1639  (`!x y. sin y = sin x /\ cos y = cos x <=>
1640          ?n. integer n /\ y = x + &2 * n * pi`,
1641   REPEAT GEN_TAC THEN MP_TAC(ISPECL [`ii * Cx y`; `ii * Cx x`] CEXP_EQ) THEN
1642   REWRITE_TAC[CEXP_EULER; GSYM CX_SIN; GSYM CX_COS] THEN
1643   REWRITE_TAC[COMPLEX_RING `ii * y = ii * x + z * ii <=> y = x + z`] THEN
1644   REWRITE_TAC[GSYM CX_ADD; CX_INJ] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
1645   REWRITE_TAC[COMPLEX_EQ; RE_ADD; IM_ADD; RE_MUL_II; IM_MUL_II; RE_CX; IM_CX;
1646               REAL_NEG_0; REAL_ADD_LID; REAL_ADD_RID] THEN
1647   MESON_TAC[]);;
1648
1649 let SIN_COS_INJ = prove
1650  (`!x y. sin x = sin y /\ cos x = cos y /\ abs(x - y) < &2 * pi ==> x = y`,
1651   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM CX_INJ] THEN
1652   MATCH_MP_TAC(COMPLEX_RING `ii * x = ii * y ==> x = y`) THEN
1653   MATCH_MP_TAC COMPLEX_EQ_CEXP THEN
1654   ASM_REWRITE_TAC[CEXP_EULER; GSYM CX_SIN; GSYM CX_COS] THEN
1655   ASM_REWRITE_TAC[IM_MUL_II; RE_CX]);;
1656
1657 let CEXP_II_NE_1 = prove
1658  (`!x. &0 < x /\ x < &2 * pi ==> ~(cexp(ii * Cx x) = Cx(&1))`,
1659   GEN_TAC THEN STRIP_TAC THEN REWRITE_TAC[CEXP_EQ_1] THEN
1660   REWRITE_TAC[RE_MUL_II; IM_CX; IM_MUL_II; IM_CX; REAL_NEG_0; RE_CX] THEN
1661   DISCH_THEN(X_CHOOSE_THEN `n:real`
1662    (CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
1663   UNDISCH_TAC `&0 < &2 * n * pi` THEN ASM_CASES_TAC `n = &0` THEN
1664   ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_LT_REFL] THEN
1665   MP_TAC(ISPEC `n:real` REAL_ABS_INTEGER_LEMMA) THEN ASM_REWRITE_TAC[] THEN
1666   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH
1667    `&2 * n * pi < &2 * pi ==> &0 < (&1 - n) * &2 * pi`)) THEN
1668   ASM_SIMP_TAC[REAL_LT_MUL_EQ; PI_POS; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN
1669   ASM_REAL_ARITH_TAC);;
1670
1671 let CSIN_EQ_0 = prove
1672  (`!z. csin z = Cx(&0) <=> ?n. integer n /\ z = Cx(n * pi)`,
1673   GEN_TAC THEN REWRITE_TAC[csin; COMPLEX_MUL_LNEG; CEXP_NEG] THEN
1674   SIMP_TAC[CEXP_NZ; COMPLEX_FIELD `~(z = Cx(&0))
1675         ==> ((z - inv z) / (Cx(&2) * ii) = Cx(&0) <=> z pow 2 = Cx(&1))`] THEN
1676   REWRITE_TAC[GSYM CEXP_N; CEXP_EQ_1] THEN
1677   REWRITE_TAC[RE_MUL_CX; IM_MUL_CX; RE_MUL_II; IM_MUL_II] THEN
1678   REWRITE_TAC[COMPLEX_EQ; IM_CX; RE_CX; RIGHT_AND_EXISTS_THM] THEN
1679   EQ_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN REAL_ARITH_TAC);;
1680
1681 let CCOS_EQ_0 = prove
1682  (`!z. ccos z = Cx(&0) <=> ?n. integer n /\ z = Cx((n + &1 / &2) * pi)`,
1683   GEN_TAC THEN MP_TAC(SPEC `z - Cx(pi / &2)` CSIN_EQ_0) THEN
1684   REWRITE_TAC[CSIN_SUB; GSYM CX_SIN; GSYM CX_COS; SIN_PI2; COS_PI2] THEN
1685   SIMP_TAC[COMPLEX_RING `s * Cx(&0) - c * Cx(&1) = Cx(&0) <=> c = Cx(&0)`] THEN
1686   REWRITE_TAC[REAL_ADD_RDISTRIB; COMPLEX_EQ_SUB_RADD; CX_ADD] THEN
1687   REWRITE_TAC[REAL_ARITH `&1 / &2 * x = x / &2`]);;
1688
1689 let CCOS_EQ_1 = prove
1690  (`!z. ccos z = Cx(&1) <=> ?n. integer n /\ z = Cx(&2 * n * pi)`,
1691   GEN_TAC THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o RAND_CONV)
1692    [COMPLEX_RING `z = Cx(&2) * z / Cx(&2)`] THEN
1693   REWRITE_TAC[CCOS_DOUBLE_CSIN; COMPLEX_RING
1694    `a - Cx(&2) * s pow 2 = a <=> s = Cx(&0)`] THEN
1695   REWRITE_TAC[CSIN_EQ_0; CX_MUL] THEN
1696   EQ_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN
1697   CONV_TAC COMPLEX_RING);;
1698
1699 let CSIN_EQ_1 = prove
1700  (`!z. csin z = Cx(&1) <=> ?n. integer n /\ z = Cx((&2 * n + &1 / &2) * pi)`,
1701   GEN_TAC THEN MP_TAC(SPEC `z - Cx(pi / &2)` CCOS_EQ_1) THEN
1702   REWRITE_TAC[CCOS_SUB; GSYM CX_SIN; GSYM CX_COS; SIN_PI2; COS_PI2] THEN
1703   SIMP_TAC[COMPLEX_RING `s * Cx(&0) + c * Cx(&1) = Cx(&1) <=> c = Cx(&1)`] THEN
1704   REWRITE_TAC[REAL_ADD_RDISTRIB; COMPLEX_EQ_SUB_RADD; CX_ADD] THEN
1705   REWRITE_TAC[REAL_MUL_ASSOC; REAL_ARITH `&1 / &2 * x = x / &2`]);;
1706
1707 let CSIN_EQ_MINUS1 = prove
1708  (`!z. csin z = --Cx(&1) <=>
1709        ?n. integer n /\ z = Cx((&2 * n + &3 / &2) * pi)`,
1710   GEN_TAC THEN REWRITE_TAC[COMPLEX_RING `z:complex = --w <=> --z = w`] THEN
1711   REWRITE_TAC[GSYM CSIN_NEG; CSIN_EQ_1] THEN
1712   REWRITE_TAC[COMPLEX_RING `--z:complex = w <=> z = --w`] THEN
1713   EQ_TAC THEN DISCH_THEN(X_CHOOSE_THEN `n:real` STRIP_ASSUME_TAC) THEN
1714   ASM_REWRITE_TAC[GSYM CX_NEG; CX_INJ] THEN
1715   EXISTS_TAC `--(n + &1)` THEN
1716   ASM_SIMP_TAC[INTEGER_CLOSED] THEN REAL_ARITH_TAC);;
1717
1718 let CCOS_EQ_MINUS1 = prove
1719  (`!z. ccos z = --Cx(&1) <=>
1720        ?n. integer n /\ z = Cx((&2 * n + &1) * pi)`,
1721   GEN_TAC THEN MP_TAC(SPEC `z - Cx(pi / &2)` CSIN_EQ_1) THEN
1722   REWRITE_TAC[CSIN_SUB; GSYM CX_SIN; GSYM CX_COS; SIN_PI2; COS_PI2] THEN
1723   SIMP_TAC[COMPLEX_RING
1724     `s * Cx(&0) - c * Cx(&1) = Cx(&1) <=> c = --Cx(&1)`] THEN
1725   REWRITE_TAC[REAL_ADD_RDISTRIB; COMPLEX_EQ_SUB_RADD; GSYM CX_ADD] THEN
1726   DISCH_TAC THEN EQ_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN
1727   SIMP_TAC[CX_INJ] THEN REAL_ARITH_TAC);;
1728
1729 let COS_EQ_1 = prove
1730  (`!x. cos x = &1 <=> ?n. integer n /\ x = &2 * n * pi`,
1731   REWRITE_TAC[GSYM CX_INJ; CX_COS; CCOS_EQ_1]);;
1732
1733 let SIN_EQ_1 = prove
1734  (`!x. sin x = &1 <=> ?n. integer n /\ x = (&2 * n + &1 / &2) * pi`,
1735   REWRITE_TAC[GSYM CX_INJ; CX_SIN; CSIN_EQ_1]);;
1736
1737 let SIN_EQ_MINUS1 = prove
1738  (`!x. sin x = --(&1) <=> ?n. integer n /\ x = (&2 * n + &3 / &2) * pi`,
1739   REWRITE_TAC[GSYM CX_INJ; CX_NEG; CX_SIN; CSIN_EQ_MINUS1]);;
1740
1741 let COS_EQ_MINUS1 = prove
1742  (`!x. cos x = --(&1) <=>
1743        ?n. integer n /\ x = (&2 * n + &1) * pi`,
1744   REWRITE_TAC[GSYM CX_INJ; CX_NEG; CX_COS; CCOS_EQ_MINUS1]);;
1745
1746 let DIST_CEXP_II_1 = prove
1747  (`!z. norm(cexp(ii * Cx t) - Cx(&1)) = &2 * abs(sin(t / &2))`,
1748   GEN_TAC THEN REWRITE_TAC[NORM_EQ_SQUARE] THEN
1749   CONJ_TAC THENL [REAL_ARITH_TAC; REWRITE_TAC[GSYM NORM_POW_2]] THEN
1750   REWRITE_TAC[CEXP_EULER; COMPLEX_SQNORM; GSYM CX_COS; GSYM CX_SIN] THEN
1751   REWRITE_TAC[IM_ADD; RE_ADD; IM_SUB; RE_SUB; IM_MUL_II; RE_MUL_II] THEN
1752   REWRITE_TAC[RE_CX; IM_CX; REAL_POW2_ABS; REAL_POW_MUL] THEN
1753   MP_TAC(ISPEC `t / &2` COS_DOUBLE_SIN) THEN
1754   REWRITE_TAC[REAL_ARITH `&2 * t / &2 = t`] THEN
1755   MP_TAC(SPEC `t:real` SIN_CIRCLE) THEN CONV_TAC REAL_RING);;
1756
1757 let CX_SINH = prove
1758  (`Cx((exp x - inv(exp x)) / &2) = --ii * csin(ii * Cx x)`,
1759   REWRITE_TAC[csin; COMPLEX_RING `--ii * ii * z = z /\ ii * ii * z = --z`] THEN
1760   REWRITE_TAC[CEXP_NEG; GSYM CX_EXP; GSYM CX_INV; CX_SUB; CX_DIV] THEN
1761   CONV_TAC COMPLEX_FIELD);;
1762
1763 let CX_COSH = prove
1764  (`Cx((exp x + inv(exp x)) / &2) = ccos(ii * Cx x)`,
1765   REWRITE_TAC[ccos; COMPLEX_RING `--ii * ii * z = z /\ ii * ii * z = --z`] THEN
1766   REWRITE_TAC[CEXP_NEG; GSYM CX_EXP; GSYM CX_INV; CX_ADD; CX_DIV] THEN
1767   CONV_TAC COMPLEX_FIELD);;
1768
1769 let NORM_CCOS_POW_2 = prove
1770  (`!z. norm(ccos z) pow 2 =
1771        cos(Re z) pow 2 + (exp(Im z) - inv(exp(Im z))) pow 2 / &4`,
1772   REWRITE_TAC[FORALL_COMPLEX; RE; IM] THEN
1773   REWRITE_TAC[COMPLEX_TRAD; CCOS_ADD; COMPLEX_SQNORM] THEN
1774   SIMP_TAC[RE_SUB; IM_SUB; GSYM CX_COS; GSYM CX_SIN; IM_MUL_CX; RE_MUL_CX] THEN
1775   REWRITE_TAC[ccos; csin; CEXP_NEG; COMPLEX_FIELD
1776    `--ii * ii * z = z /\ ii * ii * z = --z /\
1777     z / (Cx(&2) * ii) = --(ii * z / Cx(&2))`] THEN
1778   REWRITE_TAC[RE_ADD; RE_SUB; IM_ADD; IM_SUB; RE_MUL_II; IM_MUL_II;
1779               RE_DIV_CX; IM_DIV_CX; RE_NEG; IM_NEG] THEN
1780   REWRITE_TAC[GSYM CX_EXP; GSYM CX_INV; IM_CX; RE_CX] THEN
1781   MAP_EVERY X_GEN_TAC [`x:real`; `y:real`] THEN
1782   MP_TAC(SPEC `x:real` SIN_CIRCLE) THEN MP_TAC(SPEC `y:real` REAL_EXP_NZ) THEN
1783   CONV_TAC REAL_FIELD);;
1784
1785 let NORM_CSIN_POW_2 = prove
1786  (`!z. norm(csin z) pow 2 =
1787        (exp(&2 * Im z) + inv(exp(&2 * Im z)) - &2 * cos(&2 * Re z)) / &4`,
1788   REWRITE_TAC[FORALL_COMPLEX; RE; IM] THEN
1789   REWRITE_TAC[COMPLEX_TRAD; CSIN_ADD; COMPLEX_SQNORM] THEN
1790   SIMP_TAC[RE_ADD; IM_ADD; GSYM CX_SIN; GSYM CX_SIN; IM_MUL_CX; RE_MUL_CX;
1791            GSYM CX_COS] THEN
1792   REWRITE_TAC[ccos; csin; CEXP_NEG; COMPLEX_FIELD
1793    `--ii * ii * z = z /\ ii * ii * z = --z /\
1794     z / (Cx(&2) * ii) = --(ii * z / Cx(&2))`] THEN
1795   REWRITE_TAC[RE_ADD; RE_SUB; IM_ADD; IM_SUB; RE_MUL_II; IM_MUL_II;
1796               RE_DIV_CX; IM_DIV_CX; RE_NEG; IM_NEG] THEN
1797   REWRITE_TAC[GSYM CX_EXP; GSYM CX_INV; IM_CX; RE_CX] THEN
1798   REWRITE_TAC[REAL_EXP_N; COS_DOUBLE] THEN
1799   MAP_EVERY X_GEN_TAC [`x:real`; `y:real`] THEN
1800   MP_TAC(SPEC `x:real` SIN_CIRCLE) THEN MP_TAC(SPEC `y:real` REAL_EXP_NZ) THEN
1801   CONV_TAC REAL_FIELD);;
1802
1803 let CSIN_EQ = prove
1804  (`!w z. csin w = csin z <=>
1805          ?n. integer n /\
1806              (w = z + Cx(&2 * n * pi) \/ w = --z + Cx((&2 * n + &1) * pi))`,
1807   REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM COMPLEX_SUB_0] THEN
1808   REWRITE_TAC[COMPLEX_SUB_CSIN; COMPLEX_ENTIRE; CSIN_EQ_0; CCOS_EQ_0] THEN
1809   REWRITE_TAC[CX_INJ; REAL_OF_NUM_EQ; ARITH_EQ; OR_EXISTS_THM] THEN
1810   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:real` THEN
1811   ASM_CASES_TAC `integer(n)` THEN
1812   ASM_REWRITE_TAC[COMPLEX_FIELD `a / Cx(&2) = b <=> a = Cx(&2) * b`] THEN
1813   REWRITE_TAC[GSYM CX_MUL; REAL_ARITH
1814     `&2 * (n + &1 / &2) * pi = (&2 * n + &1) * pi`] THEN
1815   CONV_TAC COMPLEX_RING);;
1816
1817 let CCOS_EQ = prove
1818  (`!w z. ccos(w) = ccos(z) <=>
1819          ?n. integer n /\
1820              (w = z + Cx(&2 * n * pi) \/ w = --z + Cx(&2 * n * pi))`,
1821   REPEAT GEN_TAC THEN CONV_TAC(LAND_CONV SYM_CONV) THEN
1822   GEN_REWRITE_TAC LAND_CONV [GSYM COMPLEX_SUB_0] THEN
1823   REWRITE_TAC[COMPLEX_SUB_CCOS; COMPLEX_ENTIRE; CSIN_EQ_0] THEN
1824   REWRITE_TAC[CX_INJ; REAL_OF_NUM_EQ; ARITH_EQ; OR_EXISTS_THM] THEN
1825   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `n:real` THEN
1826   ASM_CASES_TAC `integer(n)` THEN ASM_REWRITE_TAC[CX_MUL] THEN
1827   CONV_TAC COMPLEX_RING);;
1828
1829 let SIN_EQ = prove
1830  (`!x y. sin x = sin y <=>
1831          ?n. integer n /\
1832              (x = y + &2 * n * pi \/ x = --y + (&2 * n + &1) * pi)`,
1833   REWRITE_TAC[GSYM CX_INJ; CX_SIN; CSIN_EQ] THEN
1834   REWRITE_TAC[GSYM CX_ADD; GSYM CX_NEG; CX_INJ]);;
1835
1836 let COS_EQ = prove
1837  (`!x y. cos x = cos y <=>
1838          ?n. integer n /\
1839              (x = y + &2 * n * pi \/ x = --y + &2 * n * pi)`,
1840   REWRITE_TAC[GSYM CX_INJ; CX_COS; CCOS_EQ] THEN
1841   REWRITE_TAC[GSYM CX_ADD; GSYM CX_NEG; CX_INJ]);;
1842
1843 let NORM_CCOS_LE = prove
1844  (`!z. norm(ccos z) <= exp(norm z)`,
1845   GEN_TAC THEN REWRITE_TAC[ccos] THEN
1846   REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_CX; REAL_ABS_NUM] THEN
1847   REWRITE_TAC[REAL_ARITH `x / &2 <= y <=> x <= &2 * y`] THEN
1848   MATCH_MP_TAC(NORM_ARITH
1849    `norm(a) + norm(b) <= d ==> norm(a + b) <= d`) THEN
1850   REWRITE_TAC[NORM_CEXP; COMPLEX_MUL_LNEG; RE_NEG; REAL_EXP_NEG] THEN
1851   REWRITE_TAC[COMPLEX_NORM_CX; RE_MUL_II; REAL_ABS_NUM] THEN
1852   MATCH_MP_TAC(REAL_ARITH
1853    `exp(&0) = &1 /\ (exp(&0) <= w \/ exp(&0) <= z) /\ (w <= u /\ z <= u)
1854     ==> w + z <= &2 * u`) THEN
1855   REWRITE_TAC[GSYM REAL_EXP_NEG; REAL_EXP_MONO_LE] THEN
1856   REWRITE_TAC[REAL_EXP_0] THEN
1857   MP_TAC(SPEC `z:complex` COMPLEX_NORM_GE_RE_IM) THEN
1858   REAL_ARITH_TAC);;
1859
1860 let NORM_CCOS_PLUS1_LE = prove
1861  (`!z. norm(Cx(&1) + ccos z) <= &2 * exp(norm z)`,
1862   GEN_TAC THEN REWRITE_TAC[ccos] THEN
1863   REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_CX; REAL_ABS_NUM; COMPLEX_RING
1864    `Cx(&1) + (z + z') / Cx(&2) = (Cx(&2) + z + z') / Cx(&2)`] THEN
1865   REWRITE_TAC[REAL_ARITH `x / &2 <= &2 * y <=> x <= &4 * y`] THEN
1866   MATCH_MP_TAC(NORM_ARITH
1867    `norm(a) + norm(b) + norm(c) <= d ==> norm(a + b + c) <= d`) THEN
1868   REWRITE_TAC[NORM_CEXP; COMPLEX_MUL_LNEG; RE_NEG; REAL_EXP_NEG] THEN
1869   REWRITE_TAC[COMPLEX_NORM_CX; RE_MUL_II; REAL_ABS_NUM] THEN
1870   MATCH_MP_TAC(REAL_ARITH
1871    `exp(&0) = &1 /\ (exp(&0) <= w \/ exp(&0) <= z) /\ (w <= u /\ z <= u)
1872     ==> &2 + w + z <= &4 * u`) THEN
1873   REWRITE_TAC[GSYM REAL_EXP_NEG; REAL_EXP_MONO_LE] THEN
1874   REWRITE_TAC[REAL_EXP_0] THEN
1875   MP_TAC(SPEC `z:complex` COMPLEX_NORM_GE_RE_IM) THEN
1876   REAL_ARITH_TAC);;
1877
1878 (* ------------------------------------------------------------------------- *)
1879 (* Taylor series for complex exponential.                                    *)
1880 (* ------------------------------------------------------------------------- *)
1881
1882 let TAYLOR_CEXP = prove
1883  (`!n z. norm(cexp z - vsum(0..n) (\k. z pow k / Cx(&(FACT k))))
1884          <= exp(abs(Re z)) * (norm z) pow (n + 1) / &(FACT n)`,
1885   REPEAT GEN_TAC THEN MP_TAC(ISPECL
1886    [`\k:num. cexp`; `n:num`; `segment[Cx(&0),z]`; `exp(abs(Re z))`]
1887         COMPLEX_TAYLOR) THEN
1888   REWRITE_TAC[CONVEX_SEGMENT; NORM_CEXP; REAL_EXP_MONO_LE] THEN ANTS_TAC THENL
1889    [REWRITE_TAC[IN_SEGMENT] THEN REPEAT STRIP_TAC THENL
1890      [GEN_REWRITE_TAC(RATOR_CONV o LAND_CONV) [GSYM ETA_AX] THEN
1891       COMPLEX_DIFF_TAC THEN REWRITE_TAC[COMPLEX_MUL_LID];
1892       ASM_REWRITE_TAC[GSYM COMPLEX_VEC_0; VECTOR_MUL_RZERO] THEN
1893       REWRITE_TAC[VECTOR_ADD_LID; COMPLEX_CMUL; COMPLEX_NORM_MUL] THEN
1894       GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN
1895       MATCH_MP_TAC(REAL_ARITH `abs x <= a ==> x <= a`) THEN
1896       REWRITE_TAC[RE_MUL_CX; REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_RMUL THEN
1897       ASM_REAL_ARITH_TAC];
1898     DISCH_THEN(MP_TAC o SPECL [`Cx(&0)`; `z:complex`]) THEN
1899     SIMP_TAC[ENDS_IN_SEGMENT; COMPLEX_SUB_RZERO; CEXP_0; COMPLEX_MUL_LID]]);;
1900
1901 (* ------------------------------------------------------------------------- *)
1902 (* Approximation to e.                                                       *)
1903 (* ------------------------------------------------------------------------- *)
1904
1905 let E_APPROX_32 = prove
1906  (`abs(exp(&1) - &5837465777 / &2147483648) <= inv(&2 pow 32)`,
1907   MP_TAC(ISPECL [`14`; `Cx(&1)`] TAYLOR_CEXP) THEN
1908   SIMP_TAC[RE_CX; REAL_ABS_NUM; GSYM CX_EXP; GSYM CX_DIV; GSYM CX_SUB;
1909            COMPLEX_POW_ONE; COMPLEX_NORM_CX] THEN
1910   CONV_TAC(ONCE_DEPTH_CONV EXPAND_VSUM_CONV) THEN
1911   REWRITE_TAC[GSYM CX_ADD; GSYM CX_SUB; COMPLEX_NORM_CX] THEN
1912   CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
1913   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REAL_ARITH_TAC);;
1914
1915 (* ------------------------------------------------------------------------- *)
1916 (* Taylor series for complex sine and cosine.                                *)
1917 (* ------------------------------------------------------------------------- *)
1918
1919 let TAYLOR_CSIN_RAW = prove
1920  (`!n z. norm(csin z -
1921               vsum(0..n) (\k. if ODD k
1922                               then --ii * (ii * z) pow k / Cx(&(FACT k))
1923                               else Cx(&0)))
1924          <= exp(abs(Im z)) * (norm z) pow (n + 1) / &(FACT n)`,
1925   MP_TAC TAYLOR_CEXP THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:num` THEN
1926   DISCH_TAC THEN X_GEN_TAC `z:complex` THEN REWRITE_TAC[csin] THEN
1927   REWRITE_TAC[COMPLEX_FIELD
1928     `a / (Cx(&2) * ii) - b = (a - Cx(&2) * ii * b) / (Cx(&2) * ii)`] THEN
1929   FIRST_ASSUM(fun th ->
1930     MP_TAC(SPEC `ii * z` th) THEN MP_TAC(SPEC `--ii * z` th)) THEN
1931   REWRITE_TAC[COMPLEX_MUL_LNEG; RE_NEG; REAL_ABS_NEG; RE_MUL_II] THEN
1932   REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_MUL; COMPLEX_NORM_CX; NORM_NEG;
1933               COMPLEX_NORM_II; REAL_ABS_NUM; REAL_MUL_RID; REAL_MUL_LID;
1934               REAL_ARITH `x / &2 <= y <=> x <= &2 * y`] THEN
1935   MATCH_MP_TAC(NORM_ARITH
1936    `sp - sn = s2
1937     ==> norm(en - sn) <= d
1938         ==> norm(ep - sp) <= d ==> norm(ep - en - s2) <= &2 * d`) THEN
1939   SIMP_TAC[GSYM VSUM_SUB; GSYM VSUM_COMPLEX_LMUL; FINITE_NUMSEG] THEN
1940   MATCH_MP_TAC VSUM_EQ THEN X_GEN_TAC `k:num` THEN DISCH_TAC THEN
1941   REWRITE_TAC[COMPLEX_POW_NEG; GSYM NOT_EVEN] THEN ASM_CASES_TAC `EVEN k` THEN
1942   ASM_REWRITE_TAC[COMPLEX_SUB_REFL; COMPLEX_MUL_RZERO] THEN
1943   REWRITE_TAC[COMPLEX_RING `Cx(&2) * ii * --(ii * z) = Cx(&2) * z`] THEN
1944   SIMPLE_COMPLEX_ARITH_TAC);;
1945
1946 let TAYLOR_CSIN = prove
1947  (`!n z. norm(csin z -
1948               vsum(0..n) (\k. --Cx(&1) pow k *
1949                               z pow (2 * k + 1) / Cx(&(FACT(2 * k + 1)))))
1950          <= exp(abs(Im z)) * norm(z) pow (2 * n + 3) / &(FACT(2 * n + 2))`,
1951   REPEAT STRIP_TAC THEN
1952   MP_TAC(ISPECL [`SUC(2 * n + 1)`; `z:complex`] TAYLOR_CSIN_RAW) THEN
1953   SIMP_TAC[VSUM_CLAUSES_NUMSEG; VSUM_PAIR_0; ODD_ADD; ODD_MULT; ARITH_ODD;
1954            LE_0; ODD; COMPLEX_ADD_LID; COMPLEX_ADD_RID] THEN
1955   SIMP_TAC[ARITH_RULE `SUC(2 * n + 1) = 2 * n + 2`; GSYM ADD_ASSOC; ARITH] THEN
1956   MATCH_MP_TAC(NORM_ARITH
1957    `s = t ==> norm(x - s) <= e ==> norm(x - t) <= e`) THEN
1958   MATCH_MP_TAC VSUM_EQ THEN X_GEN_TAC `k:num` THEN STRIP_TAC THEN
1959   REWRITE_TAC[COMPLEX_POW_MUL; complex_div; COMPLEX_MUL_ASSOC] THEN
1960   AP_THM_TAC THEN AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
1961   REWRITE_TAC[COMPLEX_POW_ADD; GSYM COMPLEX_POW_POW] THEN
1962   REWRITE_TAC[COMPLEX_POW_II_2] THEN CONV_TAC COMPLEX_RING);;
1963
1964 let CSIN_CONVERGES = prove
1965  (`!z. ((\n. --Cx(&1) pow n * z pow (2 * n + 1) / Cx(&(FACT(2 * n + 1))))
1966         sums csin(z)) (from 0)`,
1967   GEN_TAC THEN REWRITE_TAC[sums; FROM_0; INTER_UNIV] THEN
1968   ONCE_REWRITE_TAC[LIM_NULL] THEN MATCH_MP_TAC LIM_NULL_COMPARISON THEN
1969   EXISTS_TAC
1970    `\n. exp(abs(Im z)) * norm z pow (2 * n + 3) / &(FACT(2 * n + 2))` THEN
1971   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
1972   ONCE_REWRITE_TAC[NORM_SUB] THEN REWRITE_TAC[TAYLOR_CSIN] THEN
1973   REWRITE_TAC[LIFT_CMUL] THEN MATCH_MP_TAC LIM_NULL_CMUL THEN
1974   REWRITE_TAC[ARITH_RULE `2 * n + 3 = SUC(2 * n + 2)`; real_div] THEN
1975   REWRITE_TAC[LIFT_CMUL; real_pow] THEN
1976   REWRITE_TAC[GSYM VECTOR_MUL_ASSOC] THEN
1977   MATCH_MP_TAC LIM_NULL_CMUL THEN
1978   MP_TAC(MATCH_MP SERIES_TERMS_TOZERO (SPEC `z:complex` CEXP_CONVERGES)) THEN
1979   GEN_REWRITE_TAC LAND_CONV [LIM_NULL_NORM] THEN
1980   REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_POW; COMPLEX_NORM_CX] THEN
1981   REWRITE_TAC[REAL_ABS_NUM; GSYM LIFT_CMUL; GSYM real_div] THEN
1982   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
1983   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
1984   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
1985   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC);;
1986
1987 let TAYLOR_CCOS_RAW = prove
1988  (`!n z. norm(ccos z -
1989               vsum(0..n) (\k. if EVEN k
1990                               then (ii * z) pow k / Cx(&(FACT k))
1991                               else Cx(&0)))
1992          <= exp(abs(Im z)) * (norm z) pow (n + 1) / &(FACT n)`,
1993   MP_TAC TAYLOR_CEXP THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:num` THEN
1994   DISCH_TAC THEN X_GEN_TAC `z:complex` THEN REWRITE_TAC[ccos] THEN
1995   REWRITE_TAC[COMPLEX_FIELD
1996     `a / Cx(&2) - b = (a - Cx(&2) * b) / Cx(&2)`] THEN
1997   FIRST_ASSUM(fun th ->
1998     MP_TAC(SPEC `ii * z` th) THEN MP_TAC(SPEC `--ii * z` th)) THEN
1999   REWRITE_TAC[COMPLEX_MUL_LNEG; RE_NEG; REAL_ABS_NEG; RE_MUL_II] THEN
2000   REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_MUL; COMPLEX_NORM_CX; NORM_NEG;
2001               COMPLEX_NORM_II; REAL_ABS_NUM; REAL_MUL_RID; REAL_MUL_LID;
2002               REAL_ARITH `x / &2 <= y <=> x <= &2 * y`] THEN
2003   MATCH_MP_TAC(NORM_ARITH
2004    `sp + sn = s2
2005     ==> norm(en - sn) <= d
2006         ==> norm(ep - sp) <= d ==> norm((ep + en) - s2) <= &2 * d`) THEN
2007   SIMP_TAC[GSYM VSUM_ADD; GSYM VSUM_COMPLEX_LMUL; FINITE_NUMSEG] THEN
2008   MATCH_MP_TAC VSUM_EQ THEN X_GEN_TAC `k:num` THEN DISCH_TAC THEN
2009   REWRITE_TAC[COMPLEX_POW_NEG; GSYM NOT_EVEN] THEN ASM_CASES_TAC `EVEN k` THEN
2010   ASM_REWRITE_TAC[COMPLEX_ADD_RINV; COMPLEX_MUL_RZERO] THEN
2011   SIMPLE_COMPLEX_ARITH_TAC);;
2012
2013 let TAYLOR_CCOS = prove
2014  (`!n z. norm(ccos z -
2015               vsum(0..n) (\k. --Cx(&1) pow k *
2016                               z pow (2 * k) / Cx(&(FACT(2 * k)))))
2017          <= exp(abs(Im z)) * norm(z) pow (2 * n + 2) / &(FACT(2 * n + 1))`,
2018   REPEAT STRIP_TAC THEN
2019   MP_TAC(ISPECL [`2 * n + 1`; `z:complex`] TAYLOR_CCOS_RAW) THEN
2020   SIMP_TAC[VSUM_PAIR_0; EVEN_ADD; EVEN_MULT; ARITH_EVEN;
2021            LE_0; EVEN; COMPLEX_ADD_LID; COMPLEX_ADD_RID] THEN
2022   SIMP_TAC[ARITH_RULE `(2 * n + 1) + 1 = 2 * n + 2`] THEN
2023   MATCH_MP_TAC(NORM_ARITH
2024    `s = t ==> norm(x - s) <= e ==> norm(x - t) <= e`) THEN
2025   MATCH_MP_TAC VSUM_EQ THEN X_GEN_TAC `k:num` THEN STRIP_TAC THEN
2026   REWRITE_TAC[COMPLEX_POW_MUL; complex_div; COMPLEX_MUL_ASSOC] THEN
2027   AP_THM_TAC THEN AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
2028   REWRITE_TAC[GSYM COMPLEX_POW_POW; COMPLEX_POW_II_2]);;
2029
2030 let CCOS_CONVERGES = prove
2031  (`!z. ((\n. --Cx(&1) pow n * z pow (2 * n) / Cx(&(FACT(2 * n))))
2032         sums ccos(z)) (from 0)`,
2033   GEN_TAC THEN REWRITE_TAC[sums; FROM_0; INTER_UNIV] THEN
2034   ONCE_REWRITE_TAC[LIM_NULL] THEN MATCH_MP_TAC LIM_NULL_COMPARISON THEN
2035   EXISTS_TAC
2036    `\n. exp(abs(Im z)) * norm z pow (2 * n + 2) / &(FACT(2 * n + 1))` THEN
2037   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
2038   ONCE_REWRITE_TAC[NORM_SUB] THEN REWRITE_TAC[TAYLOR_CCOS] THEN
2039   REWRITE_TAC[LIFT_CMUL] THEN MATCH_MP_TAC LIM_NULL_CMUL THEN
2040   REWRITE_TAC[ARITH_RULE `2 * n + 2 = SUC(2 * n + 1)`; real_div] THEN
2041   REWRITE_TAC[LIFT_CMUL; real_pow] THEN
2042   REWRITE_TAC[GSYM VECTOR_MUL_ASSOC] THEN
2043   MATCH_MP_TAC LIM_NULL_CMUL THEN
2044   MP_TAC(MATCH_MP SERIES_TERMS_TOZERO (SPEC `z:complex` CEXP_CONVERGES)) THEN
2045   GEN_REWRITE_TAC LAND_CONV [LIM_NULL_NORM] THEN
2046   REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_POW; COMPLEX_NORM_CX] THEN
2047   REWRITE_TAC[REAL_ABS_NUM; GSYM LIFT_CMUL; GSYM real_div] THEN
2048   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
2049   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
2050   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
2051   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC);;
2052
2053 (* ------------------------------------------------------------------------- *)
2054 (* The argument of a complex number, where 0 <= arg(z) < 2 pi                *)
2055 (* ------------------------------------------------------------------------- *)
2056
2057 let Arg_DEF = new_definition
2058  `Arg z = if z = Cx(&0) then &0
2059           else @t. &0 <= t /\ t < &2 * pi /\
2060                    z = Cx(norm(z)) * cexp(ii * Cx t)`;;
2061
2062 let ARG_0 = prove
2063  (`Arg(Cx(&0)) = &0`,
2064   REWRITE_TAC[Arg_DEF]);;
2065
2066 let ARG = prove
2067  (`!z. &0 <= Arg(z) /\ Arg(z) < &2 * pi /\
2068        z = Cx(norm z) * cexp(ii * Cx(Arg z))`,
2069   GEN_TAC THEN REWRITE_TAC[Arg_DEF] THEN
2070   COND_CASES_TAC THEN ASM_REWRITE_TAC[COMPLEX_NORM_0; COMPLEX_MUL_LZERO] THEN
2071   SIMP_TAC[REAL_LE_REFL; REAL_LT_MUL; PI_POS; REAL_ARITH `&0 < &2`] THEN
2072   CONV_TAC SELECT_CONV THEN
2073   MP_TAC(SPECL [`Re(z) / norm z`; `Im(z) / norm z`]
2074         SINCOS_TOTAL_2PI) THEN
2075   ASM_SIMP_TAC[COMPLEX_SQNORM; COMPLEX_NORM_ZERO; REAL_FIELD
2076     `~(z = &0) /\ x pow 2 + y pow 2 = z pow 2
2077       ==> (x / z) pow 2 + (y / z) pow 2 = &1`] THEN
2078   MATCH_MP_TAC MONO_EXISTS THEN
2079   ASM_SIMP_TAC[COMPLEX_NORM_ZERO; REAL_FIELD
2080    `~(z = &0) ==> (x / z = y <=> x = z * y)`] THEN
2081   REWRITE_TAC[COMPLEX_EQ; RE_MUL_CX; IM_MUL_CX; CEXP_EULER; RE_ADD; IM_ADD;
2082         RE_MUL_II; IM_MUL_II; GSYM CX_SIN; GSYM CX_COS; RE_CX; IM_CX] THEN
2083   REAL_ARITH_TAC);;
2084
2085 let COMPLEX_NORM_EQ_1_CEXP = prove
2086  (`!z. norm z = &1 <=> (?t. z = cexp(ii * Cx t))`,
2087   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
2088   ASM_REWRITE_TAC [NORM_CEXP; RE_MUL_II; IM_CX; REAL_NEG_0; REAL_EXP_0] THEN
2089   MP_TAC (SPEC `z:complex` ARG) THEN ASM_REWRITE_TAC [COMPLEX_MUL_LID] THEN
2090   MESON_TAC[]);;
2091
2092 let ARG_UNIQUE = prove
2093  (`!a r z. &0 < r /\ Cx r * cexp(ii * Cx a) = z /\ &0 <= a /\ a < &2 * pi
2094            ==> Arg z = a`,
2095   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM CX_INJ] THEN
2096   MATCH_MP_TAC(COMPLEX_RING `ii * x = ii * y ==> x = y`) THEN
2097   MATCH_MP_TAC COMPLEX_EQ_CEXP THEN CONJ_TAC THENL
2098    [REWRITE_TAC[IM_MUL_II; RE_CX] THEN
2099     MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ x < p /\ &0 <= y /\ y < p
2100                              ==> abs(x - y) < p`) THEN
2101     ASM_SIMP_TAC[ARG];
2102     MATCH_MP_TAC(COMPLEX_RING
2103      `!a b. Cx a = Cx b /\ ~(Cx b = Cx(&0)) /\
2104             Cx a * w = Cx b * z ==> w = z`) THEN
2105     MAP_EVERY EXISTS_TAC [`norm(z:complex)`; `r:real`] THEN
2106     ASM_REWRITE_TAC[GSYM ARG] THEN ASM_SIMP_TAC[CX_INJ; REAL_LT_IMP_NZ] THEN
2107     EXPAND_TAC "z" THEN
2108     REWRITE_TAC[NORM_CEXP_II; COMPLEX_NORM_MUL; COMPLEX_NORM_CX] THEN
2109     ASM_REAL_ARITH_TAC]);;
2110
2111 let ARG_MUL_CX = prove
2112  (`!r z. &0 < r ==> Arg(Cx r * z) = Arg(z)`,
2113   REPEAT STRIP_TAC THEN
2114   ASM_CASES_TAC `z = Cx(&0)` THEN ASM_REWRITE_TAC[COMPLEX_MUL_RZERO] THEN
2115   MATCH_MP_TAC ARG_UNIQUE THEN EXISTS_TAC `r * norm(z:complex)` THEN
2116   ASM_REWRITE_TAC[CX_MUL; GSYM COMPLEX_MUL_ASSOC; GSYM ARG] THEN
2117   ASM_SIMP_TAC[REAL_LT_MUL; COMPLEX_NORM_NZ]);;
2118
2119 let ARG_DIV_CX = prove
2120  (`!r z. &0 < r ==> Arg(z / Cx r) = Arg(z)`,
2121   REWRITE_TAC[ONCE_REWRITE_RULE[COMPLEX_MUL_SYM] complex_div] THEN
2122   SIMP_TAC[GSYM CX_INV; ARG_MUL_CX; REAL_LT_INV_EQ]);;
2123
2124 let ARG_LT_NZ = prove
2125  (`!z. &0 < Arg z <=> ~(Arg z = &0)`,
2126   MP_TAC ARG THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
2127
2128 let ARG_LE_PI = prove
2129  (`!z. Arg z <= pi <=> &0 <= Im z`,
2130   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THENL
2131    [ASM_REWRITE_TAC[Arg_DEF; IM_CX; REAL_LE_REFL; PI_POS_LE]; ALL_TAC] THEN
2132   GEN_REWRITE_TAC (funpow 3 RAND_CONV) [ARG] THEN
2133   ASM_SIMP_TAC[IM_MUL_CX; CEXP_EULER; REAL_LE_MUL_EQ; COMPLEX_NORM_NZ] THEN
2134   REWRITE_TAC[IM_ADD; GSYM CX_SIN; GSYM CX_COS; IM_CX; IM_MUL_II; RE_CX] THEN
2135   REWRITE_TAC[REAL_ADD_LID] THEN EQ_TAC THEN SIMP_TAC[ARG; SIN_POS_PI_LE] THEN
2136   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
2137   SUBGOAL_THEN `&0 < sin(&2 * pi - Arg z)` MP_TAC THENL
2138    [MATCH_MP_TAC SIN_POS_PI THEN MP_TAC(SPEC `z:complex` ARG) THEN
2139     ASM_REAL_ARITH_TAC;
2140     REWRITE_TAC[SIN_SUB; SIN_NPI; COS_NPI] THEN REAL_ARITH_TAC]);;
2141
2142 let ARG_LT_PI = prove
2143  (`!z. &0 < Arg z /\ Arg z < pi <=> &0 < Im z`,
2144   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THENL
2145    [ASM_REWRITE_TAC[Arg_DEF; IM_CX; REAL_LT_REFL; PI_POS_LE]; ALL_TAC] THEN
2146   GEN_REWRITE_TAC (funpow 3 RAND_CONV) [ARG] THEN
2147   ASM_SIMP_TAC[IM_MUL_CX; CEXP_EULER; REAL_LT_MUL_EQ; COMPLEX_NORM_NZ] THEN
2148   REWRITE_TAC[IM_ADD; GSYM CX_SIN; GSYM CX_COS; IM_CX; IM_MUL_II; RE_CX] THEN
2149   REWRITE_TAC[REAL_ADD_LID] THEN EQ_TAC THEN SIMP_TAC[SIN_POS_PI] THEN
2150   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
2151   ASM_CASES_TAC `Arg z = &0` THEN
2152   ASM_REWRITE_TAC[SIN_0; REAL_LT_REFL] THEN
2153   ASM_SIMP_TAC[ARG; REAL_ARITH `~(x = &0) ==> (&0 < x <=> &0 <= x)`] THEN
2154   DISCH_TAC THEN
2155   SUBGOAL_THEN `&0 <= sin(&2 * pi - Arg z)` MP_TAC THENL
2156    [MATCH_MP_TAC SIN_POS_PI_LE THEN MP_TAC(SPEC `z:complex` ARG) THEN
2157     ASM_REAL_ARITH_TAC;
2158     REWRITE_TAC[SIN_SUB; SIN_NPI; COS_NPI] THEN REAL_ARITH_TAC]);;
2159
2160 let ARG_EQ_0 = prove
2161  (`!z. Arg z = &0 <=> real z /\ &0 <= Re z`,
2162   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THENL
2163    [ASM_REWRITE_TAC[REAL_CX; RE_CX; Arg_DEF; REAL_LE_REFL]; ALL_TAC] THEN
2164   CONV_TAC(RAND_CONV(SUBS_CONV[last(CONJUNCTS(SPEC `z:complex` ARG))])) THEN
2165   ASM_SIMP_TAC[RE_MUL_CX; REAL_MUL_CX; REAL_LE_MUL_EQ; COMPLEX_NORM_NZ] THEN
2166   ASM_REWRITE_TAC[COMPLEX_NORM_ZERO; CEXP_EULER] THEN
2167   REWRITE_TAC[real; RE_ADD; IM_ADD; RE_MUL_II; IM_MUL_II;
2168               GSYM CX_SIN; GSYM CX_COS; RE_CX; IM_CX] THEN
2169   REWRITE_TAC[REAL_ADD_RID; REAL_ADD_LID; REAL_NEG_0] THEN
2170   EQ_TAC THEN SIMP_TAC[SIN_0; COS_0; REAL_POS] THEN
2171   ASM_CASES_TAC `Arg z = pi` THENL
2172    [ASM_REWRITE_TAC[COS_PI] THEN REAL_ARITH_TAC; ALL_TAC] THEN
2173   MP_TAC(SPEC `z:complex` ARG) THEN REWRITE_TAC[CONJ_ASSOC] THEN
2174   DISCH_THEN(MP_TAC o CONJUNCT1) THEN DISCH_THEN(STRIP_ASSUME_TAC o MATCH_MP
2175    (REAL_ARITH `&0 <= x /\ x < &2 * pi
2176                 ==> --pi < x /\ x < pi \/ --pi < x - pi /\ x - pi < pi`)) THEN
2177   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[SIN_EQ_0_PI] THEN
2178   UNDISCH_TAC `~(Arg z = pi)` THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
2179   DISCH_TAC THEN REWRITE_TAC[REAL_ARITH `x = pi <=> x - pi = &0`] THEN
2180   MATCH_MP_TAC SIN_EQ_0_PI THEN ASM_REWRITE_TAC[SIN_SUB; SIN_PI] THEN
2181   REAL_ARITH_TAC);;
2182
2183 let ARG_NUM = prove
2184  (`!n. Arg(Cx(&n)) = &0`,
2185   REWRITE_TAC[ARG_EQ_0; REAL_CX; RE_CX; REAL_POS]);;
2186
2187 let ARG_EQ_PI = prove
2188  (`!z. Arg z = pi <=> real z /\ Re z < &0`,
2189   SIMP_TAC[ARG; PI_POS; REAL_ARITH
2190     `&0 < pi /\ &0 <= z
2191      ==> (z = pi <=> z <= pi /\ ~(z = &0) /\ ~(&0 < z /\ z < pi))`] THEN
2192   REWRITE_TAC[ARG_EQ_0; ARG; ARG_LT_PI; ARG_LE_PI; real] THEN
2193   REAL_ARITH_TAC);;
2194
2195 let ARG_EQ_0_PI = prove
2196  (`!z. Arg z = &0 \/ Arg z = pi <=> real z`,
2197   REWRITE_TAC[ARG_EQ_0; ARG_EQ_PI; real] THEN REAL_ARITH_TAC);;
2198
2199 let ARG_INV = prove
2200  (`!z. ~(real z /\ &0 <= Re z) ==> Arg(inv z) = &2 * pi - Arg z`,
2201   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
2202   ASM_REWRITE_TAC[REAL_CX; RE_CX; REAL_LE_REFL] THEN
2203   REWRITE_TAC[real] THEN STRIP_TAC THEN MATCH_MP_TAC ARG_UNIQUE THEN
2204   EXISTS_TAC `inv(norm(z:complex))` THEN
2205   ASM_SIMP_TAC[COMPLEX_NORM_NZ; REAL_LT_INV_EQ] THEN
2206   REWRITE_TAC[CX_SUB; CX_MUL; COMPLEX_SUB_LDISTRIB; CEXP_SUB] THEN
2207   SUBST1_TAC(SPEC `Cx(&2) * Cx pi` CEXP_EULER) THEN
2208   REWRITE_TAC[GSYM CX_MUL; GSYM CX_SIN; GSYM CX_COS] THEN
2209   REWRITE_TAC[SIN_NPI; COS_NPI; COMPLEX_MUL_RZERO; COMPLEX_ADD_RID] THEN
2210   CONV_TAC REAL_RAT_REDUCE_CONV THEN
2211   REWRITE_TAC[complex_div; COMPLEX_MUL_LID; CX_INV; GSYM COMPLEX_INV_MUL] THEN
2212   REWRITE_TAC[GSYM ARG] THEN
2213   MP_TAC(SPEC `z:complex` ARG_EQ_0) THEN ASM_REWRITE_TAC[real] THEN
2214   MP_TAC(SPEC `z:complex` ARG) THEN REAL_ARITH_TAC);;
2215
2216 let ARG_EQ = prove
2217  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
2218          ==> (Arg w = Arg z <=> ?x. &0 < x /\ w = Cx(x) * z)`,
2219   REPEAT STRIP_TAC THEN EQ_TAC THENL
2220    [ALL_TAC; STRIP_TAC THEN ASM_SIMP_TAC[ARG_MUL_CX]] THEN
2221   DISCH_TAC THEN
2222   MAP_EVERY (MP_TAC o CONJUNCT2 o CONJUNCT2 o C SPEC ARG)
2223    [`z:complex`; `w:complex`] THEN
2224   ASM_REWRITE_TAC[IMP_IMP] THEN
2225   DISCH_THEN(fun th -> CONV_TAC(SUBS_CONV(CONJUNCTS th))) THEN
2226   EXISTS_TAC `norm(w:complex) / norm(z:complex)` THEN
2227   ASM_SIMP_TAC[REAL_LT_DIV; COMPLEX_NORM_NZ; CX_DIV] THEN
2228   REWRITE_TAC[COMPLEX_MUL_ASSOC] THEN AP_THM_TAC THEN AP_TERM_TAC THEN
2229   ASM_SIMP_TAC[COMPLEX_DIV_RMUL; COMPLEX_NORM_ZERO; CX_INJ]);;
2230
2231 let ARG_INV_EQ_0 = prove
2232  (`!z. Arg(inv z) = &0 <=> Arg z = &0`,
2233   GEN_TAC THEN REWRITE_TAC[ARG_EQ_0; REAL_INV_EQ] THEN
2234   MATCH_MP_TAC(TAUT `(a ==> (b <=> c)) ==> (a /\ b <=> a /\ c)`) THEN
2235   REWRITE_TAC[real] THEN DISCH_TAC THEN ASM_REWRITE_TAC[complex_inv; RE] THEN
2236   CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[REAL_ADD_RID] THEN
2237   ASM_CASES_TAC `Re z = &0` THEN ASM_REWRITE_TAC[real_div; REAL_MUL_LZERO] THEN
2238   ASM_SIMP_TAC[REAL_FIELD `~(x = &0) ==> x * inv(x pow 2) = inv x`] THEN
2239   REWRITE_TAC[REAL_LE_INV_EQ]);;
2240
2241 let ARG_LE_DIV_SUM = prove
2242  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0)) /\ Arg(w) <= Arg(z)
2243          ==> Arg(z) = Arg(w) + Arg(z / w)`,
2244   REPEAT STRIP_TAC THEN
2245   ONCE_REWRITE_TAC[REAL_ARITH `a:real = b + c <=> c = a - b`] THEN
2246   MATCH_MP_TAC ARG_UNIQUE THEN EXISTS_TAC `norm(z / w)`THEN
2247   ASM_SIMP_TAC[ARG; REAL_ARITH
2248    `&0 <= a /\ a < &2 * pi /\ &0 <= b /\ b <= a ==> a - b < &2 * pi`] THEN
2249   ASM_REWRITE_TAC[REAL_SUB_LE] THEN
2250   ASM_SIMP_TAC[COMPLEX_NORM_DIV; CX_DIV] THEN
2251   ASM_SIMP_TAC[REAL_LT_DIV; COMPLEX_NORM_NZ] THEN
2252   REWRITE_TAC[COMPLEX_SUB_LDISTRIB; CEXP_SUB; CX_SUB] THEN
2253   REWRITE_TAC[complex_div] THEN
2254   ONCE_REWRITE_TAC[COMPLEX_RING
2255    `(a * b) * (c * d):complex = (a * c) * (b * d)`] THEN
2256   REWRITE_TAC[GSYM COMPLEX_INV_MUL] THEN ASM_SIMP_TAC[GSYM ARG]);;
2257
2258 let ARG_LE_DIV_SUM_EQ = prove
2259  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
2260          ==> (Arg(w) <= Arg(z) <=> Arg(z) = Arg(w) + Arg(z / w))`,
2261   MESON_TAC[ARG_LE_DIV_SUM; REAL_LE_ADDR; ARG]);;
2262
2263 let REAL_SUB_ARG = prove
2264  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
2265          ==> Arg w - Arg z = if Arg(z) <= Arg(w) then Arg(w / z)
2266                              else Arg(w / z) - &2 * pi`,
2267   REPEAT STRIP_TAC THEN COND_CASES_TAC THENL
2268    [MP_TAC(ISPECL [`z:complex`; `w:complex`] ARG_LE_DIV_SUM) THEN
2269     ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
2270     MP_TAC(ISPECL [`w:complex`; `z:complex`] ARG_LE_DIV_SUM) THEN
2271     ASM_REWRITE_TAC[] THEN
2272     ANTS_TAC THENL [ASM_REAL_ARITH_TAC; DISCH_THEN SUBST1_TAC] THEN
2273     REWRITE_TAC[REAL_ARITH `a - (a + b):real = --b`] THEN
2274     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM COMPLEX_INV_DIV] THEN
2275     MATCH_MP_TAC(REAL_ARITH `x = &2 * pi - y ==> --x = y - &2 * pi`) THEN
2276     MATCH_MP_TAC ARG_INV THEN REWRITE_TAC[GSYM ARG_EQ_0] THEN
2277     ONCE_REWRITE_TAC[GSYM COMPLEX_INV_DIV] THEN
2278     REWRITE_TAC[ARG_INV_EQ_0] THEN
2279     MP_TAC(ISPECL [`w:complex`; `z:complex`] ARG_LE_DIV_SUM) THEN
2280     ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC]);;
2281
2282 let REAL_ADD_ARG = prove
2283  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
2284          ==> Arg(w) + Arg(z) =
2285              if Arg w + Arg z < &2 * pi
2286              then Arg(w * z)
2287              else Arg(w * z) + &2 * pi`,
2288   REPEAT STRIP_TAC THEN
2289   MP_TAC(SPECL [`w * z:complex`; `z:complex`] REAL_SUB_ARG) THEN
2290   MP_TAC(SPECL [`z:complex`; `w * z:complex`] ARG_LE_DIV_SUM_EQ) THEN
2291   ASM_SIMP_TAC[COMPLEX_ENTIRE; COMPLEX_FIELD
2292    `~(z = Cx(&0)) ==> (w * z) / z = w`] THEN
2293   ASM_CASES_TAC `Arg (w * z) = Arg z + Arg w` THEN ASM_REWRITE_TAC[] THENL
2294    [ASM_MESON_TAC[ARG; REAL_ADD_SYM];
2295     SIMP_TAC[REAL_ARITH `wz - z = w - &2 * pi <=> w + z = wz + &2 * pi`] THEN
2296     REWRITE_TAC[REAL_ARITH `w + p < p <=> ~(&0 <= w)`; ARG]]);;
2297
2298 let ARG_MUL = prove
2299  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
2300          ==> Arg(w * z) = if Arg w + Arg z < &2 * pi
2301                           then Arg w + Arg z
2302                           else (Arg w + Arg z) - &2 * pi`,
2303   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP REAL_ADD_ARG) THEN
2304   REAL_ARITH_TAC);;
2305
2306 let ARG_CNJ = prove
2307  (`!z. Arg(cnj z) = if real z /\ &0 <= Re z then Arg z else &2 * pi - Arg z`,
2308   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
2309   ASM_REWRITE_TAC[CNJ_CX; ARG_0; REAL_CX; RE_CX; REAL_LE_REFL] THEN
2310   COND_CASES_TAC THEN ASM_SIMP_TAC[REAL_IMP_CNJ] THEN
2311   MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `Arg(inv z)` THEN CONJ_TAC THENL
2312    [REWRITE_TAC[COMPLEX_INV_CNJ] THEN
2313     ASM_SIMP_TAC[GSYM CX_POW; ARG_DIV_CX; REAL_POW_LT; COMPLEX_NORM_NZ];
2314     ASM_SIMP_TAC[ARG_INV]]);;
2315
2316 let ARG_REAL = prove
2317  (`!z. real z ==> Arg z = if &0 <= Re z then &0 else pi`,
2318   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
2319   ASM_REWRITE_TAC[ARG_EQ_PI; ARG_EQ_0] THEN ASM_REAL_ARITH_TAC);;
2320
2321 let ARG_CEXP = prove
2322  (`!z. &0 <= Im z /\ Im z < &2 * pi ==> Arg(cexp(z)) = Im z`,
2323   REPEAT STRIP_TAC THEN MATCH_MP_TAC ARG_UNIQUE THEN
2324   EXISTS_TAC `exp(Re z)` THEN
2325   ASM_REWRITE_TAC[CX_EXP; GSYM CEXP_ADD; REAL_EXP_POS_LT] THEN
2326   REWRITE_TAC[GSYM COMPLEX_EXPAND]);;
2327
2328 (* ------------------------------------------------------------------------- *)
2329 (* Properties of 2-D rotations, and their interpretation using cexp.         *)
2330 (* ------------------------------------------------------------------------- *)
2331
2332 let rotate2d = new_definition
2333  `(rotate2d:real->real^2->real^2) t x =
2334         vector[x$1 * cos(t) - x$2 * sin(t);
2335                x$1 * sin(t) + x$2 * cos(t)]`;;
2336
2337 let LINEAR_ROTATE2D = prove
2338  (`!t. linear(rotate2d t)`,
2339   SIMP_TAC[linear; CART_EQ; DIMINDEX_2; FORALL_2; VECTOR_2;
2340            VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT; rotate2d] THEN
2341   REAL_ARITH_TAC);;
2342
2343 let ROTATE2D_ADD_VECTORS = prove
2344  (`!t w z. rotate2d t (w + z) = rotate2d t w + rotate2d t z`,
2345   SIMP_TAC[LINEAR_ADD; LINEAR_ROTATE2D]);;
2346
2347 let ROTATE2D_SUB = prove
2348  (`!t w z. rotate2d t (w - z) = rotate2d t w - rotate2d t z`,
2349   SIMP_TAC[LINEAR_SUB; LINEAR_ROTATE2D]);;
2350
2351 let NORM_ROTATE2D = prove
2352  (`!t z. norm(rotate2d t z) = norm z`,
2353   REWRITE_TAC[NORM_EQ; rotate2d; DIMINDEX_2; DOT_2; VECTOR_2] THEN
2354   REPEAT GEN_TAC THEN MP_TAC(ISPEC `t:real` SIN_CIRCLE) THEN
2355   CONV_TAC REAL_RING);;
2356
2357 let ROTATE2D_0 = prove
2358  (`!t. rotate2d t (Cx(&0)) = Cx(&0)`,
2359   REWRITE_TAC[GSYM COMPLEX_NORM_ZERO; NORM_ROTATE2D; COMPLEX_NORM_0]);;
2360
2361 let ROTATE2D_EQ_0 = prove
2362  (`!t z. rotate2d t z = Cx(&0) <=> z = Cx(&0)`,
2363   REWRITE_TAC[GSYM COMPLEX_NORM_ZERO; NORM_ROTATE2D]);;
2364
2365 let ROTATE2D_ZERO = prove
2366  (`!z. rotate2d (&0) z = z`,
2367   REWRITE_TAC[rotate2d; SIN_0; COS_0] THEN
2368   REWRITE_TAC[CART_EQ; DIMINDEX_2; FORALL_2; VECTOR_2] THEN
2369   REAL_ARITH_TAC);;
2370
2371 let ORTHOGONAL_TRANSFORMATION_ROTATE2D = prove
2372  (`!t. orthogonal_transformation(rotate2d t)`,
2373   REWRITE_TAC[ORTHOGONAL_TRANSFORMATION; LINEAR_ROTATE2D; NORM_ROTATE2D]);;
2374
2375 let ROTATE2D_POLAR = prove
2376  (`!r t s. rotate2d t (vector[r * cos(s); r * sin(s)]) =
2377                         vector[r * cos(t + s); r * sin(t + s)]`,
2378   SIMP_TAC[rotate2d; DIMINDEX_2; VECTOR_2; CART_EQ; FORALL_2] THEN
2379   REWRITE_TAC[SIN_ADD; COS_ADD] THEN REAL_ARITH_TAC);;
2380
2381 let MATRIX_ROTATE2D = prove
2382  (`!t. matrix(rotate2d t) = vector[vector[cos t;--(sin t)];
2383                                    vector[sin t; cos t]]`,
2384   SIMP_TAC[MATRIX_EQ; MATRIX_WORKS; LINEAR_ROTATE2D] THEN
2385   SIMP_TAC[matrix_vector_mul; rotate2d; CART_EQ; DIMINDEX_2; FORALL_2;
2386            LAMBDA_BETA; VECTOR_2; ARITH; SUM_2] THEN
2387   REAL_ARITH_TAC);;
2388
2389 let DET_MATRIX_ROTATE2D = prove
2390  (`!t. det(matrix(rotate2d t)) = &1`,
2391   GEN_TAC THEN REWRITE_TAC[MATRIX_ROTATE2D; DET_2; VECTOR_2] THEN
2392   MP_TAC(SPEC `t:real` SIN_CIRCLE) THEN REAL_ARITH_TAC);;
2393
2394 let ROTATION_ROTATE2D = prove
2395  (`!f. orthogonal_transformation f /\ det(matrix f) = &1
2396        ==> ?t. &0 <= t /\ t < &2 * pi /\ f = rotate2d t`,
2397   REWRITE_TAC[ORTHOGONAL_TRANSFORMATION_MATRIX] THEN
2398   REWRITE_TAC[matrix_mul; orthogonal_matrix; transp] THEN
2399   SIMP_TAC[DIMINDEX_2; SUM_2; FORALL_2; LAMBDA_BETA; ARITH;
2400            CART_EQ; mat; DET_2] THEN REPEAT STRIP_TAC THEN
2401   SUBGOAL_THEN `(matrix f)$1$1 pow 2 + (matrix f)$2$1 pow 2 = &1 /\
2402                 (matrix f)$1$2 = --((matrix f)$2$1) /\
2403                 (matrix f:real^2^2)$2$2 = (matrix f)$1$1`
2404   STRIP_ASSUME_TAC THENL
2405    [REPEAT(FIRST_X_ASSUM(MP_TAC o SYM)) THEN CONV_TAC REAL_RING;
2406     FIRST_X_ASSUM(MP_TAC o MATCH_MP SINCOS_TOTAL_2PI) THEN
2407     MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2408     MATCH_MP_TAC LINEAR_EQ_MATRIX THEN
2409     ASM_REWRITE_TAC[LINEAR_ROTATE2D; MATRIX_ROTATE2D] THEN
2410     ASM_SIMP_TAC[CART_EQ; DIMINDEX_2; FORALL_2; VECTOR_2]]);;
2411
2412 let ROTATE2D_ADD = prove
2413  (`!s t x. rotate2d (s + t) x = rotate2d s (rotate2d t x)`,
2414   SIMP_TAC[CART_EQ; rotate2d; LAMBDA_BETA; DIMINDEX_2; ARITH;
2415            FORALL_2; VECTOR_2] THEN
2416   REWRITE_TAC[SIN_ADD; COS_ADD] THEN REAL_ARITH_TAC);;
2417
2418 let ROTATE2D_COMPLEX = prove
2419  (`!t z. rotate2d t z = cexp(ii * Cx t) * z`,
2420   REPEAT GEN_TAC THEN GEN_REWRITE_TAC RAND_CONV [complex_mul] THEN
2421   REWRITE_TAC[CEXP_EULER; rotate2d; GSYM CX_SIN; GSYM CX_COS;
2422               RE_ADD; IM_ADD; RE_MUL_II; IM_MUL_II; IM_CX; RE_CX] THEN
2423   REWRITE_TAC[CART_EQ; FORALL_2; VECTOR_2; DIMINDEX_2] THEN
2424   REWRITE_TAC[GSYM RE_DEF; GSYM IM_DEF; RE; IM] THEN
2425   REAL_ARITH_TAC);;
2426
2427 let ROTATE2D_PI2 = prove
2428  (`!z. rotate2d (pi / &2) z = ii * z`,
2429   REWRITE_TAC[ROTATE2D_COMPLEX; CEXP_EULER; SIN_PI2; COS_PI2; GSYM CX_SIN;
2430               GSYM CX_COS] THEN
2431   CONV_TAC COMPLEX_RING);;
2432
2433 let ROTATE2D_PI = prove
2434  (`!z. rotate2d pi z = --z`,
2435   REWRITE_TAC[ROTATE2D_COMPLEX; CEXP_EULER; SIN_PI; COS_PI; GSYM CX_SIN;
2436               GSYM CX_COS] THEN
2437   CONV_TAC COMPLEX_RING);;
2438
2439 let ROTATE2D_NPI = prove
2440  (`!n z. rotate2d (&n * pi) z = --Cx(&1) pow n * z`,
2441   REWRITE_TAC[ROTATE2D_COMPLEX; CEXP_EULER; SIN_NPI; COS_NPI; GSYM CX_SIN;
2442               GSYM CX_COS; CX_NEG; CX_POW] THEN
2443   CONV_TAC COMPLEX_RING);;
2444
2445 let ROTATE2D_2PI = prove
2446  (`!z. rotate2d (&2 * pi) z = z`,
2447   REWRITE_TAC[ROTATE2D_NPI] THEN CONV_TAC COMPLEX_RING);;
2448
2449 let ARG_ROTATE2D = prove
2450  (`!t z. ~(z = Cx(&0)) /\ &0 <= t + Arg z /\ t + Arg z < &2 * pi
2451          ==> Arg(rotate2d t z) = t + Arg z`,
2452   REPEAT STRIP_TAC THEN MATCH_MP_TAC ARG_UNIQUE THEN
2453   EXISTS_TAC `norm(z:complex)` THEN
2454   ASM_SIMP_TAC[ARG; ROTATE2D_COMPLEX; REAL_LE_ADD; COMPLEX_NORM_NZ] THEN
2455   GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [ARG] THEN
2456   REWRITE_TAC[CX_ADD; COMPLEX_ADD_LDISTRIB; CEXP_ADD] THEN
2457   REWRITE_TAC[COMPLEX_MUL_AC]);;
2458
2459 let ARG_ROTATE2D_UNIQUE = prove
2460  (`!t a z. ~(z = Cx(&0)) /\ Arg(rotate2d t z) = a
2461            ==> ?n. integer n /\ t = &2 * n * pi + (a - Arg z)`,
2462   REPEAT STRIP_TAC THEN
2463   MP_TAC(last(CONJUNCTS(ISPEC `rotate2d t z` ARG))) THEN
2464   ASM_REWRITE_TAC[NORM_ROTATE2D] THEN
2465   REWRITE_TAC[ROTATE2D_COMPLEX] THEN
2466   GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o RAND_CONV) [ARG] THEN
2467   ASM_REWRITE_TAC[COMPLEX_RING `a * z * b = z * c <=> z = Cx(&0) \/ a * b = c`;
2468                   CX_INJ; COMPLEX_NORM_ZERO; GSYM CEXP_ADD; CEXP_EQ] THEN
2469   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN
2470   REWRITE_TAC[GSYM CX_ADD; GSYM CX_SUB; CX_INJ; COMPLEX_RING
2471    `ii * t + ii * z = ii * a + n * ii <=> t = n + (a - z)`]);;
2472
2473 let ARG_ROTATE2D_UNIQUE_2PI = prove
2474  (`!s t z. ~(z = Cx(&0)) /\
2475            &0 <= s /\ s < &2 * pi /\ &0 <= t /\ t < &2 * pi /\
2476            Arg(rotate2d s z) = Arg(rotate2d t z)
2477            ==> s = t`,
2478   REPEAT STRIP_TAC THEN ABBREV_TAC `a = Arg(rotate2d t z)` THEN
2479   MP_TAC(ISPECL [`s:real`; `a:real`; `z:complex`] ARG_ROTATE2D_UNIQUE) THEN
2480   MP_TAC(ISPECL [`t:real`; `a:real`; `z:complex`] ARG_ROTATE2D_UNIQUE) THEN
2481   ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SIN_COS_INJ THEN
2482   REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
2483    [ASM_REWRITE_TAC[SIN_COS_EQ; REAL_RING
2484      `x + az:real = (y + az) + z <=> x - y = z`] THEN
2485     REWRITE_TAC[GSYM REAL_SUB_LDISTRIB; GSYM REAL_SUB_RDISTRIB] THEN
2486     ASM_MESON_TAC[INTEGER_CLOSED];
2487     ASM_REAL_ARITH_TAC]);;
2488
2489 let COMPLEX_DIV_ROTATION = prove
2490  (`!f w z. orthogonal_transformation f /\ det(matrix f) = &1
2491            ==> f w / f z = w / z`,
2492   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP ROTATION_ROTATE2D) THEN
2493   DISCH_THEN(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THEN
2494   ASM_REWRITE_TAC[ROTATE2D_COMPLEX] THEN
2495   SIMP_TAC[complex_div; COMPLEX_INV_MUL; CEXP_NZ; COMPLEX_FIELD
2496    `~(a = Cx(&0)) ==> (a * w) * (inv a * z) = w * z`]);;
2497
2498 let th = prove
2499  (`!f w z. linear f /\ (!x. norm(f x) = norm x) /\
2500            (2 <= dimindex(:2) ==> det(matrix f) = &1)
2501            ==> f w / f z = w / z`,
2502   REWRITE_TAC[CONJ_ASSOC; GSYM ORTHOGONAL_TRANSFORMATION;
2503               DIMINDEX_2; LE_REFL; COMPLEX_DIV_ROTATION]) in
2504 add_linear_invariants [th];;
2505
2506 let th = prove
2507  (`!f t z. linear f /\ (!x. norm(f x) = norm x) /\
2508            (2 <= dimindex(:2) ==> det(matrix f) = &1)
2509            ==> rotate2d t (f z) = f(rotate2d t z)`,
2510   REWRITE_TAC[DIMINDEX_2; LE_REFL] THEN REPEAT STRIP_TAC THEN
2511   MP_TAC(SPEC `f:complex->complex` ROTATION_ROTATE2D) THEN
2512   ASM_REWRITE_TAC[ORTHOGONAL_TRANSFORMATION] THEN
2513   DISCH_THEN(X_CHOOSE_THEN `s:real` STRIP_ASSUME_TAC) THEN
2514   ASM_REWRITE_TAC[GSYM ROTATE2D_ADD] THEN REWRITE_TAC[REAL_ADD_SYM]) in
2515 add_linear_invariants [th];;
2516
2517 let ROTATION_ROTATE2D_EXISTS_GEN = prove
2518  (`!x y. ?t. &0 <= t /\ t < &2 * pi /\ norm(y) % rotate2d t x = norm(x) % y`,
2519   REPEAT STRIP_TAC THEN
2520   MP_TAC(ISPECL [`norm(y:real^2) % x:real^2`; `norm(x:real^2) % y:real^2`]
2521                ROTATION_EXISTS) THEN
2522   ASM_REWRITE_TAC[DIMINDEX_2; NORM_MUL; ARITH; REAL_ABS_NORM;
2523                   EQT_INTRO(SPEC_ALL REAL_MUL_SYM); CONJ_ASSOC] THEN
2524   DISCH_THEN(X_CHOOSE_THEN `f:real^2->real^2` (CONJUNCTS_THEN ASSUME_TAC)) THEN
2525   FIRST_ASSUM(MP_TAC o MATCH_MP ROTATION_ROTATE2D) THEN
2526   MATCH_MP_TAC MONO_EXISTS THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
2527   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[LINEAR_CMUL; LINEAR_ROTATE2D]);;
2528
2529 let ROTATION_ROTATE2D_EXISTS = prove
2530  (`!x y. norm x = norm y ==> ?t. &0 <= t /\ t < &2 * pi /\ rotate2d t x = y`,
2531   REPEAT GEN_TAC THEN
2532   ASM_CASES_TAC `norm(y:complex) = &0` THENL
2533    [ASM_REWRITE_TAC[] THEN DISCH_TAC THEN EXISTS_TAC `&0` THEN
2534     SIMP_TAC[REAL_LT_MUL; PI_POS; REAL_OF_NUM_LT; ARITH; REAL_LE_REFL] THEN
2535     ASM_MESON_TAC[COMPLEX_NORM_ZERO; ROTATE2D_0];
2536     DISCH_TAC THEN
2537     MP_TAC(ISPECL [`x:complex`; `y:complex`] ROTATION_ROTATE2D_EXISTS_GEN) THEN
2538     ASM_REWRITE_TAC[VECTOR_MUL_LCANCEL]]);;
2539
2540 let ROTATION_ROTATE2D_EXISTS_ORTHOGONAL = prove
2541  (`!e1 e2. norm(e1) = &1 /\ norm(e2) = &1 /\ orthogonal e1 e2
2542            ==> e1 = rotate2d (pi / &2) e2 \/ e2 = rotate2d (pi / &2) e1`,
2543   REWRITE_TAC[NORM_EQ_1; orthogonal] THEN
2544   SIMP_TAC[DOT_2; CART_EQ; FORALL_2; DIMINDEX_2; rotate2d; VECTOR_2] THEN
2545   REWRITE_TAC[COS_PI2; SIN_PI2; REAL_MUL_RZERO; REAL_ADD_RID;
2546               REAL_SUB_LZERO; REAL_SUB_RZERO; REAL_MUL_RID] THEN
2547   CONV_TAC REAL_RING);;
2548
2549 let ROTATION_ROTATE2D_EXISTS_ORTHOGONAL_ORIENTED = prove
2550  (`!e1 e2. norm(e1) = &1 /\ norm(e2) = &1 /\ orthogonal e1 e2 /\
2551            &0 < e1$1 * e2$2 - e1$2 * e2$1
2552            ==> e2 = rotate2d (pi / &2) e1`,
2553   REPEAT GEN_TAC THEN REWRITE_TAC[CONJ_ASSOC] THEN
2554   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
2555   REWRITE_TAC[GSYM CONJ_ASSOC] THEN DISCH_TAC THEN
2556   FIRST_ASSUM(DISJ_CASES_THEN SUBST_ALL_TAC o MATCH_MP
2557     ROTATION_ROTATE2D_EXISTS_ORTHOGONAL) THEN
2558   REWRITE_TAC[] THEN
2559   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_NOT_LE]) THEN
2560   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_THEN(K ALL_TAC) THEN
2561   SIMP_TAC[DOT_2; CART_EQ; FORALL_2; DIMINDEX_2; rotate2d; VECTOR_2] THEN
2562   REWRITE_TAC[COS_PI2; SIN_PI2; REAL_MUL_RZERO; REAL_ADD_RID;
2563               REAL_SUB_LZERO; REAL_SUB_RZERO; REAL_MUL_RID] THEN
2564   REWRITE_TAC[REAL_ARITH `--x * x - y * y <= &0 <=> &0 <= x * x + y * y`] THEN
2565   MATCH_MP_TAC REAL_LE_ADD THEN REWRITE_TAC[REAL_LE_SQUARE]);;
2566
2567 let ROTATE2D_EQ = prove
2568  (`!t x y. rotate2d t x = rotate2d t y <=> x = y`,
2569   MESON_TAC[ORTHOGONAL_TRANSFORMATION_INJECTIVE;
2570             ORTHOGONAL_TRANSFORMATION_ROTATE2D]);;
2571
2572 let ROTATE2D_SUB_ARG = prove
2573  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
2574          ==> rotate2d(Arg w - Arg z) = rotate2d(Arg(w / z))`,
2575   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[REAL_SUB_ARG] THEN
2576   COND_CASES_TAC THEN REWRITE_TAC[real_sub; ROTATE2D_ADD; FUN_EQ_THM] THEN
2577   GEN_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[ROTATE2D_COMPLEX] THEN
2578   REWRITE_TAC[EULER; RE_MUL_II; IM_MUL_II; RE_CX; IM_CX; COS_NEG; SIN_NEG] THEN
2579   REWRITE_TAC[SIN_NPI; COS_NPI; REAL_EXP_NEG; REAL_EXP_0; CX_NEG] THEN
2580   REWRITE_TAC[COMPLEX_NEG_0; COMPLEX_MUL_RZERO; COMPLEX_ADD_RID] THEN
2581   CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[COMPLEX_MUL_LID]);;
2582
2583 let ROTATION_MATRIX_ROTATE2D = prove
2584  (`!t. rotation_matrix(matrix(rotate2d t))`,
2585   SIMP_TAC[ROTATION_MATRIX_2; MATRIX_ROTATE2D; VECTOR_2] THEN
2586   MESON_TAC[SIN_CIRCLE; REAL_ADD_SYM]);;
2587
2588 let ROTATION_MATRIX_ROTATE2D_EQ = prove
2589  (`!A:real^2^2. rotation_matrix A <=> ?t. A = matrix(rotate2d t)`,
2590   GEN_TAC THEN EQ_TAC THEN
2591   SIMP_TAC[LEFT_IMP_EXISTS_THM; ROTATION_MATRIX_ROTATE2D] THEN
2592   REWRITE_TAC[ROTATION_MATRIX_2; MATRIX_ROTATE2D] THEN STRIP_TAC THEN
2593   FIRST_X_ASSUM(MP_TAC o MATCH_MP SINCOS_TOTAL_2PI) THEN
2594   MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN
2595   REWRITE_TAC[CART_EQ; DIMINDEX_2; FORALL_2; VECTOR_2] THEN
2596   ASM_REAL_ARITH_TAC);;
2597
2598 (* ------------------------------------------------------------------------- *)
2599 (* Homotopy staying within the set of orthogonal transformations             *)
2600 (* ------------------------------------------------------------------------- *)
2601
2602 let NULLHOMOTOPIC_ORTHOGONAL_TRANSFORMATION = prove
2603  (`!f:real^N->real^N.
2604        orthogonal_transformation f /\ det(matrix f) = &1
2605        ==> homotopic_with orthogonal_transformation ((:real^N),(:real^N)) f I`,
2606   let lemma0 = prove
2607    (`!a x:real^N.
2608           2 <= dimindex(:N) /\ a IN span {basis 1,basis 2}
2609           ==> reflect_along (vector[a$1; a$2]:real^2) (lambda i. x$i) =
2610               (lambda i. reflect_along a x$i)`,
2611     REPEAT STRIP_TAC THEN
2612     SIMP_TAC[CART_EQ; LAMBDA_BETA; reflect_along; VECTOR_SUB_COMPONENT;
2613              VECTOR_MUL_COMPONENT; DIMINDEX_2; FORALL_2; VECTOR_2; ARITH] THEN
2614     CONJ_TAC THEN AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
2615     AP_TERM_TAC THEN BINOP_TAC THEN REWRITE_TAC[dot] THEN
2616     CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_EQ_SUPERSET THEN
2617     ASM_SIMP_TAC[FINITE_NUMSEG; IN_NUMSEG; FORALL_2; DIMINDEX_2; LAMBDA_BETA;
2618                  ARITH; VECTOR_2; SUBSET_NUMSEG] THEN
2619     REWRITE_TAC[ARITH_RULE
2620      `(1 <= i /\ i <= n) /\ ~(1 <= i /\ i <= 2) <=>
2621       1 <= i /\ 3 <= i /\ i <= n`] THEN
2622     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [SPAN_2]) THEN
2623     REWRITE_TAC[IN_ELIM_THM; IN_UNIV] THEN
2624     STRIP_TAC THEN
2625     ASM_REWRITE_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
2626     SIMP_TAC[BASIS_COMPONENT] THEN
2627     REPEAT STRIP_TAC THEN
2628     REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_MUL_RZERO]) THEN
2629     ASM_ARITH_TAC) in
2630   let lemma1 = prove
2631    (`!a b:real^2 r.
2632           ~(a = vec 0) /\ ~(b = vec 0)
2633           ==> homotopic_with orthogonal_transformation ((:real^2),(:real^2))
2634                              (reflect_along a o reflect_along b) I`,
2635     REPEAT STRIP_TAC THEN
2636     MP_TAC(SPEC `reflect_along (a:real^2) o reflect_along b`
2637           ROTATION_ROTATE2D) THEN
2638     ANTS_TAC THENL
2639      [REPEAT(FIRST_X_ASSUM(MP_TAC o
2640         MATCH_MP ROTOINVERSION_MATRIX_REFLECT_ALONG)) THEN
2641       REWRITE_TAC[rotoinversion_matrix] THEN
2642       SIMP_TAC[ORTHOGONAL_MATRIX_MATRIX;
2643                ORTHGOONAL_TRANSFORMATION_REFLECT_ALONG;
2644                ORTHOGONAL_TRANSFORMATION_COMPOSE; MATRIX_COMPOSE;
2645                LINEAR_REFLECT_ALONG; DET_MUL] THEN
2646       CONV_TAC REAL_RAT_REDUCE_CONV;
2647       DISCH_THEN(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THEN
2648       ONCE_REWRITE_TAC[HOMOTOPIC_WITH_SYM] THEN
2649       ASM_REWRITE_TAC[homotopic_with] THEN
2650       EXISTS_TAC `\z. rotate2d (drop(fstcart z) * t) (sndcart z)` THEN
2651       SIMP_TAC[ORTHOGONAL_TRANSFORMATION_ROTATE2D; SNDCART_PASTECART;
2652                ETA_AX; FSTCART_PASTECART; DROP_VEC; I_THM; NORM_ROTATE2D;
2653                REAL_MUL_LZERO; REAL_MUL_LID; SUBSET; FORALL_IN_IMAGE; IN_UNIV;
2654                FORALL_IN_PCROSS; IN_SPHERE_0; ROTATE2D_ZERO] THEN
2655       REWRITE_TAC[ROTATE2D_COMPLEX] THEN
2656       MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_MUL THEN
2657       SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_SNDCART] THEN
2658       GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
2659       MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
2660       REWRITE_TAC[CONTINUOUS_ON_CEXP; CX_MUL] THEN
2661       ONCE_REWRITE_TAC[COMPLEX_RING `ii * x * t = (ii * t) * x`] THEN
2662       MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_LMUL THEN
2663       MATCH_MP_TAC CONTINUOUS_ON_CX_DROP THEN
2664       SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART]]) in
2665   let lemma2 = prove
2666    (`!a b:real^N r.
2667           2 <= dimindex(:N) /\
2668           ~(a = vec 0) /\ ~(b = vec 0) /\
2669           {a,b} SUBSET span {basis 1,basis 2}
2670           ==> homotopic_with orthogonal_transformation ((:real^N),(:real^N))
2671                              (reflect_along a o reflect_along b) I`,
2672     REPEAT STRIP_TAC THEN
2673     SUBGOAL_THEN
2674       `homotopic_with orthogonal_transformation
2675         ((:real^N),(:real^N))
2676         ((\z. (lambda i. if i <= 2 then (fstcart z)$i
2677                          else (sndcart z)$i):real^N) o
2678          (\z. pastecart
2679                (((reflect_along (vector [(a:real^N)$1; a$2]) o
2680                  reflect_along (vector [(b:real^N)$1; b$2]))
2681                   :real^2->real^2)(fstcart z))
2682                (sndcart z)) o
2683          (\z:real^N. pastecart ((lambda i. z$i) :real^2) z))
2684         ((\z. (lambda i. if i <= 2 then (fstcart z)$i
2685                          else (sndcart z)$i):real^N) o
2686          I o
2687          (\z:real^N. pastecart ((lambda i. z$i) :real^2) z))`
2688     MP_TAC THENL
2689      [MATCH_MP_TAC HOMOTOPIC_WITH_COMPOSE_CONTINUOUS_LEFT THEN
2690       EXISTS_TAC `(:real^2) PCROSS (:real^N)` THEN
2691       REWRITE_TAC[SUBSET_UNIV] THEN CONJ_TAC THENL
2692        [ALL_TAC;
2693         MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
2694         ONCE_REWRITE_TAC[LINEAR_COMPONENTWISE] THEN
2695         SIMP_TAC[LAMBDA_BETA] THEN X_GEN_TAC `i:num` THEN
2696         STRIP_TAC THEN ASM_CASES_TAC `i <= 2` THEN ASM_REWRITE_TAC[] THEN
2697         REWRITE_TAC[linear; FSTCART_ADD; FSTCART_CMUL;
2698                             SNDCART_ADD; SNDCART_CMUL] THEN
2699         REWRITE_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
2700         REWRITE_TAC[LIFT_ADD; LIFT_CMUL]] THEN
2701       MATCH_MP_TAC HOMOTOPIC_WITH_COMPOSE_CONTINUOUS_RIGHT THEN
2702       EXISTS_TAC `(:real^2) PCROSS (:real^N)` THEN
2703       REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_UNIV; PASTECART_IN_PCROSS] THEN
2704       CONJ_TAC THENL
2705        [ALL_TAC;
2706         MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
2707         MATCH_MP_TAC LINEAR_PASTECART THEN REWRITE_TAC[LINEAR_ID] THEN
2708         SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
2709                  VECTOR_MUL_COMPONENT]] THEN
2710       SUBGOAL_THEN
2711        `I = \z:real^(2,N)finite_sum. pastecart (fstcart z) (sndcart z)`
2712       SUBST1_TAC THENL
2713        [REWRITE_TAC[PASTECART_FST_SND; I_DEF]; ALL_TAC] THEN
2714       MATCH_MP_TAC HOMOTOPIC_WITH_PCROSS THEN
2715       EXISTS_TAC `orthogonal_transformation:(real^2->real^2)->bool` THEN
2716       EXISTS_TAC `\f:real^N->real^N. f = I` THEN REPEAT CONJ_TAC THENL
2717        [REWRITE_TAC[GSYM I_DEF; ETA_AX] THEN MATCH_MP_TAC lemma1 THEN
2718         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INSERT_SUBSET]) THEN
2719         REWRITE_TAC[SING_SUBSET; SPAN_2; IN_ELIM_THM; IN_UNIV] THEN
2720         DISCH_THEN(REPEAT_TCL STRIP_THM_THEN SUBST_ALL_TAC) THEN
2721         POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
2722         REWRITE_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
2723                     DIMINDEX_2; FORALL_2; VECTOR_2] THEN
2724         SIMP_TAC[BASIS_COMPONENT; ARITH; DIMINDEX_2; VEC_COMPONENT;
2725                  DIMINDEX_GE_1; LE_REFL] THEN
2726         MATCH_MP_TAC(TAUT
2727          `(r ==> q) /\ (s ==> p) ==> a /\ ~p /\ ~q ==> ~s /\ ~r`) THEN
2728         SIMP_TAC[REAL_MUL_RZERO; REAL_MUL_LZERO; REAL_MUL_RID;
2729                  REAL_ADD_LID; REAL_ADD_RID];
2730         REWRITE_TAC[HOMOTOPIC_WITH_REFL; SUBSET_UNIV; I_DEF] THEN
2731         REWRITE_TAC[CONTINUOUS_ON_ID];
2732         SIMP_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART;
2733                  LAMBDA_BETA; DIMINDEX_2; ARITH; I_THM] THEN
2734         REWRITE_TAC[ORTHOGONAL_TRANSFORMATION; NORM_EQ] THEN
2735         X_GEN_TAC `f:real^2->real^2` THEN GEN_TAC THEN STRIP_TAC THEN
2736         CONJ_TAC THENL
2737          [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [linear]) THEN
2738           SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
2739                    VECTOR_MUL_COMPONENT; DIMINDEX_2; ARITH] THEN
2740           MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
2741           DISCH_THEN(ASSUME_TAC o GSYM) THEN GEN_TAC THEN
2742           GEN_TAC THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
2743           COND_CASES_TAC THEN ASM_SIMP_TAC[] THEN
2744           AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
2745           SIMP_TAC[CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
2746                    VECTOR_MUL_COMPONENT];
2747           X_GEN_TAC `v:real^N` THEN REWRITE_TAC[dot; GSYM REAL_POW_2] THEN
2748           SUBGOAL_THEN `dimindex(:N) = 2 + (dimindex(:N) - 2)` SUBST1_TAC THENL
2749            [ASM_ARITH_TAC; ALL_TAC] THEN
2750           ASM_SIMP_TAC[SUM_ADD_SPLIT; ARITH_RULE `1 <= n + 1`] THEN
2751           BINOP_TAC THENL
2752            [RULE_ASSUM_TAC(REWRITE_RULE[dot; DIMINDEX_2; GSYM REAL_POW_2]) THEN
2753             FIRST_X_ASSUM(MP_TAC o SPEC `(lambda i. (v:real^N)$i):real^2`) THEN
2754             MATCH_MP_TAC EQ_IMP THEN BINOP_TAC THEN
2755             MATCH_MP_TAC SUM_EQ_NUMSEG THEN
2756             FIRST_ASSUM(MP_TAC o MATCH_MP (ARITH_RULE
2757              `2 <= n ==> !i. i <= 2 ==> i <= n`)) THEN
2758             SIMP_TAC[LAMBDA_BETA; DIMINDEX_2];
2759             ASM_SIMP_TAC[ARITH_RULE `2 <= n ==> 2 + n - 2 = n`] THEN
2760             MATCH_MP_TAC SUM_EQ_NUMSEG THEN
2761             SIMP_TAC[ARITH_RULE `2 + 1 <= i ==> 1 <= i`;
2762                      LAMBDA_BETA; DIMINDEX_2] THEN
2763             REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
2764             ASM_ARITH_TAC]]];
2765       MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ_ALT] HOMOTOPIC_WITH_EQ) THEN
2766       REWRITE_TAC[IN_UNIV; GSYM FUN_EQ_THM] THEN
2767       SIMP_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART;
2768                LAMBDA_BETA; DIMINDEX_2; ARITH; I_THM] THEN
2769       RULE_ASSUM_TAC(REWRITE_RULE[INSERT_SUBSET; EMPTY_SUBSET]) THEN
2770       ASM_SIMP_TAC[lemma0] THEN
2771       SIMP_TAC[CART_EQ; LAMBDA_BETA; DIMINDEX_2; ARITH; COND_ID] THEN
2772       MAP_EVERY X_GEN_TAC [`x:real^N`; `i:num`] THEN STRIP_TAC THEN
2773       COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
2774       SUBGOAL_THEN `(a:real^N)$i = &0 /\ (b:real^N)$i = &0` ASSUME_TAC THENL
2775        [FIRST_X_ASSUM(CONJUNCTS_THEN MP_TAC) THEN
2776         REWRITE_TAC[SPAN_2; IN_ELIM_THM; IN_UNIV] THEN REPEAT STRIP_TAC THEN
2777         ASM_SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
2778                      BASIS_COMPONENT] THEN
2779         REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
2780         (REAL_ARITH_TAC ORELSE ASM_ARITH_TAC);
2781         ASM_REWRITE_TAC[reflect_along; VECTOR_SUB_COMPONENT; REAL_MUL_RZERO;
2782                         VECTOR_MUL_COMPONENT; REAL_SUB_RZERO]]]) in
2783   let lemma3 = prove
2784    (`!a b:real^N r.
2785           ~(a = vec 0) /\ ~(b = vec 0)
2786           ==> homotopic_with orthogonal_transformation ((:real^N),(:real^N))
2787                              (reflect_along a o reflect_along b) I`,
2788     REPEAT STRIP_TAC THEN ASM_CASES_TAC `dimindex(:N) = 1` THENL
2789      [ASM_SIMP_TAC[o_DEF; I_DEF; REFLECT_ALONG_1D; VECTOR_NEG_NEG] THEN
2790       REWRITE_TAC[HOMOTOPIC_WITH_REFL; SUBSET_UNIV; CONTINUOUS_ON_ID] THEN
2791       REWRITE_TAC[ORTHOGONAL_TRANSFORMATION_ID];
2792       FIRST_X_ASSUM(MP_TAC o MATCH_MP(ARITH_RULE
2793        `~(n = 1) ==> 1 <= n ==> 2 <= n`)) THEN
2794       REWRITE_TAC[DIMINDEX_GE_1] THEN DISCH_TAC] THEN
2795     MP_TAC(ISPECL [`span{a:real^N,b}`; `span{basis 1:real^N,basis 2}`]
2796           ORTHOGONAL_TRANSFORMATION_INTO_SUBSPACE) THEN
2797     REWRITE_TAC[SUBSPACE_SPAN; DIM_SPAN] THEN ANTS_TAC THENL
2798      [ASM_REWRITE_TAC[DIM_INSERT; SPAN_SING; SPAN_EMPTY;
2799                       IN_SING; DIM_EMPTY] THEN
2800       MATCH_MP_TAC(ARITH_RULE `m <= 2 /\ n = 2 ==> m <= n`) THEN
2801       CONJ_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
2802       ASM_SIMP_TAC[BASIS_NONZERO; ARITH] THEN
2803       REWRITE_TAC[IN_ELIM_THM; IN_UNIV] THEN
2804       COND_CASES_TAC THEN REWRITE_TAC[] THEN
2805       FIRST_X_ASSUM(CHOOSE_THEN (MP_TAC o AP_TERM `(\x:real^N. x$1)`)) THEN
2806       ASM_SIMP_TAC[BASIS_COMPONENT; VECTOR_MUL_COMPONENT;
2807                    ARITH; DIMINDEX_GE_1] THEN
2808       REAL_ARITH_TAC;
2809       DISCH_THEN(X_CHOOSE_THEN `f:real^N->real^N` STRIP_ASSUME_TAC) THEN
2810       MP_TAC(ISPEC `f:real^N->real^N` ORTHOGONAL_TRANSFORMATION_INVERSE_o) THEN
2811       ASM_REWRITE_TAC[] THEN
2812       DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^N` STRIP_ASSUME_TAC)] THEN
2813     SUBGOAL_THEN
2814      `homotopic_with orthogonal_transformation ((:real^N),(:real^N))
2815        (g o (f o (reflect_along a o reflect_along b) o (g:real^N->real^N)) o f)
2816        (g o (f o I o (g:real^N->real^N)) o f)`
2817     MP_TAC THENL
2818      [ALL_TAC;
2819       ASM_REWRITE_TAC[o_ASSOC] THEN ASM_REWRITE_TAC[GSYM o_ASSOC; I_O_ID]] THEN
2820     MATCH_MP_TAC HOMOTOPIC_WITH_COMPOSE_CONTINUOUS_LEFT THEN
2821     EXISTS_TAC `(:real^N)` THEN REWRITE_TAC[SUBSET_UNIV] THEN
2822     ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_LINEAR; LINEAR_CONTINUOUS_ON] THEN
2823     MATCH_MP_TAC HOMOTOPIC_WITH_COMPOSE_CONTINUOUS_RIGHT THEN
2824     EXISTS_TAC `(:real^N)` THEN REWRITE_TAC[SUBSET_UNIV] THEN
2825     ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_LINEAR; LINEAR_CONTINUOUS_ON] THEN
2826     ASM_REWRITE_TAC[I_O_ID] THEN
2827     MP_TAC(ISPEC `f:real^N->real^N` REFLECT_ALONG_LINEAR_IMAGE) THEN
2828     ASM_REWRITE_TAC[GSYM ORTHOGONAL_TRANSFORMATION] THEN
2829     DISCH_THEN(ASSUME_TAC o GSYM) THEN
2830     SUBGOAL_THEN
2831      `!h:real^N->real^N.
2832           orthogonal_transformation (g o h o (f:real^N->real^N)) <=>
2833           orthogonal_transformation h`
2834      (fun th -> REWRITE_TAC[th; ETA_AX])
2835     THENL
2836      [GEN_TAC THEN EQ_TAC THEN
2837       ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_COMPOSE] THEN
2838       DISCH_TAC THEN
2839       SUBGOAL_THEN `h:real^N->real^N = f o (g o h o f) o (g:real^N->real^N)`
2840       SUBST1_TAC THENL
2841        [ALL_TAC; ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_COMPOSE]] THEN
2842       ASM_REWRITE_TAC[o_ASSOC] THEN ASM_REWRITE_TAC[GSYM o_ASSOC; I_O_ID];
2843       ALL_TAC] THEN
2844     SUBGOAL_THEN
2845      `(f:real^N->real^N) o (reflect_along a o reflect_along b) o g =
2846       reflect_along (f a) o reflect_along (f b)`
2847     SUBST1_TAC THENL
2848      [RULE_ASSUM_TAC(REWRITE_RULE[FUN_EQ_THM; o_THM; I_THM]) THEN
2849       ASM_REWRITE_TAC[o_DEF];
2850       MATCH_MP_TAC lemma2 THEN RULE_ASSUM_TAC
2851        (REWRITE_RULE[GSYM NORM_EQ_0; ORTHOGONAL_TRANSFORMATION]) THEN
2852       ASM_REWRITE_TAC[GSYM NORM_EQ_0] THEN
2853       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
2854          SUBSET_TRANS)) THEN
2855       ASM_SIMP_TAC[GSYM SPAN_LINEAR_IMAGE; IMAGE_CLAUSES] THEN
2856       REWRITE_TAC[SPAN_INC]]) in
2857   GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2858   MP_TAC(ISPECL [`f:real^N->real^N`; `dimindex(:N)`]
2859         ORTHOGONAL_TRANSFORMATION_GENERATED_BY_REFLECTIONS) THEN
2860   ASM_REWRITE_TAC[ARITH_RULE `n:num <= a + n`] THEN
2861   DISCH_THEN(X_CHOOSE_THEN `l:(real^N)list` STRIP_ASSUME_TAC) THEN
2862   UNDISCH_TAC `ALL (\v:real^N. ~(v = vec 0)) l` THEN
2863   UNDISCH_TAC `orthogonal_transformation(f:real^N->real^N)` THEN
2864   MATCH_MP_TAC(TAUT `r /\ (p /\ q ==> s) ==> r ==> p ==> q ==> s`) THEN
2865   ASM_REWRITE_TAC[IMP_IMP] THEN
2866   SPEC_TAC(`l:(real^N)list`,`l:(real^N)list`) THEN
2867   POP_ASSUM_LIST(K ALL_TAC) THEN GEN_TAC THEN
2868   WF_INDUCT_TAC `LENGTH(l:(real^N)list)` THEN POP_ASSUM MP_TAC THEN
2869   SPEC_TAC(`l:(real^N)list`,`l:(real^N)list`) THEN
2870   MATCH_MP_TAC list_INDUCT THEN
2871   REWRITE_TAC[ALL; ITLIST; HOMOTOPIC_WITH_REFL] THEN
2872   REWRITE_TAC[REWRITE_RULE[GSYM I_DEF] CONTINUOUS_ON_ID;
2873               ORTHOGONAL_TRANSFORMATION_I; SUBSET_UNIV] THEN
2874   X_GEN_TAC `a:real^N` THEN MATCH_MP_TAC list_INDUCT THEN
2875   REWRITE_TAC[ALL; ITLIST; I_O_ID; DET_MATRIX_REFLECT_ALONG] THEN
2876   REWRITE_TAC[ORTHGOONAL_TRANSFORMATION_REFLECT_ALONG] THEN
2877   CONJ_TAC THENL [MESON_TAC[REAL_ARITH `~(-- &1 = &1)`]; ALL_TAC] THEN
2878   MAP_EVERY X_GEN_TAC [`b:real^N`; `l:(real^N)list`] THEN
2879   REPLICATE_TAC 2 (DISCH_THEN(K ALL_TAC)) THEN
2880   DISCH_THEN(MP_TAC o SPEC `l:(real^N)list`) THEN
2881   REWRITE_TAC[LENGTH; ARITH_RULE `n < SUC(SUC n)`] THEN
2882   SIMP_TAC[LINEAR_COMPOSE; LINEAR_REFLECT_ALONG; MATRIX_COMPOSE;
2883      ORTHGOONAL_TRANSFORMATION_REFLECT_ALONG;
2884      ORTHOGONAL_TRANSFORMATION_COMPOSE; ORTHOGONAL_TRANSFORMATION_LINEAR] THEN
2885   DISCH_THEN(fun th ->
2886     DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN MP_TAC th) THEN
2887   ASM_SIMP_TAC[DET_MUL; DET_MATRIX_REFLECT_ALONG; REAL_ARITH
2888    `-- &1 * -- &1 * x = x`] THEN
2889   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2890   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
2891   ASM_REWRITE_TAC[] THEN
2892   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] HOMOTOPIC_WITH_TRANS) THEN
2893   GEN_REWRITE_TAC RAND_CONV [MESON[I_O_ID] `f = I o f`] THEN
2894   REWRITE_TAC[o_ASSOC] THEN
2895   MATCH_MP_TAC HOMOTOPIC_WITH_COMPOSE_CONTINUOUS_RIGHT THEN
2896   EXISTS_TAC `(:real^N)` THEN REWRITE_TAC[SUBSET_UNIV] THEN
2897   ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON; ORTHOGONAL_TRANSFORMATION_LINEAR] THEN
2898   ABBREV_TAC `g = ITLIST (\v:real^N h. reflect_along v o h) l I` THEN
2899   SUBGOAL_THEN
2900    `(\f:real^N->real^N.
2901         orthogonal_transformation (f o g)) = orthogonal_transformation`
2902   SUBST1_TAC THENL [ALL_TAC; MATCH_MP_TAC lemma3 THEN ASM_REWRITE_TAC[]] THEN
2903   REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `f:real^N->real^N` THEN
2904   EQ_TAC THEN ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_COMPOSE] THEN
2905   DISCH_TAC THEN
2906   MP_TAC(ISPEC `g:real^N->real^N` ORTHOGONAL_TRANSFORMATION_INVERSE_o) THEN
2907   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `h:real^N->real^N` THEN
2908   STRIP_TAC THEN
2909   SUBGOAL_THEN `f = ((f:real^N->real^N) o (g:real^N->real^N)) o h`
2910   SUBST1_TAC THENL
2911    [ASM_REWRITE_TAC[GSYM o_ASSOC; I_O_ID];
2912     ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_COMPOSE]]);;
2913
2914 let HOMOTOPIC_SPECIAL_ORTHOGONAL_TRANSFORMATIONS,
2915     HOMOTOPIC_ORTHOGONAL_TRANSFORMATIONS = (CONJ_PAIR o prove)
2916  (`(!f g. homotopic_with
2917             (\h. orthogonal_transformation h /\ det(matrix h) = det(matrix f))
2918             ((:real^N),(:real^N)) f g <=>
2919           homotopic_with
2920             orthogonal_transformation ((:real^N),(:real^N)) f g) /\
2921    !f g. homotopic_with orthogonal_transformation ((:real^N),(:real^N)) f g <=>
2922          orthogonal_transformation f /\ orthogonal_transformation g /\
2923          det(matrix f) = det(matrix g)`,
2924   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
2925    `(u ==> s) /\ (s ==> t) /\ (t ==> u)
2926     ==> (u <=> t) /\ (t <=> s)`) THEN
2927   REPEAT CONJ_TAC THENL
2928    [DISCH_THEN(MP_TAC o MATCH_MP HOMOTOPIC_WITH_IMP_PROPERTY) THEN MESON_TAC[];
2929     STRIP_TAC THEN
2930     MP_TAC(ISPEC `g:real^N->real^N` ORTHOGONAL_TRANSFORMATION_INVERSE_o) THEN
2931     ASM_REWRITE_TAC[] THEN
2932     DISCH_THEN(X_CHOOSE_THEN `h:real^N->real^N` STRIP_ASSUME_TAC) THEN
2933     SUBGOAL_THEN
2934      `(f:real^N->real^N) = g o (h:real^N->real^N) o f /\ g = g o I`
2935      (fun th -> ONCE_REWRITE_TAC[th])
2936     THENL [ASM_REWRITE_TAC[o_ASSOC; I_O_ID]; ALL_TAC] THEN
2937     MATCH_MP_TAC HOMOTOPIC_WITH_COMPOSE_CONTINUOUS_LEFT THEN
2938     EXISTS_TAC `(:real^N)` THEN REWRITE_TAC[SUBSET_UNIV] THEN
2939     ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_LINEAR; LINEAR_CONTINUOUS_ON] THEN
2940     SUBGOAL_THEN
2941       `!k:real^N->real^N.
2942           orthogonal_transformation (g o k) <=> orthogonal_transformation k`
2943       (fun th -> REWRITE_TAC[th; ETA_AX])
2944     THENL
2945      [GEN_TAC THEN EQ_TAC THEN
2946       ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_COMPOSE] THEN DISCH_THEN
2947        (MP_TAC o SPEC `h:real^N->real^N` o MATCH_MP (ONCE_REWRITE_RULE
2948          [IMP_CONJ_ALT] ORTHOGONAL_TRANSFORMATION_COMPOSE)) THEN
2949       ASM_SIMP_TAC[o_ASSOC; I_O_ID];
2950       MATCH_MP_TAC NULLHOMOTOPIC_ORTHOGONAL_TRANSFORMATION THEN
2951       REPEAT(FIRST_X_ASSUM(MP_TAC o AP_TERM
2952        `\f:real^N->real^N. det(matrix f)`)) THEN
2953       ASM_SIMP_TAC[MATRIX_COMPOSE; ORTHOGONAL_TRANSFORMATION_LINEAR;
2954                    ORTHOGONAL_TRANSFORMATION_COMPOSE; DET_MUL;
2955                    MATRIX_I; DET_I]];
2956     REWRITE_TAC[homotopic_with] THEN MATCH_MP_TAC MONO_EXISTS THEN
2957     X_GEN_TAC `k:real^(1,N)finite_sum->real^N` THEN
2958     STRIP_TAC THEN ASM_SIMP_TAC[] THEN MP_TAC(ISPECL
2959      [`\t. lift(
2960        det(matrix((k:real^(1,N)finite_sum->real^N) o pastecart t)))`;
2961       `interval[vec 0:real^1,vec 1]`]
2962      CONTINUOUS_DISCRETE_RANGE_CONSTANT) THEN
2963     REWRITE_TAC[CONNECTED_INTERVAL] THEN ANTS_TAC THENL
2964      [CONJ_TAC THENL
2965        [MATCH_MP_TAC CONTINUOUS_ON_LIFT_DET THEN
2966         SIMP_TAC[matrix; LAMBDA_BETA; o_DEF] THEN
2967         MAP_EVERY X_GEN_TAC [`i:num`; `j:num`] THEN STRIP_TAC THEN
2968         MATCH_MP_TAC CONTINUOUS_ON_LIFT_COMPONENT_COMPOSE THEN
2969         ASM_REWRITE_TAC[] THEN GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
2970         MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
2971         SIMP_TAC[CONTINUOUS_ON_PASTECART; CONTINUOUS_ON_CONST;
2972                  CONTINUOUS_ON_ID] THEN
2973         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
2974           CONTINUOUS_ON_SUBSET)) THEN
2975         SIMP_TAC[SUBSET; FORALL_IN_IMAGE; PASTECART_IN_PCROSS; IN_UNIV];
2976         X_GEN_TAC `t:real^1` THEN DISCH_TAC THEN EXISTS_TAC `&1` THEN
2977         REWRITE_TAC[REAL_LT_01] THEN X_GEN_TAC `u:real^1` THEN
2978         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2979         REWRITE_TAC[GSYM LIFT_SUB; NORM_LIFT; LIFT_EQ] THEN
2980         SUBGOAL_THEN
2981          `orthogonal_transformation
2982            ((k:real^(1,N)finite_sum->real^N) o pastecart t) /\
2983           orthogonal_transformation (k o pastecart u)`
2984         MP_TAC THENL [ASM_SIMP_TAC[o_DEF]; ALL_TAC] THEN
2985         DISCH_THEN(CONJUNCTS_THEN
2986           (STRIP_ASSUME_TAC o MATCH_MP DET_ORTHOGONAL_MATRIX o
2987                     MATCH_MP ORTHOGONAL_MATRIX_MATRIX)) THEN
2988         ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV];
2989       REWRITE_TAC[o_DEF; LEFT_IMP_EXISTS_THM] THEN
2990       X_GEN_TAC `a:real^1` THEN DISCH_TAC THEN
2991       REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM FUN_EQ_THM])) THEN
2992       REPEAT(DISCH_THEN(SUBST1_TAC o SYM)) THEN
2993       ASM_SIMP_TAC[ENDS_IN_UNIT_INTERVAL; GSYM LIFT_EQ]]]);;
2994
2995 (* ------------------------------------------------------------------------- *)
2996 (* Complex tangent function.                                                 *)
2997 (* ------------------------------------------------------------------------- *)
2998
2999 let ctan = new_definition
3000  `ctan z = csin z / ccos z`;;
3001
3002 let CTAN_0 = prove
3003  (`ctan(Cx(&0)) = Cx(&0)`,
3004   REWRITE_TAC[ctan; CSIN_0; CCOS_0; COMPLEX_DIV_1]);;
3005
3006 let CTAN_NEG = prove
3007  (`!z. ctan(--z) = --(ctan z)`,
3008   REWRITE_TAC[ctan; CSIN_NEG; CCOS_NEG; complex_div; COMPLEX_MUL_LNEG]);;
3009
3010 let CTAN_ADD = prove
3011  (`!w z. ~(ccos(w) = Cx(&0)) /\
3012          ~(ccos(z) = Cx(&0)) /\
3013          ~(ccos(w + z) = Cx(&0))
3014          ==> ctan(w + z) = (ctan w + ctan z) / (Cx(&1) - ctan(w) * ctan(z))`,
3015   REPEAT GEN_TAC THEN REWRITE_TAC[ctan; CSIN_ADD; CCOS_ADD] THEN
3016   CONV_TAC COMPLEX_FIELD);;
3017
3018 let CTAN_DOUBLE = prove
3019  (`!z. ~(ccos(z) = Cx(&0)) /\ ~(ccos(Cx(&2) * z) = Cx(&0))
3020        ==> ctan(Cx(&2) * z) =
3021            (Cx(&2) * ctan z) / (Cx(&1) - ctan(z) pow 2)`,
3022   SIMP_TAC[COMPLEX_MUL_2; CTAN_ADD; COMPLEX_POW_2]);;
3023
3024 let CTAN_SUB = prove
3025  (`!w z. ~(ccos(w) = Cx(&0)) /\
3026          ~(ccos(z) = Cx(&0)) /\
3027          ~(ccos(w - z) = Cx(&0))
3028          ==> ctan(w - z) = (ctan w - ctan z) / (Cx(&1) + ctan(w) * ctan(z))`,
3029   SIMP_TAC[complex_sub; CTAN_ADD; CCOS_NEG; CTAN_NEG] THEN
3030   REWRITE_TAC[COMPLEX_MUL_RNEG; COMPLEX_NEG_NEG]);;
3031
3032 let COMPLEX_ADD_CTAN = prove
3033  (`!w z. ~(ccos(w) = Cx(&0)) /\
3034          ~(ccos(z) = Cx(&0))
3035          ==> ctan(w) + ctan(z) = csin(w + z) / (ccos(w) * ccos(z))`,
3036   REWRITE_TAC[ctan; CSIN_ADD] THEN CONV_TAC COMPLEX_FIELD);;
3037
3038 let COMPLEX_SUB_CTAN = prove
3039  (`!w z. ~(ccos(w) = Cx(&0)) /\
3040          ~(ccos(z) = Cx(&0))
3041          ==> ctan(w) - ctan(z) = csin(w - z) / (ccos(w) * ccos(z))`,
3042   REWRITE_TAC[ctan; CSIN_SUB] THEN CONV_TAC COMPLEX_FIELD);;
3043
3044 (* ------------------------------------------------------------------------- *)
3045 (* Analytic properties of tangent function.                                  *)
3046 (* ------------------------------------------------------------------------- *)
3047
3048 let HAS_COMPLEX_DERIVATIVE_CTAN = prove
3049  (`!z. ~(ccos z = Cx(&0))
3050        ==> (ctan has_complex_derivative (inv(ccos(z) pow 2))) (at z)`,
3051   REPEAT STRIP_TAC THEN
3052   GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM ETA_AX] THEN
3053   REWRITE_TAC[ctan] THEN COMPLEX_DIFF_TAC THEN
3054   MP_TAC(SPEC `z:complex` CSIN_CIRCLE) THEN
3055   POP_ASSUM MP_TAC THEN CONV_TAC COMPLEX_FIELD);;
3056
3057 let COMPLEX_DIFFERENTIABLE_AT_CTAN = prove
3058  (`!z. ~(ccos z = Cx(&0)) ==> ctan complex_differentiable at z`,
3059   REWRITE_TAC[complex_differentiable] THEN
3060   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CTAN]);;
3061
3062 let COMPLEX_DIFFERENTIABLE_WITHIN_CTAN = prove
3063  (`!s z. ~(ccos z = Cx(&0))
3064          ==> ctan complex_differentiable (at z within s)`,
3065   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
3066             COMPLEX_DIFFERENTIABLE_AT_CTAN]);;
3067
3068 add_complex_differentiation_theorems
3069  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
3070    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
3071              HAS_COMPLEX_DERIVATIVE_CTAN)));;
3072
3073 let CONTINUOUS_AT_CTAN = prove
3074  (`!z. ~(ccos z = Cx(&0)) ==> ctan continuous at z`,
3075   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CTAN;
3076             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
3077
3078 let CONTINUOUS_WITHIN_CTAN = prove
3079  (`!s z. ~(ccos z = Cx(&0)) ==> ctan continuous (at z within s)`,
3080   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CTAN]);;
3081
3082 let CONTINUOUS_ON_CTAN = prove
3083  (`!s. (!z. z IN s ==> ~(ccos z = Cx(&0))) ==> ctan continuous_on s`,
3084   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CTAN]);;
3085
3086 let HOLOMORPHIC_ON_CTAN = prove
3087  (`!s. (!z. z IN s ==> ~(ccos z = Cx(&0))) ==> ctan holomorphic_on s`,
3088   REWRITE_TAC [holomorphic_on] THEN
3089   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CTAN]);;
3090
3091 (* ------------------------------------------------------------------------- *)
3092 (* Real tangent function.                                                    *)
3093 (* ------------------------------------------------------------------------- *)
3094
3095 let tan_def = new_definition
3096  `tan(x) = Re(ctan(Cx x))`;;
3097
3098 let CNJ_CTAN = prove
3099  (`!z. cnj(ctan z) = ctan(cnj z)`,
3100   REWRITE_TAC[ctan; CNJ_DIV; CNJ_CSIN; CNJ_CCOS]);;
3101
3102 let REAL_TAN = prove
3103  (`!z. real z ==> real(ctan z)`,
3104   SIMP_TAC[REAL_CNJ; CNJ_CTAN]);;
3105
3106 let CX_TAN = prove
3107  (`!x. Cx(tan x) = ctan(Cx x)`,
3108   REWRITE_TAC[tan_def] THEN MESON_TAC[REAL; REAL_CX; REAL_TAN]);;
3109
3110 let tan = prove
3111  (`!x. tan x = sin x / cos x`,
3112   REWRITE_TAC[GSYM CX_INJ; CX_DIV; CX_TAN; CX_SIN; CX_COS; ctan]);;
3113
3114 let TAN_0 = prove
3115  (`tan(&0) = &0`,
3116   REWRITE_TAC[GSYM CX_INJ; CX_TAN; CTAN_0]);;
3117
3118 let TAN_PI = prove
3119  (`tan(pi) = &0`,
3120   REWRITE_TAC[tan; SIN_PI; real_div; REAL_MUL_LZERO]);;
3121
3122 let TAN_NPI = prove
3123  (`!n. tan(&n * pi) = &0`,
3124   REWRITE_TAC[tan; SIN_NPI; real_div; REAL_MUL_LZERO]);;
3125
3126 let TAN_NEG = prove
3127  (`!x. tan(--x) = --(tan x)`,
3128   REWRITE_TAC[GSYM CX_INJ; CX_TAN; CX_NEG; CTAN_NEG]);;
3129
3130 let TAN_PERIODIC_PI = prove
3131  (`!x. tan(x + pi) = tan(x)`,
3132   REWRITE_TAC[tan; SIN_PERIODIC_PI; COS_PERIODIC_PI; real_div] THEN
3133   REWRITE_TAC[REAL_MUL_LNEG; REAL_INV_NEG; REAL_MUL_RNEG; REAL_NEG_NEG]);;
3134
3135 let TAN_PERIODIC_NPI = prove
3136  (`!x n. tan(x + &n * pi) = tan(x)`,
3137   GEN_TAC THEN INDUCT_TAC THEN REWRITE_TAC[REAL_MUL_LZERO; REAL_ADD_RID] THEN
3138   REWRITE_TAC[GSYM REAL_OF_NUM_SUC; REAL_ADD_RDISTRIB; REAL_MUL_LID] THEN
3139   ASM_REWRITE_TAC[REAL_ADD_ASSOC; TAN_PERIODIC_PI]);;
3140
3141 let TAN_ADD = prove
3142  (`!x y. ~(cos(x) = &0) /\ ~(cos(y) = &0) /\ ~(cos(x + y) = &0)
3143          ==> tan(x + y) = (tan(x) + tan(y)) / (&1 - tan(x) * tan(y))`,
3144   REWRITE_TAC[GSYM CX_INJ; CX_TAN; CX_SIN; CX_COS; CTAN_ADD;
3145               CX_DIV; CX_ADD; CX_SUB; CX_MUL]);;
3146
3147 let TAN_SUB = prove
3148  (`!x y. ~(cos(x) = &0) /\ ~(cos(y) = &0) /\ ~(cos(x - y) = &0)
3149          ==> tan(x - y) = (tan(x) - tan(y)) / (&1 + tan(x) * tan(y))`,
3150   REWRITE_TAC[GSYM CX_INJ; CX_TAN; CX_SIN; CX_COS; CX_ADD; CTAN_SUB;
3151               CX_DIV; CX_ADD; CX_SUB; CX_MUL]);;
3152
3153 let TAN_DOUBLE = prove
3154  (`!x. ~(cos(x) = &0) /\ ~(cos(&2 * x) = &0)
3155        ==> tan(&2 * x) = (&2 * tan(x)) / (&1 - (tan(x) pow 2))`,
3156   SIMP_TAC[REAL_MUL_2; TAN_ADD; REAL_POW_2]);;
3157
3158 let REAL_ADD_TAN = prove
3159  (`!x y. ~(cos(x) = &0) /\ ~(cos(y) = &0)
3160          ==> tan(x) + tan(y) = sin(x + y) / (cos(x) * cos(y))`,
3161   REWRITE_TAC[GSYM CX_INJ; CX_TAN; CX_SIN; CX_COS; CX_MUL; CX_ADD; CX_DIV] THEN
3162   REWRITE_TAC[COMPLEX_ADD_CTAN]);;
3163
3164 let REAL_SUB_TAN = prove
3165  (`!x y. ~(cos(x) = &0) /\ ~(cos(y) = &0)
3166          ==> tan(x) - tan(y) = sin(x - y) / (cos(x) * cos(y))`,
3167   REWRITE_TAC[GSYM CX_INJ; CX_TAN; CX_SIN; CX_COS; CX_MUL; CX_SUB; CX_DIV] THEN
3168   REWRITE_TAC[COMPLEX_SUB_CTAN]);;
3169
3170 let TAN_PI4 = prove
3171  (`tan(pi / &4) = &1`,
3172   REWRITE_TAC[tan; SIN_COS; REAL_ARITH `p / &2 - p / &4 = p / &4`] THEN
3173   MATCH_MP_TAC REAL_DIV_REFL THEN REWRITE_TAC[COS_EQ_0; PI_NZ; REAL_FIELD
3174    `p / &4 = (n + &1 / &2) * p <=> p = &0 \/ n = -- &1 / &4`] THEN
3175   ONCE_REWRITE_TAC[CONJ_SYM] THEN REWRITE_TAC[UNWIND_THM2] THEN
3176   DISCH_THEN(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
3177    REAL_ABS_INTEGER_LEMMA)) THEN
3178   REAL_ARITH_TAC);;
3179
3180 let TAN_POS_PI2 = prove
3181  (`!x. &0 < x /\ x < pi / &2 ==> &0 < tan x`,
3182   REPEAT STRIP_TAC THEN REWRITE_TAC[tan] THEN
3183   MATCH_MP_TAC REAL_LT_DIV THEN CONJ_TAC THENL
3184    [MATCH_MP_TAC SIN_POS_PI; MATCH_MP_TAC COS_POS_PI] THEN
3185   ASM_REAL_ARITH_TAC);;
3186
3187 let TAN_POS_PI2_LE = prove
3188  (`!x. &0 <= x /\ x < pi / &2 ==> &0 <= tan x`,
3189   REWRITE_TAC[REAL_LE_LT] THEN MESON_TAC[TAN_0; TAN_POS_PI2]);;
3190
3191 let COS_TAN = prove
3192  (`!x. abs(x) < pi / &2 ==> cos(x) = &1 / sqrt(&1 + tan(x) pow 2)`,
3193   REPEAT STRIP_TAC THEN MATCH_MP_TAC(REAL_FIELD
3194    `sqrt(s) pow 2 = s /\ c pow 2 * s = &1 /\ ~(&1 + c * sqrt s = &0)
3195     ==> c = &1 / sqrt s`) THEN
3196   SUBGOAL_THEN `&0 < &1 + tan x pow 2` ASSUME_TAC THENL
3197    [MP_TAC(SPEC `tan x` REAL_LE_SQUARE) THEN REAL_ARITH_TAC; ALL_TAC] THEN
3198   ASM_SIMP_TAC[SQRT_POW_2; REAL_LT_IMP_LE] THEN CONJ_TAC THENL
3199    [REWRITE_TAC[tan] THEN
3200     MATCH_MP_TAC(REAL_FIELD
3201      `s pow 2 + c pow 2 = &1 /\ &0 < c
3202       ==> c pow 2 * (&1 + (s / c) pow 2) = &1`) THEN
3203     ASM_SIMP_TAC[SIN_CIRCLE; COS_POS_PI; REAL_BOUNDS_LT];
3204     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> ~(&1 + x = &0)`) THEN
3205     ASM_SIMP_TAC[SIN_CIRCLE; COS_POS_PI; REAL_BOUNDS_LT; SQRT_POS_LT;
3206                  REAL_LT_MUL]]);;
3207
3208 let SIN_TAN = prove
3209  (`!x. abs(x) < pi / &2 ==> sin(x) = tan(x) / sqrt(&1 + tan(x) pow 2)`,
3210   REPEAT STRIP_TAC THEN
3211   ONCE_REWRITE_TAC[REAL_ARITH `a / b = a * &1 / b`] THEN
3212   ASM_SIMP_TAC[GSYM COS_TAN] THEN
3213   ASM_SIMP_TAC[tan; REAL_DIV_RMUL; REAL_LT_IMP_NZ; COS_POS_PI;
3214                REAL_BOUNDS_LT]);;
3215
3216 (* ------------------------------------------------------------------------- *)
3217 (* Monotonicity theorems for the basic trig functions.                       *)
3218 (* ------------------------------------------------------------------------- *)
3219
3220 let SIN_MONO_LT = prove
3221  (`!x y. --(pi / &2) <= x /\ x < y /\ y <= pi / &2 ==> sin(x) < sin(y)`,
3222   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
3223   REWRITE_TAC[REAL_SUB_SIN; REAL_ARITH `&0 < &2 * x <=> &0 < x`] THEN
3224   MATCH_MP_TAC REAL_LT_MUL THEN CONJ_TAC THENL
3225    [MATCH_MP_TAC SIN_POS_PI; MATCH_MP_TAC COS_POS_PI] THEN
3226   ASM_REAL_ARITH_TAC);;
3227
3228 let SIN_MONO_LE = prove
3229  (`!x y. --(pi / &2) <= x /\ x <= y /\ y <= pi / &2 ==> sin(x) <= sin(y)`,
3230   MESON_TAC[SIN_MONO_LT; REAL_LE_LT]);;
3231
3232 let SIN_MONO_LT_EQ = prove
3233  (`!x y. --(pi / &2) <= x /\ x <= pi / &2 /\ --(pi / &2) <= y /\ y <= pi / &2
3234          ==> (sin(x) < sin(y) <=> x < y)`,
3235   MESON_TAC[REAL_NOT_LE; SIN_MONO_LT; SIN_MONO_LE]);;
3236
3237 let SIN_MONO_LE_EQ = prove
3238  (`!x y. --(pi / &2) <= x /\ x <= pi / &2 /\ --(pi / &2) <= y /\ y <= pi / &2
3239          ==> (sin(x) <= sin(y) <=> x <= y)`,
3240   MESON_TAC[REAL_NOT_LE; SIN_MONO_LT; SIN_MONO_LE]);;
3241
3242 let SIN_INJ_PI = prove
3243  (`!x y. --(pi / &2) <= x /\ x <= pi / &2 /\
3244          --(pi / &2) <= y /\ y <= pi / &2 /\
3245          sin(x) = sin(y)
3246          ==> x = y`,
3247   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN MESON_TAC[SIN_MONO_LE_EQ]);;
3248
3249 let COS_MONO_LT = prove
3250  (`!x y. &0 <= x /\ x < y /\ y <= pi ==> cos(y) < cos(x)`,
3251   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
3252   REWRITE_TAC[REAL_SUB_COS; REAL_ARITH `&0 < &2 * x <=> &0 < x`] THEN
3253   MATCH_MP_TAC REAL_LT_MUL THEN CONJ_TAC THEN MATCH_MP_TAC SIN_POS_PI THEN
3254   ASM_REAL_ARITH_TAC);;
3255
3256 let COS_MONO_LE = prove
3257  (`!x y. &0 <= x /\ x <= y /\ y <= pi ==> cos(y) <= cos(x)`,
3258   MESON_TAC[COS_MONO_LT; REAL_LE_LT]);;
3259
3260 let COS_MONO_LT_EQ = prove
3261  (`!x y. &0 <= x /\ x <= pi /\ &0 <= y /\ y <= pi
3262          ==> (cos(x) < cos(y) <=> y < x)`,
3263   MESON_TAC[REAL_NOT_LE; COS_MONO_LT; COS_MONO_LE]);;
3264
3265 let COS_MONO_LE_EQ = prove
3266  (`!x y. &0 <= x /\ x <= pi /\ &0 <= y /\ y <= pi
3267          ==> (cos(x) <= cos(y) <=> y <= x)`,
3268   MESON_TAC[REAL_NOT_LE; COS_MONO_LT; COS_MONO_LE]);;
3269
3270 let COS_INJ_PI = prove
3271  (`!x y. &0 <= x /\ x <= pi /\ &0 <= y /\ y <= pi /\ cos(x) = cos(y)
3272          ==> x = y`,
3273   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN MESON_TAC[COS_MONO_LE_EQ]);;
3274
3275 let TAN_MONO_LT = prove
3276  (`!x y. --(pi / &2) < x /\ x < y /\ y < pi / &2 ==> tan(x) < tan(y)`,
3277   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC I [GSYM REAL_SUB_LT] THEN
3278   SUBGOAL_THEN `&0 < cos(x) /\ &0 < cos(y)` STRIP_ASSUME_TAC THENL
3279    [CONJ_TAC THEN MATCH_MP_TAC COS_POS_PI;
3280     ASM_SIMP_TAC[REAL_LT_IMP_NZ; REAL_SUB_TAN] THEN
3281     MATCH_MP_TAC REAL_LT_DIV THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
3282     MATCH_MP_TAC SIN_POS_PI] THEN
3283   ASM_REAL_ARITH_TAC);;
3284
3285 let TAN_MONO_LE = prove
3286  (`!x y. --(pi / &2) < x /\ x <= y /\ y < pi / &2 ==> tan(x) <= tan(y)`,
3287   REWRITE_TAC[REAL_LE_LT] THEN MESON_TAC[TAN_MONO_LT]);;
3288
3289 let TAN_MONO_LT_EQ = prove
3290  (`!x y. --(pi / &2) < x /\ x < pi / &2 /\ --(pi / &2) < y /\ y < pi / &2
3291          ==> (tan(x) < tan(y) <=> x < y)`,
3292   MESON_TAC[REAL_NOT_LE; TAN_MONO_LT; TAN_MONO_LE]);;
3293
3294 let TAN_MONO_LE_EQ = prove
3295  (`!x y. --(pi / &2) < x /\ x < pi / &2 /\ --(pi / &2) < y /\ y < pi / &2
3296          ==> (tan(x) <= tan(y) <=> x <= y)`,
3297   MESON_TAC[REAL_NOT_LE; TAN_MONO_LT; TAN_MONO_LE]);;
3298
3299 let TAN_BOUND_PI2 = prove
3300  (`!x. abs(x) < pi / &4 ==> abs(tan x) < &1`,
3301   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM TAN_PI4] THEN
3302   REWRITE_TAC[GSYM TAN_NEG; REAL_ARITH `abs(x) < a <=> --a < x /\ x < a`] THEN
3303   CONJ_TAC THEN MATCH_MP_TAC TAN_MONO_LT THEN
3304   POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
3305
3306 let TAN_COT = prove
3307  (`!x. tan(pi / &2 - x) = inv(tan x)`,
3308   REWRITE_TAC[tan; SIN_SUB; COS_SUB; SIN_PI2; COS_PI2; REAL_INV_DIV] THEN
3309   GEN_TAC THEN BINOP_TAC THEN REAL_ARITH_TAC);;
3310
3311 (* ------------------------------------------------------------------------- *)
3312 (* Approximation to pi.                                                      *)
3313 (* ------------------------------------------------------------------------- *)
3314
3315 let SIN_PI6_STRADDLE = prove
3316  (`!a b. &0 <= a /\ a <= b /\ b <= &4 /\
3317          sin(a / &6) <= &1 / &2 /\ &1 / &2 <= sin(b / &6)
3318          ==> a <= pi /\ pi <= b`,
3319   REPEAT GEN_TAC THEN STRIP_TAC THEN
3320   MP_TAC(SPECL [`pi / &6`; `b / &6`] SIN_MONO_LE_EQ) THEN
3321   MP_TAC(SPECL [`a / &6`; `pi / &6`] SIN_MONO_LE_EQ) THEN
3322   ASM_REWRITE_TAC[SIN_PI6] THEN
3323   SUBGOAL_THEN `!x. &0 < x /\ x < &7 / &5 ==> &0 < sin x`
3324   MP_TAC THENL
3325    [REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`0`; `Cx(x)`] TAYLOR_CSIN) THEN
3326     REWRITE_TAC[VSUM_SING_NUMSEG] THEN CONV_TAC NUM_REDUCE_CONV THEN
3327     REWRITE_TAC[COMPLEX_DIV_1; COMPLEX_POW_1; complex_pow] THEN
3328     REWRITE_TAC[COMPLEX_MUL_LID; GSYM CX_SIN; GSYM CX_SUB] THEN
3329     REWRITE_TAC[IM_CX; COMPLEX_NORM_CX; REAL_ABS_NUM; REAL_EXP_0] THEN
3330     MATCH_MP_TAC(REAL_ARITH
3331      `e + d < a ==> abs(s - a) <= d ==> e < s`) THEN
3332     ASM_SIMP_TAC[real_abs; real_pow; REAL_MUL_LID; REAL_LT_IMP_LE] THEN
3333     SIMP_TAC[REAL_ARITH `&0 + x pow 3 / &2 < x <=> x * x pow 2 < x * &2`] THEN
3334     ASM_SIMP_TAC[REAL_LT_LMUL_EQ] THEN
3335     MATCH_MP_TAC REAL_LT_TRANS THEN EXISTS_TAC `(&7 / &5) pow 2` THEN
3336     ASM_SIMP_TAC[REAL_POW_LT2; ARITH_EQ; REAL_LT_IMP_LE] THEN
3337     CONV_TAC REAL_RAT_REDUCE_CONV;
3338     DISCH_THEN(MP_TAC o SPEC `pi`) THEN
3339     SIMP_TAC[SIN_PI; REAL_LT_REFL; PI_POS; REAL_NOT_LT] THEN
3340     ASM_REAL_ARITH_TAC]);;
3341
3342 let PI_APPROX_32 = prove
3343  (`abs(pi - &13493037705 / &4294967296) <= inv(&2 pow 32)`,
3344   REWRITE_TAC[REAL_ARITH `abs(x - a) <= e <=> a - e <= x /\ x <= a + e`] THEN
3345   MATCH_MP_TAC SIN_PI6_STRADDLE THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
3346   CONJ_TAC THENL
3347    [MP_TAC(SPECL [`5`; `Cx(&1686629713 / &3221225472)`] TAYLOR_CSIN);
3348     MP_TAC(SPECL [`5`; `Cx(&6746518853 / &12884901888)`] TAYLOR_CSIN)] THEN
3349   SIMP_TAC[COMPLEX_NORM_CX; GSYM CX_POW; GSYM CX_DIV; GSYM CX_MUL;
3350            GSYM CX_NEG; VSUM_CX; FINITE_NUMSEG; GSYM CX_SIN; GSYM CX_SUB] THEN
3351   REWRITE_TAC[IM_CX; REAL_ABS_NUM; REAL_EXP_0] THEN
3352   CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
3353   REWRITE_TAC[REAL_POW_ADD; REAL_POW_1; GSYM REAL_POW_POW] THEN
3354   REWRITE_TAC[REAL_MUL_ASSOC; GSYM REAL_POW_MUL; real_div] THEN
3355   REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
3356   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
3357   CONV_TAC(ONCE_DEPTH_CONV HORNER_SUM_CONV) THEN REAL_ARITH_TAC);;
3358
3359 let PI2_BOUNDS = prove
3360  (`&0 < pi / &2 /\ pi / &2 < &2`,
3361   MP_TAC PI_APPROX_32 THEN REAL_ARITH_TAC);;
3362
3363 (* ------------------------------------------------------------------------- *)
3364 (* Complex logarithms (the conventional principal value).                    *)
3365 (* ------------------------------------------------------------------------- *)
3366
3367 let clog = new_definition
3368  `clog z = @w. cexp(w) = z /\ --pi < Im(w) /\ Im(w) <= pi`;;
3369
3370 let EXISTS_COMPLEX' = prove
3371  (`!P. (?z. P (Re z) (Im z)) <=> ?x y. P x y`,
3372   MESON_TAC[RE; IM; COMPLEX]);;
3373
3374 let CLOG_WORKS = prove
3375  (`!z. ~(z = Cx(&0))
3376        ==> cexp(clog z) = z /\ --pi < Im(clog z) /\ Im(clog z) <= pi`,
3377   GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[clog] THEN CONV_TAC SELECT_CONV THEN
3378   MP_TAC(SPEC `z / Cx(norm z)` COMPLEX_UNIMODULAR_POLAR) THEN ANTS_TAC THENL
3379    [ASM_SIMP_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_CX] THEN
3380     ASM_SIMP_TAC[REAL_ABS_NORM; REAL_DIV_REFL; COMPLEX_NORM_ZERO];
3381     ALL_TAC] THEN
3382   DISCH_THEN(X_CHOOSE_THEN `x:real` STRIP_ASSUME_TAC) THEN
3383   MP_TAC(SPEC `x:real` SINCOS_PRINCIPAL_VALUE) THEN
3384   DISCH_THEN(X_CHOOSE_THEN `y:real` STRIP_ASSUME_TAC) THEN
3385   EXISTS_TAC `complex(log(norm(z:complex)),y)` THEN
3386   ASM_REWRITE_TAC[RE; IM; CEXP_COMPLEX] THEN
3387   REPEAT(FIRST_X_ASSUM(SUBST_ALL_TAC o SYM)) THEN
3388   ASM_SIMP_TAC[EXP_LOG; COMPLEX_NORM_NZ; COMPLEX_DIV_LMUL;
3389                COMPLEX_NORM_ZERO; CX_INJ]);;
3390
3391 let CEXP_CLOG = prove
3392  (`!z. ~(z = Cx(&0)) ==> cexp(clog z) = z`,
3393   SIMP_TAC[CLOG_WORKS]);;
3394
3395 let CLOG_CEXP = prove
3396  (`!z. --pi < Im(z) /\ Im(z) <= pi ==> clog(cexp z) = z`,
3397   REPEAT STRIP_TAC THEN REWRITE_TAC[clog] THEN
3398   MATCH_MP_TAC SELECT_UNIQUE THEN X_GEN_TAC `w:complex` THEN
3399   EQ_TAC THEN ASM_SIMP_TAC[] THEN REWRITE_TAC[CEXP_EQ] THEN
3400   REWRITE_TAC[IMP_CONJ] THEN DISCH_THEN(X_CHOOSE_THEN `n:real`
3401     (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN
3402   REWRITE_TAC[IM_ADD; IM_MUL_II; RE_CX] THEN REPEAT STRIP_TAC THEN
3403   ASM_CASES_TAC `n = &0` THEN ASM_REWRITE_TAC[REAL_MUL_LZERO] THEN
3404   REWRITE_TAC[REAL_MUL_RZERO; COMPLEX_ADD_RID; COMPLEX_MUL_LZERO] THEN
3405   SUBGOAL_THEN `abs(n * pi) < &1 * pi` MP_TAC THENL
3406    [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
3407   ASM_SIMP_TAC[REAL_ABS_MUL; REAL_LT_RMUL_EQ; PI_POS; REAL_ABS_PI] THEN
3408   ASM_MESON_TAC[REAL_ABS_INTEGER_LEMMA; REAL_NOT_LT]);;
3409
3410 let CLOG_EQ = prove
3411  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0)) ==> (clog w = clog z <=> w = z)`,
3412   MESON_TAC[CEXP_CLOG]);;
3413
3414 let CLOG_UNIQUE = prove
3415  (`!w z. --pi < Im(z) /\ Im(z) <= pi /\ cexp(z) = w ==> clog w = z`,
3416   MESON_TAC[CLOG_CEXP]);;
3417
3418 let RE_CLOG = prove
3419  (`!z. ~(z = Cx(&0)) ==> Re(clog z) = log(norm z)`,
3420   REPEAT STRIP_TAC THEN FIRST_X_ASSUM
3421    (MP_TAC o AP_TERM `norm:complex->real` o MATCH_MP CEXP_CLOG) THEN
3422   REWRITE_TAC[NORM_CEXP] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
3423   REWRITE_TAC[LOG_EXP]);;
3424
3425 let EXISTS_COMPLEX_ROOT = prove
3426  (`!a n. ~(n = 0) ==> ?z. z pow n = a`,
3427   REPEAT STRIP_TAC THEN ASM_CASES_TAC `a = Cx(&0)` THENL
3428    [EXISTS_TAC `Cx(&0)` THEN ASM_REWRITE_TAC[COMPLEX_POW_ZERO];
3429     EXISTS_TAC `cexp(clog(a) / Cx(&n))` THEN REWRITE_TAC[GSYM CEXP_N] THEN
3430     ASM_SIMP_TAC[COMPLEX_DIV_LMUL; CX_INJ; REAL_OF_NUM_EQ; CEXP_CLOG]]);;
3431
3432 (* ------------------------------------------------------------------------- *)
3433 (* Derivative of clog away from the branch cut.                              *)
3434 (* ------------------------------------------------------------------------- *)
3435
3436 let HAS_COMPLEX_DERIVATIVE_CLOG = prove
3437  (`!z. (Im(z) = &0 ==> &0 < Re(z))
3438        ==> (clog has_complex_derivative inv(z)) (at z)`,
3439   REPEAT STRIP_TAC THEN
3440   MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_INVERSE_STRONG_X THEN
3441   EXISTS_TAC `cexp` THEN
3442   EXISTS_TAC `{w | --pi < Im(w) /\ Im(w) < pi}` THEN
3443   REWRITE_TAC[IN_ELIM_THM] THEN
3444   ASM_CASES_TAC `z = Cx(&0)` THENL
3445    [FIRST_X_ASSUM SUBST_ALL_TAC THEN POP_ASSUM MP_TAC THEN
3446      ASM_REWRITE_TAC[RE_CX; IM_CX; REAL_LT_REFL];
3447      ALL_TAC] THEN
3448   ASM_SIMP_TAC[CONTINUOUS_ON_CEXP; CEXP_CLOG; CLOG_CEXP; REAL_LT_IMP_LE] THEN
3449   REPEAT CONJ_TAC THENL
3450    [REWRITE_TAC[SET_RULE `{x | p x /\ q x} = {x | p x} INTER {x | q x}`] THEN
3451     MATCH_MP_TAC OPEN_INTER THEN
3452     REWRITE_TAC[REAL_ARITH `--x < w <=> w > --x`] THEN
3453     REWRITE_TAC[OPEN_HALFSPACE_IM_LT; OPEN_HALFSPACE_IM_GT];
3454     ASM_SIMP_TAC[CLOG_WORKS];
3455     ASM_SIMP_TAC[CLOG_WORKS; REAL_LT_LE] THEN
3456     DISCH_THEN(fun th ->
3457       FIRST_X_ASSUM(SUBST_ALL_TAC o SYM o MATCH_MP CEXP_CLOG) THEN
3458       POP_ASSUM MP_TAC THEN ASSUME_TAC th) THEN
3459     ASM_REWRITE_TAC[EULER; COS_PI; SIN_PI; COMPLEX_MUL_RZERO] THEN
3460     REWRITE_TAC[COMPLEX_ADD_RID; CX_NEG; COMPLEX_MUL_RNEG] THEN
3461     REWRITE_TAC[COMPLEX_MUL_RID; IM_NEG; IM_CX; RE_NEG; RE_CX] THEN
3462     MP_TAC(SPEC `Re(clog z)` REAL_EXP_POS_LT) THEN REAL_ARITH_TAC;
3463     ASM_MESON_TAC[HAS_COMPLEX_DERIVATIVE_CEXP; CEXP_CLOG]]);;
3464
3465 let COMPLEX_DIFFERENTIABLE_AT_CLOG = prove
3466  (`!z. (Im(z) = &0 ==> &0 < Re(z)) ==> clog complex_differentiable at z`,
3467   REWRITE_TAC[complex_differentiable] THEN
3468   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CLOG]);;
3469
3470 let COMPLEX_DIFFERENTIABLE_WITHIN_CLOG = prove
3471  (`!s z. (Im(z) = &0 ==> &0 < Re(z))
3472          ==> clog complex_differentiable (at z within s)`,
3473   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
3474             COMPLEX_DIFFERENTIABLE_AT_CLOG]);;
3475
3476 add_complex_differentiation_theorems
3477  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
3478    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
3479              HAS_COMPLEX_DERIVATIVE_CLOG)));;
3480
3481 let CONTINUOUS_AT_CLOG = prove
3482  (`!z. (Im(z) = &0 ==> &0 < Re(z)) ==> clog continuous at z`,
3483   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CLOG;
3484             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
3485
3486 let CONTINUOUS_WITHIN_CLOG = prove
3487  (`!s z. (Im(z) = &0 ==> &0 < Re(z)) ==> clog continuous (at z within s)`,
3488   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CLOG]);;
3489
3490 let CONTINUOUS_ON_CLOG = prove
3491  (`!s. (!z. z IN s /\ Im(z) = &0 ==> &0 < Re(z)) ==> clog continuous_on s`,
3492   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CLOG]);;
3493
3494 let HOLOMORPHIC_ON_CLOG = prove
3495  (`!s. (!z. z IN s /\ Im(z) = &0 ==> &0 < Re(z)) ==> clog holomorphic_on s`,
3496   REWRITE_TAC [holomorphic_on] THEN
3497   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CLOG]);;
3498
3499 (* ------------------------------------------------------------------------- *)
3500 (* Relation to real log.                                                     *)
3501 (* ------------------------------------------------------------------------- *)
3502
3503 let CX_LOG = prove
3504  (`!z. &0 < z ==> Cx(log z) = clog(Cx z)`,
3505   REPEAT STRIP_TAC THEN FIRST_ASSUM(fun th ->
3506    GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV)
3507      [SYM(MATCH_MP EXP_LOG th)]) THEN
3508   REWRITE_TAC[CX_EXP] THEN CONV_TAC SYM_CONV THEN
3509   MATCH_MP_TAC CLOG_CEXP THEN REWRITE_TAC[IM_CX] THEN
3510   MP_TAC PI_POS THEN REAL_ARITH_TAC);;
3511
3512 (* ------------------------------------------------------------------------- *)
3513 (* Quadrant-type results for clog.                                           *)
3514 (* ------------------------------------------------------------------------- *)
3515
3516 let RE_CLOG_POS_LT = prove
3517  (`!z. ~(z = Cx(&0)) ==> (abs(Im(clog z)) < pi / &2 <=> &0 < Re(z))`,
3518   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CLOG_WORKS) THEN
3519   DISCH_THEN(CONJUNCTS_THEN2
3520     (fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SYM th])
3521     MP_TAC) THEN
3522   SIMP_TAC[RE_CEXP; REAL_LT_MUL_EQ; REAL_EXP_POS_LT] THEN
3523   SPEC_TAC(`clog z`,`z:complex`) THEN GEN_TAC THEN
3524   DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
3525    `--p < x /\ x <= p
3526     ==> --(p / &2) < x /\ x < p / &2 \/
3527         --(p / &2) <= p + x /\ p + x <= p / &2 \/
3528         --(p / &2) <= x - p /\ x - p <= p / &2`)) THEN
3529   DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC) THEN
3530   (FIRST_ASSUM(MP_TAC o MATCH_MP COS_POS_PI) ORELSE
3531    FIRST_ASSUM(MP_TAC o MATCH_MP COS_POS_PI_LE)) THEN
3532   REPEAT(POP_ASSUM MP_TAC) THEN
3533   REWRITE_TAC[COS_ADD; COS_SUB; COS_PI; SIN_PI] THEN
3534   REAL_ARITH_TAC);;
3535
3536 let RE_CLOG_POS_LE = prove
3537  (`!z. ~(z = Cx(&0)) ==> (abs(Im(clog z)) <= pi / &2 <=> &0 <= Re(z))`,
3538   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CLOG_WORKS) THEN
3539   DISCH_THEN(CONJUNCTS_THEN2
3540     (fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SYM th])
3541     MP_TAC) THEN
3542   SIMP_TAC[RE_CEXP; REAL_LE_MUL_EQ; REAL_EXP_POS_LT] THEN
3543   SPEC_TAC(`clog z`,`z:complex`) THEN GEN_TAC THEN
3544   DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
3545    `--p < x /\ x <= p
3546     ==> --(p / &2) <= x /\ x <= p / &2 \/
3547         --(p / &2) < p + x /\ p + x < p / &2 \/
3548         --(p / &2) < x - p /\ x - p < p / &2`)) THEN
3549   DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC) THEN
3550   (FIRST_ASSUM(MP_TAC o MATCH_MP COS_POS_PI) ORELSE
3551    FIRST_ASSUM(MP_TAC o MATCH_MP COS_POS_PI_LE)) THEN
3552   REPEAT(POP_ASSUM MP_TAC) THEN
3553   REWRITE_TAC[COS_ADD; COS_SUB; COS_PI; SIN_PI] THEN
3554   REAL_ARITH_TAC);;
3555
3556 let IM_CLOG_POS_LT = prove
3557  (`!z. ~(z = Cx(&0)) ==> (&0 < Im(clog z) /\ Im(clog z) < pi <=> &0 < Im(z))`,
3558   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CLOG_WORKS) THEN
3559   DISCH_THEN(CONJUNCTS_THEN2
3560     (fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SYM th])
3561     MP_TAC) THEN
3562   SIMP_TAC[IM_CEXP; REAL_LT_MUL_EQ; REAL_EXP_POS_LT] THEN
3563   SPEC_TAC(`clog z`,`z:complex`) THEN GEN_TAC THEN
3564   DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
3565    `--p < x /\ x <= p
3566     ==> &0 < x /\ x < p \/
3567         &0 <= x + p /\ x + p <= p \/
3568         &0 <= x - p /\ x - p <= p`)) THEN
3569   DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC) THEN
3570   (FIRST_ASSUM(MP_TAC o MATCH_MP SIN_POS_PI) ORELSE
3571    FIRST_ASSUM(MP_TAC o MATCH_MP SIN_POS_PI_LE)) THEN
3572   REPEAT(POP_ASSUM MP_TAC) THEN
3573   REWRITE_TAC[SIN_ADD; SIN_SUB; COS_PI; SIN_PI] THEN
3574   REAL_ARITH_TAC);;
3575
3576 let IM_CLOG_POS_LE = prove
3577  (`!z. ~(z = Cx(&0)) ==> (&0 <= Im(clog z) <=> &0 <= Im(z))`,
3578   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CLOG_WORKS) THEN
3579   DISCH_THEN(CONJUNCTS_THEN2
3580     (fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SYM th])
3581     MP_TAC) THEN
3582   SIMP_TAC[IM_CEXP; REAL_LE_MUL_EQ; REAL_EXP_POS_LT] THEN
3583   SPEC_TAC(`clog z`,`z:complex`) THEN GEN_TAC THEN
3584   DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
3585    `--p < x /\ x <= p
3586     ==> &0 <= x /\ x <= p \/
3587         &0 < x + p /\ x + p < p \/
3588         &0 < p - x /\ p - x < p`)) THEN
3589   DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC) THEN
3590   (FIRST_ASSUM(MP_TAC o MATCH_MP SIN_POS_PI) ORELSE
3591    FIRST_ASSUM(MP_TAC o MATCH_MP SIN_POS_PI_LE)) THEN
3592   REPEAT(POP_ASSUM MP_TAC) THEN
3593   REWRITE_TAC[SIN_ADD; SIN_SUB; COS_PI; SIN_PI] THEN
3594   REAL_ARITH_TAC);;
3595
3596 let RE_CLOG_POS_LT_IMP = prove
3597  (`!z. &0 < Re(z) ==> abs(Im(clog z)) < pi / &2`,
3598   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
3599   ASM_SIMP_TAC[RE_CLOG_POS_LT; RE_CX; REAL_LT_REFL]);;
3600
3601 let IM_CLOG_POS_LT_IMP = prove
3602  (`!z. &0 < Im(z) ==> &0 < Im(clog z) /\ Im(clog z) < pi`,
3603   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
3604   ASM_SIMP_TAC[IM_CLOG_POS_LT; IM_CX; REAL_LT_REFL]);;
3605
3606 let IM_CLOG_EQ_0 = prove
3607  (`!z. ~(z = Cx(&0)) ==> (Im(clog z) = &0 <=> &0 < Re(z) /\ Im(z) = &0)`,
3608   REPEAT STRIP_TAC THEN
3609   GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV)
3610    [REAL_ARITH `z = &0 <=> &0 <= z /\ ~(&0 < z)`] THEN
3611   ASM_SIMP_TAC[GSYM RE_CLOG_POS_LT; GSYM IM_CLOG_POS_LE;
3612                GSYM IM_CLOG_POS_LT] THEN
3613   MP_TAC PI_POS THEN REAL_ARITH_TAC);;
3614
3615 let IM_CLOG_EQ_PI = prove
3616  (`!z. ~(z = Cx(&0)) ==> (Im(clog z) = pi <=> Re(z) < &0 /\ Im(z) = &0)`,
3617   SIMP_TAC[PI_POS; RE_CLOG_POS_LE; IM_CLOG_POS_LE; IM_CLOG_POS_LT; CLOG_WORKS;
3618            REAL_ARITH `&0 < pi ==> (x = pi <=> (&0 <= x /\ x <= pi) /\
3619                             ~(abs x <= pi / &2) /\ ~(&0 < x /\ x < pi))`] THEN
3620   REAL_ARITH_TAC);;
3621
3622 (* ------------------------------------------------------------------------- *)
3623 (* Various properties.                                                       *)
3624 (* ------------------------------------------------------------------------- *)
3625
3626 let CNJ_CLOG = prove
3627  (`!z. (Im z = &0 ==> &0 < Re z) ==> cnj(clog z) = clog(cnj z)`,
3628   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
3629   ASM_REWRITE_TAC[RE_CX; IM_CX; REAL_LT_REFL] THEN
3630   DISCH_TAC THEN MATCH_MP_TAC COMPLEX_EQ_CEXP THEN
3631   REWRITE_TAC[GSYM CNJ_CEXP] THEN
3632   ASM_SIMP_TAC[CEXP_CLOG; CNJ_EQ_CX; IM_CNJ] THEN
3633   MATCH_MP_TAC(REAL_ARITH
3634    `(--p < x /\ x <= p) /\ (--p < y /\ y <= p) /\
3635     ~(x = p /\ y = p)
3636     ==> abs(--x - y) < &2 * p`) THEN
3637   ASM_SIMP_TAC[IM_CLOG_EQ_PI; CNJ_EQ_CX; CLOG_WORKS] THEN
3638   ASM_REAL_ARITH_TAC);;
3639
3640 let CLOG_INV = prove
3641  (`!z. (Im(z) = &0 ==> &0 < Re z) ==> clog(inv z) = --(clog z)`,
3642   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
3643   ASM_REWRITE_TAC[RE_CX; IM_CX; REAL_LT_REFL] THEN
3644   STRIP_TAC THEN MATCH_MP_TAC COMPLEX_EQ_CEXP THEN
3645   ASM_SIMP_TAC[CEXP_CLOG; CEXP_NEG; COMPLEX_INV_EQ_0] THEN
3646   REWRITE_TAC[IM_NEG; REAL_SUB_RNEG] THEN
3647   MATCH_MP_TAC(REAL_ARITH
3648    `--pi < x /\ x <= pi /\ --pi < y /\ y <= pi /\
3649     ~(x = pi /\ y = pi) ==> abs(x + y) < &2 * pi`) THEN
3650   ASM_SIMP_TAC[CLOG_WORKS; COMPLEX_INV_EQ_0; IM_CLOG_EQ_PI] THEN
3651   UNDISCH_TAC `Im z = &0 ==> &0 < Re z` THEN
3652   ASM_CASES_TAC `Im z = &0` THEN ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
3653
3654 let CLOG_1 = prove
3655  (`clog(Cx(&1)) = Cx(&0)`,
3656   REWRITE_TAC[GSYM CEXP_0] THEN MATCH_MP_TAC CLOG_CEXP THEN
3657   REWRITE_TAC[IM_CX] THEN MP_TAC PI_POS THEN REAL_ARITH_TAC);;
3658
3659 let CLOG_NEG_1 = prove
3660  (`clog(--Cx(&1)) = ii * Cx pi`,
3661   MATCH_MP_TAC COMPLEX_EQ_CEXP THEN REWRITE_TAC[GSYM CX_NEG] THEN
3662   SIMP_TAC[CEXP_EULER; GSYM CX_COS; GSYM CX_SIN; IM_MUL_II; IM_CX; RE_CX] THEN
3663   REWRITE_TAC[COS_PI; SIN_PI; COMPLEX_MUL_RZERO; COMPLEX_ADD_RID] THEN
3664   SIMP_TAC[CLOG_WORKS; COMPLEX_RING `~(Cx(-- &1) = Cx(&0))`;
3665            REAL_ARITH `--pi < x /\ x <= pi ==> abs(x - pi) < &2 * pi`]);;
3666
3667 let CLOG_II = prove
3668  (`clog ii = ii * Cx(pi / &2)`,
3669   MP_TAC(SPEC `ii * Cx(pi / &2)` CLOG_CEXP) THEN
3670   SIMP_TAC[CEXP_EULER; GSYM CX_COS; GSYM CX_SIN; IM_MUL_II; IM_CX; RE_CX] THEN
3671   REWRITE_TAC[COS_PI2; SIN_PI2] THEN ANTS_TAC THENL
3672    [MP_TAC PI_POS THEN REAL_ARITH_TAC;
3673     REWRITE_TAC[COMPLEX_ADD_LID; COMPLEX_MUL_RID]]);;
3674
3675 let CLOG_NEG_II = prove
3676  (`clog(--ii) = --ii * Cx(pi / &2)`,
3677   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [COMPLEX_FIELD `--ii = inv ii`] THEN
3678   SIMP_TAC[CLOG_INV; RE_II; IM_II; REAL_OF_NUM_EQ; ARITH; CLOG_II] THEN
3679   REWRITE_TAC[COMPLEX_MUL_LNEG]);;
3680
3681 (* ------------------------------------------------------------------------- *)
3682 (* Relation between square root and exp/log, and hence its derivative.       *)
3683 (* ------------------------------------------------------------------------- *)
3684
3685 let CSQRT_CEXP_CLOG = prove
3686  (`!z. ~(z = Cx(&0)) ==> csqrt z = cexp(clog(z) / Cx(&2))`,
3687   REPEAT STRIP_TAC THEN MATCH_MP_TAC CSQRT_UNIQUE THEN
3688   REWRITE_TAC[GSYM CEXP_N; RE_CEXP; IM_CEXP] THEN
3689   ASM_SIMP_TAC[COMPLEX_DIV_LMUL; CX_INJ; REAL_OF_NUM_EQ; ARITH; CEXP_CLOG] THEN
3690   SIMP_TAC[REAL_LT_MUL_EQ; REAL_EXP_POS_LT; REAL_LE_MUL_EQ] THEN
3691   REWRITE_TAC[REAL_ENTIRE; REAL_EXP_NZ; IM_DIV_CX] THEN
3692   FIRST_ASSUM(STRIP_ASSUME_TAC o CONJUNCT2 o MATCH_MP CLOG_WORKS) THEN
3693   FIRST_X_ASSUM(DISJ_CASES_TAC o REWRITE_RULE[REAL_LE_LT]) THENL
3694    [DISJ1_TAC THEN MATCH_MP_TAC COS_POS_PI THEN
3695     ASM_REAL_ARITH_TAC;
3696     DISJ2_TAC THEN ASM_REWRITE_TAC[COS_PI2; SIN_PI2; REAL_POS]]);;
3697
3698 let CNJ_CSQRT = prove
3699  (`!z. (Im z = &0 ==> &0 <= Re(z)) ==> cnj(csqrt z) = csqrt(cnj z)`,
3700   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
3701   ASM_REWRITE_TAC[CSQRT_0; CNJ_CX] THEN DISCH_TAC THEN
3702   SUBGOAL_THEN `Im z = &0 ==> &0 < Re(z)` ASSUME_TAC THENL
3703    [REPEAT(POP_ASSUM MP_TAC) THEN
3704     REWRITE_TAC[COMPLEX_EQ; IM_CX; RE_CX] THEN REAL_ARITH_TAC;
3705     ASM_REWRITE_TAC[RE_CX; IM_CX; REAL_LT_REFL] THEN
3706     ASM_SIMP_TAC[CSQRT_CEXP_CLOG; CNJ_CEXP; CNJ_CLOG;
3707                  CNJ_DIV; CNJ_EQ_CX; CNJ_CX]]);;
3708
3709 let HAS_COMPLEX_DERIVATIVE_CSQRT = prove
3710  (`!z. (Im z = &0 ==> &0 < Re(z))
3711        ==> (csqrt has_complex_derivative inv(Cx(&2) * csqrt z)) (at z)`,
3712   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
3713   ASM_REWRITE_TAC[IM_CX; RE_CX; REAL_LT_REFL] THEN DISCH_TAC THEN
3714   MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_TRANSFORM_AT THEN
3715   MAP_EVERY EXISTS_TAC [`\z. cexp(clog(z) / Cx(&2))`; `norm(z:complex)`] THEN
3716   ASM_REWRITE_TAC[COMPLEX_NORM_NZ] THEN CONJ_TAC THENL
3717    [REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN
3718     MATCH_MP_TAC CSQRT_CEXP_CLOG THEN REWRITE_TAC[GSYM COMPLEX_VEC_0] THEN
3719     REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC;
3720     COMPLEX_DIFF_TAC THEN ASM_SIMP_TAC[GSYM CSQRT_CEXP_CLOG] THEN
3721     UNDISCH_TAC `~(z = Cx(&0))` THEN MP_TAC(SPEC `z:complex` CSQRT) THEN
3722     CONV_TAC COMPLEX_FIELD]);;
3723
3724 let COMPLEX_DIFFERENTIABLE_AT_CSQRT = prove
3725  (`!z. (Im z = &0 ==> &0 < Re(z)) ==> csqrt complex_differentiable at z`,
3726   REWRITE_TAC[complex_differentiable] THEN
3727   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CSQRT]);;
3728
3729 let COMPLEX_DIFFERENTIABLE_WITHIN_CSQRT = prove
3730  (`!s z. (Im z = &0 ==> &0 < Re(z))
3731          ==> csqrt complex_differentiable (at z within s)`,
3732   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
3733             COMPLEX_DIFFERENTIABLE_AT_CSQRT]);;
3734
3735 add_complex_differentiation_theorems
3736  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
3737    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
3738              HAS_COMPLEX_DERIVATIVE_CSQRT)));;
3739
3740 let CONTINUOUS_AT_CSQRT = prove
3741  (`!z. (Im z = &0 ==> &0 < Re(z)) ==> csqrt continuous at z`,
3742   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CSQRT;
3743             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
3744
3745 let CONTINUOUS_WITHIN_CSQRT = prove
3746  (`!s z. (Im z = &0 ==> &0 < Re(z)) ==> csqrt continuous (at z within s)`,
3747   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CSQRT]);;
3748
3749 let CONTINUOUS_ON_CSQRT = prove
3750  (`!s. (!z. z IN s /\ Im z = &0 ==> &0 < Re(z)) ==> csqrt continuous_on s`,
3751   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CSQRT]);;
3752
3753 let HOLOMORPHIC_ON_CSQRT = prove
3754  (`!s. (!z. z IN s /\ Im(z) = &0 ==> &0 < Re(z)) ==> csqrt holomorphic_on s`,
3755   REWRITE_TAC [holomorphic_on] THEN
3756   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CSQRT]);;
3757
3758 let CONTINUOUS_WITHIN_CSQRT_POSREAL = prove
3759  (`!z. csqrt continuous (at z within {w | real w /\ &0 <= Re(w)})`,
3760   REPEAT STRIP_TAC THEN ASM_CASES_TAC `Im z = &0 ==> &0 < Re(z)` THENL
3761    [ASM_SIMP_TAC[CONTINUOUS_WITHIN_CSQRT]; ALL_TAC] THEN
3762   POP_ASSUM MP_TAC THEN REWRITE_TAC[NOT_IMP; REAL_NOT_LT] THEN
3763   REWRITE_TAC[REAL_ARITH `x <= &0 <=> x < &0 \/ x = &0`] THEN STRIP_TAC THENL
3764    [MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN
3765     REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
3766     SIMP_TAC[CLOSED_REAL_SET; CLOSED_INTER; IN_INTER; IN_ELIM_THM;
3767              REWRITE_RULE[real_ge] CLOSED_HALFSPACE_RE_GE] THEN
3768     ASM_REAL_ARITH_TAC;
3769     SUBGOAL_THEN `z = Cx(&0)` SUBST_ALL_TAC THENL
3770      [ASM_REWRITE_TAC[COMPLEX_EQ; RE_CX; IM_CX]; ALL_TAC] THEN
3771     REWRITE_TAC[continuous_within] THEN
3772     REWRITE_TAC[IN_ELIM_THM; IMP_CONJ; FORALL_REAL; RE_CX] THEN
3773     SIMP_TAC[GSYM CX_SQRT; REAL_LE_REFL] THEN
3774     SIMP_TAC[dist; GSYM CX_SUB; COMPLEX_NORM_CX; SQRT_0; REAL_SUB_RZERO] THEN
3775     X_GEN_TAC `e:real` THEN STRIP_TAC THEN EXISTS_TAC `(e:real) pow 2` THEN
3776     ASM_SIMP_TAC[REAL_POW_LT] THEN REPEAT STRIP_TAC THEN
3777     SUBGOAL_THEN `e = sqrt(e pow 2)` SUBST1_TAC THENL
3778      [ASM_SIMP_TAC[POW_2_SQRT; REAL_LT_IMP_LE];
3779       ASM_SIMP_TAC[real_abs; SQRT_POS_LE]] THEN
3780     MATCH_MP_TAC SQRT_MONO_LT THEN ASM_REAL_ARITH_TAC]);;
3781
3782 (* ------------------------------------------------------------------------- *)
3783 (* Complex powers.                                                           *)
3784 (* ------------------------------------------------------------------------- *)
3785
3786 parse_as_infix("cpow",(24,"left"));;
3787
3788 let cpow = new_definition
3789  `w cpow z = if w = Cx(&0) then Cx(&0)
3790              else cexp(z * clog w)`;;
3791
3792 let CPOW_0 = prove
3793  (`!z. Cx(&0) cpow z = Cx(&0)`,
3794   REWRITE_TAC[cpow]);;
3795
3796 let CPOW_N = prove
3797  (`!z. z cpow (Cx(&n)) = if z = Cx(&0) then Cx(&0) else z pow n`,
3798   GEN_TAC THEN REWRITE_TAC[cpow] THEN COND_CASES_TAC THEN
3799   ASM_SIMP_TAC[CEXP_N; CEXP_CLOG]);;
3800
3801 let CPOW_1 = prove
3802  (`!z. Cx(&1) cpow z = Cx(&1)`,
3803   REWRITE_TAC[cpow; CX_INJ; REAL_OF_NUM_EQ; ARITH_EQ; CLOG_1] THEN
3804   REWRITE_TAC[CEXP_0; COMPLEX_MUL_RZERO]);;
3805
3806 let CPOW_ADD = prove
3807  (`!w z1 z2. w cpow (z1 + z2) = w cpow z1 * w cpow z2`,
3808   REPEAT GEN_TAC THEN REWRITE_TAC[cpow] THEN
3809   ASM_CASES_TAC `w = Cx(&0)` THEN ASM_REWRITE_TAC[COMPLEX_MUL_RZERO] THEN
3810   REWRITE_TAC[COMPLEX_ADD_RDISTRIB; CEXP_ADD]);;
3811
3812 let CPOW_SUC = prove
3813  (`!w z. w cpow (z + Cx(&1)) = w * w cpow z`,
3814   REPEAT GEN_TAC THEN REWRITE_TAC[CPOW_ADD; CPOW_N] THEN
3815   COND_CASES_TAC THEN
3816   ASM_REWRITE_TAC[COMPLEX_MUL_LZERO; COMPLEX_MUL_RZERO] THEN
3817   REWRITE_TAC[COMPLEX_POW_1; COMPLEX_MUL_SYM]);;
3818
3819 let CPOW_NEG = prove
3820  (`!w z. w cpow (--z) = inv(w cpow z)`,
3821   REPEAT GEN_TAC THEN REWRITE_TAC[cpow] THEN ASM_CASES_TAC `w = Cx(&0)` THEN
3822   ASM_REWRITE_TAC[COMPLEX_MUL_RZERO; COMPLEX_INV_0] THEN
3823   REWRITE_TAC[COMPLEX_MUL_LNEG; CEXP_NEG]);;
3824
3825 let CPOW_SUB = prove
3826  (`!w z1 z2. w cpow (z1 - z2) = w cpow z1 / w cpow z2`,
3827   REWRITE_TAC[complex_sub; complex_div; CPOW_ADD; CPOW_NEG]);;
3828
3829 let CEXP_MUL_CPOW = prove
3830  (`!w z. --pi < Im w /\ Im w <= pi ==> cexp(w * z) = cexp(w) cpow z`,
3831   SIMP_TAC[cpow; CEXP_NZ; CLOG_CEXP] THEN
3832   REWRITE_TAC[COMPLEX_MUL_SYM]);;
3833
3834 let CPOW_EQ_0 = prove
3835  (`!w z. w cpow z = Cx(&0) <=> w = Cx(&0)`,
3836   REPEAT GEN_TAC THEN REWRITE_TAC[cpow] THEN
3837   COND_CASES_TAC THEN ASM_REWRITE_TAC[CEXP_NZ]);;
3838
3839 let NORM_CPOW_REAL = prove
3840  (`!w z. real w /\ &0 < Re w ==> norm(w cpow z) = exp(Re z * log(Re w))`,
3841   REPEAT STRIP_TAC THEN
3842   FIRST_X_ASSUM(SUBST_ALL_TAC o SYM o GEN_REWRITE_RULE I [REAL]) THEN
3843   RULE_ASSUM_TAC(REWRITE_RULE[RE_CX]) THEN
3844   ASM_SIMP_TAC[cpow; CX_INJ; REAL_LT_IMP_NZ] THEN
3845   ASM_SIMP_TAC[NORM_CEXP; GSYM CX_LOG; RE_MUL_CX; RE_CX]);;
3846
3847 let CPOW_REAL_REAL = prove
3848  (`!w z. real w /\ real z /\ &0 < Re w
3849          ==> w cpow z = Cx(exp(Re z * log(Re w)))`,
3850   REPEAT STRIP_TAC THEN
3851   REPEAT(FIRST_X_ASSUM(SUBST_ALL_TAC o SYM o GEN_REWRITE_RULE I [REAL])) THEN
3852   RULE_ASSUM_TAC(REWRITE_RULE[RE_CX]) THEN
3853   ASM_SIMP_TAC[cpow; CX_INJ; REAL_LT_IMP_NZ] THEN
3854   ASM_SIMP_TAC[NORM_CEXP; GSYM CX_LOG; RE_MUL_CX; RE_CX; CX_EXP; CX_MUL]);;
3855
3856 let NORM_CPOW_REAL_MONO = prove
3857  (`!w z1 z2. real w /\ &1 < Re w
3858              ==> (norm(w cpow z1) <= norm(w cpow z2) <=> Re(z1) <= Re(z2))`,
3859   SIMP_TAC[NORM_CPOW_REAL; REAL_ARITH `&1 < x ==> &0 < x`] THEN
3860   SIMP_TAC[REAL_EXP_MONO_LE; REAL_LE_RMUL_EQ; LOG_POS_LT]);;
3861
3862 let CPOW_MUL_REAL = prove
3863  (`!x y z. real x /\ real y /\ &0 <= Re x /\ &0 <= Re y
3864            ==> (x * y) cpow z = x cpow z * y cpow z`,
3865   REPEAT STRIP_TAC THEN
3866   REPEAT(FIRST_X_ASSUM(SUBST_ALL_TAC o SYM o GEN_REWRITE_RULE I [REAL])) THEN
3867   REPEAT(POP_ASSUM MP_TAC) THEN REWRITE_TAC[RE_CX; IM_CX] THEN
3868   REWRITE_TAC[REAL_ARITH `&0 <= x <=> x = &0 \/ &0 < x`] THEN
3869   REPEAT STRIP_TAC THEN
3870   ASM_REWRITE_TAC[COMPLEX_MUL_LZERO; COMPLEX_MUL_RZERO; CPOW_0] THEN
3871   ASM_SIMP_TAC[cpow; COMPLEX_ENTIRE; CX_INJ; REAL_LT_IMP_NZ] THEN
3872   REWRITE_TAC[GSYM CEXP_ADD; GSYM COMPLEX_ADD_LDISTRIB] THEN
3873   ASM_SIMP_TAC[GSYM CX_LOG; GSYM CX_ADD; GSYM CX_MUL; REAL_LT_MUL] THEN
3874   ASM_SIMP_TAC[LOG_MUL]);;
3875
3876 let HAS_COMPLEX_DERIVATIVE_CPOW = prove
3877  (`!s z. (Im z = &0 ==> &0 < Re z)
3878          ==> ((\z. z cpow s) has_complex_derivative
3879               (s * z cpow (s - Cx(&1)))) (at z)`,
3880   REPEAT GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
3881   ASM_REWRITE_TAC[IM_CX; RE_CX; REAL_LT_REFL] THEN
3882   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[cpow] THEN
3883   MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_TRANSFORM_AT THEN
3884   MAP_EVERY EXISTS_TAC [`\z. cexp (s * clog z)`; `norm(z:complex)`] THEN
3885   ASM_REWRITE_TAC[COMPLEX_NORM_NZ] THEN CONJ_TAC THENL
3886    [GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[dist] THEN
3887     REWRITE_TAC[COMPLEX_SUB_LZERO; NORM_NEG; REAL_LT_REFL];
3888     COMPLEX_DIFF_TAC THEN ASM_REWRITE_TAC[CEXP_SUB; COMPLEX_SUB_RDISTRIB] THEN
3889     ASM_SIMP_TAC[CEXP_CLOG; COMPLEX_MUL_LID] THEN
3890     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC COMPLEX_FIELD]);;
3891
3892 add_complex_differentiation_theorems
3893  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
3894    (GEN `s:complex`
3895      (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
3896                (SPEC `s:complex` HAS_COMPLEX_DERIVATIVE_CPOW)))));;
3897
3898 let HAS_COMPLEX_DERIVATIVE_CPOW_RIGHT = prove
3899  (`!w z. ~(w = Cx(&0))
3900          ==> ((\z. w cpow z) has_complex_derivative clog(w) * w cpow z) (at z)`,
3901   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[cpow] THEN
3902   COMPLEX_DIFF_TAC THEN REWRITE_TAC[COMPLEX_MUL_LID]);;
3903
3904 add_complex_differentiation_theorems
3905  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
3906    (GEN `s:complex`
3907      (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
3908                (SPEC `s:complex` HAS_COMPLEX_DERIVATIVE_CPOW_RIGHT)))));;
3909
3910 let COMPLEX_DIFFERENTIABLE_CPOW_RIGHT = prove
3911  (`!w z. (\z. w cpow z) complex_differentiable (at z)`,
3912   REPEAT GEN_TAC THEN ASM_CASES_TAC `w = Cx(&0)` THENL
3913    [ASM_REWRITE_TAC[cpow; COMPLEX_DIFFERENTIABLE_CONST];
3914     REWRITE_TAC[complex_differentiable] THEN
3915     ASM_MESON_TAC[HAS_COMPLEX_DERIVATIVE_CPOW_RIGHT]]);;
3916
3917 let HOLOMORPHIC_ON_CPOW_RIGHT = prove
3918  (`!w f s. f holomorphic_on s
3919            ==> (\z. w cpow (f z)) holomorphic_on s`,
3920   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
3921   MATCH_MP_TAC HOLOMORPHIC_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN
3922   GEN_REWRITE_TAC LAND_CONV [GSYM ETA_AX] THEN
3923   REWRITE_TAC[holomorphic_on; GSYM complex_differentiable] THEN
3924   ASM_SIMP_TAC[COMPLEX_DIFFERENTIABLE_CPOW_RIGHT;
3925                COMPLEX_DIFFERENTIABLE_AT_WITHIN]);;
3926
3927 (* ------------------------------------------------------------------------- *)
3928 (* Product rule.                                                             *)
3929 (* ------------------------------------------------------------------------- *)
3930
3931 let CLOG_MUL = prove
3932  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
3933            ==> clog(w * z) =
3934                 if Im(clog w + clog z) <= --pi then
3935                   (clog(w) + clog(z)) + ii * Cx(&2 * pi)
3936                 else if Im(clog w + clog z) > pi then
3937                   (clog(w) + clog(z)) - ii * Cx(&2 * pi)
3938                 else clog(w) + clog(z)`,
3939   REPEAT STRIP_TAC THEN
3940   REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
3941   MATCH_MP_TAC CLOG_UNIQUE THEN
3942   ASM_SIMP_TAC[CEXP_ADD; CEXP_SUB; CEXP_EULER; CEXP_CLOG; CONJ_ASSOC;
3943                GSYM CX_SIN; GSYM CX_COS; COS_NPI; SIN_NPI] THEN
3944   CONV_TAC REAL_RAT_REDUCE_CONV THEN
3945   TRY(CONJ_TAC THENL [ALL_TAC; CONV_TAC COMPLEX_FIELD]) THEN
3946   REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP CLOG_WORKS)) THEN
3947   REPEAT(POP_ASSUM MP_TAC) THEN
3948   REWRITE_TAC[IM_ADD; IM_SUB; IM_MUL_II; RE_CX] THEN
3949   REAL_ARITH_TAC);;
3950
3951 let CLOG_MUL_SIMPLE = prove
3952  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0)) /\
3953          --pi < Im(clog(w)) + Im(clog(z)) /\
3954          Im(clog(w)) + Im(clog(z)) <= pi
3955          ==> clog(w * z) = clog(w) + clog(z)`,
3956   SIMP_TAC[CLOG_MUL; IM_ADD] THEN REAL_ARITH_TAC);;
3957
3958 let CLOG_MUL_CX = prove
3959  (`(!x z. &0 < x /\ ~(z = Cx(&0)) ==> clog(Cx x * z) = Cx(log x) + clog z) /\
3960    (!x z. &0 < x /\ ~(z = Cx(&0)) ==> clog(z * Cx x) = clog z + Cx(log x))`,
3961   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CX_LOG] THEN
3962   MATCH_MP_TAC CLOG_MUL_SIMPLE THEN
3963   ASM_SIMP_TAC[CX_INJ; REAL_LT_IMP_NZ; GSYM CX_LOG] THEN
3964   ASM_SIMP_TAC[IM_CX; REAL_ADD_LID; REAL_ADD_RID; CLOG_WORKS]);;
3965
3966 let CLOG_NEG = prove
3967  (`!z. ~(z = Cx(&0))
3968        ==> clog(--z) = if Im(z) <= &0 /\ ~(Re(z) < &0 /\ Im(z) = &0)
3969                        then clog(z) + ii * Cx(pi)
3970                        else clog(z) - ii * Cx(pi)`,
3971   REPEAT STRIP_TAC THEN
3972   SUBST1_TAC(SIMPLE_COMPLEX_ARITH `--z = --Cx(&1) * z`) THEN
3973   ASM_SIMP_TAC[CLOG_MUL; COMPLEX_RING `~(--Cx(&1) = Cx(&0))`] THEN
3974   REWRITE_TAC[CLOG_NEG_1; IM_ADD; IM_MUL_II; RE_CX] THEN
3975   ASM_SIMP_TAC[CLOG_WORKS; REAL_ARITH
3976    `--p < x /\ x <= p ==> ~(p + x <= --p)`] THEN
3977   REWRITE_TAC[REAL_ARITH `p + x > p <=> &0 < x`] THEN
3978   ASM_SIMP_TAC[GSYM IM_CLOG_EQ_PI] THEN
3979   ONCE_REWRITE_TAC[REAL_ARITH `Im z <= &0 <=> ~(&0 < Im z)`] THEN
3980   ASM_SIMP_TAC[GSYM IM_CLOG_POS_LT] THEN
3981   ASM_SIMP_TAC[CLOG_WORKS; REAL_ARITH `x <= p ==> (x < p <=> ~(x = p))`] THEN
3982   REWRITE_TAC[TAUT `~(a /\ ~b) /\ ~b <=> ~a /\ ~b`] THEN
3983   ASM_CASES_TAC `Im(clog z) = pi` THEN ASM_REWRITE_TAC[PI_POS] THEN
3984   ASM_CASES_TAC `&0 < Im(clog z)` THEN ASM_REWRITE_TAC[] THEN
3985   REWRITE_TAC[CX_MUL] THEN CONV_TAC COMPLEX_RING);;
3986
3987 let CLOG_MUL_II = prove
3988  (`!z. ~(z = Cx(&0))
3989        ==> clog(ii * z) = if &0 <= Re(z) \/ Im(z) < &0
3990                           then clog(z) + ii * Cx(pi / &2)
3991                           else clog(z) - ii * Cx(&3 * pi / &2)`,
3992   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CLOG_MUL; II_NZ; CLOG_II] THEN
3993   REWRITE_TAC[IM_ADD; IM_MUL_II; RE_CX] THEN
3994   ASM_SIMP_TAC[CLOG_WORKS; REAL_ARITH
3995    `--p < x /\ x <= p ==> ~(p / &2 + x <= --p)`] THEN
3996   REWRITE_TAC[REAL_ARITH `p / &2 + x > p <=> p / &2 < x`] THEN
3997   REWRITE_TAC[REAL_ARITH `Im z < &0 <=> ~(&0 <= Im z)`] THEN
3998   ASM_SIMP_TAC[GSYM RE_CLOG_POS_LE; GSYM IM_CLOG_POS_LE] THEN
3999   MATCH_MP_TAC(MESON[]
4000    `(p <=> ~q) /\ x = a /\ y = b
4001     ==> ((if p then x else y) = (if q then b else a))`) THEN
4002   CONJ_TAC THENL
4003    [MP_TAC PI_POS THEN REAL_ARITH_TAC;
4004     REWRITE_TAC[CX_MUL; CX_DIV] THEN CONV_TAC COMPLEX_RING]);;
4005
4006 (* ------------------------------------------------------------------------- *)
4007 (* Unwinding number gives another version of log-product formula.            *)
4008 (* Note that in this special case the unwinding number is -1, 0 or 1.        *)
4009 (* ------------------------------------------------------------------------- *)
4010
4011 let unwinding = new_definition
4012  `unwinding(z) = (z - clog(cexp z)) / (Cx(&2 * pi) * ii)`;;
4013
4014 let UNWINDING_2PI = prove
4015  (`Cx(&2 * pi) * ii * unwinding(z) = z - clog(cexp z)`,
4016   REWRITE_TAC[unwinding; COMPLEX_MUL_ASSOC] THEN
4017   MATCH_MP_TAC COMPLEX_DIV_LMUL THEN
4018   REWRITE_TAC[COMPLEX_ENTIRE; CX_INJ; II_NZ] THEN
4019   MP_TAC PI_POS THEN REAL_ARITH_TAC);;
4020
4021 let CLOG_MUL_UNWINDING = prove
4022  (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
4023            ==> clog(w * z) =
4024                clog(w) + clog(z) -
4025                Cx(&2 * pi) * ii * unwinding(clog w + clog z)`,
4026   REWRITE_TAC[UNWINDING_2PI;
4027     COMPLEX_RING `w + z - ((w + z) - c) = c:complex`] THEN
4028   ASM_SIMP_TAC[CEXP_ADD; CEXP_CLOG]);;
4029
4030 (* ------------------------------------------------------------------------- *)
4031 (* Complex arctangent (branch cut gives standard bounds in real case).       *)
4032 (* ------------------------------------------------------------------------- *)
4033
4034 let catn = new_definition
4035  `catn z = (ii / Cx(&2)) * clog((Cx(&1) - ii * z) / (Cx(&1) + ii * z))`;;
4036
4037 let CATN_0 = prove
4038  (`catn(Cx(&0)) = Cx(&0)`,
4039   REWRITE_TAC[catn; COMPLEX_MUL_RZERO; COMPLEX_SUB_RZERO; COMPLEX_ADD_RID] THEN
4040   REWRITE_TAC[COMPLEX_DIV_1; CLOG_1; COMPLEX_MUL_RZERO]);;
4041
4042 let IM_COMPLEX_DIV_LEMMA = prove
4043  (`!z. Im((Cx(&1) - ii * z) / (Cx(&1) + ii * z)) = &0 <=> Re z = &0`,
4044   REWRITE_TAC[IM_COMPLEX_DIV_EQ_0] THEN
4045   REWRITE_TAC[complex_mul;  IM; RE; IM_CNJ; RE_CNJ; RE_CX; IM_CX; RE_II; IM_II;
4046               RE_SUB; RE_ADD; IM_SUB; IM_ADD] THEN
4047   REAL_ARITH_TAC);;
4048
4049 let RE_COMPLEX_DIV_LEMMA = prove
4050  (`!z. &0 < Re((Cx(&1) - ii * z) / (Cx(&1) + ii * z)) <=> norm(z) < &1`,
4051   REWRITE_TAC[RE_COMPLEX_DIV_GT_0; NORM_LT_SQUARE; REAL_LT_01] THEN
4052   REWRITE_TAC[GSYM NORM_POW_2; COMPLEX_SQNORM] THEN
4053   REWRITE_TAC[complex_mul;  IM; RE; IM_CNJ; RE_CNJ; RE_CX; IM_CX; RE_II; IM_II;
4054               RE_SUB; RE_ADD; IM_SUB; IM_ADD] THEN
4055   REAL_ARITH_TAC);;
4056
4057 let CTAN_CATN = prove
4058  (`!z. ~(z pow 2 = --Cx(&1)) ==> ctan(catn z) = z`,
4059   REPEAT STRIP_TAC THEN
4060   REWRITE_TAC[catn; ctan; csin; ccos;
4061               COMPLEX_RING `--i * i / Cx(&2) * z = --(i * i) / Cx(&2) * z`;
4062               COMPLEX_RING `i * i / Cx(&2) * z =  (i * i) / Cx(&2) * z`] THEN
4063   REWRITE_TAC[COMPLEX_POW_II_2; GSYM COMPLEX_POW_2] THEN
4064   REWRITE_TAC[COMPLEX_RING `--Cx(&1) / Cx(&2) * x = --(Cx(&1) / Cx(&2) * x)`;
4065               CEXP_NEG] THEN
4066   SUBGOAL_THEN
4067   `~(cexp(Cx(&1) / Cx(&2) *
4068           (clog((Cx(&1) - ii * z) / (Cx(&1) + ii * z)))) pow 2 = --Cx(&1))`
4069   ASSUME_TAC THENL
4070    [REWRITE_TAC[GSYM CEXP_N; CEXP_SUB; COMPLEX_RING
4071      `Cx(&2) * Cx(&1) / Cx(&2) * z = z`] THEN
4072     ASM_SIMP_TAC[CEXP_CLOG; COMPLEX_POW_II_2;
4073       COMPLEX_FIELD `~(w = Cx(&0)) /\ ~(z = Cx(&0)) ==> ~(w / z = Cx(&0))`;
4074       COMPLEX_FIELD `~(w = Cx(&0)) ==> (x / w = y <=> x = y * w)`;
4075       COMPLEX_FIELD
4076      `ii pow 2 = --Cx(&1) /\ ~(z pow 2 = --Cx(&1))
4077       ==> ~(Cx(&1) - ii * z = Cx(&0)) /\ ~(Cx(&1) + ii * z = Cx(&0))`] THEN
4078     POP_ASSUM MP_TAC THEN CONV_TAC COMPLEX_FIELD;
4079     ALL_TAC] THEN
4080   REWRITE_TAC[COMPLEX_RING `-- --Cx (&1) / Cx (&2) = Cx(&1) / Cx(&2)`] THEN
4081   ASM_SIMP_TAC[CEXP_NZ; COMPLEX_FIELD
4082     `~(z = Cx(&0)) /\ ~(z pow 2 = --Cx(&1))
4083      ==> ((inv(z) - z) / (Cx(&2) * ii)) / ((inv(z) + z) / Cx(&2)) =
4084          inv ii * ((Cx(&1) - z pow 2) / (Cx(&1) + z pow 2))`] THEN
4085   ASM_SIMP_TAC[GSYM CEXP_N; CEXP_SUB;
4086                COMPLEX_RING `Cx(&2) * Cx(&1) / Cx(&2) * z = z`] THEN
4087   ASM_SIMP_TAC[CEXP_CLOG; COMPLEX_FIELD
4088      `~(z pow 2 = --Cx(&1))
4089       ==> ~((Cx(&1) - ii * z) / (Cx(&1) + ii * z) = Cx(&0))`] THEN
4090   UNDISCH_TAC `~(z pow 2 = --Cx(&1))` THEN CONV_TAC COMPLEX_FIELD);;
4091
4092 let CATN_CTAN = prove
4093  (`!z. abs(Re z) < pi / &2 ==> catn(ctan z) = z`,
4094   REPEAT STRIP_TAC THEN REWRITE_TAC[catn; ctan; csin; ccos] THEN
4095   ASM_SIMP_TAC[COMPLEX_FIELD
4096    `ii * (a / (Cx(&2) * ii)) / (b / Cx(&2)) = a / b`] THEN
4097   SIMP_TAC[COMPLEX_FIELD
4098    `ii / Cx(&2) * x = y <=> x = Cx(&2) * --(ii * y)`] THEN
4099   SUBGOAL_THEN `~(cexp(ii * z) pow 2 = --Cx(&1))` ASSUME_TAC THENL
4100    [SUBGOAL_THEN `--Cx(&1) = cexp(ii * Cx pi)` SUBST1_TAC THENL
4101      [REWRITE_TAC[CEXP_EULER; GSYM CX_SIN; GSYM CX_COS; SIN_PI; COS_PI] THEN
4102       CONV_TAC COMPLEX_RING;
4103       ALL_TAC] THEN
4104     REWRITE_TAC[GSYM CEXP_N; CEXP_EQ] THEN
4105     DISCH_THEN(X_CHOOSE_THEN `n:real` STRIP_ASSUME_TAC) THEN
4106     FIRST_X_ASSUM(MP_TAC o AP_TERM `Im`) THEN
4107     REWRITE_TAC[IM_MUL_CX; IM_MUL_II; IM_ADD; RE_CX; IM_II; REAL_MUL_RID] THEN
4108     MATCH_MP_TAC(REAL_ARITH
4109      `abs(z) < p / &2 /\ (w = &0 \/ abs(w) >= &2 * p)
4110       ==> ~(&2 * z = p + w)`) THEN
4111     ASM_REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_PI; REAL_ABS_NUM] THEN
4112     SIMP_TAC[real_ge; REAL_MUL_ASSOC; REAL_LE_RMUL_EQ; PI_POS] THEN
4113     REWRITE_TAC[REAL_ENTIRE; PI_NZ] THEN
4114     MP_TAC(SPEC `n:real` REAL_ABS_INTEGER_LEMMA) THEN
4115     ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
4116     ASM_SIMP_TAC[CEXP_NEG; CEXP_NZ; COMPLEX_MUL_LNEG; COMPLEX_FIELD
4117      `~(w = Cx(&0)) /\ ~(w pow 2 = --Cx(&1))
4118       ==> (Cx(&1) - (w - inv w) / (w + inv w)) /
4119           (Cx(&1) + (w - inv w) / (w + inv w)) =
4120            inv(w) pow 2`] THEN
4121     REWRITE_TAC[GSYM CEXP_N; GSYM CEXP_NEG] THEN
4122     MATCH_MP_TAC CLOG_CEXP THEN REWRITE_TAC[IM_MUL_CX; IM_NEG; IM_MUL_II] THEN
4123     ASM_REAL_ARITH_TAC]);;
4124
4125 let RE_CATN_BOUNDS = prove
4126  (`!z. (Re z = &0 ==> abs(Im z) < &1) ==> abs(Re(catn z)) < pi / &2`,
4127   REWRITE_TAC[catn; complex_div; GSYM CX_INV; GSYM COMPLEX_MUL_ASSOC] THEN
4128   REPEAT STRIP_TAC THEN REWRITE_TAC[RE_MUL_II; IM_MUL_CX] THEN
4129   MATCH_MP_TAC(REAL_ARITH `abs x < p ==> abs(--(inv(&2) * x)) < p / &2`) THEN
4130   MATCH_MP_TAC(REAL_ARITH `(--p < x /\ x <= p) /\ ~(x = p) ==> abs x < p`) THEN
4131   SUBGOAL_THEN `~(z = ii) /\ ~(z = --ii)` STRIP_ASSUME_TAC THENL
4132    [CONJ_TAC THEN
4133     DISCH_THEN(fun th -> POP_ASSUM MP_TAC THEN SUBST1_TAC th) THEN
4134     REWRITE_TAC[RE_II; IM_II; RE_NEG; IM_NEG] THEN REAL_ARITH_TAC;
4135     ALL_TAC] THEN
4136   REWRITE_TAC[GSYM complex_div] THEN CONJ_TAC THENL
4137    [SUBGOAL_THEN `~((Cx(&1) - ii * z) / (Cx(&1) + ii * z) = Cx(&0))`
4138      (fun th -> MESON_TAC[th; CLOG_WORKS]) THEN
4139     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC COMPLEX_FIELD;
4140     ALL_TAC] THEN
4141   DISCH_TAC THEN
4142   MP_TAC(ISPEC `clog((Cx(&1) - ii * z) / (Cx(&1) + ii * z))` EULER) THEN
4143   ASM_REWRITE_TAC[SIN_PI; COS_PI; CX_NEG] THEN
4144   REWRITE_TAC[COMPLEX_RING
4145    `x = y * (--Cx(&1) + z * Cx(&0)) <=> x + y = Cx(&0)`] THEN
4146   REWRITE_TAC[CX_EXP] THEN
4147   ASM_SIMP_TAC[CEXP_CLOG; COMPLEX_FIELD
4148      `~(z = ii) /\ ~(z = --ii)
4149       ==> ~((Cx(&1) - ii * z) / (Cx(&1) + ii * z) = Cx(&0))`] THEN
4150   REWRITE_TAC[GSYM CX_EXP] THEN DISCH_THEN(MP_TAC o AP_TERM `Im`) THEN
4151   REWRITE_TAC[IM_ADD; IM_CX; REAL_ADD_RID; IM_COMPLEX_DIV_LEMMA] THEN
4152   DISCH_TAC THEN UNDISCH_TAC `Re z = &0 ==> abs (Im z) < &1` THEN
4153   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
4154   SUBGOAL_THEN `ii * z = --Cx(Im z)` SUBST_ALL_TAC THENL
4155    [ASM_REWRITE_TAC[COMPLEX_EQ; RE_NEG; IM_NEG; RE_MUL_II; IM_MUL_II;
4156                     RE_CX; IM_CX; REAL_NEG_0];
4157     ALL_TAC] THEN
4158   UNDISCH_TAC
4159    `Im(clog((Cx(&1) - --Cx(Im z)) / (Cx(&1) + --Cx(Im z)))) = pi` THEN
4160   REWRITE_TAC[COMPLEX_SUB_RNEG; GSYM complex_sub] THEN
4161   REWRITE_TAC[GSYM CX_ADD; GSYM CX_SUB; GSYM CX_DIV] THEN
4162   SUBGOAL_THEN `&0 < (&1 + Im z) / (&1 - Im z)` ASSUME_TAC THENL
4163    [MATCH_MP_TAC REAL_LT_DIV THEN ASM_REAL_ARITH_TAC;
4164     ASM_SIMP_TAC[GSYM CX_LOG; IM_CX; PI_NZ]]);;
4165
4166 let HAS_COMPLEX_DERIVATIVE_CATN = prove
4167  (`!z. (Re z = &0 ==> abs(Im z) < &1)
4168        ==> (catn has_complex_derivative inv(Cx(&1) + z pow 2)) (at z)`,
4169   REPEAT STRIP_TAC THEN
4170   SUBGOAL_THEN `~(z = ii) /\ ~(z = --ii)` STRIP_ASSUME_TAC THENL
4171    [CONJ_TAC THEN
4172     DISCH_THEN(fun th -> POP_ASSUM MP_TAC THEN SUBST1_TAC th) THEN
4173     REWRITE_TAC[RE_II; IM_II; RE_NEG; IM_NEG] THEN REAL_ARITH_TAC;
4174     ALL_TAC] THEN
4175   GEN_REWRITE_TAC (RATOR_CONV o LAND_CONV) [GSYM ETA_AX] THEN
4176   REWRITE_TAC[catn] THEN COMPLEX_DIFF_TAC THEN
4177   REWRITE_TAC[RE_SUB; RE_ADD; IM_SUB; IM_ADD;
4178               RE_CX; RE_MUL_II; IM_CX; IM_MUL_II] THEN
4179   REWRITE_TAC[GSYM CONJ_ASSOC] THEN CONJ_TAC THENL
4180    [ASM_REWRITE_TAC[IM_COMPLEX_DIV_LEMMA; RE_COMPLEX_DIV_LEMMA] THEN
4181     SIMP_TAC[complex_norm] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
4182     ASM_REWRITE_TAC[REAL_ADD_LID; POW_2_SQRT_ABS];
4183     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC COMPLEX_FIELD]);;
4184
4185 let COMPLEX_DIFFERENTIABLE_AT_CATN = prove
4186  (`!z. (Re z = &0 ==> abs(Im z) < &1) ==> catn complex_differentiable at z`,
4187   REWRITE_TAC[complex_differentiable] THEN
4188   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CATN]);;
4189
4190 let COMPLEX_DIFFERENTIABLE_WITHIN_CATN = prove
4191  (`!s z. (Re z = &0 ==> abs(Im z) < &1)
4192          ==> catn complex_differentiable (at z within s)`,
4193   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
4194             COMPLEX_DIFFERENTIABLE_AT_CATN]);;
4195
4196 add_complex_differentiation_theorems
4197  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
4198    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
4199              HAS_COMPLEX_DERIVATIVE_CATN)));;
4200
4201 let CONTINUOUS_AT_CATN = prove
4202  (`!z. (Re z = &0 ==> abs(Im z) < &1) ==> catn continuous at z`,
4203   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CATN;
4204             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
4205
4206 let CONTINUOUS_WITHIN_CATN = prove
4207  (`!s z. (Re z = &0 ==> abs(Im z) < &1) ==> catn continuous (at z within s)`,
4208   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CATN]);;
4209
4210 let CONTINUOUS_ON_CATN = prove
4211  (`!s. (!z. z IN s /\ Re z = &0 ==> abs(Im z) < &1) ==> catn continuous_on s`,
4212   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CATN]);;
4213
4214 let HOLOMORPHIC_ON_CATN = prove
4215  (`!s. (!z. z IN s /\ Re z = &0 ==> abs(Im z) < &1) ==> catn holomorphic_on s`,
4216   REWRITE_TAC [holomorphic_on] THEN
4217   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CATN]);;
4218
4219 (* ------------------------------------------------------------------------- *)
4220 (* Real arctangent.                                                          *)
4221 (* ------------------------------------------------------------------------- *)
4222
4223 let atn = new_definition
4224  `atn(x) = Re(catn(Cx x))`;;
4225
4226 let CX_ATN = prove
4227  (`!x. Cx(atn x) = catn(Cx x)`,
4228   GEN_TAC THEN REWRITE_TAC[atn; catn; GSYM REAL; real] THEN
4229   REWRITE_TAC[complex_div; IM_MUL_II; GSYM CX_INV; GSYM COMPLEX_MUL_ASSOC] THEN
4230   REWRITE_TAC[RE_MUL_CX; REAL_ARITH `inv(&2) * x = &0 <=> x = &0`] THEN
4231   MATCH_MP_TAC NORM_CEXP_IMAGINARY THEN
4232   SUBGOAL_THEN `~(Cx(&1) - ii * Cx(x) = Cx(&0)) /\
4233                 ~(Cx(&1) + ii * Cx(x) = Cx(&0))`
4234   STRIP_ASSUME_TAC THENL
4235    [CONJ_TAC THEN DISCH_THEN(MP_TAC o AP_TERM `Re`) THEN
4236     REWRITE_TAC[RE_ADD; RE_SUB; RE_MUL_II; IM_CX; RE_CX] THEN
4237     CONV_TAC REAL_RAT_REDUCE_CONV;
4238     ALL_TAC] THEN
4239   ASM_SIMP_TAC[CEXP_SUB; CEXP_CLOG; COMPLEX_FIELD
4240    `~(a = Cx(&0)) /\ ~(b = Cx(&0)) ==> ~(a * inv b = Cx(&0))`] THEN
4241   REWRITE_TAC[GSYM complex_div; COMPLEX_NORM_DIV] THEN
4242   MATCH_MP_TAC(REAL_FIELD `~(b = &0) /\ a = b ==> a / b = &1`) THEN
4243   ASM_REWRITE_TAC[COMPLEX_NORM_ZERO] THEN
4244   MATCH_MP_TAC(MESON[COMPLEX_NORM_CNJ] `cnj a = b ==> norm a = norm b`) THEN
4245   REWRITE_TAC[CNJ_SUB; CNJ_MUL; CNJ_MUL; CNJ_II; CNJ_CX] THEN
4246   CONV_TAC COMPLEX_RING);;
4247
4248 let ATN_TAN = prove
4249  (`!y. tan(atn y) = y`,
4250   GEN_TAC THEN REWRITE_TAC[tan_def; atn] THEN
4251   MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `Re(ctan(catn(Cx y)))` THEN
4252   CONJ_TAC THENL [REWRITE_TAC[GSYM CX_ATN; RE_CX]; ALL_TAC] THEN
4253   GEN_REWRITE_TAC RAND_CONV [GSYM RE_CX] THEN AP_TERM_TAC THEN
4254   MATCH_MP_TAC CTAN_CATN THEN MATCH_MP_TAC(COMPLEX_RING
4255    `~(z = ii) /\ ~(z = --ii) ==> ~(z pow 2 = --Cx(&1))`) THEN
4256   CONJ_TAC THEN DISCH_THEN(MP_TAC o AP_TERM `Im`) THEN
4257   REWRITE_TAC[IM_II; IM_CX; IM_NEG] THEN REAL_ARITH_TAC);;
4258
4259 let ATN_BOUND = prove
4260  (`!y. abs(atn y) < pi / &2`,
4261   GEN_TAC THEN REWRITE_TAC[atn] THEN MATCH_MP_TAC RE_CATN_BOUNDS THEN
4262   REWRITE_TAC[IM_CX] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
4263
4264 let ATN_BOUNDS = prove
4265  (`!y. --(pi / &2) < atn(y) /\ atn(y) < (pi / &2)`,
4266   MP_TAC ATN_BOUND THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
4267
4268 let TAN_ATN = prove
4269  (`!x. --(pi / &2) < x /\ x < pi / &2 ==> atn(tan(x)) = x`,
4270   REPEAT STRIP_TAC THEN REWRITE_TAC[tan_def; atn] THEN
4271   MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `Re(catn(ctan(Cx x)))` THEN
4272   CONJ_TAC THENL [REWRITE_TAC[GSYM CX_TAN; RE_CX]; ALL_TAC] THEN
4273   GEN_REWRITE_TAC RAND_CONV [GSYM RE_CX] THEN AP_TERM_TAC THEN
4274   MATCH_MP_TAC CATN_CTAN THEN REWRITE_TAC[RE_CX] THEN
4275   ASM_REAL_ARITH_TAC);;
4276
4277 let ATN_0 = prove
4278  (`atn(&0) = &0`,
4279   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [SYM TAN_0] THEN
4280   MATCH_MP_TAC TAN_ATN THEN MP_TAC PI_POS THEN REAL_ARITH_TAC);;
4281
4282 let ATN_1 = prove
4283  (`atn(&1) = pi / &4`,
4284   MP_TAC(AP_TERM `atn` TAN_PI4) THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
4285   MATCH_MP_TAC TAN_ATN THEN MP_TAC PI_POS THEN REAL_ARITH_TAC);;
4286
4287 let ATN_NEG = prove
4288  (`!x. atn(--x) = --(atn x)`,
4289   GEN_TAC THEN MP_TAC(SPEC `atn(x)` TAN_NEG) THEN REWRITE_TAC[ATN_TAN] THEN
4290   DISCH_THEN(SUBST1_TAC o SYM) THEN MATCH_MP_TAC TAN_ATN THEN
4291   MP_TAC(SPEC `x:real` ATN_BOUNDS) THEN REAL_ARITH_TAC);;
4292
4293 let ATN_MONO_LT = prove
4294  (`!x y. x < y ==> atn(x) < atn(y)`,
4295   REPEAT GEN_TAC THEN
4296   GEN_REWRITE_TAC (LAND_CONV o BINOP_CONV) [GSYM ATN_TAN] THEN
4297   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[REAL_NOT_LT] THEN
4298   SIMP_TAC[TAN_MONO_LE; ATN_BOUNDS]);;
4299
4300 let ATN_MONO_LT_EQ = prove
4301  (`!x y. atn(x) < atn(y) <=> x < y`,
4302   MESON_TAC[REAL_NOT_LE; REAL_LE_LT; ATN_MONO_LT]);;
4303
4304 let ATN_MONO_LE_EQ = prove
4305  (`!x y. atn(x) <= atn(y) <=> x <= y`,
4306   REWRITE_TAC[GSYM REAL_NOT_LT; ATN_MONO_LT_EQ]);;
4307
4308 let ATN_INJ = prove
4309  (`!x y. (atn x = atn y) <=> (x = y)`,
4310   REWRITE_TAC[GSYM REAL_LE_ANTISYM; ATN_MONO_LE_EQ]);;
4311
4312 let ATN_POS_LT = prove
4313  (`&0 < atn(x) <=> &0 < x`,
4314   MESON_TAC[ATN_0; ATN_MONO_LT_EQ]);;
4315
4316 let ATN_POS_LE = prove
4317  (`&0 <= atn(x) <=> &0 <= x`,
4318   MESON_TAC[ATN_0; ATN_MONO_LE_EQ]);;
4319
4320 let ATN_LT_PI4_POS = prove
4321  (`!x. x < &1 ==> atn(x) < pi / &4`,
4322   SIMP_TAC[GSYM ATN_1; ATN_MONO_LT]);;
4323
4324 let ATN_LT_PI4_NEG = prove
4325  (`!x. --(&1) < x ==> --(pi / &4) < atn(x)`,
4326   SIMP_TAC[GSYM ATN_1; GSYM ATN_NEG; ATN_MONO_LT]);;
4327
4328 let ATN_LT_PI4 = prove
4329  (`!x. abs(x) < &1 ==> abs(atn x) < pi / &4`,
4330   GEN_TAC THEN
4331   MATCH_MP_TAC(REAL_ARITH
4332    `(&0 < x ==> &0 < y) /\
4333     (x < &0 ==> y < &0) /\
4334     ((x = &0) ==> (y = &0)) /\
4335     (x < a ==> y < b) /\
4336     (--a < x ==> --b < y)
4337     ==> abs(x) < a ==> abs(y) < b`) THEN
4338   SIMP_TAC[ATN_LT_PI4_POS; ATN_LT_PI4_NEG; ATN_0] THEN CONJ_TAC THEN
4339   GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [GSYM ATN_0] THEN
4340   SIMP_TAC[ATN_MONO_LT]);;
4341
4342 let ATN_LE_PI4 = prove
4343  (`!x. abs(x) <= &1 ==> abs(atn x) <= pi / &4`,
4344   REWRITE_TAC[REAL_LE_LT] THEN REPEAT STRIP_TAC THEN
4345   ASM_SIMP_TAC[ATN_LT_PI4] THEN DISJ2_TAC THEN
4346   FIRST_ASSUM(DISJ_CASES_THEN SUBST1_TAC o MATCH_MP
4347     (REAL_ARITH `(abs(x) = a) ==> (x = a) \/ (x = --a)`)) THEN
4348   ASM_REWRITE_TAC[ATN_1; ATN_NEG] THEN
4349   REWRITE_TAC[REAL_ABS_DIV; REAL_ABS_NUM; REAL_ABS_NEG] THEN
4350   SIMP_TAC[real_abs; REAL_LT_IMP_LE; PI_POS]);;
4351
4352 let COS_ATN_NZ = prove
4353  (`!x. ~(cos(atn(x)) = &0)`,
4354   GEN_TAC THEN MATCH_MP_TAC REAL_LT_IMP_NZ THEN
4355   MATCH_MP_TAC COS_POS_PI THEN REWRITE_TAC[ATN_BOUNDS]);;
4356
4357 let TAN_SEC = prove
4358  (`!x. ~(cos(x) = &0) ==> (&1 + (tan(x) pow 2) = inv(cos x) pow 2)`,
4359   MP_TAC SIN_CIRCLE THEN MATCH_MP_TAC MONO_FORALL THEN REWRITE_TAC[tan] THEN
4360   CONV_TAC REAL_FIELD);;
4361
4362 let COS_ATN = prove
4363  (`!x. cos(atn x) = &1 / sqrt(&1 + x pow 2)`,
4364   SIMP_TAC[COS_TAN; ATN_BOUND; ATN_TAN]);;
4365
4366 let SIN_ATN = prove
4367  (`!x. sin(atn x) = x / sqrt(&1 + x pow 2)`,
4368   SIMP_TAC[SIN_TAN; ATN_BOUND; ATN_TAN]);;
4369
4370 let ATN_ABS = prove
4371  (`!x. atn(abs x) = abs(atn x)`,
4372   GEN_TAC THEN REWRITE_TAC[real_abs; ATN_POS_LE] THEN
4373   COND_CASES_TAC THEN ASM_REWRITE_TAC[ATN_NEG]);;
4374
4375 let ATN_ADD = prove
4376  (`!x y. abs(atn x + atn y) < pi / &2
4377          ==> atn(x) + atn(y) = atn((x + y) / (&1 - x * y))`,
4378   REPEAT STRIP_TAC THEN
4379   TRANS_TAC EQ_TRANS `atn((tan(atn x) + tan(atn y)) /
4380                           (&1 - tan(atn x) * tan(atn y)))` THEN
4381   CONJ_TAC THENL [ALL_TAC; REWRITE_TAC[ATN_TAN]] THEN
4382   W(MP_TAC o PART_MATCH (rand o rand) TAN_ADD o rand o rand o snd) THEN
4383   ANTS_TAC THENL
4384    [REWRITE_TAC[COS_ATN_NZ] THEN MATCH_MP_TAC REAL_LT_IMP_NZ THEN
4385     MATCH_MP_TAC COS_POS_PI THEN ASM_REAL_ARITH_TAC;
4386     DISCH_THEN(SUBST1_TAC o SYM) THEN CONV_TAC SYM_CONV THEN
4387     MATCH_MP_TAC TAN_ATN THEN ASM_REAL_ARITH_TAC]);;
4388
4389 let ATN_INV = prove
4390  (`!x. &0 < x ==> atn(inv x) = pi / &2 - atn x`,
4391   REPEAT STRIP_TAC THEN TRANS_TAC EQ_TRANS `atn(inv(tan(atn x)))` THEN
4392   CONJ_TAC THENL [REWRITE_TAC[ATN_TAN]; REWRITE_TAC[GSYM TAN_COT]] THEN
4393   MATCH_MP_TAC TAN_ATN THEN REWRITE_TAC[ATN_BOUNDS; REAL_ARITH
4394    `--(p / &2) < p / &2 - x /\ p / &2 - x < p / &2 <=> &0 < x /\ x < p`] THEN
4395   ASM_REWRITE_TAC[ATN_POS_LT] THEN MP_TAC(SPEC `x:real` ATN_BOUNDS) THEN
4396   ASM_REAL_ARITH_TAC);;
4397
4398 let ATN_ADD_SMALL = prove
4399  (`!x y. abs(x * y) < &1
4400          ==> (atn(x) + atn(y) = atn((x + y) / (&1 - x * y)))`,
4401   REPEAT STRIP_TAC THEN
4402   MAP_EVERY ASM_CASES_TAC [`x = &0`; `y = &0`] THEN
4403   ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_SUB_RZERO;
4404                   REAL_DIV_1; REAL_ADD_LID; REAL_ADD_RID; ATN_0] THEN
4405   MATCH_MP_TAC ATN_ADD THEN MATCH_MP_TAC(REAL_ARITH
4406    `abs(x) < p - abs(y) \/ abs(y) < p - abs(x) ==> abs(x + y) < p`) THEN
4407   REWRITE_TAC[GSYM ATN_ABS] THEN
4408   ASM_SIMP_TAC[GSYM ATN_INV; REAL_ARITH `~(x = &0) ==> &0 < abs x`;
4409         ATN_MONO_LT_EQ; REAL_ARITH `inv x = &1 / x`; REAL_LT_RDIV_EQ] THEN
4410   ASM_REAL_ARITH_TAC);;
4411
4412 (* ------------------------------------------------------------------------- *)
4413 (* Machin-like formulas for pi.                                              *)
4414 (* ------------------------------------------------------------------------- *)
4415
4416 let [MACHIN; MACHIN_EULER; MACHIN_GAUSS] = (CONJUNCTS o prove)
4417  (`(&4 * atn(&1 / &5) - atn(&1 / &239) = pi / &4) /\
4418    (&5 * atn(&1 / &7) + &2 * atn(&3 / &79) = pi / &4) /\
4419    (&12 * atn(&1 / &18) + &8 * atn(&1 / &57) - &5 * atn(&1 / &239) = pi / &4)`,
4420   REPEAT CONJ_TAC THEN CONV_TAC(ONCE_DEPTH_CONV(fun tm ->
4421     if is_binop `( * ):real->real->real` tm
4422     then LAND_CONV(RAND_CONV(TOP_DEPTH_CONV num_CONV)) tm
4423     else failwith "")) THEN
4424   REWRITE_TAC[real_sub; GSYM REAL_MUL_RNEG; GSYM ATN_NEG] THEN
4425   REWRITE_TAC[GSYM REAL_OF_NUM_SUC; REAL_ADD_RDISTRIB] THEN
4426   REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID; REAL_ADD_LID] THEN
4427   CONV_TAC(DEPTH_CONV (fun tm ->
4428     let th1 = PART_MATCH (lhand o rand) ATN_ADD_SMALL tm in
4429     let th2 = MP th1 (EQT_ELIM(REAL_RAT_REDUCE_CONV(lhand(concl th1)))) in
4430     CONV_RULE(RAND_CONV(RAND_CONV REAL_RAT_REDUCE_CONV)) th2)) THEN
4431   REWRITE_TAC[ATN_1]);;
4432
4433 (* ------------------------------------------------------------------------- *)
4434 (* Some bound theorems where a bit of simple calculus is handy.              *)
4435 (* ------------------------------------------------------------------------- *)
4436
4437 let ATN_ABS_LE_X = prove
4438  (`!x. abs(atn x) <= abs x`,
4439   REPEAT STRIP_TAC THEN
4440   MP_TAC(ISPECL [`catn`; `\z. inv(Cx(&1) + z pow 2)`; `real`; `&1`]
4441       COMPLEX_MVT) THEN
4442   REWRITE_TAC[CONVEX_REAL; IN] THEN ANTS_TAC THENL
4443    [CONJ_TAC THENL
4444      [REWRITE_TAC[real] THEN REPEAT STRIP_TAC THEN
4445       MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_AT_WITHIN THEN
4446       MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_CATN THEN
4447       ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
4448       GEN_TAC THEN REWRITE_TAC[REAL] THEN
4449       DISCH_THEN(SUBST1_TAC o SYM) THEN
4450       REWRITE_TAC[GSYM CX_POW; GSYM CX_ADD; GSYM CX_INV; COMPLEX_NORM_CX] THEN
4451       REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_INV_LE_1 THEN
4452       MP_TAC(SPEC `Re z` REAL_LE_SQUARE) THEN REAL_ARITH_TAC];
4453     DISCH_THEN(MP_TAC o SPECL [`Cx(&0)`; `Cx(x)`]) THEN
4454     REWRITE_TAC[GSYM CX_ATN; COMPLEX_SUB_RZERO; REAL_CX; ATN_0] THEN
4455     REWRITE_TAC[COMPLEX_NORM_CX; REAL_MUL_LID]]);;
4456
4457 let ATN_LE_X = prove
4458  (`!x. &0 <= x ==> atn(x) <= x`,
4459   MP_TAC ATN_ABS_LE_X THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
4460
4461 let TAN_ABS_GE_X = prove
4462  (`!x. abs(x) < pi / &2 ==> abs(x) <= abs(tan x)`,
4463   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN
4464   EXISTS_TAC `abs(atn(tan x))` THEN REWRITE_TAC[ATN_ABS_LE_X] THEN
4465   MATCH_MP_TAC REAL_EQ_IMP_LE THEN AP_TERM_TAC THEN
4466   CONV_TAC SYM_CONV THEN MATCH_MP_TAC TAN_ATN THEN
4467   POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
4468
4469 (* ------------------------------------------------------------------------- *)
4470 (* Probably not very useful, but for compatibility with old analysis theory. *)
4471 (* ------------------------------------------------------------------------- *)
4472
4473 let TAN_TOTAL = prove
4474  (`!y. ?!x. --(pi / &2) < x /\ x < (pi / &2) /\ tan(x) = y`,
4475   MESON_TAC[TAN_ATN; ATN_TAN; ATN_BOUNDS]);;
4476
4477 let TAN_TOTAL_POS = prove
4478  (`!y. &0 <= y ==> ?x. &0 <= x /\ x < pi / &2 /\ tan(x) = y`,
4479   MESON_TAC[ATN_TAN; ATN_BOUNDS; ATN_POS_LE]);;
4480
4481 let TAN_TOTAL_LEMMA = prove
4482  (`!y. &0 < y ==> ?x. &0 < x /\ x < pi / &2 /\ y < tan(x)`,
4483   REPEAT STRIP_TAC THEN EXISTS_TAC `atn(y + &1)` THEN
4484   REWRITE_TAC[ATN_TAN; ATN_BOUNDS; ATN_POS_LT] THEN
4485   POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
4486
4487 (* ------------------------------------------------------------------------- *)
4488 (* Some slightly ad hoc lemmas useful here.                                  *)
4489 (* ------------------------------------------------------------------------- *)
4490
4491 let RE_POW_2 = prove
4492  (`Re(z pow 2) = Re(z) pow 2 - Im(z) pow 2`,
4493   REWRITE_TAC[COMPLEX_POW_2; complex_mul; RE] THEN REAL_ARITH_TAC);;
4494
4495 let IM_POW_2 = prove
4496  (`Im(z pow 2) = &2 * Re(z) * Im(z)`,
4497   REWRITE_TAC[COMPLEX_POW_2; complex_mul; IM] THEN REAL_ARITH_TAC);;
4498
4499 let ABS_SQUARE_LT_1 = prove
4500  (`!x. x pow 2 < &1 <=> abs(x) < &1`,
4501   ONCE_REWRITE_TAC[GSYM REAL_ABS_NUM] THEN
4502   REWRITE_TAC[REAL_LT_SQUARE_ABS] THEN REAL_ARITH_TAC);;
4503
4504 let ABS_SQUARE_LE_1 = prove
4505  (`!x. x pow 2 <= &1 <=> abs(x) <= &1`,
4506   ONCE_REWRITE_TAC[GSYM REAL_ABS_NUM] THEN
4507   REWRITE_TAC[REAL_LT_SQUARE_ABS; GSYM REAL_NOT_LT] THEN REAL_ARITH_TAC);;
4508
4509 let ABS_SQUARE_EQ_1 = prove
4510  (`!x. x pow 2 = &1 <=> abs(x) = &1`,
4511   REWRITE_TAC[REAL_RING `x pow 2 = &1 <=> x = &1 \/ x = -- &1`] THEN
4512   REAL_ARITH_TAC);;
4513
4514 (* ------------------------------------------------------------------------- *)
4515 (* Inverse sine.                                                             *)
4516 (* ------------------------------------------------------------------------- *)
4517
4518 let casn = new_definition
4519  `casn z = --ii * clog(ii * z + csqrt(Cx(&1) - z pow 2))`;;
4520
4521 let CASN_BODY_LEMMA = prove
4522  (`!z. ~(ii * z + csqrt(Cx(&1) - z pow 2) = Cx(&0))`,
4523   GEN_TAC THEN MP_TAC(SPEC `Cx(&1) - z pow 2` CSQRT) THEN
4524   CONV_TAC COMPLEX_FIELD);;
4525
4526 let CSIN_CASN = prove
4527  (`!z. csin(casn z) = z`,
4528   GEN_TAC THEN REWRITE_TAC[csin; casn; COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG] THEN
4529   REWRITE_TAC[COMPLEX_MUL_ASSOC; COMPLEX_NEG_NEG] THEN
4530   REWRITE_TAC[COMPLEX_POW_II_2; GSYM COMPLEX_POW_2] THEN
4531   REWRITE_TAC[COMPLEX_NEG_NEG; COMPLEX_MUL_LNEG; COMPLEX_MUL_LID] THEN
4532   REWRITE_TAC[CEXP_NEG] THEN
4533   ASM_SIMP_TAC[CASN_BODY_LEMMA; CEXP_CLOG; COMPLEX_FIELD
4534      `~(z = Cx(&0))
4535       ==> ((z - inv z) / (Cx(&2) * ii) = c <=>
4536            z pow 2 - Cx(&1) = Cx(&2) * ii * c * z)`] THEN
4537   MP_TAC(SPEC `Cx(&1) - z pow 2` CSQRT) THEN CONV_TAC COMPLEX_FIELD);;
4538
4539 let CASN_CSIN = prove
4540  (`!z. abs(Re z) < pi / &2 \/ (abs(Re z) = pi / &2 /\ Im z = &0)
4541        ==> casn(csin z) = z`,
4542   GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
4543   REWRITE_TAC[csin; casn; COMPLEX_MUL_LNEG; CEXP_NEG] THEN
4544   SIMP_TAC[CEXP_NZ; COMPLEX_FIELD
4545     `~(z = Cx(&0))
4546      ==> Cx(&1) - ((z - inv z) / (Cx(&2) * ii)) pow 2 =
4547          ((z + inv z) / Cx(&2)) pow 2`] THEN
4548   SUBGOAL_THEN
4549    `csqrt(((cexp(ii * z) + inv(cexp(ii * z))) / Cx(&2)) pow 2) =
4550     (cexp(ii * z) + inv(cexp(ii * z))) / Cx(&2)`
4551   SUBST1_TAC THENL
4552    [MATCH_MP_TAC POW_2_CSQRT THEN REWRITE_TAC[GSYM CEXP_NEG] THEN
4553     REWRITE_TAC[complex_div; GSYM CX_INV; RE_MUL_CX; IM_MUL_CX] THEN
4554     REWRITE_TAC[REAL_ARITH
4555      `&0 < r * inv(&2) \/ r * inv(&2) = &0 /\ &0 <= i * inv(&2) <=>
4556       &0 < r \/ r = &0 /\ &0 <= i`] THEN
4557     REWRITE_TAC[RE_ADD; IM_ADD; RE_CEXP; IM_CEXP] THEN
4558     REWRITE_TAC[RE_MUL_II; RE_NEG; IM_MUL_II; IM_NEG] THEN
4559     REWRITE_TAC[SIN_NEG; COS_NEG; REAL_NEG_NEG] THEN
4560     REWRITE_TAC[REAL_MUL_RNEG; GSYM real_sub] THEN
4561     REWRITE_TAC[GSYM REAL_ADD_RDISTRIB; GSYM REAL_SUB_RDISTRIB] THEN
4562     FIRST_X_ASSUM(DISJ_CASES_THEN STRIP_ASSUME_TAC) THENL
4563      [DISJ1_TAC THEN MATCH_MP_TAC REAL_LT_MUL THEN
4564       ASM_SIMP_TAC[REAL_LT_ADD; REAL_EXP_POS_LT] THEN
4565       MATCH_MP_TAC COS_POS_PI THEN POP_ASSUM MP_TAC THEN REAL_ARITH_TAC;
4566       DISJ2_TAC THEN ASM_REWRITE_TAC[SIN_PI2; COS_PI2] THEN
4567       REWRITE_TAC[REAL_EXP_NEG; REAL_EXP_0; REAL_INV_1; REAL_SUB_REFL] THEN
4568       REWRITE_TAC[REAL_MUL_LZERO; REAL_LE_REFL; REAL_ENTIRE] THEN
4569       FIRST_X_ASSUM(DISJ_CASES_THEN SUBST1_TAC o MATCH_MP (REAL_ARITH
4570        `abs(x) = p ==> x = p \/ x = --p`)) THEN
4571       REWRITE_TAC[COS_PI2; COS_NEG] THEN REAL_ARITH_TAC];
4572     ALL_TAC] THEN
4573   SIMP_TAC[COMPLEX_FIELD
4574    `ii * (a - b) / (Cx(&2) * ii) + (a + b) / Cx(&2) = a`] THEN
4575   SIMP_TAC[COMPLEX_FIELD `--(ii * w) = z <=> w = ii * z`] THEN
4576   MATCH_MP_TAC CLOG_CEXP THEN REWRITE_TAC[IM_MUL_II] THEN
4577   MP_TAC PI_POS THEN POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
4578
4579 let CASN_UNIQUE = prove
4580  (`!w z. csin(z) = w /\
4581          (abs(Re z) < pi / &2 \/ (abs(Re z) = pi / &2 /\ Im z = &0))
4582          ==> casn w = z`,
4583   MESON_TAC[CASN_CSIN]);;
4584
4585 let CASN_0 = prove
4586  (`casn(Cx(&0)) = Cx(&0)`,
4587   REWRITE_TAC[casn; COMPLEX_MUL_RZERO; COMPLEX_ADD_LID; COMPLEX_POW_2;
4588               COMPLEX_SUB_RZERO; CSQRT_1; CLOG_1; COMPLEX_MUL_RZERO]);;
4589
4590 let CASN_1 = prove
4591  (`casn(Cx(&1)) = Cx(pi / &2)`,
4592   REWRITE_TAC[casn; GSYM CX_POW; GSYM CX_SUB] THEN
4593   CONV_TAC REAL_RAT_REDUCE_CONV THEN
4594   REWRITE_TAC[CSQRT_0; COMPLEX_MUL_RID; COMPLEX_ADD_RID] THEN
4595   REWRITE_TAC[CLOG_II] THEN CONV_TAC COMPLEX_RING);;
4596
4597 let CASN_NEG_1 = prove
4598  (`casn(--Cx(&1)) = --Cx(pi / &2)`,
4599   REWRITE_TAC[casn; GSYM CX_NEG; GSYM CX_POW; GSYM CX_SUB] THEN
4600   CONV_TAC REAL_RAT_REDUCE_CONV THEN
4601   REWRITE_TAC[CSQRT_0; COMPLEX_MUL_RID; COMPLEX_ADD_RID] THEN
4602   REWRITE_TAC[CX_NEG; COMPLEX_MUL_RID; COMPLEX_MUL_RNEG] THEN
4603   REWRITE_TAC[CLOG_NEG_II] THEN CONV_TAC COMPLEX_RING);;
4604
4605 let HAS_COMPLEX_DERIVATIVE_CASN = prove
4606  (`!z. (Im z = &0 ==> abs(Re z) < &1)
4607        ==> (casn has_complex_derivative inv(ccos(casn z))) (at z)`,
4608   REPEAT STRIP_TAC THEN
4609   MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_INVERSE_BASIC THEN
4610   EXISTS_TAC `csin` THEN
4611   REWRITE_TAC[CSIN_CASN; HAS_COMPLEX_DERIVATIVE_CSIN; CONTINUOUS_AT_CSIN] THEN
4612   EXISTS_TAC `ball(z:complex,&1)` THEN
4613   REWRITE_TAC[OPEN_BALL; CENTRE_IN_BALL; REAL_LT_01] THEN CONJ_TAC THENL
4614    [DISCH_THEN(MP_TAC o MATCH_MP (COMPLEX_RING
4615      `ccos z = Cx(&0) ==> csin(z) pow 2 + ccos(z) pow 2 = Cx(&1)
4616                           ==> csin(z) pow 2 = Cx(&1)`)) THEN
4617     REWRITE_TAC[CSIN_CASN; CSIN_CIRCLE] THEN
4618     REWRITE_TAC[COMPLEX_RING
4619      `z pow 2 = Cx(&1) <=> z = Cx(&1) \/ z = --Cx(&1)`] THEN
4620     DISCH_THEN(DISJ_CASES_THEN SUBST_ALL_TAC) THEN
4621     POP_ASSUM MP_TAC THEN REWRITE_TAC[RE_CX; IM_CX; RE_NEG; IM_NEG] THEN
4622     REAL_ARITH_TAC;
4623     ALL_TAC] THEN
4624   GEN_REWRITE_TAC LAND_CONV [GSYM ETA_AX] THEN REWRITE_TAC[casn] THEN
4625   MATCH_MP_TAC CONTINUOUS_COMPLEX_MUL THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
4626   ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
4627   CONJ_TAC THENL
4628    [MATCH_MP_TAC CONTINUOUS_ADD THEN
4629     SIMP_TAC[CONTINUOUS_COMPLEX_MUL; CONTINUOUS_CONST; CONTINUOUS_AT_ID] THEN
4630     ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
4631     SIMP_TAC[CONTINUOUS_COMPLEX_POW; CONTINUOUS_SUB;
4632              CONTINUOUS_CONST; CONTINUOUS_AT_ID] THEN
4633     MATCH_MP_TAC CONTINUOUS_AT_CSQRT THEN
4634     REWRITE_TAC[RE_SUB; IM_SUB; RE_CX; IM_CX; RE_POW_2; IM_POW_2] THEN
4635     REWRITE_TAC[REAL_RING `&0 - &2 * x * y = &0 <=> x = &0 \/ y = &0`] THEN
4636     STRIP_TAC THEN
4637     ASM_REWRITE_TAC[REAL_POW_2; REAL_MUL_LZERO; REAL_SUB_RZERO;
4638                     REAL_ARITH `&1 - (&0 - x) = &1 + x`] THEN
4639     ASM_SIMP_TAC[REAL_LE_SQUARE; REAL_ARITH `&0 <= x ==> &0 < &1 + x`] THEN
4640     REWRITE_TAC[REAL_ARITH `&0 < &1 - x * x <=> x pow 2 < &1 pow 2`] THEN
4641     ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN MATCH_MP_TAC REAL_POW_LT2 THEN
4642     ASM_SIMP_TAC[REAL_ABS_POS; REAL_ABS_NUM; ARITH];
4643     ALL_TAC] THEN
4644   MATCH_MP_TAC CONTINUOUS_AT_CLOG THEN
4645   REWRITE_TAC[IM_ADD; IM_MUL_II; RE_ADD; RE_MUL_II] THEN
4646   ASM_CASES_TAC `Im z = &0` THENL
4647    [DISCH_THEN(K ALL_TAC) THEN ASM_REWRITE_TAC[csqrt] THEN
4648     ASM_REWRITE_TAC[IM_SUB; RE_SUB; IM_CX; RE_CX; IM_POW_2; RE_POW_2;
4649                     REAL_MUL_RZERO; REAL_SUB_REFL] THEN
4650     CONV_TAC REAL_RAT_REDUCE_CONV THEN
4651     REWRITE_TAC[REAL_ARITH `&0 <= &1 - (z pow 2 - &0) <=> z pow 2 <= &1 pow 2`;
4652                 GSYM REAL_LE_SQUARE_ABS] THEN
4653     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_ABS_NUM; RE; REAL_ADD_LID] THEN
4654     MATCH_MP_TAC SQRT_POS_LT THEN
4655     REWRITE_TAC[REAL_ARITH `&0 < &1 - (z pow 2 - &0) <=> z pow 2 < &1 pow 2`;
4656                 GSYM REAL_LT_SQUARE_ABS] THEN
4657     ASM_REAL_ARITH_TAC;
4658     ALL_TAC] THEN
4659   REWRITE_TAC[csqrt; IM_SUB; RE_SUB; IM_CX; RE_CX; IM_POW_2; RE_POW_2] THEN
4660   REWRITE_TAC[REAL_RING `&0 - &2 * x * y = &0 <=> x = &0 \/ y = &0`] THEN
4661   ASM_CASES_TAC `Re z = &0` THEN ASM_REWRITE_TAC[RE; IM] THENL
4662    [CONV_TAC REAL_RAT_REDUCE_CONV THEN
4663     REWRITE_TAC[REAL_ARITH `&1 - (&0 - x) = &1 + x`] THEN
4664     SIMP_TAC[REAL_POW_2; REAL_LE_ADD; REAL_LE_SQUARE; REAL_POS] THEN
4665     REWRITE_TAC[RE; IM; REAL_ADD_LID; REAL_ARITH `&0 < --x + y <=> x < y`] THEN
4666     MATCH_MP_TAC REAL_LT_RSQRT THEN REAL_ARITH_TAC;
4667     ALL_TAC] THEN
4668   DISCH_TAC THEN REWRITE_TAC[REAL_ARITH `&0 < --x + y <=> x < y`] THEN
4669   MATCH_MP_TAC REAL_LT_RSQRT THEN
4670   REWRITE_TAC[REAL_POW_2; REAL_ARITH
4671    `a < (n + &1 - (b - a)) / &2 <=> (a + b) - &1 < n`] THEN
4672   REWRITE_TAC[complex_norm] THEN MATCH_MP_TAC REAL_LT_RSQRT THEN
4673   REWRITE_TAC[RE_SUB; IM_SUB; RE_CX; IM_CX; RE_POW_2; IM_POW_2] THEN
4674   REPEAT(FIRST_X_ASSUM(MP_TAC o
4675     GEN_REWRITE_RULE I [GSYM REAL_LT_SQUARE])) THEN
4676   REAL_ARITH_TAC);;
4677
4678 let COMPLEX_DIFFERENTIABLE_AT_CASN = prove
4679  (`!z. (Im z = &0 ==> abs(Re z) < &1) ==> casn complex_differentiable at z`,
4680   REWRITE_TAC[complex_differentiable] THEN
4681   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CASN]);;
4682
4683 let COMPLEX_DIFFERENTIABLE_WITHIN_CASN = prove
4684  (`!s z. (Im z = &0 ==> abs(Re z) < &1)
4685          ==> casn complex_differentiable (at z within s)`,
4686   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
4687             COMPLEX_DIFFERENTIABLE_AT_CASN]);;
4688
4689 add_complex_differentiation_theorems
4690  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
4691    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
4692              HAS_COMPLEX_DERIVATIVE_CASN)));;
4693
4694 let CONTINUOUS_AT_CASN = prove
4695  (`!z. (Im z = &0 ==> abs(Re z) < &1) ==> casn continuous at z`,
4696   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CASN;
4697             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
4698
4699 let CONTINUOUS_WITHIN_CASN = prove
4700  (`!s z. (Im z = &0 ==> abs(Re z) < &1) ==> casn continuous (at z within s)`,
4701   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CASN]);;
4702
4703 let CONTINUOUS_ON_CASN = prove
4704  (`!s. (!z. z IN s /\ Im z = &0 ==> abs(Re z) < &1) ==> casn continuous_on s`,
4705   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CASN]);;
4706
4707 let HOLOMORPHIC_ON_CASN = prove
4708  (`!s. (!z. z IN s /\ Im z = &0 ==> abs(Re z) < &1) ==> casn holomorphic_on s`,
4709   REWRITE_TAC [holomorphic_on] THEN
4710   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CASN]);;
4711
4712 (* ------------------------------------------------------------------------- *)
4713 (* Inverse cosine.                                                           *)
4714 (* ------------------------------------------------------------------------- *)
4715
4716 let cacs = new_definition
4717  `cacs z = --ii * clog(z + ii * csqrt(Cx(&1) - z pow 2))`;;
4718
4719 let CACS_BODY_LEMMA = prove
4720  (`!z. ~(z + ii * csqrt(Cx(&1) - z pow 2) = Cx(&0))`,
4721   GEN_TAC THEN MP_TAC(SPEC `Cx(&1) - z pow 2` CSQRT) THEN
4722   CONV_TAC COMPLEX_FIELD);;
4723
4724 let CCOS_CACS = prove
4725  (`!z. ccos(cacs z) = z`,
4726   GEN_TAC THEN REWRITE_TAC[ccos; cacs; COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG] THEN
4727   REWRITE_TAC[COMPLEX_MUL_ASSOC; COMPLEX_NEG_NEG] THEN
4728   REWRITE_TAC[COMPLEX_POW_II_2; GSYM COMPLEX_POW_2] THEN
4729   REWRITE_TAC[COMPLEX_NEG_NEG; COMPLEX_MUL_LNEG; COMPLEX_MUL_LID] THEN
4730   REWRITE_TAC[CEXP_NEG] THEN
4731   ASM_SIMP_TAC[CACS_BODY_LEMMA; CEXP_CLOG; COMPLEX_POW_II_2; COMPLEX_FIELD
4732      `~(z = Cx(&0))
4733       ==> ((z + inv z) / Cx(&2) = c <=>
4734            z pow 2 + Cx(&1) = Cx(&2) * c * z)`] THEN
4735   MP_TAC(SPEC `Cx(&1) - z pow 2` CSQRT) THEN CONV_TAC COMPLEX_FIELD);;
4736
4737 let CACS_CCOS = prove
4738  (`!z. &0 < Re z /\ Re z < pi \/
4739        Re(z) = &0 /\ &0 <= Im(z) \/
4740        Re(z) = pi /\ Im(z) <= &0
4741        ==> cacs(ccos z) = z`,
4742   GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
4743   REWRITE_TAC[ccos; cacs; COMPLEX_MUL_LNEG; CEXP_NEG] THEN
4744   SIMP_TAC[CEXP_NZ; COMPLEX_FIELD
4745     `~(z = Cx(&0))
4746      ==> Cx(&1) - ((z + inv z) / Cx(&2)) pow 2 =
4747          --(((z - inv z) / Cx(&2)) pow 2)`] THEN
4748   SUBGOAL_THEN
4749    `csqrt(--(((cexp(ii * z) - inv(cexp(ii * z))) / Cx(&2)) pow 2)) =
4750     --ii * (cexp(ii * z) - inv(cexp(ii * z))) / Cx(&2)`
4751   SUBST1_TAC THENL
4752    [SIMP_TAC[COMPLEX_FIELD `--(x pow 2) = (--ii * x) pow 2`] THEN
4753     MATCH_MP_TAC POW_2_CSQRT THEN REWRITE_TAC[GSYM CEXP_NEG] THEN
4754     REWRITE_TAC[complex_div; GSYM CX_INV; RE_MUL_CX; IM_MUL_CX; RE_NEG; IM_NEG;
4755                 COMPLEX_MUL_LNEG; RE_MUL_II; IM_MUL_II; RE_SUB; IM_SUB] THEN
4756     REWRITE_TAC[REAL_NEG_NEG; REAL_NEG_EQ_0] THEN
4757     REWRITE_TAC[REAL_ARITH
4758      `&0 < r * inv(&2) \/ r * inv(&2) = &0 /\ &0 <= --(i * inv(&2)) <=>
4759       &0 < r \/ r = &0 /\ &0 <= --i`] THEN
4760     REWRITE_TAC[RE_ADD; IM_ADD; RE_CEXP; IM_CEXP] THEN
4761     REWRITE_TAC[RE_MUL_II; RE_NEG; IM_MUL_II; IM_NEG] THEN
4762     REWRITE_TAC[SIN_NEG; COS_NEG; REAL_NEG_NEG] THEN
4763     REWRITE_TAC[REAL_MUL_RNEG; GSYM real_sub; REAL_SUB_RNEG; REAL_NEG_SUB] THEN
4764     REWRITE_TAC[GSYM REAL_ADD_RDISTRIB; GSYM REAL_SUB_RDISTRIB] THEN
4765     ASM_SIMP_TAC[REAL_LT_ADD; REAL_EXP_POS_LT; REAL_LT_MUL_EQ] THEN
4766     POP_ASSUM(REPEAT_TCL DISJ_CASES_THEN STRIP_ASSUME_TAC) THEN
4767     ASM_SIMP_TAC[SIN_POS_PI] THEN DISJ2_TAC THEN
4768     REWRITE_TAC[SIN_PI; REAL_MUL_RZERO; COS_PI; SIN_0; COS_0] THEN
4769     REWRITE_TAC[REAL_MUL_RID; REAL_MUL_RNEG] THEN
4770     REWRITE_TAC[REAL_NEG_SUB; REAL_SUB_LE; REAL_EXP_MONO_LE] THEN
4771     ASM_REAL_ARITH_TAC;
4772     ALL_TAC] THEN
4773   SIMP_TAC[COMPLEX_FIELD
4774    `(e + e') / Cx(&2) + ii * --ii * (e - e') / Cx(&2) = e`] THEN
4775   SIMP_TAC[COMPLEX_FIELD `--(ii * w) = z <=> w = ii * z`] THEN
4776   MATCH_MP_TAC CLOG_CEXP THEN REWRITE_TAC[IM_MUL_II] THEN
4777   MP_TAC PI_POS THEN ASM_REAL_ARITH_TAC);;
4778
4779 let CACS_UNIQUE = prove
4780  (`!w z.
4781        ccos z = w /\
4782        (&0 < Re z /\ Re z < pi \/
4783         Re(z) = &0 /\ &0 <= Im(z) \/
4784         Re(z) = pi /\ Im(z) <= &0)
4785        ==> cacs(w) = z`,
4786   MESON_TAC[CACS_CCOS]);;
4787
4788 let CACS_0 = prove
4789  (`cacs(Cx(&0)) = Cx(pi / &2)`,
4790   MATCH_MP_TAC CACS_UNIQUE THEN
4791   REWRITE_TAC[RE_CX; IM_CX; GSYM CX_COS; COS_PI2] THEN
4792   MP_TAC PI_POS THEN REAL_ARITH_TAC);;
4793
4794 let CACS_1 = prove
4795  (`cacs(Cx(&1)) = Cx(&0)`,
4796   MATCH_MP_TAC CACS_UNIQUE THEN
4797   REWRITE_TAC[RE_CX; IM_CX; GSYM CX_COS; COS_0; REAL_LE_REFL]);;
4798
4799 let CACS_NEG_1 = prove
4800  (`cacs(--Cx(&1)) = Cx pi`,
4801   MATCH_MP_TAC CACS_UNIQUE THEN
4802   REWRITE_TAC[RE_CX; IM_CX; GSYM CX_COS; COS_PI; CX_NEG; REAL_LE_REFL]);;
4803
4804 let HAS_COMPLEX_DERIVATIVE_CACS = prove
4805  (`!z. (Im z = &0 ==> abs(Re z) < &1)
4806        ==> (cacs has_complex_derivative --inv(csin(cacs z))) (at z)`,
4807   REPEAT STRIP_TAC THEN REWRITE_TAC[COMPLEX_NEG_INV] THEN
4808   MATCH_MP_TAC HAS_COMPLEX_DERIVATIVE_INVERSE_BASIC THEN
4809   EXISTS_TAC `ccos` THEN
4810   REWRITE_TAC[CCOS_CACS; HAS_COMPLEX_DERIVATIVE_CCOS; CONTINUOUS_AT_CCOS] THEN
4811   EXISTS_TAC `ball(z:complex,&1)` THEN
4812   REWRITE_TAC[OPEN_BALL; CENTRE_IN_BALL; REAL_LT_01] THEN CONJ_TAC THENL
4813    [DISCH_THEN(MP_TAC o MATCH_MP (COMPLEX_RING
4814      `--(csin z) = Cx(&0) ==> csin(z) pow 2 + ccos(z) pow 2 = Cx(&1)
4815                               ==> ccos(z) pow 2 = Cx(&1)`)) THEN
4816     REWRITE_TAC[CCOS_CACS; CSIN_CIRCLE] THEN
4817     REWRITE_TAC[COMPLEX_RING
4818      `z pow 2 = Cx(&1) <=> z = Cx(&1) \/ z = --Cx(&1)`] THEN
4819     DISCH_THEN(DISJ_CASES_THEN SUBST_ALL_TAC) THEN
4820     POP_ASSUM MP_TAC THEN REWRITE_TAC[RE_CX; IM_CX; RE_NEG; IM_NEG] THEN
4821     REAL_ARITH_TAC;
4822     ALL_TAC] THEN
4823   GEN_REWRITE_TAC LAND_CONV [GSYM ETA_AX] THEN REWRITE_TAC[cacs] THEN
4824   MATCH_MP_TAC CONTINUOUS_COMPLEX_MUL THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
4825   ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
4826   CONJ_TAC THENL
4827    [MATCH_MP_TAC CONTINUOUS_ADD THEN REWRITE_TAC[CONTINUOUS_AT_ID] THEN
4828     MATCH_MP_TAC CONTINUOUS_COMPLEX_MUL THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
4829     ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
4830     SIMP_TAC[CONTINUOUS_COMPLEX_POW; CONTINUOUS_SUB;
4831              CONTINUOUS_CONST; CONTINUOUS_AT_ID] THEN
4832     MATCH_MP_TAC CONTINUOUS_AT_CSQRT THEN
4833     REWRITE_TAC[RE_SUB; IM_SUB; RE_CX; IM_CX; RE_POW_2; IM_POW_2] THEN
4834     REWRITE_TAC[REAL_RING `&0 - &2 * x * y = &0 <=> x = &0 \/ y = &0`] THEN
4835     STRIP_TAC THEN
4836     ASM_REWRITE_TAC[REAL_POW_2; REAL_MUL_LZERO; REAL_SUB_RZERO;
4837                     REAL_ARITH `&1 - (&0 - x) = &1 + x`] THEN
4838     ASM_SIMP_TAC[REAL_LE_SQUARE; REAL_ARITH `&0 <= x ==> &0 < &1 + x`] THEN
4839     REWRITE_TAC[REAL_ARITH `&0 < &1 - x * x <=> x pow 2 < &1 pow 2`] THEN
4840     ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN MATCH_MP_TAC REAL_POW_LT2 THEN
4841     ASM_SIMP_TAC[REAL_ABS_POS; REAL_ABS_NUM; ARITH];
4842     ALL_TAC] THEN
4843   MATCH_MP_TAC CONTINUOUS_AT_CLOG THEN
4844   REWRITE_TAC[IM_ADD; IM_MUL_II; RE_ADD; RE_MUL_II] THEN
4845   ASM_CASES_TAC `Im z = &0` THENL
4846    [ASM_REWRITE_TAC[csqrt] THEN
4847     ASM_REWRITE_TAC[IM_SUB; RE_SUB; IM_CX; RE_CX; IM_POW_2; RE_POW_2;
4848                     REAL_MUL_RZERO; REAL_SUB_REFL] THEN
4849     CONV_TAC REAL_RAT_REDUCE_CONV THEN
4850     REWRITE_TAC[REAL_ARITH `&0 <= &1 - (z pow 2 - &0) <=> z pow 2 <= &1 pow 2`;
4851                 GSYM REAL_LE_SQUARE_ABS] THEN
4852     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_ABS_NUM; RE; REAL_ADD_LID] THEN
4853     REWRITE_TAC[GSYM real_sub; IM; REAL_SUB_LT; REAL_SUB_RZERO] THEN
4854     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> x = &0 ==> &0 < y`) THEN
4855     MATCH_MP_TAC SQRT_POS_LT THEN
4856     ASM_SIMP_TAC[REAL_SUB_LT; ABS_SQUARE_LT_1];
4857     ALL_TAC] THEN
4858   REWRITE_TAC[csqrt; IM_SUB; RE_SUB; IM_CX; RE_CX; IM_POW_2; RE_POW_2] THEN
4859   REWRITE_TAC[REAL_RING `&0 - &2 * x * y = &0 <=> x = &0 \/ y = &0`] THEN
4860   ASM_CASES_TAC `Re z = &0` THEN ASM_REWRITE_TAC[RE; IM] THENL
4861    [CONV_TAC REAL_RAT_REDUCE_CONV THEN
4862     REWRITE_TAC[REAL_ARITH `&1 - (&0 - x) = &1 + x`] THEN
4863     SIMP_TAC[REAL_POW_2; REAL_LE_ADD; REAL_LE_SQUARE; REAL_POS] THEN
4864     REWRITE_TAC[RE; IM; REAL_ADD_LID] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
4865     DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH `a + b = &0 ==> a = --b`)) THEN
4866     DISCH_THEN(MP_TAC o AP_TERM `\x:real. x pow 2`) THEN
4867     SIMP_TAC[SQRT_POW_2; REAL_POW_NEG; ARITH; REAL_LE_SQUARE; REAL_LE_ADD;
4868              REAL_POS] THEN
4869     REAL_ARITH_TAC;
4870     ALL_TAC] THEN
4871   DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH `a + b = &0 ==> a = --b`)) THEN
4872   DISCH_THEN(MP_TAC o AP_TERM `\x:real. x pow 2`) THEN
4873   SUBGOAL_THEN `&0 < (norm(Cx (&1) - z pow 2) +
4874                       &1 - (Re z pow 2 - Im z pow 2)) / &2`
4875   ASSUME_TAC THENL
4876    [REWRITE_TAC[REAL_ARITH `&0 < (x + y - z) / &2 <=> z - y < x`] THEN
4877     REWRITE_TAC[complex_norm] THEN MATCH_MP_TAC REAL_LT_RSQRT THEN
4878     REWRITE_TAC[RE_SUB; IM_SUB; RE_CX; IM_CX; RE_POW_2; IM_POW_2] THEN
4879     REPEAT(FIRST_X_ASSUM(MP_TAC o
4880      GEN_REWRITE_RULE I [GSYM REAL_LT_SQUARE])) THEN
4881     REWRITE_TAC[IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP REAL_LT_MUL) THEN
4882     REAL_ARITH_TAC;
4883     ALL_TAC] THEN
4884   ASM_SIMP_TAC[SQRT_POW_2; REAL_POW_NEG; ARITH; REAL_LT_IMP_LE] THEN
4885   REWRITE_TAC[REAL_POW_2; REAL_ARITH
4886    `a = (n + &1 - (b - a)) / &2 <=> (a + b) - &1 = n`] THEN
4887   REWRITE_TAC[complex_norm] THEN
4888   DISCH_THEN(MP_TAC o AP_TERM `\x:real. x pow 2`) THEN
4889   SIMP_TAC[SQRT_POW_2; REWRITE_RULE[GSYM REAL_POW_2] REAL_LE_SQUARE;
4890            REAL_LE_ADD] THEN
4891   REWRITE_TAC[RE_SUB; RE_CX; RE_POW_2; IM_SUB; IM_CX; IM_POW_2] THEN
4892   REPEAT(FIRST_X_ASSUM(MP_TAC o
4893    GEN_REWRITE_RULE I [GSYM REAL_LT_SQUARE])) THEN
4894   REAL_ARITH_TAC);;
4895
4896 let COMPLEX_DIFFERENTIABLE_AT_CACS = prove
4897  (`!z. (Im z = &0 ==> abs(Re z) < &1) ==> cacs complex_differentiable at z`,
4898   REWRITE_TAC[complex_differentiable] THEN
4899   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CACS]);;
4900
4901 let COMPLEX_DIFFERENTIABLE_WITHIN_CACS = prove
4902  (`!s z. (Im z = &0 ==> abs(Re z) < &1)
4903          ==> cacs complex_differentiable (at z within s)`,
4904   MESON_TAC[COMPLEX_DIFFERENTIABLE_AT_WITHIN;
4905             COMPLEX_DIFFERENTIABLE_AT_CACS]);;
4906
4907 add_complex_differentiation_theorems
4908  (CONJUNCTS(REWRITE_RULE[FORALL_AND_THM]
4909    (MATCH_MP HAS_COMPLEX_DERIVATIVE_CHAIN
4910              HAS_COMPLEX_DERIVATIVE_CACS)));;
4911
4912 let CONTINUOUS_AT_CACS = prove
4913  (`!z. (Im z = &0 ==> abs(Re z) < &1) ==> cacs continuous at z`,
4914   MESON_TAC[HAS_COMPLEX_DERIVATIVE_CACS;
4915             HAS_COMPLEX_DERIVATIVE_IMP_CONTINUOUS_AT]);;
4916
4917 let CONTINUOUS_WITHIN_CACS = prove
4918  (`!s z. (Im z = &0 ==> abs(Re z) < &1) ==> cacs continuous (at z within s)`,
4919   MESON_TAC[CONTINUOUS_AT_WITHIN; CONTINUOUS_AT_CACS]);;
4920
4921 let CONTINUOUS_ON_CACS = prove
4922  (`!s. (!z. z IN s /\ Im z = &0 ==> abs(Re z) < &1) ==> cacs continuous_on s`,
4923   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CACS]);;
4924
4925 let HOLOMORPHIC_ON_CACS = prove
4926  (`!s. (!z. z IN s /\ Im z = &0 ==> abs(Re z) < &1) ==> cacs holomorphic_on s`,
4927   REWRITE_TAC [holomorphic_on] THEN
4928   MESON_TAC [HAS_COMPLEX_DERIVATIVE_AT_WITHIN; HAS_COMPLEX_DERIVATIVE_CACS]);;
4929
4930 (* ------------------------------------------------------------------------- *)
4931 (* Some crude range theorems (could be sharpened).                           *)
4932 (* ------------------------------------------------------------------------- *)
4933
4934 let CASN_RANGE_LEMMA = prove
4935  (`!z. abs (Re z) < &1 ==> &0 < Re(ii * z + csqrt(Cx(&1) - z pow 2))`,
4936   REPEAT STRIP_TAC THEN REWRITE_TAC[RE_ADD; RE_MUL_II] THEN
4937   REWRITE_TAC[REAL_ARITH `&0 < --i + r <=> i < r`] THEN
4938   REWRITE_TAC[csqrt; IM_SUB; RE_SUB; COMPLEX_POW_2; RE_CX; IM_CX] THEN
4939   REWRITE_TAC[complex_mul; RE; IM] THEN REWRITE_TAC[GSYM complex_mul] THEN
4940   REWRITE_TAC[REAL_ARITH `r * i + i * r = &2 * r * i`] THEN
4941   REWRITE_TAC[REAL_SUB_LZERO; REAL_NEG_EQ_0; REAL_ABS_NEG] THEN
4942   REWRITE_TAC[REAL_NEG_SUB; REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH] THEN
4943   MAP_EVERY ASM_CASES_TAC [`Re z = &0`; `Im z = &0`] THEN
4944   ASM_REWRITE_TAC[REAL_SUB_LZERO; REAL_SUB_RZERO] THEN
4945   CONV_TAC REAL_RAT_REDUCE_CONV THEN
4946   REWRITE_TAC[RE; SQRT_1] THEN CONV_TAC REAL_RAT_REDUCE_CONV THENL
4947    [REWRITE_TAC[REAL_ARITH `&1 - (&0 - z) = &1 + z`] THEN
4948     SIMP_TAC[REAL_LE_ADD; REAL_POS; REAL_LE_SQUARE; RE] THEN
4949     MATCH_MP_TAC REAL_LT_RSQRT THEN REAL_ARITH_TAC;
4950     SUBGOAL_THEN `Re(z) pow 2 < &1 pow 2` MP_TAC THENL
4951      [ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN MATCH_MP_TAC REAL_POW_LT2 THEN
4952       ASM_REWRITE_TAC[REAL_ABS_POS; REAL_ABS_NUM; ARITH];
4953       REWRITE_TAC[REAL_POW_ONE] THEN STRIP_TAC] THEN
4954     COND_CASES_TAC THEN ASM_REWRITE_TAC[RE] THEN
4955     TRY(MATCH_MP_TAC SQRT_POS_LT) THEN ASM_REAL_ARITH_TAC;
4956     MATCH_MP_TAC REAL_LT_RSQRT THEN
4957     REWRITE_TAC[REAL_POW_2; REAL_ARITH
4958      `a < (n + &1 - (b - a)) / &2 <=> (a + b) - &1 < n`] THEN
4959     REWRITE_TAC[complex_norm] THEN MATCH_MP_TAC REAL_LT_RSQRT THEN
4960     REWRITE_TAC[RE_SUB; IM_SUB; RE_CX; IM_CX] THEN
4961     REWRITE_TAC[complex_mul; RE; IM] THEN
4962     REPEAT(FIRST_X_ASSUM(MP_TAC o
4963       GEN_REWRITE_RULE I [GSYM REAL_LT_SQUARE])) THEN
4964     REAL_ARITH_TAC]);;
4965
4966 let CACS_RANGE_LEMMA = prove
4967  (`!z. abs(Re z) < &1 ==> &0 < Im(z + ii * csqrt(Cx(&1) - z pow 2))`,
4968   REPEAT STRIP_TAC THEN MP_TAC(SPEC `--z:complex` CASN_RANGE_LEMMA) THEN
4969   ASM_SIMP_TAC[IM_NEG; RE_NEG; IM_ADD; RE_ADD; IM_MUL_II; RE_MUL_II;
4970                COMPLEX_POW_NEG; ARITH; REAL_ABS_NEG] THEN
4971   REAL_ARITH_TAC);;
4972
4973 let RE_CASN = prove
4974  (`!z. Re(casn z) = Im(clog(ii * z + csqrt(Cx(&1) - z pow 2)))`,
4975   REWRITE_TAC[casn; COMPLEX_MUL_LNEG; RE_NEG; RE_MUL_II; REAL_NEGNEG]);;
4976
4977 let RE_CACS = prove
4978  (`!z. Re(cacs z) = Im(clog(z + ii * csqrt(Cx(&1) - z pow 2)))`,
4979   REWRITE_TAC[cacs; COMPLEX_MUL_LNEG; RE_NEG; RE_MUL_II; REAL_NEGNEG]);;
4980
4981 let CASN_BOUNDS = prove
4982  (`!z. abs(Re z) < &1 ==> abs(Re(casn z)) < pi / &2`,
4983   GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[RE_CASN] THEN
4984   MATCH_MP_TAC RE_CLOG_POS_LT_IMP THEN ASM_SIMP_TAC[CASN_RANGE_LEMMA]);;
4985
4986 let CACS_BOUNDS = prove
4987  (`!z. abs(Re z) < &1 ==> &0 < Re(cacs z) /\ Re(cacs z) < pi`,
4988   GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[RE_CACS] THEN
4989   MATCH_MP_TAC IM_CLOG_POS_LT_IMP THEN ASM_SIMP_TAC[CACS_RANGE_LEMMA]);;
4990
4991 let RE_CACS_BOUNDS = prove
4992  (`!z. --pi < Re(cacs z) /\ Re(cacs z) <= pi`,
4993   REWRITE_TAC[RE_CACS] THEN SIMP_TAC[CLOG_WORKS; CACS_BODY_LEMMA]);;
4994
4995 let RE_CACS_BOUND = prove
4996  (`!z. abs(Re(cacs z)) <= pi`,
4997   MP_TAC RE_CACS_BOUNDS THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
4998
4999 let RE_CASN_BOUNDS = prove
5000  (`!z. --pi < Re(casn z) /\ Re(casn z) <= pi`,
5001   REWRITE_TAC[RE_CASN] THEN SIMP_TAC[CLOG_WORKS; CASN_BODY_LEMMA]);;
5002
5003 let RE_CASN_BOUND = prove
5004  (`!z. abs(Re(casn z)) <= pi`,
5005   MP_TAC RE_CASN_BOUNDS THEN MATCH_MP_TAC MONO_FORALL THEN REAL_ARITH_TAC);;
5006
5007 (* ------------------------------------------------------------------------- *)
5008 (* Interrelations between the two functions.                                 *)
5009 (* ------------------------------------------------------------------------- *)
5010
5011 let CCOS_CASN_NZ = prove
5012  (`!z. ~(z pow 2 = Cx(&1)) ==> ~(ccos(casn z) = Cx(&0))`,
5013   REWRITE_TAC[ccos; casn; CEXP_NEG; COMPLEX_RING `ii * --ii * z = z`;
5014               COMPLEX_RING `--ii * --ii * z = --z`] THEN
5015   SIMP_TAC[CEXP_CLOG; CASN_BODY_LEMMA;
5016            COMPLEX_FIELD `~(x = Cx(&0))
5017                           ==> ((x + inv(x)) / Cx(&2) = Cx(&0) <=>
5018                                 x pow 2 = --Cx(&1))`] THEN
5019   SIMP_TAC[CSQRT; COMPLEX_FIELD
5020               `s pow 2 = Cx(&1) - z pow 2
5021                ==> ((ii * z + s) pow 2 = --Cx(&1) <=>
5022                     ii * s * z = Cx(&1) - z pow 2)`] THEN
5023   GEN_TAC THEN STRIP_TAC THEN
5024   MATCH_MP_TAC(COMPLEX_RING
5025    `~(x pow 2 + y pow 2 = Cx(&0)) ==> ~(ii * x = y)`) THEN
5026   REPEAT(POP_ASSUM MP_TAC) THEN
5027   MP_TAC(SPEC `Cx(&1) - z pow 2` CSQRT) THEN CONV_TAC COMPLEX_RING);;
5028
5029 let CSIN_CACS_NZ = prove
5030  (`!z. ~(z pow 2 = Cx(&1)) ==> ~(csin(cacs z) = Cx(&0))`,
5031   REWRITE_TAC[csin; cacs; CEXP_NEG; COMPLEX_RING `ii * --ii * z = z`;
5032               COMPLEX_RING `--ii * --ii * z = --z`] THEN
5033   SIMP_TAC[CEXP_CLOG; CACS_BODY_LEMMA;
5034            COMPLEX_FIELD `~(x = Cx(&0))
5035                           ==> ((x - inv(x)) / (Cx(&2) * ii) = Cx(&0) <=>
5036                                 x pow 2 = Cx(&1))`] THEN
5037   SIMP_TAC[CSQRT; COMPLEX_FIELD
5038               `s pow 2 = Cx(&1) - z pow 2
5039                ==> ((z + ii * s) pow 2 = Cx(&1) <=>
5040                     ii * s * z = Cx(&1) - z pow 2)`] THEN
5041   GEN_TAC THEN STRIP_TAC THEN
5042   MATCH_MP_TAC(COMPLEX_RING
5043    `~(x pow 2 + y pow 2 = Cx(&0)) ==> ~(ii * x = y)`) THEN
5044   REPEAT(POP_ASSUM MP_TAC) THEN
5045   MP_TAC(SPEC `Cx(&1) - z pow 2` CSQRT) THEN CONV_TAC COMPLEX_RING);;
5046
5047 let CCOS_CSIN_CSQRT = prove
5048  (`!z. &0 < cos(Re z) \/ cos(Re z) = &0 /\ Im(z) * sin(Re z) <= &0
5049        ==> ccos(z) = csqrt(Cx(&1) - csin(z) pow 2)`,
5050   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC CSQRT_UNIQUE THEN
5051   REWRITE_TAC[COMPLEX_EQ_SUB_LADD] THEN ONCE_REWRITE_TAC[COMPLEX_ADD_SYM] THEN
5052   REWRITE_TAC[CSIN_CIRCLE] THEN REWRITE_TAC[RE_CCOS; IM_CCOS] THEN
5053   ASM_SIMP_TAC[REAL_LT_MUL_EQ; REAL_HALF; REAL_LT_ADD; REAL_EXP_POS_LT] THEN
5054   DISJ2_TAC THEN REWRITE_TAC[REAL_MUL_RZERO] THEN
5055   FIRST_ASSUM(MP_TAC o MATCH_MP(REAL_ARITH
5056    `x * y <= &0 ==> &0 <= --x * y`)) THEN
5057   REWRITE_TAC[REAL_MUL_POS_LE] THEN
5058   SIMP_TAC[REAL_ARITH `x / &2 = &0 <=> x = &0`; REAL_LT_RDIV_EQ; REAL_ADD_LID;
5059            REAL_SUB_LT; REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH; REAL_MUL_LZERO;
5060            REAL_SUB_0; REAL_EXP_MONO_LT; REAL_LT_SUB_RADD; REAL_EXP_INJ] THEN
5061   REAL_ARITH_TAC);;
5062
5063 let CSIN_CCOS_CSQRT = prove
5064  (`!z. &0 < sin(Re z) \/ sin(Re z) = &0 /\ &0 <= Im(z) * cos(Re z)
5065        ==> csin(z) = csqrt(Cx(&1) - ccos(z) pow 2)`,
5066   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC CSQRT_UNIQUE THEN
5067   REWRITE_TAC[COMPLEX_EQ_SUB_LADD] THEN ONCE_REWRITE_TAC[COMPLEX_ADD_SYM] THEN
5068   REWRITE_TAC[ONCE_REWRITE_RULE[COMPLEX_ADD_SYM] CSIN_CIRCLE] THEN
5069   REWRITE_TAC[RE_CSIN; IM_CSIN] THEN
5070   ASM_SIMP_TAC[REAL_LT_MUL_EQ; REAL_HALF; REAL_LT_ADD; REAL_EXP_POS_LT] THEN
5071   DISJ2_TAC THEN REWRITE_TAC[REAL_MUL_RZERO] THEN
5072   REPEAT(POP_ASSUM MP_TAC) THEN
5073   REWRITE_TAC[REAL_MUL_POS_LE] THEN
5074   SIMP_TAC[REAL_ARITH `x / &2 = &0 <=> x = &0`; REAL_LT_RDIV_EQ; REAL_ADD_LID;
5075            REAL_SUB_LT; REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH; REAL_MUL_LZERO;
5076
5077            REAL_SUB_0; REAL_EXP_MONO_LT; REAL_LT_SUB_RADD; REAL_EXP_INJ] THEN
5078   REAL_ARITH_TAC);;
5079
5080 let CASN_CACS_SQRT_POS = prove
5081  (`!z. (&0 < Re z \/ Re z = &0 /\ &0 <= Im z)
5082        ==> casn(z) = cacs(csqrt(Cx(&1) - z pow 2))`,
5083   GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[casn; cacs] THEN
5084   AP_TERM_TAC THEN AP_TERM_TAC THEN
5085   MATCH_MP_TAC(COMPLEX_RING `w = z ==> ii * z + s = s + ii * w`) THEN
5086   MATCH_MP_TAC CSQRT_UNIQUE THEN
5087   ASM_REWRITE_TAC[CSQRT] THEN CONV_TAC COMPLEX_RING);;
5088
5089 let CACS_CASN_SQRT_POS = prove
5090  (`!z. (&0 < Re z \/ Re z = &0 /\ &0 <= Im z)
5091        ==> cacs(z) = casn(csqrt(Cx(&1) - z pow 2))`,
5092   GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[casn; cacs] THEN
5093   AP_TERM_TAC THEN AP_TERM_TAC THEN
5094   MATCH_MP_TAC(COMPLEX_RING `w = z ==> z + ii * s = ii * s + w`) THEN
5095   MATCH_MP_TAC CSQRT_UNIQUE THEN
5096   ASM_REWRITE_TAC[CSQRT] THEN CONV_TAC COMPLEX_RING);;
5097
5098 let CSIN_CACS = prove
5099  (`!z. &0 < Re z \/ Re(z) = &0 /\ &0 <= Im z
5100        ==> csin(cacs z) = csqrt(Cx(&1) - z pow 2)`,
5101   GEN_TAC THEN DISCH_TAC THEN
5102   GEN_REWRITE_TAC RAND_CONV [GSYM CSIN_CASN] THEN
5103   AP_TERM_TAC THEN MATCH_MP_TAC CACS_CASN_SQRT_POS THEN
5104   ASM_REWRITE_TAC[]);;
5105
5106 let CCOS_CASN = prove
5107  (`!z. &0 < Re z \/ Re(z) = &0 /\ &0 <= Im z
5108        ==> ccos(casn z) = csqrt(Cx(&1) - z pow 2)`,
5109   GEN_TAC THEN DISCH_TAC THEN
5110   GEN_REWRITE_TAC RAND_CONV [GSYM CCOS_CACS] THEN
5111   AP_TERM_TAC THEN MATCH_MP_TAC CASN_CACS_SQRT_POS THEN
5112   ASM_REWRITE_TAC[]);;
5113
5114 (* ------------------------------------------------------------------------- *)
5115 (* Real arcsin.                                                              *)
5116 (* ------------------------------------------------------------------------- *)
5117
5118 let asn = new_definition `asn(x) = Re(casn(Cx x))`;;
5119
5120 let REAL_ASN = prove
5121  (`!z. real z /\ abs(Re z) <= &1 ==> real(casn z)`,
5122   GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
5123   GEN_REWRITE_TAC LAND_CONV [REAL] THEN
5124   DISCH_THEN(SUBST1_TAC o SYM) THEN SPEC_TAC(`Re z`,`x:real`) THEN
5125   REWRITE_TAC[real; casn; COMPLEX_MUL_LNEG; IM_NEG; IM_MUL_II] THEN
5126   GEN_TAC THEN REWRITE_TAC[RE_CX; REAL_NEG_EQ_0] THEN DISCH_TAC THEN
5127   MATCH_MP_TAC NORM_CEXP_IMAGINARY THEN
5128   SIMP_TAC[CEXP_CLOG; CASN_BODY_LEMMA; NORM_EQ_SQUARE] THEN
5129   REWRITE_TAC[DOT_SQUARE_NORM; COMPLEX_SQNORM] THEN
5130   REWRITE_TAC[RE_ADD; IM_ADD; RE_MUL_II; IM_MUL_II; RE_CX; IM_CX] THEN
5131   ASM_SIMP_TAC[GSYM CX_POW; GSYM CX_SUB; GSYM CX_SQRT; REAL_SUB_LE;
5132                ABS_SQUARE_LE_1; RE_CX; IM_CX; REAL_NEG_0; REAL_ADD_LID;
5133                SQRT_POW_2] THEN
5134   REAL_ARITH_TAC);;
5135
5136 let CX_ASN = prove
5137  (`!x. abs(x) <= &1 ==> Cx(asn x) = casn(Cx x)`,
5138   REWRITE_TAC[asn] THEN MESON_TAC[REAL; RE_CX; REAL_CX; REAL_ASN]);;
5139
5140 let SIN_ASN = prove
5141  (`!y. --(&1) <= y /\ y <= &1 ==> sin(asn(y)) = y`,
5142   REWRITE_TAC[REAL_ARITH `--(&1) <= y /\ y <= &1 <=> abs(y) <= &1`] THEN
5143   ONCE_REWRITE_TAC[GSYM CX_INJ] THEN SIMP_TAC[CX_ASN; CX_SIN; CSIN_CASN]);;
5144
5145 let ASN_SIN = prove
5146  (`!x. --(pi / &2) <= x /\ x <= pi / &2 ==> asn(sin(x)) = x`,
5147   ONCE_REWRITE_TAC[GSYM CX_INJ] THEN SIMP_TAC[CX_ASN; SIN_BOUND; CX_SIN] THEN
5148   REPEAT STRIP_TAC THEN MATCH_MP_TAC CASN_CSIN THEN
5149   REWRITE_TAC[IM_CX; RE_CX] THEN REPEAT(POP_ASSUM MP_TAC) THEN
5150   REAL_ARITH_TAC);;
5151
5152 let ASN_BOUNDS_LT = prove
5153  (`!y. --(&1) < y /\ y < &1 ==> --(pi / &2) < asn(y) /\ asn(y) < pi / &2`,
5154   GEN_TAC THEN REWRITE_TAC[asn] THEN
5155   MP_TAC(SPEC `Cx y` CASN_BOUNDS) THEN
5156   REWRITE_TAC[RE_CX] THEN REAL_ARITH_TAC);;
5157
5158 let ASN_0 = prove
5159  (`asn(&0) = &0`,
5160   REWRITE_TAC[asn; CASN_0; RE_CX]);;
5161
5162 let ASN_1 = prove
5163  (`asn(&1) = pi / &2`,
5164   REWRITE_TAC[asn; CASN_1; RE_CX]);;
5165
5166 let ASN_NEG_1 = prove
5167  (`asn(-- &1) = --(pi / &2)`,
5168   REWRITE_TAC[asn; CX_NEG; CASN_NEG_1; RE_CX; RE_NEG]);;
5169
5170 let ASN_BOUNDS = prove
5171  (`!y. --(&1) <= y /\ y <= &1 ==> --(pi / &2) <= asn(y) /\ asn(y) <= pi / &2`,
5172   REWRITE_TAC[REAL_LE_LT] THEN REPEAT STRIP_TAC THEN
5173   MAP_EVERY MP_TAC [ASN_1; ASN_NEG_1; SPEC `y:real` ASN_BOUNDS_LT] THEN
5174   ASM_REWRITE_TAC[] THEN REPEAT(POP_ASSUM MP_TAC) THEN
5175   MP_TAC PI_POS THEN REAL_ARITH_TAC);;
5176
5177 let ASN_BOUNDS_PI2 = prove
5178  (`!x. &0 <= x /\ x <= &1 ==> &0 <= asn x /\ asn x <= pi / &2`,
5179   REPEAT STRIP_TAC THEN
5180   MP_TAC(ISPECL [`&0`; `asn x`] SIN_MONO_LE_EQ) THEN
5181   ASM_SIMP_TAC[SIN_0; SIN_ASN; REAL_ARITH `&0 <= x ==> --(&1) <= x`] THEN
5182   MP_TAC(SPEC `x:real` ASN_BOUNDS) THEN MP_TAC PI_POS THEN
5183   ASM_REAL_ARITH_TAC);;
5184
5185 let ASN_NEG = prove
5186  (`!x. -- &1 <= x /\ x <= &1 ==> asn(--x) = --asn(x)`,
5187   GEN_TAC THEN DISCH_TAC THEN
5188   FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o RAND_CONV)
5189      [GSYM(MATCH_MP SIN_ASN th)]) THEN
5190   REWRITE_TAC[GSYM SIN_NEG] THEN MATCH_MP_TAC ASN_SIN THEN
5191   REWRITE_TAC[REAL_ARITH `--a <= --x /\ --x <= a <=> --a <= x /\ x <= a`] THEN
5192   ASM_SIMP_TAC[ASN_BOUNDS]);;
5193
5194 let COS_ASN_NZ = prove
5195  (`!x. --(&1) < x /\ x < &1 ==> ~(cos(asn(x)) = &0)`,
5196   ONCE_REWRITE_TAC[GSYM CX_INJ] THEN SIMP_TAC[CX_ASN; CX_COS;
5197     REAL_ARITH `--(&1) < x /\ x < &1 ==> abs(x) <= &1`] THEN
5198   GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC CCOS_CASN_NZ THEN
5199   SIMP_TAC[COMPLEX_RING `x pow 2 = Cx(&1) <=> x = Cx(&1) \/ x = --Cx(&1)`] THEN
5200   REWRITE_TAC[GSYM CX_NEG; CX_INJ] THEN
5201   ASM_REAL_ARITH_TAC);;
5202
5203 let ASN_MONO_LT_EQ = prove
5204  (`!x y. abs(x) <= &1 /\ abs(y) <= &1 ==> (asn(x) < asn(y) <=> x < y)`,
5205   REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
5206   EXISTS_TAC `sin(asn(x)) < sin(asn(y))` THEN CONJ_TAC THENL
5207    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC SIN_MONO_LT_EQ THEN
5208     ONCE_REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THEN MATCH_MP_TAC ASN_BOUNDS;
5209     BINOP_TAC THEN MATCH_MP_TAC SIN_ASN] THEN
5210   ASM_REAL_ARITH_TAC);;
5211
5212 let ASN_MONO_LE_EQ = prove
5213  (`!x y. abs(x) <= &1 /\ abs(y) <= &1 ==> (asn(x) <= asn(y) <=> x <= y)`,
5214   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
5215   ASM_SIMP_TAC[ASN_MONO_LT_EQ]);;
5216
5217 let ASN_MONO_LT = prove
5218  (`!x y. --(&1) <= x /\ x < y /\ y <= &1 ==> asn(x) < asn(y)`,
5219   MP_TAC ASN_MONO_LT_EQ THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
5220   REAL_ARITH_TAC);;
5221
5222 let ASN_MONO_LE = prove
5223  (`!x y. --(&1) <= x /\ x <= y /\ y <= &1 ==> asn(x) <= asn(y)`,
5224   MP_TAC ASN_MONO_LE_EQ THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
5225   REAL_ARITH_TAC);;
5226
5227 let COS_ASN = prove
5228  (`!x. --(&1) <= x /\ x <= &1 ==> cos(asn x) = sqrt(&1 - x pow 2)`,
5229   REPEAT STRIP_TAC THEN MATCH_MP_TAC(GSYM SQRT_UNIQUE) THEN
5230   ASM_SIMP_TAC[ASN_BOUNDS; COS_POS_PI_LE; REAL_EQ_SUB_RADD] THEN
5231   ASM_MESON_TAC[SIN_ASN; SIN_CIRCLE; REAL_ADD_SYM]);;
5232
5233 (* ------------------------------------------------------------------------- *)
5234 (* Real arccosine.                                                           *)
5235 (* ------------------------------------------------------------------------- *)
5236
5237 let acs = new_definition `acs(x) = Re(cacs(Cx x))`;;
5238
5239 let REAL_ACS = prove
5240  (`!z. real z /\ abs(Re z) <= &1 ==> real(cacs z)`,
5241   GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
5242   GEN_REWRITE_TAC LAND_CONV [REAL] THEN
5243   DISCH_THEN(SUBST1_TAC o SYM) THEN SPEC_TAC(`Re z`,`x:real`) THEN
5244   REWRITE_TAC[real; cacs; COMPLEX_MUL_LNEG; IM_NEG; IM_MUL_II] THEN
5245   GEN_TAC THEN REWRITE_TAC[RE_CX; REAL_NEG_EQ_0] THEN DISCH_TAC THEN
5246   MATCH_MP_TAC NORM_CEXP_IMAGINARY THEN
5247   SIMP_TAC[CEXP_CLOG; CACS_BODY_LEMMA; NORM_EQ_SQUARE] THEN
5248   REWRITE_TAC[DOT_SQUARE_NORM; COMPLEX_SQNORM] THEN
5249   REWRITE_TAC[RE_ADD; IM_ADD; RE_MUL_II; IM_MUL_II; RE_CX; IM_CX] THEN
5250   ASM_SIMP_TAC[GSYM CX_POW; GSYM CX_SUB; GSYM CX_SQRT; REAL_SUB_LE;
5251                ABS_SQUARE_LE_1; RE_CX; IM_CX; REAL_NEG_0; REAL_ADD_LID;
5252                SQRT_POW_2] THEN
5253   REAL_ARITH_TAC);;
5254
5255 let CX_ACS = prove
5256  (`!x. abs(x) <= &1 ==> Cx(acs x) = cacs(Cx x)`,
5257   REWRITE_TAC[acs] THEN MESON_TAC[REAL; RE_CX; REAL_CX; REAL_ACS]);;
5258
5259 let COS_ACS = prove
5260  (`!y. --(&1) <= y /\ y <= &1 ==> cos(acs(y)) = y`,
5261   REWRITE_TAC[REAL_ARITH `--(&1) <= y /\ y <= &1 <=> abs(y) <= &1`] THEN
5262   ONCE_REWRITE_TAC[GSYM CX_INJ] THEN SIMP_TAC[CX_ACS; CX_COS; CCOS_CACS]);;
5263
5264 let ACS_COS = prove
5265  (`!x. &0 <= x /\ x <= pi ==> acs(cos(x)) = x`,
5266   ONCE_REWRITE_TAC[GSYM CX_INJ] THEN SIMP_TAC[CX_ACS; COS_BOUND; CX_COS] THEN
5267   REPEAT STRIP_TAC THEN MATCH_MP_TAC CACS_CCOS THEN
5268   REWRITE_TAC[IM_CX; RE_CX] THEN ASM_REAL_ARITH_TAC);;
5269
5270 let ACS_BOUNDS_LT = prove
5271  (`!y. --(&1) < y /\ y < &1 ==> &0 < acs(y) /\ acs(y) < pi`,
5272   GEN_TAC THEN REWRITE_TAC[acs] THEN
5273   MP_TAC(SPEC `Cx y` CACS_BOUNDS) THEN
5274   REWRITE_TAC[RE_CX] THEN REAL_ARITH_TAC);;
5275
5276 let ACS_0 = prove
5277  (`acs(&0) = pi / &2`,
5278   REWRITE_TAC[acs; CACS_0; RE_CX]);;
5279
5280 let ACS_1 = prove
5281  (`acs(&1) = &0`,
5282   REWRITE_TAC[acs; CACS_1; RE_CX]);;
5283
5284 let ACS_NEG_1 = prove
5285  (`acs(-- &1) = pi`,
5286   REWRITE_TAC[acs; CX_NEG; CACS_NEG_1; RE_CX; RE_NEG]);;
5287
5288 let ACS_BOUNDS = prove
5289  (`!y. --(&1) <= y /\ y <= &1 ==> &0 <= acs(y) /\ acs(y) <= pi`,
5290   REWRITE_TAC[REAL_LE_LT] THEN REPEAT STRIP_TAC THEN
5291   MAP_EVERY MP_TAC [ACS_1; ACS_NEG_1; SPEC `y:real` ACS_BOUNDS_LT] THEN
5292   ASM_REWRITE_TAC[] THEN REPEAT(POP_ASSUM MP_TAC) THEN
5293   MP_TAC PI_POS THEN REAL_ARITH_TAC);;
5294
5295 let ACS_NEG = prove
5296  (`!x. -- &1 <= x /\ x <= &1 ==> acs(--x) = pi - acs(x)`,
5297   GEN_TAC THEN DISCH_TAC THEN
5298   FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o RAND_CONV)
5299      [GSYM(MATCH_MP COS_ACS th)]) THEN
5300   ONCE_REWRITE_TAC[GSYM COS_NEG] THEN REWRITE_TAC[GSYM COS_PERIODIC_PI] THEN
5301   REWRITE_TAC[REAL_ARITH `--x + y:real = y - x`] THEN MATCH_MP_TAC ACS_COS THEN
5302   SIMP_TAC[REAL_ARITH `&0 <= p - x /\ p - x <= p <=> &0 <= x /\ x <= p`] THEN
5303   ASM_SIMP_TAC[ACS_BOUNDS]);;
5304
5305 let SIN_ACS_NZ = prove
5306  (`!x. --(&1) < x /\ x < &1 ==> ~(sin(acs(x)) = &0)`,
5307   ONCE_REWRITE_TAC[GSYM CX_INJ] THEN SIMP_TAC[CX_ACS; CX_SIN;
5308     REAL_ARITH `--(&1) < x /\ x < &1 ==> abs(x) <= &1`] THEN
5309   GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC CSIN_CACS_NZ THEN
5310   SIMP_TAC[COMPLEX_RING `x pow 2 = Cx(&1) <=> x = Cx(&1) \/ x = --Cx(&1)`] THEN
5311   REWRITE_TAC[GSYM CX_NEG; CX_INJ] THEN
5312   ASM_REAL_ARITH_TAC);;
5313
5314 let ACS_MONO_LT_EQ = prove
5315  (`!x y. abs(x) <= &1 /\ abs(y) <= &1 ==> (acs(x) < acs(y) <=> y < x)`,
5316   REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
5317   EXISTS_TAC `cos(acs(y)) < cos(acs(x))` THEN CONJ_TAC THENL
5318    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC COS_MONO_LT_EQ THEN
5319     ONCE_REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THEN MATCH_MP_TAC ACS_BOUNDS;
5320     BINOP_TAC THEN MATCH_MP_TAC COS_ACS] THEN
5321   ASM_REAL_ARITH_TAC);;
5322
5323 let ACS_MONO_LE_EQ = prove
5324  (`!x y. abs(x) <= &1 /\ abs(y) <= &1 ==> (acs(x) <= acs(y) <=> y <= x)`,
5325   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
5326   ASM_SIMP_TAC[ACS_MONO_LT_EQ]);;
5327
5328 let ACS_MONO_LT = prove
5329  (`!x y. --(&1) <= x /\ x < y /\ y <= &1 ==> acs(y) < acs(x)`,
5330   REPEAT GEN_TAC THEN
5331   MP_TAC(SPECL [`y:real`; `x:real`] ACS_MONO_LT_EQ) THEN
5332   REAL_ARITH_TAC);;
5333
5334 let ACS_MONO_LE = prove
5335  (`!x y. --(&1) <= x /\ x <= y /\ y <= &1 ==> acs(y) <= acs(x)`,
5336   REPEAT GEN_TAC THEN
5337   MP_TAC(SPECL [`y:real`; `x:real`] ACS_MONO_LE_EQ) THEN
5338   REAL_ARITH_TAC);;
5339
5340 let SIN_ACS = prove
5341  (`!x. --(&1) <= x /\ x <= &1 ==> sin(acs x) = sqrt(&1 - x pow 2)`,
5342   REPEAT STRIP_TAC THEN MATCH_MP_TAC(GSYM SQRT_UNIQUE) THEN
5343   ASM_SIMP_TAC[ACS_BOUNDS; SIN_POS_PI_LE; REAL_EQ_SUB_RADD] THEN
5344   ASM_MESON_TAC[COS_ACS; SIN_CIRCLE]);;
5345
5346 let ACS_INJ = prove
5347  (`!x y. abs(x) <= &1 /\ abs(y) <= &1 ==> (acs x = acs y <=> x = y)`,
5348   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
5349   ASM_SIMP_TAC[ACS_MONO_LE_EQ] THEN REAL_ARITH_TAC);;
5350
5351 (* ------------------------------------------------------------------------- *)
5352 (* Some interrelationships among the real inverse trig functions.            *)
5353 (* ------------------------------------------------------------------------- *)
5354
5355 let ACS_ATN = prove
5356  (`!x. -- &1 < x /\ x < &1 ==> acs(x) = pi / &2 - atn(x / sqrt(&1 - x pow 2))`,
5357   REPEAT STRIP_TAC THEN
5358   ONCE_REWRITE_TAC[REAL_ARITH `x:real = p - y <=> y - (p - x) = &0`] THEN
5359   MATCH_MP_TAC SIN_EQ_0_PI THEN
5360   ASM_SIMP_TAC[ATN_BOUND; ACS_BOUNDS; REAL_LT_IMP_LE; REAL_ARITH
5361    `abs(x) < pi / &2 /\ &0 <= y /\ y <= pi
5362     ==> --pi < x - (pi / &2 - y) /\ x - (pi / &2 - y) < pi`] THEN
5363   SUBGOAL_THEN `tan(atn(x / sqrt(&1 - x pow 2))) = tan(pi / &2 - acs x)`
5364   MP_TAC THENL
5365    [REWRITE_TAC[TAN_COT; ATN_TAN] THEN REWRITE_TAC[tan] THEN
5366     ASM_SIMP_TAC[SIN_ACS; COS_ACS; REAL_LT_IMP_LE; REAL_INV_DIV];
5367     ALL_TAC] THEN
5368   GEN_REWRITE_TAC LAND_CONV [GSYM REAL_SUB_0] THEN
5369   ASM_SIMP_TAC[SIN_ACS_NZ; GSYM SIN_COS; COS_ATN_NZ; REAL_SUB_TAN; REAL_FIELD
5370    `~(y = &0) /\ ~(z = &0) ==> (x / (y * z) = &0 <=> x = &0)`]);;
5371
5372 let ASN_PLUS_ACS = prove
5373  (`!x. -- &1 <= x /\ x <= &1 ==> asn(x) + acs(x) = pi / &2`,
5374   REPEAT STRIP_TAC THEN
5375   ONCE_REWRITE_TAC[REAL_ARITH `x + y:real = p <=> x = p - y`] THEN
5376   MATCH_MP_TAC SIN_INJ_PI THEN
5377   ASM_SIMP_TAC[SIN_PI2; COS_PI2; SIN_SUB; REAL_MUL_LZERO; REAL_SUB_RZERO] THEN
5378   ASM_SIMP_TAC[SIN_ASN; COS_ACS; REAL_MUL_LID] THEN
5379   REWRITE_TAC[REAL_ARITH `--p <= p - x <=> x <= &2 * p`;
5380               REAL_ARITH `p - x <= p <=> &0 <= x`] THEN
5381   ASM_SIMP_TAC[ASN_BOUNDS; ACS_BOUNDS; REAL_ARITH `&2 * x / &2 = x`]);;
5382
5383 let ASN_ACS = prove
5384  (`!x. -- &1 <= x /\ x <= &1 ==> asn(x) = pi / &2 - acs(x)`,
5385   SIMP_TAC[REAL_EQ_SUB_LADD; ASN_PLUS_ACS]);;
5386
5387 let ACS_ASN = prove
5388  (`!x. -- &1 <= x /\ x <= &1 ==> acs(x) = pi / &2 - asn(x)`,
5389   SIMP_TAC[ASN_ACS] THEN REAL_ARITH_TAC);;
5390
5391 let ASN_ATN = prove
5392  (`!x. -- &1 < x /\ x < &1 ==> asn(x) = atn(x / sqrt(&1 - x pow 2))`,
5393   SIMP_TAC[ASN_ACS; REAL_LT_IMP_LE; ACS_ATN] THEN REAL_ARITH_TAC);;
5394
5395 let ASN_ACS_SQRT_POS = prove
5396  (`!x. &0 <= x /\ x <= &1 ==> asn(x) = acs(sqrt(&1 - x pow 2))`,
5397   REPEAT STRIP_TAC THEN REWRITE_TAC[asn; acs] THEN
5398   ASM_SIMP_TAC[CX_SQRT; REAL_SUB_LE; REAL_POW_1_LE; CX_SUB; CX_POW] THEN
5399   AP_TERM_TAC THEN MATCH_MP_TAC CASN_CACS_SQRT_POS THEN
5400   ASM_REWRITE_TAC[RE_CX; IM_CX] THEN ASM_REAL_ARITH_TAC);;
5401
5402 let ASN_ACS_SQRT_NEG = prove
5403  (`!x. -- &1 <= x /\ x <= &0 ==> asn(x) = --acs(sqrt(&1 - x pow 2))`,
5404   REPEAT STRIP_TAC THEN
5405   ONCE_REWRITE_TAC[REAL_ARITH `x = --y <=> (--x:real) = y`] THEN
5406   ASM_SIMP_TAC[GSYM ASN_NEG; REAL_ARITH `x <= &0 ==> x <= &1`] THEN
5407   ONCE_REWRITE_TAC[REAL_ARITH `(x:real) pow 2 = (--x) pow 2`] THEN
5408   MATCH_MP_TAC ASN_ACS_SQRT_POS THEN ASM_REAL_ARITH_TAC);;
5409
5410 let ACS_ASN_SQRT_POS = prove
5411  (`!x. &0 <= x /\ x <= &1 ==> acs(x) = asn(sqrt(&1 - x pow 2))`,
5412   REPEAT STRIP_TAC THEN REWRITE_TAC[asn; acs] THEN
5413   ASM_SIMP_TAC[CX_SQRT; REAL_SUB_LE; REAL_POW_1_LE; CX_SUB; CX_POW] THEN
5414   AP_TERM_TAC THEN MATCH_MP_TAC CACS_CASN_SQRT_POS THEN
5415   ASM_REWRITE_TAC[RE_CX; IM_CX] THEN ASM_REAL_ARITH_TAC);;
5416
5417 let ACS_ASN_SQRT_NEG = prove
5418  (`!x. -- &1 <= x /\ x <= &0 ==> acs(x) = pi - asn(sqrt(&1 - x pow 2))`,
5419   REPEAT STRIP_TAC THEN MP_TAC(SPEC `--x:real` ACS_ASN_SQRT_POS) THEN
5420   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; SIMP_TAC[REAL_POW_NEG; ARITH]] THEN
5421   DISCH_THEN(SUBST1_TAC o SYM) THEN
5422   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM REAL_NEG_NEG] THEN
5423   MATCH_MP_TAC ACS_NEG THEN ASM_REAL_ARITH_TAC);;
5424
5425 (* ------------------------------------------------------------------------- *)
5426 (* More delicate continuity results for arcsin and arccos.                   *)
5427 (* ------------------------------------------------------------------------- *)
5428
5429 let CONTINUOUS_ON_CASN_REAL = prove
5430  (`casn continuous_on {w | real w /\ abs(Re w) <= &1}`,
5431   MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
5432   EXISTS_TAC `IMAGE csin {z | real z /\ abs(Re z) <= pi / &2}` THEN
5433   CONJ_TAC THENL
5434    [MATCH_MP_TAC CONTINUOUS_ON_INVERSE THEN
5435     REWRITE_TAC[CONTINUOUS_ON_CSIN] THEN CONJ_TAC THENL
5436      [REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN CONJ_TAC THENL
5437        [MATCH_MP_TAC BOUNDED_SUBSET THEN
5438         EXISTS_TAC `cball(Cx(&0),pi / &2)` THEN
5439         REWRITE_TAC[BOUNDED_CBALL; SUBSET; IN_ELIM_THM; IN_CBALL] THEN
5440         REWRITE_TAC[dist; COMPLEX_SUB_LZERO; NORM_NEG; real] THEN
5441         X_GEN_TAC `z:complex` THEN
5442         MP_TAC(SPEC `z:complex` COMPLEX_NORM_LE_RE_IM) THEN REAL_ARITH_TAC;
5443         SIMP_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`;
5444                   GSYM REAL_BOUNDS_LE] THEN
5445         SIMP_TAC[CLOSED_INTER; CLOSED_REAL_SET; CLOSED_HALFSPACE_RE_LE;
5446                  REWRITE_RULE[real_ge] CLOSED_HALFSPACE_RE_GE]];
5447       SIMP_TAC[SUBSET; IMP_CONJ; FORALL_REAL; IN_ELIM_THM; RE_CX] THEN
5448       REPEAT STRIP_TAC THEN MATCH_MP_TAC CASN_CSIN THEN
5449       REWRITE_TAC[RE_CX; IM_CX] THEN ASM_REAL_ARITH_TAC];
5450     SIMP_TAC[SUBSET; IMP_CONJ; FORALL_REAL; IN_ELIM_THM; RE_CX; IN_IMAGE] THEN
5451     X_GEN_TAC `x:real` THEN DISCH_TAC THEN
5452     EXISTS_TAC `Cx(asn x)` THEN
5453     ASM_SIMP_TAC[RE_CX; ASN_BOUNDS; REAL_BOUNDS_LE; REAL_CX; SIN_ASN;
5454                  GSYM CX_SIN] THEN
5455     ASM_MESON_TAC[REAL_BOUNDS_LE; ASN_BOUNDS]]);;
5456
5457 let CONTINUOUS_WITHIN_CASN_REAL = prove
5458  (`!z. casn continuous (at z within {w | real w /\ abs(Re w) <= &1})`,
5459   GEN_TAC THEN ASM_CASES_TAC `z IN {w | real w /\ abs(Re w) <= &1}` THENL
5460    [ASM_SIMP_TAC[REWRITE_RULE[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN]
5461       CONTINUOUS_ON_CASN_REAL];
5462     MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN
5463     ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM REAL_BOUNDS_LE] THEN
5464     ASM_SIMP_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
5465     SIMP_TAC[CLOSED_INTER; CLOSED_REAL_SET; CLOSED_HALFSPACE_RE_LE;
5466              REWRITE_RULE[real_ge] CLOSED_HALFSPACE_RE_GE]]);;
5467
5468 let CONTINUOUS_ON_CACS_REAL = prove
5469  (`cacs continuous_on {w | real w /\ abs(Re w) <= &1}`,
5470   MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
5471   EXISTS_TAC `IMAGE ccos {z | real z /\ &0 <= Re z /\ Re z <= pi}` THEN
5472   CONJ_TAC THENL
5473    [MATCH_MP_TAC CONTINUOUS_ON_INVERSE THEN
5474     REWRITE_TAC[CONTINUOUS_ON_CCOS] THEN CONJ_TAC THENL
5475      [REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN CONJ_TAC THENL
5476        [MATCH_MP_TAC BOUNDED_SUBSET THEN
5477         EXISTS_TAC `cball(Cx(&0),&2 * pi)` THEN
5478         REWRITE_TAC[BOUNDED_CBALL; SUBSET; IN_ELIM_THM; IN_CBALL] THEN
5479         REWRITE_TAC[dist; COMPLEX_SUB_LZERO; NORM_NEG; real] THEN
5480         X_GEN_TAC `z:complex` THEN
5481         MP_TAC(SPEC `z:complex` COMPLEX_NORM_LE_RE_IM) THEN REAL_ARITH_TAC;
5482         SIMP_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
5483         SIMP_TAC[CLOSED_INTER; CLOSED_REAL_SET; CLOSED_HALFSPACE_RE_LE;
5484                  REWRITE_RULE[real_ge] CLOSED_HALFSPACE_RE_GE]];
5485       SIMP_TAC[SUBSET; IMP_CONJ; FORALL_REAL; IN_ELIM_THM; RE_CX] THEN
5486       REPEAT STRIP_TAC THEN MATCH_MP_TAC CACS_CCOS THEN
5487       REWRITE_TAC[RE_CX; IM_CX] THEN ASM_REAL_ARITH_TAC];
5488     SIMP_TAC[SUBSET; IMP_CONJ; FORALL_REAL; IN_ELIM_THM; RE_CX; IN_IMAGE] THEN
5489     X_GEN_TAC `x:real` THEN DISCH_TAC THEN
5490     EXISTS_TAC `Cx(acs x)` THEN
5491     ASM_SIMP_TAC[RE_CX; ACS_BOUNDS; REAL_BOUNDS_LE; REAL_CX; COS_ACS;
5492                  GSYM CX_COS]]);;
5493
5494 let CONTINUOUS_WITHIN_CACS_REAL = prove
5495  (`!z. cacs continuous (at z within {w | real w /\ abs(Re w) <= &1})`,
5496   GEN_TAC THEN ASM_CASES_TAC `z IN {w | real w /\ abs(Re w) <= &1}` THENL
5497    [ASM_SIMP_TAC[REWRITE_RULE[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN]
5498       CONTINUOUS_ON_CACS_REAL];
5499     MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN
5500     ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM REAL_BOUNDS_LE] THEN
5501     ASM_SIMP_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
5502     SIMP_TAC[CLOSED_INTER; CLOSED_REAL_SET; CLOSED_HALFSPACE_RE_LE;
5503              REWRITE_RULE[real_ge] CLOSED_HALFSPACE_RE_GE]]);;
5504
5505 (* ------------------------------------------------------------------------- *)
5506 (* Some limits, most involving sequences of transcendentals.                 *)
5507 (* ------------------------------------------------------------------------- *)
5508
5509 let LIM_CX_OVER_CEXP = prove
5510  (`((\x. Cx x / cexp(Cx x)) --> Cx(&0)) at_posinfinity`,
5511   ONCE_REWRITE_TAC[LIM_NULL_COMPLEX_NORM] THEN
5512   REWRITE_TAC[LIM_AT_POSINFINITY; real_ge] THEN
5513   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5514   EXISTS_TAC `max (&1) (&1 + &2 * log (&2 / e))` THEN
5515   X_GEN_TAC `x:real` THEN REWRITE_TAC[REAL_MAX_LE] THEN STRIP_TAC THEN
5516   REWRITE_TAC[dist; COMPLEX_SUB_RZERO; COMPLEX_NORM_CX; REAL_ABS_NORM] THEN
5517   ASM_SIMP_TAC[COMPLEX_NORM_DIV; NORM_CEXP; COMPLEX_NORM_CX; RE_CX] THEN
5518   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_EXP_POS_LT] THEN
5519   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
5520   ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ] THEN GEN_REWRITE_TAC
5521    (RAND_CONV o RAND_CONV) [REAL_ARITH `x = x / &2 + x / &2`] THEN
5522   REWRITE_TAC[REAL_EXP_ADD; REAL_ARITH
5523    `x / e < y * y <=> x / &2 * &2 / e < y * y`] THEN
5524   MATCH_MP_TAC REAL_LT_MUL2 THEN REPEAT CONJ_TAC THENL
5525    [REAL_ARITH_TAC;
5526     MATCH_MP_TAC(REAL_ARITH
5527      `&1 <= x /\ &1 + x / &2 <= y ==> abs x / &2 < y`) THEN
5528     ASM_REWRITE_TAC[REAL_EXP_LE_X];
5529     ASM_SIMP_TAC[REAL_LE_DIV; REAL_POS; REAL_LT_IMP_LE];
5530     MATCH_MP_TAC LOG_MONO_LT_REV THEN
5531     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; LOG_EXP;
5532                  REAL_ARITH `&1 <= x ==> &0 < x`; REAL_EXP_POS_LT] THEN
5533     ASM_REAL_ARITH_TAC]);;
5534
5535 let LIM_Z_TIMES_CLOG = prove
5536  (`((\z. z * clog z) --> Cx(&0)) (at (Cx(&0)))`,
5537   ONCE_REWRITE_TAC[SPEC `clog z` COMPLEX_EXPAND] THEN
5538   REWRITE_TAC[COMPLEX_ADD_LDISTRIB] THEN
5539   MATCH_MP_TAC LIM_NULL_COMPLEX_ADD THEN CONJ_TAC THENL
5540    [SIMP_TAC[RE_CLOG] THEN MP_TAC LIM_CX_OVER_CEXP THEN
5541     REWRITE_TAC[LIM_AT_POSINFINITY; LIM_AT; dist; COMPLEX_SUB_RZERO] THEN
5542     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
5543     ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[real_ge] THEN
5544     REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_CX; NORM_CEXP; RE_CX] THEN
5545     DISCH_THEN(X_CHOOSE_TAC `b:real`) THEN
5546     REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_CX] THEN
5547     EXISTS_TAC `inv(exp b)` THEN SIMP_TAC[REAL_LT_INV_EQ; REAL_EXP_POS_LT] THEN
5548     X_GEN_TAC `z:complex` THEN STRIP_TAC THEN
5549     FIRST_X_ASSUM(MP_TAC o SPEC `log(inv(norm(z:complex)))`) THEN
5550     ASM_SIMP_TAC[LOG_INV; EXP_LOG; REAL_LT_INV_EQ] THEN
5551     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
5552     REWRITE_TAC[real_div; REAL_INV_INV; REAL_ABS_NEG] THEN
5553     DISCH_THEN MATCH_MP_TAC THEN
5554     GEN_REWRITE_TAC I [GSYM REAL_EXP_MONO_LE] THEN
5555     ASM_SIMP_TAC[EXP_LOG; REAL_EXP_NEG] THEN
5556     GEN_REWRITE_TAC LAND_CONV [GSYM REAL_INV_INV] THEN
5557     MATCH_MP_TAC REAL_LE_INV2 THEN ASM_REAL_ARITH_TAC;
5558     MATCH_MP_TAC LIM_NULL_COMPLEX_RMUL_BOUNDED THEN
5559     REWRITE_TAC[LIM_AT_ID] THEN EXISTS_TAC `pi` THEN
5560     REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_II; COMPLEX_NORM_CX] THEN
5561     REWRITE_TAC[EVENTUALLY_AT; dist; COMPLEX_SUB_0; COMPLEX_NORM_NZ] THEN
5562     SIMP_TAC[CLOG_WORKS; REAL_MUL_LID; REAL_ABS_BOUNDS; REAL_LT_IMP_LE] THEN
5563     MESON_TAC[REAL_LT_01]]);;
5564
5565 let LIM_LOG_OVER_Z = prove
5566  (`((\z. clog z / z) --> Cx(&0)) at_infinity`,
5567   SIMP_TAC[LIM_AT_INFINITY_COMPLEX_0; o_DEF; complex_div; COMPLEX_INV_INV;
5568            CLOG_INV] THEN
5569   ONCE_REWRITE_TAC[COMPLEX_RING
5570    `clog(inv z) * z = z * (clog z + clog(inv z)) - z * clog z`] THEN
5571   MATCH_MP_TAC LIM_NULL_COMPLEX_SUB THEN
5572   REWRITE_TAC[LIM_Z_TIMES_CLOG] THEN
5573   MATCH_MP_TAC LIM_NULL_COMPLEX_RMUL_BOUNDED THEN
5574   REWRITE_TAC[LIM_AT_ID] THEN EXISTS_TAC `&2 * pi` THEN
5575   REWRITE_TAC[EVENTUALLY_AT; dist; COMPLEX_SUB_RZERO; COMPLEX_NORM_NZ] THEN
5576   EXISTS_TAC `&1` THEN SIMP_TAC[REAL_LT_01] THEN
5577   X_GEN_TAC `z:complex` THEN STRIP_TAC THEN
5578   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [COMPLEX_EXPAND] THEN
5579   ASM_SIMP_TAC[RE_ADD; RE_CLOG; REAL_LT_INV_EQ; COMPLEX_INV_EQ_0;
5580                COMPLEX_NORM_INV; LOG_INV; COMPLEX_NORM_NZ] THEN
5581   REWRITE_TAC[REAL_ADD_RINV; COMPLEX_ADD_LID; COMPLEX_NORM_MUL] THEN
5582   REWRITE_TAC[COMPLEX_NORM_II; COMPLEX_NORM_CX; IM_ADD] THEN
5583   MATCH_MP_TAC(REAL_ARITH
5584    `--pi < x /\ x <= pi /\ --pi < y /\ y <= pi
5585     ==> &1 * abs(x + y) <= &2 * pi`) THEN
5586   ASM_SIMP_TAC[CLOG_WORKS; COMPLEX_INV_EQ_0]);;
5587
5588 let LIM_LOG_OVER_POWER = prove
5589  (`!s. &0 < Re s
5590        ==> ((\x. clog(Cx x) / (Cx x) cpow s) --> Cx(&0)) at_posinfinity`,
5591   REPEAT STRIP_TAC THEN REWRITE_TAC[LIM_AT_POSINFINITY] THEN
5592   X_GEN_TAC `e:real` THEN DISCH_TAC THEN REWRITE_TAC[real_ge] THEN
5593   MP_TAC(REWRITE_RULE[LIM_AT_POSINFINITY] LIM_CX_OVER_CEXP) THEN
5594   DISCH_THEN(MP_TAC o SPEC `Re s * e`) THEN
5595   ASM_SIMP_TAC[REAL_LT_MUL; real_ge; dist; COMPLEX_SUB_RZERO] THEN
5596   REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_CX; NORM_CEXP; RE_CX] THEN
5597   DISCH_THEN(X_CHOOSE_TAC `B:real`) THEN
5598   EXISTS_TAC `max (&1) (exp((abs B + &1) / Re s))` THEN X_GEN_TAC `x:real` THEN
5599   REWRITE_TAC[REAL_MAX_LE] THEN STRIP_TAC THEN
5600   SUBGOAL_THEN `&0 < x` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
5601   ASM_SIMP_TAC[NORM_CPOW_REAL; COMPLEX_NORM_DIV; REAL_CX; RE_CX;
5602                GSYM CX_LOG; COMPLEX_NORM_CX; real_abs; LOG_POS] THEN
5603   MATCH_MP_TAC REAL_LT_LCANCEL_IMP THEN EXISTS_TAC `Re s` THEN
5604   ASM_REWRITE_TAC[] THEN
5605   FIRST_X_ASSUM(MP_TAC o SPEC `Re s * log x`) THEN
5606   ASM_SIMP_TAC[real_abs; REAL_LE_MUL; LOG_POS; REAL_LT_IMP_LE] THEN
5607   REWRITE_TAC[real_div; GSYM REAL_MUL_ASSOC] THEN DISCH_THEN MATCH_MP_TAC THEN
5608   MATCH_MP_TAC(REAL_ARITH `abs b + &1 <= x * y ==> b <= y * x`) THEN
5609   ASM_SIMP_TAC[GSYM REAL_LE_LDIV_EQ] THEN
5610   ONCE_REWRITE_TAC[GSYM REAL_EXP_MONO_LE] THEN
5611   ASM_SIMP_TAC[EXP_LOG]);;
5612
5613 let LIM_LOG_OVER_X = prove
5614  (`((\x. clog(Cx x) / Cx x) --> Cx(&0)) at_posinfinity`,
5615   MP_TAC(SPEC `Cx(&1)` LIM_LOG_OVER_POWER) THEN
5616   REWRITE_TAC[CPOW_N; RE_CX; REAL_LT_01; COMPLEX_POW_1] THEN
5617   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN
5618   REWRITE_TAC[EVENTUALLY_AT_POSINFINITY; CX_INJ] THEN
5619   EXISTS_TAC `&1` THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
5620   REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
5621
5622 let LIM_LOG_OVER_POWER_N = prove
5623  (`!s. &0 < Re s
5624        ==> ((\n. clog(Cx(&n)) / Cx(&n) cpow s) --> Cx(&0)) sequentially`,
5625   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_POSINFINITY_SEQUENTIALLY THEN
5626   ASM_SIMP_TAC[LIM_LOG_OVER_POWER]);;
5627
5628 let LIM_LOG_OVER_N = prove
5629  (`((\n. clog(Cx(&n)) / Cx(&n)) --> Cx(&0)) sequentially`,
5630   MP_TAC(SPEC `Cx(&1)` LIM_LOG_OVER_POWER_N) THEN
5631   SIMP_TAC[RE_CX; REAL_LT_01] THEN
5632   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN
5633   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY; CPOW_N; CX_INJ] THEN EXISTS_TAC `1` THEN
5634   SIMP_TAC[COMPLEX_POW_1; REAL_OF_NUM_EQ; ARITH_RULE `1 <= n <=> ~(n = 0)`]);;
5635
5636 let LIM_1_OVER_POWER = prove
5637  (`!s. &0 < Re s
5638        ==> ((\n. Cx(&1) / Cx(&n) cpow s) --> Cx(&0)) sequentially`,
5639   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_NULL_COMPLEX_BOUND THEN
5640   EXISTS_TAC `\n. clog(Cx(&n)) / Cx(&n) cpow s` THEN
5641   ASM_SIMP_TAC[LIM_LOG_OVER_POWER_N] THEN
5642   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
5643   MP_TAC(ISPEC `exp(&1)` REAL_ARCH_SIMPLE) THEN
5644   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
5645   ASM_CASES_TAC `N = 0` THENL
5646    [ASM_SIMP_TAC[GSYM REAL_NOT_LT; REAL_EXP_POS_LT]; ALL_TAC] THEN
5647   DISCH_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
5648   REWRITE_TAC[complex_div; COMPLEX_NORM_MUL] THEN
5649   MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
5650   SUBGOAL_THEN `~(n = 0)` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
5651   ASM_SIMP_TAC[GSYM CX_LOG; REAL_OF_NUM_LT; LT_NZ;
5652                COMPLEX_NORM_CX; REAL_ABS_NUM] THEN
5653   MATCH_MP_TAC(REAL_ARITH `x <= y ==> x <= abs y`) THEN
5654   ONCE_REWRITE_TAC[GSYM REAL_EXP_MONO_LE] THEN
5655   ASM_SIMP_TAC[EXP_LOG; REAL_OF_NUM_LT; LT_NZ] THEN
5656   RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC);;
5657
5658 let LIM_INV_Z_OFFSET = prove
5659  (`!z. ((\w. inv(w + z)) --> Cx(&0)) at_infinity`,
5660   GEN_TAC THEN REWRITE_TAC[LIM_AT_INFINITY_COMPLEX_0; o_DEF] THEN
5661   SIMP_TAC[COMPLEX_INV_DIV; COMPLEX_FIELD
5662    `~(w = Cx(&0)) ==> inv w + z = (Cx(&1) + w * z) / w`] THEN
5663   GEN_REWRITE_TAC LAND_CONV
5664    [COMPLEX_FIELD `Cx(&0) = Cx(&0) / (Cx(&1) + Cx(&0) * z)`] THEN
5665   MATCH_MP_TAC LIM_COMPLEX_DIV THEN
5666   REWRITE_TAC[COMPLEX_RING `~(Cx(&1) + Cx(&0) * z = Cx(&0))`] THEN
5667   CONJ_TAC THEN LIM_TAC);;
5668
5669 let LIM_INV_Z = prove
5670  (`((\z. inv(z)) --> Cx(&0)) at_infinity`,
5671   ONCE_REWRITE_TAC[MESON[COMPLEX_ADD_RID] `inv z = inv(z + Cx(&0))`] THEN
5672   REWRITE_TAC[LIM_INV_Z_OFFSET]);;
5673
5674 let LIM_INV_X_OFFSET = prove
5675  (`!z. ((\x. inv(Cx x + z)) --> Cx(&0)) at_posinfinity`,
5676   GEN_TAC THEN
5677   MATCH_MP_TAC(REWRITE_RULE[o_DEF] LIM_INFINITY_POSINFINITY_CX) THEN
5678   REWRITE_TAC[LIM_INV_Z_OFFSET]);;
5679
5680 let LIM_INV_X = prove
5681  (`((\x. inv(Cx x)) --> Cx(&0)) at_posinfinity`,
5682   MATCH_MP_TAC(REWRITE_RULE[o_DEF] LIM_INFINITY_POSINFINITY_CX) THEN
5683   REWRITE_TAC[REWRITE_RULE[ETA_AX] LIM_INV_Z]);;
5684
5685 let LIM_INV_N_OFFSET = prove
5686  (`!z. ((\n. inv(Cx(&n) + z)) --> Cx(&0)) sequentially`,
5687   GEN_TAC THEN MATCH_MP_TAC LIM_POSINFINITY_SEQUENTIALLY THEN
5688   REWRITE_TAC[LIM_INV_X_OFFSET]);;
5689
5690 let LIM_1_OVER_N = prove
5691  (`((\n. Cx(&1) / Cx(&n)) --> Cx(&0)) sequentially`,
5692   MP_TAC(SPEC `Cx(&1)` LIM_1_OVER_POWER) THEN SIMP_TAC[RE_CX; REAL_LT_01] THEN
5693   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN
5694   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY; CPOW_N; CX_INJ] THEN EXISTS_TAC `1` THEN
5695   SIMP_TAC[COMPLEX_POW_1; REAL_OF_NUM_EQ; ARITH_RULE `1 <= n <=> ~(n = 0)`]);;
5696
5697 let LIM_INV_N = prove
5698  (`((\n. inv(Cx(&n))) --> Cx(&0)) sequentially`,
5699   MP_TAC LIM_1_OVER_N THEN REWRITE_TAC[complex_div; COMPLEX_MUL_LID]);;
5700
5701 let LIM_INV_Z_POW_OFFSET = prove
5702  (`!z n. 1 <= n ==> ((\w. inv(w + z) pow n) --> Cx(&0)) at_infinity`,
5703   REPEAT STRIP_TAC THEN
5704   SUBGOAL_THEN `Cx(&0) = Cx(&0) pow n` SUBST1_TAC THENL
5705    [ASM_SIMP_TAC[COMPLEX_POW_ZERO; LE_1];
5706     MATCH_MP_TAC LIM_COMPLEX_POW THEN REWRITE_TAC[LIM_INV_Z_OFFSET]]);;
5707
5708 let LIM_INV_Z_POW = prove
5709  (`!n. 1 <= n ==> ((\z. inv(z) pow n) --> Cx(&0)) at_infinity`,
5710   REPEAT STRIP_TAC THEN
5711   SUBGOAL_THEN `Cx(&0) = Cx(&0) pow n` SUBST1_TAC THENL
5712    [ASM_SIMP_TAC[COMPLEX_POW_ZERO; LE_1];
5713     MATCH_MP_TAC LIM_COMPLEX_POW THEN
5714     REWRITE_TAC[REWRITE_RULE[ETA_AX] LIM_INV_Z]]);;
5715
5716 let LIM_INV_X_POW_OFFSET = prove
5717  (`!z n. 1 <= n ==> ((\x. inv(Cx x + z) pow n) --> Cx(&0)) at_posinfinity`,
5718   REPEAT STRIP_TAC THEN
5719   MATCH_MP_TAC(REWRITE_RULE[o_DEF] LIM_INFINITY_POSINFINITY_CX) THEN
5720   ASM_SIMP_TAC[LIM_INV_Z_POW_OFFSET]);;
5721
5722 let LIM_INV_X_POW = prove
5723  (`!n. 1 <= n ==> ((\x. inv(Cx x) pow n) --> Cx(&0)) at_posinfinity`,
5724   REPEAT STRIP_TAC THEN
5725   MATCH_MP_TAC(REWRITE_RULE[o_DEF] LIM_INFINITY_POSINFINITY_CX) THEN
5726   ASM_SIMP_TAC[LIM_INV_Z_POW]);;
5727
5728 let LIM_INV_N_POW_OFFSET = prove
5729  (`!z m. 1 <= m ==> ((\n. inv(Cx(&n) + z) pow m) --> Cx(&0)) sequentially`,
5730   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_POSINFINITY_SEQUENTIALLY THEN
5731   ASM_SIMP_TAC[LIM_INV_X_POW_OFFSET]);;
5732
5733 let LIM_INV_N_POW = prove
5734  (`!m. 1 <= m ==> ((\n. inv(Cx(&n)) pow m) --> Cx(&0)) sequentially`,
5735   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_POSINFINITY_SEQUENTIALLY THEN
5736   ASM_SIMP_TAC[LIM_INV_X_POW]);;
5737
5738 let LIM_1_OVER_LOG = prove
5739  (`((\n. Cx(&1) / clog(Cx(&n))) --> Cx(&0)) sequentially`,
5740   REWRITE_TAC[LIM_SEQUENTIALLY] THEN X_GEN_TAC `e:real` THEN
5741   DISCH_TAC THEN X_CHOOSE_TAC `N:num` (SPEC `exp(inv e)` REAL_ARCH_SIMPLE) THEN
5742   EXISTS_TAC `N + 1` THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
5743   REWRITE_TAC[dist; COMPLEX_SUB_RZERO; COMPLEX_MUL_LID; complex_div] THEN
5744   SUBGOAL_THEN `0 < n` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
5745   RULE_ASSUM_TAC(REWRITE_RULE
5746    [GSYM REAL_OF_NUM_LT; GSYM REAL_OF_NUM_LE; GSYM REAL_OF_NUM_ADD]) THEN
5747   ASM_SIMP_TAC[GSYM CX_LOG; COMPLEX_NORM_CX; COMPLEX_NORM_INV] THEN
5748   GEN_REWRITE_TAC RAND_CONV [GSYM REAL_INV_INV] THEN
5749   MATCH_MP_TAC REAL_LT_INV2 THEN ASM_REWRITE_TAC[REAL_LT_INV_EQ] THEN
5750   MATCH_MP_TAC(REAL_ARITH `a < x ==> a < abs x`) THEN
5751   ONCE_REWRITE_TAC[GSYM REAL_EXP_MONO_LT] THEN
5752   ASM_SIMP_TAC[EXP_LOG] THEN ASM_REAL_ARITH_TAC);;
5753
5754 let LIM_N_TIMES_POWN = prove
5755  (`!z. norm(z) < &1 ==> ((\n. Cx(&n) * z pow n) --> Cx(&0)) sequentially`,
5756   REPEAT STRIP_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
5757   ASM_SIMP_TAC[COMPLEX_POW_ZERO; LIM_CASES_FINITE_SEQUENTIALLY; LIM_CONST;
5758                COND_RAND; FINITE_SING; SING_GSPEC; COMPLEX_MUL_RZERO] THEN
5759   MP_TAC LIM_LOG_OVER_N THEN
5760   REWRITE_TAC[LIM_SEQUENTIALLY; dist; COMPLEX_SUB_RZERO] THEN
5761   DISCH_THEN(MP_TAC o SPEC `log(inv(norm(z:complex))) / &2`) THEN
5762   ASM_SIMP_TAC[LOG_POS_LT; REAL_INV_1_LT; COMPLEX_NORM_NZ; REAL_HALF] THEN
5763   DISCH_THEN(X_CHOOSE_THEN `N1:num` (LABEL_TAC "+")) THEN
5764   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5765   FIRST_ASSUM(X_CHOOSE_THEN `N2:num` STRIP_ASSUME_TAC o
5766               GEN_REWRITE_RULE I [REAL_ARCH_INV]) THEN
5767   EXISTS_TAC `MAX 1 (MAX N1 N2)` THEN
5768   REWRITE_TAC[ARITH_RULE `MAX a b <= c <=> a <= c /\ b <= c`] THEN
5769   X_GEN_TAC `n:num` THEN STRIP_TAC THEN
5770   FIRST_X_ASSUM(MP_TAC o SPEC `n:num`) THEN
5771   ASM_SIMP_TAC[GSYM CX_LOG; REAL_OF_NUM_LT; LE_1; GSYM CX_DIV;
5772                COMPLEX_NORM_CX; REAL_ABS_DIV; REAL_ABS_NUM] THEN
5773   ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH; real_abs;
5774                LOG_POS; REAL_OF_NUM_LE] THEN
5775   ONCE_REWRITE_TAC[REAL_ARITH `a / b * &2 = (&2 * a) / b`] THEN
5776   ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; LE_1] THEN
5777   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [REAL_MUL_SYM] THEN
5778   GEN_REWRITE_TAC LAND_CONV [GSYM REAL_EXP_MONO_LT] THEN
5779   ASM_SIMP_TAC[REAL_EXP_N; EXP_LOG; REAL_OF_NUM_LT; LE_1;
5780                REAL_LT_INV_EQ; COMPLEX_NORM_NZ] THEN
5781   REWRITE_TAC[REAL_POW_INV] THEN
5782   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM REAL_MUL_LID] THEN
5783   ASM_SIMP_TAC[GSYM real_div; REAL_LT_RDIV_EQ; REAL_POW_LT; COMPLEX_NORM_NZ;
5784                COMPLEX_NORM_MUL; COMPLEX_NORM_NUM; COMPLEX_NORM_POW] THEN
5785   DISCH_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&N2)` THEN
5786   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_TRANS THEN
5787   EXISTS_TAC `inv(&n)` THEN
5788   ASM_SIMP_TAC[REAL_LE_INV2; REAL_OF_NUM_LE; REAL_OF_NUM_LT; LE_1] THEN
5789   MATCH_MP_TAC REAL_LE_LCANCEL_IMP THEN EXISTS_TAC `&n` THEN
5790   ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ; REAL_OF_NUM_LT; LE_1] THEN
5791   ASM_REAL_ARITH_TAC);;
5792
5793 let LIM_N_OVER_POWN = prove
5794  (`!z. &1 < norm(z) ==> ((\n. Cx(&n) / z pow n) --> Cx(&0)) sequentially`,
5795   ASM_SIMP_TAC[complex_div; GSYM COMPLEX_POW_INV; COMPLEX_NORM_INV;
5796                REAL_INV_LT_1; LIM_N_TIMES_POWN]);;
5797
5798 let LIM_POWN = prove
5799  (`!z. norm(z) < &1 ==> ((\n. z pow n) --> Cx(&0)) sequentially`,
5800   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_NULL_COMPARISON_COMPLEX THEN
5801   EXISTS_TAC `\n. Cx(&n) * z pow n` THEN ASM_SIMP_TAC[LIM_N_TIMES_POWN] THEN
5802   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `1` THEN
5803   REWRITE_TAC[COMPLEX_NORM_MUL; COMPLEX_NORM_CX; REAL_ABS_NUM] THEN
5804   REWRITE_TAC[REAL_ARITH `a <= n * a <=> &0 <= (n - &1) * a`] THEN
5805   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_MUL THEN
5806   ASM_REWRITE_TAC[NORM_POS_LE; REAL_SUB_LE; REAL_OF_NUM_LE]);;
5807
5808 let LIM_CSIN_OVER_X = prove
5809  (`((\z. csin z / z) --> Cx(&1)) (at (Cx(&0)))`,
5810   ONCE_REWRITE_TAC[LIM_NULL_COMPLEX] THEN
5811   MATCH_MP_TAC LIM_NULL_COMPARISON_COMPLEX THEN
5812   EXISTS_TAC `\z. cexp(Cx(abs(Im z))) * z pow 2 / Cx(&2)` THEN
5813   REWRITE_TAC[EVENTUALLY_AT] THEN CONJ_TAC THENL
5814    [EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01; dist; COMPLEX_SUB_RZERO] THEN
5815     X_GEN_TAC `z:complex` THEN SIMP_TAC[COMPLEX_NORM_NZ] THEN STRIP_TAC THEN
5816     MATCH_MP_TAC REAL_LE_LCANCEL_IMP THEN EXISTS_TAC `norm(z:complex)` THEN
5817     ASM_REWRITE_TAC[COMPLEX_NORM_NZ; GSYM COMPLEX_NORM_MUL] THEN
5818     ASM_SIMP_TAC[COMPLEX_FIELD
5819      `~(z = Cx(&0)) ==> z * (s / z - Cx(&1)) = s - z`] THEN
5820     REWRITE_TAC[GSYM CX_EXP; COMPLEX_NORM_MUL; COMPLEX_NORM_CX] THEN
5821     REWRITE_TAC[real_abs; REAL_EXP_POS_LE] THEN REWRITE_TAC[GSYM real_abs] THEN
5822     MP_TAC(ISPECL [`0`; `z:complex`] TAYLOR_CSIN) THEN
5823     REWRITE_TAC[VSUM_SING_NUMSEG] THEN CONV_TAC NUM_REDUCE_CONV THEN
5824     REWRITE_TAC[complex_pow; COMPLEX_POW_1; COMPLEX_DIV_1] THEN
5825     REWRITE_TAC[COMPLEX_MUL_LID] THEN
5826     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
5827     MATCH_MP_TAC REAL_EQ_IMP_LE THEN
5828     REWRITE_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_CX; REAL_ABS_NUM] THEN
5829     REWRITE_TAC[COMPLEX_NORM_POW] THEN REAL_ARITH_TAC;
5830     LIM_TAC THEN TRY(CONV_TAC COMPLEX_RING) THEN
5831     GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN
5832     MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
5833     REWRITE_TAC[CONTINUOUS_AT_CEXP] THEN
5834     REWRITE_TAC[CONTINUOUS_AT; LIM_AT; dist; COMPLEX_SUB_RZERO;
5835                 IM_CX; REAL_ABS_NUM; COMPLEX_NORM_CX; REAL_ABS_ABS] THEN
5836     MESON_TAC[REAL_LET_TRANS; COMPLEX_NORM_GE_RE_IM]]);;
5837
5838 (* ------------------------------------------------------------------------- *)
5839 (* Roots of unity.                                                           *)
5840 (* ------------------------------------------------------------------------- *)
5841
5842 let COMPLEX_ROOT_POLYFUN = prove
5843  (`!n z a.
5844         1 <= n
5845         ==> (z pow n = a <=>
5846              vsum(0..n) (\i. (if i = 0 then --a else if i = n then Cx(&1)
5847                               else Cx(&0)) * z pow i) = Cx(&0))`,
5848   ASM_SIMP_TAC[VSUM_CLAUSES_RIGHT; LE_1; LE_0] THEN
5849   SIMP_TAC[VSUM_CLAUSES_LEFT; LE_0; ADD_CLAUSES] THEN
5850   ASM_SIMP_TAC[LE_1; ARITH_RULE `1 <= n /\ 1 <= i /\ i <= n - 1
5851                            ==> ~(i = n)`] THEN
5852   REWRITE_TAC[COMPLEX_MUL_LZERO; complex_pow; COMPLEX_MUL_RID] THEN
5853   REWRITE_TAC[GSYM COMPLEX_VEC_0; VSUM_0; VECTOR_ADD_RID] THEN
5854   REWRITE_TAC[COMPLEX_VEC_0] THEN CONV_TAC COMPLEX_RING);;
5855
5856 let COMPLEX_ROOT_UNITY = prove
5857  (`!n j. ~(n = 0)
5858          ==> cexp(Cx(&2) * Cx pi * ii * Cx(&j / &n)) pow n = Cx(&1)`,
5859   REWRITE_TAC[GSYM CEXP_N; CX_DIV] THEN
5860   ASM_SIMP_TAC[CX_INJ; complex_div; REAL_OF_NUM_EQ; COMPLEX_FIELD
5861     `~(n = Cx(&0)) ==> n * t * p * ii * j * inv(n) = j * (ii * t * p)`] THEN
5862   REWRITE_TAC[CEXP_N; GSYM CX_MUL] THEN
5863   REWRITE_TAC[CEXP_EULER; GSYM CX_MUL; GSYM CX_SIN; GSYM CX_COS] THEN
5864   REWRITE_TAC[COS_NPI; SIN_NPI; REAL_POW_NEG; COMPLEX_MUL_RZERO;
5865               REAL_POW_ONE; ARITH_EVEN; COMPLEX_ADD_RID; COMPLEX_POW_ONE]);;
5866
5867 let COMPLEX_ROOT_UNITY_EQ = prove
5868  (`!n j k. ~(n = 0)
5869            ==> (cexp(Cx(&2) * Cx pi * ii * Cx(&j / &n)) =
5870                 cexp(Cx(&2) * Cx pi * ii * Cx(&k / &n)) <=> (j == k) (mod n))`,
5871   REPEAT STRIP_TAC THEN REWRITE_TAC[CEXP_EQ; num_congruent; CX_MUL] THEN
5872   REWRITE_TAC[COMPLEX_RING
5873    `t * p * ii * j = t * p * ii * k + (t * n * p) * ii <=>
5874         (t * p * ii = Cx(&0)) \/ j - k = n`] THEN
5875   SIMP_TAC[COMPLEX_ENTIRE; II_NZ; CX_INJ; PI_NZ; REAL_OF_NUM_EQ; ARITH] THEN
5876   REWRITE_TAC[GSYM CX_SUB; CX_INJ] THEN
5877   ASM_SIMP_TAC[REAL_OF_NUM_EQ; REAL_FIELD
5878    `~(n = &0) ==> (j / n - k / n = m <=> j - k = n * m)`] THEN
5879   REWRITE_TAC[int_congruent] THEN
5880   REWRITE_TAC[int_eq; int_sub_th; int_mul_th; int_of_num_th] THEN
5881   MESON_TAC[int_abstr; int_rep]);;
5882
5883 let COMPLEX_ROOT_UNITY_EQ_1 = prove
5884  (`!n j. ~(n = 0)
5885          ==> (cexp(Cx(&2) * Cx pi * ii * Cx(&j / &n)) = Cx(&1) <=>
5886               n divides j)`,
5887   REPEAT STRIP_TAC THEN
5888   SUBGOAL_THEN `Cx(&1) = cexp(Cx(&2) * Cx pi * ii * Cx(&n / &n))`
5889   SUBST1_TAC THENL
5890    [ASM_SIMP_TAC[REAL_DIV_REFL; REAL_OF_NUM_EQ; COMPLEX_MUL_RID] THEN
5891     ONCE_REWRITE_TAC[COMPLEX_RING `t * p * ii = ii * t * p`] THEN
5892     REWRITE_TAC[CEXP_EULER; GSYM CX_MUL; GSYM CX_SIN; GSYM CX_COS] THEN
5893     REWRITE_TAC[COS_NPI; SIN_NPI] THEN SIMPLE_COMPLEX_ARITH_TAC;
5894     ASM_SIMP_TAC[COMPLEX_ROOT_UNITY_EQ] THEN CONV_TAC NUMBER_RULE]);;
5895
5896 let FINITE_CARD_COMPLEX_ROOTS_UNITY = prove
5897  (`!n. 1 <= n
5898        ==> FINITE {z | z pow n = Cx(&1)} /\ CARD {z | z pow n = Cx(&1)} <= n`,
5899   REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_SIMP_TAC[COMPLEX_ROOT_POLYFUN] THEN
5900   MATCH_MP_TAC COMPLEX_POLYFUN_ROOTBOUND THEN
5901   DISCH_THEN(MP_TAC o SPEC `n:num`) THEN
5902   ASM_SIMP_TAC[IN_NUMSEG; LE_1; LE_0; LE_REFL] THEN CONV_TAC COMPLEX_RING);;
5903
5904 let FINITE_COMPLEX_ROOTS_UNITY = prove
5905  (`!n. ~(n = 0) ==> FINITE {z | z pow n = Cx(&1)}`,
5906   SIMP_TAC[FINITE_CARD_COMPLEX_ROOTS_UNITY; LE_1]);;
5907
5908 let FINITE_CARD_COMPLEX_ROOTS_UNITY_EXPLICIT = prove
5909  (`!n. 1 <= n
5910        ==> FINITE {cexp(Cx(&2) * Cx pi * ii * Cx(&j / &n)) | j | j < n} /\
5911            CARD {cexp(Cx(&2) * Cx pi * ii * Cx(&j / &n)) | j | j < n} = n`,
5912   let lemma = prove (* So we don't need to load number theories yet *)
5913    (`!x y n:num. (x == y) (mod n) /\ x < y + n /\ y < x + n ==> x = y`,
5914     REWRITE_TAC[num_congruent; GSYM INT_OF_NUM_EQ; GSYM INT_OF_NUM_LT] THEN
5915     REWRITE_TAC[GSYM INT_OF_NUM_ADD] THEN
5916     REWRITE_TAC[INT_ARITH `x < y + n /\ y < x + n <=> abs(x - y:int) < n`] THEN
5917     REPEAT GEN_TAC THEN REWRITE_TAC[int_congruent] THEN
5918     DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `d:int`) MP_TAC) THEN
5919     ONCE_REWRITE_TAC[GSYM INT_SUB_0] THEN
5920     ASM_SIMP_TAC[INT_ABS_MUL; INT_ENTIRE; INT_ABS_NUM;
5921                  INT_ARITH `n * x:int < n <=> n * x < n * &1`] THEN
5922     DISJ_CASES_TAC(INT_ARITH `&n:int = &0 \/ &0:int < &n`) THEN
5923     ASM_SIMP_TAC[INT_LT_LMUL_EQ] THEN INT_ARITH_TAC) in
5924   REWRITE_TAC[GSYM HAS_SIZE] THEN
5925   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC [SIMPLE_IMAGE_GEN] THEN
5926   MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN REWRITE_TAC[IN_ELIM_THM] THEN
5927   ASM_SIMP_TAC[HAS_SIZE_NUMSEG_LT; COMPLEX_ROOT_UNITY_EQ; LE_1] THEN
5928   REPEAT STRIP_TAC THEN MATCH_MP_TAC lemma THEN EXISTS_TAC `n:num` THEN
5929   ASM_REWRITE_TAC[] THEN ASM_ARITH_TAC);;
5930
5931 let COMPLEX_ROOTS_UNITY = prove
5932  (`!n. 1 <= n
5933        ==> {z | z pow n = Cx(&1)} =
5934            {cexp(Cx(&2) * Cx pi * ii * Cx(&j / &n)) | j | j < n}`,
5935   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC CARD_SUBSET_LE THEN
5936   ASM_SIMP_TAC[FINITE_CARD_COMPLEX_ROOTS_UNITY;
5937                FINITE_CARD_COMPLEX_ROOTS_UNITY_EXPLICIT] THEN
5938   GEN_REWRITE_TAC LAND_CONV [SIMPLE_IMAGE_GEN] THEN
5939   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM] THEN
5940   ASM_SIMP_TAC[COMPLEX_ROOT_UNITY; LE_1]);;
5941
5942 let CARD_COMPLEX_ROOTS_UNITY = prove
5943  (`!n. 1 <= n ==> CARD {z | z pow n = Cx(&1)} = n`,
5944   SIMP_TAC[COMPLEX_ROOTS_UNITY; FINITE_CARD_COMPLEX_ROOTS_UNITY_EXPLICIT]);;
5945
5946 let HAS_SIZE_COMPLEX_ROOTS_UNITY = prove
5947  (`!n. 1 <= n ==> {z | z pow n = Cx(&1)} HAS_SIZE n`,
5948   SIMP_TAC[HAS_SIZE; CARD_COMPLEX_ROOTS_UNITY; FINITE_COMPLEX_ROOTS_UNITY;
5949            LE_1]);;
5950
5951 let COMPLEX_NOT_ROOT_UNITY = prove
5952  (`!n. 1 <= n ==> ?u. norm u = &1 /\ ~(u pow n = Cx(&1))`,
5953   GEN_TAC THEN DISCH_TAC THEN
5954   ABBREV_TAC `u = cexp (Cx pi * ii * Cx (&1 / &n))` THEN
5955   EXISTS_TAC `u : complex` THEN CONJ_TAC THEN EXPAND_TAC "u" THEN
5956   REWRITE_TAC [NORM_CEXP; RE_MUL_CX; RE_II; REAL_MUL_LZERO;
5957                REAL_MUL_RZERO; REAL_EXP_0] THEN
5958   EXPAND_TAC "u" THEN REWRITE_TAC[GSYM CEXP_N] THEN
5959   ASM_SIMP_TAC[CX_DIV; LE_1; CX_INJ; REAL_OF_NUM_EQ; COMPLEX_FIELD
5960        `~(n = Cx(&0)) ==> n * p * i * Cx(&1) / n = i * p`] THEN
5961   REWRITE_TAC[CEXP_EULER; RE_CX; IM_CX; GSYM CX_COS; GSYM CX_SIN] THEN
5962   REWRITE_TAC[COS_PI; SIN_PI] THEN CONV_TAC COMPLEX_RING);;
5963
5964 (* ------------------------------------------------------------------------- *)
5965 (* Relation between clog and Arg, and hence continuity of Arg.               *)
5966 (* ------------------------------------------------------------------------- *)
5967
5968 let ARG_CLOG = prove
5969  (`!z. &0 < Arg z ==> Arg z = Im(clog(--z)) + pi`,
5970   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THENL
5971    [ASM_REWRITE_TAC[Arg_DEF; REAL_LT_REFL]; ALL_TAC] THEN
5972   DISCH_TAC THEN MP_TAC(last(CONJUNCTS(SPEC `z:complex` ARG))) THEN
5973   ASM_SIMP_TAC[CX_INJ; COMPLEX_NORM_ZERO; COMPLEX_FIELD
5974    `~(z = Cx(&0)) ==> (w = z * a <=> a = w / z)`] THEN
5975   DISCH_THEN(MP_TAC o AP_TERM `( * ) (cexp(--(ii * Cx pi)))`) THEN
5976   REWRITE_TAC[GSYM CEXP_ADD] THEN DISCH_THEN(MP_TAC o AP_TERM `clog`) THEN
5977   W(MP_TAC o PART_MATCH (lhs o rand) CLOG_CEXP o lhand o lhand o snd) THEN
5978   REWRITE_TAC[IM_ADD; IM_MUL_II; RE_CX; IM_NEG] THEN
5979   ASM_SIMP_TAC[REAL_LT_ADDR; ARG; REAL_ARITH
5980     `z < &2 * pi ==> --pi + z <= pi`] THEN
5981   DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[CEXP_NEG; CEXP_EULER] THEN
5982   REWRITE_TAC[GSYM CX_SIN; GSYM CX_COS; SIN_PI; COS_PI] THEN
5983   REWRITE_TAC[CX_NEG; COMPLEX_MUL_RZERO; COMPLEX_ADD_RID;
5984               SIMPLE_COMPLEX_ARITH `inv(--Cx(&1)) * z / w = --z / w`] THEN
5985   DISCH_THEN(MP_TAC o AP_TERM `Im`) THEN
5986   REWRITE_TAC[IM_ADD; IM_NEG; IM_MUL_II; RE_CX] THEN
5987   MATCH_MP_TAC(REAL_RING `w = z ==> --pi + x = w ==> x = z + pi`) THEN
5988   REWRITE_TAC[complex_div] THEN
5989   W(MP_TAC o PART_MATCH (lhs o rand) CLOG_MUL_SIMPLE o rand o lhand o snd) THEN
5990   ASM_SIMP_TAC[CX_INJ; REAL_INV_EQ_0; COMPLEX_NORM_ZERO; COMPLEX_NEG_EQ_0;
5991     GSYM CX_INV; GSYM CX_LOG; REAL_LT_INV_EQ; COMPLEX_NORM_NZ; IM_CX] THEN
5992   ASM_SIMP_TAC[REAL_ADD_RID; CLOG_WORKS; COMPLEX_NEG_EQ_0] THEN
5993   DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[IM_ADD; IM_CX; REAL_ADD_RID]);;
5994
5995 let CONTINUOUS_AT_ARG = prove
5996  (`!z. ~(real z /\ &0 <= Re z) ==> (Cx o Arg) continuous (at z)`,
5997   let lemma = prove
5998    (`(\z. Cx(Im(f z) + pi)) = (Cx o Im) o (\z. f z + ii * Cx pi)`,
5999     REWRITE_TAC[FUN_EQ_THM; o_DEF; IM_ADD; IM_CX; IM_MUL_II; RE_CX]) in
6000   REPEAT STRIP_TAC THEN REWRITE_TAC[CONTINUOUS_AT] THEN
6001   MATCH_MP_TAC LIM_TRANSFORM_WITHIN_OPEN THEN
6002   EXISTS_TAC `\z. Cx(Im(clog(--z)) + pi)` THEN
6003   EXISTS_TAC `(:complex) DIFF {z | real z /\ &0 <= Re z}` THEN
6004   ASM_REWRITE_TAC[IN_DIFF; IN_UNIV; IN_ELIM_THM; GSYM closed] THEN
6005   ASM_SIMP_TAC[o_THM; ARG_CLOG; ARG_LT_NZ; ARG_EQ_0] THEN CONJ_TAC THENL
6006    [REWRITE_TAC[SET_RULE `{z | P z /\ Q z} = P INTER {z | Q z}`] THEN
6007     MATCH_MP_TAC CLOSED_INTER THEN
6008     REWRITE_TAC[CLOSED_REAL; GSYM real_ge; CLOSED_HALFSPACE_RE_GE];
6009     REWRITE_TAC[GSYM CONTINUOUS_AT; lemma] THEN
6010     MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
6011     REWRITE_TAC[CONTINUOUS_AT_CX_IM] THEN
6012     MATCH_MP_TAC CONTINUOUS_ADD THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
6013     MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_AT_COMPOSE) THEN
6014     GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [GSYM ETA_AX] THEN
6015     SIMP_TAC[CONTINUOUS_NEG; CONTINUOUS_AT_ID] THEN
6016     MATCH_MP_TAC CONTINUOUS_AT_CLOG THEN POP_ASSUM MP_TAC THEN
6017     REWRITE_TAC[real; IM_NEG; RE_NEG] THEN REAL_ARITH_TAC]);;
6018
6019 let CONTINUOUS_WITHIN_UPPERHALF_ARG = prove
6020  (`!z. ~(z = Cx(&0))
6021        ==> (Cx o Arg) continuous (at z) within {z | &0 <= Im z}`,
6022   REPEAT STRIP_TAC THEN ASM_CASES_TAC `real z /\ &0 <= Re z` THEN
6023   ASM_SIMP_TAC[CONTINUOUS_AT_ARG; CONTINUOUS_AT_WITHIN] THEN
6024   FIRST_X_ASSUM(CONJUNCTS_THEN2
6025    (ASSUME_TAC o GEN_REWRITE_RULE I [real]) MP_TAC) THEN
6026   SUBGOAL_THEN `~(Re z = &0)` ASSUME_TAC THENL
6027    [DISCH_TAC THEN UNDISCH_TAC `~(z = Cx(&0))` THEN
6028     ASM_REWRITE_TAC[COMPLEX_EQ; RE_CX; IM_CX];
6029     GEN_REWRITE_TAC LAND_CONV [REAL_LE_LT]] THEN
6030   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
6031   MP_TAC(ISPEC `rotate2d (pi / &2) z` CONTINUOUS_AT_ARG) THEN ANTS_TAC THENL
6032    [ASM_REWRITE_TAC[ROTATE2D_PI2; real; IM_MUL_II]; ALL_TAC] THEN
6033   REWRITE_TAC[continuous_at; continuous_within] THEN
6034   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
6035   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
6036   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN
6037   REWRITE_TAC[o_THM; dist; GSYM CX_SUB; COMPLEX_NORM_CX] THEN
6038   STRIP_TAC THEN ASM_REWRITE_TAC[IN_ELIM_THM] THEN
6039   X_GEN_TAC `w:complex` THEN STRIP_TAC THEN
6040   SUBGOAL_THEN `Arg z = &0` ASSUME_TAC THENL
6041    [ASM_SIMP_TAC[ARG_EQ_0; real; REAL_LT_IMP_LE]; ALL_TAC] THEN
6042   ASM_CASES_TAC `Arg w = &0` THEN
6043   ASM_REWRITE_TAC[REAL_SUB_REFL; REAL_ABS_NUM] THEN
6044   SUBGOAL_THEN `&0 < Arg w` ASSUME_TAC THENL
6045    [ASM_REWRITE_TAC[ARG; REAL_LT_LE]; ALL_TAC] THEN
6046   FIRST_X_ASSUM(MP_TAC o SPEC `rotate2d (pi / &2) w`) THEN
6047   ASM_REWRITE_TAC[GSYM ROTATE2D_SUB; NORM_ROTATE2D] THEN
6048   MP_TAC(ISPECL [`pi / &2`; `z:complex`] ARG_ROTATE2D) THEN ANTS_TAC THENL
6049    [ASM_REWRITE_TAC[] THEN MP_TAC PI_POS THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN
6050   DISCH_THEN SUBST1_TAC THEN ASM_REWRITE_TAC[REAL_ADD_RID] THEN
6051   MATCH_MP_TAC(REAL_ARITH
6052    `w' = p + w ==> abs(w' - p) < e ==> abs(w - &0) < e`) THEN
6053   MATCH_MP_TAC ARG_ROTATE2D THEN CONJ_TAC THENL
6054    [DISCH_TAC THEN UNDISCH_TAC `&0 < Arg w` THEN
6055     ASM_REWRITE_TAC[Arg_DEF; REAL_LT_REFL];
6056     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM ARG_LE_PI]) THEN
6057     MP_TAC(SPEC `w:complex` ARG) THEN REAL_ARITH_TAC]);;
6058
6059 let CONTINUOUS_ON_UPPERHALF_ARG = prove
6060  (`(Cx o Arg) continuous_on ({z | &0 <= Im z} DIFF {Cx(&0)})`,
6061   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
6062   X_GEN_TAC `z:complex` THEN REWRITE_TAC[IN_DIFF; IN_SING; IN_ELIM_THM] THEN
6063   STRIP_TAC THEN FIRST_ASSUM(MP_TAC o
6064     MATCH_MP CONTINUOUS_WITHIN_UPPERHALF_ARG) THEN
6065   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_WITHIN_SUBSET) THEN
6066   SET_TAC[]);;
6067
6068 let CONTINUOUS_ON_COMPOSE_ARG = prove
6069  (`!s p:real->real^N.
6070         (p o drop) continuous_on interval[vec 0,lift(&2 * pi)] /\
6071         p(&2 * pi) = p(&0) /\ ~(Cx(&0) IN s)
6072         ==> (\z. p(Arg z)) continuous_on s`,
6073   let ulemma = prove
6074    (`!s. s INTER {z | &0 <= Im z} UNION s INTER {z | Im z <= &0} = s`,
6075     SET_TAC[REAL_LE_TOTAL]) in
6076   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THEN
6077   EXISTS_TAC
6078    `\z. if &0 <= Im z then p(Arg z)
6079         else p(&2 * pi - Arg(cnj z)):real^N` THEN
6080   REWRITE_TAC[IN_UNIV; IN_SING; IN_DIFF] THEN CONJ_TAC THENL
6081    [X_GEN_TAC `z:complex` THEN DISCH_TAC THEN
6082     COND_CASES_TAC THEN ASM_REWRITE_TAC[ARG_CNJ] THEN
6083     COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_SUB_SUB2] THEN
6084     SUBGOAL_THEN `Arg z = &0`
6085      (fun th -> ASM_REWRITE_TAC[REAL_SUB_RZERO; th]) THEN
6086     ASM_REWRITE_TAC[ARG_EQ_0];
6087     GEN_REWRITE_TAC RAND_CONV [GSYM ulemma] THEN
6088     MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL THEN REWRITE_TAC[ulemma] THEN
6089     SIMP_TAC[CLOSED_IN_CLOSED_INTER; CLOSED_HALFSPACE_IM_LE;
6090              REWRITE_RULE[real_ge] CLOSED_HALFSPACE_IM_GE] THEN
6091     REWRITE_TAC[IN_INTER; IN_DIFF; IN_UNIV; IN_SING; IN_ELIM_THM] THEN
6092     SIMP_TAC[GSYM CONJ_ASSOC; REAL_LE_ANTISYM; TAUT `~(p /\ ~p)`] THEN
6093     REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
6094      [GEN_REWRITE_TAC (BINOP_CONV o LAND_CONV) [GSYM o_DEF] THEN
6095       SUBGOAL_THEN `(p:real->real^N) = (p o drop) o lift` SUBST1_TAC THENL
6096        [REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX]; ALL_TAC] THEN
6097       ONCE_REWRITE_TAC[GSYM o_ASSOC] THEN
6098       CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN CONJ_TAC THENL
6099        [REWRITE_TAC[o_DEF; GSYM CONTINUOUS_ON_CX_LIFT] THEN
6100         MP_TAC CONTINUOUS_ON_UPPERHALF_ARG THEN REWRITE_TAC[o_DEF] THEN
6101         MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_ON_SUBSET) THEN
6102         ASM SET_TAC[];
6103         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
6104           CONTINUOUS_ON_SUBSET)) THEN
6105         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_ELIM_THM] THEN
6106         REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP; o_THM; DROP_VEC] THEN
6107         SIMP_TAC[ARG; REAL_LT_IMP_LE];
6108         REWRITE_TAC[o_DEF; LIFT_SUB] THEN MATCH_MP_TAC CONTINUOUS_ON_SUB THEN
6109         REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
6110         GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [GSYM o_DEF] THEN
6111         REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
6112         REWRITE_TAC[CONTINUOUS_ON_CNJ; o_DEF; GSYM CONTINUOUS_ON_CX_LIFT] THEN
6113         MP_TAC CONTINUOUS_ON_UPPERHALF_ARG THEN REWRITE_TAC[o_DEF] THEN
6114         MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_ON_SUBSET) THEN
6115         SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_ELIM_THM; IN_DIFF] THEN
6116         SIMP_TAC[IN_SING; CNJ_EQ_0; IM_CNJ; REAL_NEG_GE0] THEN ASM SET_TAC[];
6117         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
6118           CONTINUOUS_ON_SUBSET)) THEN
6119         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_ELIM_THM] THEN
6120         REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP; o_THM; DROP_VEC] THEN
6121         X_GEN_TAC `z:complex` THEN STRIP_TAC THEN
6122         MP_TAC(SPEC `cnj z` ARG) THEN REAL_ARITH_TAC];
6123       REWRITE_TAC[GSYM ARG_EQ_0_PI; GSYM real; ARG_CNJ] THEN
6124       REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
6125       COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_SUB_SUB2; REAL_SUB_RZERO] THEN
6126       ASM_REWRITE_TAC[REAL_ARITH `&2 * x - x = x`]]]);;
6127
6128 let OPEN_ARG_LTT = prove
6129  (`!s t. &0 <= s /\ t <= &2 * pi ==> open {z | s < Arg z /\ Arg z < t}`,
6130   REPEAT STRIP_TAC THEN
6131   MP_TAC(ISPECL [`Cx o Arg`; `(:complex) DIFF {z | real z /\ &0 <= Re z}`;
6132                    `{z | Re(z) > s} INTER {z | Re(z) < t}`]
6133            CONTINUOUS_OPEN_PREIMAGE) THEN
6134   ASM_SIMP_TAC[OPEN_INTER; OPEN_HALFSPACE_RE_GT; OPEN_HALFSPACE_RE_LT] THEN
6135   ANTS_TAC THENL
6136    [CONJ_TAC THENL
6137      [MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
6138       REWRITE_TAC[IN_DIFF; IN_UNIV; IN_ELIM_THM; CONTINUOUS_AT_ARG];
6139       REWRITE_TAC[GSYM closed] THEN
6140       REWRITE_TAC[SET_RULE `{z | P z /\ Q z} = P INTER {z | Q z}`] THEN
6141       MATCH_MP_TAC CLOSED_INTER THEN
6142       REWRITE_TAC[CLOSED_REAL; GSYM real_ge; CLOSED_HALFSPACE_RE_GE]];
6143     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION] THEN
6144     ASM_SIMP_TAC[IN_DIFF; IN_INTER; IN_UNIV; IN_ELIM_THM; o_THM; RE_CX;
6145                  GSYM ARG_EQ_0] THEN
6146     ASM_REAL_ARITH_TAC]);;
6147
6148 let OPEN_ARG_GT = prove
6149  (`!t. open {z | t < Arg z}`,
6150   GEN_TAC THEN DISJ_CASES_TAC(REAL_ARITH `t < &0 \/ &0 <= t`) THENL
6151    [SUBGOAL_THEN `{z | t < Arg z} = (:complex)`
6152      (fun th -> SIMP_TAC[th; OPEN_UNIV]) THEN
6153     REWRITE_TAC[EXTENSION; IN_UNIV; IN_ELIM_THM] THEN
6154     MP_TAC ARG THEN MATCH_MP_TAC MONO_FORALL THEN ASM_REAL_ARITH_TAC;
6155     MP_TAC(ISPECL [`t:real`; `&2 * pi`] OPEN_ARG_LTT) THEN
6156     ASM_REWRITE_TAC[ARG; REAL_LE_REFL]]);;
6157
6158 let CLOSED_ARG_LE = prove
6159  (`!t. closed {z | Arg z <= t}`,
6160   REWRITE_TAC[closed; DIFF; IN_UNIV; IN_ELIM_THM] THEN
6161   REWRITE_TAC[REAL_NOT_LE; OPEN_ARG_GT]);;
6162
6163 (* ------------------------------------------------------------------------- *)
6164 (* Relation between Arg and arctangent in upper halfplane.                   *)
6165 (* ------------------------------------------------------------------------- *)
6166
6167 let ARG_ATAN_UPPERHALF = prove
6168  (`!z. &0 < Im z ==> Arg(z) = pi / &2 - atn(Re z / Im z)`,
6169   GEN_TAC THEN ASM_CASES_TAC `z = Cx(&0)` THEN
6170   ASM_REWRITE_TAC[IM_CX; REAL_LT_REFL] THEN DISCH_TAC THEN
6171   MATCH_MP_TAC ARG_UNIQUE THEN EXISTS_TAC `norm(z:complex)` THEN
6172   ASM_REWRITE_TAC[COMPLEX_NORM_NZ] THEN CONJ_TAC THENL
6173    [ALL_TAC; MP_TAC(ISPEC `Re z / Im z` ATN_BOUNDS) THEN REAL_ARITH_TAC] THEN
6174   REWRITE_TAC[CEXP_EULER; GSYM CX_SIN; GSYM CX_COS] THEN
6175   REWRITE_TAC[SIN_SUB; COS_SUB; SIN_PI2; COS_PI2] THEN
6176   REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID; SIN_ATN; COS_ATN] THEN
6177   SUBGOAL_THEN `sqrt(&1 + (Re z / Im z) pow 2) = norm(z) / Im z`
6178   SUBST1_TAC THENL
6179    [MATCH_MP_TAC SQRT_UNIQUE THEN
6180     ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE; REAL_LT_IMP_LE] THEN
6181     REWRITE_TAC[REAL_POW_DIV; COMPLEX_SQNORM] THEN
6182     UNDISCH_TAC `&0 < Im z` THEN CONV_TAC REAL_FIELD;
6183     REWRITE_TAC[REAL_ADD_LID; REAL_SUB_RZERO; real_div] THEN
6184     REWRITE_TAC[COMPLEX_EQ; RE_MUL_CX; IM_MUL_CX; RE_MUL_II; IM_MUL_II;
6185                 RE_ADD; IM_ADD; RE_CX; IM_CX] THEN
6186     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM COMPLEX_NORM_NZ]) THEN
6187     POP_ASSUM MP_TAC THEN CONV_TAC REAL_FIELD]);;
6188
6189 (* ------------------------------------------------------------------------- *)
6190 (* Real n'th roots. Regardless of whether n is odd or even, we totalize by   *)
6191 (* setting root_n(-x) = -root_n(x), which makes some convenient facts hold.  *)
6192 (* ------------------------------------------------------------------------- *)
6193
6194 let root = new_definition
6195  `root(n) x = real_sgn(x) * exp(log(abs x) / &n)`;;
6196
6197 let ROOT_0 = prove
6198  (`!n. root n (&0) = &0`,
6199   REWRITE_TAC[root; REAL_SGN_0; REAL_MUL_LZERO]);;
6200
6201 let ROOT_1 = prove
6202  (`!n. root n (&1) = &1`,
6203   REWRITE_TAC[root; REAL_ABS_NUM; LOG_1; real_div; REAL_MUL_LZERO] THEN
6204   REWRITE_TAC[real_sgn; REAL_EXP_0] THEN REAL_ARITH_TAC);;
6205
6206 let ROOT_2 = prove
6207  (`!x. root 2 x = sqrt x`,
6208   GEN_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC SQRT_UNIQUE_GEN THEN
6209   REWRITE_TAC[root; REAL_SGN_MUL; REAL_POW_MUL; REAL_SGN_REAL_SGN] THEN
6210   REWRITE_TAC[REAL_SGN_POW_2; GSYM REAL_SGN_POW] THEN
6211   SIMP_TAC[real_sgn; REAL_EXP_POS_LT; REAL_MUL_RID] THEN
6212   REWRITE_TAC[REAL_ARITH `(&0 < abs x <=> ~(x = &0)) /\ ~(abs x < &0)`] THEN
6213   ASM_CASES_TAC `x = &0` THEN
6214   ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_ABS_NUM; REAL_MUL_LID] THEN
6215   REWRITE_TAC[GSYM REAL_EXP_N; REAL_ARITH `&2 * x / &2 = x`] THEN
6216   ASM_SIMP_TAC[EXP_LOG; REAL_ARITH `&0 < abs x <=> ~(x = &0)`]);;
6217
6218 let ROOT_NEG = prove
6219  (`!n x. root n (--x) = --(root n x)`,
6220   REWRITE_TAC[root; REAL_SGN_NEG; REAL_ABS_NEG; REAL_MUL_LNEG]);;
6221
6222 let ROOT_WORKS = prove
6223  (`!n x. real_sgn(root n x) = real_sgn x /\
6224          (root n x) pow n = if n = 0 then &1
6225                             else real_sgn(x) pow n * abs x`,
6226   REWRITE_TAC[root; REAL_SGN_MUL; REAL_POW_MUL; GSYM REAL_EXP_N] THEN
6227   REPEAT GEN_TAC THEN COND_CASES_TAC THEN
6228   ASM_REWRITE_TAC[real_div; REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_INV_0;
6229                   REAL_EXP_0; REAL_MUL_RID; real_pow; REAL_SGN_REAL_SGN] THEN
6230   REWRITE_TAC[real_sgn; REAL_LT_01; REAL_MUL_RID] THEN
6231   ASM_SIMP_TAC[REAL_EXP_POS_LT; REAL_MUL_RID; GSYM REAL_ABS_NZ;
6232                GSYM real_div; REAL_DIV_LMUL; REAL_OF_NUM_EQ] THEN
6233   ASM_CASES_TAC `x = &0` THEN
6234   ASM_REWRITE_TAC[REAL_LT_REFL; REAL_POW_ZERO; REAL_MUL_LZERO] THEN
6235   ASM_SIMP_TAC[EXP_LOG; GSYM REAL_ABS_NZ]);;
6236
6237 let REAL_POW_ROOT = prove
6238  (`!n x. ODD n \/ ~(n = 0) /\ &0 <= x ==> (root n x) pow n = x`,
6239   REPEAT GEN_TAC THEN ASM_CASES_TAC `n = 0` THEN
6240   ASM_REWRITE_TAC[ARITH] THEN STRIP_TAC THEN ASM_REWRITE_TAC[ROOT_WORKS] THENL
6241    [FIRST_ASSUM(CHOOSE_THEN SUBST1_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
6242     REWRITE_TAC[ONCE_REWRITE_RULE[REAL_MUL_SYM] real_pow] THEN
6243     REWRITE_TAC[GSYM REAL_MUL_ASSOC; REAL_SGN_ABS] THEN
6244     REWRITE_TAC[GSYM REAL_POW_POW] THEN
6245     REWRITE_TAC[REWRITE_RULE[REAL_SGN_POW] REAL_SGN_POW_2] THEN
6246     REWRITE_TAC[real_sgn; GSYM REAL_ABS_NZ] THEN
6247     ASM_CASES_TAC `x = &0` THEN
6248     ASM_REWRITE_TAC[REAL_LT_REFL; REAL_POW_ONE] THEN ASM_REAL_ARITH_TAC;
6249     ASM_REWRITE_TAC[real_sgn; REAL_LT_LE] THEN
6250     ASM_CASES_TAC `x = &0` THEN
6251     ASM_REWRITE_TAC[REAL_POW_ZERO; REAL_POW_ONE] THEN
6252     ASM_REAL_ARITH_TAC]);;
6253
6254 let ROOT_POS_LT = prove
6255  (`!n x. &0 < x ==> &0 < root n x`,
6256   REPEAT STRIP_TAC THEN REWRITE_TAC[root] THEN
6257   MATCH_MP_TAC REAL_LT_MUL THEN
6258   ASM_REWRITE_TAC[REAL_EXP_POS_LT; REAL_SGN_INEQS]);;
6259
6260 let ROOT_POS_LE = prove
6261  (`!n x. &0 <= x ==> &0 <= root n x`,
6262   MESON_TAC[REAL_LE_LT; ROOT_POS_LT; ROOT_0; REAL_LT_REFL]);;
6263
6264 let ROOT_LT_0 = prove
6265  (`!n x. &0 < root n x <=> &0 < x`,
6266   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[ROOT_POS_LT] THEN
6267   REWRITE_TAC[GSYM REAL_NOT_LE] THEN
6268   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
6269   REWRITE_TAC[REAL_ARITH `x <= &0 <=> &0 <= --x`; GSYM ROOT_NEG] THEN
6270   REWRITE_TAC[ROOT_POS_LE]);;
6271
6272 let ROOT_LE_0 = prove
6273  (`!n x. &0 <= root n x <=> &0 <= x`,
6274   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[ROOT_POS_LE] THEN
6275   REWRITE_TAC[GSYM REAL_NOT_LT] THEN
6276   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
6277   REWRITE_TAC[REAL_ARITH `x < &0 <=> &0 < --x`; GSYM ROOT_NEG] THEN
6278   REWRITE_TAC[ROOT_POS_LT]);;
6279
6280 let ROOT_EQ_0 = prove
6281  (`!n x. root n x = &0 <=> x = &0`,
6282   REWRITE_TAC[root; REAL_ENTIRE; REAL_EXP_NZ; REAL_SGN_INEQS]);;
6283
6284 let REAL_ROOT_MUL = prove
6285  (`!n x y. root n (x * y) = root n x * root n y`,
6286   REPEAT GEN_TAC THEN
6287   ASM_CASES_TAC `x = &0` THEN ASM_REWRITE_TAC[REAL_MUL_LZERO; ROOT_0] THEN
6288   ASM_CASES_TAC `y = &0` THEN ASM_REWRITE_TAC[REAL_MUL_RZERO; ROOT_0] THEN
6289   REWRITE_TAC[root; REAL_SGN_MUL; REAL_ABS_MUL] THEN
6290   ASM_SIMP_TAC[LOG_MUL; GSYM REAL_ABS_NZ; real_div] THEN
6291   REWRITE_TAC[REAL_ADD_RDISTRIB; REAL_EXP_ADD] THEN
6292   REAL_ARITH_TAC);;
6293
6294 let REAL_ROOT_POW_GEN = prove
6295  (`!m n x y. root n (x pow m) = (root n x) pow m`,
6296   INDUCT_TAC THEN ASM_REWRITE_TAC[REAL_ROOT_MUL; ROOT_1; real_pow]);;
6297
6298 let REAL_ROOT_POW = prove
6299  (`!n x. ODD n \/ ~(n = 0) /\ &0 <= x ==> root n (x pow n) = x`,
6300   SIMP_TAC[REAL_ROOT_POW_GEN; REAL_POW_ROOT]);;
6301
6302 let ROOT_UNIQUE = prove
6303  (`!n x y. y pow n = x /\ (ODD n \/ ~(n = 0) /\ &0 <= y) ==> root n x = y`,
6304   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN ASSUME_TAC) THEN
6305   UNDISCH_THEN `(y:real) pow n = x` (SUBST_ALL_TAC o SYM) THEN
6306   MATCH_MP_TAC REAL_ROOT_POW THEN ASM_REWRITE_TAC[]);;
6307
6308 let REAL_ROOT_INV = prove
6309  (`!n x. root n (inv x) = inv(root n x)`,
6310   REPEAT GEN_TAC THEN REWRITE_TAC[root; REAL_SGN_INV; REAL_INV_SGN] THEN
6311   ASM_CASES_TAC `x = &0` THEN
6312   ASM_REWRITE_TAC[REAL_SGN_0; REAL_MUL_LZERO; REAL_INV_0] THEN
6313   REWRITE_TAC[REAL_INV_MUL; REAL_INV_SGN; REAL_ABS_INV] THEN
6314   ASM_SIMP_TAC[GSYM REAL_EXP_NEG; LOG_INV; GSYM REAL_ABS_NZ] THEN
6315   REWRITE_TAC[real_div; REAL_MUL_LNEG]);;
6316
6317 let REAL_ROOT_DIV = prove
6318  (`!n x y. root n (x / y) = root n x / root n y`,
6319   SIMP_TAC[real_div; REAL_ROOT_MUL; REAL_ROOT_INV]);;
6320
6321 let ROOT_MONO_LT = prove
6322  (`!n x y. ~(n = 0) /\ x < y ==> root n x < root n y`,
6323   GEN_TAC THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
6324   DISCH_TAC THEN
6325   SUBGOAL_THEN `!x y. &0 <= x /\ x < y ==> root n x < root n y`
6326   ASSUME_TAC THENL
6327    [REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_POW_LT2_REV THEN
6328     EXISTS_TAC `n:num` THEN ASM_REWRITE_TAC[ROOT_WORKS; ROOT_LE_0] THEN
6329     ASM_REWRITE_TAC[real_sgn] THEN REPEAT
6330      (COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_POW_ONE; REAL_POW_ZERO]) THEN
6331     ASM_REAL_ARITH_TAC;
6332     REPEAT STRIP_TAC THEN ASM_CASES_TAC `&0 <= x` THEN ASM_SIMP_TAC[] THEN
6333     ASM_CASES_TAC `&0 <= y` THENL
6334      [MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `&0` THEN
6335       ASM_REWRITE_TAC[GSYM REAL_NOT_LE; ROOT_LE_0];
6336       FIRST_X_ASSUM(MP_TAC o SPECL [`--y:real`; `--x:real`]) THEN
6337       REWRITE_TAC[ROOT_NEG] THEN ASM_REAL_ARITH_TAC]]);;
6338
6339 let ROOT_MONO_LE = prove
6340  (`!n x y. x <= y ==> root n x <= root n y`,
6341   REPEAT GEN_TAC THEN ASM_CASES_TAC `n = 0` THENL
6342    [ASM_REWRITE_TAC[root; real_div; REAL_INV_0; REAL_MUL_RZERO;
6343                     REAL_EXP_0; REAL_MUL_RID] THEN
6344     REWRITE_TAC[real_sgn] THEN ASM_REAL_ARITH_TAC;
6345     ASM_MESON_TAC[REAL_LE_LT; ROOT_0; ROOT_MONO_LT]]);;
6346
6347 let ROOT_MONO_LT_EQ = prove
6348  (`!n x y. ~(n = 0) ==> (root n x < root n y <=> x < y)`,
6349   MESON_TAC[ROOT_MONO_LT; REAL_NOT_LT; ROOT_MONO_LE]);;
6350
6351 let ROOT_MONO_LE_EQ = prove
6352  (`!n x y. ~(n = 0) ==> (root n x <= root n y <=> x <= y)`,
6353   MESON_TAC[ROOT_MONO_LT; REAL_NOT_LT; ROOT_MONO_LE]);;
6354
6355 let ROOT_INJ = prove
6356  (`!n x y. ~(n = 0) ==> (root n x = root n y <=> x = y)`,
6357   SIMP_TAC[GSYM REAL_LE_ANTISYM; ROOT_MONO_LE_EQ]);;
6358
6359 let REAL_ROOT_LE = prove
6360  (`!n x y. ~(n = 0) /\ &0 <= y
6361            ==> (root n x <= y <=> x <= y pow n)`,
6362   MESON_TAC[REAL_ROOT_POW; REAL_POW_LE; ROOT_MONO_LE_EQ]);;
6363
6364 let REAL_LE_ROOT = prove
6365  (`!n x y. ~(n = 0) /\ &0 <= x
6366            ==> (x <= root n y <=> x pow n <= y)`,
6367   MESON_TAC[REAL_ROOT_POW; REAL_POW_LE; ROOT_MONO_LE_EQ]);;
6368
6369 let LOG_ROOT = prove
6370  (`!n x. ~(n = 0) /\ &0 < x ==> log(root n x) = log x / &n`,
6371   SIMP_TAC[REAL_EQ_RDIV_EQ; REAL_OF_NUM_LT; LE_1] THEN
6372   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
6373   SIMP_TAC[GSYM LOG_POW; ROOT_POS_LT; REAL_POW_ROOT; REAL_LT_IMP_LE]);;
6374
6375 let ROOT_EXP_LOG = prove
6376  (`!n x. ~(n = 0) /\ &0 < x ==> root n x = exp(log x / &n)`,
6377   SIMP_TAC[root; real_sgn; real_abs; REAL_LT_IMP_LE; REAL_MUL_LID]);;
6378
6379 let ROOT_PRODUCT = prove
6380  (`!n f s. FINITE s ==> root n (product s f) = product s (\i. root n (f i))`,
6381   GEN_TAC THEN GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
6382   SIMP_TAC[PRODUCT_CLAUSES; REAL_ROOT_MUL; ROOT_1]);;
6383
6384 let SQRT_PRODUCT = prove
6385  (`!f s. FINITE s ==> sqrt(product s f) = product s (\i. sqrt(f i))`,
6386   GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
6387   SIMP_TAC[PRODUCT_CLAUSES; SQRT_MUL; SQRT_1]);;
6388
6389 (* ------------------------------------------------------------------------- *)
6390 (* Real power function. This involves a few arbitrary choices.               *)
6391 (*                                                                           *)
6392 (* The value of x^y is unarguable when x > 0.                                *)
6393 (*                                                                           *)
6394 (* We make 0^0 = 1 to agree with "pow", but otherwise 0^y = 0.               *)
6395 (*                                                                           *)
6396 (* There is a sensible real value for (-x)^(p/q) where q is odd and either   *)
6397 (* p is even [(-x)^y = x^y] or odd [(-x)^y = -x^y].                          *)
6398 (*                                                                           *)
6399 (* In all other cases, we return (-x)^y = -x^y. This is meaningless but at   *)
6400 (* least it covers half the cases above without another case split.          *)
6401 (*                                                                           *)
6402 (* As for laws of indices, we do have x^-y = 1/x^y. Of course we can't  have *)
6403 (* x^(yz) = x^y^z or x^(y+z) = x^y x^z since then (-1)^(1/2)^2 = -1.         *)
6404 (* ------------------------------------------------------------------------- *)
6405
6406 parse_as_infix("rpow",(24,"left"));;
6407
6408 let rpow = new_definition
6409   `x rpow y = if &0 < x then exp(y * log x)
6410                else if x = &0 then if y = &0 then &1 else &0
6411                else if ?m n. ODD(m) /\ ODD(n) /\ (abs y = &m / &n)
6412                     then --(exp(y * log(--x)))
6413                     else exp(y * log(--x))`;;
6414
6415 let RPOW_POW = prove
6416  (`!x n. x rpow &n = x pow n`,
6417   REPEAT GEN_TAC THEN REWRITE_TAC[rpow] THEN
6418   COND_CASES_TAC THEN ASM_SIMP_TAC[REAL_EXP_N; EXP_LOG] THEN
6419   COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_POW_ZERO; REAL_OF_NUM_EQ] THEN
6420   ASM_SIMP_TAC[EXP_LOG; REAL_ARITH `~(&0 < x) /\ ~(x = &0) ==> &0 < --x`] THEN
6421   REWRITE_TAC[REAL_POW_NEG; REAL_ABS_NUM] THEN
6422   SUBGOAL_THEN `(?p q. ODD(p) /\ ODD(q) /\ &n = &p / &q) <=> ODD n`
6423    (fun th -> SIMP_TAC[th; GSYM NOT_ODD; REAL_NEG_NEG; COND_ID]) THEN
6424   EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
6425    [REPEAT GEN_TAC THEN ASM_CASES_TAC `q = 0` THEN
6426     ASM_REWRITE_TAC[ARITH_ODD] THEN
6427     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6428     ASM_SIMP_TAC[REAL_OF_NUM_EQ; REAL_FIELD
6429      `~(q = &0) ==> (n = p / q <=> q * n = p)`] THEN
6430     REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_EQ] THEN
6431     ASM_MESON_TAC[ODD_MULT];
6432     DISCH_TAC THEN MAP_EVERY EXISTS_TAC [`n:num`; `1`] THEN
6433     ASM_REWRITE_TAC[REAL_DIV_1; ARITH_ODD]]);;
6434
6435 let RPOW_0 = prove
6436  (`!x. x rpow &0 = &1`,
6437   REWRITE_TAC[RPOW_POW; real_pow]);;
6438
6439 let RPOW_NEG = prove
6440  (`!x y. x rpow (--y) = inv(x rpow y)`,
6441   REPEAT GEN_TAC THEN REWRITE_TAC[rpow] THEN
6442   COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_MUL_LNEG; REAL_EXP_NEG] THEN
6443   COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_NEG_EQ_0] THENL
6444    [COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_INV_0; REAL_INV_1];
6445     REWRITE_TAC[REAL_ABS_NEG] THEN
6446     COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_INV_NEG]]);;
6447
6448 let RPOW_ZERO = prove
6449  (`!y. &0 rpow y = if y = &0 then &1 else &0`,
6450   REWRITE_TAC[rpow; REAL_LT_REFL]);;
6451
6452 let RPOW_POS_LT = prove
6453  (`!x y. &0 < x ==> &0 < x rpow y`,
6454   SIMP_TAC[rpow; REAL_EXP_POS_LT]);;
6455
6456 let RPOW_POS_LE = prove
6457  (`!x y. &0 <= x ==> &0 <= x rpow y`,
6458   REPEAT GEN_TAC THEN ASM_CASES_TAC `x = &0` THENL
6459    [ASM_REWRITE_TAC[RPOW_ZERO] THEN MESON_TAC[REAL_POS];
6460     ASM_SIMP_TAC[RPOW_POS_LT; REAL_LE_LT]]);;
6461
6462 let RPOW_LT2 = prove
6463  (`!x y z. &0 <= x /\ x < y /\ &0 < z ==> x rpow z < y rpow z`,
6464   REPEAT GEN_TAC THEN ASM_CASES_TAC `x = &0` THEN
6465   ASM_SIMP_TAC[RPOW_ZERO; REAL_LT_IMP_NZ; RPOW_POS_LT] THEN
6466   REPEAT STRIP_TAC THEN REWRITE_TAC[rpow] THEN
6467   ASM_CASES_TAC `&0 < x /\ &0 < y` THENL
6468    [ALL_TAC; MATCH_MP_TAC(TAUT `F ==> p`) THEN ASM_REAL_ARITH_TAC] THEN
6469   ASM_SIMP_TAC[REAL_EXP_MONO_LT; REAL_LT_LMUL_EQ] THEN
6470   MATCH_MP_TAC LOG_MONO_LT_IMP THEN ASM_REAL_ARITH_TAC);;
6471
6472 let RPOW_LE2 = prove
6473  (`!x y z. &0 <= x /\ x <= y /\ &0 <= z ==> x rpow z <= y rpow z`,
6474   REPEAT GEN_TAC THEN ASM_CASES_TAC `z = &0` THEN
6475   ASM_REWRITE_TAC[RPOW_POW; real_pow; REAL_LE_REFL] THEN
6476   ASM_CASES_TAC `x:real = y` THEN ASM_REWRITE_TAC[REAL_LE_REFL] THEN
6477   ASM_MESON_TAC[RPOW_LT2; REAL_LE_LT]);;
6478
6479 let REAL_ABS_RPOW = prove
6480  (`!x y. abs(x rpow y) = abs(x) rpow y`,
6481   REPEAT GEN_TAC THEN REWRITE_TAC[rpow] THEN
6482   ASM_CASES_TAC `x = &0` THEN ASM_REWRITE_TAC[REAL_ABS_NUM; REAL_LT_REFL] THENL
6483    [REAL_ARITH_TAC; ALL_TAC] THEN
6484   ASM_REWRITE_TAC[GSYM REAL_ABS_NZ; REAL_ABS_ZERO] THEN
6485   COND_CASES_TAC THEN
6486   ASM_SIMP_TAC[REAL_ABS_EXP; REAL_ARITH `&0 < x ==> abs x = x`] THEN
6487   COND_CASES_TAC THEN REWRITE_TAC[REAL_ABS_NEG; REAL_ABS_EXP] THEN
6488   AP_TERM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN ASM_REAL_ARITH_TAC);;
6489
6490 let RPOW_ONE = prove
6491  (`!z. &1 rpow z = &1`,
6492   REWRITE_TAC[rpow; REAL_LT_01; LOG_1; REAL_MUL_RZERO; REAL_EXP_0]);;
6493
6494 let RPOW_RPOW = prove
6495  (`!x y z. &0 <= x ==> x rpow y rpow z = x rpow (y * z)`,
6496   REPEAT GEN_TAC THEN REWRITE_TAC[REAL_LE_LT] THEN
6497   ASM_CASES_TAC `x = &0` THEN ASM_REWRITE_TAC[] THENL
6498    [ASM_REWRITE_TAC[RPOW_ZERO; REAL_ENTIRE] THEN
6499     ASM_CASES_TAC `y = &0` THEN ASM_REWRITE_TAC[RPOW_ZERO; RPOW_ONE];
6500     SIMP_TAC[rpow; REAL_EXP_POS_LT; LOG_EXP] THEN
6501     REWRITE_TAC[REAL_MUL_AC]]);;
6502
6503 let RPOW_LNEG = prove
6504  (`!x y. --x rpow y =
6505          if ?m n. ODD m /\ ODD n /\ abs y = &m / &n
6506          then --(x rpow y) else x rpow y`,
6507   REPEAT GEN_TAC THEN REWRITE_TAC[rpow] THEN
6508   ASM_CASES_TAC `x = &0` THEN
6509   ASM_REWRITE_TAC[REAL_NEG_0; REAL_ABS_NUM; REAL_LT_REFL] THENL
6510    [ASM_CASES_TAC `y = &0` THEN ASM_REWRITE_TAC[REAL_NEG_0; COND_ID] THEN
6511     REWRITE_TAC[REAL_ARITH `abs(&0) = m / n <=> m * inv n = &0`] THEN
6512     SIMP_TAC[REAL_ENTIRE; REAL_INV_EQ_0; REAL_OF_NUM_EQ] THEN MESON_TAC[ODD];
6513     ASM_SIMP_TAC[REAL_ARITH `~(x = &0) ==> (&0 < --x <=> ~(&0 < x))`] THEN
6514     ASM_REWRITE_TAC[REAL_NEG_EQ_0] THEN
6515     ASM_CASES_TAC `&0 < x` THEN ASM_REWRITE_TAC[REAL_NEG_NEG; COND_ID]]);;
6516
6517 let RPOW_EQ_0 = prove
6518  (`!x y. x rpow y = &0 <=> x = &0 /\ ~(y = &0)`,
6519   REPEAT GEN_TAC THEN REWRITE_TAC[rpow] THEN
6520   ASM_CASES_TAC `x = &0` THEN ASM_REWRITE_TAC[REAL_LT_REFL] THEN
6521   REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_NEG_EQ_0; REAL_EXP_NZ]) THEN
6522   REAL_ARITH_TAC);;
6523
6524 let RPOW_MUL = prove
6525  (`!x y z. (x * y) rpow z = x rpow z * y rpow z`,
6526   SUBGOAL_THEN
6527     `!x y z. &0 <= x /\ &0 <= y ==> (x * y) rpow z = x rpow z * y rpow z`
6528   ASSUME_TAC THENL
6529    [REPEAT GEN_TAC THEN REWRITE_TAC[REAL_LE_LT] THEN
6530     ASM_CASES_TAC `z = &0` THEN
6531     ASM_REWRITE_TAC[RPOW_POW; real_pow; REAL_MUL_LID] THEN
6532     ASM_CASES_TAC `x = &0` THEN ASM_REWRITE_TAC[REAL_MUL_LZERO; RPOW_ZERO] THEN
6533     ASM_CASES_TAC `y = &0` THEN ASM_REWRITE_TAC[REAL_MUL_RZERO; RPOW_ZERO] THEN
6534     SIMP_TAC[rpow; REAL_LT_MUL; LOG_MUL; REAL_ADD_LDISTRIB; REAL_EXP_ADD];
6535     REPEAT GEN_TAC THEN
6536     REPEAT_TCL DISJ_CASES_THEN (ANTE_RES_THEN (MP_TAC o SPEC `z:real`))
6537      (REAL_ARITH `&0 <= x /\ &0 <= y \/ &0 <= x /\ &0 <= --y \/
6538                   &0 <= --x /\ &0 <= y \/ &0 <= --x /\ &0 <= --y`) THEN
6539     REWRITE_TAC[RPOW_LNEG; REAL_MUL_RNEG; REAL_MUL_LNEG] THEN
6540     COND_CASES_TAC THEN
6541     ASM_REWRITE_TAC[REAL_MUL_RNEG; REAL_MUL_LNEG; REAL_EQ_NEG2]]);;
6542
6543 let RPOW_INV = prove
6544  (`!x y. inv(x) rpow y = inv(x rpow y)`,
6545   REPEAT GEN_TAC THEN REWRITE_TAC[rpow; REAL_LT_INV_EQ] THEN
6546   SIMP_TAC[LOG_INV; REAL_MUL_RNEG; REAL_EXP_NEG] THEN
6547   COND_CASES_TAC THEN REWRITE_TAC[] THEN
6548   REWRITE_TAC[REAL_INV_EQ_0] THEN
6549   REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_INV_1; REAL_INV_0]) THEN
6550   ASM_SIMP_TAC[GSYM REAL_INV_NEG; LOG_INV;
6551                REAL_ARITH `~(&0 < x) /\ ~(x = &0) ==> &0 < --x`] THEN
6552   REWRITE_TAC[REAL_MUL_RNEG; REAL_EXP_NEG; REAL_INV_NEG]);;
6553
6554 let REAL_INV_RPOW = prove
6555  (`!x y. inv(x rpow y) = inv(x) rpow y`,
6556   REWRITE_TAC[RPOW_INV]);;
6557
6558 let RPOW_DIV = prove
6559  (`!x y z. (x / y) rpow z = x rpow z / y rpow z`,
6560   REWRITE_TAC[real_div; RPOW_MUL; RPOW_INV]);;
6561
6562 let RPOW_PRODUCT = prove
6563  (`!s:A->bool x y.
6564       FINITE s ==> (product s x) rpow y = product s (\i. x i rpow y)`,
6565   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
6566   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
6567   ASM_SIMP_TAC[PRODUCT_CLAUSES; RPOW_MUL; RPOW_ONE]);;
6568
6569 let RPOW_ADD = prove
6570  (`!x y z. &0 < x ==> x rpow (y + z) = x rpow y * x rpow z`,
6571   REPEAT STRIP_TAC THEN
6572   ASM_REWRITE_TAC[rpow; REAL_ADD_RDISTRIB; REAL_EXP_ADD]);;
6573
6574 let RPOW_ADD_ALT = prove
6575  (`!x y z. &0 <= x /\ (x = &0 /\ y + z = &0 ==> y = &0 \/ z = &0)
6576            ==> x rpow (y + z) = x rpow y * x rpow z`,
6577   REPEAT GEN_TAC THEN
6578   ASM_CASES_TAC `x = &0` THEN ASM_SIMP_TAC[REAL_LE_LT; RPOW_ADD] THEN
6579   REWRITE_TAC[RPOW_ZERO] THEN
6580   ASM_CASES_TAC `y = &0` THEN
6581   ASM_REWRITE_TAC[REAL_MUL_LID; REAL_ADD_LID] THEN
6582   ASM_CASES_TAC `y + z = &0` THEN ASM_REWRITE_TAC[] THEN
6583   ASM_REAL_ARITH_TAC);;
6584
6585 let RPOW_SQRT = prove
6586  (`!x. &0 <= x ==> x rpow (&1 / &2) = sqrt x`,
6587   REPEAT STRIP_TAC THEN
6588   MATCH_MP_TAC(REAL_RING
6589    `x pow 2 = y pow 2 /\ (x + y = &0 ==> x = &0 /\ y = &0)
6590     ==> x = y`) THEN
6591   CONJ_TAC THENL
6592    [ASM_SIMP_TAC[SQRT_POW_2] THEN
6593     ASM_SIMP_TAC[GSYM RPOW_POW; RPOW_RPOW] THEN
6594     CONV_TAC REAL_RAT_REDUCE_CONV THEN
6595     REWRITE_TAC[RPOW_POW; REAL_POW_1];
6596     MATCH_MP_TAC(REAL_ARITH
6597      `&0 <= x /\ &0 <= y ==> x + y = &0 ==> x = &0 /\ y = &0`) THEN
6598     ASM_SIMP_TAC[SQRT_POS_LE; RPOW_POS_LE]]);;
6599
6600 let RPOW_MONO = prove
6601  (`!a b x. &1 <= x /\ a <= b ==> x rpow a <= x rpow b`,
6602   SIMP_TAC[rpow; REAL_ARITH `&1 <= x ==> &0 < x`] THEN
6603   SIMP_TAC[REAL_EXP_MONO_LE; LOG_POS; REAL_LE_RMUL]);;
6604
6605 let RPOW_MONO_INV = prove
6606  (`!a b x. &0 < x /\ x <= &1 /\ b <= a ==> x rpow a <= x rpow b`,
6607   REPEAT STRIP_TAC THEN
6608   GEN_REWRITE_TAC BINOP_CONV [GSYM REAL_INV_INV] THEN
6609   MATCH_MP_TAC REAL_LE_INV2 THEN
6610   ASM_SIMP_TAC[REAL_LT_INV_EQ; RPOW_POS_LT; GSYM RPOW_INV] THEN
6611   MATCH_MP_TAC RPOW_MONO THEN
6612   ASM_SIMP_TAC[REAL_INV_1_LE]);;
6613
6614 let RPOW_1_LE = prove
6615  (`!a x. &0 <= x /\ x <= &1 /\ &0 <= a ==> x rpow a <= &1`,
6616   REPEAT STRIP_TAC THEN  MATCH_MP_TAC REAL_LE_TRANS THEN
6617   EXISTS_TAC `&1 rpow a` THEN CONJ_TAC THENL
6618    [MATCH_MP_TAC RPOW_LE2 THEN ASM_REAL_ARITH_TAC;
6619     REWRITE_TAC[RPOW_ONE; REAL_LE_REFL]]);;
6620
6621 let REAL_ROOT_RPOW = prove
6622  (`!n x. ~(n = 0) /\ (&0 <= x \/ ODD n) ==> root n x = x rpow (inv(&n))`,
6623   REPEAT GEN_TAC THEN ASM_CASES_TAC `x = &0` THEN
6624   ASM_SIMP_TAC[ROOT_0; RPOW_ZERO; REAL_INV_EQ_0; REAL_OF_NUM_EQ] THEN
6625   ASM_CASES_TAC `&0 <= x` THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THENL
6626    [ASM_SIMP_TAC[ROOT_EXP_LOG; rpow; REAL_LT_LE] THEN AP_TERM_TAC THEN
6627     REAL_ARITH_TAC;
6628     ASM_REWRITE_TAC[rpow] THEN COND_CASES_TAC THENL
6629      [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
6630     REWRITE_TAC[REAL_ABS_INV; REAL_ABS_NUM] THEN
6631     REWRITE_TAC[REAL_ARITH `inv x = &1 / x`] THEN
6632     COND_CASES_TAC THENL [ALL_TAC; ASM_MESON_TAC[ARITH]] THEN
6633     MATCH_MP_TAC ROOT_UNIQUE THEN
6634     ASM_REWRITE_TAC[REAL_POW_NEG; GSYM REAL_EXP_N; GSYM NOT_ODD] THEN
6635     ASM_SIMP_TAC[REAL_OF_NUM_EQ; REAL_FIELD
6636       `~(n = &0) ==> n * &1 / n * x = x`] THEN
6637     ONCE_REWRITE_TAC[REAL_ARITH `--x:real = y <=> x = --y`] THEN
6638     MATCH_MP_TAC EXP_LOG THEN ASM_REAL_ARITH_TAC]);;
6639
6640 let LOG_RPOW = prove
6641  (`!x y. &0 < x ==> log(x rpow y) = y * log x`,
6642   SIMP_TAC[rpow; LOG_EXP]);;
6643
6644 let LOG_SQRT = prove
6645  (`!x. &0 < x ==> log(sqrt x) = log x / &2`,
6646   SIMP_TAC[GSYM RPOW_SQRT; LOG_RPOW; REAL_LT_IMP_LE] THEN
6647   REAL_ARITH_TAC);;
6648
6649 (* ------------------------------------------------------------------------- *)
6650 (* Formulation of loop homotopy in terms of maps out of S^1                  *)
6651 (* ------------------------------------------------------------------------- *)
6652
6653 let HOMOTOPIC_CIRCLEMAPS_IMP_HOMOTOPIC_LOOPS = prove
6654  (`!f:complex->real^N g s.
6655         homotopic_with (\h. T) (sphere(vec 0,&1),s) f g
6656         ==> homotopic_loops s (f o cexp o (\t. Cx(&2 * pi * drop t) * ii))
6657                               (g o cexp o (\t. Cx(&2 * pi * drop t) * ii))`,
6658   REWRITE_TAC[homotopic_loops; sphere; DIST_0] THEN REPEAT STRIP_TAC THEN
6659   MATCH_MP_TAC HOMOTOPIC_WITH_COMPOSE_CONTINUOUS_RIGHT THEN
6660   EXISTS_TAC `{z:complex | norm z = &1}` THEN
6661   REWRITE_TAC[pathstart; pathfinish; o_THM; DROP_VEC] THEN
6662   ONCE_REWRITE_TAC[REAL_ARITH `&2 * pi * n = &2 * n * pi`] THEN
6663   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; o_THM; IN_ELIM_THM] THEN
6664   ASM_SIMP_TAC[CEXP_INTEGER_2PI; INTEGER_CLOSED] THEN
6665   REWRITE_TAC[ONCE_REWRITE_RULE[COMPLEX_MUL_SYM] NORM_CEXP_II] THEN
6666   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN REWRITE_TAC[CONTINUOUS_ON_CEXP] THEN
6667   REWRITE_TAC[CX_MUL] THEN
6668   REPEAT(MATCH_MP_TAC CONTINUOUS_ON_COMPLEX_MUL THEN
6669          REWRITE_TAC[CONTINUOUS_ON_CONST]) THEN
6670   SIMP_TAC[CONTINUOUS_ON_CX_DROP; CONTINUOUS_ON_ID]);;
6671
6672 let HOMOTOPIC_LOOPS_IMP_HOMOTOPIC_CIRCLEMAPS = prove
6673  (`!p q s:real^N->bool.
6674         homotopic_loops s p q
6675         ==> homotopic_with (\h. T) (sphere(vec 0,&1),s)
6676                                    (p o (\z. lift(Arg z / (&2 * pi))))
6677                                    (q o (\z. lift(Arg z / (&2 * pi))))`,
6678  let ulemma = prove
6679    (`!s. s INTER (UNIV PCROSS {z | &0 <= Im z}) UNION
6680          s INTER (UNIV PCROSS {z | Im z <= &0}) = s`,
6681     REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_INTER; IN_UNION;
6682                  PASTECART_IN_PCROSS] THEN
6683     SET_TAC[REAL_LE_TOTAL]) in
6684   REPEAT GEN_TAC THEN REWRITE_TAC[homotopic_loops; sphere; DIST_0] THEN
6685   GEN_REWRITE_TAC LAND_CONV [homotopic_with] THEN
6686   SIMP_TAC[pathstart; pathfinish; LEFT_IMP_EXISTS_THM; HOMOTOPIC_WITH] THEN
6687   X_GEN_TAC `h:real^(1,1)finite_sum->real^N` THEN STRIP_TAC THEN
6688   EXISTS_TAC `\w. (h:real^(1,1)finite_sum->real^N)
6689                   (pastecart (fstcart w)
6690                              (lift(Arg(sndcart w) / (&2 * pi))))` THEN
6691   ASM_REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART; o_THM] THEN
6692   CONJ_TAC THENL
6693    [MATCH_MP_TAC CONTINUOUS_ON_EQ THEN
6694     EXISTS_TAC
6695      `(\z. if &0 <= Im(sndcart z)
6696            then h (pastecart (fstcart z) (lift(Arg(sndcart z) / (&2 * pi))))
6697            else h (pastecart (fstcart z)
6698                              (vec 1 - lift(Arg(cnj(sndcart z)) / (&2 * pi)))))
6699       :real^(1,2)finite_sum->real^N` THEN
6700     REWRITE_TAC[FORALL_IN_PCROSS; FSTCART_PASTECART; SNDCART_PASTECART] THEN
6701     REWRITE_TAC[IN_ELIM_THM] THEN CONJ_TAC THENL
6702      [MAP_EVERY X_GEN_TAC [`t:real^1`; `z:complex`] THEN STRIP_TAC THEN
6703       COND_CASES_TAC THEN ASM_REWRITE_TAC[ARG_CNJ] THEN
6704       COND_CASES_TAC THENL [ASM_MESON_TAC[real; REAL_LE_REFL]; ALL_TAC] THEN
6705       SIMP_TAC[PI_POS; LIFT_SUB; LIFT_NUM; REAL_FIELD
6706         `&0 < pi ==> (&2 * pi - z) / (&2 * pi) = &1 - z / (&2 * pi)`] THEN
6707       REWRITE_TAC[VECTOR_ARITH `a - (a - b):real^N = b`];
6708       GEN_REWRITE_TAC RAND_CONV [GSYM ulemma] THEN
6709       MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL THEN REWRITE_TAC[ulemma] THEN
6710       SIMP_TAC[CLOSED_IN_CLOSED_INTER; CLOSED_HALFSPACE_IM_LE; CLOSED_UNIV;
6711         CLOSED_PCROSS; REWRITE_RULE[real_ge] CLOSED_HALFSPACE_IM_GE] THEN
6712       REWRITE_TAC[FORALL_PASTECART; PASTECART_IN_PCROSS; IN_INTER; IN_DIFF;
6713        FSTCART_PASTECART; SNDCART_PASTECART; IN_UNIV; IN_SING; IN_ELIM_THM;
6714        GSYM CONJ_ASSOC; REAL_LE_ANTISYM; TAUT `~(p /\ ~p)`] THEN
6715       REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
6716        [ALL_TAC;
6717         REWRITE_TAC[GSYM ARG_EQ_0_PI; GSYM real; ARG_CNJ] THEN
6718         REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
6719         SIMP_TAC[REAL_ARITH `&2 * x - x = x`; COND_ID; GSYM LIFT_NUM; PI_POS;
6720          GSYM LIFT_SUB; REAL_FIELD
6721           `&0 < pi ==> &1 - pi / (&2 * pi) = pi / (&2 * pi)`] THEN
6722         COND_CASES_TAC THEN
6723         SIMP_TAC[REAL_SUB_RZERO; REAL_DIV_REFL; REAL_ENTIRE; REAL_OF_NUM_EQ;
6724                  ARITH_EQ; PI_NZ] THEN
6725         SIMP_TAC[real_div; REAL_MUL_LZERO; REAL_SUB_REFL; REAL_SUB_RZERO] THEN
6726         ASM_SIMP_TAC[LIFT_NUM]] THEN
6727       GEN_REWRITE_TAC (BINOP_CONV o LAND_CONV) [GSYM o_DEF] THEN
6728       CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN CONJ_TAC THENL
6729        [MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN
6730         SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART] THEN
6731         REWRITE_TAC[real_div; REWRITE_RULE[REAL_MUL_SYM] LIFT_CMUL] THEN
6732         MATCH_MP_TAC CONTINUOUS_ON_VMUL THEN
6733         GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
6734         REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
6735         SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_SNDCART] THEN
6736         REWRITE_TAC[o_DEF; GSYM CONTINUOUS_ON_CX_LIFT] THEN
6737         MP_TAC CONTINUOUS_ON_UPPERHALF_ARG THEN REWRITE_TAC[o_DEF] THEN
6738         MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_ON_SUBSET) THEN
6739         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; FORALL_PASTECART; IN_INTER;
6740                     PASTECART_IN_PCROSS; IN_ELIM_THM; SNDCART_PASTECART] THEN
6741         MAP_EVERY X_GEN_TAC [`t:real^1`; `z:complex`] THEN
6742         SIMP_TAC[IN_DIFF; IN_ELIM_THM; IN_SING] THEN
6743         ASM_CASES_TAC `z = Cx(&0)` THEN ASM_REWRITE_TAC[COMPLEX_NORM_0] THEN
6744         REWRITE_TAC[REAL_OF_NUM_EQ; ARITH_EQ];
6745         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
6746           CONTINUOUS_ON_SUBSET)) THEN
6747         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; FORALL_PASTECART; IN_INTER;
6748                     PASTECART_IN_PCROSS; IN_ELIM_THM; SNDCART_PASTECART;
6749                     FSTCART_PASTECART] THEN
6750         SIMP_TAC[IN_INTERVAL_1; LIFT_DROP; DROP_VEC] THEN
6751         SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ; PI_POS; REAL_MUL_LZERO;
6752              REAL_MUL_LID; REAL_ARITH `&0 < &2 * x <=> &0 < x`] THEN
6753         SIMP_TAC[ARG; REAL_LT_IMP_LE];
6754         MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN
6755         SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART] THEN
6756         MATCH_MP_TAC CONTINUOUS_ON_SUB THEN
6757         REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
6758         REWRITE_TAC[real_div; REWRITE_RULE[REAL_MUL_SYM] LIFT_CMUL] THEN
6759         MATCH_MP_TAC CONTINUOUS_ON_VMUL THEN
6760         GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
6761         REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
6762         GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [GSYM o_DEF] THEN
6763         SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_SNDCART; CONTINUOUS_ON_COMPOSE;
6764                  CONTINUOUS_ON_CNJ] THEN
6765         REWRITE_TAC[o_DEF; GSYM CONTINUOUS_ON_CX_LIFT] THEN
6766         MP_TAC CONTINUOUS_ON_UPPERHALF_ARG THEN REWRITE_TAC[o_DEF] THEN
6767         MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_ON_SUBSET) THEN
6768         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; FORALL_PASTECART; IN_INTER;
6769                     PASTECART_IN_PCROSS; IN_ELIM_THM; SNDCART_PASTECART] THEN
6770         MAP_EVERY X_GEN_TAC [`t:real^1`; `z:complex`] THEN
6771         SIMP_TAC[IN_DIFF; IN_ELIM_THM; IN_SING] THEN
6772         SIMP_TAC[IM_CNJ; REAL_NEG_GE0; CNJ_EQ_0] THEN
6773         ASM_CASES_TAC `z = Cx(&0)` THEN ASM_REWRITE_TAC[COMPLEX_NORM_0] THEN
6774         REWRITE_TAC[REAL_OF_NUM_EQ; ARITH_EQ];
6775         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
6776           CONTINUOUS_ON_SUBSET)) THEN
6777         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; FORALL_PASTECART; IN_INTER;
6778                     PASTECART_IN_PCROSS; IN_ELIM_THM; SNDCART_PASTECART;
6779                     FSTCART_PASTECART] THEN
6780         SIMP_TAC[IN_INTERVAL_1; DROP_SUB; DROP_VEC; LIFT_DROP] THEN
6781         REWRITE_TAC[REAL_ARITH `&0 <= &1 - x /\ &1 - x <= &1 <=>
6782                                 &0 <= x /\ x <= &1`] THEN
6783         SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ; PI_POS; REAL_MUL_LZERO;
6784              REAL_MUL_LID; REAL_ARITH `&0 < &2 * x <=> &0 < x`] THEN
6785         SIMP_TAC[ARG; REAL_LT_IMP_LE]]];
6786     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; FORALL_IN_PCROSS; IN_ELIM_THM] THEN
6787     REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART] THEN
6788     REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
6789      `IMAGE h s SUBSET t ==> y IN s ==> h y IN t`)) THEN
6790     ASM_REWRITE_TAC[PASTECART_IN_PCROSS; IN_INTERVAL_1; LIFT_DROP] THEN
6791     SIMP_TAC[DROP_VEC; REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ; PI_POS;
6792              REAL_ARITH `&0 < &2 * x <=> &0 < x`] THEN
6793     SIMP_TAC[REAL_MUL_LZERO; REAL_MUL_LID; ARG; REAL_LT_IMP_LE]]);;
6794
6795 let SIMPLY_CONNECTED_EQ_HOMOTOPIC_CIRCLEMAPS,
6796     SIMPLY_CONNECTED_EQ_CONTRACTIBLE_CIRCLEMAP =
6797  (CONJ_PAIR o prove)
6798  (`(!s:real^N->bool.
6799         simply_connected s <=>
6800         !f g:complex->real^N.
6801               f continuous_on sphere(vec 0,&1) /\
6802               IMAGE f (sphere(vec 0,&1)) SUBSET s /\
6803               g continuous_on sphere(vec 0,&1) /\
6804               IMAGE g (sphere(vec 0,&1)) SUBSET s
6805               ==> homotopic_with (\h. T) (sphere(vec 0,&1),s) f g) /\
6806    (!s:real^N->bool.
6807       simply_connected s <=>
6808       path_connected s /\
6809       !f:real^2->real^N.
6810               f continuous_on sphere(vec 0,&1) /\
6811               IMAGE f (sphere(vec 0,&1)) SUBSET s
6812               ==> ?a. homotopic_with (\h. T) (sphere(vec 0,&1),s) f (\x. a))`,
6813   REWRITE_TAC[AND_FORALL_THM] THEN GEN_TAC THEN MATCH_MP_TAC(TAUT
6814    `(p ==> q) /\ (q ==> r) /\ (r ==> p) ==> (p <=> q) /\ (p <=> r)`) THEN
6815   REPEAT CONJ_TAC THENL
6816    [REWRITE_TAC[simply_connected] THEN DISCH_TAC THEN
6817     MAP_EVERY X_GEN_TAC [`f:complex->real^N`; `g:complex->real^N`] THEN
6818     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
6819      [`(f:complex->real^N) o cexp o (\t. Cx(&2 * pi * drop t) * ii)`;
6820       `(g:complex->real^N) o cexp o (\t. Cx(&2 * pi * drop t) * ii)`]) THEN
6821     ONCE_REWRITE_TAC[TAUT `p1 /\ q1 /\ r1 /\ p2 /\ q2 /\ r2 <=>
6822                            (p1 /\ r1 /\ q1) /\ (p2 /\ r2 /\ q2)`] THEN
6823     REWRITE_TAC[GSYM HOMOTOPIC_LOOPS_REFL] THEN
6824     ASM_SIMP_TAC[HOMOTOPIC_CIRCLEMAPS_IMP_HOMOTOPIC_LOOPS;
6825                  HOMOTOPIC_WITH_REFL] THEN
6826     DISCH_THEN(MP_TAC o MATCH_MP HOMOTOPIC_LOOPS_IMP_HOMOTOPIC_CIRCLEMAPS) THEN
6827     MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ_ALT] HOMOTOPIC_WITH_EQ) THEN
6828     REWRITE_TAC[IN_SPHERE_0; LIFT_DROP; o_DEF] THEN X_GEN_TAC `z:complex` THEN
6829     REPEAT STRIP_TAC THEN AP_TERM_TAC THEN MP_TAC(SPEC `z:complex` ARG) THEN
6830     ASM_REWRITE_TAC[COMPLEX_MUL_LID] THEN
6831     DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN SIMP_TAC[PI_POS;
6832       REAL_FIELD `&0 < pi ==> &2 * pi * x / (&2 * pi) = x`] THEN
6833     ASM_MESON_TAC[COMPLEX_MUL_SYM];
6834     DISCH_TAC THEN CONJ_TAC THENL
6835      [REWRITE_TAC[PATH_CONNECTED_EQ_HOMOTOPIC_POINTS] THEN
6836       MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
6837       FIRST_X_ASSUM(MP_TAC o SPECL
6838        [`(\x. a):complex->real^N`; `(\x. b):complex->real^N`]) THEN
6839       REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
6840       ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN DISCH_THEN
6841        (MP_TAC o MATCH_MP HOMOTOPIC_CIRCLEMAPS_IMP_HOMOTOPIC_LOOPS) THEN
6842       REWRITE_TAC[o_DEF; LINEPATH_REFL];
6843       X_GEN_TAC `f:complex->real^N` THEN STRIP_TAC THEN
6844       EXISTS_TAC `f(Cx(&1)):real^N` THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
6845       ASM_REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
6846       RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; FORALL_IN_IMAGE; IN_SPHERE_0]) THEN
6847       REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_SPHERE_0] THEN
6848       REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
6849       REWRITE_TAC[COMPLEX_NORM_CX] THEN REAL_ARITH_TAC];
6850     STRIP_TAC THEN
6851     ASM_REWRITE_TAC[SIMPLY_CONNECTED_EQ_CONTRACTIBLE_LOOP_SOME] THEN
6852     X_GEN_TAC `p:real^1->real^N` THEN STRIP_TAC THEN
6853     FIRST_X_ASSUM(MP_TAC o SPEC
6854      `(p:real^1->real^N) o (\z. lift(Arg z / (&2 * pi)))`) THEN
6855     ANTS_TAC THENL
6856      [MP_TAC(ISPECL [`s:real^N->bool`; `p:real^1->real^N`]
6857         HOMOTOPIC_LOOPS_REFL) THEN
6858       ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o MATCH_MP
6859         HOMOTOPIC_LOOPS_IMP_HOMOTOPIC_CIRCLEMAPS) THEN
6860       SIMP_TAC[HOMOTOPIC_WITH_REFL];
6861       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
6862       STRIP_TAC THEN FIRST_ASSUM
6863        (MP_TAC o MATCH_MP HOMOTOPIC_CIRCLEMAPS_IMP_HOMOTOPIC_LOOPS) THEN
6864       FIRST_ASSUM(MP_TAC o MATCH_MP HOMOTOPIC_WITH_IMP_SUBSET) THEN
6865       REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_SPHERE_0; o_DEF] THEN
6866       DISCH_THEN(MP_TAC o SPEC `Cx(&1)` o CONJUNCT2) THEN
6867       REWRITE_TAC[COMPLEX_NORM_CX; REAL_ABS_NUM] THEN
6868       STRIP_TAC THEN ASM_REWRITE_TAC[LINEPATH_REFL] THEN
6869       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] HOMOTOPIC_LOOPS_TRANS) THEN
6870       MATCH_MP_TAC HOMOTOPIC_LOOPS_EQ THEN ASM_REWRITE_TAC[] THEN
6871       REWRITE_TAC[IN_INTERVAL_1; FORALL_LIFT; LIFT_DROP; DROP_VEC] THEN
6872       X_GEN_TAC `t:real` THEN STRIP_TAC THEN ASM_CASES_TAC `t = &1` THENL
6873        [ASM_REWRITE_TAC[REAL_ARITH `&2 * pi * &1 = &2 * &1 * pi`] THEN
6874         SIMP_TAC[CEXP_INTEGER_2PI; INTEGER_CLOSED; ARG_NUM] THEN
6875         REWRITE_TAC[real_div; REAL_MUL_LZERO; LIFT_NUM] THEN
6876         ASM_MESON_TAC[pathstart; pathfinish];
6877         AP_TERM_TAC THEN AP_TERM_TAC THEN SIMP_TAC[PI_POS; REAL_FIELD
6878          `&0 < pi ==> (t = x / (&2 * pi) <=> x = &2 * pi * t)`] THEN
6879         MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `Im(Cx (&2 * pi * t) * ii)` THEN
6880         CONJ_TAC THENL [MATCH_MP_TAC ARG_CEXP; ALL_TAC] THEN
6881         SIMP_TAC[IM_MUL_II; RE_CX; REAL_ARITH
6882           `a < &2 * pi <=> a < &2 * pi * &1`] THEN
6883         ASM_SIMP_TAC[REAL_LE_MUL; REAL_LT_LMUL_EQ; REAL_OF_NUM_LT; ARITH;
6884                      PI_POS; REAL_LT_IMP_LE; REAL_POS; REAL_LE_MUL] THEN
6885         ASM_REWRITE_TAC[REAL_LT_LE]]]]);;
6886
6887 let HOMOTOPY_EQUIVALENT_SIMPLE_CONNECTEDNESS = prove
6888  (`!s:real^M->bool t:real^N->bool.
6889         s homotopy_equivalent t
6890         ==> (simply_connected s <=> simply_connected t)`,
6891   REWRITE_TAC[SIMPLY_CONNECTED_EQ_HOMOTOPIC_CIRCLEMAPS] THEN
6892   REWRITE_TAC[HOMOTOPY_EQUIVALENT_HOMOTOPIC_TRIVIALITY]);;
6893
6894 (* ------------------------------------------------------------------------- *)
6895 (* Homeomorphism of simple closed curves to circles.                         *)
6896 (* ------------------------------------------------------------------------- *)
6897
6898 let HOMEOMORPHIC_SIMPLE_PATH_IMAGE_CIRCLE = prove
6899  (`!g:real^1->real^N a:real^2 r.
6900         simple_path g /\ pathfinish g = pathstart g /\ &0 < r
6901         ==> (path_image g) homeomorphic sphere(a,r)`,
6902   REPEAT STRIP_TAC THEN
6903   TRANS_TAC HOMEOMORPHIC_TRANS `sphere(vec 0:real^2,&1)` THEN
6904   ASM_SIMP_TAC[HOMEOMORPHIC_SPHERES; REAL_LT_01] THEN MP_TAC(ISPECL
6905    [`g:real^1->real^N`; `g:real^1->real^N`; `path_image(g:real^1->real^N)`]
6906    HOMOTOPIC_LOOPS_IMP_HOMOTOPIC_CIRCLEMAPS) THEN
6907   REWRITE_TAC[HOMOTOPIC_LOOPS_REFL; HOMOTOPIC_WITH_REFL; SUBSET_REFL] THEN
6908   ASM_SIMP_TAC[SIMPLE_PATH_IMP_PATH] THEN STRIP_TAC THEN
6909   ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN REWRITE_TAC[homeomorphic] THEN
6910   EXISTS_TAC `(g:real^1->real^N) o (\z. lift(Arg z / (&2 * pi)))` THEN
6911   MATCH_MP_TAC HOMEOMORPHISM_COMPACT THEN
6912   ASM_REWRITE_TAC[COMPACT_SPHERE] THEN CONJ_TAC THENL
6913    [MATCH_MP_TAC SUBSET_ANTISYM THEN ASM_REWRITE_TAC[] THEN
6914     REWRITE_TAC[SUBSET; path_image; FORALL_IN_IMAGE; IN_INTERVAL_1] THEN
6915     X_GEN_TAC `t:real^1` THEN REWRITE_TAC[DROP_VEC] THEN STRIP_TAC THEN
6916     REWRITE_TAC[IN_IMAGE; o_THM; IN_SPHERE_0] THEN
6917     ASM_CASES_TAC `t:real^1 = vec 1` THENL
6918      [EXISTS_TAC `Cx(&1)` THEN
6919       ASM_REWRITE_TAC[ARG_NUM; COMPLEX_NORM_CX; real_div; REAL_MUL_LZERO] THEN
6920       REWRITE_TAC[LIFT_NUM; REAL_ABS_NUM] THEN
6921       ASM_MESON_TAC[pathstart; pathfinish];
6922       EXISTS_TAC `cexp(ii * Cx(&2 * pi * drop t))` THEN
6923       REWRITE_TAC[NORM_CEXP_II] THEN AP_TERM_TAC THEN
6924       W(MP_TAC o PART_MATCH (lhand o rand) ARG_CEXP o
6925         lhand o rand o rand o snd) THEN
6926       REWRITE_TAC[IM_MUL_II; RE_CX] THEN ANTS_TAC THENL
6927        [ASM_SIMP_TAC[REAL_LE_MUL; PI_POS_LE; REAL_POS] THEN
6928         SIMP_TAC[REAL_ARITH `&2 * pi * x < &2 * pi <=> pi * x < pi * &1`;
6929                  REAL_LT_LMUL_EQ; PI_POS] THEN
6930         ASM_REWRITE_TAC[REAL_LT_LE] THEN
6931         ASM_REWRITE_TAC[GSYM LIFT_EQ; LIFT_DROP; LIFT_NUM];
6932         DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[GSYM DROP_EQ; LIFT_DROP] THEN
6933         MP_TAC PI_POS THEN CONV_TAC REAL_FIELD]];
6934     MAP_EVERY X_GEN_TAC [`w:complex`; `z:complex`] THEN
6935     REWRITE_TAC[IN_SPHERE_0] THEN STRIP_TAC THEN
6936     MAP_EVERY (SUBST1_TAC o last o CONJUNCTS o C SPEC ARG)
6937      [`w:complex`; `z:complex`] THEN
6938     FIRST_X_ASSUM(MP_TAC o SYM o SYM) THEN
6939     ASM_REWRITE_TAC[o_DEF; COMPLEX_MUL_LID] THEN DISCH_TAC THEN
6940     AP_TERM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
6941     MATCH_MP_TAC(REAL_FIELD
6942      `&0 < pi /\ x / (&2 * pi) = y / (&2 * pi) ==> x = y`) THEN
6943     REWRITE_TAC[PI_POS; GSYM LIFT_EQ] THEN
6944     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [simple_path]) THEN
6945     DISCH_THEN(MP_TAC  o SPECL
6946      [`lift(Arg w / (&2 * pi))`; `lift(Arg z / (&2 * pi))`] o CONJUNCT2) THEN
6947     ASM_REWRITE_TAC[GSYM LIFT_NUM; IN_INTERVAL_1; LIFT_DROP; LIFT_EQ] THEN
6948     ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ; PI_POS;
6949                  REAL_ARITH `&0 < &2 * x <=> &0 < x`;
6950                  REAL_FIELD `&0 < y ==> (x / y = &1 <=> x = y)`] THEN
6951     SIMP_TAC[REAL_MUL_LZERO; REAL_MUL_LID; ARG; REAL_LT_IMP_LE;
6952              REAL_LT_IMP_NE]]);;
6953
6954 let HOMEOMORPHIC_SIMPLE_PATH_IMAGES = prove
6955  (`!g:real^1->real^M h:real^1->real^N.
6956         simple_path g /\ pathfinish g = pathstart g /\
6957         simple_path h /\ pathfinish h = pathstart h
6958         ==> (path_image g) homeomorphic (path_image h)`,
6959   REPEAT STRIP_TAC THEN
6960   TRANS_TAC HOMEOMORPHIC_TRANS `sphere(vec 0:real^2,&1)` THEN
6961   CONJ_TAC THENL [ALL_TAC; ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM]] THEN
6962   MATCH_MP_TAC HOMEOMORPHIC_SIMPLE_PATH_IMAGE_CIRCLE THEN
6963   ASM_REWRITE_TAC[REAL_LT_01]);;
6964
6965 let ENR_PATH_IMAGE_SIMPLE_PATH = prove
6966  (`!g:real^1->real^N. simple_path g ==> ENR(path_image g)`,
6967   REPEAT STRIP_TAC THEN
6968   ASM_CASES_TAC `pathfinish g:real^N = pathstart g` THENL
6969    [MP_TAC(ISPECL [`g:real^1->real^N`; `vec 0:real^2`; `&1`]
6970         HOMEOMORPHIC_SIMPLE_PATH_IMAGE_CIRCLE) THEN
6971     ASM_REWRITE_TAC[REAL_LT_01] THEN
6972     DISCH_THEN(SUBST1_TAC o MATCH_MP HOMEOMORPHIC_ENRNESS) THEN
6973     REWRITE_TAC[ENR_SPHERE];
6974     REWRITE_TAC[ENR] THEN EXISTS_TAC `(:real^N)` THEN
6975     REWRITE_TAC[OPEN_UNIV] THEN
6976     MATCH_MP_TAC ABSOLUTE_RETRACT_PATH_IMAGE_ARC THEN
6977     ASM_REWRITE_TAC[ARC_SIMPLE_PATH; SUBSET_UNIV]]);;
6978
6979 let ANR_PATH_IMAGE_SIMPLE_PATH = prove
6980  (`!g:real^1->real^N. simple_path g ==> ANR(path_image g)`,
6981   SIMP_TAC[ENR_PATH_IMAGE_SIMPLE_PATH; ENR_IMP_ANR]);;