/* Complex object implementation */ /* Borrows heavily from floatobject.c */ /* Submitted by Jim Hugunin */ #include "Python.h"#include "structmember.h" #ifndef WITHOUT_COMPLEX /* 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 /* elementary operations on complex numbers */ static Py_complex c_1 = {1., 0.}; Py_complexc_sum(Py_complex a, Py_complex b){ Py_complex r; r.real = a.real + b.real; r.imag = a.imag + b.imag; return r;} Py_complexc_diff(Py_complex a, Py_complex b){ Py_complex r; r.real = a.real - b.real; r.imag = a.imag - b.imag; return r;} Py_complexc_neg(Py_complex a){ Py_complex r; r.real = -a.real; r.imag = -a.imag; return r;} Py_complexc_prod(Py_complex a, Py_complex b){ Py_complex r; r.real = a.real*b.real - a.imag*b.imag; r.imag = a.real*b.imag + a.imag*b.real; return r;} Py_complexc_quot(Py_complex a, Py_complex b){ /****************************************************************** This was the original algorithm. It's grossly prone to spurious overflow and underflow errors. It also merrily divides by 0 despite checking for that(!). The code still serves a doc purpose here, as the algorithm following is a simple by-cases transformation of this one: Py_complex r; double d = b.real*b.real + b.imag*b.imag; if (d == 0.) errno = EDOM; r.real = (a.real*b.real + a.imag*b.imag)/d; r.imag = (a.imag*b.real - a.real*b.imag)/d; return r; ******************************************************************/ /* This algorithm is better, and is pretty obvious: first divide the * numerators and denominator by whichever of {b.real, b.imag} has * larger magnitude. The earliest reference I found was to CACM * Algorithm 116 (Complex Division, Robert L. Smith, Stanford * University). As usual, though, we're still ignoring all IEEE * endcases. */ Py_complex r; /* the result */ const double abs_breal = b.real < 0 ? -b.real : b.real; const double abs_bimag = b.imag < 0 ? -b.imag : b.imag; if (abs_breal >= abs_bimag) { /* divide tops and bottom by b.real */ if (abs_breal == 0.0) { errno = EDOM; r.real = r.imag = 0.0; } else { const double ratio = b.imag / b.real; const double denom = b.real + b.imag * ratio; r.real = (a.real + a.imag * ratio) / denom; r.imag = (a.imag - a.real * ratio) / denom; } } else { /* divide tops and bottom by b.imag */ const double ratio = b.real / b.imag; const double denom = b.real * ratio + b.imag; assert(b.imag != 0.0); r.real = (a.real * ratio + a.imag) / denom; r.imag = (a.imag * ratio - a.real) / denom; } return r;} Py_complexc_pow(Py_complex a, Py_complex b){ Py_complex r; 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 = EDOM; 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;} static Py_complexc_powu(Py_complex x, long n){ Py_complex r, p; long mask = 1; r = c_1; p = x; while (mask > 0 && n >= mask) { if (n & mask) r = c_prod(r,p); mask <<= 1; p = c_prod(p,p); } return r;} static Py_complexc_powi(Py_complex x, long n){ Py_complex cn; 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)); } static PyObject *complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval){ PyObject *op; op = type->tp_alloc(type, 0); if (op != NULL) ((PyComplexObject *)op)->cval = cval; return op;} PyObject *PyComplex_FromCComplex(Py_complex cval){ register PyComplexObject *op; /* Inline PyObject_New */ op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject)); if (op == NULL) return PyErr_NoMemory(); PyObject_INIT(op, &PyComplex_Type); op->cval = cval; return (PyObject *) op;} static PyObject *complex_subtype_from_doubles(PyTypeObject *type, double real, double imag){ Py_complex c; c.real = real; c.imag = imag; return complex_subtype_from_c_complex(type, c);} PyObject *PyComplex_FromDoubles(double real, double imag){ Py_complex c; c.real = real; c.imag = imag; return PyComplex_FromCComplex(c);} doublePyComplex_RealAsDouble(PyObject *op){ if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval.real; } else { return PyFloat_AsDouble(op); }} doublePyComplex_ImagAsDouble(PyObject *op){ if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval.imag; } else { return 0.0; }} Py_complexPyComplex_AsCComplex(PyObject *op){ Py_complex cv; if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval; } else { cv.real = PyFloat_AsDouble(op); cv.imag = 0.; return cv; }} static voidcomplex_dealloc(PyObject *op){ op->ob_type->tp_free(op);} static voidcomplex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision){ char format[32]; if (v->cval.real == 0.) { PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag); strncat(buf, "j", 1); } else { char re[64], im[64]; /* Format imaginary part with sign, real part without */ PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real); PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision); PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag); PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im); }} static intcomplex_print(PyComplexObject *v, FILE *fp, int flags){ char buf[100]; complex_to_buf(buf, sizeof(buf), v, (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR); fputs(buf, fp); return 0;} static PyObject *complex_repr(PyComplexObject *v){ char buf[100]; complex_to_buf(buf, sizeof(buf), v, PREC_REPR); return PyString_FromString(buf);} static PyObject *complex_str(PyComplexObject *v){ char buf[100]; complex_to_buf(buf, sizeof(buf), v, PREC_STR); return PyString_FromString(buf);} static longcomplex_hash(PyComplexObject *v){ 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;} static PyObject *complex_add(PyComplexObject *v, PyComplexObject *w){ Py_complex result; PyFPE_START_PROTECT("complex_add", return 0) result = c_sum(v->cval,w->cval); PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result);} static PyObject *complex_sub(PyComplexObject *v, PyComplexObject *w){ Py_complex result; PyFPE_START_PROTECT("complex_sub", return 0) result = c_diff(v->cval,w->cval); PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result);} static PyObject *complex_mul(PyComplexObject *v, PyComplexObject *w){ Py_complex result; PyFPE_START_PROTECT("complex_mul", return 0) result = c_prod(v->cval,w->cval); PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result);} static PyObject *complex_div(PyComplexObject *v, PyComplexObject *w){ Py_complex quot; PyFPE_START_PROTECT("complex_div", return 0) errno = 0; quot = c_quot(v->cval,w->cval); PyFPE_END_PROTECT(quot) if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "complex division"); return NULL; } return PyComplex_FromCComplex(quot);} static PyObject *complex_classic_div(PyComplexObject *v, PyComplexObject *w){ Py_complex quot; if (Py_DivisionWarningFlag >= 2 && PyErr_Warn(PyExc_DeprecationWarning, "classic complex division") < 0) return NULL; PyFPE_START_PROTECT("complex_classic_div", return 0) errno = 0; quot = c_quot(v->cval,w->cval); PyFPE_END_PROTECT(quot) if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "complex division"); return NULL; } return PyComplex_FromCComplex(quot);} static PyObject *complex_remainder(PyComplexObject *v, PyComplexObject *w){ Py_complex div, mod; if (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0) return NULL; errno = 0; div = c_quot(v->cval,w->cval); /* The raw divisor value. */ if (errno == EDOM) { 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)); return PyComplex_FromCComplex(mod);} static PyObject *complex_divmod(PyComplexObject *v, PyComplexObject *w){ Py_complex div, mod; PyObject *d, *m, *z; if (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0) return NULL; errno = 0; div = c_quot(v->cval,w->cval); /* The raw divisor value. */ if (errno == EDOM) { 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)); d = PyComplex_FromCComplex(div); m = PyComplex_FromCComplex(mod); z = PyTuple_Pack(2, d, m); Py_XDECREF(d); Py_XDECREF(m); return z;} static PyObject *complex_pow(PyComplexObject *v, PyObject *w, PyComplexObject *z){ Py_complex p; Py_complex exponent; long int_exponent; if ((PyObject *)z!=Py_None) { PyErr_SetString(PyExc_ValueError, "complex modulo"); return NULL; } PyFPE_START_PROTECT("complex_pow", return 0) errno = 0; exponent = ((PyComplexObject*)w)->cval; 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); PyFPE_END_PROTECT(p) Py_ADJUST_ERANGE2(p.real, p.imag); if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "0.0 to a negative or complex power"); return NULL; } else if (errno == ERANGE) { PyErr_SetString(PyExc_OverflowError, "complex exponentiation"); return NULL; } return PyComplex_FromCComplex(p);} static PyObject *complex_int_div(PyComplexObject *v, PyComplexObject *w){ PyObject *t, *r; t = complex_divmod(v, w); if (t != NULL) { r = PyTuple_GET_ITEM(t, 0); Py_INCREF(r); Py_DECREF(t); return r;Lines 1–500 of 1031. Load more
/* Complex object implementation */ /* Borrows heavily from floatobject.c */ /* Submitted by Jim Hugunin */ #include "Python.h" #include "structmember.h" #ifndef WITHOUT_COMPLEX /* 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 /* elementary operations on complex numbers */ static Py_complex c_1 = {1., 0.}; Py_complex c_sum(Py_complex a, Py_complex b) { Py_complex r; r.real = a.real + b.real; r.imag = a.imag + b.imag; return r; } Py_complex c_diff(Py_complex a, Py_complex b) { Py_complex r; r.real = a.real - b.real; r.imag = a.imag - b.imag; return r; } Py_complex c_neg(Py_complex a) { Py_complex r; r.real = -a.real; r.imag = -a.imag; return r; } Py_complex c_prod(Py_complex a, Py_complex b) { Py_complex r; r.real = a.real*b.real - a.imag*b.imag; r.imag = a.real*b.imag + a.imag*b.real; return r; } Py_complex c_quot(Py_complex a, Py_complex b) { /****************************************************************** This was the original algorithm. It's grossly prone to spurious overflow and underflow errors. It also merrily divides by 0 despite checking for that(!). The code still serves a doc purpose here, as the algorithm following is a simple by-cases transformation of this one: Py_complex r; double d = b.real*b.real + b.imag*b.imag; if (d == 0.) errno = EDOM; r.real = (a.real*b.real + a.imag*b.imag)/d; r.imag = (a.imag*b.real - a.real*b.imag)/d; return r; ******************************************************************/ /* This algorithm is better, and is pretty obvious: first divide the * numerators and denominator by whichever of {b.real, b.imag} has * larger magnitude. The earliest reference I found was to CACM * Algorithm 116 (Complex Division, Robert L. Smith, Stanford * University). As usual, though, we're still ignoring all IEEE * endcases. */ Py_complex r; /* the result */ const double abs_breal = b.real < 0 ? -b.real : b.real; const double abs_bimag = b.imag < 0 ? -b.imag : b.imag; if (abs_breal >= abs_bimag) { /* divide tops and bottom by b.real */ if (abs_breal == 0.0) { errno = EDOM; r.real = r.imag = 0.0; } else { const double ratio = b.imag / b.real; const double denom = b.real + b.imag * ratio; r.real = (a.real + a.imag * ratio) / denom; r.imag = (a.imag - a.real * ratio) / denom; } } else { /* divide tops and bottom by b.imag */ const double ratio = b.real / b.imag; const double denom = b.real * ratio + b.imag; assert(b.imag != 0.0); r.real = (a.real * ratio + a.imag) / denom; r.imag = (a.imag * ratio - a.real) / denom; } return r; } Py_complex c_pow(Py_complex a, Py_complex b) { Py_complex r; 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 = EDOM; 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; } static Py_complex c_powu(Py_complex x, long n) { Py_complex r, p; long mask = 1; r = c_1; p = x; while (mask > 0 && n >= mask) { if (n & mask) r = c_prod(r,p); mask <<= 1; p = c_prod(p,p); } return r; } static Py_complex c_powi(Py_complex x, long n) { Py_complex cn; 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)); } static PyObject * complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval) { PyObject *op; op = type->tp_alloc(type, 0); if (op != NULL) ((PyComplexObject *)op)->cval = cval; return op; } PyObject * PyComplex_FromCComplex(Py_complex cval) { register PyComplexObject *op; /* Inline PyObject_New */ op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject)); if (op == NULL) return PyErr_NoMemory(); PyObject_INIT(op, &PyComplex_Type); op->cval = cval; return (PyObject *) op; } static PyObject * complex_subtype_from_doubles(PyTypeObject *type, double real, double imag) { Py_complex c; c.real = real; c.imag = imag; return complex_subtype_from_c_complex(type, c); } PyObject * PyComplex_FromDoubles(double real, double imag) { Py_complex c; c.real = real; c.imag = imag; return PyComplex_FromCComplex(c); } double PyComplex_RealAsDouble(PyObject *op) { if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval.real; } else { return PyFloat_AsDouble(op); } } double PyComplex_ImagAsDouble(PyObject *op) { if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval.imag; } else { return 0.0; } } Py_complex PyComplex_AsCComplex(PyObject *op) { Py_complex cv; if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval; } else { cv.real = PyFloat_AsDouble(op); cv.imag = 0.; return cv; } } static void complex_dealloc(PyObject *op) { op->ob_type->tp_free(op); } static void complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision) { char format[32]; if (v->cval.real == 0.) { PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag); strncat(buf, "j", 1); } else { char re[64], im[64]; /* Format imaginary part with sign, real part without */ PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real); PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision); PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag); PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im); } } static int complex_print(PyComplexObject *v, FILE *fp, int flags) { char buf[100]; complex_to_buf(buf, sizeof(buf), v, (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR); fputs(buf, fp); return 0; } static PyObject * complex_repr(PyComplexObject *v) { char buf[100]; complex_to_buf(buf, sizeof(buf), v, PREC_REPR); return PyString_FromString(buf); } static PyObject * complex_str(PyComplexObject *v) { char buf[100]; complex_to_buf(buf, sizeof(buf), v, PREC_STR); return PyString_FromString(buf); } static long complex_hash(PyComplexObject *v) { 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; } static PyObject * complex_add(PyComplexObject *v, PyComplexObject *w) { Py_complex result; PyFPE_START_PROTECT("complex_add", return 0) result = c_sum(v->cval,w->cval); PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result); } static PyObject * complex_sub(PyComplexObject *v, PyComplexObject *w) { Py_complex result; PyFPE_START_PROTECT("complex_sub", return 0) result = c_diff(v->cval,w->cval); PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result); } static PyObject * complex_mul(PyComplexObject *v, PyComplexObject *w) { Py_complex result; PyFPE_START_PROTECT("complex_mul", return 0) result = c_prod(v->cval,w->cval); PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result); } static PyObject * complex_div(PyComplexObject *v, PyComplexObject *w) { Py_complex quot; PyFPE_START_PROTECT("complex_div", return 0) errno = 0; quot = c_quot(v->cval,w->cval); PyFPE_END_PROTECT(quot) if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "complex division"); return NULL; } return PyComplex_FromCComplex(quot); } static PyObject * complex_classic_div(PyComplexObject *v, PyComplexObject *w) { Py_complex quot; if (Py_DivisionWarningFlag >= 2 && PyErr_Warn(PyExc_DeprecationWarning, "classic complex division") < 0) return NULL; PyFPE_START_PROTECT("complex_classic_div", return 0) errno = 0; quot = c_quot(v->cval,w->cval); PyFPE_END_PROTECT(quot) if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "complex division"); return NULL; } return PyComplex_FromCComplex(quot); } static PyObject * complex_remainder(PyComplexObject *v, PyComplexObject *w) { Py_complex div, mod; if (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0) return NULL; errno = 0; div = c_quot(v->cval,w->cval); /* The raw divisor value. */ if (errno == EDOM) { 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)); return PyComplex_FromCComplex(mod); } static PyObject * complex_divmod(PyComplexObject *v, PyComplexObject *w) { Py_complex div, mod; PyObject *d, *m, *z; if (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0) return NULL; errno = 0; div = c_quot(v->cval,w->cval); /* The raw divisor value. */ if (errno == EDOM) { 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)); d = PyComplex_FromCComplex(div); m = PyComplex_FromCComplex(mod); z = PyTuple_Pack(2, d, m); Py_XDECREF(d); Py_XDECREF(m); return z; } static PyObject * complex_pow(PyComplexObject *v, PyObject *w, PyComplexObject *z) { Py_complex p; Py_complex exponent; long int_exponent; if ((PyObject *)z!=Py_None) { PyErr_SetString(PyExc_ValueError, "complex modulo"); return NULL; } PyFPE_START_PROTECT("complex_pow", return 0) errno = 0; exponent = ((PyComplexObject*)w)->cval; 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); PyFPE_END_PROTECT(p) Py_ADJUST_ERANGE2(p.real, p.imag); if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "0.0 to a negative or complex power"); return NULL; } else if (errno == ERANGE) { PyErr_SetString(PyExc_OverflowError, "complex exponentiation"); return NULL; } return PyComplex_FromCComplex(p); } static PyObject * complex_int_div(PyComplexObject *v, PyComplexObject *w) { PyObject *t, *r; t = complex_divmod(v, w); if (t != NULL) { r = PyTuple_GET_ITEM(t, 0); Py_INCREF(r); Py_DECREF(t); return r;