diff options
Diffstat (limited to 'Objects/complexobject.c')
-rw-r--r-- | Objects/complexobject.c | 580 |
1 files changed, 396 insertions, 184 deletions
diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 367752d..871eea3 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -8,19 +8,30 @@ #include "Python.h" #include "structmember.h" -/*[clinic input] -class complex "PyComplexObject *" "&PyComplex_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=819e057d2d10f5ec]*/ +#ifndef WITHOUT_COMPLEX -#include "clinic/complexobject.c.h" +/* 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 -_Py_c_sum(Py_complex a, Py_complex b) +c_sum(Py_complex a, Py_complex b) { Py_complex r; r.real = a.real + b.real; @@ -29,7 +40,7 @@ _Py_c_sum(Py_complex a, Py_complex b) } Py_complex -_Py_c_diff(Py_complex a, Py_complex b) +c_diff(Py_complex a, Py_complex b) { Py_complex r; r.real = a.real - b.real; @@ -38,7 +49,7 @@ _Py_c_diff(Py_complex a, Py_complex b) } Py_complex -_Py_c_neg(Py_complex a) +c_neg(Py_complex a) { Py_complex r; r.real = -a.real; @@ -47,7 +58,7 @@ _Py_c_neg(Py_complex a) } Py_complex -_Py_c_prod(Py_complex a, Py_complex b) +c_prod(Py_complex a, Py_complex b) { Py_complex r; r.real = a.real*b.real - a.imag*b.imag; @@ -55,12 +66,8 @@ _Py_c_prod(Py_complex a, Py_complex b) return r; } -/* Avoid bad optimization on Windows ARM64 until the compiler is fixed */ -#ifdef _M_ARM64 -#pragma optimize("", off) -#endif Py_complex -_Py_c_quot(Py_complex a, Py_complex b) +c_quot(Py_complex a, Py_complex b) { /****************************************************************** This was the original algorithm. It's grossly prone to spurious @@ -116,12 +123,9 @@ _Py_c_quot(Py_complex a, Py_complex b) } return r; } -#ifdef _M_ARM64 -#pragma optimize("", on) -#endif Py_complex -_Py_c_pow(Py_complex a, Py_complex b) +c_pow(Py_complex a, Py_complex b) { Py_complex r; double vabs,len,at,phase; @@ -159,9 +163,9 @@ c_powu(Py_complex x, long n) p = x; while (mask > 0 && n >= mask) { if (n & mask) - r = _Py_c_prod(r,p); + r = c_prod(r,p); mask <<= 1; - p = _Py_c_prod(p,p); + p = c_prod(p,p); } return r; } @@ -174,17 +178,17 @@ c_powi(Py_complex x, long n) if (n > 100 || n < -100) { cn.real = (double) n; cn.imag = 0.; - return _Py_c_pow(x,cn); + return c_pow(x,cn); } else if (n > 0) return c_powu(x,n); else - return _Py_c_quot(c_1, c_powu(x,-n)); + return c_quot(c_1,c_powu(x,-n)); } double -_Py_c_abs(Py_complex z) +c_abs(Py_complex z) { /* sets errno = ERANGE on overflow; otherwise errno = 0 */ double result; @@ -229,7 +233,7 @@ complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval) PyObject * PyComplex_FromCComplex(Py_complex cval) { - PyComplexObject *op; + register PyComplexObject *op; /* Inline PyObject_New */ op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject)); @@ -281,34 +285,32 @@ PyComplex_ImagAsDouble(PyObject *op) } static PyObject * -try_complex_special_method(PyObject *op) -{ +try_complex_special_method(PyObject *op) { PyObject *f; - _Py_IDENTIFIER(__complex__); + static PyObject *complexstr; - f = _PyObject_LookupSpecial(op, &PyId___complex__); - if (f) { - PyObject *res = _PyObject_CallNoArg(f); - Py_DECREF(f); - if (!res || PyComplex_CheckExact(res)) { - return res; - } - if (!PyComplex_Check(res)) { - PyErr_Format(PyExc_TypeError, - "__complex__ returned non-complex (type %.200s)", - res->ob_type->tp_name); - Py_DECREF(res); + if (complexstr == NULL) { + complexstr = PyString_InternFromString("__complex__"); + if (complexstr == NULL) return NULL; + } + if (PyInstance_Check(op)) { + f = PyObject_GetAttr(op, complexstr); + if (f == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + return NULL; } - /* Issue #29894: warn if 'res' not of exact type complex. */ - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__complex__ returned non-complex (type %.200s). " - "The ability to return an instance of a strict subclass of complex " - "is deprecated, and may be removed in a future version of Python.", - res->ob_type->tp_name)) { - Py_DECREF(res); + } + else { + f = _PyObject_LookupSpecial(op, "__complex__", &complexstr); + if (f == NULL && PyErr_Occurred()) return NULL; - } + } + if (f != NULL) { + PyObject *res = PyObject_CallFunctionObjArgs(f, NULL); + Py_DECREF(f); return res; } return NULL; @@ -334,6 +336,12 @@ PyComplex_AsCComplex(PyObject *op) newop = try_complex_special_method(op); if (newop) { + if (!PyComplex_Check(newop)) { + PyErr_SetString(PyExc_TypeError, + "__complex__ should return a complex object"); + Py_DECREF(newop); + return cv; + } cv = ((PyComplexObject *)newop)->cval; Py_DECREF(newop); return cv; @@ -350,27 +358,32 @@ PyComplex_AsCComplex(PyObject *op) } } +static void +complex_dealloc(PyObject *op) +{ + op->ob_type->tp_free(op); +} + + static PyObject * -complex_repr(PyComplexObject *v) +complex_format(PyComplexObject *v, int precision, char format_code) { - int precision = 0; - char format_code = 'r'; PyObject *result = NULL; + Py_ssize_t len; /* If these are non-NULL, they'll need to be freed. */ char *pre = NULL; char *im = NULL; + char *buf = NULL; /* These do not need to be freed. re is either an alias for pre or a pointer to a constant. lead and tail are pointers to constants. */ - const char *re = NULL; - const char *lead = ""; - const char *tail = ""; + char *re = NULL; + char *lead = ""; + char *tail = ""; if (v->cval.real == 0. && copysign(1.0, v->cval.real)==1.0) { - /* Real part is +0: just output the imaginary part and do not - include parens. */ re = ""; im = PyOS_double_to_string(v->cval.imag, format_code, precision, 0, NULL); @@ -379,8 +392,7 @@ complex_repr(PyComplexObject *v) goto done; } } else { - /* Format imaginary part with sign, real part without. Include - parens in the result. */ + /* Format imaginary part with sign, real part without */ pre = PyOS_double_to_string(v->cval.real, format_code, precision, 0, NULL); if (!pre) { @@ -398,23 +410,64 @@ complex_repr(PyComplexObject *v) lead = "("; tail = ")"; } - result = PyUnicode_FromFormat("%s%s%sj%s", lead, re, im, tail); + /* Alloc the final buffer. Add one for the "j" in the format string, + and one for the trailing zero. */ + len = strlen(lead) + strlen(re) + strlen(im) + strlen(tail) + 2; + buf = PyMem_Malloc(len); + if (!buf) { + PyErr_NoMemory(); + goto done; + } + PyOS_snprintf(buf, len, "%s%s%sj%s", lead, re, im, tail); + result = PyString_FromString(buf); done: PyMem_Free(im); PyMem_Free(pre); + PyMem_Free(buf); return result; } -static Py_hash_t +static int +complex_print(PyComplexObject *v, FILE *fp, int flags) +{ + PyObject *formatv; + char *buf; + if (flags & Py_PRINT_RAW) + formatv = complex_format(v, PyFloat_STR_PRECISION, 'g'); + else + formatv = complex_format(v, 0, 'r'); + if (formatv == NULL) + return -1; + buf = PyString_AS_STRING(formatv); + Py_BEGIN_ALLOW_THREADS + fputs(buf, fp); + Py_END_ALLOW_THREADS + Py_DECREF(formatv); + return 0; +} + +static PyObject * +complex_repr(PyComplexObject *v) +{ + return complex_format(v, 0, 'r'); +} + +static PyObject * +complex_str(PyComplexObject *v) +{ + return complex_format(v, PyFloat_STR_PRECISION, 'g'); +} + +static long complex_hash(PyComplexObject *v) { - Py_uhash_t hashreal, hashimag, combined; - hashreal = (Py_uhash_t)_Py_HashDouble(v->cval.real); - if (hashreal == (Py_uhash_t)-1) + long hashreal, hashimag, combined; + hashreal = _Py_HashDouble(v->cval.real); + if (hashreal == -1) return -1; - hashimag = (Py_uhash_t)_Py_HashDouble(v->cval.imag); - if (hashimag == (Py_uhash_t)-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 @@ -422,10 +475,10 @@ complex_hash(PyComplexObject *v) * compare equal must have the same hash value, so that * hash(x + 0*j) must equal hash(x). */ - combined = hashreal + _PyHASH_IMAG * hashimag; - if (combined == (Py_uhash_t)-1) - combined = (Py_uhash_t)-2; - return (Py_hash_t)combined; + combined = hashreal + 1000003 * hashimag; + if (combined == -1) + combined = -2; + return combined; } /* This macro may return! */ @@ -441,6 +494,10 @@ to_complex(PyObject **pobj, Py_complex *pc) PyObject *obj = *pobj; pc->real = pc->imag = 0.0; + if (PyInt_Check(obj)) { + pc->real = PyInt_AS_LONG(obj); + return 0; + } if (PyLong_Check(obj)) { pc->real = PyLong_AsDouble(obj); if (pc->real == -1.0 && PyErr_Occurred()) { @@ -466,7 +523,9 @@ complex_add(PyObject *v, PyObject *w) Py_complex a, b; TO_COMPLEX(v, a); TO_COMPLEX(w, b); - result = _Py_c_sum(a, b); + PyFPE_START_PROTECT("complex_add", return 0) + result = c_sum(a, b); + PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result); } @@ -476,8 +535,10 @@ complex_sub(PyObject *v, PyObject *w) Py_complex result; Py_complex a, b; TO_COMPLEX(v, a); - TO_COMPLEX(w, b); - result = _Py_c_diff(a, b); + TO_COMPLEX(w, b);; + PyFPE_START_PROTECT("complex_sub", return 0) + result = c_diff(a, b); + PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result); } @@ -488,7 +549,9 @@ complex_mul(PyObject *v, PyObject *w) Py_complex a, b; TO_COMPLEX(v, a); TO_COMPLEX(w, b); - result = _Py_c_prod(a, b); + PyFPE_START_PROTECT("complex_mul", return 0) + result = c_prod(a, b); + PyFPE_END_PROTECT(result) return PyComplex_FromCComplex(result); } @@ -499,8 +562,33 @@ complex_div(PyObject *v, PyObject *w) Py_complex a, b; TO_COMPLEX(v, a); TO_COMPLEX(w, b); + PyFPE_START_PROTECT("complex_div", return 0) errno = 0; - quot = _Py_c_quot(a, b); + quot = c_quot(a, b); + PyFPE_END_PROTECT(quot) + if (errno == EDOM) { + PyErr_SetString(PyExc_ZeroDivisionError, "complex division by zero"); + return NULL; + } + return PyComplex_FromCComplex(quot); +} + +static PyObject * +complex_classic_div(PyObject *v, PyObject *w) +{ + Py_complex quot; + Py_complex a, b; + TO_COMPLEX(v, a); + TO_COMPLEX(w, b); + 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(a, b); + PyFPE_END_PROTECT(quot) if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "complex division by zero"); return NULL; @@ -511,18 +599,55 @@ complex_div(PyObject *v, PyObject *w) static PyObject * complex_remainder(PyObject *v, PyObject *w) { - PyErr_SetString(PyExc_TypeError, - "can't mod complex numbers."); - return NULL; + Py_complex div, mod; + Py_complex a, b; + TO_COMPLEX(v, a); + TO_COMPLEX(w, b); + if (PyErr_Warn(PyExc_DeprecationWarning, + "complex divmod(), // and % are deprecated") < 0) + return NULL; + + errno = 0; + div = c_quot(a, b); /* 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(a, c_prod(b, div)); + + return PyComplex_FromCComplex(mod); } static PyObject * complex_divmod(PyObject *v, PyObject *w) { - PyErr_SetString(PyExc_TypeError, - "can't take floor or mod of complex number."); - return NULL; + Py_complex div, mod; + PyObject *d, *m, *z; + Py_complex a, b; + TO_COMPLEX(v, a); + TO_COMPLEX(w, b); + if (PyErr_Warn(PyExc_DeprecationWarning, + "complex divmod(), // and % are deprecated") < 0) + return NULL; + + errno = 0; + div = c_quot(a, b); /* 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(a, c_prod(b, 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 * @@ -534,19 +659,20 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z) Py_complex a, b; TO_COMPLEX(v, a); TO_COMPLEX(w, b); - - if (z != Py_None) { + if (z!=Py_None) { PyErr_SetString(PyExc_ValueError, "complex modulo"); return NULL; } + PyFPE_START_PROTECT("complex_pow", return 0) errno = 0; exponent = b; int_exponent = (long)exponent.real; if (exponent.imag == 0. && exponent.real == int_exponent) - p = c_powi(a, int_exponent); + p = c_powi(a,int_exponent); else - p = _Py_c_pow(a, exponent); + p = c_pow(a,exponent); + PyFPE_END_PROTECT(p) Py_ADJUST_ERANGE2(p.real, p.imag); if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, @@ -564,8 +690,21 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z) static PyObject * complex_int_div(PyObject *v, PyObject *w) { - PyErr_SetString(PyExc_TypeError, - "can't take floor of complex number."); + PyObject *t, *r; + Py_complex a, b; + TO_COMPLEX(v, a); + TO_COMPLEX(w, b); + if (PyErr_Warn(PyExc_DeprecationWarning, + "complex divmod(), // and % are deprecated") < 0) + return NULL; + + t = complex_divmod(v, w); + if (t != NULL) { + r = PyTuple_GET_ITEM(t, 0); + Py_INCREF(r); + Py_DECREF(t); + return r; + } return NULL; } @@ -594,7 +733,9 @@ complex_abs(PyComplexObject *v) { double result; - result = _Py_c_abs(v->cval); + PyFPE_START_PROTECT("complex_abs", return 0) + result = c_abs(v->cval); + PyFPE_END_PROTECT(result) if (errno == ERANGE) { PyErr_SetString(PyExc_OverflowError, @@ -605,11 +746,44 @@ complex_abs(PyComplexObject *v) } static int -complex_bool(PyComplexObject *v) +complex_nonzero(PyComplexObject *v) { return v->cval.real != 0.0 || v->cval.imag != 0.0; } +static int +complex_coerce(PyObject **pv, PyObject **pw) +{ + Py_complex cval; + cval.imag = 0.; + if (PyInt_Check(*pw)) { + cval.real = (double)PyInt_AsLong(*pw); + *pw = PyComplex_FromCComplex(cval); + Py_INCREF(*pv); + return 0; + } + else if (PyLong_Check(*pw)) { + cval.real = PyLong_AsDouble(*pw); + if (cval.real == -1.0 && PyErr_Occurred()) + return -1; + *pw = PyComplex_FromCComplex(cval); + Py_INCREF(*pv); + return 0; + } + else if (PyFloat_Check(*pw)) { + cval.real = PyFloat_AsDouble(*pw); + *pw = PyComplex_FromCComplex(cval); + Py_INCREF(*pv); + return 0; + } + else if (PyComplex_Check(*pw)) { + Py_INCREF(*pv); + Py_INCREF(*pw); + return 0; + } + return 1; /* Can't do it */ +} + static PyObject * complex_richcompare(PyObject *v, PyObject *w, int op) { @@ -618,13 +792,24 @@ complex_richcompare(PyObject *v, PyObject *w, int op) int equal; if (op != Py_EQ && op != Py_NE) { + /* for backwards compatibility, comparisons with non-numbers return + * NotImplemented. Only comparisons with core numeric types raise + * TypeError. + */ + if (_PyAnyInt_Check(w) || + PyFloat_Check(w) || PyComplex_Check(w)) { + PyErr_SetString(PyExc_TypeError, + "no ordering relation is defined " + "for complex numbers"); + return NULL; + } goto Unimplemented; } assert(PyComplex_Check(v)); TO_COMPLEX(v, i); - if (PyLong_Check(w)) { + if (_PyAnyInt_Check(w)) { /* Check for 0.0 imaginary part first to avoid the rich * comparison when possible. */ @@ -663,8 +848,9 @@ complex_richcompare(PyObject *v, PyObject *w, int op) Py_INCREF(res); return res; -Unimplemented: - Py_RETURN_NOTIMPLEMENTED; + Unimplemented: + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } static PyObject * @@ -676,6 +862,14 @@ complex_int(PyObject *v) } static PyObject * +complex_long(PyObject *v) +{ + PyErr_SetString(PyExc_TypeError, + "can't convert complex to long"); + return NULL; +} + +static PyObject * complex_float(PyObject *v) { PyErr_SetString(PyExc_TypeError, @@ -684,7 +878,7 @@ complex_float(PyObject *v) } static PyObject * -complex_conjugate(PyObject *self, PyObject *Py_UNUSED(ignored)) +complex_conjugate(PyObject *self) { Py_complex c; c = ((PyComplexObject *)self)->cval; @@ -698,7 +892,7 @@ PyDoc_STRVAR(complex_conjugate_doc, "Return the complex conjugate of its argument. (3-4j).conjugate() == 3+4j."); static PyObject * -complex_getnewargs(PyComplexObject *v, PyObject *Py_UNUSED(ignored)) +complex_getnewargs(PyComplexObject *v) { Py_complex c = v->cval; return Py_BuildValue("(dd)", c.real, c.imag); @@ -713,22 +907,30 @@ static PyObject * complex__format__(PyObject* self, PyObject* args) { PyObject *format_spec; - _PyUnicodeWriter writer; - int ret; - if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) + if (!PyArg_ParseTuple(args, "O:__format__", &format_spec)) return NULL; + if (PyBytes_Check(format_spec)) + return _PyComplex_FormatAdvanced(self, + PyBytes_AS_STRING(format_spec), + PyBytes_GET_SIZE(format_spec)); + if (PyUnicode_Check(format_spec)) { + /* Convert format_spec to a str */ + PyObject *result; + PyObject *str_spec = PyObject_Str(format_spec); + + if (str_spec == NULL) + return NULL; - _PyUnicodeWriter_Init(&writer); - ret = _PyComplex_FormatAdvancedWriter( - &writer, - self, - format_spec, 0, PyUnicode_GET_LENGTH(format_spec)); - if (ret == -1) { - _PyUnicodeWriter_Dealloc(&writer); - return NULL; + result = _PyComplex_FormatAdvanced(self, + PyBytes_AS_STRING(str_spec), + PyBytes_GET_SIZE(str_spec)); + + Py_DECREF(str_spec); + return result; } - return _PyUnicodeWriter_Finish(&writer); + PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode"); + return NULL; } #if 0 @@ -769,12 +971,40 @@ static PyMemberDef complex_members[] = { }; static PyObject * -complex_from_string_inner(const char *s, Py_ssize_t len, void *type) +complex_subtype_from_string(PyTypeObject *type, PyObject *v) { + const char *s, *start; + char *end; double x=0.0, y=0.0, z; int got_bracket=0; - const char *start; - char *end; +#ifdef Py_USING_UNICODE + char *s_buffer = NULL; +#endif + Py_ssize_t len; + + if (PyString_Check(v)) { + s = PyString_AS_STRING(v); + len = PyString_GET_SIZE(v); + } +#ifdef Py_USING_UNICODE + else if (PyUnicode_Check(v)) { + s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1); + if (s_buffer == NULL) + return PyErr_NoMemory(); + if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), + PyUnicode_GET_SIZE(v), + s_buffer, + NULL)) + goto error; + s = s_buffer; + len = strlen(s); + } +#endif + else { + PyErr_SetString(PyExc_TypeError, + "complex() arg is not a string"); + return NULL; + } /* position on first nonblank */ start = s; @@ -815,7 +1045,7 @@ complex_from_string_inner(const char *s, Py_ssize_t len, void *type) if (PyErr_ExceptionMatches(PyExc_ValueError)) PyErr_Clear(); else - return NULL; + goto error; } if (end != s) { /* all 4 forms starting with <float> land here */ @@ -828,7 +1058,7 @@ complex_from_string_inner(const char *s, Py_ssize_t len, void *type) if (PyErr_ExceptionMatches(PyExc_ValueError)) PyErr_Clear(); else - return NULL; + goto error; } if (end != s) /* <float><signed-float>j */ @@ -883,65 +1113,40 @@ complex_from_string_inner(const char *s, Py_ssize_t len, void *type) if (s-start != len) goto parse_error; - return complex_subtype_from_doubles((PyTypeObject *)type, x, y); + +#ifdef Py_USING_UNICODE + if (s_buffer) + PyMem_FREE(s_buffer); +#endif + return complex_subtype_from_doubles(type, x, y); parse_error: PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); + error: +#ifdef Py_USING_UNICODE + if (s_buffer) + PyMem_FREE(s_buffer); +#endif return NULL; } static PyObject * -complex_subtype_from_string(PyTypeObject *type, PyObject *v) -{ - const char *s; - PyObject *s_buffer = NULL, *result = NULL; - Py_ssize_t len; - - if (PyUnicode_Check(v)) { - s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v); - if (s_buffer == NULL) { - return NULL; - } - assert(PyUnicode_IS_ASCII(s_buffer)); - /* Simply get a pointer to existing ASCII characters. */ - s = PyUnicode_AsUTF8AndSize(s_buffer, &len); - assert(s != NULL); - } - else { - PyErr_Format(PyExc_TypeError, - "complex() argument must be a string or a number, not '%.200s'", - Py_TYPE(v)->tp_name); - return NULL; - } - - result = _Py_string_to_number_with_underscores(s, len, "complex", v, type, - complex_from_string_inner); - Py_DECREF(s_buffer); - return result; -} - -/*[clinic input] -@classmethod -complex.__new__ as complex_new - real as r: object(c_default="_PyLong_Zero") = 0 - imag as i: object(c_default="NULL") = 0 - -Create a complex number from a real part and an optional imaginary part. - -This is equivalent to (real + imag*1j) where imag defaults to 0. -[clinic start generated code]*/ - -static PyObject * -complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i) -/*[clinic end generated code: output=b6c7dd577b537dc1 input=6f6b0bedba29bcb5]*/ +complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *tmp; + PyObject *r, *i, *tmp; PyNumberMethods *nbr, *nbi = NULL; Py_complex cr, ci; int own_r = 0; int cr_is_complex = 0; int ci_is_complex = 0; + static char *kwlist[] = {"real", "imag", 0}; + + r = Py_False; + i = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist, + &r, &i)) + return NULL; /* Special-case for a single argument when type(arg) is complex. */ if (PyComplex_CheckExact(r) && i == NULL && @@ -954,7 +1159,7 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i) Py_INCREF(r); return r; } - if (PyUnicode_Check(r)) { + if (PyString_Check(r) || PyUnicode_Check(r)) { if (i != NULL) { PyErr_SetString(PyExc_TypeError, "complex() can't take second arg" @@ -963,7 +1168,7 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i) } return complex_subtype_from_string(type, r); } - if (i != NULL && PyUnicode_Check(i)) { + if (i != NULL && (PyString_Check(i) || PyUnicode_Check(i))) { PyErr_SetString(PyExc_TypeError, "complex() second arg can't be a string"); return NULL; @@ -979,29 +1184,17 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i) } nbr = r->ob_type->tp_as_number; - if (nbr == NULL || (nbr->nb_float == NULL && nbr->nb_index == NULL)) { - PyErr_Format(PyExc_TypeError, - "complex() first argument must be a string or a number, " - "not '%.200s'", - Py_TYPE(r)->tp_name); + 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))) { + PyErr_SetString(PyExc_TypeError, + "complex() argument must be a string or a number"); if (own_r) { Py_DECREF(r); } return NULL; } - if (i != NULL) { - nbi = i->ob_type->tp_as_number; - if (nbi == NULL || (nbi->nb_float == NULL && nbi->nb_index == NULL)) { - PyErr_Format(PyExc_TypeError, - "complex() second argument must be a number, " - "not '%.200s'", - Py_TYPE(i)->tp_name); - if (own_r) { - Py_DECREF(r); - } - return NULL; - } - } /* If we get this far, then the "real" and "imag" parts should both be treated as numbers, and the constructor should return a @@ -1032,7 +1225,12 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i) } if (tmp == NULL) return NULL; - assert(PyFloat_Check(tmp)); + 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); cr.imag = 0.0; Py_DECREF(tmp); @@ -1047,7 +1245,7 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i) /* The "imag" part really is entirely imaginary, and contributes nothing in the real direction. Just treat it as a double. */ - tmp = PyNumber_Float(i); + tmp = (*nbi->nb_float)(i); if (tmp == NULL) return NULL; ci.real = PyFloat_AsDouble(tmp); @@ -1066,29 +1264,40 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i) return complex_subtype_from_doubles(type, cr.real, ci.real); } +PyDoc_STRVAR(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 */ (binaryfunc)complex_mul, /* nb_multiply */ + (binaryfunc)complex_classic_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_bool, /* nb_bool */ + (inquiry)complex_nonzero, /* nb_nonzero */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ + complex_coerce, /* nb_coerce */ complex_int, /* nb_int */ - 0, /* nb_reserved */ + complex_long, /* nb_long */ complex_float, /* nb_float */ + 0, /* nb_oct */ + 0, /* nb_hex */ 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 */ @@ -1107,23 +1316,24 @@ PyTypeObject PyComplex_Type = { "complex", sizeof(PyComplexObject), 0, - 0, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ + complex_dealloc, /* tp_dealloc */ + (printfunc)complex_print, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_as_async */ + 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 */ - 0, /* tp_str */ + (reprfunc)complex_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - complex_new__doc__, /* tp_doc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + complex_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ complex_richcompare, /* tp_richcompare */ @@ -1143,3 +1353,5 @@ PyTypeObject PyComplex_Type = { complex_new, /* tp_new */ PyObject_Del, /* tp_free */ }; + +#endif |