1997-05-20 15:21:34 -03:00
|
|
|
|
1996-01-11 20:47:05 -04:00
|
|
|
/* Complex object implementation */
|
|
|
|
|
|
|
|
/* Borrows heavily from floatobject.c */
|
|
|
|
|
1997-05-20 15:21:34 -03:00
|
|
|
/* 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"
|
2001-08-02 01:15:00 -03:00
|
|
|
#include "structmember.h"
|
1996-01-11 20:47:05 -04:00
|
|
|
|
2001-03-11 04:37:29 -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
|
|
|
|
2001-03-18 04:21:57 -04: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;
|
|
|
|
}
|
|
|
|
|
2001-03-18 04:21:57 -04: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;
|
|
|
|
}
|
|
|
|
|
2001-03-18 04:21:57 -04: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;
|
|
|
|
}
|
|
|
|
|
2001-03-18 04:21:57 -04: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;
|
|
|
|
}
|
|
|
|
|
2001-03-18 04:21:57 -04:00
|
|
|
Py_complex
|
|
|
|
c_quot(Py_complex a, Py_complex b)
|
1996-01-11 20:47:05 -04:00
|
|
|
{
|
2001-03-18 04:21:57 -04:00
|
|
|
/******************************************************************
|
|
|
|
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:
|
|
|
|
|
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.)
|
1997-05-20 15:21:34 -03:00
|
|
|
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;
|
2001-03-18 04:21:57 -04:00
|
|
|
******************************************************************/
|
|
|
|
|
|
|
|
/* 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;
|
1996-01-11 20:47:05 -04:00
|
|
|
}
|
|
|
|
|
2001-03-18 04:21:57 -04: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.)
|
1997-05-20 15:21:34 -03:00
|
|
|
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);
|
2001-09-06 05:16:17 -03:00
|
|
|
at = atan2(a.imag, a.real);
|
1996-01-11 20:47:05 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2001-03-18 04:21:57 -04:00
|
|
|
static Py_complex
|
|
|
|
c_powu(Py_complex x, long n)
|
1996-01-11 20:47:05 -04:00
|
|
|
{
|
1996-08-19 16:30:45 -03:00
|
|
|
Py_complex r, p;
|
1996-01-11 20:47:05 -04:00
|
|
|
long mask = 1;
|
1996-08-19 16:30:45 -03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2001-03-18 04:21:57 -04: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));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-08-02 01:15:00 -03:00
|
|
|
static PyObject *
|
|
|
|
complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval)
|
|
|
|
{
|
|
|
|
PyObject *op;
|
|
|
|
|
|
|
|
op = PyType_GenericAlloc(type, 0);
|
|
|
|
if (op != NULL)
|
|
|
|
((PyComplexObject *)op)->cval = cval;
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
1996-01-11 20:47:05 -04:00
|
|
|
PyObject *
|
2000-07-09 01:36:04 -03:00
|
|
|
PyComplex_FromCComplex(Py_complex cval)
|
1996-01-11 20:47:05 -04:00
|
|
|
{
|
2000-05-03 20:44:39 -03: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();
|
2000-05-03 20:44:39 -03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2001-08-02 01:15:00 -03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
1996-01-11 20:47:05 -04:00
|
|
|
PyObject *
|
2000-07-09 01:36:04 -03:00
|
|
|
PyComplex_FromDoubles(double real, double imag)
|
1996-08-19 16:30:45 -03:00
|
|
|
{
|
|
|
|
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)
|
1996-08-19 16:30:45 -03:00
|
|
|
{
|
|
|
|
if (PyComplex_Check(op)) {
|
|
|
|
return ((PyComplexObject *)op)->cval.real;
|
2000-07-09 01:36:04 -03:00
|
|
|
}
|
|
|
|
else {
|
1996-08-19 16:30:45 -03:00
|
|
|
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)
|
1996-08-19 16:30:45 -03:00
|
|
|
{
|
|
|
|
if (PyComplex_Check(op)) {
|
|
|
|
return ((PyComplexObject *)op)->cval.imag;
|
2000-07-09 01:36:04 -03:00
|
|
|
}
|
|
|
|
else {
|
1996-08-19 16:30:45 -03:00
|
|
|
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-08-19 16:30:45 -03:00
|
|
|
{
|
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;
|
2001-03-11 04:37:29 -04:00
|
|
|
}
|
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
|
|
|
{
|
2001-10-05 17:51:39 -03:00
|
|
|
op->ob_type->tp_free(op);
|
1996-01-11 20:47:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1996-05-24 17:45:01 -03:00
|
|
|
static void
|
2001-11-28 16:50:56 -04:00
|
|
|
complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision)
|
1996-01-11 20:47:05 -04:00
|
|
|
{
|
|
|
|
if (v->cval.real == 0.)
|
2001-11-28 16:50:56 -04:00
|
|
|
PyOS_snprintf(buf, bufsz, "%.*gj",
|
|
|
|
precision, v->cval.imag);
|
1996-01-11 20:47:05 -04:00
|
|
|
else
|
2001-11-28 16:50:56 -04:00
|
|
|
PyOS_snprintf(buf, bufsz, "(%.*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];
|
2001-11-28 16:50:56 -04:00
|
|
|
complex_to_buf(buf, sizeof(buf), v,
|
2001-03-11 04:37:29 -04:00
|
|
|
(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];
|
2001-11-28 16:50:56 -04:00
|
|
|
complex_to_buf(buf, sizeof(buf), v, PREC_REPR);
|
2001-03-11 04:37:29 -04:00
|
|
|
return PyString_FromString(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
complex_str(PyComplexObject *v)
|
|
|
|
{
|
|
|
|
char buf[100];
|
2001-11-28 16:50:56 -04:00
|
|
|
complex_to_buf(buf, sizeof(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
|
|
|
{
|
2000-08-15 00:34:48 -03: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
|
|
|
{
|
1997-02-14 18:54:21 -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
|
|
|
{
|
1997-02-14 18:54:21 -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
|
|
|
{
|
1997-02-14 18:54:21 -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;
|
1997-02-14 18:54:21 -04:00
|
|
|
PyFPE_START_PROTECT("complex_div", return 0)
|
1997-05-20 15:21:34 -03:00
|
|
|
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)
|
1997-05-20 15:21:34 -03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
Add warning mode for classic division, almost exactly as specified in
PEP 238. Changes:
- add a new flag variable Py_DivisionWarningFlag, declared in
pydebug.h, defined in object.c, set in main.c, and used in
{int,long,float,complex}object.c. When this flag is set, the
classic division operator issues a DeprecationWarning message.
- add a new API PyRun_SimpleStringFlags() to match
PyRun_SimpleString(). The main() function calls this so that
commands run with -c can also benefit from -Dnew.
- While I was at it, I changed the usage message in main() somewhat:
alphabetized the options, split it in *four* parts to fit in under
512 bytes (not that I still believe this is necessary -- doc strings
elsewhere are much longer), and perhaps most visibly, don't display
the full list of options on each command line error. Instead, the
full list is only displayed when -h is used, and otherwise a brief
reminder of -h is displayed. When -h is used, write to stdout so
that you can do `python -h | more'.
Notes:
- I don't want to use the -W option to control whether the classic
division warning is issued or not, because the machinery to decide
whether to display the warning or not is very expensive (it involves
calling into the warnings.py module). You can use -Werror to turn
the warnings into exceptions though.
- The -Dnew option doesn't select future division for all of the
program -- only for the __main__ module. I don't know if I'll ever
change this -- it would require changes to the .pyc file magic
number to do it right, and a more global notion of compiler flags.
- You can usefully combine -Dwarn and -Dnew: this gives the __main__
module new division, and warns about classic division everywhere
else.
2001-08-31 14:40:15 -03:00
|
|
|
static PyObject *
|
|
|
|
complex_classic_div(PyComplexObject *v, PyComplexObject *w)
|
|
|
|
{
|
|
|
|
Py_complex quot;
|
|
|
|
|
2001-09-04 00:51:09 -03:00
|
|
|
if (Py_DivisionWarningFlag >= 2 &&
|
Add warning mode for classic division, almost exactly as specified in
PEP 238. Changes:
- add a new flag variable Py_DivisionWarningFlag, declared in
pydebug.h, defined in object.c, set in main.c, and used in
{int,long,float,complex}object.c. When this flag is set, the
classic division operator issues a DeprecationWarning message.
- add a new API PyRun_SimpleStringFlags() to match
PyRun_SimpleString(). The main() function calls this so that
commands run with -c can also benefit from -Dnew.
- While I was at it, I changed the usage message in main() somewhat:
alphabetized the options, split it in *four* parts to fit in under
512 bytes (not that I still believe this is necessary -- doc strings
elsewhere are much longer), and perhaps most visibly, don't display
the full list of options on each command line error. Instead, the
full list is only displayed when -h is used, and otherwise a brief
reminder of -h is displayed. When -h is used, write to stdout so
that you can do `python -h | more'.
Notes:
- I don't want to use the -W option to control whether the classic
division warning is issued or not, because the machinery to decide
whether to display the warning or not is very expensive (it involves
calling into the warnings.py module). You can use -Werror to turn
the warnings into exceptions though.
- The -Dnew option doesn't select future division for all of the
program -- only for the __main__ module. I don't know if I'll ever
change this -- it would require changes to the .pyc file magic
number to do it right, and a more global notion of compiler flags.
- You can usefully combine -Dwarn and -Dnew: this gives the __main__
module new division, and warns about classic division everywhere
else.
2001-08-31 14:40:15 -03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
1997-05-02 00:12:38 -03:00
|
|
|
static PyObject *
|
2000-07-09 01:36:04 -03:00
|
|
|
complex_remainder(PyComplexObject *v, PyComplexObject *w)
|
1996-09-11 10:55:55 -03:00
|
|
|
{
|
1996-09-12 17:56:18 -03:00
|
|
|
Py_complex div, mod;
|
1997-05-20 15:21:34 -03:00
|
|
|
errno = 0;
|
1996-09-12 17:56:18 -03:00
|
|
|
div = c_quot(v->cval,w->cval); /* The raw divisor value. */
|
1997-05-20 15:21:34 -03:00
|
|
|
if (errno == EDOM) {
|
1997-05-02 00:12:38 -03:00
|
|
|
PyErr_SetString(PyExc_ZeroDivisionError, "complex remainder");
|
1996-09-12 17:56:18 -03:00
|
|
|
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);
|
1996-09-11 10:55:55 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-05-02 00:12:38 -03:00
|
|
|
static PyObject *
|
2000-07-09 01:36:04 -03:00
|
|
|
complex_divmod(PyComplexObject *v, PyComplexObject *w)
|
1996-09-12 17:56:18 -03:00
|
|
|
{
|
|
|
|
Py_complex div, mod;
|
|
|
|
PyObject *d, *m, *z;
|
1997-05-20 15:21:34 -03:00
|
|
|
errno = 0;
|
1996-09-12 17:56:18 -03:00
|
|
|
div = c_quot(v->cval,w->cval); /* The raw divisor value. */
|
1997-05-20 15:21:34 -03:00
|
|
|
if (errno == EDOM) {
|
1997-05-02 00:12:38 -03:00
|
|
|
PyErr_SetString(PyExc_ZeroDivisionError, "complex divmod()");
|
1996-09-12 17:56:18 -03:00
|
|
|
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);
|
1996-09-12 17:56:18 -03:00
|
|
|
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;
|
|
|
|
}
|
1997-02-14 18:54:21 -04:00
|
|
|
PyFPE_START_PROTECT("complex_pow", return 0)
|
1997-05-20 15:21:34 -03:00
|
|
|
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)
|
1997-05-20 15:21:34 -03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2001-08-08 02:00:18 -03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2001-09-12 16:12:49 -03:00
|
|
|
if (PyComplex_CheckExact(v)) {
|
|
|
|
Py_INCREF(v);
|
|
|
|
return (PyObject *)v;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return PyComplex_FromCComplex(v->cval);
|
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
|
|
|
{
|
1997-02-14 18:54:21 -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
|
|
|
{
|
1999-01-25 15:42:19 -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);
|
2001-09-04 02:14:19 -03:00
|
|
|
if (cval.real == -1.0 && PyErr_Occurred())
|
|
|
|
return -1;
|
1997-05-02 00:12:38 -03:00
|
|
|
*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;
|
|
|
|
}
|
2001-09-18 22:13:10 -03:00
|
|
|
else if (PyComplex_Check(*pw)) {
|
|
|
|
Py_INCREF(*pv);
|
|
|
|
Py_INCREF(*pw);
|
|
|
|
return 0;
|
|
|
|
}
|
1996-01-11 20:47:05 -04:00
|
|
|
return 1; /* Can't do it */
|
|
|
|
}
|
|
|
|
|
2001-01-17 21:12:39 -04:00
|
|
|
static PyObject *
|
|
|
|
complex_richcompare(PyObject *v, PyObject *w, int op)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
Py_complex i, j;
|
|
|
|
PyObject *res;
|
|
|
|
|
|
|
|
c = PyNumber_CoerceEx(&v, &w);
|
|
|
|
if (c < 0)
|
|
|
|
return NULL;
|
|
|
|
if (c > 0) {
|
|
|
|
Py_INCREF(Py_NotImplemented);
|
|
|
|
return Py_NotImplemented;
|
|
|
|
}
|
2001-09-27 17:30:07 -03:00
|
|
|
/* Make sure both arguments are complex. */
|
|
|
|
if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
|
2001-01-17 21:12:39 -04:00
|
|
|
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);
|
|
|
|
|
2001-09-24 14:52:04 -03:00
|
|
|
if (op != Py_EQ && op != Py_NE) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"cannot compare complex numbers using <, <=, >, >=");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-01-17 21:12:39 -04:00
|
|
|
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,
|
1996-09-11 19:54:37 -03:00
|
|
|
"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,
|
1996-09-11 19:54:37 -03:00
|
|
|
"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,
|
1996-09-11 19:54:37 -03:00
|
|
|
"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 *
|
2001-08-16 10:15:00 -03:00
|
|
|
complex_conjugate(PyObject *self)
|
1996-01-11 20:47:05 -04:00
|
|
|
{
|
1996-08-19 16:30:45 -03:00
|
|
|
Py_complex c;
|
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[] = {
|
2001-08-16 10:15:00 -03:00
|
|
|
{"conjugate", (PyCFunction)complex_conjugate, METH_NOARGS},
|
1996-01-11 20:47:05 -04:00
|
|
|
{NULL, NULL} /* sentinel */
|
|
|
|
};
|
|
|
|
|
2001-09-20 17:46:19 -03:00
|
|
|
static PyMemberDef complex_members[] = {
|
|
|
|
{"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0,
|
|
|
|
"the real part of a complex number"},
|
|
|
|
{"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0,
|
|
|
|
"the imaginary part of a complex number"},
|
2001-08-02 01:15:00 -03:00
|
|
|
{0},
|
|
|
|
};
|
1996-01-11 20:47:05 -04:00
|
|
|
|
1997-05-02 00:12:38 -03:00
|
|
|
static PyObject *
|
2001-08-02 01:15:00 -03:00
|
|
|
complex_subtype_from_string(PyTypeObject *type, PyObject *v)
|
|
|
|
{
|
|
|
|
extern double strtod(const char *, char **);
|
|
|
|
const char *s, *start;
|
|
|
|
char *end;
|
|
|
|
double x=0.0, y=0.0, z;
|
|
|
|
int got_re=0, got_im=0, done=0;
|
|
|
|
int digit_or_dot;
|
|
|
|
int sw_error=0;
|
|
|
|
int sign;
|
|
|
|
char buffer[256]; /* For errors */
|
2001-10-25 15:07:22 -03:00
|
|
|
#ifdef Py_USING_UNICODE
|
|
|
|
char s_buffer[256];
|
|
|
|
#endif
|
2001-08-02 01:15:00 -03:00
|
|
|
int len;
|
|
|
|
|
|
|
|
if (PyString_Check(v)) {
|
|
|
|
s = PyString_AS_STRING(v);
|
|
|
|
len = PyString_GET_SIZE(v);
|
|
|
|
}
|
2001-08-17 15:39:25 -03:00
|
|
|
#ifdef Py_USING_UNICODE
|
2001-08-02 01:15:00 -03:00
|
|
|
else if (PyUnicode_Check(v)) {
|
|
|
|
if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"complex() literal too large to convert");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
|
|
|
|
PyUnicode_GET_SIZE(v),
|
|
|
|
s_buffer,
|
|
|
|
NULL))
|
|
|
|
return NULL;
|
|
|
|
s = s_buffer;
|
|
|
|
len = (int)strlen(s);
|
|
|
|
}
|
2001-08-17 15:39:25 -03:00
|
|
|
#endif
|
2001-08-02 01:15:00 -03:00
|
|
|
else if (PyObject_AsCharBuffer(v, &s, &len)) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"complex() arg is not a string");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* position on first nonblank */
|
|
|
|
start = s;
|
|
|
|
while (*s && isspace(Py_CHARMASK(*s)))
|
|
|
|
s++;
|
|
|
|
if (s[0] == '\0') {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"complex() arg is an empty string");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
z = -1.0;
|
|
|
|
sign = 1;
|
|
|
|
do {
|
|
|
|
|
|
|
|
switch (*s) {
|
|
|
|
|
|
|
|
case '\0':
|
|
|
|
if (s-start != len) {
|
|
|
|
PyErr_SetString(
|
|
|
|
PyExc_ValueError,
|
|
|
|
"complex() arg contains a null byte");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if(!done) sw_error=1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
sign = -1;
|
|
|
|
/* Fallthrough */
|
|
|
|
case '+':
|
|
|
|
if (done) sw_error=1;
|
|
|
|
s++;
|
|
|
|
if ( *s=='\0'||*s=='+'||*s=='-' ||
|
|
|
|
isspace(Py_CHARMASK(*s)) ) sw_error=1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'j':
|
|
|
|
if (got_im || done) {
|
|
|
|
sw_error = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (z<0.0) {
|
|
|
|
y=sign;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
y=sign*z;
|
|
|
|
}
|
|
|
|
got_im=1;
|
|
|
|
s++;
|
|
|
|
if (*s!='+' && *s!='-' )
|
|
|
|
done=1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (isspace(Py_CHARMASK(*s))) {
|
|
|
|
while (*s && isspace(Py_CHARMASK(*s)))
|
|
|
|
s++;
|
|
|
|
if (s[0] != '\0')
|
|
|
|
sw_error=1;
|
|
|
|
else
|
|
|
|
done = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
digit_or_dot =
|
|
|
|
(*s=='.' || isdigit(Py_CHARMASK(*s)));
|
|
|
|
if (done||!digit_or_dot) {
|
|
|
|
sw_error=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
errno = 0;
|
|
|
|
PyFPE_START_PROTECT("strtod", return 0)
|
|
|
|
z = strtod(s, &end) ;
|
|
|
|
PyFPE_END_PROTECT(z)
|
|
|
|
if (errno != 0) {
|
2001-11-28 16:50:56 -04:00
|
|
|
PyOS_snprintf(buffer, sizeof(buffer),
|
2001-08-02 01:15:00 -03:00
|
|
|
"float() out of range: %.150s", s);
|
|
|
|
PyErr_SetString(
|
|
|
|
PyExc_ValueError,
|
|
|
|
buffer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
s=end;
|
|
|
|
if (*s=='J' || *s=='j') {
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (got_re) {
|
|
|
|
sw_error=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* accept a real part */
|
|
|
|
x=sign*z;
|
|
|
|
got_re=1;
|
|
|
|
if (got_im) done=1;
|
|
|
|
z = -1.0;
|
|
|
|
sign = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
} /* end of switch */
|
|
|
|
|
|
|
|
} while (*s!='\0' && !sw_error);
|
|
|
|
|
|
|
|
if (sw_error) {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"complex() arg is a malformed string");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return complex_subtype_from_doubles(type, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
|
|
{
|
|
|
|
PyObject *r, *i, *tmp;
|
|
|
|
PyNumberMethods *nbr, *nbi = NULL;
|
|
|
|
Py_complex cr, ci;
|
|
|
|
int own_r = 0;
|
|
|
|
static char *kwlist[] = {"real", "imag", 0};
|
|
|
|
|
|
|
|
r = Py_False;
|
|
|
|
i = NULL;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist,
|
|
|
|
&r, &i))
|
|
|
|
return NULL;
|
|
|
|
if (PyString_Check(r) || PyUnicode_Check(r))
|
|
|
|
return complex_subtype_from_string(type, r);
|
2001-09-12 16:12:49 -03:00
|
|
|
|
|
|
|
nbr = r->ob_type->tp_as_number;
|
|
|
|
if (i != NULL)
|
|
|
|
nbi = i->ob_type->tp_as_number;
|
|
|
|
if (nbr == NULL || nbr->nb_float == NULL ||
|
|
|
|
((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) {
|
2001-08-02 01:15:00 -03:00
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"complex() arg can't be converted to complex");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* XXX Hack to support classes with __complex__ method */
|
|
|
|
if (PyInstance_Check(r)) {
|
|
|
|
static PyObject *complexstr;
|
|
|
|
PyObject *f;
|
|
|
|
if (complexstr == NULL) {
|
|
|
|
complexstr = PyString_InternFromString("__complex__");
|
|
|
|
if (complexstr == NULL)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
f = PyObject_GetAttr(r, complexstr);
|
|
|
|
if (f == NULL)
|
|
|
|
PyErr_Clear();
|
|
|
|
else {
|
|
|
|
PyObject *args = Py_BuildValue("()");
|
|
|
|
if (args == NULL)
|
|
|
|
return NULL;
|
|
|
|
r = PyEval_CallObject(f, args);
|
|
|
|
Py_DECREF(args);
|
|
|
|
Py_DECREF(f);
|
|
|
|
if (r == NULL)
|
|
|
|
return NULL;
|
|
|
|
own_r = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (PyComplex_Check(r)) {
|
2001-09-12 16:12:49 -03:00
|
|
|
/* Note that if r is of a complex subtype, we're only
|
|
|
|
retaining its real & imag parts here, and the return
|
|
|
|
value is (properly) of the builtin complex type. */
|
2001-08-02 01:15:00 -03:00
|
|
|
cr = ((PyComplexObject*)r)->cval;
|
|
|
|
if (own_r) {
|
|
|
|
Py_DECREF(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tmp = PyNumber_Float(r);
|
|
|
|
if (own_r) {
|
|
|
|
Py_DECREF(r);
|
|
|
|
}
|
|
|
|
if (tmp == NULL)
|
|
|
|
return NULL;
|
|
|
|
if (!PyFloat_Check(tmp)) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"float(r) didn't return a float");
|
|
|
|
Py_DECREF(tmp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
cr.real = PyFloat_AsDouble(tmp);
|
|
|
|
Py_DECREF(tmp);
|
|
|
|
cr.imag = 0.0;
|
|
|
|
}
|
|
|
|
if (i == NULL) {
|
|
|
|
ci.real = 0.0;
|
|
|
|
ci.imag = 0.0;
|
|
|
|
}
|
|
|
|
else if (PyComplex_Check(i))
|
|
|
|
ci = ((PyComplexObject*)i)->cval;
|
|
|
|
else {
|
|
|
|
tmp = (*nbi->nb_float)(i);
|
|
|
|
if (tmp == NULL)
|
|
|
|
return NULL;
|
|
|
|
ci.real = PyFloat_AsDouble(tmp);
|
|
|
|
Py_DECREF(tmp);
|
|
|
|
ci.imag = 0.;
|
|
|
|
}
|
|
|
|
cr.real -= ci.imag;
|
|
|
|
cr.imag += ci.real;
|
|
|
|
return complex_subtype_from_c_complex(type, cr);
|
1996-01-11 20:47:05 -04:00
|
|
|
}
|
|
|
|
|
2001-08-02 01:15:00 -03:00
|
|
|
static char complex_doc[] =
|
2001-09-12 16:12:49 -03:00
|
|
|
"complex(real[, imag]) -> complex number\n"
|
|
|
|
"\n"
|
|
|
|
"Create a complex number from a real part and an optional imaginary part.\n"
|
|
|
|
"This is equivalent to (real + imag*1j) where imag defaults to 0.";
|
2001-08-02 01:15:00 -03:00
|
|
|
|
1997-05-02 00:12:38 -03:00
|
|
|
static PyNumberMethods complex_as_number = {
|
2001-01-17 21:12:39 -04:00
|
|
|
(binaryfunc)complex_add, /* nb_add */
|
|
|
|
(binaryfunc)complex_sub, /* nb_subtract */
|
|
|
|
(binaryfunc)complex_mul, /* nb_multiply */
|
Add warning mode for classic division, almost exactly as specified in
PEP 238. Changes:
- add a new flag variable Py_DivisionWarningFlag, declared in
pydebug.h, defined in object.c, set in main.c, and used in
{int,long,float,complex}object.c. When this flag is set, the
classic division operator issues a DeprecationWarning message.
- add a new API PyRun_SimpleStringFlags() to match
PyRun_SimpleString(). The main() function calls this so that
commands run with -c can also benefit from -Dnew.
- While I was at it, I changed the usage message in main() somewhat:
alphabetized the options, split it in *four* parts to fit in under
512 bytes (not that I still believe this is necessary -- doc strings
elsewhere are much longer), and perhaps most visibly, don't display
the full list of options on each command line error. Instead, the
full list is only displayed when -h is used, and otherwise a brief
reminder of -h is displayed. When -h is used, write to stdout so
that you can do `python -h | more'.
Notes:
- I don't want to use the -W option to control whether the classic
division warning is issued or not, because the machinery to decide
whether to display the warning or not is very expensive (it involves
calling into the warnings.py module). You can use -Werror to turn
the warnings into exceptions though.
- The -Dnew option doesn't select future division for all of the
program -- only for the __main__ module. I don't know if I'll ever
change this -- it would require changes to the .pyc file magic
number to do it right, and a more global notion of compiler flags.
- You can usefully combine -Dwarn and -Dnew: this gives the __main__
module new division, and warns about classic division everywhere
else.
2001-08-31 14:40:15 -03:00
|
|
|
(binaryfunc)complex_classic_div, /* nb_divide */
|
2001-01-17 21:12:39 -04:00
|
|
|
(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 */
|
2001-08-08 02:00:18 -03:00
|
|
|
0, /* nb_inplace_add */
|
|
|
|
0, /* nb_inplace_subtract */
|
|
|
|
0, /* nb_inplace_multiply*/
|
|
|
|
0, /* nb_inplace_divide */
|
|
|
|
0, /* nb_inplace_remainder */
|
|
|
|
0, /* nb_inplace_power */
|
|
|
|
0, /* nb_inplace_lshift */
|
|
|
|
0, /* nb_inplace_rshift */
|
|
|
|
0, /* nb_inplace_and */
|
|
|
|
0, /* nb_inplace_xor */
|
|
|
|
0, /* nb_inplace_or */
|
|
|
|
(binaryfunc)complex_int_div, /* nb_floor_divide */
|
|
|
|
(binaryfunc)complex_div, /* nb_true_divide */
|
|
|
|
0, /* nb_inplace_floor_divide */
|
|
|
|
0, /* nb_inplace_true_divide */
|
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,
|
2001-01-17 21:12:39 -04:00
|
|
|
(destructor)complex_dealloc, /* tp_dealloc */
|
|
|
|
(printfunc)complex_print, /* tp_print */
|
2001-08-02 01:15:00 -03:00
|
|
|
0, /* tp_getattr */
|
2001-01-17 21:12:39 -04:00
|
|
|
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 */
|
2001-03-11 04:37:29 -04:00
|
|
|
(reprfunc)complex_str, /* tp_str */
|
2001-08-02 01:15:00 -03:00
|
|
|
PyObject_GenericGetAttr, /* tp_getattro */
|
2001-01-17 21:12:39 -04:00
|
|
|
0, /* tp_setattro */
|
|
|
|
0, /* tp_as_buffer */
|
2001-08-02 01:15:00 -03:00
|
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
|
|
complex_doc, /* tp_doc */
|
2001-01-17 21:12:39 -04:00
|
|
|
0, /* tp_traverse */
|
|
|
|
0, /* tp_clear */
|
|
|
|
complex_richcompare, /* tp_richcompare */
|
2001-08-02 01:15:00 -03:00
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
0, /* tp_iter */
|
|
|
|
0, /* tp_iternext */
|
|
|
|
complex_methods, /* tp_methods */
|
|
|
|
complex_members, /* tp_members */
|
|
|
|
0, /* tp_getset */
|
|
|
|
0, /* tp_base */
|
|
|
|
0, /* tp_dict */
|
|
|
|
0, /* tp_descr_get */
|
|
|
|
0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
0, /* tp_init */
|
|
|
|
0, /* tp_alloc */
|
|
|
|
complex_new, /* tp_new */
|
2001-10-05 17:51:39 -03:00
|
|
|
_PyObject_Del, /* tp_free */
|
1996-01-11 20:47:05 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|