1 (* ========================================================================= *)
2 (* Complex transcendental functions. *)
3 (* ========================================================================= *)
5 needs "Library/transc.ml";;
6 needs "Library/floor.ml";;
7 needs "Complex/complexnumbers.ml";;
9 unparse_as_infix "exp";;
10 remove_interface "exp";;
12 (* ------------------------------------------------------------------------- *)
13 (* Complex square roots. *)
14 (* ------------------------------------------------------------------------- *)
16 let csqrt = new_definition
17 `csqrt(z) = if Im(z) = &0 then
18 if &0 <= Re(z) then complex(sqrt(Re(z)),&0)
19 else complex(&0,sqrt(--Re(z)))
20 else complex(sqrt((norm(z) + Re(z)) / &2),
21 (Im(z) / abs(Im(z))) *
22 sqrt((norm(z) - Re(z)) / &2))`;;
24 let COMPLEX_NORM_GE_RE_IM = prove
25 (`!z. abs(Re(z)) <= norm(z) /\ abs(Im(z)) <= norm(z)`,
26 GEN_TAC THEN ONCE_REWRITE_TAC[GSYM POW_2_SQRT_ABS] THEN
27 REWRITE_TAC[complex_norm] THEN
29 MATCH_MP_TAC SQRT_MONO_LE THEN
30 ASM_SIMP_TAC[REAL_LE_ADDR; REAL_LE_ADDL; REAL_POW_2; REAL_LE_SQUARE]);;
33 (`!z. csqrt(z) pow 2 = z`,
34 GEN_TAC THEN REWRITE_TAC[COMPLEX_POW_2; csqrt] THEN COND_CASES_TAC THENL
36 ASM_REWRITE_TAC[CX_DEF; complex_mul; RE; IM; REAL_MUL_RZERO; REAL_MUL_LZERO;
37 REAL_SUB_LZERO; REAL_SUB_RZERO; REAL_ADD_LID; COMPLEX_EQ] THEN
38 REWRITE_TAC[REAL_NEG_EQ; GSYM REAL_POW_2] THEN
39 ASM_SIMP_TAC[SQRT_POW_2; REAL_ARITH `~(&0 <= x) ==> &0 <= --x`];
41 REWRITE_TAC[complex_mul; RE; IM] THEN
42 ONCE_REWRITE_TAC[REAL_ARITH
43 `(s * s - (i * s') * (i * s') = s * s - (i * i) * (s' * s')) /\
44 (s * i * s' + (i * s')* s = &2 * i * s * s')`] THEN
45 REWRITE_TAC[GSYM REAL_POW_2] THEN
46 SUBGOAL_THEN `&0 <= norm(z) + Re(z) /\ &0 <= norm(z) - Re(z)`
47 STRIP_ASSUME_TAC THENL
48 [MP_TAC(SPEC `z:complex` COMPLEX_NORM_GE_RE_IM) THEN REAL_ARITH_TAC;
50 ASM_SIMP_TAC[REAL_LE_DIV; REAL_POS; GSYM SQRT_MUL; SQRT_POW_2] THEN
51 REWRITE_TAC[COMPLEX_EQ; RE; IM] THEN CONJ_TAC THENL
52 [ASM_SIMP_TAC[REAL_POW_DIV; REAL_POW2_ABS;
53 REAL_POW_EQ_0; REAL_DIV_REFL] THEN
54 REWRITE_TAC[real_div; REAL_MUL_LID; GSYM REAL_SUB_RDISTRIB] THEN
55 REWRITE_TAC[REAL_ARITH `(m + r) - (m - r) = r * &2`] THEN
56 REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
57 REWRITE_TAC[REAL_MUL_RID]; ALL_TAC] THEN
58 REWRITE_TAC[real_div] THEN
59 ONCE_REWRITE_TAC[AC REAL_MUL_AC
60 `(a * b) * a' * b = (a * a') * (b * b:real)`] THEN
61 REWRITE_TAC[REAL_DIFFSQ] THEN
62 REWRITE_TAC[complex_norm; GSYM REAL_POW_2] THEN
63 SIMP_TAC[SQRT_POW_2; REAL_LE_ADD;
64 REWRITE_RULE[GSYM REAL_POW_2] REAL_LE_SQUARE] THEN
65 REWRITE_TAC[REAL_ADD_SUB; GSYM REAL_POW_MUL] THEN
66 REWRITE_TAC[POW_2_SQRT_ABS] THEN
67 REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_INV; REAL_ABS_NUM] THEN
68 ONCE_REWRITE_TAC[AC REAL_MUL_AC
69 `&2 * (i * a') * a * h = i * (&2 * h) * a * a'`] THEN
70 CONV_TAC REAL_RAT_REDUCE_CONV THEN
71 REWRITE_TAC[REAL_MUL_LID; GSYM real_div] THEN
72 ASM_SIMP_TAC[REAL_DIV_REFL; REAL_ABS_ZERO; REAL_MUL_RID]);;
74 (* ------------------------------------------------------------------------- *)
75 (* Complex exponential. *)
76 (* ------------------------------------------------------------------------- *)
78 let cexp = new_definition
79 `cexp z = Cx(exp(Re z)) * complex(cos(Im z),sin(Im z))`;;
82 (`!x. Cx(exp x) = cexp(Cx x)`,
83 REWRITE_TAC[cexp; CX_DEF; RE; IM; SIN_0; COS_0] THEN
84 REWRITE_TAC[GSYM CX_DEF; GSYM CX_MUL; REAL_MUL_RID]);;
87 (`cexp(Cx(&0)) = Cx(&1)`,
88 REWRITE_TAC[GSYM CX_CEXP; REAL_EXP_0]);;
91 (`!w z. cexp(w + z) = cexp(w) * cexp(z)`,
92 REWRITE_TAC[COMPLEX_EQ; cexp; complex_mul; complex_add; RE; IM; CX_DEF] THEN
93 REWRITE_TAC[REAL_EXP_ADD; SIN_ADD; COS_ADD] THEN CONV_TAC REAL_RING);;
96 (`!n z. cexp(Cx(&n) * z) = cexp(z) pow n`,
97 INDUCT_TAC THEN REWRITE_TAC[complex_pow] THEN
98 REWRITE_TAC[COMPLEX_MUL_LZERO; CEXP_0] THEN
99 REWRITE_TAC[GSYM REAL_OF_NUM_SUC; COMPLEX_ADD_RDISTRIB; CX_ADD] THEN
100 ASM_REWRITE_TAC[CEXP_ADD; COMPLEX_MUL_LID] THEN
101 REWRITE_TAC[COMPLEX_MUL_AC]);;
103 let CEXP_NONZERO = prove
104 (`!z. ~(cexp z = Cx(&0))`,
105 GEN_TAC THEN REWRITE_TAC[cexp; COMPLEX_ENTIRE; CX_INJ; REAL_EXP_NZ] THEN
106 REWRITE_TAC[CX_DEF; RE; IM; COMPLEX_EQ] THEN
107 MP_TAC(SPEC `Im z` SIN_CIRCLE) THEN CONV_TAC REAL_RING);;
109 let CEXP_NEG_LMUL = prove
110 (`!z. cexp(--z) * cexp(z) = Cx(&1)`,
111 REWRITE_TAC[GSYM CEXP_ADD; COMPLEX_ADD_LINV; CEXP_0]);;
113 let CEXP_NEG_RMUL = prove
114 (`!z. cexp(z) * cexp(--z) = Cx(&1)`,
115 REWRITE_TAC[GSYM CEXP_ADD; COMPLEX_ADD_RINV; CEXP_0]);;
118 (`!z. cexp(--z) = inv(cexp z)`,
119 MESON_TAC[CEXP_NEG_LMUL; COMPLEX_MUL_LINV_UNIQ]);;
122 (`!w z. cexp(w - z) = cexp(w) / cexp(z)`,
123 REWRITE_TAC[complex_sub; complex_div; CEXP_NEG; CEXP_ADD]);;
125 (* ------------------------------------------------------------------------- *)
126 (* Complex trig functions. *)
127 (* ------------------------------------------------------------------------- *)
129 let ccos = new_definition
130 `ccos z = (cexp(ii * z) + cexp(--ii * z)) / Cx(&2)`;;
132 let csin = new_definition
133 `csin z = (cexp(ii * z) - cexp(--ii * z)) / (Cx(&2) * ii)`;;
135 let CX_CSIN,CX_CCOS = (CONJ_PAIR o prove)
136 (`(!x. Cx(sin x) = csin(Cx x)) /\ (!x. Cx(cos x) = ccos(Cx x))`,
137 REWRITE_TAC[csin; ccos; cexp; CX_DEF; ii; RE; IM; complex_mul; complex_add;
138 REAL_MUL_RZERO; REAL_MUL_LZERO; REAL_SUB_RZERO;
139 REAL_MUL_LID; complex_neg; REAL_EXP_0; REAL_ADD_LID;
140 REAL_MUL_LNEG; REAL_NEG_0; REAL_ADD_RID; complex_sub;
141 SIN_NEG; COS_NEG; GSYM REAL_MUL_2; GSYM real_sub;
142 complex_div; REAL_SUB_REFL; complex_inv; REAL_SUB_RNEG] THEN
143 CONJ_TAC THEN GEN_TAC THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
144 REWRITE_TAC[REAL_MUL_RZERO] THEN
145 AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN CONV_TAC REAL_RING);;
148 (`csin(Cx(&0)) = Cx(&0)`,
149 REWRITE_TAC[GSYM CX_CSIN; SIN_0]);;
152 (`ccos(Cx(&0)) = Cx(&1)`,
153 REWRITE_TAC[GSYM CX_CCOS; COS_0]);;
155 let CSIN_CIRCLE = prove
156 (`!z. csin(z) pow 2 + ccos(z) pow 2 = Cx(&1)`,
157 GEN_TAC THEN REWRITE_TAC[csin; ccos] THEN
158 MP_TAC(SPEC `ii * z` CEXP_NEG_LMUL) THEN
159 MP_TAC COMPLEX_POW_II_2 THEN REWRITE_TAC[COMPLEX_MUL_LNEG] THEN
160 CONV_TAC COMPLEX_FIELD);;
163 (`!w z. csin(w + z) = csin(w) * ccos(z) + ccos(w) * csin(z)`,
165 REWRITE_TAC[csin; ccos; COMPLEX_ADD_LDISTRIB; CEXP_ADD] THEN
166 MP_TAC COMPLEX_POW_II_2 THEN CONV_TAC COMPLEX_FIELD);;
169 (`!w z. ccos(w + z) = ccos(w) * ccos(z) - csin(w) * csin(z)`,
171 REWRITE_TAC[csin; ccos; COMPLEX_ADD_LDISTRIB; CEXP_ADD] THEN
172 MP_TAC COMPLEX_POW_II_2 THEN CONV_TAC COMPLEX_FIELD);;
175 (`!z. csin(--z) = --(csin(z))`,
176 REWRITE_TAC[csin; COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG; COMPLEX_NEG_NEG] THEN
177 GEN_TAC THEN MP_TAC COMPLEX_POW_II_2 THEN
178 CONV_TAC COMPLEX_FIELD);;
181 (`!z. ccos(--z) = ccos(z)`,
182 REWRITE_TAC[ccos; COMPLEX_MUL_LNEG; COMPLEX_MUL_RNEG; COMPLEX_NEG_NEG] THEN
183 GEN_TAC THEN MP_TAC COMPLEX_POW_II_2 THEN
184 CONV_TAC COMPLEX_FIELD);;
186 let CSIN_DOUBLE = prove
187 (`!z. csin(Cx(&2) * z) = Cx(&2) * csin(z) * ccos(z)`,
188 REWRITE_TAC[COMPLEX_RING `Cx(&2) * x = x + x`; CSIN_ADD] THEN
189 CONV_TAC COMPLEX_RING);;
191 let CCOS_DOUBLE = prove
192 (`!z. ccos(Cx(&2) * z) = (ccos(z) pow 2) - (csin(z) pow 2)`,
193 REWRITE_TAC[COMPLEX_RING `Cx(&2) * x = x + x`; CCOS_ADD] THEN
194 CONV_TAC COMPLEX_RING);;
196 (* ------------------------------------------------------------------------- *)
197 (* Euler and de Moivre formulas. *)
198 (* ------------------------------------------------------------------------- *)
200 let CEXP_EULER = prove
201 (`!z. cexp(ii * z) = ccos(z) + ii * csin(z)`,
202 REWRITE_TAC[ccos; csin] THEN MP_TAC COMPLEX_POW_II_2 THEN
203 CONV_TAC COMPLEX_FIELD);;
206 (`!z n. (ccos z + ii * csin z) pow n =
207 ccos(Cx(&n) * z) + ii * csin(Cx(&n) * z)`,
208 REWRITE_TAC[GSYM CEXP_EULER; GSYM CEXP_MUL] THEN
209 REWRITE_TAC[COMPLEX_MUL_AC]);;
211 (* ------------------------------------------------------------------------- *)
213 (* ------------------------------------------------------------------------- *)
215 let EXISTS_COMPLEX = prove
216 (`!P. (?z. P (Re z) (Im z)) <=> ?x y. P x y`,
217 MESON_TAC[RE; IM; COMPLEX]);;
219 let COMPLEX_UNIMODULAR_POLAR = prove
220 (`!z. (norm z = &1) ==> ?x. z = complex(cos(x),sin(x))`,
222 DISCH_THEN(MP_TAC o C AP_THM `2` o AP_TERM `(pow):real->num->real`) THEN
223 REWRITE_TAC[complex_norm] THEN
224 SIMP_TAC[REAL_POW_2; REWRITE_RULE[REAL_POW_2] SQRT_POW_2;
225 REAL_LE_SQUARE; REAL_LE_ADD] THEN
226 REWRITE_TAC[GSYM REAL_POW_2; REAL_MUL_LID] THEN
227 DISCH_THEN(X_CHOOSE_TAC `t:real` o MATCH_MP CIRCLE_SINCOS) THEN
228 EXISTS_TAC `t:real` THEN ASM_REWRITE_TAC[COMPLEX_EQ; RE; IM]);;
230 let SIN_INTEGER_2PI = prove
231 (`!n. integer n ==> sin((&2 * pi) * n) = &0`,
232 REWRITE_TAC[integer; REAL_ARITH `abs(x) = &n <=> x = &n \/ x = -- &n`] THEN
233 REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[REAL_MUL_RNEG; SIN_NEG] THEN
234 REWRITE_TAC[GSYM REAL_MUL_ASSOC; SIN_DOUBLE] THEN
235 REWRITE_TAC[REAL_ARITH `pi * &n = &n * pi`; SIN_NPI] THEN
236 REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_NEG_0]);;
238 let COS_INTEGER_2PI = prove
239 (`!n. integer n ==> cos((&2 * pi) * n) = &1`,
240 REWRITE_TAC[integer; REAL_ARITH `abs(x) = &n <=> x = &n \/ x = -- &n`] THEN
241 REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[REAL_MUL_RNEG; COS_NEG] THEN
242 REWRITE_TAC[GSYM REAL_MUL_ASSOC; COS_DOUBLE] THEN
243 REWRITE_TAC[REAL_ARITH `pi * &n = &n * pi`; SIN_NPI; COS_NPI] THEN
244 REWRITE_TAC[REAL_POW_POW] THEN ONCE_REWRITE_TAC[MULT_SYM] THEN
245 REWRITE_TAC[GSYM REAL_POW_POW; REAL_POW_2] THEN
246 CONV_TAC REAL_RAT_REDUCE_CONV THEN
247 REWRITE_TAC[REAL_POW_ONE; REAL_SUB_RZERO]);;
249 let SINCOS_PRINCIPAL_VALUE = prove
250 (`!x. ?y. (--pi < y /\ y <= pi) /\ (sin(y) = sin(x) /\ cos(y) = cos(x))`,
251 GEN_TAC THEN EXISTS_TAC `pi - (&2 * pi) * frac((pi - x) / (&2 * pi))` THEN
253 [SIMP_TAC[REAL_ARITH `--p < p - x <=> x < (&2 * p) * &1`;
254 REAL_ARITH `p - x <= p <=> (&2 * p) * &0 <= x`;
255 REAL_LT_LMUL_EQ; REAL_LE_LMUL_EQ; REAL_LT_MUL;
256 PI_POS; REAL_OF_NUM_LT; ARITH; FLOOR_FRAC];
257 REWRITE_TAC[FRAC_FLOOR; REAL_SUB_LDISTRIB] THEN
258 SIMP_TAC[REAL_DIV_LMUL; REAL_ENTIRE; REAL_OF_NUM_EQ; ARITH; REAL_LT_IMP_NZ;
259 PI_POS; REAL_ARITH `a - (a - b - c):real = b + c`; SIN_ADD; COS_ADD] THEN
260 SIMP_TAC[FLOOR_FRAC; SIN_INTEGER_2PI; COS_INTEGER_2PI] THEN
261 CONV_TAC REAL_RING]);;
263 (* ------------------------------------------------------------------------- *)
264 (* Complex logarithms (the conventional principal value). *)
265 (* ------------------------------------------------------------------------- *)
267 let clog = new_definition
268 `clog z = @w. cexp(w) = z /\ --pi < Im(w) /\ Im(w) <= pi`;;
270 let CLOG_WORKS = prove
272 ==> cexp(clog z) = z /\ --pi < Im(clog z) /\ Im(clog z) <= pi`,
273 GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[clog] THEN CONV_TAC SELECT_CONV THEN
274 REWRITE_TAC[cexp; EXISTS_COMPLEX] THEN
275 EXISTS_TAC `ln(norm(z:complex))` THEN
276 SUBGOAL_THEN `exp(ln(norm(z:complex))) = norm(z)` SUBST1_TAC THENL
277 [ASM_MESON_TAC[REAL_EXP_LN; COMPLEX_NORM_NZ]; ALL_TAC] THEN
278 MP_TAC(SPEC `z / Cx(norm z)` COMPLEX_UNIMODULAR_POLAR) THEN ANTS_TAC THENL
279 [ASM_SIMP_TAC[COMPLEX_NORM_DIV; COMPLEX_NORM_CX] THEN
280 ASM_SIMP_TAC[COMPLEX_ABS_NORM; REAL_DIV_REFL; COMPLEX_NORM_ZERO];
282 DISCH_THEN(X_CHOOSE_THEN `x:real` STRIP_ASSUME_TAC) THEN
283 MP_TAC(SPEC `x:real` SINCOS_PRINCIPAL_VALUE) THEN
284 MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real` THEN
285 STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
286 ASM_MESON_TAC[CX_INJ; COMPLEX_DIV_LMUL; COMPLEX_NORM_ZERO]);;
288 let CEXP_CLOG = prove
289 (`!z. ~(z = Cx(&0)) ==> cexp(clog z) = z`,
290 SIMP_TAC[CLOG_WORKS]);;
292 (* ------------------------------------------------------------------------- *)
293 (* Unwinding number. *)
294 (* ------------------------------------------------------------------------- *)
296 let unwinding = new_definition
297 `unwinding(z) = (z - clog(cexp z)) / (Cx(&2 * pi) * ii)`;;
299 let COMPLEX_II_NZ = prove
301 MP_TAC COMPLEX_POW_II_2 THEN CONV_TAC COMPLEX_RING);;
303 let UNWINDING_2PI = prove
304 (`Cx(&2 * pi) * ii * unwinding(z) = z - clog(cexp z)`,
305 REWRITE_TAC[unwinding; COMPLEX_MUL_ASSOC] THEN
306 MATCH_MP_TAC COMPLEX_DIV_LMUL THEN
307 REWRITE_TAC[COMPLEX_ENTIRE; CX_INJ; COMPLEX_II_NZ] THEN
308 MP_TAC PI_POS THEN REAL_ARITH_TAC);;
310 (* ------------------------------------------------------------------------- *)
311 (* An example of how to get nice identities with unwinding number. *)
312 (* ------------------------------------------------------------------------- *)
315 (`!w z. ~(w = Cx(&0)) /\ ~(z = Cx(&0))
318 Cx(&2 * pi) * ii * unwinding(clog w + clog z)`,
319 REWRITE_TAC[UNWINDING_2PI;
320 COMPLEX_RING `w + z - ((w + z) - c) = c:complex`] THEN
321 ASM_SIMP_TAC[CEXP_ADD; CEXP_CLOG]);;