cmathmodule.c 8.02 KB
Newer Older
Guido van Rossum's avatar
Guido van Rossum committed
1 2 3 4
/* Complex math module */

/* much code borrowed from mathmodule.c */

Roger E. Masse's avatar
Roger E. Masse committed
5
#include "Python.h"
Guido van Rossum's avatar
Guido van Rossum committed
6 7 8 9 10 11 12 13

#ifndef M_PI
#define M_PI (3.141592653589793239)
#endif

/* First, the C functions that do the real work */

/* constants */
14
static Py_complex c_one = {1., 0.};
Guido van Rossum's avatar
Guido van Rossum committed
15 16
static Py_complex c_half = {0.5, 0.};
static Py_complex c_i = {0., 1.};
17
static Py_complex c_halfi = {0., 0.5};
Guido van Rossum's avatar
Guido van Rossum committed
18 19

/* forward declarations */
20 21 22
static Py_complex c_log(Py_complex);
static Py_complex c_prodi(Py_complex);
static Py_complex c_sqrt(Py_complex);
23
static PyObject * math_error(void);
Guido van Rossum's avatar
Guido van Rossum committed
24 25


26 27
static Py_complex
c_acos(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
28 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))))))));
Guido van Rossum's avatar
Guido van Rossum committed
31 32
}

33
PyDoc_STRVAR(c_acos_doc,
34 35
"acos(x)\n"
"\n"
36
"Return the arc cosine of x.");
37 38


