mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Merge of descr-branch back into trunk.
This commit is contained in:
parent
52d55a3926
commit
6d6c1a35e0
57 changed files with 6923 additions and 1309 deletions
|
@ -8,6 +8,7 @@
|
|||
#ifndef WITHOUT_COMPLEX
|
||||
|
||||
#include "Python.h"
|
||||
#include "structmember.h"
|
||||
|
||||
/* Precisions used by repr() and str(), respectively.
|
||||
|
||||
|
@ -182,6 +183,17 @@ c_powi(Py_complex x, long n)
|
|||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyComplex_FromCComplex(Py_complex cval)
|
||||
{
|
||||
|
@ -196,6 +208,15 @@ PyComplex_FromCComplex(Py_complex 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)
|
||||
{
|
||||
|
@ -559,19 +580,261 @@ static PyMethodDef complex_methods[] = {
|
|||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static struct memberlist complex_members[] = {
|
||||
{"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0},
|
||||
{"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0},
|
||||
{0},
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
complex_getattr(PyComplexObject *self, char *name)
|
||||
complex_subtype_from_string(PyTypeObject *type, PyObject *v)
|
||||
{
|
||||
if (strcmp(name, "real") == 0)
|
||||
return (PyObject *)PyFloat_FromDouble(self->cval.real);
|
||||
else if (strcmp(name, "imag") == 0)
|
||||
return (PyObject *)PyFloat_FromDouble(self->cval.imag);
|
||||
else if (strcmp(name, "__members__") == 0)
|
||||
return Py_BuildValue("[ss]", "imag", "real");
|
||||
return Py_FindMethod(complex_methods, (PyObject *)self, name);
|
||||
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 */
|
||||
char s_buffer[256];
|
||||
int len;
|
||||
|
||||
if (PyString_Check(v)) {
|
||||
s = PyString_AS_STRING(v);
|
||||
len = PyString_GET_SIZE(v);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
sprintf(buffer,
|
||||
"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);
|
||||
if ((nbr = r->ob_type->tp_as_number) == NULL ||
|
||||
nbr->nb_float == NULL ||
|
||||
(i != NULL &&
|
||||
((nbi = i->ob_type->tp_as_number) == NULL ||
|
||||
nbi->nb_float == NULL))) {
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
|
||||
static char complex_doc[] =
|
||||
"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.";
|
||||
|
||||
static PyNumberMethods complex_as_number = {
|
||||
(binaryfunc)complex_add, /* nb_add */
|
||||
(binaryfunc)complex_sub, /* nb_subtract */
|
||||
|
@ -606,7 +869,7 @@ PyTypeObject PyComplex_Type = {
|
|||
0,
|
||||
(destructor)complex_dealloc, /* tp_dealloc */
|
||||
(printfunc)complex_print, /* tp_print */
|
||||
(getattrfunc)complex_getattr, /* tp_getattr */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)complex_repr, /* tp_repr */
|
||||
|
@ -616,14 +879,28 @@ PyTypeObject PyComplex_Type = {
|
|||
(hashfunc)complex_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
(reprfunc)complex_str, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
complex_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
complex_richcompare, /* tp_richcompare */
|
||||
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 */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue