blob: d58ecd1dab628d315936ffe4538bcc3383b7525d [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) {
367 err_setstr(ZeroDivisionError, "float division");
368 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{
378 err_setstr(TypeError,
379 "remainder and divmod not implemented for complex numbers");
380 return NULL;
381}
382
383#define complex_divmod complex_remainder
384
Guido van Rossumf9fca921996-01-12 00:47:05 +0000385
386static object *
387complex_pow(v, w, z)
388 complexobject *v;
389 object *w;
390 complexobject *z;
391{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000392 Py_complex p;
393 Py_complex exponent;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000394 long int_exponent;
395
396 if ((object *)z!=None) {
397 err_setstr(ValueError, "complex modulo");
398 return NULL;
399 }
400
401 c_error = 0;
402 exponent = ((complexobject*)w)->cval;
403 int_exponent = (long)exponent.real;
404 if (exponent.imag == 0. && exponent.real == int_exponent)
405 p = c_powi(v->cval,int_exponent);
406 else
407 p = c_pow(v->cval,exponent);
408
409 if (c_error == 2) {
410 err_setstr(ValueError, "0.0 to a negative or complex power");
411 return NULL;
412 }
413
414 return newcomplexobject(p);
415}
416
417static object *
418complex_neg(v)
419 complexobject *v;
420{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000421 Py_complex neg;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000422 neg.real = -v->cval.real;
423 neg.imag = -v->cval.imag;
424 return newcomplexobject(neg);
425}
426
427static object *
428complex_pos(v)
429 complexobject *v;
430{
431 INCREF(v);
432 return (object *)v;
433}
434
435static object *
436complex_abs(v)
437 complexobject *v;
438{
439 return newfloatobject(hypot(v->cval.real,v->cval.imag));
440}
441
442static int
443complex_nonzero(v)
444 complexobject *v;
445{
446 return v->cval.real != 0.0 && v->cval.imag != 0.0;
447}
448
449static int
450complex_coerce(pv, pw)
451 object **pv;
452 object **pw;
453{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000454 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000455 cval.imag = 0.;
456 if (is_intobject(*pw)) {
457 cval.real = (double)getintvalue(*pw);
458 *pw = newcomplexobject(cval);
459 INCREF(*pv);
460 return 0;
461 }
462 else if (is_longobject(*pw)) {
463 cval.real = dgetlongvalue(*pw);
464 *pw = newcomplexobject(cval);
465 INCREF(*pv);
466 return 0;
467 }
468 else if (is_floatobject(*pw)) {
469 cval.real = getfloatvalue(*pw);
470 *pw = newcomplexobject(cval);
471 INCREF(*pv);
472 return 0;
473 }
474 return 1; /* Can't do it */
475}
476
477static object *
478complex_int(v)
479 object *v;
480{
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000481 err_setstr(TypeError,
482 "can't convert complex to int; use e.g. int(abs(z))");
483 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000484}
485
486static object *
487complex_long(v)
488 object *v;
489{
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000490 err_setstr(TypeError,
491 "can't convert complex to long; use e.g. long(abs(z))");
492 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000493}
494
495static object *
496complex_float(v)
497 object *v;
498{
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000499 err_setstr(TypeError,
500 "can't convert complex to float; use e.g. abs(z)");
501 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000502}
503
504
505static object *
506complex_new(self, args)
507 object *self;
508 object *args;
509{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000510 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000511
512 cval.imag = 0.;
513 if (!PyArg_ParseTuple(args, "d|d", &cval.real, &cval.imag))
514 return NULL;
515 return newcomplexobject(cval);
516}
517
518static object *
519complex_conjugate(self)
520 object *self;
521{
Guido van Rossum926518b1996-08-19 19:30:45 +0000522 Py_complex c;
523 c = ((complexobject *)self)->cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000524 c.imag = -c.imag;
525 return newcomplexobject(c);
526}
527
528static PyMethodDef complex_methods[] = {
529 {"conjugate", (PyCFunction)complex_conjugate, 1},
530 {NULL, NULL} /* sentinel */
531};
532
533
534static object *
535complex_getattr(self, name)
536 complexobject *self;
537 char *name;
538{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000539 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000540 if (strcmp(name, "real") == 0)
541 return (object *)newfloatobject(self->cval.real);
542 else if (strcmp(name, "imag") == 0)
543 return (object *)newfloatobject(self->cval.imag);
544 else if (strcmp(name, "conj") == 0) {
545 cval.real = self->cval.real;
546 cval.imag = -self->cval.imag;
547 return (object *)newcomplexobject(cval);
548 }
549 return findmethod(complex_methods, (object *)self, name);
550}
551
552static number_methods complex_as_number = {
553 (binaryfunc)complex_add, /*nb_add*/
554 (binaryfunc)complex_sub, /*nb_subtract*/
555 (binaryfunc)complex_mul, /*nb_multiply*/
556 (binaryfunc)complex_div, /*nb_divide*/
Guido van Rossumee09fc11996-09-11 13:55:55 +0000557 (binaryfunc)complex_remainder, /*nb_remainder*/
558 (binaryfunc)complex_divmod, /*nb_divmod*/
Guido van Rossumf9fca921996-01-12 00:47:05 +0000559 (ternaryfunc)complex_pow, /*nb_power*/
560 (unaryfunc)complex_neg, /*nb_negative*/
561 (unaryfunc)complex_pos, /*nb_positive*/
562 (unaryfunc)complex_abs, /*nb_absolute*/
563 (inquiry)complex_nonzero, /*nb_nonzero*/
564 0, /*nb_invert*/
565 0, /*nb_lshift*/
566 0, /*nb_rshift*/
567 0, /*nb_and*/
568 0, /*nb_xor*/
569 0, /*nb_or*/
570 (coercion)complex_coerce, /*nb_coerce*/
571 (unaryfunc)complex_int, /*nb_int*/
572 (unaryfunc)complex_long, /*nb_long*/
573 (unaryfunc)complex_float, /*nb_float*/
574 0, /*nb_oct*/
575 0, /*nb_hex*/
576};
577
578typeobject Complextype = {
579 OB_HEAD_INIT(&Typetype)
580 0,
581 "complex",
582 sizeof(complexobject),
583 0,
584 (destructor)complex_dealloc, /*tp_dealloc*/
585 (printfunc)complex_print, /*tp_print*/
586 (getattrfunc)complex_getattr, /*tp_getattr*/
587 0, /*tp_setattr*/
588 (cmpfunc)complex_compare, /*tp_compare*/
589 (reprfunc)complex_repr, /*tp_repr*/
590 &complex_as_number, /*tp_as_number*/
591 0, /*tp_as_sequence*/
592 0, /*tp_as_mapping*/
593 (hashfunc)complex_hash, /*tp_hash*/
594};
595
596#endif