2 * Math routines for complex-number expression parser.
3 * In the routines, rv is variable holding 'return value'.
11 /*#include <libraries/mathieeedp.h>*/
13 /*extern struct Library * MathIeeeDoubTransBase;*/
15 extern const Complex zero
, eye
;
17 const Complex one
= {1.0, 0.0},
18 minuseye
= {0.0, -1.0};
20 int precision
= 12; /* number of decimal places to print */
21 /* (when they exist) */
23 void cprin(fp
, prefix
, suffix
, z
) /* print a complex number to file fp */
25 char *prefix
, *suffix
;
31 fprintf(fp
, "%.*g", precision
, z
.real
);
32 else if (z
.real
== 0.0)
33 fprintf(fp
, "%.*g i", precision
, z
.imag
);
35 fprintf(fp
, "%.*g %c %.*g i",
36 precision
, z
.real
, sign(z
.imag
), precision
, fabs(z
.imag
));
41 double Re(z
) /* real part of complex number */
47 double Im(z
) /* imaginary part of complex number */
53 #define marg(z) atan((z).imag / (z).real) /* macro arg */
55 double arg(z
) /* argument of complex number, in range (-PI,PI] */
58 return atan(z
.imag
/ z
.real
);
61 double norm(z
) /* norm of a complex number */
64 return sqr(z
.real
) + sqr(z
.imag
);
67 double _cabs(z
) /* absolute value of a complex number */
73 Complex
cadd(w
,z
) /* complex addition */
78 rv
.real
= w
.real
+ z
.real
;
79 rv
.imag
= w
.imag
+ z
.imag
;
84 Complex
csub(w
,z
) /* complex subtraction */
89 rv
.real
= w
.real
- z
.real
;
90 rv
.imag
= w
.imag
- z
.imag
;
95 Complex
cmul(w
,z
) /* complex multiplication */
100 rv
.real
= w
.real
*z
.real
- w
.imag
*z
.imag
;
101 rv
.imag
= w
.real
*z
.imag
+ w
.imag
*z
.real
;
106 Complex
cdiv(w
,z
) /* complex division */
110 double temp
= sqr(z
.real
)+sqr(z
.imag
);
113 execerror("division by zero", NULL
);
115 rv
.real
= (w
.real
*z
.real
+ w
.imag
*z
.imag
)/temp
;
116 rv
.imag
= (w
.imag
*z
.real
- w
.real
*z
.imag
)/temp
;
121 Complex
cneg(z
) /* complex negation */
130 Complex
csqr(z
) /* complex square, w^2 */
140 rv
.real
= sqr(z
.real
) - sqr(z
.imag
);
141 rv
.imag
= 2*z
.real
*z
.imag
;
146 Complex
csqrt(z
) /* complex square-root */
150 double temp
= _cabs(z
);
152 rv
.real
= Sqrt((temp
+ z
.real
)*0.5);
153 rv
.imag
= Sqrt((temp
- z
.real
)*0.5);
158 Complex
conj(z
) /* conjugate of w */
166 Complex
cexp(z
) /* complex exponential function e^z */
169 double temp
= exp(z
.real
);
175 z
.real
= temp
*cos(z
.imag
);
176 z
.imag
= temp
*sin(z
.imag
);
181 Complex
clog(z
) /* complex natural logarithm */
186 rv
.real
= Log(norm(z
))*0.5;
192 Complex
cpow(w
,z
) /* complex exponential, w^z */
195 return cexp(cmul(z
,clog(w
)));
198 Complex
csin(z
) /* complex sine */
203 z
.real
= sin(z
.real
);
210 rv
.real
= sin(z
.real
)*cosh(z
.imag
);
211 rv
.imag
= cos(z
.real
)*sinh(z
.imag
);
217 Complex
ccos(z
) /* complex cosine */
222 z
.real
= cos(z
.real
);
229 rv
.real
= cos(z
.real
)*cosh(z
.imag
);
230 rv
.imag
= -(sin(z
.real
)*sinh(z
.imag
));
236 Complex
ctan(z
) /* complex tangent */
241 z
.real
= tan(z
.real
);
245 return cdiv(csin(z
),ccos(z
));
248 Complex
casin(z
) /* complex arcsine - lazy version */
251 /* asin z = -ilog(iz + sqrt(1-z^2)) */
253 if (abs(z
.real
) <= 1.0 && z
.imag
== 0.0)
255 z
.real
= Asin(z
.real
);
259 return cmul(minuseye
,clog(cadd(cmul(eye
,z
),csqrt(csub(one
,csqr(z
))))));
262 Complex
cacos(z
) /* complex arccosine - lazy version */
265 /* acos z = -ilog(z + sqrt(z^2-1)) */
267 if (abs(z
.real
) <= 1.0 && z
.imag
== 0.0)
269 z
.real
= Acos(z
.real
);
273 return cmul(minuseye
,clog(cadd(z
,csqrt(csub(csqr(z
),one
)))));
276 Complex
catan(z
) /* complex arctangent - not so lazy version */
280 z
.real
= atan(z
.real
);
284 double temp
= norm(z
);
286 ctemp
.real
= ctemp
.imag
= 1.0 / (1.0 + temp
- 2.0 * z
.imag
);
287 ctemp
.real
*= 1.0 - temp
;
288 ctemp
.imag
*= -2.0*z
.real
;
290 z
.real
= -0.5*ctemp
.imag
;
291 z
.imag
= 0.5*ctemp
.real
;
297 Complex
csinh(z
) /* complex hyperbolic sine */
302 rv
.real
= cos(z
.imag
)*sinh(z
.real
);
303 rv
.imag
= sin(z
.imag
)*cosh(z
.real
);
308 Complex
ccosh(z
) /* complex hyperbolic cosine */
313 rv
.real
= cos(z
.imag
)*cosh(z
.real
);
314 rv
.imag
= sin(z
.imag
)*sinh(z
.real
);
319 Complex
ctanh(z
) /* complex tangent */
322 return cdiv(csinh(z
),ccosh(z
));