complexobject.c 13.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/***********************************************************
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

******************************************************************/

32 33 34 35
/* Complex object implementation */

/* Borrows heavily from floatobject.c */

36 37
/* Submitted by Jim Hugunin */

38 39
#ifndef WITHOUT_COMPLEX

40
#include "Python.h"
41 42 43 44 45 46 47 48 49
#include "mymath.h"

#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif


/* elementary operations on complex numbers */

Guido van Rossum's avatar
Guido van Rossum committed
50
static Py_complex c_1 = {1., 0.};
51

Guido van Rossum's avatar
Guido van Rossum committed
52 53
Py_complex c_sum(a,b)
	Py_complex a,b;
54
{
Guido van Rossum's avatar
Guido van Rossum committed
55
	Py_complex r;
56 57 58 59 60
	r.real = a.real + b.real;
	r.imag = a.imag + b.imag;
	return r;
}

Guido van Rossum's avatar
Guido van Rossum committed
61 62
Py_complex c_diff(a,b)
	Py_complex a,b;
63
{
Guido van Rossum's avatar
Guido van Rossum committed
64
	Py_complex r;
65 66 67 68 69
	r.real = a.real - b.real;
	r.imag = a.imag - b.imag;
	return r;
}

Guido van Rossum's avatar
Guido van Rossum committed
70 71
Py_complex c_neg(a)
	Py_complex a;
72
{
Guido van Rossum's avatar
Guido van Rossum committed
73
	Py_complex r;
74 75 76 77 78
	r.real = -a.real;
	r.imag = -a.imag;
	return r;
}

Guido van Rossum's avatar
Guido van Rossum committed
79 80
Py_complex c_prod(a,b)
	Py_complex a,b;
81
{
Guido van Rossum's avatar
Guido van Rossum committed
82
	Py_complex r;
83 84 85 86 87
	r.real = a.real*b.real - a.imag*b.imag;
	r.imag = a.real*b.imag + a.imag*b.real;
	return r;
}

Guido van Rossum's avatar
Guido van Rossum committed
88 89
Py_complex c_quot(a,b)
	Py_complex a,b;
90
{
Guido van Rossum's avatar
Guido van Rossum committed
91
	Py_complex r;
92 93
	double d = b.real*b.real + b.imag*b.imag;
	if (d == 0.)
94
		errno = EDOM;
95 96 97 98 99
	r.real = (a.real*b.real + a.imag*b.imag)/d;
	r.imag = (a.imag*b.real - a.real*b.imag)/d;
	return r;
}

Guido van Rossum's avatar
Guido van Rossum committed
100 101
Py_complex c_pow(a,b)
	Py_complex a,b;
102
{
Guido van Rossum's avatar
Guido van Rossum committed
103
	Py_complex r;
104 105 106 107 108 109 110
	double vabs,len,at,phase;
	if (b.real == 0. && b.imag == 0.) {
		r.real = 1.;
		r.imag = 0.;
	}
	else if (a.real == 0. && a.imag == 0.) {
		if (b.imag != 0. || b.real < 0.)
111
			errno = ERANGE;
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
		r.real = 0.;
		r.imag = 0.;
	}
	else {
		vabs = hypot(a.real,a.imag);
		len = pow(vabs,b.real);
		at = atan2(a.imag, a.real);
		phase = at*b.real;
		if (b.imag != 0.0) {
			len /= exp(at*b.imag);
			phase += b.imag*log(vabs);
		}
		r.real = len*cos(phase);
		r.imag = len*sin(phase);
	}
	return r;
}

Guido van Rossum's avatar
Guido van Rossum committed
130 131
static Py_complex c_powu(x, n)
	Py_complex x;
132 133
	long n;
{
134
	Py_complex r, p;
135
	long mask = 1;
136 137
	r = c_1;
	p = x;
138 139 140 141 142 143 144 145 146
	while (mask > 0 && n >= mask) {
		if (n & mask)
			r = c_prod(r,p);
		mask <<= 1;
		p = c_prod(p,p);
	}
	return r;
}

Guido van Rossum's avatar
Guido van Rossum committed
147 148
static Py_complex c_powi(x, n)
	Py_complex x;
149 150
	long n;
{
Guido van Rossum's avatar
Guido van Rossum committed
151
	Py_complex cn;
152 153 154 155 156 157 158 159 160 161 162 163 164 165

	if (n > 100 || n < -100) {
		cn.real = (double) n;
		cn.imag = 0.;
		return c_pow(x,cn);
	}
	else if (n > 0)
		return c_powu(x,n);
	else
		return c_quot(c_1,c_powu(x,-n));

}

PyObject *
166 167
PyComplex_FromCComplex(cval)
	Py_complex cval;
168
{
169 170
	register PyComplexObject *op =
		(PyComplexObject *) malloc(sizeof(PyComplexObject));
171
	if (op == NULL)
172 173
		return PyErr_NoMemory();
	op->ob_type = &PyComplex_Type;
174
	op->cval = cval;
175 176
	_Py_NewReference(op);
	return (PyObject *) op;
177 178 179
}

PyObject *
180 181 182 183 184 185 186
PyComplex_FromDoubles(real, imag)
	double real, imag;
{
	Py_complex c;
	c.real = real;
	c.imag = imag;
	return PyComplex_FromCComplex(c);
187 188 189
}

double
190 191 192 193 194 195 196 197
PyComplex_RealAsDouble(op)
	PyObject *op;
{
	if (PyComplex_Check(op)) {
		return ((PyComplexObject *)op)->cval.real;
	} else {
		return PyFloat_AsDouble(op);
	}
198 199 200
}

double
201 202 203 204 205 206 207 208
PyComplex_ImagAsDouble(op)
	PyObject *op;
{
	if (PyComplex_Check(op)) {
		return ((PyComplexObject *)op)->cval.imag;
	} else {
		return 0.0;
	}
209 210
}

Guido van Rossum's avatar
Guido van Rossum committed
211
Py_complex
212 213 214
PyComplex_AsCComplex(op)
	PyObject *op;
{
Guido van Rossum's avatar
Guido van Rossum committed
215
	Py_complex cv;
216 217 218 219 220 221 222 223 224
	if (PyComplex_Check(op)) {
		return ((PyComplexObject *)op)->cval;
	} else {
		cv.real = PyFloat_AsDouble(op);
		cv.imag = 0.;
		return cv;
	}   
}

225 226
static void
complex_dealloc(op)
227
	PyObject *op;
228
{
229
	PyMem_DEL(op);
230 231 232
}


233
static void
234 235
complex_buf_repr(buf, v)
	char *buf;
236
	PyComplexObject *v;
237 238
{
	if (v->cval.real == 0.)
239
		sprintf(buf, "%.12gj", v->cval.imag);
240
	else
241
		sprintf(buf, "(%.12g%+.12gj)", v->cval.real, v->cval.imag);
242 243 244 245
}

static int
complex_print(v, fp, flags)
246
	PyComplexObject *v;
247 248 249 250 251 252 253 254 255
	FILE *fp;
	int flags; /* Not used but required by interface */
{
	char buf[100];
	complex_buf_repr(buf, v);
	fputs(buf, fp);
	return 0;
}

256
static PyObject *
257
complex_repr(v)
258
	PyComplexObject *v;
259 260 261
{
	char buf[100];
	complex_buf_repr(buf, v);
262
	return PyString_FromString(buf);
263 264 265 266
}

static int
complex_compare(v, w)
267
	PyComplexObject *v, *w;
268 269 270
{
/* Note: "greater" and "smaller" have no meaning for complex numbers,
   but Python requires that they be defined nevertheless. */
271 272 273
	Py_complex i, j;
	i = v->cval;
	j = w->cval;
274 275 276 277 278 279 280 281 282 283
	if (i.real == j.real && i.imag == j.imag)
	   return 0;
	else if (i.real != j.real)
	   return (i.real < j.real) ? -1 : 1;
	else
	   return (i.imag < j.imag) ? -1 : 1;
}

static long
complex_hash(v)
284
	PyComplexObject *v;
285 286 287
{
	double intpart, fractpart;
	int expo;
288
	long hipart, x;
289 290 291 292 293 294 295 296 297 298 299 300 301 302
	/* This is designed so that Python numbers with the same
	   value hash to the same value, otherwise comparisons
	   of mapping keys will turn out weird */

#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
{
	extended e;
	fractpart = modf(v->cval.real, &e);
	intpart = e;
}
#else
	fractpart = modf(v->cval.real, &intpart);
#endif

303
	if (fractpart == 0.0 && v->cval.imag == 0.0) {
304 305
		if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
			/* Convert to long int and use its hash... */
306
			PyObject *w = PyLong_FromDouble(v->cval.real);
307 308
			if (w == NULL)
				return -1;
309 310
			x = PyObject_Hash(w);
			Py_DECREF(w);
311 312 313 314 315 316
			return x;
		}
		x = (long)intpart;
	}
	else {
		fractpart = frexp(fractpart, &expo);
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
		fractpart = fractpart * 2147483648.0; /* 2**31 */
		hipart = (long)fractpart; /* Take the top 32 bits */
		fractpart = (fractpart - (double)hipart) * 2147483648.0;
						/* Get the next 32 bits */
		x = hipart + (long)fractpart + (long)intpart + (expo << 15);
						/* Combine everything */

		if (v->cval.imag != 0.0) { /* Hash the imaginary part */
			/* XXX Note that this hashes complex(x, y)
			   to the same value as complex(y, x).
			   Still better than it used to be :-) */
#ifdef MPW
			{
				extended e;
				fractpart = modf(v->cval.imag, &e);
				intpart = e;
			}
#else
			fractpart = modf(v->cval.imag, &intpart);
#endif
			fractpart = frexp(fractpart, &expo);
			fractpart = fractpart * 2147483648.0; /* 2**31 */
			hipart = (long)fractpart; /* Take the top 32 bits */
			fractpart =
				(fractpart - (double)hipart) * 2147483648.0;
						/* Get the next 32 bits */
			x ^= hipart + (long)fractpart +
				(long)intpart + (expo << 15);
						/* Combine everything */
		}
347 348 349 350 351 352
	}
	if (x == -1)
		x = -2;
	return x;
}

353
static PyObject *
354
complex_add(v, w)
355 356
	PyComplexObject *v;
	PyComplexObject *w;
357
{
358 359 360
	Py_complex result;
	PyFPE_START_PROTECT("complex_add", return 0)
	result = c_sum(v->cval,w->cval);
361
	PyFPE_END_PROTECT(result)
362
	return PyComplex_FromCComplex(result);
363 364
}

365
static PyObject *
366
complex_sub(v, w)
367 368
	PyComplexObject *v;
	PyComplexObject *w;
369
{
370 371 372
	Py_complex result;
	PyFPE_START_PROTECT("complex_sub", return 0)
	result = c_diff(v->cval,w->cval);
373
	PyFPE_END_PROTECT(result)
374
	return PyComplex_FromCComplex(result);
375 376
}

377
static PyObject *
378
complex_mul(v, w)
379 380
	PyComplexObject *v;
	PyComplexObject *w;
381
{
382 383 384
	Py_complex result;
	PyFPE_START_PROTECT("complex_mul", return 0)
	result = c_prod(v->cval,w->cval);
385
	PyFPE_END_PROTECT(result)
386
	return PyComplex_FromCComplex(result);
387 388
}

389
static PyObject *
390
complex_div(v, w)
391 392
	PyComplexObject *v;
	PyComplexObject *w;
393
{
Guido van Rossum's avatar
Guido van Rossum committed
394
	Py_complex quot;
395
	PyFPE_START_PROTECT("complex_div", return 0)
396
	errno = 0;
397
	quot = c_quot(v->cval,w->cval);
398
	PyFPE_END_PROTECT(quot)
399
	if (errno == EDOM) {
400
		PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
401 402
		return NULL;
	}
403
	return PyComplex_FromCComplex(quot);
404 405
}

406
static PyObject *
407
complex_remainder(v, w)
408 409
	PyComplexObject *v;
	PyComplexObject *w;
410
{
411
        Py_complex div, mod;
412
	errno = 0;
413
	div = c_quot(v->cval,w->cval); /* The raw divisor value. */
414
	if (errno == EDOM) {
415
		PyErr_SetString(PyExc_ZeroDivisionError, "complex remainder");
416 417 418 419 420 421
		return NULL;
	}
	div.real = floor(div.real); /* Use the floor of the real part. */
	div.imag = 0.0;
	mod = c_diff(v->cval, c_prod(w->cval, div));

422
	return PyComplex_FromCComplex(mod);
423 424 425
}


