cpython/Objects/complexobject.c

580 lines
12 KiB
C
Raw Normal View History

1996-01-11 20:47:05 -04:00
/* Complex object implementation */
/* Borrows heavily from floatobject.c */
/* Submitted by Jim Hugunin */
1996-01-11 20:47:05 -04:00
#ifndef WITHOUT_COMPLEX
1997-05-02 00:12:38 -03:00
#include "Python.h"
1996-01-11 20:47:05 -04:00
/* Precisions used by repr() and str(), respectively.
The repr() precision (17 significant decimal digits) is the minimal number
that is guaranteed to have enough precision so that if the number is read
back in the exact same binary value is recreated. This is true for IEEE
floating point by design, and also happens to work for all other modern
hardware.
The str() precision is chosen so that in most cases, the rounding noise
created by various operations is suppressed, while giving plenty of
precision for practical use.
*/
#define PREC_REPR 17
#define PREC_STR 12
1996-01-11 20:47:05 -04:00
/* elementary operations on complex numbers */
1996-07-20 23:31:35 -03:00
static Py_complex c_1 = {1., 0.};
1996-01-11 20:47:05 -04:00
2000-07-09 01:36:04 -03:00
Py_complex c_sum(Py_complex a, Py_complex b)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex r;
1996-01-11 20:47:05 -04:00
r.real = a.real + b.real;
r.imag = a.imag + b.imag;
return r;
}
2000-07-09 01:36:04 -03:00
Py_complex c_diff(Py_complex a, Py_complex b)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex r;
1996-01-11 20:47:05 -04:00
r.real = a.real - b.real;
r.imag = a.imag - b.imag;
return r;
}
2000-07-09 01:36:04 -03:00
Py_complex c_neg(Py_complex a)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex r;
1996-01-11 20:47:05 -04:00
r.real = -a.real;
r.imag = -a.imag;
return r;
}
2000-07-09 01:36:04 -03:00
Py_complex c_prod(Py_complex a, Py_complex b)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex r;
1996-01-11 20:47:05 -04:00
r.real = a.real*b.real - a.imag*b.imag;
r.imag = a.real*b.imag + a.imag*b.real;
return r;
}
2000-07-09 01:36:04 -03:00
Py_complex c_quot(Py_complex a, Py_complex b)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex r;
1996-01-11 20:47:05 -04:00
double d = b.real*b.real + b.imag*b.imag;
if (d == 0.)
errno = EDOM;
1996-01-11 20:47:05 -04:00
r.real = (a.real*b.real + a.imag*b.imag)/d;
r.imag = (a.imag*b.real - a.real*b.imag)/d;
return r;
}
2000-07-09 01:36:04 -03:00
Py_complex c_pow(Py_complex a, Py_complex b)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex r;
1996-01-11 20:47:05 -04:00
double vabs,len,at,phase;
if (b.real == 0. && b.imag == 0.) {
r.real = 1.;
r.imag = 0.;
}
else if (a.real == 0. && a.imag == 0.) {
if (b.imag != 0. || b.real < 0.)
errno = ERANGE;
1996-01-11 20:47:05 -04:00
r.real = 0.;
r.imag = 0.;
}
else {
vabs = hypot(a.real,a.imag);
len = pow(vabs,b.real);
at = atan2(a.imag, a.real);
phase = at*b.real;
if (b.imag != 0.0) {
len /= exp(at*b.imag);
phase += b.imag*log(vabs);
}
r.real = len*cos(phase);
r.imag = len*sin(phase);
}
return r;
}
2000-07-09 01:36:04 -03:00
static Py_complex c_powu(Py_complex x, long n)
1996-01-11 20:47:05 -04:00
{
Py_complex r, p;
1996-01-11 20:47:05 -04:00
long mask = 1;
r = c_1;
p = x;
1996-01-11 20:47:05 -04:00
while (mask > 0 && n >= mask) {
if (n & mask)
r = c_prod(r,p);
mask <<= 1;
p = c_prod(p,p);
}
return r;
}
2000-07-09 01:36:04 -03:00
static Py_complex c_powi(Py_complex x, long n)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex cn;
1996-01-11 20:47:05 -04:00
if (n > 100 || n < -100) {
cn.real = (double) n;
cn.imag = 0.;
return c_pow(x,cn);
}
else if (n > 0)
return c_powu(x,n);
else
return c_quot(c_1,c_powu(x,-n));
}
PyObject *
2000-07-09 01:36:04 -03:00
PyComplex_FromCComplex(Py_complex cval)
1996-01-11 20:47:05 -04:00
{
register PyComplexObject *op;
/* PyObject_New is inlined */
op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
1996-01-11 20:47:05 -04:00
if (op == NULL)
1997-05-02 00:12:38 -03:00
return PyErr_NoMemory();
PyObject_INIT(op, &PyComplex_Type);
1996-01-11 20:47:05 -04:00
op->cval = cval;
1997-05-02 00:12:38 -03:00
return (PyObject *) op;
1996-01-11 20:47:05 -04:00
}
PyObject *
2000-07-09 01:36:04 -03:00
PyComplex_FromDoubles(double real, double imag)
{
Py_complex c;
c.real = real;
c.imag = imag;
return PyComplex_FromCComplex(c);
1996-01-11 20:47:05 -04:00
}
double
2000-07-09 01:36:04 -03:00
PyComplex_RealAsDouble(PyObject *op)
{
if (PyComplex_Check(op)) {
return ((PyComplexObject *)op)->cval.real;
2000-07-09 01:36:04 -03:00
}
else {
return PyFloat_AsDouble(op);
}
1996-01-11 20:47:05 -04:00
}
double
2000-07-09 01:36:04 -03:00
PyComplex_ImagAsDouble(PyObject *op)
{
if (PyComplex_Check(op)) {
return ((PyComplexObject *)op)->cval.imag;
2000-07-09 01:36:04 -03:00
}
else {
return 0.0;
}
1996-01-11 20:47:05 -04:00
}
1996-07-20 23:31:35 -03:00
Py_complex
2000-07-09 01:36:04 -03:00
PyComplex_AsCComplex(PyObject *op)
{
1996-07-20 23:31:35 -03:00
Py_complex cv;
1996-01-11 21:21:14 -04:00
if (PyComplex_Check(op)) {
return ((PyComplexObject *)op)->cval;
2000-07-09 01:36:04 -03:00
}
else {
1996-01-11 21:21:14 -04:00
cv.real = PyFloat_AsDouble(op);
cv.imag = 0.;
return cv;
}
1996-01-11 21:21:14 -04:00
}
1996-01-11 20:47:05 -04:00
static void
2000-07-09 01:36:04 -03:00
complex_dealloc(PyObject *op)
1996-01-11 20:47:05 -04:00
{
PyObject_DEL(op);
1996-01-11 20:47:05 -04:00
}
1996-05-24 17:45:01 -03:00
static void
complex_to_buf(char *buf, PyComplexObject *v, int precision)
1996-01-11 20:47:05 -04:00
{
if (v->cval.real == 0.)
sprintf(buf, "%.*gj", precision, v->cval.imag);
1996-01-11 20:47:05 -04:00
else
sprintf(buf, "(%.*g%+.*gj)", precision, v->cval.real,
precision, v->cval.imag);
1996-01-11 20:47:05 -04:00
}
static int
2000-07-09 01:36:04 -03:00
complex_print(PyComplexObject *v, FILE *fp, int flags)
1996-01-11 20:47:05 -04:00
{
char buf[100];
complex_to_buf(buf, v,
(flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
1996-01-11 20:47:05 -04:00
fputs(buf, fp);
return 0;
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_repr(PyComplexObject *v)
1996-01-11 20:47:05 -04:00
{
char buf[100];
complex_to_buf(buf, v, PREC_REPR);
return PyString_FromString(buf);
}
static PyObject *
complex_str(PyComplexObject *v)
{
char buf[100];
complex_to_buf(buf, v, PREC_STR);
1997-05-02 00:12:38 -03:00
return PyString_FromString(buf);
1996-01-11 20:47:05 -04:00
}
static long
2000-07-09 01:36:04 -03:00
complex_hash(PyComplexObject *v)
1996-01-11 20:47:05 -04:00
{
long hashreal, hashimag, combined;
hashreal = _Py_HashDouble(v->cval.real);
if (hashreal == -1)
return -1;
hashimag = _Py_HashDouble(v->cval.imag);
if (hashimag == -1)
return -1;
/* Note: if the imaginary part is 0, hashimag is 0 now,
* so the following returns hashreal unchanged. This is
* important because numbers of different types that
* compare equal must have the same hash value, so that
* hash(x + 0*j) must equal hash(x).
*/
combined = hashreal + 1000003 * hashimag;
if (combined == -1)
combined = -2;
return combined;
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_add(PyComplexObject *v, PyComplexObject *w)
1996-01-11 20:47:05 -04:00
{
Py_complex result;
PyFPE_START_PROTECT("complex_add", return 0)
result = c_sum(v->cval,w->cval);
1997-03-14 00:32:50 -04:00
PyFPE_END_PROTECT(result)
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(result);
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_sub(PyComplexObject *v, PyComplexObject *w)
1996-01-11 20:47:05 -04:00
{
Py_complex result;
PyFPE_START_PROTECT("complex_sub", return 0)
result = c_diff(v->cval,w->cval);
1997-03-14 00:32:50 -04:00
PyFPE_END_PROTECT(result)
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(result);
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_mul(PyComplexObject *v, PyComplexObject *w)
1996-01-11 20:47:05 -04:00
{
Py_complex result;
PyFPE_START_PROTECT("complex_mul", return 0)
result = c_prod(v->cval,w->cval);
1997-03-14 00:32:50 -04:00
PyFPE_END_PROTECT(result)
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(result);
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_div(PyComplexObject *v, PyComplexObject *w)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex quot;
PyFPE_START_PROTECT("complex_div", return 0)
errno = 0;
1996-01-11 20:47:05 -04:00
quot = c_quot(v->cval,w->cval);
1997-03-14 00:32:50 -04:00
PyFPE_END_PROTECT(quot)
if (errno == EDOM) {
1997-05-02 00:12:38 -03:00
PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
1996-01-11 20:47:05 -04:00
return NULL;
}
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(quot);
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_remainder(PyComplexObject *v, PyComplexObject *w)
{
Py_complex div, mod;
errno = 0;
div = c_quot(v->cval,w->cval); /* The raw divisor value. */
if (errno == EDOM) {
1997-05-02 00:12:38 -03:00
PyErr_SetString(PyExc_ZeroDivisionError, "complex remainder");
return NULL;
}
div.real = floor(div.real); /* Use the floor of the real part. */
div.imag = 0.0;
mod = c_diff(v->cval, c_prod(w->cval, div));
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(mod);
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_divmod(PyComplexObject *v, PyComplexObject *w)
{
Py_complex div, mod;
PyObject *d, *m, *z;
errno = 0;
div = c_quot(v->cval,w->cval); /* The raw divisor value. */
if (errno == EDOM) {
1997-05-02 00:12:38 -03:00
PyErr_SetString(PyExc_ZeroDivisionError, "complex divmod()");
return NULL;
}
div.real = floor(div.real); /* Use the floor of the real part. */
div.imag = 0.0;
mod = c_diff(v->cval, c_prod(w->cval, div));
1997-05-02 00:12:38 -03:00
d = PyComplex_FromCComplex(div);
m = PyComplex_FromCComplex(mod);
z = Py_BuildValue("(OO)", d, m);
Py_XDECREF(d);
Py_XDECREF(m);
return z;
}
1996-01-11 20:47:05 -04:00
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_pow(PyComplexObject *v, PyObject *w, PyComplexObject *z)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex p;
Py_complex exponent;
1996-01-11 20:47:05 -04:00
long int_exponent;
1997-05-02 00:12:38 -03:00
if ((PyObject *)z!=Py_None) {
PyErr_SetString(PyExc_ValueError, "complex modulo");
1996-01-11 20:47:05 -04:00
return NULL;
}
PyFPE_START_PROTECT("complex_pow", return 0)
errno = 0;
1997-05-02 00:12:38 -03:00
exponent = ((PyComplexObject*)w)->cval;
1996-01-11 20:47:05 -04:00
int_exponent = (long)exponent.real;
if (exponent.imag == 0. && exponent.real == int_exponent)
p = c_powi(v->cval,int_exponent);
else
p = c_pow(v->cval,exponent);
1997-03-14 00:32:50 -04:00
PyFPE_END_PROTECT(p)
if (errno == ERANGE) {
1997-05-02 00:12:38 -03:00
PyErr_SetString(PyExc_ValueError,
"0.0 to a negative or complex power");
1996-01-11 20:47:05 -04:00
return NULL;
}
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(p);
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_neg(PyComplexObject *v)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex neg;
1996-01-11 20:47:05 -04:00
neg.real = -v->cval.real;
neg.imag = -v->cval.imag;
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(neg);
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_pos(PyComplexObject *v)
1996-01-11 20:47:05 -04:00
{
1997-05-02 00:12:38 -03:00
Py_INCREF(v);
return (PyObject *)v;
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_abs(PyComplexObject *v)
1996-01-11 20:47:05 -04:00
{
double result;
PyFPE_START_PROTECT("complex_abs", return 0)
result = hypot(v->cval.real,v->cval.imag);
1997-03-14 00:32:50 -04:00
PyFPE_END_PROTECT(result)
1997-05-02 00:12:38 -03:00
return PyFloat_FromDouble(result);
1996-01-11 20:47:05 -04:00
}
static int
2000-07-09 01:36:04 -03:00
complex_nonzero(PyComplexObject *v)
1996-01-11 20:47:05 -04:00
{
return v->cval.real != 0.0 || v->cval.imag != 0.0;
1996-01-11 20:47:05 -04:00
}
static int
2000-07-09 01:36:04 -03:00
complex_coerce(PyObject **pv, PyObject **pw)
1996-01-11 20:47:05 -04:00
{
1996-07-20 23:31:35 -03:00
Py_complex cval;
1996-01-11 20:47:05 -04:00
cval.imag = 0.;
1997-05-02 00:12:38 -03:00
if (PyInt_Check(*pw)) {
cval.real = (double)PyInt_AsLong(*pw);
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
1996-01-11 20:47:05 -04:00
return 0;
}
1997-05-02 00:12:38 -03:00
else if (PyLong_Check(*pw)) {
cval.real = PyLong_AsDouble(*pw);
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
1996-01-11 20:47:05 -04:00
return 0;
}
1997-05-02 00:12:38 -03:00
else if (PyFloat_Check(*pw)) {
cval.real = PyFloat_AsDouble(*pw);
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
1996-01-11 20:47:05 -04:00
return 0;
}
return 1; /* Can't do it */
}
static PyObject *
complex_richcompare(PyObject *v, PyObject *w, int op)
{
int c;
Py_complex i, j;
PyObject *res;
if (op != Py_EQ && op != Py_NE) {
PyErr_SetString(PyExc_TypeError,
"cannot compare complex numbers using <, <=, >, >=");
return NULL;
}
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
return NULL;
if (c > 0) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
if (!PyComplex_Check(v) || !PyComplex_Check(w)) {
Py_DECREF(v);
Py_DECREF(w);
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
i = ((PyComplexObject *)v)->cval;
j = ((PyComplexObject *)w)->cval;
Py_DECREF(v);
Py_DECREF(w);
if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ))
res = Py_True;
else
res = Py_False;
Py_INCREF(res);
return res;
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_int(PyObject *v)
1996-01-11 20:47:05 -04:00
{
1997-05-02 00:12:38 -03:00
PyErr_SetString(PyExc_TypeError,
"can't convert complex to int; use e.g. int(abs(z))");
return NULL;
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_long(PyObject *v)
1996-01-11 20:47:05 -04:00
{
1997-05-02 00:12:38 -03:00
PyErr_SetString(PyExc_TypeError,
"can't convert complex to long; use e.g. long(abs(z))");
return NULL;
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_float(PyObject *v)
1996-01-11 20:47:05 -04:00
{
1997-05-02 00:12:38 -03:00
PyErr_SetString(PyExc_TypeError,
"can't convert complex to float; use e.g. abs(z)");
return NULL;
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_conjugate(PyObject *self, PyObject *args)
1996-01-11 20:47:05 -04:00
{
Py_complex c;
if (!PyArg_ParseTuple(args, ":conjugate"))
return NULL;
1997-05-02 00:12:38 -03:00
c = ((PyComplexObject *)self)->cval;
1996-01-11 20:47:05 -04:00
c.imag = -c.imag;
1997-05-02 00:12:38 -03:00
return PyComplex_FromCComplex(c);
1996-01-11 20:47:05 -04:00
}
static PyMethodDef complex_methods[] = {
{"conjugate", complex_conjugate, 1},
1996-01-11 20:47:05 -04:00
{NULL, NULL} /* sentinel */
};
1997-05-02 00:12:38 -03:00
static PyObject *
2000-07-09 01:36:04 -03:00
complex_getattr(PyComplexObject *self, char *name)
1996-01-11 20:47:05 -04:00
{
if (strcmp(name, "real") == 0)
1997-05-02 00:12:38 -03:00
return (PyObject *)PyFloat_FromDouble(self->cval.real);
1996-01-11 20:47:05 -04:00
else if (strcmp(name, "imag") == 0)
1997-05-02 00:12:38 -03:00
return (PyObject *)PyFloat_FromDouble(self->cval.imag);
else if (strcmp(name, "__members__") == 0)
1997-05-02 00:12:38 -03:00
return Py_BuildValue("[ss]", "imag", "real");
return Py_FindMethod(complex_methods, (PyObject *)self, name);
1996-01-11 20:47:05 -04:00
}
1997-05-02 00:12:38 -03:00
static PyNumberMethods complex_as_number = {
(binaryfunc)complex_add, /* nb_add */
(binaryfunc)complex_sub, /* nb_subtract */
(binaryfunc)complex_mul, /* nb_multiply */
(binaryfunc)complex_div, /* nb_divide */
(binaryfunc)complex_remainder, /* nb_remainder */
(binaryfunc)complex_divmod, /* nb_divmod */
(ternaryfunc)complex_pow, /* nb_power */
(unaryfunc)complex_neg, /* nb_negative */
(unaryfunc)complex_pos, /* nb_positive */
(unaryfunc)complex_abs, /* nb_absolute */
(inquiry)complex_nonzero, /* nb_nonzero */
0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
(coercion)complex_coerce, /* nb_coerce */
(unaryfunc)complex_int, /* nb_int */
(unaryfunc)complex_long, /* nb_long */
(unaryfunc)complex_float, /* nb_float */
0, /* nb_oct */
0, /* nb_hex */
1996-01-11 20:47:05 -04:00
};
1997-05-02 00:12:38 -03:00
PyTypeObject PyComplex_Type = {
PyObject_HEAD_INIT(&PyType_Type)
1996-01-11 20:47:05 -04:00
0,
"complex",
1997-05-02 00:12:38 -03:00
sizeof(PyComplexObject),
1996-01-11 20:47:05 -04:00
0,
(destructor)complex_dealloc, /* tp_dealloc */
(printfunc)complex_print, /* tp_print */
(getattrfunc)complex_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)complex_repr, /* tp_repr */
&complex_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)complex_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)complex_str, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
complex_richcompare, /* tp_richcompare */
1996-01-11 20:47:05 -04:00
};
#endif