1 /* Complex math module */
3 /* much code borrowed from mathmodule.c */
8 #define M_PI (3.141592653589793239)
11 /* First, the C functions that do the real work */
14 static Py_complex c_one
= {1., 0.};
15 static Py_complex c_half
= {0.5, 0.};
16 static Py_complex c_i
= {0., 1.};
17 static Py_complex c_halfi
= {0., 0.5};
19 /* forward declarations */
20 static Py_complex
c_log(Py_complex
);
21 static Py_complex
c_prodi(Py_complex
);
22 static Py_complex
c_sqrt(Py_complex
);
23 static PyObject
* math_error(void);
29 return c_neg(c_prodi(c_log(c_sum(x
,c_prod(c_i
,
30 c_sqrt(c_diff(c_one
,c_prod(x
,x
))))))));
33 PyDoc_STRVAR(c_acos_doc
,
36 "Return the arc cosine of x.");
44 z
= c_log(c_prod(z
, c_sum(c_sqrt(c_sum(x
,c_one
)),
45 c_sqrt(c_diff(x
,c_one
)))));
49 PyDoc_STRVAR(c_acosh_doc
,
52 "Return the hyperbolic arccosine of x.");
58 /* -i * log[(sqrt(1-x**2) + i*x] */
59 const Py_complex squared
= c_prod(x
, x
);
60 const Py_complex sqrt_1_minus_x_sq
= c_sqrt(c_diff(c_one
, squared
));
61 return c_neg(c_prodi(c_log(
62 c_sum(sqrt_1_minus_x_sq
, c_prodi(x
))
66 PyDoc_STRVAR(c_asin_doc
,
69 "Return the arc sine of x.");
77 z
= c_log(c_prod(z
, c_sum(c_sqrt(c_sum(x
, c_i
)),
78 c_sqrt(c_diff(x
, c_i
)))));
82 PyDoc_STRVAR(c_asinh_doc
,
85 "Return the hyperbolic arc sine of x.");
91 return c_prod(c_halfi
,c_log(c_quot(c_sum(c_i
,x
),c_diff(c_i
,x
))));
94 PyDoc_STRVAR(c_atan_doc
,
97 "Return the arc tangent of x.");
101 c_atanh(Py_complex x
)
103 return c_prod(c_half
,c_log(c_quot(c_sum(c_one
,x
),c_diff(c_one
,x
))));
106 PyDoc_STRVAR(c_atanh_doc
,
109 "Return the hyperbolic arc tangent of x.");
116 r
.real
= cos(x
.real
)*cosh(x
.imag
);
117 r
.imag
= -sin(x
.real
)*sinh(x
.imag
);
121 PyDoc_STRVAR(c_cos_doc
,
124 "Return the cosine of x.");
131 r
.real
= cos(x
.imag
)*cosh(x
.real
);
132 r
.imag
= sin(x
.imag
)*sinh(x
.real
);
136 PyDoc_STRVAR(c_cosh_doc
,
139 "Return the hyperbolic cosine of x.");
146 double l
= exp(x
.real
);
147 r
.real
= l
*cos(x
.imag
);
148 r
.imag
= l
*sin(x
.imag
);
152 PyDoc_STRVAR(c_exp_doc
,
155 "Return the exponential value e**x.");
162 double l
= hypot(x
.real
,x
.imag
);
163 r
.imag
= atan2(x
.imag
, x
.real
);
170 c_log10(Py_complex x
)
173 double l
= hypot(x
.real
,x
.imag
);
174 r
.imag
= atan2(x
.imag
, x
.real
)/log(10.);
179 PyDoc_STRVAR(c_log10_doc
,
182 "Return the base-10 logarithm of x.");
185 /* internal function not available from Python */
187 c_prodi(Py_complex x
)
200 r
.real
= sin(x
.real
) * cosh(x
.imag
);
201 r
.imag
= cos(x
.real
) * sinh(x
.imag
);
205 PyDoc_STRVAR(c_sin_doc
,
208 "Return the sine of x.");
215 r
.real
= cos(x
.imag
) * sinh(x
.real
);
216 r
.imag
= sin(x
.imag
) * cosh(x
.real
);
220 PyDoc_STRVAR(c_sinh_doc
,
223 "Return the hyperbolic sine of x.");
231 if (x
.real
== 0. && x
.imag
== 0.)
234 s
= sqrt(0.5*(fabs(x
.real
) + hypot(x
.real
,x
.imag
)));
240 else if (x
.imag
>= 0.) {
252 PyDoc_STRVAR(c_sqrt_doc
,
255 "Return the square root of x.");
262 double sr
,cr
,shi
,chi
;
274 r
.real
= (rs
*rc
+ is
*ic
) / d
;
275 r
.imag
= (is
*rc
- rs
*ic
) / d
;
279 PyDoc_STRVAR(c_tan_doc
,
282 "Return the tangent of x.");
289 double si
,ci
,shr
,chr
;
301 r
.real
= (rs
*rc
+ is
*ic
) / d
;
302 r
.imag
= (is
*rc
- rs
*ic
) / d
;
306 PyDoc_STRVAR(c_tanh_doc
,
309 "Return the hyperbolic tangent of x.");
312 cmath_log(PyObject
*self
, PyObject
*args
)
317 if (!PyArg_ParseTuple(args
, "D|D", &x
, &y
))
321 PyFPE_START_PROTECT("complex function", return 0)
323 if (PyTuple_GET_SIZE(args
) == 2)
324 x
= c_quot(x
, c_log(y
));
328 Py_ADJUST_ERANGE2(x
.real
, x
.imag
);
329 return PyComplex_FromCComplex(x
);
332 PyDoc_STRVAR(cmath_log_doc
,
333 "log(x[, base]) -> the logarithm of x to the given base.\n\
334 If the base not specified, returns the natural logarithm (base e) of x.");
337 /* And now the glue to make them available from Python: */
343 PyErr_SetString(PyExc_ValueError
, "math domain error");
344 else if (errno
== ERANGE
)
345 PyErr_SetString(PyExc_OverflowError
, "math range error");
346 else /* Unexpected math error */
347 PyErr_SetFromErrno(PyExc_ValueError
);
352 math_1(PyObject
*args
, Py_complex (*func
)(Py_complex
))
355 if (!PyArg_ParseTuple(args
, "D", &x
))
358 PyFPE_START_PROTECT("complex function", return 0)
361 Py_ADJUST_ERANGE2(x
.real
, x
.imag
);
365 return PyComplex_FromCComplex(x
);
368 #define FUNC1(stubname, func) \
369 static PyObject * stubname(PyObject *self, PyObject *args) { \
370 return math_1(args, func); \
373 FUNC1(cmath_acos
, c_acos
)
374 FUNC1(cmath_acosh
, c_acosh
)
375 FUNC1(cmath_asin
, c_asin
)
376 FUNC1(cmath_asinh
, c_asinh
)
377 FUNC1(cmath_atan
, c_atan
)
378 FUNC1(cmath_atanh
, c_atanh
)
379 FUNC1(cmath_cos
, c_cos
)
380 FUNC1(cmath_cosh
, c_cosh
)
381 FUNC1(cmath_exp
, c_exp
)
382 FUNC1(cmath_log10
, c_log10
)
383 FUNC1(cmath_sin
, c_sin
)
384 FUNC1(cmath_sinh
, c_sinh
)
385 FUNC1(cmath_sqrt
, c_sqrt
)
386 FUNC1(cmath_tan
, c_tan
)
387 FUNC1(cmath_tanh
, c_tanh
)
390 PyDoc_STRVAR(module_doc
,
391 "This module is always available. It provides access to mathematical\n"
392 "functions for complex numbers.");
394 static PyMethodDef cmath_methods
[] = {
395 {"acos", cmath_acos
, METH_VARARGS
, c_acos_doc
},
396 {"acosh", cmath_acosh
, METH_VARARGS
, c_acosh_doc
},
397 {"asin", cmath_asin
, METH_VARARGS
, c_asin_doc
},
398 {"asinh", cmath_asinh
, METH_VARARGS
, c_asinh_doc
},
399 {"atan", cmath_atan
, METH_VARARGS
, c_atan_doc
},
400 {"atanh", cmath_atanh
, METH_VARARGS
, c_atanh_doc
},
401 {"cos", cmath_cos
, METH_VARARGS
, c_cos_doc
},
402 {"cosh", cmath_cosh
, METH_VARARGS
, c_cosh_doc
},
403 {"exp", cmath_exp
, METH_VARARGS
, c_exp_doc
},
404 {"log", cmath_log
, METH_VARARGS
, cmath_log_doc
},
405 {"log10", cmath_log10
, METH_VARARGS
, c_log10_doc
},
406 {"sin", cmath_sin
, METH_VARARGS
, c_sin_doc
},
407 {"sinh", cmath_sinh
, METH_VARARGS
, c_sinh_doc
},
408 {"sqrt", cmath_sqrt
, METH_VARARGS
, c_sqrt_doc
},
409 {"tan", cmath_tan
, METH_VARARGS
, c_tan_doc
},
410 {"tanh", cmath_tanh
, METH_VARARGS
, c_tanh_doc
},
411 {NULL
, NULL
} /* sentinel */
419 m
= Py_InitModule3("cmath", cmath_methods
, module_doc
);
421 PyModule_AddObject(m
, "pi",
422 PyFloat_FromDouble(atan(1.0) * 4.0));
423 PyModule_AddObject(m
, "e", PyFloat_FromDouble(exp(1.0)));