1 /* Complex math module */
3 /* much code borrowed from mathmodule.c */
10 /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
15 #define CHECK(x) if (errno != 0) ; \
16 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
19 #define CHECK(x) /* Don't know how to check */
23 #define M_PI (3.141592653589793239)
26 /* First, the C functions that do the real work */
29 static Py_complex c_1
= {1., 0.};
30 static Py_complex c_half
= {0.5, 0.};
31 static Py_complex c_i
= {0., 1.};
32 static Py_complex c_i2
= {0., 0.5};
34 static Py_complex c_mi
= {0., -1.};
35 static Py_complex c_pi2
= {M_PI
/2., 0.};
38 /* forward declarations */
39 staticforward Py_complex
c_log();
40 staticforward Py_complex
c_prodi();
41 staticforward Py_complex
c_sqrt();
44 static Py_complex
c_acos(x
)
47 return c_neg(c_prodi(c_log(c_sum(x
,c_prod(c_i
,
48 c_sqrt(c_diff(c_1
,c_prod(x
,x
))))))));
51 static Py_complex
c_acosh(x
)
54 return c_log(c_sum(x
,c_prod(c_i
,
55 c_sqrt(c_diff(c_1
,c_prod(x
,x
))))));
58 static Py_complex
c_asin(x
)
61 return c_neg(c_prodi(c_log(c_sum(c_prod(c_i
,x
),
62 c_sqrt(c_diff(c_1
,c_prod(x
,x
)))))));
65 static Py_complex
c_asinh(x
)
68 return c_neg(c_log(c_diff(c_sqrt(c_sum(c_1
,c_prod(x
,x
))),x
)));
71 static Py_complex
c_atan(x
)
74 return c_prod(c_i2
,c_log(c_quot(c_sum(c_i
,x
),c_diff(c_i
,x
))));
77 static Py_complex
c_atanh(x
)
80 return c_prod(c_half
,c_log(c_quot(c_sum(c_1
,x
),c_diff(c_1
,x
))));
83 static Py_complex
c_cos(x
)
87 r
.real
= cos(x
.real
)*cosh(x
.imag
);
88 r
.imag
= -sin(x
.real
)*sinh(x
.imag
);
92 static Py_complex
c_cosh(x
)
96 r
.real
= cos(x
.imag
)*cosh(x
.real
);
97 r
.imag
= sin(x
.imag
)*sinh(x
.real
);
101 static Py_complex
c_exp(x
)
105 double l
= exp(x
.real
);
106 r
.real
= l
*cos(x
.imag
);
107 r
.imag
= l
*sin(x
.imag
);
111 static Py_complex
c_log(x
)
115 double l
= hypot(x
.real
,x
.imag
);
116 r
.imag
= atan2(x
.imag
, x
.real
);
121 static Py_complex
c_log10(x
)
125 double l
= hypot(x
.real
,x
.imag
);
126 r
.imag
= atan2(x
.imag
, x
.real
)/log(10.);
131 static Py_complex
c_prodi(x
)
140 static Py_complex
c_sin(x
)
144 r
.real
= sin(x
.real
)*cosh(x
.imag
);
145 r
.imag
= cos(x
.real
)*sinh(x
.imag
);
149 static Py_complex
c_sinh(x
)
153 r
.real
= cos(x
.imag
)*sinh(x
.real
);
154 r
.imag
= sin(x
.imag
)*cosh(x
.real
);
158 static Py_complex
c_sqrt(x
)
163 if (x
.real
== 0. && x
.imag
== 0.)
166 s
= sqrt(0.5*(fabs(x
.real
) + hypot(x
.real
,x
.imag
)));
172 else if (x
.imag
>= 0.) {
184 static Py_complex
c_tan(x
)
188 double sr
,cr
,shi
,chi
;
200 r
.real
= (rs
*rc
+is
*ic
)/d
;
201 r
.imag
= (is
*rc
-rs
*ic
)/d
;
205 static Py_complex
c_tanh(x
)
209 double si
,ci
,shr
,chr
;
221 r
.real
= (rs
*rc
+is
*ic
)/d
;
222 r
.imag
= (is
*rc
-rs
*ic
)/d
;
227 /* And now the glue to make them available from Python: */
233 PyErr_SetString(PyExc_ValueError
, "math domain error");
234 else if (errno
== ERANGE
)
235 PyErr_SetString(PyExc_OverflowError
, "math range error");
236 else /* Unexpected math error */
237 PyErr_SetFromErrno(PyExc_ValueError
);
244 Py_complex (*func
) Py_FPROTO((Py_complex
));
247 if (!PyArg_ParseTuple(args
, "D", &x
))
250 PyFPE_START_PROTECT("complex function", return 0)
258 return PyComplex_FromCComplex(x
);
261 #define FUNC1(stubname, func) \
262 static PyObject * stubname(self, args) PyObject *self, *args; { \
263 return math_1(args, func); \
266 FUNC1(cmath_acos
, c_acos
)
267 FUNC1(cmath_acosh
, c_acosh
)
268 FUNC1(cmath_asin
, c_asin
)
269 FUNC1(cmath_asinh
, c_asinh
)
270 FUNC1(cmath_atan
, c_atan
)
271 FUNC1(cmath_atanh
, c_atanh
)
272 FUNC1(cmath_cos
, c_cos
)
273 FUNC1(cmath_cosh
, c_cosh
)
274 FUNC1(cmath_exp
, c_exp
)
275 FUNC1(cmath_log
, c_log
)
276 FUNC1(cmath_log10
, c_log10
)
277 FUNC1(cmath_sin
, c_sin
)
278 FUNC1(cmath_sinh
, c_sinh
)
279 FUNC1(cmath_sqrt
, c_sqrt
)
280 FUNC1(cmath_tan
, c_tan
)
281 FUNC1(cmath_tanh
, c_tanh
)
284 static PyMethodDef cmath_methods
[] = {
285 {"acos", cmath_acos
, 1},
286 {"acosh", cmath_acosh
, 1},
287 {"asin", cmath_asin
, 1},
288 {"asinh", cmath_asinh
, 1},
289 {"atan", cmath_atan
, 1},
290 {"atanh", cmath_atanh
, 1},
291 {"cos", cmath_cos
, 1},
292 {"cosh", cmath_cosh
, 1},
293 {"exp", cmath_exp
, 1},
294 {"log", cmath_log
, 1},
295 {"log10", cmath_log10
, 1},
296 {"sin", cmath_sin
, 1},
297 {"sinh", cmath_sinh
, 1},
298 {"sqrt", cmath_sqrt
, 1},
299 {"tan", cmath_tan
, 1},
300 {"tanh", cmath_tanh
, 1},
301 {NULL
, NULL
} /* sentinel */
309 m
= Py_InitModule("cmath", cmath_methods
);
310 d
= PyModule_GetDict(m
);
311 PyDict_SetItemString(d
, "pi",
312 v
= PyFloat_FromDouble(atan(1.0) * 4.0));
314 PyDict_SetItemString(d
, "e", v
= PyFloat_FromDouble(exp(1.0)));