blob: 89a7380c80c0c9527376db713e98c4509cd55b61 [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
373
374static object *
375complex_pow(v, w, z)
376 complexobject *v;
377 object *w;
378 complexobject *z;
379{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000380 Py_complex p;
381 Py_complex exponent;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000382 long int_exponent;
383
384 if ((object *)z!=None) {
385 err_setstr(ValueError, "complex modulo");
386 return NULL;
387 }
388
389 c_error = 0;
390 exponent = ((complexobject*)w)->cval;
391 int_exponent = (long)exponent.real;
392 if (exponent.imag == 0. && exponent.real == int_exponent)
393 p = c_powi(v->cval,int_exponent);
394 else
395 p = c_pow(v->cval,exponent);
396
397 if (c_error == 2) {
398 err_setstr(ValueError, "0.0 to a negative or complex power");
399 return NULL;
400 }
401
402 return newcomplexobject(p);
403}
404
405static object *
406complex_neg(v)
407 complexobject *v;
408{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000409 Py_complex neg;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000410 neg.real = -v->cval.real;
411 neg.imag = -v->cval.imag;
412 return newcomplexobject(neg);
413}
414
415static object *
416complex_pos(v)
417 complexobject *v;
418{
419 INCREF(v);
420 return (object *)v;
421}
422
423static object *
424complex_abs(v)
425 complexobject *v;
426{
427 return newfloatobject(hypot(v->cval.real,v->cval.imag));
428}
429
430static int
431complex_nonzero(v)
432 complexobject *v;
433{
434 return v->cval.real != 0.0 && v->cval.imag != 0.0;
435}
436
437static int
438complex_coerce(pv, pw)
439 object **pv;
440 object **pw;
441{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000442 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000443 cval.imag = 0.;
444 if (is_intobject(*pw)) {
445 cval.real = (double)getintvalue(*pw);
446 *pw = newcomplexobject(cval);
447 INCREF(*pv);
448 return 0;
449 }
450 else if (is_longobject(*pw)) {
451 cval.real = dgetlongvalue(*pw);
452 *pw = newcomplexobject(cval);
453 INCREF(*pv);
454 return 0;
455 }
456 else if (is_floatobject(*pw)) {
457 cval.real = getfloatvalue(*pw);
458 *pw = newcomplexobject(cval);
459 INCREF(*pv);
460 return 0;
461 }
462 return 1; /* Can't do it */
463}
464
465static object *
466complex_int(v)
467 object *v;
468{
469 double x = ((complexobject *)v)->cval.real;
470 if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN
471 : (x = floor(x)) > (double)LONG_MAX) {
472 err_setstr(OverflowError, "float too large to convert");
473 return NULL;
474 }
475 return newintobject((long)x);
476}
477
478static object *
479complex_long(v)
480 object *v;
481{
482 double x = ((complexobject *)v)->cval.real;
483 return dnewlongobject(x);
484}
485
486static object *
487complex_float(v)
488 object *v;
489{
490 double x = ((complexobject *)v)->cval.real;
491 return newfloatobject(x);
492}
493
494
495static object *
496complex_new(self, args)
497 object *self;
498 object *args;
499{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000500 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000501
502 cval.imag = 0.;
503 if (!PyArg_ParseTuple(args, "d|d", &cval.real, &cval.imag))
504 return NULL;
505 return newcomplexobject(cval);
506}
507
508static object *
509complex_conjugate(self)
510 object *self;
511{
Guido van Rossum926518b1996-08-19 19:30:45 +0000512 Py_complex c;
513 c = ((complexobject *)self)->cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000514 c.imag = -c.imag;
515 return newcomplexobject(c);
516}
517
518static PyMethodDef complex_methods[] = {
519 {"conjugate", (PyCFunction)complex_conjugate, 1},
520 {NULL, NULL} /* sentinel */
521};
522
523
524static object *
525complex_getattr(self, name)
526 complexobject *self;
527 char *name;
528{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000529 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000530 if (strcmp(name, "real") == 0)
531 return (object *)newfloatobject(self->cval.real);
532 else if (strcmp(name, "imag") == 0)
533 return (object *)newfloatobject(self->cval.imag);
534 else if (strcmp(name, "conj") == 0) {
535 cval.real = self->cval.real;
536 cval.imag = -self->cval.imag;
537 return (object *)newcomplexobject(cval);
538 }
539 return findmethod(complex_methods, (object *)self, name);
540}
541
542static number_methods complex_as_number = {
543 (binaryfunc)complex_add, /*nb_add*/
544 (binaryfunc)complex_sub, /*nb_subtract*/
545 (binaryfunc)complex_mul, /*nb_multiply*/
546 (binaryfunc)complex_div, /*nb_divide*/
547 0, /*nb_remainder*/
548 0, /*nb_divmod*/
549 (ternaryfunc)complex_pow, /*nb_power*/
550 (unaryfunc)complex_neg, /*nb_negative*/
551 (unaryfunc)complex_pos, /*nb_positive*/
552 (unaryfunc)complex_abs, /*nb_absolute*/
553 (inquiry)complex_nonzero, /*nb_nonzero*/
554 0, /*nb_invert*/
555 0, /*nb_lshift*/
556 0, /*nb_rshift*/
557 0, /*nb_and*/
558 0, /*nb_xor*/
559 0, /*nb_or*/
560 (coercion)complex_coerce, /*nb_coerce*/
561 (unaryfunc)complex_int, /*nb_int*/
562 (unaryfunc)complex_long, /*nb_long*/
563 (unaryfunc)complex_float, /*nb_float*/
564 0, /*nb_oct*/
565 0, /*nb_hex*/
566};
567
568typeobject Complextype = {
569 OB_HEAD_INIT(&Typetype)
570 0,
571 "complex",
572 sizeof(complexobject),
573 0,
574 (destructor)complex_dealloc, /*tp_dealloc*/
575 (printfunc)complex_print, /*tp_print*/
576 (getattrfunc)complex_getattr, /*tp_getattr*/
577 0, /*tp_setattr*/
578 (cmpfunc)complex_compare, /*tp_compare*/
579 (reprfunc)complex_repr, /*tp_repr*/
580 &complex_as_number, /*tp_as_number*/
581 0, /*tp_as_sequence*/
582 0, /*tp_as_mapping*/
583 (hashfunc)complex_hash, /*tp_hash*/
584};
585
586#endif