blob: 34dbab0becaaaf98a6689ff1d177fad4dd202228 [file] [log] [blame]
Guido van Rossum96783941997-05-20 18:21:34 +00001
Guido van Rossumf9fca921996-01-12 00:47:05 +00002/* Complex object implementation */
3
4/* Borrows heavily from floatobject.c */
5
Guido van Rossum96783941997-05-20 18:21:34 +00006/* Submitted by Jim Hugunin */
7
Guido van Rossumf9fca921996-01-12 00:47:05 +00008#ifndef WITHOUT_COMPLEX
9
Guido van Rossumc0b618a1997-05-02 03:12:38 +000010#include "Python.h"
Guido van Rossumf9fca921996-01-12 00:47:05 +000011
Tim Peters70695122001-03-11 08:37:29 +000012/* Precisions used by repr() and str(), respectively.
13
14 The repr() precision (17 significant decimal digits) is the minimal number
15 that is guaranteed to have enough precision so that if the number is read
16 back in the exact same binary value is recreated. This is true for IEEE
17 floating point by design, and also happens to work for all other modern
18 hardware.
19
20 The str() precision is chosen so that in most cases, the rounding noise
21 created by various operations is suppressed, while giving plenty of
22 precision for practical use.
23*/
24
25#define PREC_REPR 17
26#define PREC_STR 12
Guido van Rossumf9fca921996-01-12 00:47:05 +000027
28/* elementary operations on complex numbers */
29
Guido van Rossum9e720e31996-07-21 02:31:35 +000030static Py_complex c_1 = {1., 0.};
Guido van Rossumf9fca921996-01-12 00:47:05 +000031
Tim Peters0f336042001-03-18 08:21:57 +000032Py_complex
33c_sum(Py_complex a, Py_complex b)
Guido van Rossumf9fca921996-01-12 00:47:05 +000034{
Guido van Rossum9e720e31996-07-21 02:31:35 +000035 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000036 r.real = a.real + b.real;
37 r.imag = a.imag + b.imag;
38 return r;
39}
40
Tim Peters0f336042001-03-18 08:21:57 +000041Py_complex
42c_diff(Py_complex a, Py_complex b)
Guido van Rossumf9fca921996-01-12 00:47:05 +000043{
Guido van Rossum9e720e31996-07-21 02:31:35 +000044 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000045 r.real = a.real - b.real;
46 r.imag = a.imag - b.imag;
47 return r;
48}
49
Tim Peters0f336042001-03-18 08:21:57 +000050Py_complex
51c_neg(Py_complex a)
Guido van Rossumf9fca921996-01-12 00:47:05 +000052{
Guido van Rossum9e720e31996-07-21 02:31:35 +000053 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000054 r.real = -a.real;
55 r.imag = -a.imag;
56 return r;
57}
58
Tim Peters0f336042001-03-18 08:21:57 +000059Py_complex
60c_prod(Py_complex a, Py_complex b)
Guido van Rossumf9fca921996-01-12 00:47:05 +000061{
Guido van Rossum9e720e31996-07-21 02:31:35 +000062 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000063 r.real = a.real*b.real - a.imag*b.imag;
64 r.imag = a.real*b.imag + a.imag*b.real;
65 return r;
66}
67
Tim Peters0f336042001-03-18 08:21:57 +000068Py_complex
69c_quot(Py_complex a, Py_complex b)
Guido van Rossumf9fca921996-01-12 00:47:05 +000070{
Tim Peters0f336042001-03-18 08:21:57 +000071 /******************************************************************
72 This was the original algorithm. It's grossly prone to spurious
73 overflow and underflow errors. It also merrily divides by 0 despite
74 checking for that(!). The code still serves a doc purpose here, as
75 the algorithm following is a simple by-cases transformation of this
76 one:
77
Guido van Rossum9e720e31996-07-21 02:31:35 +000078 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +000079 double d = b.real*b.real + b.imag*b.imag;
80 if (d == 0.)
Guido van Rossum96783941997-05-20 18:21:34 +000081 errno = EDOM;
Guido van Rossumf9fca921996-01-12 00:47:05 +000082 r.real = (a.real*b.real + a.imag*b.imag)/d;
83 r.imag = (a.imag*b.real - a.real*b.imag)/d;
84 return r;
Tim Peters0f336042001-03-18 08:21:57 +000085 ******************************************************************/
86
87 /* This algorithm is better, and is pretty obvious: first divide the
88 * numerators and denominator by whichever of {b.real, b.imag} has
89 * larger magnitude. The earliest reference I found was to CACM
90 * Algorithm 116 (Complex Division, Robert L. Smith, Stanford
91 * University). As usual, though, we're still ignoring all IEEE
92 * endcases.
93 */
94 Py_complex r; /* the result */
95 const double abs_breal = b.real < 0 ? -b.real : b.real;
96 const double abs_bimag = b.imag < 0 ? -b.imag : b.imag;
97
98 if (abs_breal >= abs_bimag) {
99 /* divide tops and bottom by b.real */
100 if (abs_breal == 0.0) {
101 errno = EDOM;
102 r.real = r.imag = 0.0;
103 }
104 else {
105 const double ratio = b.imag / b.real;
106 const double denom = b.real + b.imag * ratio;
107 r.real = (a.real + a.imag * ratio) / denom;
108 r.imag = (a.imag - a.real * ratio) / denom;
109 }
110 }
111 else {
112 /* divide tops and bottom by b.imag */
113 const double ratio = b.real / b.imag;
114 const double denom = b.real * ratio + b.imag;
115 assert(b.imag != 0.0);
116 r.real = (a.real * ratio + a.imag) / denom;
117 r.imag = (a.imag * ratio - a.real) / denom;
118 }
119 return r;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000120}
121
Tim Peters0f336042001-03-18 08:21:57 +0000122Py_complex
123c_pow(Py_complex a, Py_complex b)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000124{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000125 Py_complex r;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000126 double vabs,len,at,phase;
127 if (b.real == 0. && b.imag == 0.) {
128 r.real = 1.;
129 r.imag = 0.;
130 }
131 else if (a.real == 0. && a.imag == 0.) {
132 if (b.imag != 0. || b.real < 0.)
Guido van Rossum96783941997-05-20 18:21:34 +0000133 errno = ERANGE;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000134 r.real = 0.;
135 r.imag = 0.;
136 }
137 else {
138 vabs = hypot(a.real,a.imag);
139 len = pow(vabs,b.real);
140 at = atan2(a.imag, a.real);
141 phase = at*b.real;
142 if (b.imag != 0.0) {
143 len /= exp(at*b.imag);
144 phase += b.imag*log(vabs);
145 }
146 r.real = len*cos(phase);
147 r.imag = len*sin(phase);
148 }
149 return r;
150}
151
Tim Peters0f336042001-03-18 08:21:57 +0000152static Py_complex
153c_powu(Py_complex x, long n)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000154{
Guido van Rossum926518b1996-08-19 19:30:45 +0000155 Py_complex r, p;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000156 long mask = 1;
Guido van Rossum926518b1996-08-19 19:30:45 +0000157 r = c_1;
158 p = x;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000159 while (mask > 0 && n >= mask) {
160 if (n & mask)
161 r = c_prod(r,p);
162 mask <<= 1;
163 p = c_prod(p,p);
164 }
165 return r;
166}
167
Tim Peters0f336042001-03-18 08:21:57 +0000168static Py_complex
169c_powi(Py_complex x, long n)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000170{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000171 Py_complex cn;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000172
173 if (n > 100 || n < -100) {
174 cn.real = (double) n;
175 cn.imag = 0.;
176 return c_pow(x,cn);
177 }
178 else if (n > 0)
179 return c_powu(x,n);
180 else
181 return c_quot(c_1,c_powu(x,-n));
182
183}
184
185PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000186PyComplex_FromCComplex(Py_complex cval)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000187{
Guido van Rossumb18618d2000-05-03 23:44:39 +0000188 register PyComplexObject *op;
189
190 /* PyObject_New is inlined */
191 op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
Guido van Rossumf9fca921996-01-12 00:47:05 +0000192 if (op == NULL)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000193 return PyErr_NoMemory();
Guido van Rossumb18618d2000-05-03 23:44:39 +0000194 PyObject_INIT(op, &PyComplex_Type);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000195 op->cval = cval;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000196 return (PyObject *) op;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000197}
198
199PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000200PyComplex_FromDoubles(double real, double imag)
Guido van Rossum926518b1996-08-19 19:30:45 +0000201{
202 Py_complex c;
203 c.real = real;
204 c.imag = imag;
205 return PyComplex_FromCComplex(c);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000206}
207
208double
Fred Drake4288c802000-07-09 04:36:04 +0000209PyComplex_RealAsDouble(PyObject *op)
Guido van Rossum926518b1996-08-19 19:30:45 +0000210{
211 if (PyComplex_Check(op)) {
212 return ((PyComplexObject *)op)->cval.real;
Fred Drake4288c802000-07-09 04:36:04 +0000213 }
214 else {
Guido van Rossum926518b1996-08-19 19:30:45 +0000215 return PyFloat_AsDouble(op);
216 }
Guido van Rossumf9fca921996-01-12 00:47:05 +0000217}
218
219double
Fred Drake4288c802000-07-09 04:36:04 +0000220PyComplex_ImagAsDouble(PyObject *op)
Guido van Rossum926518b1996-08-19 19:30:45 +0000221{
222 if (PyComplex_Check(op)) {
223 return ((PyComplexObject *)op)->cval.imag;
Fred Drake4288c802000-07-09 04:36:04 +0000224 }
225 else {
Guido van Rossum926518b1996-08-19 19:30:45 +0000226 return 0.0;
227 }
Guido van Rossumf9fca921996-01-12 00:47:05 +0000228}
229
Guido van Rossum9e720e31996-07-21 02:31:35 +0000230Py_complex
Fred Drake4288c802000-07-09 04:36:04 +0000231PyComplex_AsCComplex(PyObject *op)
Guido van Rossum926518b1996-08-19 19:30:45 +0000232{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000233 Py_complex cv;
Guido van Rossumcf3d1081996-01-12 01:21:14 +0000234 if (PyComplex_Check(op)) {
235 return ((PyComplexObject *)op)->cval;
Fred Drake4288c802000-07-09 04:36:04 +0000236 }
237 else {
Guido van Rossumcf3d1081996-01-12 01:21:14 +0000238 cv.real = PyFloat_AsDouble(op);
239 cv.imag = 0.;
240 return cv;
Tim Peters70695122001-03-11 08:37:29 +0000241 }
Guido van Rossumcf3d1081996-01-12 01:21:14 +0000242}
243
Guido van Rossumf9fca921996-01-12 00:47:05 +0000244static void
Fred Drake4288c802000-07-09 04:36:04 +0000245complex_dealloc(PyObject *op)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000246{
Guido van Rossumb18618d2000-05-03 23:44:39 +0000247 PyObject_DEL(op);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000248}
249
250
Guido van Rossum363078a1996-05-24 20:45:01 +0000251static void
Tim Peters70695122001-03-11 08:37:29 +0000252complex_to_buf(char *buf, PyComplexObject *v, int precision)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000253{
254 if (v->cval.real == 0.)
Tim Peters70695122001-03-11 08:37:29 +0000255 sprintf(buf, "%.*gj", precision, v->cval.imag);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000256 else
Tim Peters70695122001-03-11 08:37:29 +0000257 sprintf(buf, "(%.*g%+.*gj)", precision, v->cval.real,
258 precision, v->cval.imag);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000259}
260
261static int
Fred Drake4288c802000-07-09 04:36:04 +0000262complex_print(PyComplexObject *v, FILE *fp, int flags)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000263{
264 char buf[100];
Tim Peters70695122001-03-11 08:37:29 +0000265 complex_to_buf(buf, v,
266 (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000267 fputs(buf, fp);
268 return 0;
269}
270
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000271static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000272complex_repr(PyComplexObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000273{
274 char buf[100];
Tim Peters70695122001-03-11 08:37:29 +0000275 complex_to_buf(buf, v, PREC_REPR);
276 return PyString_FromString(buf);
277}
278
279static PyObject *
280complex_str(PyComplexObject *v)
281{
282 char buf[100];
283 complex_to_buf(buf, v, PREC_STR);
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000284 return PyString_FromString(buf);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000285}
286
Guido van Rossumf9fca921996-01-12 00:47:05 +0000287static long
Fred Drake4288c802000-07-09 04:36:04 +0000288complex_hash(PyComplexObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000289{
Tim Peters39dce292000-08-15 03:34:48 +0000290 long hashreal, hashimag, combined;
291 hashreal = _Py_HashDouble(v->cval.real);
292 if (hashreal == -1)
293 return -1;
294 hashimag = _Py_HashDouble(v->cval.imag);
295 if (hashimag == -1)
296 return -1;
297 /* Note: if the imaginary part is 0, hashimag is 0 now,
298 * so the following returns hashreal unchanged. This is
299 * important because numbers of different types that
300 * compare equal must have the same hash value, so that
301 * hash(x + 0*j) must equal hash(x).
302 */
303 combined = hashreal + 1000003 * hashimag;
304 if (combined == -1)
305 combined = -2;
306 return combined;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000307}
308
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000309static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000310complex_add(PyComplexObject *v, PyComplexObject *w)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000311{
Guido van Rossum09e6ad01997-02-14 22:54:21 +0000312 Py_complex result;
313 PyFPE_START_PROTECT("complex_add", return 0)
314 result = c_sum(v->cval,w->cval);
Guido van Rossum45b83911997-03-14 04:32:50 +0000315 PyFPE_END_PROTECT(result)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000316 return PyComplex_FromCComplex(result);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000317}
318
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000319static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000320complex_sub(PyComplexObject *v, PyComplexObject *w)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000321{
Guido van Rossum09e6ad01997-02-14 22:54:21 +0000322 Py_complex result;
323 PyFPE_START_PROTECT("complex_sub", return 0)
324 result = c_diff(v->cval,w->cval);
Guido van Rossum45b83911997-03-14 04:32:50 +0000325 PyFPE_END_PROTECT(result)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000326 return PyComplex_FromCComplex(result);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000327}
328
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000329static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000330complex_mul(PyComplexObject *v, PyComplexObject *w)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000331{
Guido van Rossum09e6ad01997-02-14 22:54:21 +0000332 Py_complex result;
333 PyFPE_START_PROTECT("complex_mul", return 0)
334 result = c_prod(v->cval,w->cval);
Guido van Rossum45b83911997-03-14 04:32:50 +0000335 PyFPE_END_PROTECT(result)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000336 return PyComplex_FromCComplex(result);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000337}
338
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000339static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000340complex_div(PyComplexObject *v, PyComplexObject *w)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000341{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000342 Py_complex quot;
Guido van Rossum09e6ad01997-02-14 22:54:21 +0000343 PyFPE_START_PROTECT("complex_div", return 0)
Guido van Rossum96783941997-05-20 18:21:34 +0000344 errno = 0;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000345 quot = c_quot(v->cval,w->cval);
Guido van Rossum45b83911997-03-14 04:32:50 +0000346 PyFPE_END_PROTECT(quot)
Guido van Rossum96783941997-05-20 18:21:34 +0000347 if (errno == EDOM) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000348 PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
Guido van Rossumf9fca921996-01-12 00:47:05 +0000349 return NULL;
350 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000351 return PyComplex_FromCComplex(quot);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000352}
353
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000354static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000355complex_remainder(PyComplexObject *v, PyComplexObject *w)
Guido van Rossumee09fc11996-09-11 13:55:55 +0000356{
Guido van Rossum3be12e91996-09-12 20:56:18 +0000357 Py_complex div, mod;
Guido van Rossum96783941997-05-20 18:21:34 +0000358 errno = 0;
Guido van Rossum3be12e91996-09-12 20:56:18 +0000359 div = c_quot(v->cval,w->cval); /* The raw divisor value. */
Guido van Rossum96783941997-05-20 18:21:34 +0000360 if (errno == EDOM) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000361 PyErr_SetString(PyExc_ZeroDivisionError, "complex remainder");
Guido van Rossum3be12e91996-09-12 20:56:18 +0000362 return NULL;
363 }
364 div.real = floor(div.real); /* Use the floor of the real part. */
365 div.imag = 0.0;
366 mod = c_diff(v->cval, c_prod(w->cval, div));
367
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000368 return PyComplex_FromCComplex(mod);
Guido van Rossumee09fc11996-09-11 13:55:55 +0000369}
370
Guido van Rossumee09fc11996-09-11 13:55:55 +0000371
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000372static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000373complex_divmod(PyComplexObject *v, PyComplexObject *w)
Guido van Rossum3be12e91996-09-12 20:56:18 +0000374{
375 Py_complex div, mod;
376 PyObject *d, *m, *z;
Guido van Rossum96783941997-05-20 18:21:34 +0000377 errno = 0;
Guido van Rossum3be12e91996-09-12 20:56:18 +0000378 div = c_quot(v->cval,w->cval); /* The raw divisor value. */
Guido van Rossum96783941997-05-20 18:21:34 +0000379 if (errno == EDOM) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000380 PyErr_SetString(PyExc_ZeroDivisionError, "complex divmod()");
Guido van Rossum3be12e91996-09-12 20:56:18 +0000381 return NULL;
382 }
383 div.real = floor(div.real); /* Use the floor of the real part. */
384 div.imag = 0.0;
385 mod = c_diff(v->cval, c_prod(w->cval, div));
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000386 d = PyComplex_FromCComplex(div);
387 m = PyComplex_FromCComplex(mod);
388 z = Py_BuildValue("(OO)", d, m);
Guido van Rossum3be12e91996-09-12 20:56:18 +0000389 Py_XDECREF(d);
390 Py_XDECREF(m);
391 return z;
392}
Guido van Rossumf9fca921996-01-12 00:47:05 +0000393
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000394static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000395complex_pow(PyComplexObject *v, PyObject *w, PyComplexObject *z)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000396{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000397 Py_complex p;
398 Py_complex exponent;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000399 long int_exponent;
400
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000401 if ((PyObject *)z!=Py_None) {
402 PyErr_SetString(PyExc_ValueError, "complex modulo");
Guido van Rossumf9fca921996-01-12 00:47:05 +0000403 return NULL;
404 }
Guido van Rossum09e6ad01997-02-14 22:54:21 +0000405 PyFPE_START_PROTECT("complex_pow", return 0)
Guido van Rossum96783941997-05-20 18:21:34 +0000406 errno = 0;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000407 exponent = ((PyComplexObject*)w)->cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000408 int_exponent = (long)exponent.real;
409 if (exponent.imag == 0. && exponent.real == int_exponent)
410 p = c_powi(v->cval,int_exponent);
411 else
412 p = c_pow(v->cval,exponent);
413
Guido van Rossum45b83911997-03-14 04:32:50 +0000414 PyFPE_END_PROTECT(p)
Guido van Rossum96783941997-05-20 18:21:34 +0000415 if (errno == ERANGE) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000416 PyErr_SetString(PyExc_ValueError,
417 "0.0 to a negative or complex power");
Guido van Rossumf9fca921996-01-12 00:47:05 +0000418 return NULL;
419 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000420 return PyComplex_FromCComplex(p);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000421}
422
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000423static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000424complex_neg(PyComplexObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000425{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000426 Py_complex neg;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000427 neg.real = -v->cval.real;
428 neg.imag = -v->cval.imag;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000429 return PyComplex_FromCComplex(neg);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000430}
431
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000432static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000433complex_pos(PyComplexObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000434{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000435 Py_INCREF(v);
436 return (PyObject *)v;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000437}
438
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000439static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000440complex_abs(PyComplexObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000441{
Guido van Rossum09e6ad01997-02-14 22:54:21 +0000442 double result;
443 PyFPE_START_PROTECT("complex_abs", return 0)
444 result = hypot(v->cval.real,v->cval.imag);
Guido van Rossum45b83911997-03-14 04:32:50 +0000445 PyFPE_END_PROTECT(result)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000446 return PyFloat_FromDouble(result);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000447}
448
449static int
Fred Drake4288c802000-07-09 04:36:04 +0000450complex_nonzero(PyComplexObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000451{
Guido van Rossum3bbef601999-01-25 19:42:19 +0000452 return v->cval.real != 0.0 || v->cval.imag != 0.0;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000453}
454
455static int
Fred Drake4288c802000-07-09 04:36:04 +0000456complex_coerce(PyObject **pv, PyObject **pw)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000457{
Guido van Rossum9e720e31996-07-21 02:31:35 +0000458 Py_complex cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000459 cval.imag = 0.;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000460 if (PyInt_Check(*pw)) {
461 cval.real = (double)PyInt_AsLong(*pw);
462 *pw = PyComplex_FromCComplex(cval);
463 Py_INCREF(*pv);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000464 return 0;
465 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000466 else if (PyLong_Check(*pw)) {
467 cval.real = PyLong_AsDouble(*pw);
468 *pw = PyComplex_FromCComplex(cval);
469 Py_INCREF(*pv);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000470 return 0;
471 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000472 else if (PyFloat_Check(*pw)) {
473 cval.real = PyFloat_AsDouble(*pw);
474 *pw = PyComplex_FromCComplex(cval);
475 Py_INCREF(*pv);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000476 return 0;
477 }
478 return 1; /* Can't do it */
479}
480
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000481static PyObject *
Guido van Rossumbe4cbb12001-01-18 01:12:39 +0000482complex_richcompare(PyObject *v, PyObject *w, int op)
483{
484 int c;
485 Py_complex i, j;
486 PyObject *res;
487
488 if (op != Py_EQ && op != Py_NE) {
489 PyErr_SetString(PyExc_TypeError,
490 "cannot compare complex numbers using <, <=, >, >=");
491 return NULL;
492 }
493
494 c = PyNumber_CoerceEx(&v, &w);
495 if (c < 0)
496 return NULL;
497 if (c > 0) {
498 Py_INCREF(Py_NotImplemented);
499 return Py_NotImplemented;
500 }
501 if (!PyComplex_Check(v) || !PyComplex_Check(w)) {
502 Py_DECREF(v);
503 Py_DECREF(w);
504 Py_INCREF(Py_NotImplemented);
505 return Py_NotImplemented;
506 }
507
508 i = ((PyComplexObject *)v)->cval;
509 j = ((PyComplexObject *)w)->cval;
510 Py_DECREF(v);
511 Py_DECREF(w);
512
513 if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ))
514 res = Py_True;
515 else
516 res = Py_False;
517
518 Py_INCREF(res);
519 return res;
520}
521
522static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000523complex_int(PyObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000524{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000525 PyErr_SetString(PyExc_TypeError,
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000526 "can't convert complex to int; use e.g. int(abs(z))");
527 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000528}
529
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000530static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000531complex_long(PyObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000532{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000533 PyErr_SetString(PyExc_TypeError,
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000534 "can't convert complex to long; use e.g. long(abs(z))");
535 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000536}
537
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000538static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000539complex_float(PyObject *v)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000540{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000541 PyErr_SetString(PyExc_TypeError,
Guido van Rossumd4ab3cd1996-09-11 22:54:37 +0000542 "can't convert complex to float; use e.g. abs(z)");
543 return NULL;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000544}
545
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000546static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000547complex_conjugate(PyObject *self, PyObject *args)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000548{
Guido van Rossum926518b1996-08-19 19:30:45 +0000549 Py_complex c;
Guido van Rossum43713e52000-02-29 13:59:29 +0000550 if (!PyArg_ParseTuple(args, ":conjugate"))
Guido van Rossum8530ef61998-05-07 16:29:10 +0000551 return NULL;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000552 c = ((PyComplexObject *)self)->cval;
Guido van Rossumf9fca921996-01-12 00:47:05 +0000553 c.imag = -c.imag;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000554 return PyComplex_FromCComplex(c);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000555}
556
557static PyMethodDef complex_methods[] = {
Guido van Rossum8530ef61998-05-07 16:29:10 +0000558 {"conjugate", complex_conjugate, 1},
Guido van Rossumf9fca921996-01-12 00:47:05 +0000559 {NULL, NULL} /* sentinel */
560};
561
562
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000563static PyObject *
Fred Drake4288c802000-07-09 04:36:04 +0000564complex_getattr(PyComplexObject *self, char *name)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000565{
Guido van Rossumf9fca921996-01-12 00:47:05 +0000566 if (strcmp(name, "real") == 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000567 return (PyObject *)PyFloat_FromDouble(self->cval.real);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000568 else if (strcmp(name, "imag") == 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000569 return (PyObject *)PyFloat_FromDouble(self->cval.imag);
Guido van Rossumc054d701997-04-01 03:12:33 +0000570 else if (strcmp(name, "__members__") == 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000571 return Py_BuildValue("[ss]", "imag", "real");
572 return Py_FindMethod(complex_methods, (PyObject *)self, name);
Guido van Rossumf9fca921996-01-12 00:47:05 +0000573}
574
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000575static PyNumberMethods complex_as_number = {
Guido van Rossumbe4cbb12001-01-18 01:12:39 +0000576 (binaryfunc)complex_add, /* nb_add */
577 (binaryfunc)complex_sub, /* nb_subtract */
578 (binaryfunc)complex_mul, /* nb_multiply */
579 (binaryfunc)complex_div, /* nb_divide */
580 (binaryfunc)complex_remainder, /* nb_remainder */
581 (binaryfunc)complex_divmod, /* nb_divmod */
582 (ternaryfunc)complex_pow, /* nb_power */
583 (unaryfunc)complex_neg, /* nb_negative */
584 (unaryfunc)complex_pos, /* nb_positive */
585 (unaryfunc)complex_abs, /* nb_absolute */
586 (inquiry)complex_nonzero, /* nb_nonzero */
587 0, /* nb_invert */
588 0, /* nb_lshift */
589 0, /* nb_rshift */
590 0, /* nb_and */
591 0, /* nb_xor */
592 0, /* nb_or */
593 (coercion)complex_coerce, /* nb_coerce */
594 (unaryfunc)complex_int, /* nb_int */
595 (unaryfunc)complex_long, /* nb_long */
596 (unaryfunc)complex_float, /* nb_float */
597 0, /* nb_oct */
598 0, /* nb_hex */
Guido van Rossumf9fca921996-01-12 00:47:05 +0000599};
600
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000601PyTypeObject PyComplex_Type = {
602 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossumf9fca921996-01-12 00:47:05 +0000603 0,
604 "complex",
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000605 sizeof(PyComplexObject),
Guido van Rossumf9fca921996-01-12 00:47:05 +0000606 0,
Guido van Rossumbe4cbb12001-01-18 01:12:39 +0000607 (destructor)complex_dealloc, /* tp_dealloc */
608 (printfunc)complex_print, /* tp_print */
609 (getattrfunc)complex_getattr, /* tp_getattr */
610 0, /* tp_setattr */
611 0, /* tp_compare */
612 (reprfunc)complex_repr, /* tp_repr */
613 &complex_as_number, /* tp_as_number */
614 0, /* tp_as_sequence */
615 0, /* tp_as_mapping */
616 (hashfunc)complex_hash, /* tp_hash */
617 0, /* tp_call */
Tim Peters70695122001-03-11 08:37:29 +0000618 (reprfunc)complex_str, /* tp_str */
Guido van Rossumbe4cbb12001-01-18 01:12:39 +0000619 0, /* tp_getattro */
620 0, /* tp_setattro */
621 0, /* tp_as_buffer */
622 Py_TPFLAGS_DEFAULT, /* tp_flags */
623 0, /* tp_doc */
624 0, /* tp_traverse */
625 0, /* tp_clear */
626 complex_richcompare, /* tp_richcompare */
Guido van Rossumf9fca921996-01-12 00:47:05 +0000627};
628
629#endif