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 char c_acos_doc
[] =
54 Return the arc cosine of x.";
57 static Py_complex
c_acosh(x
)
60 return c_log(c_sum(x
,c_prod(c_i
,
61 c_sqrt(c_diff(c_1
,c_prod(x
,x
))))));
64 static char c_acosh_doc
[] =
67 Return the hyperbolic cosine of x.";
70 static Py_complex
c_asin(x
)
73 return c_neg(c_prodi(c_log(c_sum(c_prod(c_i
,x
),
74 c_sqrt(c_diff(c_1
,c_prod(x
,x
)))))));
77 static char c_asin_doc
[] =
80 Return the arc sine of x.";
83 static Py_complex
c_asinh(x
)
86 /* Break up long expression for WATCOM */
88 z
= c_sum(c_1
,c_prod(x
,x
));
89 z
= c_diff(c_sqrt(z
),x
);
90 return c_neg(c_log(z
));
93 static char c_asinh_doc
[] =
96 Return the hyperbolic arc sine of x.";
99 static Py_complex
c_atan(x
)
102 return c_prod(c_i2
,c_log(c_quot(c_sum(c_i
,x
),c_diff(c_i
,x
))));
105 static char c_atan_doc
[] =
108 Return the arc tangent of x.";
111 static Py_complex
c_atanh(x
)
114 return c_prod(c_half
,c_log(c_quot(c_sum(c_1
,x
),c_diff(c_1
,x
))));
117 static char c_atanh_doc
[] =
120 Return the hyperbolic arc tangent of x.";
123 static Py_complex
c_cos(x
)
127 r
.real
= cos(x
.real
)*cosh(x
.imag
);
128 r
.imag
= -sin(x
.real
)*sinh(x
.imag
);
132 static char c_cos_doc
[] =
135 Return the cosine of x.";
138 static Py_complex
c_cosh(x
)
142 r
.real
= cos(x
.imag
)*cosh(x
.real
);
143 r
.imag
= sin(x
.imag
)*sinh(x
.real
);
147 static char c_cosh_doc
[] =
150 Return the hyperbolic cosine of x.";
153 static Py_complex
c_exp(x
)
157 double l
= exp(x
.real
);
158 r
.real
= l
*cos(x
.imag
);
159 r
.imag
= l
*sin(x
.imag
);
163 static char c_exp_doc
[] =
166 Return the exponential value e**x.";
169 static Py_complex
c_log(x
)
173 double l
= hypot(x
.real
,x
.imag
);
174 r
.imag
= atan2(x
.imag
, x
.real
);
179 static char c_log_doc
[] =
182 Return the natural logarithm of x.";
185 static Py_complex
c_log10(x
)
189 double l
= hypot(x
.real
,x
.imag
);
190 r
.imag
= atan2(x
.imag
, x
.real
)/log(10.);
195 static char c_log10_doc
[] =
198 Return the base-10 logarithm of x.";
201 /* internal function not available from Python */
202 static Py_complex
c_prodi(x
)
212 static Py_complex
c_sin(x
)
216 r
.real
= sin(x
.real
)*cosh(x
.imag
);
217 r
.imag
= cos(x
.real
)*sinh(x
.imag
);
221 static char c_sin_doc
[] =
224 Return the sine of x.";
227 static Py_complex
c_sinh(x
)
231 r
.real
= cos(x
.imag
)*sinh(x
.real
);
232 r
.imag
= sin(x
.imag
)*cosh(x
.real
);
236 static char c_sinh_doc
[] =
239 Return the hyperbolic sine of x.";
242 static Py_complex
c_sqrt(x
)
247 if (x
.real
== 0. && x
.imag
== 0.)
250 s
= sqrt(0.5*(fabs(x
.real
) + hypot(x
.real
,x
.imag
)));
256 else if (x
.imag
>= 0.) {
268 static char c_sqrt_doc
[] =
271 Return the square root of x.";
274 static Py_complex
c_tan(x
)
278 double sr
,cr
,shi
,chi
;
290 r
.real
= (rs
*rc
+is
*ic
)/d
;
291 r
.imag
= (is
*rc
-rs
*ic
)/d
;
295 static char c_tan_doc
[] =
298 Return the tangent of x.";
301 static Py_complex
c_tanh(x
)
305 double si
,ci
,shr
,chr
;
317 r
.real
= (rs
*rc
+is
*ic
)/d
;
318 r
.imag
= (is
*rc
-rs
*ic
)/d
;
322 static char c_tanh_doc
[] =
325 Return the hyperbolic tangent of x.";
328 /* And now the glue to make them available from Python: */
334 PyErr_SetString(PyExc_ValueError
, "math domain error");
335 else if (errno
== ERANGE
)
336 PyErr_SetString(PyExc_OverflowError
, "math range error");
337 else /* Unexpected math error */
338 PyErr_SetFromErrno(PyExc_ValueError
);
345 Py_complex (*func
) Py_FPROTO((Py_complex
));
348 if (!PyArg_ParseTuple(args
, "D", &x
))
351 PyFPE_START_PROTECT("complex function", return 0)
359 return PyComplex_FromCComplex(x
);
362 #define FUNC1(stubname, func) \
363 static PyObject * stubname(self, args) PyObject *self, *args; { \
364 return math_1(args, func); \
367 FUNC1(cmath_acos
, c_acos
)
368 FUNC1(cmath_acosh
, c_acosh
)
369 FUNC1(cmath_asin
, c_asin
)
370 FUNC1(cmath_asinh
, c_asinh
)
371 FUNC1(cmath_atan
, c_atan
)
372 FUNC1(cmath_atanh
, c_atanh
)
373 FUNC1(cmath_cos
, c_cos
)
374 FUNC1(cmath_cosh
, c_cosh
)
375 FUNC1(cmath_exp
, c_exp
)
376 FUNC1(cmath_log
, c_log
)
377 FUNC1(cmath_log10
, c_log10
)
378 FUNC1(cmath_sin
, c_sin
)
379 FUNC1(cmath_sinh
, c_sinh
)
380 FUNC1(cmath_sqrt
, c_sqrt
)
381 FUNC1(cmath_tan
, c_tan
)
382 FUNC1(cmath_tanh
, c_tanh
)
385 static char module_doc
[] =
386 "This module is always available. It provides access to mathematical\n\
387 functions for complex numbers.";
390 static PyMethodDef cmath_methods
[] = {
391 {"acos", cmath_acos
, 1, c_acos_doc
},
392 {"acosh", cmath_acosh
, 1, c_acosh_doc
},
393 {"asin", cmath_asin
, 1, c_asin_doc
},
394 {"asinh", cmath_asinh
, 1, c_asinh_doc
},
395 {"atan", cmath_atan
, 1, c_atan_doc
},
396 {"atanh", cmath_atanh
, 1, c_atanh_doc
},
397 {"cos", cmath_cos
, 1, c_cos_doc
},
398 {"cosh", cmath_cosh
, 1, c_cosh_doc
},
399 {"exp", cmath_exp
, 1, c_exp_doc
},
400 {"log", cmath_log
, 1, c_log_doc
},
401 {"log10", cmath_log10
, 1, c_log10_doc
},
402 {"sin", cmath_sin
, 1, c_sin_doc
},
403 {"sinh", cmath_sinh
, 1, c_sinh_doc
},
404 {"sqrt", cmath_sqrt
, 1, c_sqrt_doc
},
405 {"tan", cmath_tan
, 1, c_tan_doc
},
406 {"tanh", cmath_tanh
, 1, c_tanh_doc
},
407 {NULL
, NULL
} /* sentinel */
415 m
= Py_InitModule3("cmath", cmath_methods
, module_doc
);
416 d
= PyModule_GetDict(m
);
417 PyDict_SetItemString(d
, "pi",
418 v
= PyFloat_FromDouble(atan(1.0) * 4.0));
420 PyDict_SetItemString(d
, "e", v
= PyFloat_FromDouble(exp(1.0)));