426
static PyObject *
427
complex_divmod(v, w)
428 429
	PyComplexObject *v;
	PyComplexObject *w;
430 431 432
{
        Py_complex div, mod;
	PyObject *d, *m, *z;
433
	errno = 0;
434
	div = c_quot(v->cval,w->cval); /* The raw divisor value. */
435
	if (errno == EDOM) {
436
		PyErr_SetString(PyExc_ZeroDivisionError, "complex divmod()");
437 438 439 440 441
		return NULL;
	}
	div.real = floor(div.real); /* Use the floor of the real part. */
	div.imag = 0.0;
	mod = c_diff(v->cval, c_prod(w->cval, div));
442 443 444
	d = PyComplex_FromCComplex(div);
	m = PyComplex_FromCComplex(mod);
	z = Py_BuildValue("(OO)", d, m);
445 446 447 448
	Py_XDECREF(d);
	Py_XDECREF(m);
	return z;
}
449

450
static PyObject *
451
complex_pow(v, w, z)
452 453 454
	PyComplexObject *v;
	PyObject *w;
	PyComplexObject *z;
455
{
Guido van Rossum's avatar
Guido van Rossum committed
456 457
	Py_complex p;
	Py_complex exponent;
458 459
	long int_exponent;

460 461
 	if ((PyObject *)z!=Py_None) {
		PyErr_SetString(PyExc_ValueError, "complex modulo");
462 463 464
		return NULL;
	}

465
	PyFPE_START_PROTECT("complex_pow", return 0)
466
	errno = 0;
467
	exponent = ((PyComplexObject*)w)->cval;
468 469 470 471 472 473
	int_exponent = (long)exponent.real;
	if (exponent.imag == 0. && exponent.real == int_exponent)
		p = c_powi(v->cval,int_exponent);
	else
		p = c_pow(v->cval,exponent);

474
	PyFPE_END_PROTECT(p)
475
	if (errno == ERANGE) {
476 477
		PyErr_SetString(PyExc_ValueError,
				"0.0 to a negative or complex power");
478 479 480
		return NULL;
	}

481
	return PyComplex_FromCComplex(p);
482 483
}

484
static PyObject *
485
complex_neg(v)
486
	PyComplexObject *v;
487
{
Guido van Rossum's avatar
Guido van Rossum committed
488
	Py_complex neg;
489 490
	neg.real = -v->cval.real;
	neg.imag = -v->cval.imag;
491
	return PyComplex_FromCComplex(neg);
492 493
}

494
static PyObject *
495
complex_pos(v)
496
	PyComplexObject *v;
497
{
498 499
	Py_INCREF(v);
	return (PyObject *)v;
500 501
}

502
static PyObject *
503
complex_abs(v)
504
	PyComplexObject *v;
505
{
506 507 508
	double result;
	PyFPE_START_PROTECT("complex_abs", return 0)
	result = hypot(v->cval.real,v->cval.imag);
509
	PyFPE_END_PROTECT(result)
510
	return PyFloat_FromDouble(result);
511 512 513 514
}

static int
complex_nonzero(v)
515
	PyComplexObject *v;
516
{
517
	return v->cval.real != 0.0 || v->cval.imag != 0.0;
518 519 520 521
}

static int
complex_coerce(pv, pw)
522 523
	PyObject **pv;
	PyObject **pw;
524
{
Guido van Rossum's avatar
Guido van Rossum committed
525
	Py_complex cval;
526
	cval.imag = 0.;
527 528 529 530
	if (PyInt_Check(*pw)) {
		cval.real = (double)PyInt_AsLong(*pw);
		*pw = PyComplex_FromCComplex(cval);
		Py_INCREF(*pv);
531 532
		return 0;
	}
533 534 535 536
	else if (PyLong_Check(*pw)) {
		cval.real = PyLong_AsDouble(*pw);
		*pw = PyComplex_FromCComplex(cval);
		Py_INCREF(*pv);
537 538
		return 0;
	}
539 540 541 542
	else if (PyFloat_Check(*pw)) {
		cval.real = PyFloat_AsDouble(*pw);
		*pw = PyComplex_FromCComplex(cval);
		Py_INCREF(*pv);
543 544 545 546 547
		return 0;
	}
	return 1; /* Can't do it */
}

548
static PyObject *
549
complex_int(v)
550
	PyObject *v;
551
{
552
	PyErr_SetString(PyExc_TypeError,
553 554
		   "can't convert complex to int; use e.g. int(abs(z))");
	return NULL;
555 556
}

557
static PyObject *
558
complex_long(v)
559
	PyObject *v;
560
{
561
	PyErr_SetString(PyExc_TypeError,
562 563
		   "can't convert complex to long; use e.g. long(abs(z))");
	return NULL;
564 565
}

566
static PyObject *
567
complex_float(v)
568
	PyObject *v;
569
{
570
	PyErr_SetString(PyExc_TypeError,
571 572
		   "can't convert complex to float; use e.g. abs(z)");
	return NULL;
573 574
}

575
static PyObject *
576
complex_conjugate(self, args)
577
	PyObject *self;
578
	PyObject *args;
579
{
580
	Py_complex c;
581 582
	if (!PyArg_ParseTuple(args, ""))
		return NULL;
583
	c = ((PyComplexObject *)self)->cval;
584
	c.imag = -c.imag;
585
	return PyComplex_FromCComplex(c);
586 587 588
}

static PyMethodDef complex_methods[] = {
589
	{"conjugate",	complex_conjugate,	1},
590 591 592 593
	{NULL,		NULL}		/* sentinel */
};


594
static PyObject *
595
complex_getattr(self, name)
596
	PyComplexObject *self;
597 598 599
	char *name;
{
	if (strcmp(name, "real") == 0)
600
		return (PyObject *)PyFloat_FromDouble(self->cval.real);
601
	else if (strcmp(name, "imag") == 0)
602
		return (PyObject *)PyFloat_FromDouble(self->cval.imag);
603
	else if (strcmp(name, "__members__") == 0)
604 605
		return Py_BuildValue("[ss]", "imag", "real");
	return Py_FindMethod(complex_methods, (PyObject *)self, name);
606 607
}

608
static PyNumberMethods complex_as_number = {
609 610 611 612
	(binaryfunc)complex_add, /*nb_add*/
	(binaryfunc)complex_sub, /*nb_subtract*/
	(binaryfunc)complex_mul, /*nb_multiply*/
	(binaryfunc)complex_div, /*nb_divide*/
613 614
	(binaryfunc)complex_remainder,	/*nb_remainder*/
	(binaryfunc)complex_divmod,	/*nb_divmod*/
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
	(ternaryfunc)complex_pow, /*nb_power*/
	(unaryfunc)complex_neg, /*nb_negative*/
	(unaryfunc)complex_pos, /*nb_positive*/
	(unaryfunc)complex_abs, /*nb_absolute*/
	(inquiry)complex_nonzero, /*nb_nonzero*/
	0,		/*nb_invert*/
	0,		/*nb_lshift*/
	0,		/*nb_rshift*/
	0,		/*nb_and*/
	0,		/*nb_xor*/
	0,		/*nb_or*/
	(coercion)complex_coerce, /*nb_coerce*/
	(unaryfunc)complex_int, /*nb_int*/
	(unaryfunc)complex_long, /*nb_long*/
	(unaryfunc)complex_float, /*nb_float*/
	0,		/*nb_oct*/
	0,		/*nb_hex*/
};

634 635
PyTypeObject PyComplex_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
636 637
	0,
	"complex",
638
	sizeof(PyComplexObject),
639 640 641 642 643 644 645 646 647 648 649 650 651 652
	0,
	(destructor)complex_dealloc,	/*tp_dealloc*/
	(printfunc)complex_print,	/*tp_print*/
	(getattrfunc)complex_getattr,	/*tp_getattr*/
	0,				/*tp_setattr*/
	(cmpfunc)complex_compare,	/*tp_compare*/
	(reprfunc)complex_repr,		/*tp_repr*/
	&complex_as_number,    		/*tp_as_number*/
	0,				/*tp_as_sequence*/
	0,				/*tp_as_mapping*/
	(hashfunc)complex_hash, 	/*tp_hash*/
};

#endif