39 40
static Py_complex
c_acosh(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
41
{
42 43
	Py_complex z;
	z = c_sqrt(c_half);
44 45
	z = c_log(c_prod(z, c_sum(c_sqrt(c_sum(x,c_one)),
				  c_sqrt(c_diff(x,c_one)))));
46
	return c_sum(z, z);
Guido van Rossum's avatar
Guido van Rossum committed
47 48
}

49
PyDoc_STRVAR(c_acosh_doc,
50 51
"acosh(x)\n"
"\n"
52
"Return the hyperbolic arccosine of x.");
53 54


55 56
static Py_complex
c_asin(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
57
{
58 59 60
	/* -i * log[(sqrt(1-x**2) + i*x] */
	const Py_complex squared = c_prod(x, x);
	const Py_complex sqrt_1_minus_x_sq = c_sqrt(c_diff(c_one, squared));
61 62 63
        return c_neg(c_prodi(c_log(
        		c_sum(sqrt_1_minus_x_sq, c_prodi(x))
		    )       )     );
Guido van Rossum's avatar
Guido van Rossum committed
64 65
}

66
PyDoc_STRVAR(c_asin_doc,
67 68
"asin(x)\n"
"\n"
69
"Return the arc sine of x.");
70 71


72 73
static Py_complex
c_asinh(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
74
{
75
	Py_complex z;
76 77 78 79
	z = c_sqrt(c_half);
	z = c_log(c_prod(z, c_sum(c_sqrt(c_sum(x, c_i)),
				  c_sqrt(c_diff(x, c_i)))));
	return c_sum(z, z);
Guido van Rossum's avatar
Guido van Rossum committed
80 81
}

82
PyDoc_STRVAR(c_asinh_doc,
83 84
"asinh(x)\n"
"\n"
85
"Return the hyperbolic arc sine of x.");
86 87


88 89
static Py_complex
c_atan(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
90
{
91
	return c_prod(c_halfi,c_log(c_quot(c_sum(c_i,x),c_diff(c_i,x))));
Guido van Rossum's avatar
Guido van Rossum committed
92 93
}

94
PyDoc_STRVAR(c_atan_doc,
95 96
"atan(x)\n"
"\n"
97
"Return the arc tangent of x.");
98 99


100 101
static Py_complex
c_atanh(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
102
{
103
	return c_prod(c_half,c_log(c_quot(c_sum(c_one,x),c_diff(c_one,x))));
Guido van Rossum's avatar
Guido van Rossum committed
104 105
}

106
PyDoc_STRVAR(c_atanh_doc,
107 108
"atanh(x)\n"
"\n"
109
"Return the hyperbolic arc tangent of x.");
110 111


112 113
static Py_complex
c_cos(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
114
{
Guido van Rossum's avatar
Guido van Rossum committed
115
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
116 117 118 119 120
	r.real = cos(x.real)*cosh(x.imag);
	r.imag = -sin(x.real)*sinh(x.imag);
	return r;
}

121
PyDoc_STRVAR(c_cos_doc,
122 123
"cos(x)\n"
"n"
124
"Return the cosine of x.");
125 126


127 128
static Py_complex
c_cosh(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
129
{
Guido van Rossum's avatar
Guido van Rossum committed
130
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
131 132 133 134 135
	r.real = cos(x.imag)*cosh(x.real);
	r.imag = sin(x.imag)*sinh(x.real);
	return r;
}

136
PyDoc_STRVAR(c_cosh_doc,
137 138
"cosh(x)\n"
"n"
139
"Return the hyperbolic cosine of x.");
140 141


142 143
static Py_complex
c_exp(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
144
{
Guido van Rossum's avatar
Guido van Rossum committed
145
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
146 147 148 149 150 151
	double l = exp(x.real);
	r.real = l*cos(x.imag);
	r.imag = l*sin(x.imag);
	return r;
}

152
PyDoc_STRVAR(c_exp_doc,
153 154
"exp(x)\n"
"\n"
155
"Return the exponential value e**x.");
156 157


158 159
static Py_complex
c_log(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
160
{
Guido van Rossum's avatar
Guido van Rossum committed
161
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
162
	double l = hypot(x.real,x.imag);
163
	r.imag = atan2(x.imag, x.real);
Guido van Rossum's avatar
Guido van Rossum committed
164 165 166 167
	r.real = log(l);
	return r;
}

168

169 170
static Py_complex
c_log10(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
171
{
Guido van Rossum's avatar
Guido van Rossum committed
172
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
173
	double l = hypot(x.real,x.imag);
174
	r.imag = atan2(x.imag, x.real)/log(10.);
Guido van Rossum's avatar
Guido van Rossum committed
175 176 177 178
	r.real = log10(l);
	return r;
}

179
PyDoc_STRVAR(c_log10_doc,
180 181
"log10(x)\n"
"\n"
182
"Return the base-10 logarithm of x.");
183 184 185


/* internal function not available from Python */
186 187
static Py_complex
c_prodi(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
188
{
Guido van Rossum's avatar
Guido van Rossum committed
189
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
190 191 192 193 194
	r.real = -x.imag;
	r.imag = x.real;
	return r;
}

195

196 197
static Py_complex
c_sin(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
198
{
Guido van Rossum's avatar
Guido van Rossum committed
199
	Py_complex r;
200 201
	r.real = sin(x.real) * cosh(x.imag);
	r.imag = cos(x.real) * sinh(x.imag);
Guido van Rossum's avatar
Guido van Rossum committed
202 203 204
	return r;
}

205
PyDoc_STRVAR(c_sin_doc,
206 207
"sin(x)\n"
"\n"
208
"Return the sine of x.");
209 210


211 212
static Py_complex
c_sinh(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
213
{
Guido van Rossum's avatar
Guido van Rossum committed
214
	Py_complex r;
215 216
	r.real = cos(x.imag) * sinh(x.real);
	r.imag = sin(x.imag) * cosh(x.real);
Guido van Rossum's avatar
Guido van Rossum committed
217 218 219
	return r;
}

220
PyDoc_STRVAR(c_sinh_doc,
221 222
"sinh(x)\n"
"\n"
223
"Return the hyperbolic sine of x.");
224 225


226 227
static Py_complex
c_sqrt(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
228
{
Guido van Rossum's avatar
Guido van Rossum committed
229
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
	double s,d;
	if (x.real == 0. && x.imag == 0.)
		r = x;
	else {
		s = sqrt(0.5*(fabs(x.real) + hypot(x.real,x.imag)));
		d = 0.5*x.imag/s;
		if (x.real > 0.) {
			r.real = s;
			r.imag = d;
		}
		else if (x.imag >= 0.) {
			r.real = d;
			r.imag = s;
		}
		else {
			r.real = -d;
			r.imag = -s;
		}
	}
	return r;
}

252
PyDoc_STRVAR(c_sqrt_doc,
253 254
"sqrt(x)\n"
"\n"
255
"Return the square root of x.");
256 257


258 259
static Py_complex
c_tan(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
260
{
Guido van Rossum's avatar
Guido van Rossum committed
261
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
262 263 264 265 266 267 268
	double sr,cr,shi,chi;
	double rs,is,rc,ic;
	double d;
	sr = sin(x.real);
	cr = cos(x.real);
	shi = sinh(x.imag);
	chi = cosh(x.imag);
269 270 271 272 273 274 275
	rs = sr * chi;
	is = cr * shi;
	rc = cr * chi;
	ic = -sr * shi;
	d = rc*rc + ic * ic;
	r.real = (rs*rc + is*ic) / d;
	r.imag = (is*rc - rs*ic) / d;
Guido van Rossum's avatar
Guido van Rossum committed
276 277 278
	return r;
}

279
PyDoc_STRVAR(c_tan_doc,
280 281
"tan(x)\n"
"\n"
282
"Return the tangent of x.");
283 284


285 286
static Py_complex
c_tanh(Py_complex x)
Guido van Rossum's avatar
Guido van Rossum committed
287
{
Guido van Rossum's avatar
Guido van Rossum committed
288
	Py_complex r;
Guido van Rossum's avatar
Guido van Rossum committed
289 290 291 292 293 294 295
	double si,ci,shr,chr;
	double rs,is,rc,ic;
	double d;
	si = sin(x.imag);
	ci = cos(x.imag);
	shr = sinh(x.real);
	chr = cosh(x.real);
296 297 298 299
	rs = ci * shr;
	is = si * chr;
	rc = ci * chr;
	ic = si * shr;
Guido van Rossum's avatar
Guido van Rossum committed
300
	d = rc*rc + ic*ic;
301 302
	r.real = (rs*rc + is*ic) / d;
	r.imag = (is*rc - rs*ic) / d;
Guido van Rossum's avatar
Guido van Rossum committed
303 304 305
	return r;
}

306
PyDoc_STRVAR(c_tanh_doc,
307 308
"tanh(x)\n"
"\n"
309
"Return the hyperbolic tangent of x.");
310

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
static PyObject *
cmath_log(PyObject *self, PyObject *args)
{
	Py_complex x;
	Py_complex y;

	if (!PyArg_ParseTuple(args, "D|D", &x, &y))
		return NULL;

	errno = 0;
	PyFPE_START_PROTECT("complex function", return 0)
	x = c_log(x);
	if (PyTuple_GET_SIZE(args) == 2)
		x = c_quot(x, c_log(y));
	PyFPE_END_PROTECT(x)
	if (errno != 0)
		return math_error();
	Py_ADJUST_ERANGE2(x.real, x.imag);
	return PyComplex_FromCComplex(x);
}

PyDoc_STRVAR(cmath_log_doc,
"log(x[, base]) -> the logarithm of x to the given base.\n\
If the base not specified, returns the natural logarithm (base e) of x.");

Guido van Rossum's avatar
Guido van Rossum committed
336 337 338

/* And now the glue to make them available from Python: */

Roger E. Masse's avatar
Roger E. Masse committed
339
static PyObject *
340
math_error(void)
Guido van Rossum's avatar
Guido van Rossum committed
341 342
{
	if (errno == EDOM)
Roger E. Masse's avatar
Roger E. Masse committed
343
		PyErr_SetString(PyExc_ValueError, "math domain error");
Guido van Rossum's avatar
Guido van Rossum committed
344
	else if (errno == ERANGE)
Roger E. Masse's avatar
Roger E. Masse committed
345 346
		PyErr_SetString(PyExc_OverflowError, "math range error");
	else    /* Unexpected math error */
347
		PyErr_SetFromErrno(PyExc_ValueError);
Guido van Rossum's avatar
Guido van Rossum committed
348 349 350
	return NULL;
}

Roger E. Masse's avatar
Roger E. Masse committed
351
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
352
math_1(PyObject *args, Py_complex (*func)(Py_complex))
Guido van Rossum's avatar
Guido van Rossum committed
353
{
Guido van Rossum's avatar
Guido van Rossum committed
354
	Py_complex x;
Guido van Rossum's avatar
Guido van Rossum committed
355 356 357
	if (!PyArg_ParseTuple(args, "D", &x))
		return NULL;
	errno = 0;
358
	PyFPE_START_PROTECT("complex function", return 0)
Guido van Rossum's avatar
Guido van Rossum committed
359
	x = (*func)(x);
360
	PyFPE_END_PROTECT(x)
361
	Py_ADJUST_ERANGE2(x.real, x.imag);
Guido van Rossum's avatar
Guido van Rossum committed
362 363 364
	if (errno != 0)
		return math_error();
	else
Roger E. Masse's avatar
Roger E. Masse committed
365
		return PyComplex_FromCComplex(x);
Guido van Rossum's avatar
Guido van Rossum committed
366 367 368
}

#define FUNC1(stubname, func) \
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
369
	static PyObject * stubname(PyObject *self, PyObject *args) { \
Guido van Rossum's avatar
Guido van Rossum committed
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
		return math_1(args, func); \
	}

FUNC1(cmath_acos, c_acos)
FUNC1(cmath_acosh, c_acosh)
FUNC1(cmath_asin, c_asin)
FUNC1(cmath_asinh, c_asinh)
FUNC1(cmath_atan, c_atan)
FUNC1(cmath_atanh, c_atanh)
FUNC1(cmath_cos, c_cos)
FUNC1(cmath_cosh, c_cosh)
FUNC1(cmath_exp, c_exp)
FUNC1(cmath_log10, c_log10)
FUNC1(cmath_sin, c_sin)
FUNC1(cmath_sinh, c_sinh)
FUNC1(cmath_sqrt, c_sqrt)
FUNC1(cmath_tan, c_tan)
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.");
393

Roger E. Masse's avatar
Roger E. Masse committed
394
static PyMethodDef cmath_methods[] = {
395 396 397 398 399 400 401 402 403
	{"acos",   cmath_acos,  METH_VARARGS, c_acos_doc},
	{"acosh",  cmath_acosh, METH_VARARGS, c_acosh_doc},
	{"asin",   cmath_asin,  METH_VARARGS, c_asin_doc},
	{"asinh",  cmath_asinh, METH_VARARGS, c_asinh_doc},
	{"atan",   cmath_atan,  METH_VARARGS, c_atan_doc},
	{"atanh",  cmath_atanh, METH_VARARGS, c_atanh_doc},
	{"cos",    cmath_cos,   METH_VARARGS, c_cos_doc},
	{"cosh",   cmath_cosh,  METH_VARARGS, c_cosh_doc},
	{"exp",    cmath_exp,   METH_VARARGS, c_exp_doc},
404
	{"log",    cmath_log,   METH_VARARGS, cmath_log_doc},
405 406 407 408 409 410
	{"log10",  cmath_log10, METH_VARARGS, c_log10_doc},
	{"sin",    cmath_sin,   METH_VARARGS, c_sin_doc},
	{"sinh",   cmath_sinh,  METH_VARARGS, c_sinh_doc},
	{"sqrt",   cmath_sqrt,  METH_VARARGS, c_sqrt_doc},
	{"tan",    cmath_tan,   METH_VARARGS, c_tan_doc},
	{"tanh",   cmath_tanh,  METH_VARARGS, c_tanh_doc},
Guido van Rossum's avatar
Guido van Rossum committed
411 412 413
	{NULL,		NULL}		/* sentinel */
};

414
PyMODINIT_FUNC
415
initcmath(void)
Guido van Rossum's avatar
Guido van Rossum committed
416
{
417
	PyObject *m;
418

419
	m = Py_InitModule3("cmath", cmath_methods, module_doc);
420 421
	if (m == NULL)
		return;
422 423 424 425

	PyModule_AddObject(m, "pi",
                           PyFloat_FromDouble(atan(1.0) * 4.0));
	PyModule_AddObject(m, "e", PyFloat_FromDouble(exp(1.0)));
Guido van Rossum's avatar
Guido van Rossum committed
426
}