blob: 175933a514e7a04f3ed8530d901ffa2902fd327c [file] [log] [blame]
Guido van Rossumf9fca921996-01-12 00:47:05 +00001/* Complex object implementation */
2
3/* Borrows heavily from floatobject.c */
4
5#ifndef WITHOUT_COMPLEX
6
7#include "allobjects.h"
8#include "modsupport.h"
9
10#include <errno.h>
11#include "mymath.h"
12
13#ifdef i860
14/* Cray APP has bogus definition of HUGE_VAL in <math.h> */
15#undef HUGE_VAL
16#endif
17
18#ifdef HUGE_VAL
19#define CHECK(x) if (errno != 0) ; \
20 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
21 else errno = ERANGE
22#else
23#define CHECK(x) /* Don't know how to check */
24#endif
25
26#ifdef HAVE_LIMITS_H
27#include <limits.h>
28#endif
29
30#ifndef LONG_MAX
31#define LONG_MAX 0X7FFFFFFFL
32#endif
33
34#ifndef LONG_MIN
35#define LONG_MIN (-LONG_MAX-1)
36#endif
37
38#ifdef __NeXT__
39#ifdef __sparc__
40/*
41 * This works around a bug in the NS/Sparc 3.3 pre-release
42 * limits.h header file.
43 * 10-Feb-1995 bwarsaw@cnri.reston.va.us
44 */
45#undef LONG_MIN
46#define LONG_MIN (-LONG_MAX-1)
47#endif
48#endif
49
50#if !defined(__STDC__) && !defined(macintosh)
51extern double fmod PROTO((double, double));
52extern double pow PROTO((double, double));
53#endif
54
55
56/* elementary operations on complex numbers */
57
Guido van Rossum363078a1996-05-24 20:45:01 +000058static int c_error;
Guido van Rossum9e720e31996-07-21 02:31:35 +000059static Py_complex c_1 = {1., 0.};
Guido van Rossumf9fca921996-01-12 00:47:05 +000060
Guido van Rossum9e720e31996-07-21 02:31:35 +000061Py_complex c_sum(a,b)
62 Py_complex a,b;
Guido van Rossumf9fca921996-01-12 00:47:05 +000063{
Guido van Rossum9e720e31996-07-21 02:31:35 +000064 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000065 r.real = a.real + b.real;
66 r.imag = a.imag + b.imag;
67 return r;
68}
69
Guido van Rossum9e720e31996-07-21 02:31:35 +000070Py_complex c_diff(a,b)
71 Py_complex a,b;
Guido van Rossumf9fca921996-01-12 00:47:05 +000072{
Guido van Rossum9e720e31996-07-21 02:31:35 +000073 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000074 r.real = a.real - b.real;
75 r.imag = a.imag - b.imag;
76 return r;
77}
78
Guido van Rossum9e720e31996-07-21 02:31:35 +000079Py_complex c_neg(a)
80 Py_complex a;
Guido van Rossumf9fca921996-01-12 00:47:05 +000081{
Guido van Rossum9e720e31996-07-21 02:31:35 +000082 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000083 r.real = -a.real;
84 r.imag = -a.imag;
85 return r;
86}
87
Guido van Rossum9e720e31996-07-21 02:31:35 +000088Py_complex c_prod(a,b)
89 Py_complex a,b;
Guido van Rossumf9fca921996-01-12 00:47:05 +000090{
Guido van Rossum9e720e31996-07-21 02:31:35 +000091 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000092 r.real = a.real*b.real - a.imag*b.imag;
93 r.imag = a.real*b.imag + a.imag*b.real;
94 return r;
95}
96
Guido van Rossum9e720e31996-07-21 02:31:35 +000097Py_complex c_quot(a,b)
98 Py_complex a,b;
Guido van Rossumf9fca921996-01-12 00:47:05 +000099{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000100 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000101 double d = b.real*b.real + b.imag*b.imag;
102 if (d == 0.)
103 c_error = 1;
104 r.real = (a.real*b.real + a.imag*b.imag)/d;
105 r.imag = (a.imag*b.real - a.real*b.imag)/d;
106 return r;
107}
108
Guido van Rossum9e720e31996-07-21 02:31:35 +0000109Py_complex c_pow(a,b)
110 Py_complex a,b;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000111{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000112 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000113 double vabs,len,at,phase;
114 if (b.real == 0. && b.imag == 0.) {
115 r.real = 1.;
116 r.imag = 0.;
117 }
118 else if (a.real == 0. && a.imag == 0.) {
119 if (b.imag != 0. || b.real < 0.)
120 c_error = 2;
121 r.real = 0.;
122 r.imag = 0.;
123 }
124 else {
125 vabs = hypot(a.real,a.imag);
126 len = pow(vabs,b.real);
127 at = atan2(a.imag, a.real);
128 phase = at*b.real;
129 if (b.imag != 0.0) {
130 len /= exp(at*b.imag);
131 phase += b.imag*log(vabs);
132 }
133 r.real = len*cos(phase);
134 r.imag = len*sin(phase);
135 }
136 return r;
137}
138
Guido van Rossum9e720e31996-07-21 02:31:35 +0000139static Py_complex c_powu(x, n)
140 Py_complex x;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000141 long n;
142{
Guido van Rossum926518b1996-08-19 19:30:45 +0000143 Py_complex r, p;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000144 long mask = 1;
Guido van Rossum926518b1996-08-19 19:30:45 +0000145 r = c_1;
146 p = x;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000147 while (mask > 0 && n >= mask) {
148 if (n & mask)
149 r = c_prod(r,p);
150 mask <<= 1;
151 p = c_prod(p,p);
152 }
153 return r;
154}
155
Guido van Rossum9e720e31996-07-21 02:31:35 +0000156static Py_complex c_powi(x, n)
157 Py_complex x;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000158 long n;
159{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000160 Py_complex cn;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000161
162 if (n > 100 || n < -100) {
163 cn.real = (double) n;
164 cn.imag = 0.;
165 return c_pow(x,cn);
166 }
167 else if (n > 0)
168 return c_powu(x,n);
169 else
170 return c_quot(c_1,c_powu(x,-n));
171
172}
173
174PyObject *
Guido van Rossum926518b1996-08-19 19:30:45 +0000175PyComplex_FromCComplex(cval)
176 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000177{
Guido van Rossum926518b1996-08-19 19:30:45 +0000178 register complexobject *op =
179 (complexobject *) malloc(sizeof(complexobject));
Guido van Rossumf9fca921996-01-12 00:47:05 +0000180 if (op == NULL)
181 return err_nomem();
182 op->ob_type = &Complextype;
183 op->cval = cval;
184 NEWREF(op);
185 return (object *) op;
186}
187
188PyObject *
Guido van Rossum926518b1996-08-19 19:30:45 +0000189PyComplex_FromDoubles(real, imag)
190 double real, imag;
191{
192 Py_complex c;
193 c.real = real;
194 c.imag = imag;
195 return PyComplex_FromCComplex(c);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000196}
197
198double
Guido van Rossum926518b1996-08-19 19:30:45 +0000199PyComplex_RealAsDouble(op)
200 PyObject *op;
201{
202 if (PyComplex_Check(op)) {
203 return ((PyComplexObject *)op)->cval.real;
204 } else {
205 return PyFloat_AsDouble(op);
206 }
Guido van Rossumf9fca921996-01-12 00:47:05 +0000207}
208
209double
Guido van Rossum926518b1996-08-19 19:30:45 +0000210PyComplex_ImagAsDouble(op)
211 PyObject *op;
212{
213 if (PyComplex_Check(op)) {
214 return ((PyComplexObject *)op)->cval.imag;
215 } else {
216 return 0.0;
217 }
Guido van Rossumf9fca921996-01-12 00:47:05 +0000218}
219
Guido van Rossum9e720e31996-07-21 02:31:35 +0000220Py_complex
Guido van Rossum926518b1996-08-19 19:30:45 +0000221PyComplex_AsCComplex(op)
222 PyObject *op;
223{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000224 Py_complex cv;
Guido van Rossumcf3d1081996-01-12 01:21:14 +0000225 if (PyComplex_Check(op)) {
226 return ((PyComplexObject *)op)->cval;
227 } else {
228 cv.real = PyFloat_AsDouble(op);
229 cv.imag = 0.;
230 return cv;
231 }
232}
233
Guido van Rossumf9fca921996-01-12 00:47:05 +0000234static void
235complex_dealloc(op)
236 object *op;
237{
238 DEL(op);
239}
240
241
Guido van Rossum363078a1996-05-24 20:45:01 +0000242static void
Guido van Rossumf9fca921996-01-12 00:47:05 +0000243complex_buf_repr(buf, v)
244 char *buf;
245 complexobject *v;
246{
247 if (v->cval.real == 0.)
Guido van Rossum72418791996-01-25 16:21:31 +0000248 sprintf(buf, "%.12gj", v->cval.imag);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000249 else
Guido van Rossum72418791996-01-25 16:21:31 +0000250 sprintf(buf, "(%.12g%+.12gj)", v->cval.real, v->cval.imag);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000251}
252
253static int
254complex_print(v, fp, flags)
255 complexobject *v;
256 FILE *fp;
257 int flags; /* Not used but required by interface */
258{
259 char buf[100];
260 complex_buf_repr(buf, v);
261 fputs(buf, fp);
262 return 0;
263}
264
265static object *
266complex_repr(v)
267 complexobject *v;
268{
269 char buf[100];
270 complex_buf_repr(buf, v);
271 return newstringobject(buf);
272}
273
274static int
275complex_compare(v, w)
276 complexobject *v, *w;
277{
278/* Note: "greater" and "smaller" have no meaning for complex numbers,
279 but Python requires that they be defined nevertheless. */
Guido van Rossum926518b1996-08-19 19:30:45 +0000280 Py_complex i, j;
281 i = v->cval;
282 j = w->cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000283 if (i.real == j.real && i.imag == j.imag)
284 return 0;
285 else if (i.real != j.real)
286 return (i.real < j.real) ? -1 : 1;
287 else
288 return (i.imag < j.imag) ? -1 : 1;
289}
290
291static long
292complex_hash(v)
293 complexobject *v;
294{
295 double intpart, fractpart;
296 int expo;
297 long x;
298 /* This is designed so that Python numbers with the same
299 value hash to the same value, otherwise comparisons
300 of mapping keys will turn out weird */
301
302#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
303{
304 extended e;
305 fractpart = modf(v->cval.real, &e);
306 intpart = e;
307}
308#else
309 fractpart = modf(v->cval.real, &intpart);
310#endif
311
312 if (fractpart == 0.0) {
313 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
314 /* Convert to long int and use its hash... */
315 object *w = dnewlongobject(v->cval.real);
316 if (w == NULL)
317 return -1;
318 x = hashobject(w);
319 DECREF(w);
320 return x;
321 }
322 x = (long)intpart;
323 }
324 else {
325 fractpart = frexp(fractpart, &expo);
326 fractpart = fractpart*2147483648.0; /* 2**31 */
327 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
328 }
329 if (x == -1)
330 x = -2;
331 return x;
332}
333
334static object *
335complex_add(v, w)
336 complexobject *v;
337 complexobject *w;
338{
339 return newcomplexobject(c_sum(v->cval,w->cval));
340}
341
342static object *
343complex_sub(v, w)
344 complexobject *v;
345 complexobject *w;
346{
347 return newcomplexobject(c_diff(v->cval,w->cval));
348}
349
350static object *
351complex_mul(v, w)
352 complexobject *v;
353 complexobject *w;
354{
355 return newcomplexobject(c_prod(v->cval,w->cval));
356}
357
358static object *
359complex_div(v, w)
360 complexobject *v;
361 complexobject *w;
362{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000363 Py_complex quot;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000364 c_error = 0;
365 quot = c_quot(v->cval,w->cval);
366 if (c_error == 1) {
Guido van Rossum3be12e91996-09-12 20:56:18 +0000367 err_setstr(ZeroDivisionError, "complex division");
Guido van Rossumf9fca921996-01-12 00:47:05 +0000368 return NULL;
369 }
370 return newcomplexobject(quot);
371}
372
Guido van Rossumee09fc11996-09-11 13:55:55 +0000373static object *
374complex_remainder(v, w)
375 complexobject *v;
376 complexobject *w;
377{
Guido van Rossum3be12e91996-09-12 20:56:18 +0000378 Py_complex div, mod;
Guido van Rossum24048581996-09-12 21:02:02 +0000379 c_error = 0;
Guido van Rossum3be12e91996-09-12 20:56:18 +0000380 div = c_quot(v->cval,w->cval); /* The raw divisor value. */
381 if (c_error == 1) {
382 err_setstr(ZeroDivisionError, "complex remainder");
383 return NULL;
384 }
385 div.real = floor(div.real); /* Use the floor of the real part. */
386 div.imag = 0.0;
387 mod = c_diff(v->cval, c_prod(w->cval, div));
388
389 return newcomplexobject(mod);
Guido van Rossumee09fc11996-09-11 13:55:55 +0000390}
391
Guido van Rossumee09fc11996-09-11 13:55:55 +0000392
Guido van Rossum3be12e91996-09-12 20:56:18 +0000393static object *
394complex_divmod(v, w)
395 complexobject *v;
396 complexobject *w;
397{
398 Py_complex div, mod;
399 PyObject *d, *m, *z;
Guido van Rossum24048581996-09-12 21:02:02 +0000400 c_error = 0;
Guido van Rossum3be12e91996-09-12 20:56:18 +0000401 div = c_quot(v->cval,w->cval); /* The raw divisor value. */
402 if (c_error == 1) {
403 err_setstr(ZeroDivisionError, "complex divmod()");
404 return NULL;
405 }
406 div.real = floor(div.real); /* Use the floor of the real part. */
407 div.imag = 0.0;
408 mod = c_diff(v->cval, c_prod(w->cval, div));
409 d = newcomplexobject(div);
410 m = newcomplexobject(mod);
411 z = mkvalue("(OO)", d, m);
412 Py_XDECREF(d);
413 Py_XDECREF(m);
414 return z;
415}
Guido van Rossumf9fca921996-01-12 00:47:05 +0000416
417static object *
418complex_pow(v, w, z)
419 complexobject *v;
420 object *w;
421 complexobject *z;
422{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000423 Py_complex p;
424 Py_complex exponent;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000425 long int_exponent;
426
427 if ((object *)z!=None) {
428 err_setstr(ValueError, "complex modulo");
429 return NULL;
430 }
431
432 c_error = 0;
433 exponent = ((complexobject*)w)->cval;
434 int_exponent = (long)exponent.real;
435 if (exponent.imag == 0. && exponent.real == int_exponent)
436 p = c_powi(v->cval,int_exponent);
437 else
438 p = c_pow(v->cval,exponent);
439
440 if (c_error == 2) {
441 err_setstr(ValueError, "0.0 to a negative or complex power");
442 return NULL;
443 }
444
445 return newcomplexobject(p);
446}
447
448static object *
449complex_neg(v)
450 complexobject *v;
451{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000452 Py_complex neg;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000453 neg.real = -v->cval.real;
454 neg.imag = -v->cval.imag;
455 return newcomplexobject(neg);
456}
457
458static object *
459complex_pos(v)
460 complexobject *v;
461{
462 INCREF(v);
463 return (object *)v;
464}
465
466static object *
467complex_abs(v)
468 complexobject *v;
469{
470 return newfloatobject(hypot(v->cval.real,v->cval.imag));
471}
472
473static int
474complex_nonzero(v)
475 complexobject *v;
476{
477 return v->cval.real != 0.0 && v->cval.imag != 0.0;
478}
479
480static int
481complex_coerce(pv, pw)
482 object **pv;
483 object **pw;
484{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000485 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000486 cval.imag = 0.;
487 if (is_intobject(*pw)) {
488 cval.real = (double)getintvalue(*pw);
489 *pw = newcomplexobject(cval);
490 INCREF(*pv);
491 return 0;
492 }
493 else if (is_longobject(*pw)) {
494 cval.real = dgetlongvalue(*pw);
495 *pw = newcomplexobject(cval);
496 INCREF(*pv);
497 return 0;
498 }
499 else if (is_floatobject(*pw)) {
500 cval.real = getfloatvalue(*pw);
501 *pw = newcomplexobject(cval);
502 INCREF(*pv);
503 return 0;
504 }
505 return 1; /* Can't do it */
506}
507
508static object *
509complex_int(v)
510 object *v;
511{
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000512 err_setstr(TypeError,
513 "can't convert complex to int; use e.g. int(abs(z))");
514 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000515}
516
517static object *
518complex_long(v)
519 object *v;
520{
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000521 err_setstr(TypeError,
522 "can't convert complex to long; use e.g. long(abs(z))");
523 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000524}
525
526static object *
527complex_float(v)
528 object *v;
529{
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000530 err_setstr(TypeError,
531 "can't convert complex to float; use e.g. abs(z)");
532 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000533}
534
Guido van Rossumf9fca921996-01-12 00:47:05 +0000535static object *
536complex_conjugate(self)
537 object *self;
538{
Guido van Rossum926518b1996-08-19 19:30:45 +0000539 Py_complex c;
540 c = ((complexobject *)self)->cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000541 c.imag = -c.imag;
542 return newcomplexobject(c);
543}
544
545static PyMethodDef complex_methods[] = {
546 {"conjugate", (PyCFunction)complex_conjugate, 1},
547 {NULL, NULL} /* sentinel */
548};
549
550
551static object *
552complex_getattr(self, name)
553 complexobject *self;
554 char *name;
555{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000556 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000557 if (strcmp(name, "real") == 0)
558 return (object *)newfloatobject(self->cval.real);
559 else if (strcmp(name, "imag") == 0)
560 return (object *)newfloatobject(self->cval.imag);
561 else if (strcmp(name, "conj") == 0) {
562 cval.real = self->cval.real;
563 cval.imag = -self->cval.imag;
564 return (object *)newcomplexobject(cval);
565 }
566 return findmethod(complex_methods, (object *)self, name);
567}
568
569static number_methods complex_as_number = {
570 (binaryfunc)complex_add, /*nb_add*/
571 (binaryfunc)complex_sub, /*nb_subtract*/
572 (binaryfunc)complex_mul, /*nb_multiply*/
573 (binaryfunc)complex_div, /*nb_divide*/
Guido van Rossumee09fc11996-09-11 13:55:55 +0000574 (binaryfunc)complex_remainder, /*nb_remainder*/
575 (binaryfunc)complex_divmod, /*nb_divmod*/
Guido van Rossumf9fca921996-01-12 00:47:05 +0000576 (ternaryfunc)complex_pow, /*nb_power*/
577 (unaryfunc)complex_neg, /*nb_negative*/
578 (unaryfunc)complex_pos, /*nb_positive*/
579 (unaryfunc)complex_abs, /*nb_absolute*/
580 (inquiry)complex_nonzero, /*nb_nonzero*/
581 0, /*nb_invert*/
582 0, /*nb_lshift*/
583 0, /*nb_rshift*/
584 0, /*nb_and*/
585 0, /*nb_xor*/
586 0, /*nb_or*/
587 (coercion)complex_coerce, /*nb_coerce*/
588 (unaryfunc)complex_int, /*nb_int*/
589 (unaryfunc)complex_long, /*nb_long*/
590 (unaryfunc)complex_float, /*nb_float*/
591 0, /*nb_oct*/
592 0, /*nb_hex*/
593};
594
595typeobject Complextype = {
596 OB_HEAD_INIT(&Typetype)
597 0,
598 "complex",
599 sizeof(complexobject),
600 0,
601 (destructor)complex_dealloc, /*tp_dealloc*/
602 (printfunc)complex_print, /*tp_print*/
603 (getattrfunc)complex_getattr, /*tp_getattr*/
604 0, /*tp_setattr*/
605 (cmpfunc)complex_compare, /*tp_compare*/
606 (reprfunc)complex_repr, /*tp_repr*/
607 &complex_as_number, /*tp_as_number*/
608 0, /*tp_as_sequence*/
609 0, /*tp_as_mapping*/
610 (hashfunc)complex_hash, /*tp_hash*/
611};
612
613#endif