1 /* Complex object implementation */
3 /* Borrows heavily from floatobject.c */
5 #ifndef WITHOUT_COMPLEX
7 #include "allobjects.h"
8 #include "modsupport.h"
14 /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
19 #define CHECK(x) if (errno != 0) ; \
20 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
23 #define CHECK(x) /* Don't know how to check */
31 #define LONG_MAX 0X7FFFFFFFL
35 #define LONG_MIN (-LONG_MAX-1)
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
46 #define LONG_MIN (-LONG_MAX-1)
50 #if !defined(__STDC__) && !defined(macintosh)
51 extern double fmod
PROTO((double, double));
52 extern double pow
PROTO((double, double));
56 /* elementary operations on complex numbers */
59 static complex c_1
= {1., 0.};
65 r
.real
= a
.real
+ b
.real
;
66 r
.imag
= a
.imag
+ b
.imag
;
74 r
.real
= a
.real
- b
.real
;
75 r
.imag
= a
.imag
- b
.imag
;
92 r
.real
= a
.real
*b
.real
- a
.imag
*b
.imag
;
93 r
.imag
= a
.real
*b
.imag
+ a
.imag
*b
.real
;
101 double d
= b
.real
*b
.real
+ b
.imag
*b
.imag
;
104 r
.real
= (a
.real
*b
.real
+ a
.imag
*b
.imag
)/d
;
105 r
.imag
= (a
.imag
*b
.real
- a
.real
*b
.imag
)/d
;
113 double vabs
,len
,at
,phase
;
114 if (b
.real
== 0. && b
.imag
== 0.) {
118 else if (a
.real
== 0. && a
.imag
== 0.) {
119 if (b
.imag
!= 0. || b
.real
< 0.)
125 vabs
= hypot(a
.real
,a
.imag
);
126 len
= pow(vabs
,b
.real
);
127 at
= atan2(a
.imag
, a
.real
);
130 len
/= exp(at
*b
.imag
);
131 phase
+= b
.imag
*log(vabs
);
133 r
.real
= len
*cos(phase
);
134 r
.imag
= len
*sin(phase
);
139 static complex c_powu(x
, n
)
146 while (mask
> 0 && n
>= mask
) {
155 static complex c_powi(x
, n
)
161 if (n
> 100 || n
< -100) {
162 cn
.real
= (double) n
;
169 return c_quot(c_1
,c_powu(x
,-n
));
174 PyComplex_FromCComplex(complex cval
)
176 register complexobject
*op
= (complexobject
*) malloc(sizeof(complexobject
));
179 op
->ob_type
= &Complextype
;
182 return (object
*) op
;
186 PyComplex_FromDoubles(double real
, double imag
) {
190 return PyComplex_FromCComplex(c
);
194 PyComplex_RealAsDouble(PyObject
*op
) {
195 if (PyComplex_Check(op
)) {
196 return ((PyComplexObject
*)op
)->cval
.real
;
198 return PyFloat_AsDouble(op
);
203 PyComplex_ImagAsDouble(PyObject
*op
) {
204 if (PyComplex_Check(op
)) {
205 return ((PyComplexObject
*)op
)->cval
.imag
;
212 PyComplex_AsCComplex(PyObject
*op
) {
214 if (PyComplex_Check(op
)) {
215 return ((PyComplexObject
*)op
)->cval
;
217 cv
.real
= PyFloat_AsDouble(op
);
232 complex_buf_repr(buf
, v
)
236 if (v
->cval
.real
== 0.)
237 sprintf(buf
, "%.12gj", v
->cval
.imag
);
239 sprintf(buf
, "(%.12g%+.12gj)", v
->cval
.real
, v
->cval
.imag
);
243 complex_print(v
, fp
, flags
)
246 int flags
; /* Not used but required by interface */
249 complex_buf_repr(buf
, v
);
259 complex_buf_repr(buf
, v
);
260 return newstringobject(buf
);
264 complex_compare(v
, w
)
265 complexobject
*v
, *w
;
267 /* Note: "greater" and "smaller" have no meaning for complex numbers,
268 but Python requires that they be defined nevertheless. */
271 if (i
.real
== j
.real
&& i
.imag
== j
.imag
)
273 else if (i
.real
!= j
.real
)
274 return (i
.real
< j
.real
) ? -1 : 1;
276 return (i
.imag
< j
.imag
) ? -1 : 1;
283 double intpart
, fractpart
;
286 /* This is designed so that Python numbers with the same
287 value hash to the same value, otherwise comparisons
288 of mapping keys will turn out weird */
290 #ifdef MPW /* MPW C modf expects pointer to extended as second argument */
293 fractpart
= modf(v
->cval
.real
, &e
);
297 fractpart
= modf(v
->cval
.real
, &intpart
);
300 if (fractpart
== 0.0) {
301 if (intpart
> 0x7fffffffL
|| -intpart
> 0x7fffffffL
) {
302 /* Convert to long int and use its hash... */
303 object
*w
= dnewlongobject(v
->cval
.real
);
313 fractpart
= frexp(fractpart
, &expo
);
314 fractpart
= fractpart
*2147483648.0; /* 2**31 */
315 x
= (long) (intpart
+ fractpart
) ^ expo
; /* Rather arbitrary */
327 return newcomplexobject(c_sum(v
->cval
,w
->cval
));
335 return newcomplexobject(c_diff(v
->cval
,w
->cval
));
343 return newcomplexobject(c_prod(v
->cval
,w
->cval
));
353 quot
= c_quot(v
->cval
,w
->cval
);
355 err_setstr(ZeroDivisionError
, "float division");
358 return newcomplexobject(quot
);
372 if ((object
*)z
!=None
) {
373 err_setstr(ValueError
, "complex modulo");
378 exponent
= ((complexobject
*)w
)->cval
;
379 int_exponent
= (long)exponent
.real
;
380 if (exponent
.imag
== 0. && exponent
.real
== int_exponent
)
381 p
= c_powi(v
->cval
,int_exponent
);
383 p
= c_pow(v
->cval
,exponent
);
386 err_setstr(ValueError
, "0.0 to a negative or complex power");
390 return newcomplexobject(p
);
398 neg
.real
= -v
->cval
.real
;
399 neg
.imag
= -v
->cval
.imag
;
400 return newcomplexobject(neg
);
415 return newfloatobject(hypot(v
->cval
.real
,v
->cval
.imag
));
422 return v
->cval
.real
!= 0.0 && v
->cval
.imag
!= 0.0;
426 complex_coerce(pv
, pw
)
432 if (is_intobject(*pw
)) {
433 cval
.real
= (double)getintvalue(*pw
);
434 *pw
= newcomplexobject(cval
);
438 else if (is_longobject(*pw
)) {
439 cval
.real
= dgetlongvalue(*pw
);
440 *pw
= newcomplexobject(cval
);
444 else if (is_floatobject(*pw
)) {
445 cval
.real
= getfloatvalue(*pw
);
446 *pw
= newcomplexobject(cval
);
450 return 1; /* Can't do it */
457 double x
= ((complexobject
*)v
)->cval
.real
;
458 if (x
< 0 ? (x
= ceil(x
)) < (double)LONG_MIN
459 : (x
= floor(x
)) > (double)LONG_MAX
) {
460 err_setstr(OverflowError
, "float too large to convert");
463 return newintobject((long)x
);
470 double x
= ((complexobject
*)v
)->cval
.real
;
471 return dnewlongobject(x
);
478 double x
= ((complexobject
*)v
)->cval
.real
;
479 return newfloatobject(x
);
484 complex_new(self
, args
)
491 if (!PyArg_ParseTuple(args
, "d|d", &cval
.real
, &cval
.imag
))
493 return newcomplexobject(cval
);
497 complex_conjugate(self
)
500 complex c
= ((complexobject
*)self
)->cval
;
502 return newcomplexobject(c
);
505 static PyMethodDef complex_methods
[] = {
506 {"conjugate", (PyCFunction
)complex_conjugate
, 1},
507 {NULL
, NULL
} /* sentinel */
512 complex_getattr(self
, name
)
517 if (strcmp(name
, "real") == 0)
518 return (object
*)newfloatobject(self
->cval
.real
);
519 else if (strcmp(name
, "imag") == 0)
520 return (object
*)newfloatobject(self
->cval
.imag
);
521 else if (strcmp(name
, "conj") == 0) {
522 cval
.real
= self
->cval
.real
;
523 cval
.imag
= -self
->cval
.imag
;
524 return (object
*)newcomplexobject(cval
);
526 return findmethod(complex_methods
, (object
*)self
, name
);
529 static number_methods complex_as_number
= {
530 (binaryfunc
)complex_add
, /*nb_add*/
531 (binaryfunc
)complex_sub
, /*nb_subtract*/
532 (binaryfunc
)complex_mul
, /*nb_multiply*/
533 (binaryfunc
)complex_div
, /*nb_divide*/
536 (ternaryfunc
)complex_pow
, /*nb_power*/
537 (unaryfunc
)complex_neg
, /*nb_negative*/
538 (unaryfunc
)complex_pos
, /*nb_positive*/
539 (unaryfunc
)complex_abs
, /*nb_absolute*/
540 (inquiry
)complex_nonzero
, /*nb_nonzero*/
547 (coercion
)complex_coerce
, /*nb_coerce*/
548 (unaryfunc
)complex_int
, /*nb_int*/
549 (unaryfunc
)complex_long
, /*nb_long*/
550 (unaryfunc
)complex_float
, /*nb_float*/
555 typeobject Complextype
= {
556 OB_HEAD_INIT(&Typetype
)
559 sizeof(complexobject
),
561 (destructor
)complex_dealloc
, /*tp_dealloc*/
562 (printfunc
)complex_print
, /*tp_print*/
563 (getattrfunc
)complex_getattr
, /*tp_getattr*/
565 (cmpfunc
)complex_compare
, /*tp_compare*/
566 (reprfunc
)complex_repr
, /*tp_repr*/
567 &complex_as_number
, /*tp_as_number*/
568 0, /*tp_as_sequence*/
570 (hashfunc
)complex_hash
, /*tp_hash*/